[clang-tools-extra] 9215e3a - Revert "[clang-tidy] Add modernize-printf-to-std-print check"
Piotr Zegar via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 26 02:50:51 PDT 2023
Author: Piotr Zegar
Date: 2023-06-26T09:50:38Z
New Revision: 9215e3a88483c94cba87590caea754e102078844
URL: https://github.com/llvm/llvm-project/commit/9215e3a88483c94cba87590caea754e102078844
DIFF: https://github.com/llvm/llvm-project/commit/9215e3a88483c94cba87590caea754e102078844.diff
LOG: Revert "[clang-tidy] Add modernize-printf-to-std-print check"
This reverts commit ec89cb9a81529fd41fb37b8e62203a2e9f23bd54.
Added:
Modified:
clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
clang-tools-extra/clang-tidy/utils/CMakeLists.txt
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/list.rst
clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/stdio.h
clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string.h
Removed:
clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h
clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstddef
clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstdint
clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstdio
clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/inttypes.h
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-fmt.cpp
clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
################################################################################
diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index ef10cb0e38826..91e2d8d5ee4e5 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -37,7 +37,6 @@ add_clang_library(clangTidyModernizeModule
UseNoexceptCheck.cpp
UseNullptrCheck.cpp
UseOverrideCheck.cpp
- UseStdPrintCheck.cpp
UseTrailingReturnTypeCheck.cpp
UseTransparentFunctorsCheck.cpp
UseUncaughtExceptionsCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index 9bbc4dc50ec0e..ee0fab18d2068 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -38,7 +38,6 @@
#include "UseNoexceptCheck.h"
#include "UseNullptrCheck.h"
#include "UseOverrideCheck.h"
-#include "UseStdPrintCheck.h"
#include "UseTrailingReturnTypeCheck.h"
#include "UseTransparentFunctorsCheck.h"
#include "UseUncaughtExceptionsCheck.h"
@@ -65,7 +64,6 @@ class ModernizeModule : public ClangTidyModule {
CheckFactories.registerCheck<MakeSharedCheck>("modernize-make-shared");
CheckFactories.registerCheck<MakeUniqueCheck>("modernize-make-unique");
CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value");
- CheckFactories.registerCheck<UseStdPrintCheck>("modernize-use-std-print");
CheckFactories.registerCheck<RawStringLiteralCheck>(
"modernize-raw-string-literal");
CheckFactories.registerCheck<RedundantVoidArgCheck>(
diff --git a/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
deleted file mode 100644
index 9b368f9a3e6c9..0000000000000
--- a/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-//===--- UseStdPrintCheck.cpp - clang-tidy-----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "UseStdPrintCheck.h"
-#include "../utils/FormatStringConverter.h"
-#include "../utils/Matchers.h"
-#include "../utils/OptionsUtils.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Tooling/FixIt.h"
-
-using namespace clang::ast_matchers;
-
-namespace clang::tidy::modernize {
-
-namespace {
-AST_MATCHER(StringLiteral, isOrdinary) { return Node.isOrdinary(); }
-} // namespace
-
-UseStdPrintCheck::UseStdPrintCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context),
- StrictMode(Options.getLocalOrGlobal("StrictMode", false)),
- PrintfLikeFunctions(utils::options::parseStringList(
- Options.get("PrintfLikeFunctions", ""))),
- FprintfLikeFunctions(utils::options::parseStringList(
- Options.get("FprintfLikeFunctions", ""))),
- ReplacementPrintFunction(
- Options.get("ReplacementPrintFunction", "std::print")),
- ReplacementPrintlnFunction(
- Options.get("ReplacementPrintlnFunction", "std::println")),
- IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
- utils::IncludeSorter::IS_LLVM),
- areDiagsSelfContained()),
- MaybeHeaderToInclude(Options.get("PrintHeader")) {
-
- if (PrintfLikeFunctions.empty() && FprintfLikeFunctions.empty()) {
- PrintfLikeFunctions.push_back("::printf");
- PrintfLikeFunctions.push_back("absl::PrintF");
- FprintfLikeFunctions.push_back("::fprintf");
- FprintfLikeFunctions.push_back("absl::FPrintF");
- }
-
- if (!MaybeHeaderToInclude && (ReplacementPrintFunction == "std::print" ||
- ReplacementPrintlnFunction == "std::println"))
- MaybeHeaderToInclude = "<print>";
-}
-
-void UseStdPrintCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
- using utils::options::serializeStringList;
- Options.store(Opts, "StrictMode", StrictMode);
- Options.store(Opts, "PrintfLikeFunctions",
- serializeStringList(PrintfLikeFunctions));
- Options.store(Opts, "FprintfLikeFunctions",
- serializeStringList(FprintfLikeFunctions));
- Options.store(Opts, "ReplacementPrintFunction", ReplacementPrintFunction);
- Options.store(Opts, "ReplacementPrintlnFunction", ReplacementPrintlnFunction);
- Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
- if (MaybeHeaderToInclude)
- Options.store(Opts, "PrintHeader", *MaybeHeaderToInclude);
-}
-
-void UseStdPrintCheck::registerPPCallbacks(const SourceManager &SM,
- Preprocessor *PP,
- Preprocessor *ModuleExpanderPP) {
- IncludeInserter.registerPreprocessor(PP);
-}
-
-void UseStdPrintCheck::registerMatchers(MatchFinder *Finder) {
- if (!PrintfLikeFunctions.empty())
- Finder->addMatcher(
- callExpr(argumentCountAtLeast(1),
- hasArgument(0, stringLiteral(isOrdinary())),
- callee(functionDecl(
- unless(cxxMethodDecl()),
- matchers::matchesAnyListedName(PrintfLikeFunctions))
- .bind("func_decl")))
- .bind("printf"),
- this);
-
- if (!FprintfLikeFunctions.empty())
- Finder->addMatcher(
- callExpr(argumentCountAtLeast(2),
- hasArgument(1, stringLiteral(isOrdinary())),
- callee(functionDecl(unless(cxxMethodDecl()),
- matchers::matchesAnyListedName(
- FprintfLikeFunctions))
- .bind("func_decl")))
- .bind("fprintf"),
- this);
-}
-
-void UseStdPrintCheck::check(const MatchFinder::MatchResult &Result) {
- unsigned FormatArgOffset = 0;
- const auto *OldFunction = Result.Nodes.getNodeAs<FunctionDecl>("func_decl");
- const auto *Printf = Result.Nodes.getNodeAs<CallExpr>("printf");
- if (!Printf) {
- Printf = Result.Nodes.getNodeAs<CallExpr>("fprintf");
- FormatArgOffset = 1;
- }
-
- utils::FormatStringConverter Converter(
- Result.Context, Printf, FormatArgOffset, StrictMode, getLangOpts());
- const Expr *PrintfCall = Printf->getCallee();
- const StringRef ReplacementFunction = Converter.usePrintNewlineFunction()
- ? ReplacementPrintlnFunction
- : ReplacementPrintFunction;
- if (!Converter.canApply()) {
- diag(PrintfCall->getBeginLoc(),
- "unable to use '%0' instead of %1 because %2")
- << ReplacementFunction << OldFunction->getIdentifier()
- << Converter.conversionNotPossibleReason();
- return;
- }
-
- DiagnosticBuilder Diag =
- diag(PrintfCall->getBeginLoc(), "use '%0' instead of %1")
- << ReplacementFunction << OldFunction->getIdentifier();
-
- Diag << FixItHint::CreateReplacement(
- CharSourceRange::getTokenRange(PrintfCall->getBeginLoc(),
- PrintfCall->getEndLoc()),
- ReplacementFunction);
- Converter.applyFixes(Diag, *Result.SourceManager);
-
- if (MaybeHeaderToInclude)
- Diag << IncludeInserter.createIncludeInsertion(
- Result.Context->getSourceManager().getFileID(PrintfCall->getBeginLoc()),
- *MaybeHeaderToInclude);
-}
-
-} // namespace clang::tidy::modernize
diff --git a/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h b/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h
deleted file mode 100644
index 7a06cf38b4264..0000000000000
--- a/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//===--- UseStdPrintCheck.h - clang-tidy-------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_USESTDPRINTCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_USESTDPRINTCHECK_H
-
-#include "../ClangTidyCheck.h"
-#include "../utils/IncludeInserter.h"
-
-namespace clang::tidy::modernize {
-/// Convert calls to printf-like functions to std::print and std::println
-///
-/// For the user-facing documentation see:
-/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-std-print.html
-class UseStdPrintCheck : public ClangTidyCheck {
-public:
- UseStdPrintCheck(StringRef Name, ClangTidyContext *Context);
- bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
- if (ReplacementPrintFunction == "std::print" ||
- ReplacementPrintlnFunction == "std::println")
- return LangOpts.CPlusPlus23;
- return LangOpts.CPlusPlus;
- }
- void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
- Preprocessor *ModuleExpanderPP) override;
- void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
- void registerMatchers(ast_matchers::MatchFinder *Finder) override;
- void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
- std::optional<TraversalKind> getCheckTraversalKind() const override {
- return TK_IgnoreUnlessSpelledInSource;
- }
-
-private:
- bool StrictMode;
- std::vector<StringRef> PrintfLikeFunctions;
- std::vector<StringRef> FprintfLikeFunctions;
- StringRef ReplacementPrintFunction;
- StringRef ReplacementPrintlnFunction;
- utils::IncludeInserter IncludeInserter;
- std::optional<StringRef> MaybeHeaderToInclude;
-};
-
-} // namespace clang::tidy::modernize
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_USESTDPRINTCHECK_H
diff --git a/clang-tools-extra/clang-tidy/utils/CMakeLists.txt b/clang-tools-extra/clang-tidy/utils/CMakeLists.txt
index 6c7d52a4b1873..50d1cf812b690 100644
--- a/clang-tools-extra/clang-tidy/utils/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/utils/CMakeLists.txt
@@ -11,7 +11,6 @@ add_clang_library(clangTidyUtils
ExceptionSpecAnalyzer.cpp
ExprSequence.cpp
FileExtensionsUtils.cpp
- FormatStringConverter.cpp
FixItHintUtils.cpp
HeaderGuard.cpp
IncludeInserter.cpp
diff --git a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
deleted file mode 100644
index 624bc917ac937..0000000000000
--- a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
+++ /dev/null
@@ -1,677 +0,0 @@
-//===--- FormatStringConverter.cpp - clang-tidy----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// Implementation of the FormatStringConverter class which is used to convert
-/// printf format strings to C++ std::formatter format strings.
-///
-//===----------------------------------------------------------------------===//
-
-#include "FormatStringConverter.h"
-#include "../utils/FixItHintUtils.h"
-#include "clang/AST/Expr.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Lex/Lexer.h"
-#include "clang/Tooling/FixIt.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Debug.h"
-
-using namespace clang::ast_matchers;
-using namespace clang::analyze_printf;
-
-namespace clang::tidy::utils {
-using clang::analyze_format_string::ConversionSpecifier;
-
-/// Is the passed type the actual "char" type, whether that be signed or
-/// unsigned, rather than explicit signed char or unsigned char types.
-static bool isRealCharType(const clang::QualType &Ty) {
- using namespace clang;
- const Type *DesugaredType = Ty->getUnqualifiedDesugaredType();
- if (const auto *BT = llvm::dyn_cast<BuiltinType>(DesugaredType))
- return (BT->getKind() == BuiltinType::Char_U ||
- BT->getKind() == BuiltinType::Char_S);
- return false;
-}
-
-/// If possible, return the text name of the signed type that corresponds to the
-/// passed integer type. If the passed type is already signed then its name is
-/// just returned. Only supports BuiltinTypes.
-static std::optional<std::string>
-getCorrespondingSignedTypeName(const clang::QualType &QT) {
- using namespace clang;
- const auto UQT = QT.getUnqualifiedType();
- if (const auto *BT = llvm::dyn_cast<BuiltinType>(UQT)) {
- switch (BT->getKind()) {
- case BuiltinType::UChar:
- case BuiltinType::Char_U:
- case BuiltinType::SChar:
- case BuiltinType::Char_S:
- return "signed char";
- case BuiltinType::UShort:
- case BuiltinType::Short:
- return "short";
- case BuiltinType::UInt:
- case BuiltinType::Int:
- return "int";
- case BuiltinType::ULong:
- case BuiltinType::Long:
- return "long";
- case BuiltinType::ULongLong:
- case BuiltinType::LongLong:
- return "long long";
- default:
- llvm::dbgs() << "Unknown corresponding signed type for BuiltinType '"
- << QT.getAsString() << "'\n";
- return std::nullopt;
- }
- }
-
- // Deal with fixed-width integer types from <cstdint>. Use std:: prefix only
- // if the argument type does.
- const std::string TypeName = UQT.getAsString();
- StringRef SimplifiedTypeName{TypeName};
- const bool InStd = SimplifiedTypeName.consume_front("std::");
- const StringRef Prefix = InStd ? "std::" : "";
-
- if (SimplifiedTypeName.starts_with("uint") &&
- SimplifiedTypeName.ends_with("_t"))
- return (Twine(Prefix) + SimplifiedTypeName.drop_front()).str();
-
- if (SimplifiedTypeName == "size_t")
- return (Twine(Prefix) + "ssize_t").str();
-
- llvm::dbgs() << "Unknown corresponding signed type for non-BuiltinType '"
- << UQT.getAsString() << "'\n";
- return std::nullopt;
-}
-
-/// If possible, return the text name of the unsigned type that corresponds to
-/// the passed integer type. If the passed type is already unsigned then its
-/// name is just returned. Only supports BuiltinTypes.
-static std::optional<std::string>
-getCorrespondingUnsignedTypeName(const clang::QualType &QT) {
- using namespace clang;
- const auto UQT = QT.getUnqualifiedType();
- if (const auto *BT = llvm::dyn_cast<BuiltinType>(UQT)) {
- switch (BT->getKind()) {
- case BuiltinType::SChar:
- case BuiltinType::Char_S:
- case BuiltinType::UChar:
- case BuiltinType::Char_U:
- return "unsigned char";
- case BuiltinType::Short:
- case BuiltinType::UShort:
- return "unsigned short";
- case BuiltinType::Int:
- case BuiltinType::UInt:
- return "unsigned int";
- case BuiltinType::Long:
- case BuiltinType::ULong:
- return "unsigned long";
- case BuiltinType::LongLong:
- case BuiltinType::ULongLong:
- return "unsigned long long";
- default:
- llvm::dbgs() << "Unknown corresponding unsigned type for BuiltinType '"
- << UQT.getAsString() << "'\n";
- return std::nullopt;
- }
- }
-
- // Deal with fixed-width integer types from <cstdint>. Use std:: prefix only
- // if the argument type does.
- const std::string TypeName = UQT.getAsString();
- StringRef SimplifiedTypeName{TypeName};
- const bool InStd = SimplifiedTypeName.consume_front("std::");
- const StringRef Prefix = InStd ? "std::" : "";
-
- if (SimplifiedTypeName.starts_with("int") &&
- SimplifiedTypeName.ends_with("_t"))
- return (Twine(Prefix) + "u" + SimplifiedTypeName).str();
-
- if (SimplifiedTypeName == "ssize_t")
- return (Twine(Prefix) + "size_t").str();
- if (SimplifiedTypeName == "ptr
diff _t")
- return (Twine(Prefix) + "size_t").str();
-
- llvm::dbgs() << "Unknown corresponding unsigned type for non-BuiltinType '"
- << UQT.getAsString() << "'\n";
- return std::nullopt;
-}
-
-static std::optional<std::string>
-castTypeForArgument(ConversionSpecifier::Kind ArgKind,
- const clang::QualType &QT) {
- if (ArgKind == ConversionSpecifier::Kind::uArg)
- return getCorrespondingUnsignedTypeName(QT);
- return getCorrespondingSignedTypeName(QT);
-}
-
-static bool isMatchingSignedness(ConversionSpecifier::Kind ArgKind,
- const clang::QualType &ArgType) {
- if (ArgKind == ConversionSpecifier::Kind::uArg)
- return ArgType->isUnsignedIntegerType();
- return ArgType->isSignedIntegerType();
-}
-
-namespace {
-AST_MATCHER(clang::QualType, isRealChar) {
- return clang::tidy::utils::isRealCharType(Node);
-}
-} // namespace
-
-static bool castMismatchedIntegerTypes(const CallExpr *Call, bool StrictMode) {
- /// For printf-style functions, the signedness of the type printed is
- /// indicated by the corresponding type in the format string.
- /// std::print will determine the signedness from the type of the
- /// argument. This means that it is necessary to generate a cast in
- /// StrictMode to ensure that the exact behaviour is maintained.
- /// However, for templated functions like absl::PrintF and
- /// fmt::printf, the signedness of the type printed is also taken from
- /// the actual argument like std::print, so such casts are never
- /// necessary. printf-style functions are variadic, whereas templated
- /// ones aren't, so we can use that to distinguish between the two
- /// cases.
- if (StrictMode) {
- const FunctionDecl *FuncDecl = Call->getDirectCallee();
- assert(FuncDecl);
- return FuncDecl->isVariadic();
- }
- return false;
-}
-
-FormatStringConverter::FormatStringConverter(ASTContext *ContextIn,
- const CallExpr *Call,
- unsigned FormatArgOffset,
- bool StrictMode,
- const LangOptions &LO)
- : Context(ContextIn),
- CastMismatchedIntegerTypes(castMismatchedIntegerTypes(Call, StrictMode)),
- Args(Call->getArgs()), NumArgs(Call->getNumArgs()),
- ArgsOffset(FormatArgOffset + 1), LangOpts(LO) {
- assert(ArgsOffset <= NumArgs);
- FormatExpr = llvm::dyn_cast<StringLiteral>(
- Args[FormatArgOffset]->IgnoreImplicitAsWritten());
- assert(FormatExpr);
- if (!FormatExpr->isOrdinary())
- return; // No wide string support yet
- PrintfFormatString = FormatExpr->getString();
-
- // Assume that the output will be approximately the same size as the input,
- // but perhaps with a few escapes expanded.
- const size_t EstimatedGrowth = 8;
- StandardFormatString.reserve(PrintfFormatString.size() + EstimatedGrowth);
- StandardFormatString.push_back('\"');
-
- const bool IsFreeBsdkPrintf = false;
-
- using clang::analyze_format_string::ParsePrintfString;
- ParsePrintfString(*this, PrintfFormatString.data(),
- PrintfFormatString.data() + PrintfFormatString.size(),
- LangOpts, Context->getTargetInfo(), IsFreeBsdkPrintf);
- finalizeFormatText();
-}
-
-void FormatStringConverter::emitAlignment(const PrintfSpecifier &FS,
- std::string &FormatSpec) {
- ConversionSpecifier::Kind ArgKind = FS.getConversionSpecifier().getKind();
-
- // We only care about alignment if a field width is specified
- if (FS.getFieldWidth().getHowSpecified() != OptionalAmount::NotSpecified) {
- if (ArgKind == ConversionSpecifier::sArg) {
- // Strings are left-aligned by default with std::format, so we only
- // need to emit an alignment if this one needs to be right aligned.
- if (!FS.isLeftJustified())
- FormatSpec.push_back('>');
- } else {
- // Numbers are right-aligned by default with std::format, so we only
- // need to emit an alignment if this one needs to be left aligned.
- if (FS.isLeftJustified())
- FormatSpec.push_back('<');
- }
- }
-}
-
-void FormatStringConverter::emitSign(const PrintfSpecifier &FS,
- std::string &FormatSpec) {
- const ConversionSpecifier Spec = FS.getConversionSpecifier();
-
- // Ignore on something that isn't numeric. For printf it's would be a
- // compile-time warning but ignored at runtime, but for std::format it
- // ought to be a compile-time error.
- if (Spec.isAnyIntArg() || Spec.isDoubleArg()) {
- // + is preferred to ' '
- if (FS.hasPlusPrefix())
- FormatSpec.push_back('+');
- else if (FS.hasSpacePrefix())
- FormatSpec.push_back(' ');
- }
-}
-
-void FormatStringConverter::emitAlternativeForm(const PrintfSpecifier &FS,
- std::string &FormatSpec) {
- if (FS.hasAlternativeForm()) {
- switch (FS.getConversionSpecifier().getKind()) {
- case ConversionSpecifier::Kind::aArg:
- case ConversionSpecifier::Kind::AArg:
- case ConversionSpecifier::Kind::eArg:
- case ConversionSpecifier::Kind::EArg:
- case ConversionSpecifier::Kind::fArg:
- case ConversionSpecifier::Kind::FArg:
- case ConversionSpecifier::Kind::gArg:
- case ConversionSpecifier::Kind::GArg:
- case ConversionSpecifier::Kind::xArg:
- case ConversionSpecifier::Kind::XArg:
- case ConversionSpecifier::Kind::oArg:
- FormatSpec.push_back('#');
- break;
- default:
- // Alternative forms don't exist for other argument kinds
- break;
- }
- }
-}
-
-void FormatStringConverter::emitFieldWidth(const PrintfSpecifier &FS,
- std::string &FormatSpec) {
- {
- const OptionalAmount FieldWidth = FS.getFieldWidth();
- switch (FieldWidth.getHowSpecified()) {
- case OptionalAmount::NotSpecified:
- break;
- case OptionalAmount::Constant:
- FormatSpec.append(llvm::utostr(FieldWidth.getConstantAmount()));
- break;
- case OptionalAmount::Arg:
- FormatSpec.push_back('{');
- if (FieldWidth.usesPositionalArg()) {
- // std::format argument identifiers are zero-based, whereas printf
- // ones are one based.
- assert(FieldWidth.getPositionalArgIndex() > 0U);
- FormatSpec.append(llvm::utostr(FieldWidth.getPositionalArgIndex() - 1));
- }
- FormatSpec.push_back('}');
- break;
- case OptionalAmount::Invalid:
- break;
- }
- }
-}
-
-void FormatStringConverter::emitPrecision(const PrintfSpecifier &FS,
- std::string &FormatSpec) {
- const OptionalAmount FieldPrecision = FS.getPrecision();
- switch (FieldPrecision.getHowSpecified()) {
- case OptionalAmount::NotSpecified:
- break;
- case OptionalAmount::Constant:
- FormatSpec.push_back('.');
- FormatSpec.append(llvm::utostr(FieldPrecision.getConstantAmount()));
- break;
- case OptionalAmount::Arg:
- FormatSpec.push_back('.');
- FormatSpec.push_back('{');
- if (FieldPrecision.usesPositionalArg()) {
- // std::format argument identifiers are zero-based, whereas printf
- // ones are one based.
- assert(FieldPrecision.getPositionalArgIndex() > 0U);
- FormatSpec.append(
- llvm::utostr(FieldPrecision.getPositionalArgIndex() - 1));
- }
- FormatSpec.push_back('}');
- break;
- case OptionalAmount::Invalid:
- break;
- }
-}
-
-void FormatStringConverter::emitStringArgument(const Expr *Arg) {
- // If the argument is the result of a call to std::string::c_str() or
- // data() with a return type of char then we can remove that call and
- // pass the std::string directly. We don't want to do so if the return
- // type is not a char pointer (though it's unlikely that such code would
- // compile without warnings anyway.) See RedundantStringCStrCheck.
-
- if (!StringCStrCallExprMatcher) {
- // Lazily create the matcher
- const auto StringDecl = type(hasUnqualifiedDesugaredType(recordType(
- hasDeclaration(cxxRecordDecl(hasName("::std::basic_string"))))));
- const auto StringExpr = expr(
- anyOf(hasType(StringDecl), hasType(qualType(pointsTo(StringDecl)))));
-
- StringCStrCallExprMatcher =
- cxxMemberCallExpr(
- on(StringExpr.bind("arg")), callee(memberExpr().bind("member")),
- callee(cxxMethodDecl(hasAnyName("c_str", "data"),
- returns(pointerType(pointee(isRealChar()))))))
- .bind("call");
- }
-
- auto CStrMatches = match(*StringCStrCallExprMatcher, *Arg, *Context);
- if (CStrMatches.size() == 1)
- ArgCStrRemovals.push_back(CStrMatches.front());
- else if (Arg->getType()->isPointerType()) {
- const QualType Pointee = Arg->getType()->getPointeeType();
- // printf is happy to print signed char and unsigned char strings, but
- // std::format only likes char strings.
- if (Pointee->isCharType() && !isRealCharType(Pointee))
- ArgFixes.emplace_back(Arg, "reinterpret_cast<const char *>(");
- }
-}
-
-bool FormatStringConverter::emitIntegerArgument(
- ConversionSpecifier::Kind ArgKind, const Expr *Arg, unsigned ArgIndex,
- std::string &FormatSpec) {
- const clang::QualType &ArgType = Arg->getType();
- if (ArgType->isBooleanType()) {
- // std::format will print bool as either "true" or "false" by default,
- // but printf prints them as "0" or "1". Be compatible with printf by
- // requesting decimal output.
- FormatSpec.push_back('d');
- } else if (ArgType->isEnumeralType()) {
- // std::format will try to find a specialization to print the enum
- // (and probably fail), whereas printf would have just expected it to
- // be passed as its underlying type. However, printf will have forced
- // the signedness based on the format string, so we need to do the
- // same.
- if (const auto *ET = ArgType->getAs<EnumType>()) {
- if (const std::optional<std::string> MaybeCastType =
- castTypeForArgument(ArgKind, ET->getDecl()->getIntegerType()))
- ArgFixes.emplace_back(
- Arg, (Twine("static_cast<") + *MaybeCastType + ">(").str());
- else
- return conversionNotPossible(
- (Twine("argument ") + Twine(ArgIndex) + " has unexpected enum type")
- .str());
- }
- } else if (CastMismatchedIntegerTypes &&
- !isMatchingSignedness(ArgKind, ArgType)) {
- // printf will happily print an unsigned type as signed if told to.
- // Even -Wformat doesn't warn for this. std::format will format as
- // unsigned unless we cast it.
- if (const std::optional<std::string> MaybeCastType =
- castTypeForArgument(ArgKind, ArgType))
- ArgFixes.emplace_back(
- Arg, (Twine("static_cast<") + *MaybeCastType + ">(").str());
- else
- return conversionNotPossible(
- (Twine("argument ") + Twine(ArgIndex) + " cannot be cast to " +
- Twine(ArgKind == ConversionSpecifier::Kind::uArg ? "unsigned"
- : "signed") +
- " integer type to match format"
- " specifier and StrictMode is enabled")
- .str());
- } else if (isRealCharType(ArgType) || !ArgType->isIntegerType()) {
- // Only specify integer if the argument is of a
diff erent type
- FormatSpec.push_back('d');
- }
- return true;
-}
-
-/// Append the corresponding standard format string type fragment to FormatSpec,
-/// and store any argument fixes for later application.
-/// @returns true on success, false on failure
-bool FormatStringConverter::emitType(const PrintfSpecifier &FS, const Expr *Arg,
- std::string &FormatSpec) {
- ConversionSpecifier::Kind ArgKind = FS.getConversionSpecifier().getKind();
- switch (ArgKind) {
- case ConversionSpecifier::Kind::sArg:
- emitStringArgument(Arg);
- break;
- case ConversionSpecifier::Kind::cArg:
- // The type must be "c" to get a character unless the type is exactly
- // char (whether that be signed or unsigned for the target.)
- if (!isRealCharType(Arg->getType()))
- FormatSpec.push_back('c');
- break;
- case ConversionSpecifier::Kind::dArg:
- case ConversionSpecifier::Kind::iArg:
- case ConversionSpecifier::Kind::uArg:
- if (!emitIntegerArgument(ArgKind, Arg, FS.getArgIndex() + ArgsOffset,
- FormatSpec))
- return false;
- break;
- case ConversionSpecifier::Kind::pArg: {
- const clang::QualType &ArgType = Arg->getType();
- // std::format knows how to format void pointers and nullptrs
- if (!ArgType->isNullPtrType() && !ArgType->isVoidPointerType())
- ArgFixes.emplace_back(Arg, "static_cast<const void *>(");
- break;
- }
- case ConversionSpecifier::Kind::xArg:
- FormatSpec.push_back('x');
- break;
- case ConversionSpecifier::Kind::XArg:
- FormatSpec.push_back('X');
- break;
- case ConversionSpecifier::Kind::oArg:
- FormatSpec.push_back('o');
- break;
- case ConversionSpecifier::Kind::aArg:
- FormatSpec.push_back('a');
- break;
- case ConversionSpecifier::Kind::AArg:
- FormatSpec.push_back('A');
- break;
- case ConversionSpecifier::Kind::eArg:
- FormatSpec.push_back('e');
- break;
- case ConversionSpecifier::Kind::EArg:
- FormatSpec.push_back('E');
- break;
- case ConversionSpecifier::Kind::fArg:
- FormatSpec.push_back('f');
- break;
- case ConversionSpecifier::Kind::FArg:
- FormatSpec.push_back('F');
- break;
- case ConversionSpecifier::Kind::gArg:
- FormatSpec.push_back('g');
- break;
- case ConversionSpecifier::Kind::GArg:
- FormatSpec.push_back('G');
- break;
- default:
- // Something we don't understand
- return conversionNotPossible((Twine("argument ") +
- Twine(FS.getArgIndex() + ArgsOffset) +
- " has an unsupported format specifier")
- .str());
- }
-
- return true;
-}
-
-/// Append the standard format string equivalent of the passed PrintfSpecifier
-/// to StandardFormatString and store any argument fixes for later application.
-/// @returns true on success, false on failure
-bool FormatStringConverter::convertArgument(const PrintfSpecifier &FS,
- const Expr *Arg,
- std::string &StandardFormatString) {
- // The specifier must have an associated argument
- assert(FS.consumesDataArgument());
-
- StandardFormatString.push_back('{');
-
- if (FS.usesPositionalArg()) {
- // std::format argument identifiers are zero-based, whereas printf ones
- // are one based.
- assert(FS.getPositionalArgIndex() > 0U);
- StandardFormatString.append(llvm::utostr(FS.getPositionalArgIndex() - 1));
- }
-
- // std::format format argument parts to potentially emit:
- // [[fill]align][sign]["#"]["0"][width]["."precision][type]
- std::string FormatSpec;
-
- // printf doesn't support specifying the fill character - it's always a
- // space, so we never need to generate one.
-
- emitAlignment(FS, FormatSpec);
- emitSign(FS, FormatSpec);
- emitAlternativeForm(FS, FormatSpec);
-
- if (FS.hasLeadingZeros())
- FormatSpec.push_back('0');
-
- emitFieldWidth(FS, FormatSpec);
- emitPrecision(FS, FormatSpec);
-
- if (!emitType(FS, Arg, FormatSpec))
- return false;
-
- if (!FormatSpec.empty()) {
- StandardFormatString.push_back(':');
- StandardFormatString.append(FormatSpec);
- }
-
- StandardFormatString.push_back('}');
- return true;
-}
-
-/// Called for each format specifier by ParsePrintfString.
-bool FormatStringConverter::HandlePrintfSpecifier(const PrintfSpecifier &FS,
- const char *StartSpecifier,
- unsigned SpecifierLen,
- const TargetInfo &Target) {
-
- const size_t StartSpecifierPos = StartSpecifier - PrintfFormatString.data();
- assert(StartSpecifierPos + SpecifierLen <= PrintfFormatString.size());
-
- // Everything before the specifier needs copying verbatim
- assert(StartSpecifierPos >= PrintfFormatStringPos);
-
- appendFormatText(StringRef(PrintfFormatString.begin() + PrintfFormatStringPos,
- StartSpecifierPos - PrintfFormatStringPos));
-
- const ConversionSpecifier::Kind ArgKind =
- FS.getConversionSpecifier().getKind();
-
- // Skip over specifier
- PrintfFormatStringPos = StartSpecifierPos + SpecifierLen;
- assert(PrintfFormatStringPos <= PrintfFormatString.size());
-
- FormatStringNeededRewriting = true;
-
- if (ArgKind == ConversionSpecifier::Kind::nArg) {
- // std::print doesn't do the equivalent of %n
- return conversionNotPossible("'%n' is not supported in format string");
- }
-
- if (ArgKind == ConversionSpecifier::Kind::PrintErrno) {
- // std::print doesn't support %m. In theory we could insert a
- // strerror(errno) parameter (assuming that libc has a thread-safe
- // implementation, which glibc does), but that would require keeping track
- // of the input and output parameter indices for position arguments too.
- return conversionNotPossible("'%m' is not supported in format string");
- }
-
- if (ArgKind == ConversionSpecifier::PercentArg) {
- StandardFormatString.push_back('%');
- return true;
- }
-
- const unsigned ArgIndex = FS.getArgIndex() + ArgsOffset;
- if (ArgIndex >= NumArgs) {
- // Argument index out of range. Give up.
- return conversionNotPossible(
- (Twine("argument index ") + Twine(ArgIndex) + " is out of range")
- .str());
- }
-
- return convertArgument(FS, Args[ArgIndex]->IgnoreImplicitAsWritten(),
- StandardFormatString);
-}
-
-/// Called at the very end just before applying fixes to capture the last part
-/// of the format string.
-void FormatStringConverter::finalizeFormatText() {
- appendFormatText(
- StringRef(PrintfFormatString.begin() + PrintfFormatStringPos,
- PrintfFormatString.size() - PrintfFormatStringPos));
- PrintfFormatStringPos = PrintfFormatString.size();
-
- if (StringRef(StandardFormatString).ends_with("\\n") &&
- !StringRef(StandardFormatString).ends_with("\\\\n")) {
- UsePrintNewlineFunction = true;
- FormatStringNeededRewriting = true;
- StandardFormatString.erase(StandardFormatString.end() - 2,
- StandardFormatString.end());
- }
-
- StandardFormatString.push_back('\"');
-}
-
-/// Append literal parts of the format text, reinstating escapes as required.
-void FormatStringConverter::appendFormatText(const StringRef Text) {
- for (const char Ch : Text) {
- if (Ch == '\a')
- StandardFormatString += "\\a";
- else if (Ch == '\b')
- StandardFormatString += "\\b";
- else if (Ch == '\f')
- StandardFormatString += "\\f";
- else if (Ch == '\n')
- StandardFormatString += "\\n";
- else if (Ch == '\r')
- StandardFormatString += "\\r";
- else if (Ch == '\t')
- StandardFormatString += "\\t";
- else if (Ch == '\v')
- StandardFormatString += "\\v";
- else if (Ch == '\"')
- StandardFormatString += "\\\"";
- else if (Ch == '\\')
- StandardFormatString += "\\\\";
- else if (Ch == '{') {
- StandardFormatString += "{{";
- FormatStringNeededRewriting = true;
- } else if (Ch == '}') {
- StandardFormatString += "}}";
- FormatStringNeededRewriting = true;
- } else if (Ch < 32) {
- StandardFormatString += "\\x";
- StandardFormatString += llvm::hexdigit(Ch >> 4, true);
- StandardFormatString += llvm::hexdigit(Ch & 0xf, true);
- } else
- StandardFormatString += Ch;
- }
-}
-
-/// Called by the check when it is ready to apply the fixes.
-void FormatStringConverter::applyFixes(DiagnosticBuilder &Diag,
- SourceManager &SM) {
- if (FormatStringNeededRewriting) {
- Diag << FixItHint::CreateReplacement(
- CharSourceRange::getTokenRange(FormatExpr->getBeginLoc(),
- FormatExpr->getEndLoc()),
- StandardFormatString);
- }
-
- for (const auto &[Arg, Replacement] : ArgFixes) {
- SourceLocation AfterOtherSide =
- Lexer::findNextToken(Arg->getEndLoc(), SM, LangOpts)->getLocation();
-
- Diag << FixItHint::CreateInsertion(Arg->getBeginLoc(), Replacement)
- << FixItHint::CreateInsertion(AfterOtherSide, ")");
- }
-
- for (const auto &Match : ArgCStrRemovals) {
- const auto *Call = Match.getNodeAs<CallExpr>("call");
- const auto *Arg = Match.getNodeAs<Expr>("arg");
- const auto *Member = Match.getNodeAs<MemberExpr>("member");
- const bool Arrow = Member->isArrow();
- const std::string ArgText =
- Arrow ? utils::fixit::formatDereference(*Arg, *Context)
- : tooling::fixit::getText(*Arg, *Context).str();
- if (!ArgText.empty())
- Diag << FixItHint::CreateReplacement(Call->getSourceRange(), ArgText);
- }
-}
-} // namespace clang::tidy::utils
diff --git a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.h b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
deleted file mode 100644
index b246013c24c45..0000000000000
--- a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.h
+++ /dev/null
@@ -1,98 +0,0 @@
-//===--- FormatStringConverter.h - clang-tidy--------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// Declaration of the FormatStringConverter class which is used to convert
-/// printf format strings to C++ std::formatter format strings.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_FORMATSTRINGCONVERTER_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_FORMATSTRINGCONVERTER_H
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/FormatString.h"
-#include "clang/ASTMatchers/ASTMatchers.h"
-#include <string>
-
-namespace clang::tidy::utils {
-
-/// Convert a printf-style format string to a std::formatter-style one, and
-/// prepare any casts that are required to wrap the arguments to retain printf
-/// compatibility. This class is expecting to work on the already-cooked format
-/// string (i.e. all the escapes have been converted) so we have to convert them
-/// back. This means that we might not convert them back using the same form.
-class FormatStringConverter
- : public clang::analyze_format_string::FormatStringHandler {
-public:
- using ConversionSpecifier = clang::analyze_format_string::ConversionSpecifier;
- using PrintfSpecifier = analyze_printf::PrintfSpecifier;
- FormatStringConverter(ASTContext *Context, const CallExpr *Call,
- unsigned FormatArgOffset, bool StrictMode,
- const LangOptions &LO);
-
- bool canApply() const { return ConversionNotPossibleReason.empty(); }
- const std::string &conversionNotPossibleReason() const {
- return ConversionNotPossibleReason;
- }
- void applyFixes(DiagnosticBuilder &Diag, SourceManager &SM);
- bool usePrintNewlineFunction() const { return UsePrintNewlineFunction; }
-
-private:
- ASTContext *Context;
- const bool CastMismatchedIntegerTypes;
- const Expr *const *Args;
- const unsigned NumArgs;
- unsigned ArgsOffset;
- const LangOptions &LangOpts;
- std::string ConversionNotPossibleReason;
- bool FormatStringNeededRewriting = false;
- bool UsePrintNewlineFunction = false;
- size_t PrintfFormatStringPos = 0U;
- StringRef PrintfFormatString;
-
- /// Lazily-created c_str() call matcher
- std::optional<clang::ast_matchers::StatementMatcher>
- StringCStrCallExprMatcher;
-
- const StringLiteral *FormatExpr;
- std::string StandardFormatString;
-
- /// Casts to be used to wrap arguments to retain printf compatibility.
- std::vector<std::tuple<const Expr *, std::string>> ArgFixes;
- std::vector<clang::ast_matchers::BoundNodes> ArgCStrRemovals;
-
- void emitAlignment(const PrintfSpecifier &FS, std::string &FormatSpec);
- void emitSign(const PrintfSpecifier &FS, std::string &FormatSpec);
- void emitAlternativeForm(const PrintfSpecifier &FS, std::string &FormatSpec);
- void emitFieldWidth(const PrintfSpecifier &FS, std::string &FormatSpec);
- void emitPrecision(const PrintfSpecifier &FS, std::string &FormatSpec);
- void emitStringArgument(const Expr *Arg);
- bool emitIntegerArgument(ConversionSpecifier::Kind ArgKind, const Expr *Arg,
- unsigned ArgIndex, std::string &FormatSpec);
-
- bool emitType(const PrintfSpecifier &FS, const Expr *Arg,
- std::string &FormatSpec);
- bool convertArgument(const PrintfSpecifier &FS, const Expr *Arg,
- std::string &StandardFormatString);
-
- bool HandlePrintfSpecifier(const PrintfSpecifier &FS,
- const char *StartSpecifier, unsigned SpecifierLen,
- const TargetInfo &Target) override;
-
- void appendFormatText(StringRef Text);
- void finalizeFormatText();
- bool conversionNotPossible(std::string Reason) {
- ConversionNotPossibleReason = std::move(Reason);
- return false;
- }
-};
-
-} // namespace clang::tidy::utils
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_FORMATSTRINGCONVERTER_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 726ec41f6a736..03426772f6037 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -181,16 +181,6 @@ New checks
Converts standard library type traits of the form ``traits<...>::type`` and
``traits<...>::value`` into ``traits_t<...>`` and ``traits_v<...>`` respectively.
-- New :doc:`modernize-use-std-print
- <clang-tidy/checks/modernize/use-std-print>` check.
-
- Converts calls to ``printf``, ``fprintf``, ``absl::PrintF``,
- ``absl::FPrintf`` or other functions via configuration options, to
- equivalent calls to C++23's ``std::print`` and ``std::println``, or other
- functions via a configuration option, modifying the format string
- appropriately and removing now-unnecessary calls to
- ``std::string::c_str()`` and ``std::string::data()``.
-
- New :doc:`performance-avoid-endl
<clang-tidy/checks/performance/avoid-endl>` check.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 966e98672e0fb..552d1c40c25b8 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -302,7 +302,6 @@ Clang-Tidy Checks
`modernize-use-noexcept <modernize/use-noexcept.html>`_, "Yes"
`modernize-use-nullptr <modernize/use-nullptr.html>`_, "Yes"
`modernize-use-override <modernize/use-override.html>`_, "Yes"
- `modernize-use-std-print <modernize/use-std-print.html>`_, "Yes"
`modernize-use-trailing-return-type <modernize/use-trailing-return-type.html>`_, "Yes"
`modernize-use-transparent-functors <modernize/use-transparent-functors.html>`_, "Yes"
`modernize-use-uncaught-exceptions <modernize/use-uncaught-exceptions.html>`_, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
deleted file mode 100644
index 385ee35c4f8f8..0000000000000
--- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst
+++ /dev/null
@@ -1,147 +0,0 @@
-.. title:: clang-tidy - modernize-use-std-print
-
-modernize-use-std-print
-=======================
-
-Converts calls to ``printf``, ``fprintf``, ``absl::PrintF`` and
-``absl::FPrintf`` to equivalent calls to C++23's ``std::print`` or
-``std::println`` as appropriate, modifying the format string appropriately.
-The replaced and replacement functions can be customised by configuration
-options. Each argument that is the result of a call to ``std::string::c_str()`` and
-``std::string::data()`` will have that now-unnecessary call removed in a
-similar manner to the readability-redundant-string-cstr check.
-
-In other words, it turns lines like::
-
-.. code-block:: c++
-
- fprintf(stderr, "The %s is %3d\n", description.c_str(), value);
-
-into::
-
-.. code-block:: c++
-
- std::println(stderr, "The {} is {:3}", description, value);
-
-It doesn't do a bad job, but it's not perfect. In particular:
-
-- It assumes that the format string is correct for the arguments. If you
- get any warnings when compiling with `-Wformat` then misbehaviour is
- possible.
-
-- At the point that the check runs, the AST contains a single
- ``StringLiteral`` for the format string and any macro expansion, token
- pasting, adjacent string literal concatenation and escaping has been
- handled. Although it's possible for the check to automatically put the
- escapes back, they may not be exactly as they were written (e.g.
- ``"\x0a"`` will become ``"\n"`` and ``"ab" "cd"`` will become
- ``"abcd"``.) This is helpful since it means that the PRIx macros from
- ``<inttypes.h>`` are removed correctly.
-
-- It supports field widths, precision, positional arguments, leading zeros,
- leading ``+``, alignment and alternative forms.
-
-- Use of any unsupported flags or specifiers will cause the entire
- statement to be left alone and a warning to be emitted. Particular
- unsupported features are:
-
- - The ``%'`` flag for thousands separators.
-
- - The glibc extension ``%m``.
-
-If conversion would be incomplete or unsafe then the entire invocation will
-be left unchanged.
-
-If the call is deemed suitable for conversion then:
-
-- ``printf``, ``fprintf``, ``absl::PrintF``, ``absl::FPrintF`` and any
- functions specified by the `PrintfLikeFunctions` option or
- `FprintfLikeFunctions` are replaced with the function specified by the
- `ReplacementPrintlnFunction` option if the format string ends with ``\n``
- or `ReplacementPrintFunction` otherwise.
-- the format string is rewritten to use the ``std::formatter`` language and
- a ``\n`` is removed from the end.
-- any arguments that corresponded to ``%p`` specifiers that
- ``std::formatter`` wouldn't accept are wrapped in a ``static_cast``
- to ``const void *``.
-- any arguments that corresponded to ``%s`` specifiers where the argument
- is of ``signed char`` or ``unsigned char`` type are wrapped in a
- ``reinterpret_cast<const char *>``.
-- any arguments where the format string and the parameter
diff er in
- signedness will be wrapped in an approprate ``static_cast`` if `StrictMode`
- is enabled.
-- any arguments that end in a call to ``std::string::c_str()`` or
- ``std::string_data()`` will have that call removed.
-
-Options
--------
-
-.. option:: StrictMode
-
- When `true`, the check will add casts when converting from variadic
- functions like ``printf`` and printing signed or unsigned integer types
- (including fixed-width integer types from ``<cstdint>``, ``ptr
diff _t``,
- ``size_t`` and ``ssize_t``) as the opposite signedness to ensure that
- the output matches that of ``printf``. This does not apply when
- converting from non-variadic functions such as ``absl::PrintF`` and
- ``fmt::printf``. For example, with `StrictMode` enabled:
-
- .. code-block:: c++
-
- int i = -42;
- unsigned int u = 0xffffffff;
- printf("%d %u\n", i, u);
-
- would be converted to::
-
- .. code-block:: c++
-
- std::print("{} {}\n", static_cast<unsigned int>(i), static_cast<int>(u));
-
- to ensure that the output will continue to be the unsigned representation
- of `-42` and the signed representation of `0xffffffff` (often
- `4294967254` and `-1` respectively.) When `false` (which is the default),
- these casts will not be added which may cause a change in the output.
-
-.. option:: PrintfLikeFunctions
-
- A semicolon-separated list of (fully qualified) extra function names to
- replace, with the requirement that the first parameter contains the
- printf-style format string and the arguments to be formatted follow
- immediately afterwards. If neither this option nor
- `FprintfLikeFunctions` are set then the default value for this option
- is `printf; absl::PrintF`, otherwise it is empty.
-
-
-.. option:: FprintfLikeFunctions
-
- A semicolon-separated list of (fully qualified) extra function names to
- replace, with the requirement that the first parameter is retained, the
- second parameter contains the printf-style format string and the
- arguments to be formatted follow immediately afterwards. If neither this
- option nor `PrintfLikeFunctions` are set then the default value for
- this option is `fprintf; absl::FPrintF`, otherwise it is empty.
-
-.. option:: ReplacementPrintFunction
-
- The function that will be used to replace ``printf``, ``fprintf`` etc.
- during conversion rather than the default ``std::print`` when the
- originalformat string does not end with ``\n``. It is expected that the
- function provides an interface that is compatible with ``std::print``. A
- suitable candidate would be ``fmt::print``.
-
-.. option:: ReplacementPrintlnFunction
-
- The function that will be used to replace ``printf``, ``fprintf`` etc.
- during conversion rather than the default ``std::println`` when the
- original format string ends with ``\n``. It is expected that the
- function provides an interface that is compatible with ``std::println``.
- A suitable candidate would be ``fmt::println``.
-
-.. option:: PrintHeader
-
- The header that must be included for the declaration of
- `ReplacementPrintFunction` so that a ``#include`` directive can be
- added if required. If `ReplacementPrintFunction` is ``std::print``
- then this option will default to ``<print>``, otherwise this option will
- default to nothing and no ``#include`` directive will be added.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstddef b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstddef
deleted file mode 100644
index 800285e887cda..0000000000000
--- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstddef
+++ /dev/null
@@ -1,19 +0,0 @@
-//===--- cstddef - Stub header for tests -------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _CSTDDEF_
-#define _CSTDDEF_
-
-#include "stddef.h"
-
-namespace std {
- using ::ptr
diff _t;
- using ::size_t;
-}
-
-#endif // _CSTDDEF_
diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstdint b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstdint
deleted file mode 100644
index 2029eb90dcb87..0000000000000
--- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstdint
+++ /dev/null
@@ -1,40 +0,0 @@
-//===--- cstdint - Stub header for tests ------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _CSTDINT_
-#define _CSTDINT_
-
-typedef __INTMAX_TYPE__ intmax_t;
-typedef __UINTMAX_TYPE__ uintmax_t;
-
-namespace std {
- using ::intmax_t;
- using ::uintmax_t;
-}
-
-#define DECLARE_INTTYPE(N) \
- typedef __INT ## N ## _TYPE__ int ## N ## _t; \
- typedef int ## N ## _t int_least ## N ## _t; \
- typedef int ## N ## _t int_fast ## N ## _t; \
- typedef __UINT ## N ## _TYPE__ uint ## N ## _t; \
- typedef uint ## N ## _t uint_least ## N ## _t; \
- typedef uint ## N ## _t uint_fast ## N ## _t; \
- namespace std { \
- using ::int ## N ## _t; \
- using ::int_least ## N ## _t; \
- using ::int_fast ## N ## _t; \
- using ::uint ## N ## _t; \
- using ::uint_least ## N ## _t; \
- using ::uint_fast ## N ## _t; \
- } // std
-
-// For reasons unknown, these aren't coming in from <stdint.h>
-DECLARE_INTTYPE(8)
-DECLARE_INTTYPE(64)
-
-#endif // _CSTDINT__
diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstdio b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstdio
deleted file mode 100644
index 5024529f96da6..0000000000000
--- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/cstdio
+++ /dev/null
@@ -1,21 +0,0 @@
-//===--- cstdio - Stub header for tests -------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _STDIO_
-#define _STDIO_
-
-#include <stdio.h>
-
-namespace std {
- using ::FILE;
- using ::printf;
- using ::fprintf;
-}
-
-#endif // _STDIO_
-
diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/inttypes.h b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/inttypes.h
deleted file mode 100644
index 9dc7ae39b3a3f..0000000000000
--- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/inttypes.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//===--- inttypes.h - Stub header for tests ---------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _INTTYPES_H_
-#define _INTTYPES_H_
-
-typedef __INTMAX_TYPE__ intmax_t;
-typedef __INT64_TYPE__ int64_t;
-typedef __INT32_TYPE__ int32_t;
-typedef __INT16_TYPE__ int16_t;
-typedef __INT8_TYPE__ int8_t;
-
-typedef __UINTMAX_TYPE__ uintmax_t;
-typedef __UINT64_TYPE__ uint64_t;
-typedef __UINT32_TYPE__ uint32_t;
-typedef __UINT16_TYPE__ uint16_t;
-typedef __UINT8_TYPE__ uint8_t;
-
-#define PRIdMAX "lld"
-#define PRId64 "lld"
-#define PRId32 "d"
-#define PRId16 "hd"
-#define PRId8 "hhd"
-
-#define PRIiMAX "lli"
-#define PRIi64 "lli"
-#define PRIi32 "i"
-#define PRIi16 "hi"
-#define PRIi8 "hhi"
-
-#define PRIiFAST64 "lli"
-#define PRIiFAST32 "i"
-#define PRIiFAST16 "hi"
-#define PRIiFAST8 "hhi"
-
-#define PRIiLEAST64 "lli"
-#define PRIiLEAST32 "i"
-#define PRIiLEAST16 "hi"
-#define PRIiLEAST8 "hhi"
-
-#define PRIuMAX "llu"
-#define PRIu64 "llu"
-#define PRIu32 "u"
-#define PRIu16 "hu"
-#define PRIu8 "hhu"
-
-#define PRIuFAST64 "llu"
-#define PRIuFAST32 "u"
-#define PRIuFAST16 "hu"
-#define PRIuFAST8 "hhu"
-
-#define PRIuLEAST64 "llu"
-#define PRIuLEAST32 "u"
-#define PRIuLEAST16 "hu"
-#define PRIuLEAST8 "hhu"
-
-#endif // _INTTYPES_H_
diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/stdio.h b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/stdio.h
index 803abfdd590f7..eebe9fd914ad0 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/stdio.h
+++ b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/stdio.h
@@ -12,13 +12,7 @@
// A header intended to contain C standard input and output library
// declarations.
-typedef struct structFILE {} FILE;
-extern FILE *stderr;
-
int printf(const char *, ...);
-int fprintf(FILE *, const char *, ...);
-
-#define NULL (0)
#endif // _STDIO_H_
diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string.h b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string.h
index 4ab7e930e4b50..931fcf36345a5 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string.h
+++ b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string.h
@@ -9,7 +9,7 @@
#ifndef _STRING_H_
#define _STRING_H_
-#include "stddef.h"
+typedef __typeof__(sizeof(0)) size_t;
void *memcpy(void *dest, const void *src, size_t n);
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp
deleted file mode 100644
index 5345380028309..0000000000000
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-absl.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-// RUN: %check_clang_tidy \
-// RUN: -std=c++23 %s modernize-use-std-print %t -- \
-// RUN: -config="{CheckOptions: [{key: StrictMode, value: true}]}" \
-// RUN: -- -isystem %clang_tidy_headers
-// RUN: %check_clang_tidy \
-// RUN: -std=c++23 %s modernize-use-std-print %t -- \
-// RUN: -config="{CheckOptions: [{key: StrictMode, value: false}]}" \
-// RUN: -- -isystem %clang_tidy_headers
-
-#include <cstdio>
-#include <string.h>
-
-namespace absl
-{
-// Use const char * for the format since the real type is hard to mock up.
-template <typename... Args>
-int PrintF(const char *format, const Args&... args);
-
-template <typename... Args>
-int FPrintF(FILE* output, const char *format, const Args&... args);
-}
-
-void printf_simple() {
- absl::PrintF("Hello %s %d", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'PrintF' [modernize-use-std-print]
- // CHECK-FIXES: std::print("Hello {} {}", "world", 42);
-}
-
-void printf_newline() {
- absl::PrintF("Hello %s %d\n", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'PrintF' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {} {}", "world", 42);
-
- using namespace absl;
- PrintF("Hello %s %d\n", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'PrintF' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {} {}", "world", 42);
-}
-
-// absl uses the type of the argument rather than the format string, so unsigned
-// types will be printed as unsigned even if the format string indicates signed
-// and vice-versa. This is exactly what std::print will do too, so no casts are
-// required.
-void printf_no_casts_in_strict_mode() {
- using namespace absl;
-
- const unsigned short us = 42U;
- PrintF("Integer %hd from unsigned short\n", us);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'PrintF' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from unsigned short", us);
-
- const short s = 42;
- PrintF("Unsigned integer %hu from short\n", s);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'PrintF' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Unsigned integer {} from short", s);
-}
-
-void fprintf_simple(FILE *fp) {
- absl::FPrintF(fp, "Hello %s %d", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'FPrintF' [modernize-use-std-print]
- // CHECK-FIXES: std::print(fp, "Hello {} {}", "world", 42);
-}
-
-void fprintf_newline(FILE *fp) {
- absl::FPrintF(fp, "Hello %s %d\n", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'FPrintF' [modernize-use-std-print]
- // CHECK-FIXES: std::println(fp, "Hello {} {}", "world", 42);
-
- using namespace absl;
- FPrintF(fp, "Hello %s %d\n", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'FPrintF' [modernize-use-std-print]
- // CHECK-FIXES: std::println(fp, "Hello {} {}", "world", 42);
-}
-
-void fprintf_no_casts_in_strict_mode(FILE *fp) {
- using namespace absl;
-
- const unsigned short us = 42U;
- FPrintF(fp, "Integer %hd from unsigned short\n", us);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'FPrintF' [modernize-use-std-print]
- // CHECK-FIXES: std::println(fp, "Integer {} from unsigned short", us);
-
- const short s = 42;
- FPrintF(fp, "Unsigned integer %hu from short\n", s);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'FPrintF' [modernize-use-std-print]
- // CHECK-FIXES: std::println(fp, "Unsigned integer {} from short", s);
-}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
deleted file mode 100644
index 08779837c75e7..0000000000000
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-custom.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-// RUN: %check_clang_tidy -std=c++23 %s modernize-use-std-print %t -- \
-// RUN: -config="{CheckOptions: \
-// RUN: [ \
-// RUN: { \
-// RUN: key: modernize-use-std-print.PrintfLikeFunctions, \
-// RUN: value: '::myprintf; mynamespace::myprintf2' \
-// RUN: }, \
-// RUN: { \
-// RUN: key: modernize-use-std-print.FprintfLikeFunctions, \
-// RUN: value: '::myfprintf; mynamespace::myfprintf2' \
-// RUN: } \
-// RUN: ] \
-// RUN: }" \
-// RUN: -- -isystem %clang_tidy_headers
-
-#include <cstdio>
-#include <string.h>
-
-int myprintf(const char *, ...);
-int myfprintf(FILE *fp, const char *, ...);
-
-namespace mynamespace {
-int myprintf2(const char *, ...);
-int myfprintf2(FILE *fp, const char *, ...);
-}
-
-void printf_simple() {
- myprintf("Hello %s %d", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'myprintf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("Hello {} {}", "world", 42);
-}
-
-void printf_newline() {
- myprintf("Hello %s %d\n", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myprintf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {} {}", "world", 42);
-
- mynamespace::myprintf2("Hello %s %d\n", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myprintf2' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {} {}", "world", 42);
-
- using mynamespace::myprintf2;
- myprintf2("Hello %s %d\n", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myprintf2' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {} {}", "world", 42);
-
- // When using custom options leave printf alone
- printf("Hello %s %d\n", "world", 42);
-}
-
-void fprintf_simple(FILE *fp)
-{
- myfprintf(stderr, "Hello %s %d", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'myfprintf' [modernize-use-std-print]
- // CHECK-FIXES: std::print(stderr, "Hello {} {}", "world", 42);
-}
-
-void fprintf_newline(FILE *fp)
-{
- myfprintf(stderr, "Hello %s %d\n", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myfprintf' [modernize-use-std-print]
- // CHECK-FIXES: std::println(stderr, "Hello {} {}", "world", 42);
-
- mynamespace::myfprintf2(stderr, "Hello %s %d\n", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myfprintf2' [modernize-use-std-print]
- // CHECK-FIXES: std::println(stderr, "Hello {} {}", "world", 42);
-
- using mynamespace::myfprintf2;
- myfprintf2(stderr, "Hello %s %d\n", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'myfprintf2' [modernize-use-std-print]
- // CHECK-FIXES: std::println(stderr, "Hello {} {}", "world", 42);
-
- // When using custom options leave fprintf alone
- fprintf(stderr, "Hello %s %d\n", "world", 42);
-}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-fmt.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-fmt.cpp
deleted file mode 100644
index 81a5631fd9d84..0000000000000
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print-fmt.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-// RUN: %check_clang_tidy %s modernize-use-std-print %t -- \
-// RUN: -config="{CheckOptions: \
-// RUN: [ \
-// RUN: { \
-// RUN: key: modernize-use-std-print.ReplacementPrintFunction, \
-// RUN: value: 'fmt::print' \
-// RUN: }, \
-// RUN: { \
-// RUN: key: modernize-use-std-print.ReplacementPrintlnFunction, \
-// RUN: value: 'fmt::println' \
-// RUN: }, \
-// RUN: { \
-// RUN: key: modernize-use-std-print.PrintHeader, \
-// RUN: value: '<fmt/core.h>' \
-// RUN: } \
-// RUN: ] \
-// RUN: }" \
-// RUN: -- -isystem %clang_tidy_headers
-
-#include <cstdio>
-// CHECK-FIXES: #include <fmt/core.h>
-#include <string.h>
-
-void printf_simple() {
- printf("Hello %s %d", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'fmt::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: fmt::print("Hello {} {}", "world", 42);
-}
-
-void printf_newline() {
- printf("Hello %s %d\n", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'fmt::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: fmt::println("Hello {} {}", "world", 42);
-}
-
-void fprintf_simple(FILE *fp) {
- fprintf(fp, "Hello %s %d", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'fmt::print' instead of 'fprintf' [modernize-use-std-print]
- // CHECK-FIXES: fmt::print(fp, "Hello {} {}", "world", 42);
-}
-
-void fprintf_newline(FILE *fp) {
- fprintf(fp, "Hello %s %d\n", "world", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'fmt::println' instead of 'fprintf' [modernize-use-std-print]
- // CHECK-FIXES: fmt::println(fp, "Hello {} {}", "world", 42);
-}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
deleted file mode 100644
index 2c7cc6263d7ea..0000000000000
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp
+++ /dev/null
@@ -1,1255 +0,0 @@
-// RUN: %check_clang_tidy -check-suffixes=,STRICT \
-// RUN: -std=c++23 %s modernize-use-std-print %t -- \
-// RUN: -config="{CheckOptions: [{key: StrictMode, value: true}]}" \
-// RUN: -- -isystem %clang_tidy_headers
-// RUN: %check_clang_tidy -check-suffixes=,NOTSTRICT \
-// RUN: -std=c++23 %s modernize-use-std-print %t -- \
-// RUN: -config="{CheckOptions: [{key: StrictMode, value: false}]}" \
-// RUN: -- -isystem %clang_tidy_headers
-#include <cstddef>
-#include <cstdint>
-#include <cstdio>
-// CHECK-FIXES: #include <print>
-#include <inttypes.h>
-#include <string.h>
-#include <string>
-
-void printf_simple() {
- printf("Hello");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("Hello");
-}
-
-void printf_newline() {
- printf("Hello\n");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello");
-
- printf("Split" "\n");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Split");
-
- printf("Double\n\n");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Double\n");
-}
-
-void printf_deceptive_newline() {
- printf("Hello\\n");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("Hello\\n");
-
- printf("Hello\x0a");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello");
-}
-
-void fprintf_simple() {
- fprintf(stderr, "Hello");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'fprintf' [modernize-use-std-print]
- // CHECK-FIXES: std::print(stderr, "Hello");
-}
-
-void std_printf_simple() {
- std::printf("std::Hello");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("std::Hello");
-}
-
-void printf_escape() {
- printf("before \t");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("before \t");
-
- printf("\n after");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("\n after");
-
- printf("before \a after");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("before \a after");
-
- printf("Bell\a%dBackspace\bFF%s\fNewline\nCR\rTab\tVT\vEscape\x1b\x07%d", 42, "string", 99);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("Bell\a{}Backspace\bFF{}\fNewline\nCR\rTab\tVT\vEscape\x1b\a{}", 42, "string", 99);
-
- printf("not special \x1b\x01\x7f");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("not special \x1b\x01\x7f");
-}
-
-void printf_percent() {
- printf("before %%");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("before %");
-
- printf("%% after");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("% after");
-
- printf("before %% after");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("before % after");
-
- printf("Hello %% and another %%");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("Hello % and another %");
-
- printf("Not a string %%s");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("Not a string %s");
-}
-
-void printf_curlies() {
- printf("%d {}", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{} {{[{][{]}}}}", 42);
-
- printf("{}");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{{[{][{]}}}}");
-}
-
-void printf_unsupported_format_specifiers() {
- int pos;
- printf("%d %n %d\n", 42, &pos, 72);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: unable to use 'std::println' instead of 'printf' because '%n' is not supported in format string [modernize-use-std-print]
-
- printf("Error %m\n");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: unable to use 'std::println' instead of 'printf' because '%m' is not supported in format string [modernize-use-std-print]
-}
-
-void printf_not_string_literal(const char *fmt) {
- // We can't convert the format string if it's not a literal
- printf(fmt, 42);
-}
-
-void printf_inttypes_ugliness() {
- // The one advantage of the checker seeing the token pasted version of the
- // format string is that we automatically cope with the horrendously-ugly
- // inttypes.h macros!
- int64_t u64 = 42;
- uintmax_t umax = 4242;
- printf("uint64:%" PRId64 " uintmax:%" PRIuMAX "\n", u64, umax);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("uint64:{} uintmax:{}", u64, umax);
-}
-
-void printf_raw_string() {
- // This one doesn't require the format string to be changed, so it stays intact
- printf(R"(First\Second)");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print(R"(First\Second)");
-
- // This one does require the format string to be changed, so unfortunately it
- // gets reformatted as a normal string.
- printf(R"(First %d\Second)", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("First {}\\Second", 42);
-}
-
-void printf_integer_d() {
- const bool b = true;
- // The "d" type is necessary here for compatibility with printf since
- // std::print will print booleans as "true" or "false".
- printf("Integer %d from bool\n", b);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {:d} from bool", b);
-
- // The "d" type is necessary here for compatibility with printf since
- // std::print will print booleans as "true" or "false".
- printf("Integer %i from bool\n", b);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {:d} from bool", b);
-
- // The 'd' is always necessary since otherwise the parameter will be formatted as a character
- const char c = 'A';
- printf("Integer %d from char\n", c);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {:d} from char", c);
-
- printf("Integer %i from char\n", 'A');
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {:d} from char", 'A');
-
- const signed char sc = 'A';
- printf("Integer %hhd from signed char\n", sc);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from signed char", sc);
-
- printf("Integer %hhi from signed char\n", sc);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from signed char", sc);
-
- const unsigned char uc = 'A';
- printf("Integer %hhd from unsigned char\n", uc);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integer {} from unsigned char", uc);
- // CHECK-FIXES-STRICT: std::println("Integer {} from unsigned char", static_cast<signed char>(uc));
-
- printf("Integer %hhi from unsigned char\n", uc);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integer {} from unsigned char", uc);
- // CHECK-FIXES-STRICT: std::println("Integer {} from unsigned char", static_cast<signed char>(uc));
-
- const int8_t i8 = 42;
- printf("Integer %" PRIi8 " from int8_t\n", i8);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from int8_t", i8);
-
- const int_fast8_t if8 = 42;
- printf("Integer %" PRIiFAST8 " from int_fast8_t\n", if8);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from int_fast8_t", if8);
-
- const int_least8_t il8 = 42;
- printf("Integer %" PRIiFAST8 " from int_least8_t\n", il8);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from int_least8_t", il8);
-
- const uint8_t u8 = 42U;
- const std::uint8_t su8 = u8;
- printf("Integers %" PRIi8 " and %" PRId8 " from uint8_t\n", u8, su8);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integers {} and {} from uint8_t", u8, su8);
- // CHECK-FIXES-STRICT: std::println("Integers {} and {} from uint8_t", static_cast<int8_t>(u8), static_cast<std::int8_t>(su8));
-
- const uint_fast8_t uf8 = 42U;
- printf("Integer %" PRIiFAST8 " from uint_fast8_t\n", uf8);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integer {} from uint_fast8_t", uf8);
- // CHECK-FIXES-STRICT: std::println("Integer {} from uint_fast8_t", static_cast<int_fast8_t>(uf8));
-
- const uint_least8_t ul8 = 42U;
- printf("Integer %" PRIiLEAST8 " from uint_least8_t\n", ul8);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integer {} from uint_least8_t", ul8);
- // CHECK-FIXES-STRICT: std::println("Integer {} from uint_least8_t", static_cast<int_least8_t>(ul8));
-
- const short s = 42;
- printf("Integer %hd from short\n", s);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from short", s);
-
- printf("Integer %hi from short\n", s);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from short", s);
-
- const unsigned short us = 42U;
- printf("Integer %hd from unsigned short\n", us);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integer {} from unsigned short", us);
- // CHECK-FIXES-STRICT: std::println("Integer {} from unsigned short", static_cast<short>(us));
-
- printf("Integer %hi from unsigned short\n", us);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integer {} from unsigned short", us);
- // CHECK-FIXES-STRICT: std::println("Integer {} from unsigned short", static_cast<short>(us));
-
- const int i = 42;
- printf("Integer %d from integer\n", i);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from integer", i);
-
- printf("Integer %i from integer\n", i);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from integer", i);
-
- const unsigned int ui = 42U;
- printf("Integer %d from unsigned integer\n", ui);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integer {} from unsigned integer", ui);
- // CHECK-FIXES-STRICT: std::println("Integer {} from unsigned integer", static_cast<int>(ui));
-
- printf("Integer %i from unsigned integer\n", ui);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integer {} from unsigned integer", ui);
- // CHECK-FIXES-STRICT: std::println("Integer {} from unsigned integer", static_cast<int>(ui));
-
- const long l = 42L;
- printf("Integer %ld from long\n", l);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from long", l);
-
- printf("Integer %li from long\n", l);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from long", l);
-
- const unsigned long ul = 42UL;
- printf("Integer %ld from unsigned long\n", ul);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integer {} from unsigned long", ul);
- // CHECK-FIXES-STRICT: std::println("Integer {} from unsigned long", static_cast<long>(ul));
-
- printf("Integer %li from unsigned long\n", ul);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integer {} from unsigned long", ul);
- // CHECK-FIXES-STRICT: std::println("Integer {} from unsigned long", static_cast<long>(ul));
-
- const long long ll = 42LL;
- printf("Integer %lld from long long\n", ll);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from long long", ll);
-
- printf("Integer %lli from long long\n", ll);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integer {} from long long", ll);
-
- const unsigned long long ull = 42ULL;
- printf("Integer %lld from unsigned long long\n", ull);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integer {} from unsigned long long", ull);
- // CHECK-FIXES-STRICT: std::println("Integer {} from unsigned long long", static_cast<long long>(ull));
-
- printf("Integer %lli from unsigned long long\n", ull);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integer {} from unsigned long long", ull);
- // CHECK-FIXES-STRICT: std::println("Integer {} from unsigned long long", static_cast<long long>(ull));
-
- const intmax_t im = 42;
- const std::intmax_t sim = im;
- printf("Integers %jd and %jd from intmax_t\n", im, sim);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integers {} and {} from intmax_t", im, sim);
-
- printf("Integers %ji and %ji from intmax_t\n", im, sim);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integers {} and {} from intmax_t", im, sim);
-
- const uintmax_t uim = 42;
- const std::uintmax_t suim = uim;
- printf("Integers %jd and %jd from uintmax_t\n", uim, suim);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integers {} and {} from uintmax_t", uim, suim);
- // CHECK-FIXES-STRICT: std::println("Integers {} and {} from uintmax_t", static_cast<intmax_t>(uim), static_cast<std::intmax_t>(suim));
-
- printf("Integer %ji from intmax_t\n", uim);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integer {} from intmax_t", uim);
- // CHECK-FIXES-STRICT: std::println("Integer {} from intmax_t", static_cast<intmax_t>(uim));
-
- const int ai[] = { 0, 1, 2, 3};
- const ptr
diff _t pd = &ai[3] - &ai[0];
- const std::ptr
diff _t spd = pd;
- printf("Integers %td and %td from ptr
diff _t\n", pd, spd);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integers {} and {} from ptr
diff _t", pd, spd);
-
- printf("Integers %ti and %ti from ptr
diff _t\n", pd, spd);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Integers {} and {} from ptr
diff _t", pd, spd);
-
- const size_t z = 42UL;
- const std::size_t sz = z;
- printf("Integers %zd and %zd from size_t\n", z, sz);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Integers {} and {} from size_t", z, sz);
- // CHECK-FIXES-STRICT: std::println("Integers {} and {} from size_t", static_cast<ssize_t>(z), static_cast<std::ssize_t>(sz));
-}
-
-void printf_integer_u()
-{
- const bool b = true;
- // The "d" type is necessary here for compatibility with printf since
- // std::print will print booleans as "true" or "false".
- printf("Unsigned integer %u from bool\n", b);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Unsigned integer {:d} from bool", b);
-
- const char c = 'A';
- printf("Unsigned integer %hhu from char\n", c);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Unsigned integer {:d} from char", c);
- // CHECK-FIXES-STRICT: std::println("Unsigned integer {} from char", static_cast<unsigned char>(c));
-
- const signed char sc = 'A';
- printf("Unsigned integer %hhu from signed char\n", sc);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Unsigned integer {} from signed char", sc);
- // CHECK-FIXES-STRICT: std::println("Unsigned integer {} from signed char", static_cast<unsigned char>(sc));
-
- printf("Unsigned integer %u from signed char\n", sc);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Unsigned integer {} from signed char", sc);
- // CHECK-FIXES-STRICT: std::println("Unsigned integer {} from signed char", static_cast<unsigned char>(sc));
-
- const unsigned char uc = 'A';
- printf("Unsigned integer %hhu from unsigned char\n", uc);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Unsigned integer {} from unsigned char", uc);
-
- printf("Unsigned integer %u from unsigned char\n", uc);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Unsigned integer {} from unsigned char", uc);
-
- const int8_t i8 = 42;
- printf("Unsigned integer %" PRIu8 " from int8_t\n", i8);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Unsigned integer {} from int8_t", i8);
- // CHECK-FIXES-STRICT: std::println("Unsigned integer {} from int8_t", static_cast<uint8_t>(i8));
-
- const int_fast8_t if8 = 42;
- printf("Unsigned integer %" PRIuFAST8 " from int_fast8_t\n", if8);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Unsigned integer {} from int_fast8_t", if8);
- // CHECK-FIXES-STRICT: std::println("Unsigned integer {} from int_fast8_t", static_cast<uint_fast8_t>(if8));
-
- const int_least8_t il8 = 42;
- printf("Unsigned integer %" PRIuFAST8 " from int_least8_t\n", il8);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Unsigned integer {} from int_least8_t", il8);
- // CHECK-FIXES-STRICT: std::println("Unsigned integer {} from int_least8_t", static_cast<uint_least8_t>(il8));
-
- const uint8_t u8 = 42U;
- printf("Unsigned integer %" PRIu8 " from uint8_t\n", u8);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Unsigned integer {} from uint8_t", u8);
-
- const uint_fast8_t uf8 = 42U;
- printf("Unsigned integer %" PRIuFAST8 " from uint_fast8_t\n", uf8);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Unsigned integer {} from uint_fast8_t", uf8);
-
- const uint_least8_t ul8 = 42U;
- printf("Unsigned integer %" PRIuLEAST8 " from uint_least8_t\n", ul8);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Unsigned integer {} from uint_least8_t", ul8);
-
- const short s = 42;
- printf("Unsigned integer %hu from short\n", s);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Unsigned integer {} from short", s);
- // CHECK-FIXES-STRICT: std::println("Unsigned integer {} from short", static_cast<unsigned short>(s));
-
- const unsigned short us = 42U;
- printf("Unsigned integer %hu from unsigned short\n", us);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Unsigned integer {} from unsigned short", us);
-
- const int i = 42;
- printf("Unsigned integer %u from signed integer\n", i);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Unsigned integer {} from signed integer", i);
- // CHECK-FIXES-STRICT: std::println("Unsigned integer {} from signed integer", static_cast<unsigned int>(i));
-
- const unsigned int ui = 42U;
- printf("Unsigned integer %u from unsigned integer\n", ui);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Unsigned integer {} from unsigned integer", ui);
-
- const long l = 42L;
- printf("Unsigned integer %u from signed long\n", l);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Unsigned integer {} from signed long", l);
- // CHECK-FIXES-STRICT: std::println("Unsigned integer {} from signed long", static_cast<unsigned long>(l));
-
- const unsigned long ul = 42UL;
- printf("Unsigned integer %lu from unsigned long\n", ul);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Unsigned integer {} from unsigned long", ul);
-
- const long long ll = 42LL;
- printf("Unsigned integer %llu from long long\n", ll);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Unsigned integer {} from long long", ll);
- // CHECK-FIXES-STRICT: std::println("Unsigned integer {} from long long", static_cast<unsigned long long>(ll));
-
- const unsigned long long ull = 42ULL;
- printf("Unsigned integer %llu from unsigned long long\n", ull);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Unsigned integer {} from unsigned long long", ull);
-
- const intmax_t im = 42;
- const std::intmax_t sim = im;
- printf("Unsigned integers %ju and %ju from intmax_t\n", im, sim);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Unsigned integers {} and {} from intmax_t", im, sim);
- // CHECK-FIXES-STRICT: std::println("Unsigned integers {} and {} from intmax_t", static_cast<uintmax_t>(im), static_cast<std::uintmax_t>(sim));
-
- const uintmax_t uim = 42U;
- const std::uintmax_t suim = uim;
- printf("Unsigned integers %ju and %ju from uintmax_t\n", uim, suim);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Unsigned integers {} and {} from uintmax_t", uim, suim);
-
- const int ai[] = { 0, 1, 2, 3};
- const ptr
diff _t pd = &ai[3] - &ai[0];
- const std::ptr
diff _t spd = pd;
- printf("Unsigned integers %tu and %tu from ptr
diff _t\n", pd, spd);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES-NOTSTRICT: std::println("Unsigned integers {} and {} from ptr
diff _t", pd, spd);
- // CHECK-FIXES-STRICT: std::println("Unsigned integers {} and {} from ptr
diff _t", static_cast<size_t>(pd), static_cast<std::size_t>(spd));
-
- const size_t z = 42U;
- const std::size_t sz = z;
- printf("Unsigned integers %zu and %zu from size_t\n", z, sz);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Unsigned integers {} and {} from size_t", z, sz);
-}
-
-// This checks that we get the argument offset right with the extra FILE * argument
-void fprintf_integer() {
- fprintf(stderr, "Integer %d from integer\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'fprintf' [modernize-use-std-print]
- // CHECK-FIXES: std::println(stderr, "Integer {} from integer", 42);
-
- fprintf(stderr, "Integer %i from integer\n", 65);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'fprintf' [modernize-use-std-print]
- // CHECK-FIXES: std::println(stderr, "Integer {} from integer", 65);
-
- fprintf(stderr, "Integer %i from char\n", 'A');
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'fprintf' [modernize-use-std-print]
- // CHECK-FIXES: std::println(stderr, "Integer {:d} from char", 'A');
-
- fprintf(stderr, "Integer %d from char\n", 'A');
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'fprintf' [modernize-use-std-print]
- // CHECK-FIXES: std::println(stderr, "Integer {:d} from char", 'A');
-}
-
-void printf_char() {
- const char c = 'A';
- printf("Char %c from char\n", c);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Char {} from char", c);
-
- const signed char sc = 'A';
- printf("Char %c from signed char\n", sc);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Char {:c} from signed char", sc);
-
- const unsigned char uc = 'A';
- printf("Char %c from unsigned char\n", uc);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Char {:c} from unsigned char", uc);
-
- const int i = 65;
- printf("Char %c from integer\n", i);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Char {:c} from integer", i);
-
- const unsigned int ui = 65;
- printf("Char %c from unsigned integer\n", ui);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Char {:c} from unsigned integer", ui);
-
- const unsigned long long ull = 65;
- printf("Char %c from unsigned long long\n", ull);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Char {:c} from unsigned long long", ull);
-}
-
-void printf_bases() {
- printf("Hex %lx\n", 42L);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hex {:x}", 42L);
-
- printf("HEX %X\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("HEX {:X}", 42);
-
- printf("Oct %lo\n", 42L);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Oct {:o}", 42L);
-}
-
-void printf_alternative_forms() {
- printf("Hex %#lx\n", 42L);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hex {:#x}", 42L);
-
- printf("HEX %#X\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("HEX {:#X}", 42);
-
- printf("Oct %#lo\n", 42L);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Oct {:#o}", 42L);
-
- printf("Double %#f %#F\n", -42.0, -42.0);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Double {:#f} {:#F}", -42.0, -42.0);
-
- printf("Double %#g %#G\n", -42.0, -42.0);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Double {:#g} {:#G}", -42.0, -42.0);
-
- printf("Double %#e %#E\n", -42.0, -42.0);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Double {:#e} {:#E}", -42.0, -42.0);
-
- printf("Double %#a %#A\n", -42.0, -42.0);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Double {:#a} {:#A}", -42.0, -42.0);
-
- // Characters don't have an alternate form
- printf("Char %#c\n", 'A');
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Char {}", 'A');
-
- // Strings don't have an alternate form
- printf("Char %#c\n", 'A');
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Char {}", 'A');
-}
-
-void printf_string() {
- printf("Hello %s after\n", "Goodbye");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {} after", "Goodbye");
-
- // std::print can't print signed char strings.
- const signed char *sstring = reinterpret_cast<const signed char *>("ustring");
- printf("signed char string %s\n", sstring);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("signed char string {}", reinterpret_cast<const char *>(sstring));
-
- // std::print can't print unsigned char strings.
- const unsigned char *ustring = reinterpret_cast<const unsigned char *>("ustring");
- printf("unsigned char string %s\n", ustring);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("unsigned char string {}", reinterpret_cast<const char *>(ustring));
-}
-
-void printf_float() {
- // If the type is not specified then either f or e will be used depending on
- // whichever is shorter. This means that it is necessary to be specific to
- // maintain compatibility with printf.
-
- // TODO: Should we force a cast here, since printf will promote to double
- // automatically, but std::format will not, which could result in
diff erent
- // output?
-
- const float f = 42.0F;
- printf("Hello %f after\n", f);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:f} after", f);
-
- printf("Hello %g after\n", f);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:g} after", f);
-
- printf("Hello %e after\n", f);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:e} after", f);
-}
-
-void printf_double() {
- // If the type is not specified then either f or e will be used depending on
- // whichever is shorter. This means that it is necessary to be specific to
- // maintain compatibility with printf.
-
- const double d = 42.0;
- printf("Hello %f after\n", d);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:f} after", d);
-
- printf("Hello %g after\n", d);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:g} after", d);
-
- printf("Hello %e after\n", d);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:e} after", d);
-}
-
-void printf_long_double() {
- // If the type is not specified then either f or e will be used depending on
- // whichever is shorter. This means that it is necessary to be specific to
- // maintain compatibility with printf.
-
- const long double ld = 42.0L;
- printf("Hello %Lf after\n", ld);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:f} after", ld);
-
- printf("Hello %g after\n", ld);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:g} after", ld);
-
- printf("Hello %e after\n", ld);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:e} after", ld);
-}
-
-void printf_pointer() {
- int i;
- double j;
- printf("Int* %p %s %p\n", &i, "Double*", &j);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Int* {} {} {}", static_cast<const void *>(&i), "Double*", static_cast<const void *>(&j));
-
- printf("%p\n", nullptr);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("{}", nullptr);
-
- const auto np = nullptr;
- printf("%p\n", np);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("{}", np);
-
- // NULL isn't a pointer, so std::print needs some help.
- printf("%p\n", NULL);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("{}", static_cast<const void *>(NULL));
-
- printf("%p\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("{}", static_cast<const void *>(42));
-
- // If we already have a void pointer then no cast is required.
- printf("%p\n", reinterpret_cast<const void *>(44));
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("{}", reinterpret_cast<const void *>(44));
-
- const void *p;
- printf("%p\n", p);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("{}", p);
-
- // But a pointer to a pointer to void does need a cast
- const void **pp;
- printf("%p\n", pp);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("{}", static_cast<const void *>(pp));
-
- printf("%p\n", printf_pointer);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("{}", static_cast<const void *>(printf_pointer));
-}
-
-class AClass
-{
- int member;
-
- void printf_this_pointer()
- {
- printf("%p\n", this);
- // CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("{}", static_cast<const void *>(this));
- }
-
- void printf_pointer_to_member_function()
- {
- printf("%p\n", &AClass::printf_pointer_to_member_function);
- // CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("{}", static_cast<const void *>(&AClass::printf_pointer_to_member_function));
- }
-
- void printf_pointer_to_member_variable()
- {
- printf("%p\n", &AClass::member);
- // CHECK-MESSAGES: [[@LINE-1]]:5: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("{}", static_cast<const void *>(&AClass::member));
- }
-};
-
-void printf_positional_arg() {
- printf("%1$d", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{0}", 42);
-
- printf("before %1$d", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("before {0}", 42);
-
- printf("%1$d after", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{0} after", 42);
-
- printf("before %1$d after", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("before {0} after", 42);
-
- printf("before %2$d between %1$s after", "string", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("before {1} between {0} after", "string", 42);
-}
-
-// printf always defaults to right justification,, no matter what the type is of
-// the argument. std::format uses left justification by default for strings, and
-// right justification for numbers.
-void printf_right_justified() {
- printf("Right-justified integer %4d after\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Right-justified integer {:4} after", 42);
-
- printf("Right-justified double %4f\n", 227.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Right-justified double {:4f}", 227.2);
-
- printf("Right-justified double %4g\n", 227.4);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Right-justified double {:4g}", 227.4);
-
- printf("Right-justified integer with field width argument %*d after\n", 5, 424242);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Right-justified integer with field width argument {:{}} after", 5, 424242);
-
- printf("Right-justified integer with field width argument %2$*1$d after\n", 5, 424242);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Right-justified integer with field width argument {1:{0}} after", 5, 424242);
-
- printf("Right-justified string %20s\n", "Hello");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Right-justified string {:>20}", "Hello");
-
- printf("Right-justified string with field width argument %2$*1$s after\n", 20, "wibble");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Right-justified string with field width argument {1:>{0}} after", 20, "wibble");
-}
-
-// printf always requires - for left justification, no matter what the type is
-// of the argument. std::format uses left justification by default for strings,
-// and right justification for numbers.
-void printf_left_justified() {
- printf("Left-justified integer %-4d\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Left-justified integer {:<4}", 42);
-
- printf("Left-justified integer %--4d\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Left-justified integer {:<4}", 42);
-
- printf("Left-justified double %-4f\n", 227.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Left-justified double {:<4f}", 227.2);
-
- printf("Left-justified double %-4g\n", 227.4);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Left-justified double {:<4g}", 227.4);
-
- printf("Left-justified integer with field width argument %-*d after\n", 5, 424242);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Left-justified integer with field width argument {:<{}} after", 5, 424242);
-
- printf("Left-justified integer with field width argument %2$-*1$d after\n", 5, 424242);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Left-justified integer with field width argument {1:<{0}} after", 5, 424242);
-
- printf("Left-justified string %-20s\n", "Hello");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Left-justified string {:20}", "Hello");
-
- printf("Left-justified string with field width argument %2$-*1$s after\n", 5, "wibble");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Left-justified string with field width argument {1:{0}} after", 5, "wibble");
-}
-
-void printf_precision() {
- printf("Hello %.3f\n", 3.14159);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:.3f}", 3.14159);
-
- printf("Hello %10.3f\n", 3.14159);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:10.3f}", 3.14159);
-
- printf("Hello %.*f after\n", 10, 3.14159265358979323846);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:.{}f} after", 10, 3.14159265358979323846);
-
- printf("Hello %10.*f after\n", 3, 3.14159265358979323846);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:10.{}f} after", 3, 3.14159265358979323846);
-
- printf("Hello %*.*f after\n", 10, 4, 3.14159265358979323846);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:{}.{}f} after", 10, 4, 3.14159265358979323846);
-
- printf("Hello %1$.*2$f after\n", 3.14159265358979323846, 4);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {0:.{1}f} after", 3.14159265358979323846, 4);
-
- // Precision is ignored, but maintained on non-numeric arguments
- printf("Hello %.5s\n", "Goodbye");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:.5}", "Goodbye");
-
- printf("Hello %.5c\n", 'G');
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {:.5}", 'G');
-}
-
-void printf_field_width_and_precision() {
- printf("Hello %1$*2$.*3$f after\n", 3.14159265358979323846, 4, 2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Hello {0:{1}.{2}f} after", 3.14159265358979323846, 4, 2);
-}
-
-void printf_alternative_form() {
- printf("Wibble %#x\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Wibble {:#x}", 42);
-
- printf("Wibble %#20x\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Wibble {:#20x}", 42);
-
- printf("Wibble %#020x\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Wibble {:#020x}", 42);
-
- printf("Wibble %#-20x\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Wibble {:<#20x}", 42);
-}
-
-void printf_leading_plus() {
- printf("Positive integer %+d\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Positive integer {:+}", 42);
-
- printf("Positive double %+f\n", 42.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Positive double {:+f}", 42.2);
-
- printf("Positive double %+g\n", 42.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Positive double {:+g}", 42.2);
-
- // Ignore leading plus on strings to avoid potential runtime exception where
- // printf would have just ignored it.
- printf("Positive string %+s\n", "string");
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Positive string {}", "string");
-}
-
-void printf_leading_space() {
- printf("Spaced integer % d\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Spaced integer {: }", 42);
-
- printf("Spaced integer %- d\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Spaced integer {: }", 42);
-
- printf("Spaced double % f\n", 42.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Spaced double {: f}", 42.2);
-
- printf("Spaced double % g\n", 42.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Spaced double {: g}", 42.2);
-}
-
-void printf_leading_zero() {
- printf("Leading zero integer %03d\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Leading zero integer {:03}", 42);
-
- printf("Leading minus and zero integer %-03d minus ignored\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Leading minus and zero integer {:<03} minus ignored", 42);
-
- printf("Leading zero unsigned integer %03u\n", 42U);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Leading zero unsigned integer {:03}", 42U);
-
- printf("Leading zero double %03f\n", 42.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Leading zero double {:03f}", 42.2);
-
- printf("Leading zero double %03g\n", 42.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Leading zero double {:03g}", 42.2);
-}
-
-void printf_leading_plus_and_space() {
- // printf prefers plus to space. {fmt} will throw if both are present.
- printf("Spaced integer % +d\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Spaced integer {:+}", 42);
-
- printf("Spaced double %+ f\n", 42.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Spaced double {:+f}", 42.2);
-
- printf("Spaced double % +g\n", 42.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Spaced double {:+g}", 42.2);
-}
-
-void printf_leading_zero_and_plus() {
- printf("Leading zero integer %+03d\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Leading zero integer {:+03}", 42);
-
- printf("Leading zero double %0+3f\n", 42.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Leading zero double {:+03f}", 42.2);
-
- printf("Leading zero double %0+3g\n", 42.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Leading zero double {:+03g}", 42.2);
-}
-
-void printf_leading_zero_and_space() {
- printf("Leading zero and space integer %0 3d\n", 42);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Leading zero and space integer {: 03}", 42);
-
- printf("Leading zero and space double %0 3f\n", 42.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Leading zero and space double {: 03f}", 42.2);
-
- printf("Leading zero and space double %0 3g\n", 42.2);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("Leading zero and space double {: 03g}", 42.2);
-}
-
-// add signed plained enum too
-enum PlainEnum { red };
-enum SignedPlainEnum { black = -42 };
-enum BoolEnum : unsigned int { yellow };
-enum CharEnum : char { purple };
-enum SCharEnum : signed char { aquamarine };
-enum UCharEnum : unsigned char { pink };
-enum ShortEnum : short { beige };
-enum UShortEnum : unsigned short { grey };
-enum IntEnum : int { green };
-enum UIntEnum : unsigned int { blue };
-enum LongEnum : long { magenta };
-enum ULongEnum : unsigned long { cyan };
-enum LongLongEnum : long long { taupe };
-enum ULongLongEnum : unsigned long long { brown };
-
-void printf_enum_d() {
- PlainEnum plain_enum;
- printf("%d", plain_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<int>(plain_enum));
-
- SignedPlainEnum splain_enum;
- printf("%d", splain_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<int>(splain_enum));
-
- BoolEnum bool_enum;
- printf("%d", bool_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<int>(bool_enum));
-
- CharEnum char_enum;
- printf("%d", char_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<signed char>(char_enum));
-
- SCharEnum schar_enum;
- printf("%d", schar_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<signed char>(schar_enum));
-
- UCharEnum uchar_enum;
- printf("%d", uchar_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<signed char>(uchar_enum));
-
- ShortEnum short_enum;
- printf("%d", short_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<short>(short_enum));
-
- UShortEnum ushort_enum;
- printf("%d", ushort_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<short>(ushort_enum));
-
- IntEnum int_enum;
- printf("%d", int_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<int>(int_enum));
-
- UIntEnum uint_enum;
- printf("%d", uint_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<int>(uint_enum));
-
- LongEnum long_enum;
- printf("%d", long_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<long>(long_enum));
-
- ULongEnum ulong_enum;
- printf("%d", ulong_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<long>(ulong_enum));
-
- LongLongEnum longlong_enum;
- printf("%d", longlong_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<long long>(longlong_enum));
-
- ULongLongEnum ulonglong_enum;
- printf("%d", ulonglong_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<long long>(ulonglong_enum));
-}
-
-void printf_enum_u() {
- PlainEnum plain_enum;
- printf("%u", plain_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned int>(plain_enum));
-
- SignedPlainEnum splain_enum;
- printf("%u", splain_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned int>(splain_enum));
-
- BoolEnum bool_enum;
- printf("%u", bool_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned int>(bool_enum));
-
- CharEnum char_enum;
- printf("%u", char_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned char>(char_enum));
-
- SCharEnum schar_enum;
- printf("%u", schar_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned char>(schar_enum));
-
- UCharEnum uchar_enum;
- printf("%u", uchar_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned char>(uchar_enum));
-
- ShortEnum short_enum;
- printf("%u", short_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned short>(short_enum));
-
- UShortEnum ushort_enum;
- printf("%u", ushort_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned short>(ushort_enum));
-
- IntEnum int_enum;
- printf("%u", int_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned int>(int_enum));
-
- UIntEnum uint_enum;
- printf("%u", uint_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned int>(uint_enum));
-
- LongEnum long_enum;
- printf("%u", long_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned long>(long_enum));
-
- ULongEnum ulong_enum;
- printf("%u", ulong_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned long>(ulong_enum));
-
- LongLongEnum longlong_enum;
- printf("%u", longlong_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned long long>(longlong_enum));
-
- ULongLongEnum ulonglong_enum;
- printf("%u", ulonglong_enum);
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("{}", static_cast<unsigned long long>(ulonglong_enum));
-}
-
-void printf_string_function(const char *(*callback)()) {
- printf("printf string from callback %s", callback());
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("printf string from callback {}", callback());
-}
-
-template <typename CharType>
-struct X
-{
- const CharType *str() const;
-};
-
-void printf_string_member_function(const X<char> &x, const X<const char> &cx) {
- printf("printf string from member function %s", x.str());
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("printf string from member function {}", x.str());
-
- printf("printf string from member function on const %s", cx.str());
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("printf string from member function on const {}", cx.str());
-}
-
-void printf_string_cstr(const std::string &s1, const std::string &s2) {
- printf("printf string one c_str %s", s1.c_str());
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("printf string one c_str {}", s1);
-
- printf("printf string two c_str %s %s\n", s1.c_str(), s2.data());
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("printf string two c_str {} {}", s1, s2);
-}
-
-void printf_not_char_string_cstr(const std::wstring &ws1) {
- // This test is to check that we only remove
- // std::basic_string<CharType>::c_str()/data() when CharType is char. I've
- // been unable to come up with a genuine situation where someone would have
- // actually successfully called those methods when this isn't the case without
- // -Wformat warning, but it seems sensible to restrict removal regardless.
- printf("printf bogus wstring c_str %s", ws1.c_str());
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("printf bogus wstring c_str {}", ws1.c_str());
-}
-
-void fprintf_string_cstr(const std::string &s1) {
- fprintf(stderr, "fprintf string c_str %s", s1.c_str());
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'fprintf' [modernize-use-std-print]
- // CHECK-FIXES: std::print(stderr, "fprintf string c_str {}", s1);
-}
-
-void printf_string_pointer_cstr(const std::string *s1, const std::string *s2) {
- printf("printf string pointer one c_str %s", s1->c_str());
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("printf string pointer one c_str {}", *s1);
-
- printf("printf string pointer two c_str %s %s\n", s1->c_str(), s2->data());
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("printf string pointer two c_str {} {}", *s1, *s2);
-}
-
-void fprintf_string_pointer_cstr(const std::string *s1) {
- fprintf(stderr, "fprintf string pointer c_str %s", s1->c_str());
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'fprintf' [modernize-use-std-print]
- // CHECK-FIXES: std::print(stderr, "fprintf string pointer c_str {}", *s1);
-}
-
-template <typename T>
-struct iterator {
- T *operator->();
- T &operator*();
-};
-
-void printf_iterator_cstr(iterator<std::string> i1, iterator<std::string> i2)
-{
- printf("printf iterator c_str %s %s\n", i1->c_str(), i2->data());
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::println("printf iterator c_str {} {}", *i1, *i2);
-}
-
-// Something that isn't std::string, so the calls to c_str() and data() must not
-// be removed even though the printf call will be replaced.
-struct S
-{
- const char *c_str() const;
- const char *data() const;
-};
-
-void p(S s1, S *s2)
-{
- printf("Not std::string %s %s", s1.c_str(), s2->c_str());
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("Not std::string {} {}", s1.c_str(), s2->c_str());
-
- printf("Not std::string %s %s", s1.data(), s2->data());
- // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print]
- // CHECK-FIXES: std::print("Not std::string {} {}", s1.data(), s2->data());
-}
More information about the cfe-commits
mailing list