diff options
Diffstat (limited to 'clang-tools-extra/clang-tidy')
20 files changed, 169 insertions, 147 deletions
diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp index e6115f6..7adff8a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -61,6 +61,7 @@ #include "ParentVirtualCallCheck.h" #include "PointerArithmeticOnPolymorphicObjectCheck.h" #include "PosixReturnCheck.h" +#include "RawMemoryCallOnNonTrivialTypeCheck.h" #include "RedundantBranchConditionCheck.h" #include "ReservedIdentifierCheck.h" #include "ReturnConstRefFromParameterCheck.h" @@ -216,6 +217,8 @@ public: CheckFactories.registerCheck<ParentVirtualCallCheck>( "bugprone-parent-virtual-call"); CheckFactories.registerCheck<PosixReturnCheck>("bugprone-posix-return"); + CheckFactories.registerCheck<RawMemoryCallOnNonTrivialTypeCheck>( + "bugprone-raw-memory-call-on-non-trivial-type"); CheckFactories.registerCheck<ReservedIdentifierCheck>( "bugprone-reserved-identifier"); CheckFactories.registerCheck<SharedPtrArrayMismatchCheck>( diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt index c8943e5..c0fdb4d 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -62,6 +62,7 @@ add_clang_library(clangTidyBugproneModule STATIC ParentVirtualCallCheck.cpp PointerArithmeticOnPolymorphicObjectCheck.cpp PosixReturnCheck.cpp + RawMemoryCallOnNonTrivialTypeCheck.cpp RedundantBranchConditionCheck.cpp ReservedIdentifierCheck.cpp ReturnConstRefFromParameterCheck.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp index 76df992..18eb40f 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp @@ -20,6 +20,8 @@ namespace clang::tidy::bugprone { namespace { +// Preserve same name as AST_MATCHER(isCompleteAndHasNoZeroValue) +// NOLINTNEXTLINE(llvm-prefer-static-over-anonymous-namespace) bool isCompleteAndHasNoZeroValue(const EnumDecl *D) { const EnumDecl *Definition = D->getDefinition(); return Definition && Definition->isComplete() && diff --git a/clang-tools-extra/clang-tidy/cert/NonTrivialTypesLibcMemoryCallsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/RawMemoryCallOnNonTrivialTypeCheck.cpp index e266cf9..f7f7ccb 100644 --- a/clang-tools-extra/clang-tidy/cert/NonTrivialTypesLibcMemoryCallsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/RawMemoryCallOnNonTrivialTypeCheck.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "NonTrivialTypesLibcMemoryCallsCheck.h" +#include "RawMemoryCallOnNonTrivialTypeCheck.h" #include "../utils/OptionsUtils.h" #include "clang/AST/Decl.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -17,7 +17,7 @@ using namespace clang::ast_matchers; -namespace clang::tidy::cert { +namespace clang::tidy::bugprone { namespace { AST_MATCHER(CXXRecordDecl, isTriviallyDefaultConstructible) { @@ -48,22 +48,21 @@ static constexpr llvm::StringRef ComparisonOperators[] = { "operator==", "operator!=", "operator<", "operator>", "operator<=", "operator>="}; -NonTrivialTypesLibcMemoryCallsCheck::NonTrivialTypesLibcMemoryCallsCheck( +RawMemoryCallOnNonTrivialTypeCheck::RawMemoryCallOnNonTrivialTypeCheck( StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), MemSetNames(Options.get("MemSetNames", "")), MemCpyNames(Options.get("MemCpyNames", "")), MemCmpNames(Options.get("MemCmpNames", "")) {} -void NonTrivialTypesLibcMemoryCallsCheck::storeOptions( +void RawMemoryCallOnNonTrivialTypeCheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "MemSetNames", MemSetNames); Options.store(Opts, "MemCpyNames", MemCpyNames); Options.store(Opts, "MemCmpNames", MemCmpNames); } -void NonTrivialTypesLibcMemoryCallsCheck::registerMatchers( - MatchFinder *Finder) { +void RawMemoryCallOnNonTrivialTypeCheck::registerMatchers(MatchFinder *Finder) { using namespace ast_matchers::internal; auto IsStructPointer = [](Matcher<CXXRecordDecl> Constraint = anything(), bool Bind = false) { @@ -103,7 +102,7 @@ void NonTrivialTypesLibcMemoryCallsCheck::registerMatchers( this); } -void NonTrivialTypesLibcMemoryCallsCheck::check( +void RawMemoryCallOnNonTrivialTypeCheck::check( const MatchFinder::MatchResult &Result) { if (const auto *Caller = Result.Nodes.getNodeAs<CallExpr>("lazyConstruct")) { diag(Caller->getBeginLoc(), "calling %0 on a non-trivially default " @@ -122,4 +121,4 @@ void NonTrivialTypesLibcMemoryCallsCheck::check( } } -} // namespace clang::tidy::cert +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/cert/NonTrivialTypesLibcMemoryCallsCheck.h b/clang-tools-extra/clang-tidy/bugprone/RawMemoryCallOnNonTrivialTypeCheck.h index 4589ce4..002aac6 100644 --- a/clang-tools-extra/clang-tidy/cert/NonTrivialTypesLibcMemoryCallsCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/RawMemoryCallOnNonTrivialTypeCheck.h @@ -6,22 +6,21 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_NONTRIVIALTYPESLIBCMEMORYCALLSCHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_NONTRIVIALTYPESLIBCMEMORYCALLSCHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RAWMEMORYCALLONNONTRIVIALTYPECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RAWMEMORYCALLONNONTRIVIALTYPECHECK_H #include "../ClangTidyCheck.h" -namespace clang::tidy::cert { +namespace clang::tidy::bugprone { -/// Flags use of the `C` standard library functions 'memset', 'memcpy' and +/// Flags use of the C standard library functions 'memset', 'memcpy' and /// 'memcmp' and similar derivatives on non-trivial types. /// /// For the user-facing documentation see: -/// https://clang.llvm.org/extra/clang-tidy/checks/cert/oop57-cpp.html -class NonTrivialTypesLibcMemoryCallsCheck : public ClangTidyCheck { +/// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/raw-memory-call-on-non-trivial-type.html +class RawMemoryCallOnNonTrivialTypeCheck : public ClangTidyCheck { public: - NonTrivialTypesLibcMemoryCallsCheck(StringRef Name, - ClangTidyContext *Context); + RawMemoryCallOnNonTrivialTypeCheck(StringRef Name, ClangTidyContext *Context); bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { return LangOpts.CPlusPlus && !LangOpts.ObjC; } @@ -35,6 +34,6 @@ private: const StringRef MemCmpNames; }; -} // namespace clang::tidy::cert +} // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_NONTRIVIALTYPESLIBCMEMORYCALLSCHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RAWMEMORYCALLONNONTRIVIALTYPECHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/SmartPtrArrayMismatchCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SmartPtrArrayMismatchCheck.cpp index ee797ec..f76e4a7 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SmartPtrArrayMismatchCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SmartPtrArrayMismatchCheck.cpp @@ -15,13 +15,11 @@ using namespace clang::ast_matchers; namespace clang::tidy::bugprone { -namespace { +static constexpr char ConstructExprN[] = "found_construct_expr"; +static constexpr char NewExprN[] = "found_new_expr"; +static constexpr char ConstructorN[] = "found_constructor"; -constexpr char ConstructExprN[] = "found_construct_expr"; -constexpr char NewExprN[] = "found_new_expr"; -constexpr char ConstructorN[] = "found_constructor"; - -bool isInSingleDeclStmt(const DeclaratorDecl *D) { +static bool isInSingleDeclStmt(const DeclaratorDecl *D) { const DynTypedNodeList Parents = D->getASTContext().getParentMapContext().getParents(*D); for (const DynTypedNode &PNode : Parents) @@ -30,8 +28,8 @@ bool isInSingleDeclStmt(const DeclaratorDecl *D) { return false; } -const DeclaratorDecl *getConstructedVarOrField(const Expr *FoundConstructExpr, - ASTContext &Ctx) { +static const DeclaratorDecl * +getConstructedVarOrField(const Expr *FoundConstructExpr, ASTContext &Ctx) { const DynTypedNodeList ConstructParents = Ctx.getParentMapContext().getParents(*FoundConstructExpr); if (ConstructParents.size() != 1) @@ -43,8 +41,6 @@ const DeclaratorDecl *getConstructedVarOrField(const Expr *FoundConstructExpr, return nullptr; } -} // namespace - const char SmartPtrArrayMismatchCheck::PointerTypeN[] = "pointer_type"; SmartPtrArrayMismatchCheck::SmartPtrArrayMismatchCheck( diff --git a/clang-tools-extra/clang-tidy/bugprone/UncheckedStringToNumberConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UncheckedStringToNumberConversionCheck.cpp index d1e7b89..d0bf72b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UncheckedStringToNumberConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UncheckedStringToNumberConversionCheck.cpp @@ -51,7 +51,7 @@ enum class ConversionKind { static ConversionKind classifyConversionFunc(const FunctionDecl *FD) { return llvm::StringSwitch<ConversionKind>(FD->getName()) - .Cases("atoi", "atol", ConversionKind::ToInt) + .Cases({"atoi", "atol"}, ConversionKind::ToInt) .Case("atoll", ConversionKind::ToLongInt) .Case("atof", ConversionKind::ToDouble) .Default(ConversionKind::None); diff --git a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp index c1ca2ce..fa1eb4a 100644 --- a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp @@ -12,6 +12,7 @@ #include "../bugprone/BadSignalToKillThreadCheck.h" #include "../bugprone/CommandProcessorCheck.h" #include "../bugprone/PointerArithmeticOnPolymorphicObjectCheck.h" +#include "../bugprone/RawMemoryCallOnNonTrivialTypeCheck.h" #include "../bugprone/ReservedIdentifierCheck.h" #include "../bugprone/SignalHandlerCheck.h" #include "../bugprone/SignedCharMisuseCheck.h" @@ -39,7 +40,6 @@ #include "FloatLoopCounter.h" #include "LimitedRandomnessCheck.h" #include "MutatingCopyCheck.h" -#include "NonTrivialTypesLibcMemoryCallsCheck.h" #include "ProperlySeededRandomGeneratorCheck.h" #include "ThrownExceptionTypeCheck.h" @@ -278,7 +278,7 @@ public: "cert-oop11-cpp"); CheckFactories.registerCheck<bugprone::UnhandledSelfAssignmentCheck>( "cert-oop54-cpp"); - CheckFactories.registerCheck<NonTrivialTypesLibcMemoryCallsCheck>( + CheckFactories.registerCheck<bugprone::RawMemoryCallOnNonTrivialTypeCheck>( "cert-oop57-cpp"); CheckFactories.registerCheck<MutatingCopyCheck>("cert-oop58-cpp"); diff --git a/clang-tools-extra/clang-tidy/cert/CMakeLists.txt b/clang-tools-extra/clang-tidy/cert/CMakeLists.txt index 453d1d3..ce57faa 100644 --- a/clang-tools-extra/clang-tidy/cert/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cert/CMakeLists.txt @@ -10,7 +10,6 @@ add_clang_library(clangTidyCERTModule STATIC FloatLoopCounter.cpp LimitedRandomnessCheck.cpp MutatingCopyCheck.cpp - NonTrivialTypesLibcMemoryCallsCheck.cpp ProperlySeededRandomGeneratorCheck.cpp ThrownExceptionTypeCheck.cpp diff --git a/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.cpp b/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.cpp index 3d75f4d..ce0e4e6 100644 --- a/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/FunctionNamingCheck.cpp @@ -14,9 +14,7 @@ using namespace clang::ast_matchers; namespace clang::tidy::google::objc { -namespace { - -std::string validFunctionNameRegex(bool RequirePrefix) { +static std::string validFunctionNameRegex(bool RequirePrefix) { // Allow the following name patterns for all functions: // • ABFoo (prefix + UpperCamelCase) // • ABURL (prefix + capitalized acronym/initialism) @@ -43,7 +41,7 @@ std::string validFunctionNameRegex(bool RequirePrefix) { /// For now we will only fix functions of static storage class with names like /// 'functionName' or 'function_name' and convert them to 'FunctionName'. For /// other cases the user must determine an appropriate name on their own. -FixItHint generateFixItHint(const FunctionDecl *Decl) { +static FixItHint generateFixItHint(const FunctionDecl *Decl) { // A fixit can be generated for functions of static storage class but // otherwise the check cannot determine the appropriate function name prefix // to use. @@ -82,8 +80,6 @@ FixItHint generateFixItHint(const FunctionDecl *Decl) { return {}; } -} // namespace - void FunctionNamingCheck::registerMatchers(MatchFinder *Finder) { // Enforce Objective-C function naming conventions on all functions except: // • Functions defined in system headers. diff --git a/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp index bd51cc5..0014153 100644 --- a/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp @@ -18,18 +18,15 @@ #include "llvm/Support/FormatVariadic.h" namespace clang::tidy::llvm_check { -namespace { using namespace ::clang::ast_matchers; using namespace ::clang::transformer; -EditGenerator rewrite(RangeSelector Call, RangeSelector Builder, - RangeSelector CallArgs) { +static EditGenerator rewrite(RangeSelector Call, RangeSelector Builder) { // This is using an EditGenerator rather than ASTEdit as we want to warn even // if in macro. - return [Call = std::move(Call), Builder = std::move(Builder), - CallArgs = - std::move(CallArgs)](const MatchFinder::MatchResult &Result) + return [Call = std::move(Call), + Builder = std::move(Builder)](const MatchFinder::MatchResult &Result) -> Expected<SmallVector<transformer::Edit, 1>> { Expected<CharSourceRange> CallRange = Call(Result); if (!CallRange) @@ -54,7 +51,7 @@ EditGenerator rewrite(RangeSelector Call, RangeSelector Builder, auto NextToken = [&](std::optional<Token> CurrentToken) { if (!CurrentToken) return CurrentToken; - if (CurrentToken->getEndLoc() >= CallRange->getEnd()) + if (CurrentToken->is(clang::tok::eof)) return std::optional<Token>(); return clang::Lexer::findNextToken(CurrentToken->getLocation(), SM, LangOpts); @@ -68,9 +65,10 @@ EditGenerator rewrite(RangeSelector Call, RangeSelector Builder, return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument, "missing '<' token"); } + std::optional<Token> EndToken = NextToken(LessToken); - for (std::optional<Token> GreaterToken = NextToken(EndToken); - GreaterToken && GreaterToken->getKind() != clang::tok::greater; + std::optional<Token> GreaterToken = NextToken(EndToken); + for (; GreaterToken && GreaterToken->getKind() != clang::tok::greater; GreaterToken = NextToken(GreaterToken)) { EndToken = GreaterToken; } @@ -79,12 +77,21 @@ EditGenerator rewrite(RangeSelector Call, RangeSelector Builder, "missing '>' token"); } + std::optional<Token> ArgStart = NextToken(GreaterToken); + if (!ArgStart || ArgStart->getKind() != clang::tok::l_paren) { + return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument, + "missing '(' token"); + } + std::optional<Token> Arg = NextToken(ArgStart); + if (!Arg) { + return llvm::make_error<llvm::StringError>(llvm::errc::invalid_argument, + "unexpected end of file"); + } + const bool HasArgs = Arg->getKind() != clang::tok::r_paren; + Expected<CharSourceRange> BuilderRange = Builder(Result); if (!BuilderRange) return BuilderRange.takeError(); - Expected<CharSourceRange> CallArgsRange = CallArgs(Result); - if (!CallArgsRange) - return CallArgsRange.takeError(); // Helper for concatting below. auto GetText = [&](const CharSourceRange &Range) { @@ -93,43 +100,42 @@ EditGenerator rewrite(RangeSelector Call, RangeSelector Builder, Edit Replace; Replace.Kind = EditKind::Range; - Replace.Range = *CallRange; - std::string CallArgsStr; - // Only emit args if there are any. - if (auto CallArgsText = GetText(*CallArgsRange).ltrim(); - !CallArgsText.rtrim().empty()) { - CallArgsStr = llvm::formatv(", {}", CallArgsText); + Replace.Range.setBegin(CallRange->getBegin()); + Replace.Range.setEnd(ArgStart->getEndLoc()); + const Expr *BuilderExpr = Result.Nodes.getNodeAs<Expr>("builder"); + std::string BuilderText = GetText(*BuilderRange).str(); + if (BuilderExpr->getType()->isPointerType()) { + BuilderText = BuilderExpr->isImplicitCXXThis() + ? "*this" + : llvm::formatv("*{}", BuilderText).str(); } - Replace.Replacement = - llvm::formatv("{}::create({}{})", - GetText(CharSourceRange::getTokenRange( - LessToken->getEndLoc(), EndToken->getLastLoc())), - GetText(*BuilderRange), CallArgsStr); + const StringRef OpType = GetText(CharSourceRange::getTokenRange( + LessToken->getEndLoc(), EndToken->getLastLoc())); + Replace.Replacement = llvm::formatv("{}::create({}{}", OpType, BuilderText, + HasArgs ? ", " : ""); return SmallVector<Edit, 1>({Replace}); }; } -RewriteRuleWith<std::string> useNewMlirOpBuilderCheckRule() { +static RewriteRuleWith<std::string> useNewMlirOpBuilderCheckRule() { Stencil Message = cat("use 'OpType::create(builder, ...)' instead of " "'builder.create<OpType>(...)'"); // Match a create call on an OpBuilder. + auto BuilderType = cxxRecordDecl(isSameOrDerivedFrom("::mlir::OpBuilder")); ast_matchers::internal::Matcher<Stmt> Base = cxxMemberCallExpr( - on(expr(hasType( - cxxRecordDecl(isSameOrDerivedFrom("::mlir::OpBuilder")))) + on(expr(anyOf(hasType(BuilderType), hasType(pointsTo(BuilderType)))) .bind("builder")), - callee(cxxMethodDecl(hasTemplateArgument(0, templateArgument()))), - callee(cxxMethodDecl(hasName("create")))) + callee(cxxMethodDecl(hasTemplateArgument(0, templateArgument()), + hasName("create")))) .bind("call"); return applyFirst( // Attempt rewrite given an lvalue builder, else just warn. {makeRule(cxxMemberCallExpr(unless(on(cxxTemporaryObjectExpr())), Base), - rewrite(node("call"), node("builder"), callArgs("call")), - Message), + rewrite(node("call"), node("builder")), Message), makeRule(Base, noopEdit(node("call")), Message)}); } -} // namespace UseNewMlirOpBuilderCheck::UseNewMlirOpBuilderCheck(StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/misc/UseInternalLinkageCheck.cpp b/clang-tools-extra/clang-tidy/misc/UseInternalLinkageCheck.cpp index 415852d..1d27064 100644 --- a/clang-tools-extra/clang-tidy/misc/UseInternalLinkageCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/UseInternalLinkageCheck.cpp @@ -43,12 +43,6 @@ struct OptionEnumMapping<misc::UseInternalLinkageCheck::FixModeKind> { namespace clang::tidy::misc { -namespace { - -AST_MATCHER(Decl, isFirstDecl) { return Node.isFirstDecl(); } - -AST_MATCHER(FunctionDecl, hasBody) { return Node.hasBody(); } - static bool isInMainFile(SourceLocation L, SourceManager &SM, const FileExtensionsSet &HeaderFileExtensions) { for (;;) { @@ -65,6 +59,12 @@ static bool isInMainFile(SourceLocation L, SourceManager &SM, } } +namespace { + +AST_MATCHER(Decl, isFirstDecl) { return Node.isFirstDecl(); } + +AST_MATCHER(FunctionDecl, hasBody) { return Node.hasBody(); } + AST_MATCHER_P(Decl, isAllRedeclsInMainFile, FileExtensionsSet, HeaderFileExtensions) { return llvm::all_of(Node.redecls(), [&](const Decl *D) { diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp index 9290019..71d89d3 100644 --- a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp @@ -15,6 +15,14 @@ using namespace clang::ast_matchers; namespace clang::tidy::modernize { +template <typename TargetType, typename NodeType> +static const TargetType *getAs(const NodeType *Node) { + if constexpr (std::is_same_v<NodeType, clang::DynTypedNode>) + return Node->template get<TargetType>(); + else + return llvm::dyn_cast<TargetType>(Node); +} + namespace { AST_MATCHER(clang::TypeLoc, hasValidBeginLoc) { @@ -39,14 +47,6 @@ AST_MATCHER(clang::ParmVarDecl, isArgvOfMain) { return FD ? FD->isMain() : false; } -template <typename TargetType, typename NodeType> -const TargetType *getAs(const NodeType *Node) { - if constexpr (std::is_same_v<NodeType, clang::DynTypedNode>) - return Node->template get<TargetType>(); - else - return llvm::dyn_cast<TargetType>(Node); -} - AST_MATCHER(clang::TypeLoc, isWithinImplicitTemplateInstantiation) { const auto IsImplicitTemplateInstantiation = [](const auto *Node) { const auto IsImplicitInstantiation = [](const auto *Node) { diff --git a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp index 01796a6..084349b 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp @@ -20,14 +20,13 @@ using namespace clang::ast_matchers; using namespace clang::ast_matchers::internal; namespace clang::tidy::modernize { -namespace { -const char IteratorDeclStmtId[] = "iterator_decl"; -const char DeclWithNewId[] = "decl_new"; -const char DeclWithCastId[] = "decl_cast"; -const char DeclWithTemplateCastId[] = "decl_template"; +static const char IteratorDeclStmtId[] = "iterator_decl"; +static const char DeclWithNewId[] = "decl_new"; +static const char DeclWithCastId[] = "decl_cast"; +static const char DeclWithTemplateCastId[] = "decl_template"; -size_t getTypeNameLength(bool RemoveStars, StringRef Text) { +static size_t getTypeNameLength(bool RemoveStars, StringRef Text) { enum CharType { Space, Alpha, Punctuation }; CharType LastChar = Space, BeforeSpace = Punctuation; size_t NumChars = 0; @@ -54,6 +53,7 @@ size_t getTypeNameLength(bool RemoveStars, StringRef Text) { return NumChars; } +namespace { /// Matches variable declarations that have explicit initializers that /// are not initializer lists. /// @@ -65,7 +65,7 @@ size_t getTypeNameLength(bool RemoveStars, StringRef Text) { /// MyType C; /// \endcode /// -/// varDecl(hasWrittenNonListInitializer()) maches \c I and \c A but not \c B +/// varDecl(hasWrittenNonListInitializer()) matches \c I and \c A but not \c B /// or \c C. AST_MATCHER(VarDecl, hasWrittenNonListInitializer) { const Expr *Init = Node.getAnyInitializer(); @@ -108,6 +108,15 @@ AST_MATCHER_P(QualType, isSugarFor, Matcher<QualType>, SugarMatcher) { } } +/// Matches declaration reference or member expressions with explicit template +/// arguments. +AST_POLYMORPHIC_MATCHER(hasExplicitTemplateArgs, + AST_POLYMORPHIC_SUPPORTED_TYPES(DeclRefExpr, + MemberExpr)) { + return Node.hasExplicitTemplateArgs(); +} +} // namespace + /// Matches named declarations that have one of the standard iterator /// names: iterator, reverse_iterator, const_iterator, const_reverse_iterator. /// @@ -118,7 +127,7 @@ AST_MATCHER_P(QualType, isSugarFor, Matcher<QualType>, SugarMatcher) { /// \endcode /// /// namedDecl(hasStdIteratorName()) matches \c I and \c CI. -Matcher<NamedDecl> hasStdIteratorName() { +static Matcher<NamedDecl> hasStdIteratorName() { static const StringRef IteratorNames[] = {"iterator", "reverse_iterator", "const_iterator", "const_reverse_iterator"}; @@ -137,7 +146,7 @@ Matcher<NamedDecl> hasStdIteratorName() { /// /// recordDecl(hasStdContainerName()) matches \c vector and \c forward_list /// but not \c my_vec. -Matcher<NamedDecl> hasStdContainerName() { +static Matcher<NamedDecl> hasStdContainerName() { static StringRef ContainerNames[] = {"array", "deque", "forward_list", "list", "vector", @@ -154,17 +163,9 @@ Matcher<NamedDecl> hasStdContainerName() { return hasAnyName(ContainerNames); } -/// Matches declaration reference or member expressions with explicit template -/// arguments. -AST_POLYMORPHIC_MATCHER(hasExplicitTemplateArgs, - AST_POLYMORPHIC_SUPPORTED_TYPES(DeclRefExpr, - MemberExpr)) { - return Node.hasExplicitTemplateArgs(); -} - /// Returns a DeclarationMatcher that matches standard iterators nested /// inside records with a standard container name. -DeclarationMatcher standardIterator() { +static DeclarationMatcher standardIterator() { return decl( namedDecl(hasStdIteratorName()), hasDeclContext(recordDecl(hasStdContainerName(), isInStdNamespace()))); @@ -172,19 +173,19 @@ DeclarationMatcher standardIterator() { /// Returns a TypeMatcher that matches typedefs for standard iterators /// inside records with a standard container name. -TypeMatcher typedefIterator() { +static TypeMatcher typedefIterator() { return typedefType(hasDeclaration(standardIterator())); } /// Returns a TypeMatcher that matches records named for standard /// iterators nested inside records named for standard containers. -TypeMatcher nestedIterator() { +static TypeMatcher nestedIterator() { return recordType(hasDeclaration(standardIterator())); } /// Returns a TypeMatcher that matches types declared with using /// declarations and which name standard iterators for standard containers. -TypeMatcher iteratorFromUsingDeclaration() { +static TypeMatcher iteratorFromUsingDeclaration() { auto HasIteratorDecl = hasDeclaration(namedDecl(hasStdIteratorName())); // Unwrap the nested name specifier to test for one of the standard // containers. @@ -198,7 +199,7 @@ TypeMatcher iteratorFromUsingDeclaration() { /// This matcher returns declaration statements that contain variable /// declarations with written non-list initializer for standard iterators. -StatementMatcher makeIteratorDeclMatcher() { +static StatementMatcher makeIteratorDeclMatcher() { return declStmt(unless(has( varDecl(anyOf(unless(hasWrittenNonListInitializer()), unless(hasType(isSugarFor(anyOf( @@ -207,7 +208,7 @@ StatementMatcher makeIteratorDeclMatcher() { .bind(IteratorDeclStmtId); } -StatementMatcher makeDeclWithNewMatcher() { +static StatementMatcher makeDeclWithNewMatcher() { return declStmt( unless(has(varDecl(anyOf( unless(hasInitializer(ignoringParenImpCasts(cxxNewExpr()))), @@ -225,13 +226,13 @@ StatementMatcher makeDeclWithNewMatcher() { .bind(DeclWithNewId); } -StatementMatcher makeDeclWithCastMatcher() { +static StatementMatcher makeDeclWithCastMatcher() { return declStmt( unless(has(varDecl(unless(hasInitializer(explicitCastExpr())))))) .bind(DeclWithCastId); } -StatementMatcher makeDeclWithTemplateCastMatcher() { +static StatementMatcher makeDeclWithTemplateCastMatcher() { auto ST = substTemplateTypeParmType(hasReplacementType(equalsBoundNode("arg"))); @@ -252,7 +253,7 @@ StatementMatcher makeDeclWithTemplateCastMatcher() { .bind(DeclWithTemplateCastId); } -StatementMatcher makeCombinedMatcher() { +static StatementMatcher makeCombinedMatcher() { return declStmt( // At least one varDecl should be a child of the declStmt to ensure // it's a declaration list and avoid matching other declarations, @@ -265,8 +266,6 @@ StatementMatcher makeCombinedMatcher() { makeDeclWithCastMatcher(), makeDeclWithTemplateCastMatcher())); } -} // namespace - UseAutoCheck::UseAutoCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), MinTypeNameLength(Options.get("MinTypeNameLength", 5)), diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp index cc7c2d1..c1094b1 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp @@ -40,6 +40,12 @@ static constexpr char StrictCppStandardComplianceName[] = "StrictCppStandardCompliance"; static constexpr bool StrictCppStandardComplianceDefault = true; +static unsigned getNumberOfDesignated(const InitListExpr *SyntacticInitList) { + return llvm::count_if(*SyntacticInitList, [](auto *InitExpr) { + return isa<DesignatedInitExpr>(InitExpr); + }); +} + namespace { struct Designators { @@ -74,12 +80,6 @@ private: } }; -unsigned getNumberOfDesignated(const InitListExpr *SyntacticInitList) { - return llvm::count_if(*SyntacticInitList, [](auto *InitExpr) { - return isa<DesignatedInitExpr>(InitExpr); - }); -} - AST_MATCHER(CXXRecordDecl, isAggregate) { return Node.hasDefinition() && Node.isAggregate(); } diff --git a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp index ade0085..e585dd1 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp @@ -81,41 +81,44 @@ AST_MATCHER(CXXMemberCallExpr, hasSameNumArgsAsDeclNumParams) { AST_MATCHER(DeclRefExpr, hasExplicitTemplateArgs) { return Node.hasExplicitTemplateArgs(); } +} // namespace // Helper Matcher which applies the given QualType Matcher either directly or by // resolving a pointer type to its pointee. Used to match v.push_back() as well // as p->push_back(). -auto hasTypeOrPointeeType( +static auto hasTypeOrPointeeType( const ast_matchers::internal::Matcher<QualType> &TypeMatcher) { return anyOf(hasType(TypeMatcher), hasType(pointerType(pointee(TypeMatcher)))); } // Matches if the node has canonical type matching any of the given names. -auto hasWantedType(llvm::ArrayRef<StringRef> TypeNames) { +static auto hasWantedType(llvm::ArrayRef<StringRef> TypeNames) { return hasCanonicalType(hasDeclaration(cxxRecordDecl(hasAnyName(TypeNames)))); } // Matches member call expressions of the named method on the listed container // types. -auto cxxMemberCallExprOnContainer(StringRef MethodName, - llvm::ArrayRef<StringRef> ContainerNames) { +static auto +cxxMemberCallExprOnContainer(StringRef MethodName, + llvm::ArrayRef<StringRef> ContainerNames) { return cxxMemberCallExpr( hasDeclaration(functionDecl(hasName(MethodName))), on(hasTypeOrPointeeType(hasWantedType(ContainerNames)))); } -const auto DefaultContainersWithPushBack = +static const auto DefaultContainersWithPushBack = "::std::vector; ::std::list; ::std::deque"; -const auto DefaultContainersWithPush = +static const auto DefaultContainersWithPush = "::std::stack; ::std::queue; ::std::priority_queue"; -const auto DefaultContainersWithPushFront = +static const auto DefaultContainersWithPushFront = "::std::forward_list; ::std::list; ::std::deque"; -const auto DefaultSmartPointers = +static const auto DefaultSmartPointers = "::std::shared_ptr; ::std::unique_ptr; ::std::auto_ptr; ::std::weak_ptr"; -const auto DefaultTupleTypes = "::std::pair; ::std::tuple"; -const auto DefaultTupleMakeFunctions = "::std::make_pair; ::std::make_tuple"; -const auto DefaultEmplacyFunctions = +static const auto DefaultTupleTypes = "::std::pair; ::std::tuple"; +static const auto DefaultTupleMakeFunctions = + "::std::make_pair; ::std::make_tuple"; +static const auto DefaultEmplacyFunctions = "vector::emplace_back; vector::emplace;" "deque::emplace; deque::emplace_front; deque::emplace_back;" "forward_list::emplace_after; forward_list::emplace_front;" @@ -129,7 +132,6 @@ const auto DefaultEmplacyFunctions = "unordered_multiset::emplace; unordered_multiset::emplace_hint;" "unordered_multimap::emplace; unordered_multimap::emplace_hint;" "stack::emplace; queue::emplace; priority_queue::emplace"; -} // namespace UseEmplaceCheck::UseEmplaceCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IgnoreImplicitConstructors(Options.get( diff --git a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp index 6f6da57..4cf8574 100644 --- a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp @@ -29,6 +29,8 @@ AST_MATCHER(Stmt, isMacroExpansion) { AST_MATCHER(Stmt, isC23) { return Finder->getASTContext().getLangOpts().C23; } +// Preserve same name as AST_MATCHER(isNULLMacroExpansion) +// NOLINTNEXTLINE(llvm-prefer-static-over-anonymous-namespace) bool isNULLMacroExpansion(const Stmt *Statement, ASTContext &Context) { SourceManager &SM = Context.getSourceManager(); const LangOptions &LO = Context.getLangOpts(); diff --git a/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp index 0ab59ff..874b961 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.cpp @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// #include "RedundantParenthesesCheck.h" +#include "../utils/Matchers.h" +#include "../utils/OptionsUtils.h" #include "clang/AST/Expr.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" @@ -32,15 +34,30 @@ AST_MATCHER(ParenExpr, isInMacro) { } // namespace +RedundantParenthesesCheck::RedundantParenthesesCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + AllowedDecls(utils::options::parseStringList( + Options.get("AllowedDecls", "std::max;std::min"))) {} + +void RedundantParenthesesCheck::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "AllowedDecls", + utils::options::serializeStringList(AllowedDecls)); +} + void RedundantParenthesesCheck::registerMatchers(MatchFinder *Finder) { const auto ConstantExpr = expr(anyOf(integerLiteral(), floatLiteral(), characterLiteral(), cxxBoolLiteral(), stringLiteral(), cxxNullPtrLiteralExpr())); Finder->addMatcher( - parenExpr(subExpr(anyOf(parenExpr(), ConstantExpr, declRefExpr())), - unless(anyOf(isInMacro(), - // sizeof(...) is common used. - hasParent(unaryExprOrTypeTraitExpr())))) + parenExpr( + subExpr(anyOf(parenExpr(), ConstantExpr, + declRefExpr(to(namedDecl(unless( + matchers::matchesAnyListedName(AllowedDecls))))))), + unless(anyOf(isInMacro(), + // sizeof(...) is common used. + hasParent(unaryExprOrTypeTraitExpr())))) .bind("dup"), this); } diff --git a/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.h index 9a0409b..2638a09 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.h +++ b/clang-tools-extra/clang-tidy/readability/RedundantParenthesesCheck.h @@ -20,13 +20,16 @@ namespace clang::tidy::readability { /// https://clang.llvm.org/extra/clang-tidy/checks/readability/redundant-parentheses.html class RedundantParenthesesCheck : public ClangTidyCheck { public: - RedundantParenthesesCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + RedundantParenthesesCheck(StringRef Name, ClangTidyContext *Context); + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { return LangOpts.CPlusPlus | LangOpts.C99; } + +private: + const std::vector<StringRef> AllowedDecls; }; } // namespace clang::tidy::readability diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp index fd4320e..706dd67 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp @@ -44,10 +44,9 @@ ExceptionAnalyzer::ExceptionInfo &ExceptionAnalyzer::ExceptionInfo::merge( } // FIXME: This could be ported to clang later. -namespace { -bool isUnambiguousPublicBaseClass(const Type *DerivedType, - const Type *BaseType) { +static bool isUnambiguousPublicBaseClass(const Type *DerivedType, + const Type *BaseType) { const auto *DerivedClass = DerivedType->getCanonicalTypeUnqualified()->getAsCXXRecordDecl(); const auto *BaseClass = @@ -78,11 +77,11 @@ bool isUnambiguousPublicBaseClass(const Type *DerivedType, IsPublicBaseClass; } -inline bool isPointerOrPointerToMember(const Type *T) { +static bool isPointerOrPointerToMember(const Type *T) { return T->isPointerType() || T->isMemberPointerType(); } -std::optional<QualType> getPointeeOrArrayElementQualType(QualType T) { +static std::optional<QualType> getPointeeOrArrayElementQualType(QualType T) { if (T->isAnyPointerType() || T->isMemberPointerType()) return T->getPointeeType(); @@ -92,7 +91,7 @@ std::optional<QualType> getPointeeOrArrayElementQualType(QualType T) { return std::nullopt; } -bool isBaseOf(const Type *DerivedType, const Type *BaseType) { +static bool isBaseOf(const Type *DerivedType, const Type *BaseType) { const auto *DerivedClass = DerivedType->getAsCXXRecordDecl(); const auto *BaseClass = BaseType->getAsCXXRecordDecl(); if (!DerivedClass || !BaseClass) @@ -103,12 +102,12 @@ bool isBaseOf(const Type *DerivedType, const Type *BaseType) { } // Check if T1 is more or Equally qualified than T2. -bool moreOrEquallyQualified(QualType T1, QualType T2) { +static bool moreOrEquallyQualified(QualType T1, QualType T2) { return T1.getQualifiers().isStrictSupersetOf(T2.getQualifiers()) || T1.getQualifiers() == T2.getQualifiers(); } -bool isStandardPointerConvertible(QualType From, QualType To) { +static bool isStandardPointerConvertible(QualType From, QualType To) { assert((From->isPointerType() || From->isMemberPointerType()) && (To->isPointerType() || To->isMemberPointerType()) && "Pointer conversion should be performed on pointer types only."); @@ -150,7 +149,7 @@ bool isStandardPointerConvertible(QualType From, QualType To) { return false; } -bool isFunctionPointerConvertible(QualType From, QualType To) { +static bool isFunctionPointerConvertible(QualType From, QualType To) { if (!From->isFunctionPointerType() && !From->isFunctionType() && !From->isMemberFunctionPointerType()) return false; @@ -192,8 +191,8 @@ bool isFunctionPointerConvertible(QualType From, QualType To) { // from the C rules. // // The function should only be called in C++ mode. -bool isQualificationConvertiblePointer(QualType From, QualType To, - LangOptions LangOpts) { +static bool isQualificationConvertiblePointer(QualType From, QualType To, + LangOptions LangOpts) { // [N4659 7.5 (1)] // A cv-decomposition of a type T is a sequence of cv_i and P_i such that T is @@ -320,7 +319,6 @@ bool isQualificationConvertiblePointer(QualType From, QualType To, return From.getTypePtr() == To.getTypePtr(); } -} // namespace static bool canThrow(const FunctionDecl *Func) { // consteval specifies that every call to the function must produce a |
