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("modernize-make-shared"); CheckFactories.registerCheck("modernize-make-unique"); CheckFactories.registerCheck("modernize-pass-by-value"); - CheckFactories.registerCheck("modernize-use-std-print"); CheckFactories.registerCheck( "modernize-raw-string-literal"); CheckFactories.registerCheck( 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 = ""; -} - -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("func_decl"); - const auto *Printf = Result.Nodes.getNodeAs("printf"); - if (!Printf) { - Printf = Result.Nodes.getNodeAs("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 getCheckTraversalKind() const override { - return TK_IgnoreUnlessSpelledInSource; - } - -private: - bool StrictMode; - std::vector PrintfLikeFunctions; - std::vector FprintfLikeFunctions; - StringRef ReplacementPrintFunction; - StringRef ReplacementPrintlnFunction; - utils::IncludeInserter IncludeInserter; - std::optional 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(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 -getCorrespondingSignedTypeName(const clang::QualType &QT) { - using namespace clang; - const auto UQT = QT.getUnqualifiedType(); - if (const auto *BT = llvm::dyn_cast(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 . 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 -getCorrespondingUnsignedTypeName(const clang::QualType &QT) { - using namespace clang; - const auto UQT = QT.getUnqualifiedType(); - if (const auto *BT = llvm::dyn_cast(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 . 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 == "ptrdiff_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 -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( - 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("); - } -} - -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()) { - if (const std::optional 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 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 different 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("); - 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("call"); - const auto *Arg = Match.getNodeAs("arg"); - const auto *Member = Match.getNodeAs("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 - -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 - StringCStrCallExprMatcher; - - const StringLiteral *FormatExpr; - std::string StandardFormatString; - - /// Casts to be used to wrap arguments to retain printf compatibility. - std::vector> ArgFixes; - std::vector 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 - ` 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 ` 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 `_, "Yes" `modernize-use-nullptr `_, "Yes" `modernize-use-override `_, "Yes" - `modernize-use-std-print `_, "Yes" `modernize-use-trailing-return-type `_, "Yes" `modernize-use-transparent-functors `_, "Yes" `modernize-use-uncaught-exceptions `_, "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 - ```` 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``. -- any arguments where the format string and the parameter differ 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 ````, ``ptrdiff_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(i), static_cast(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 ````, 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 ::ptrdiff_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 -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 - -namespace std { - using ::FILE; - using ::printf; - using ::fprintf; -} - -#endif // _STDIO_ - 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 -#include - -namespace absl -{ -// Use const char * for the format since the real type is hard to mock up. -template -int PrintF(const char *format, const Args&... args); - -template -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 -#include - -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: '' \ -// RUN: } \ -// RUN: ] \ -// RUN: }" \ -// RUN: -- -isystem %clang_tidy_headers - -#include -// CHECK-FIXES: #include -#include - -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 -#include -#include -// CHECK-FIXES: #include -#include -#include -#include - -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(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(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(u8), static_cast(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(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(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(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(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(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(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(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(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(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(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(uim), static_cast(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(uim)); - - const int ai[] = { 0, 1, 2, 3}; - const ptrdiff_t pd = &ai[3] - &ai[0]; - const std::ptrdiff_t spd = pd; - printf("Integers %td and %td from ptrdiff_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 ptrdiff_t", pd, spd); - - printf("Integers %ti and %ti from ptrdiff_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 ptrdiff_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(z), static_cast(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(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(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(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(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(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(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(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(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(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(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(im), static_cast(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 ptrdiff_t pd = &ai[3] - &ai[0]; - const std::ptrdiff_t spd = pd; - printf("Unsigned integers %tu and %tu from ptrdiff_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 ptrdiff_t", pd, spd); - // CHECK-FIXES-STRICT: std::println("Unsigned integers {} and {} from ptrdiff_t", static_cast(pd), static_cast(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("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(sstring)); - - // std::print can't print unsigned char strings. - const unsigned char *ustring = reinterpret_cast("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(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 different - // 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(&i), "Double*", static_cast(&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(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(42)); - - // If we already have a void pointer then no cast is required. - printf("%p\n", reinterpret_cast(44)); - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print] - // CHECK-FIXES: std::println("{}", reinterpret_cast(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(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(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(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(&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(&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(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(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(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(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(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(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_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(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_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(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_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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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 -struct X -{ - const CharType *str() const; -}; - -void printf_string_member_function(const X &x, const X &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::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 -struct iterator { - T *operator->(); - T &operator*(); -}; - -void printf_iterator_cstr(iterator i1, iterator 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()); -}