diff --git a/clang-tools-extra/clang-tidy/abseil/DurationDivisionCheck.cpp b/clang-tools-extra/clang-tidy/abseil/DurationDivisionCheck.cpp --- a/clang-tools-extra/clang-tidy/abseil/DurationDivisionCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/DurationDivisionCheck.cpp @@ -20,16 +20,17 @@ const auto DurationExpr = expr(hasType(cxxRecordDecl(hasName("::absl::Duration")))); finder->addMatcher( - implicitCastExpr( - hasSourceExpression(ignoringParenCasts( - cxxOperatorCallExpr(hasOverloadedOperatorName("/"), - hasArgument(0, DurationExpr), - hasArgument(1, DurationExpr)) - .bind("OpCall"))), - hasImplicitDestinationType(qualType(unless(isInteger()))), - unless(hasParent(cxxStaticCastExpr())), - unless(hasParent(cStyleCastExpr())), - unless(isInTemplateInstantiation())), + traverse(ast_type_traits::TK_AsIs, + implicitCastExpr( + hasSourceExpression(ignoringParenCasts( + cxxOperatorCallExpr(hasOverloadedOperatorName("/"), + hasArgument(0, DurationExpr), + hasArgument(1, DurationExpr)) + .bind("OpCall"))), + hasImplicitDestinationType(qualType(unless(isInteger()))), + unless(hasParent(cxxStaticCastExpr())), + unless(hasParent(cStyleCastExpr())), + unless(isInTemplateInstantiation()))), this); } diff --git a/clang-tools-extra/clang-tidy/abseil/FasterStrsplitDelimiterCheck.cpp b/clang-tools-extra/clang-tidy/abseil/FasterStrsplitDelimiterCheck.cpp --- a/clang-tools-extra/clang-tidy/abseil/FasterStrsplitDelimiterCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/FasterStrsplitDelimiterCheck.cpp @@ -78,20 +78,23 @@ // Find uses of absl::StrSplit(..., "x") and absl::StrSplit(..., // absl::ByAnyChar("x")) to transform them into absl::StrSplit(..., 'x'). - Finder->addMatcher(callExpr(callee(functionDecl(hasName("::absl::StrSplit"))), - hasArgument(1, anyOf(ByAnyCharArg, SingleChar)), - unless(isInTemplateInstantiation())) - .bind("StrSplit"), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + callExpr(callee(functionDecl(hasName("::absl::StrSplit"))), + hasArgument(1, anyOf(ByAnyCharArg, SingleChar)), + unless(isInTemplateInstantiation())) + .bind("StrSplit")), + this); // Find uses of absl::MaxSplits("x", N) and // absl::MaxSplits(absl::ByAnyChar("x"), N) to transform them into // absl::MaxSplits('x', N). Finder->addMatcher( - callExpr( - callee(functionDecl(hasName("::absl::MaxSplits"))), - hasArgument(0, anyOf(ByAnyCharArg, ignoringParenCasts(SingleChar))), - unless(isInTemplateInstantiation())), + traverse(ast_type_traits::TK_AsIs, + callExpr(callee(functionDecl(hasName("::absl::MaxSplits"))), + hasArgument(0, anyOf(ByAnyCharArg, + ignoringParenCasts(SingleChar))), + unless(isInTemplateInstantiation()))), this); } diff --git a/clang-tools-extra/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp b/clang-tools-extra/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp --- a/clang-tools-extra/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/RedundantStrcatCallsCheck.cpp @@ -64,11 +64,12 @@ static const auto* const Strcat = new auto(hasName("::absl::StrCat")); const auto IsStrcat = cxxBindTemporaryExpr( has(callExpr(callee(functionDecl(*Strcat))).bind("StrCat"))); - if (const auto* SubStrcatCall = selectFirst( + if (const auto *SubStrcatCall = selectFirst( "StrCat", - match(stmt(anyOf( - cxxConstructExpr(IsAlphanum, hasArgument(0, IsStrcat)), - IsStrcat)), + match(stmt(traverse(ast_type_traits::TK_AsIs, + anyOf(cxxConstructExpr(IsAlphanum, + hasArgument(0, IsStrcat)), + IsStrcat))), *Arg->IgnoreParenImpCasts(), *Result.Context))) { RemoveCallLeaveArgs(SubStrcatCall, CheckResult); return SubStrcatCall; diff --git a/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp b/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp --- a/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/StrCatAppendCheck.cpp @@ -58,14 +58,17 @@ // StrCat on the RHS. The first argument of the StrCat call should be the same // as the LHS. Ignore calls from template instantiations. Finder->addMatcher( - cxxOperatorCallExpr( - unless(isInTemplateInstantiation()), hasOverloadedOperatorName("="), - hasArgument(0, declRefExpr(to(decl().bind("LHS")))), - hasArgument(1, IgnoringTemporaries( - callExpr(callee(StrCat), hasArgument(0, AlphaNum), - unless(HasAnotherReferenceToLhs)) - .bind("Call")))) - .bind("Op"), + traverse(ast_type_traits::TK_AsIs, + cxxOperatorCallExpr( + unless(isInTemplateInstantiation()), + hasOverloadedOperatorName("="), + hasArgument(0, declRefExpr(to(decl().bind("LHS")))), + hasArgument( + 1, IgnoringTemporaries( + callExpr(callee(StrCat), hasArgument(0, AlphaNum), + unless(HasAnotherReferenceToLhs)) + .bind("Call")))) + .bind("Op")), this); } diff --git a/clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp b/clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp --- a/clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/UpgradeDurationConversionsCheck.cpp @@ -99,14 +99,17 @@ // `absl::Hours(x)` // where `x` is not of a built-in type. Finder->addMatcher( - implicitCastExpr( - anyOf(hasCastKind(CK_UserDefinedConversion), - has(implicitCastExpr(hasCastKind(CK_UserDefinedConversion)))), - hasParent(callExpr( - callee(functionDecl(DurationFactoryFunction(), - unless(hasParent(functionTemplateDecl())))), - hasArgument(0, expr().bind("arg"))))) - .bind("OuterExpr"), + traverse( + ast_type_traits::TK_AsIs, + implicitCastExpr(anyOf(hasCastKind(CK_UserDefinedConversion), + has(implicitCastExpr( + hasCastKind(CK_UserDefinedConversion)))), + hasParent(callExpr( + callee(functionDecl( + DurationFactoryFunction(), + unless(hasParent(functionTemplateDecl())))), + hasArgument(0, expr().bind("arg"))))) + .bind("OuterExpr")), this); } @@ -116,6 +119,8 @@ "implicit conversion to 'int64_t' is deprecated in this context; use an " "explicit cast instead"; + TraversalKindScope RAII(*Result.Context, ast_type_traits::TK_AsIs); + const auto *ArgExpr = Result.Nodes.getNodeAs("arg"); SourceLocation Loc = ArgExpr->getBeginLoc(); diff --git a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp @@ -84,7 +84,8 @@ void AssertSideEffectCheck::registerMatchers(MatchFinder *Finder) { auto DescendantWithSideEffect = - hasDescendant(expr(hasSideEffect(CheckFunctionCalls))); + traverse(ast_type_traits::TK_AsIs, + hasDescendant(expr(hasSideEffect(CheckFunctionCalls)))); auto ConditionWithSideEffect = hasCondition(DescendantWithSideEffect); Finder->addMatcher( stmt( diff --git a/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BoolPointerImplicitConversionCheck.cpp @@ -18,14 +18,16 @@ // Look for ifs that have an implicit bool* to bool conversion in the // condition. Filter negations. Finder->addMatcher( - ifStmt(hasCondition(findAll(implicitCastExpr( - unless(hasParent(unaryOperator(hasOperatorName("!")))), - hasSourceExpression( - expr(hasType(pointerType(pointee(booleanType()))), - ignoringParenImpCasts(declRefExpr().bind("expr")))), - hasCastKind(CK_PointerToBoolean)))), - unless(isInTemplateInstantiation())) - .bind("if"), + traverse( + ast_type_traits::TK_AsIs, + ifStmt(hasCondition(findAll(implicitCastExpr( + unless(hasParent(unaryOperator(hasOperatorName("!")))), + hasSourceExpression(expr( + hasType(pointerType(pointee(booleanType()))), + ignoringParenImpCasts(declRefExpr().bind("expr")))), + hasCastKind(CK_PointerToBoolean)))), + unless(isInTemplateInstantiation())) + .bind("if")), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp @@ -117,55 +117,63 @@ // Find 'Handle foo = ReturnsAValue();' Finder->addMatcher( - varDecl( - hasType(hasUnqualifiedDesugaredType( - recordType(hasDeclaration(cxxRecordDecl(IsAHandle))))), - unless(parmVarDecl()), - hasInitializer(exprWithCleanups(has(ignoringParenImpCasts(handleFrom( + traverse(ast_type_traits::TK_AsIs, + varDecl(hasType(hasUnqualifiedDesugaredType(recordType( + hasDeclaration(cxxRecordDecl(IsAHandle))))), + unless(parmVarDecl()), + hasInitializer(exprWithCleanups( + has(ignoringParenImpCasts(handleFrom( IsAHandle, ConvertedHandle)))) - .bind("bad_stmt"))), + .bind("bad_stmt")))), this); // Find 'foo = ReturnsAValue(); // foo is Handle' Finder->addMatcher( - cxxOperatorCallExpr(callee(cxxMethodDecl(ofClass(IsAHandle))), - hasOverloadedOperatorName("="), - hasArgument(1, ConvertedHandle)) - .bind("bad_stmt"), + traverse(ast_type_traits::TK_AsIs, + cxxOperatorCallExpr(callee(cxxMethodDecl(ofClass(IsAHandle))), + hasOverloadedOperatorName("="), + hasArgument(1, ConvertedHandle)) + .bind("bad_stmt")), this); // Container insertions that will dangle. - Finder->addMatcher(makeContainerMatcher(IsAHandle).bind("bad_stmt"), this); + Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, + makeContainerMatcher(IsAHandle).bind("bad_stmt")), + this); } void DanglingHandleCheck::registerMatchersForReturn(MatchFinder *Finder) { // Return a local. Finder->addMatcher( - returnStmt( - // The AST contains two constructor calls: - // 1. Value to Handle conversion. - // 2. Handle copy construction. - // We have to match both. - has(ignoringImplicit(handleFrom( - IsAHandle, - handleFrom(IsAHandle, - declRefExpr(to(varDecl( - // Is function scope ... - hasAutomaticStorageDuration(), - // ... and it is a local array or Value. - anyOf(hasType(arrayType()), - hasType(hasUnqualifiedDesugaredType( - recordType(hasDeclaration(recordDecl( - unless(IsAHandle)))))))))))))), - // Temporary fix for false positives inside lambdas. - unless(hasAncestor(lambdaExpr()))) - .bind("bad_stmt"), + traverse( + ast_type_traits::TK_AsIs, + returnStmt( + // The AST contains two constructor calls: + // 1. Value to Handle conversion. + // 2. Handle copy construction. + // We have to match both. + has(ignoringImplicit(handleFrom( + IsAHandle, + handleFrom(IsAHandle, + declRefExpr(to(varDecl( + // Is function scope ... + hasAutomaticStorageDuration(), + // ... and it is a local array or Value. + anyOf(hasType(arrayType()), + hasType(hasUnqualifiedDesugaredType( + recordType(hasDeclaration(recordDecl( + unless(IsAHandle)))))))))))))), + // Temporary fix for false positives inside lambdas. + unless(hasAncestor(lambdaExpr()))) + .bind("bad_stmt")), this); // Return a temporary. Finder->addMatcher( - returnStmt(has(exprWithCleanups(has(ignoringParenImpCasts(handleFrom( - IsAHandle, handleFromTemporaryValue(IsAHandle))))))) - .bind("bad_stmt"), + traverse( + ast_type_traits::TK_AsIs, + returnStmt(has(exprWithCleanups(has(ignoringParenImpCasts(handleFrom( + IsAHandle, handleFromTemporaryValue(IsAHandle))))))) + .bind("bad_stmt")), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp @@ -32,13 +32,15 @@ const auto DeclInStd = type(hasUnqualifiedDesugaredType( tagType(hasDeclaration(decl(isInStdNamespace()))))); Finder->addMatcher( - cxxMemberCallExpr( - on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))), - callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1), - hasArgument(0, has(ignoringImplicit( - anyOf(EndCall, has(ignoringImplicit(EndCall)))))), - unless(isInTemplateInstantiation())) - .bind("erase"), + traverse( + ast_type_traits::TK_AsIs, + cxxMemberCallExpr( + on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))), + callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1), + hasArgument(0, has(ignoringImplicit(anyOf( + EndCall, has(ignoringImplicit(EndCall)))))), + unless(isInTemplateInstantiation())) + .bind("erase")), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/IncorrectRoundingsCheck.cpp @@ -51,10 +51,11 @@ // Find expressions of cast to int of the sum of a floating point expression // and 0.5. MatchFinder->addMatcher( - implicitCastExpr( - hasImplicitDestinationType(isInteger()), - ignoringParenCasts(binaryOperator(hasOperatorName("+"), OneSideHalf))) - .bind("CastExpr"), + traverse(ast_type_traits::TK_AsIs, + implicitCastExpr(hasImplicitDestinationType(isInteger()), + ignoringParenCasts(binaryOperator( + hasOperatorName("+"), OneSideHalf))) + .bind("CastExpr")), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.cpp @@ -30,14 +30,16 @@ callExpr(IntType), explicitCastExpr(IntType), UnaryOperators); Finder->addMatcher( - binaryOperator( - hasOperatorName("/"), hasLHS(expr(IntType)), hasRHS(expr(IntType)), - hasAncestor( - castExpr(hasCastKind(CK_IntegralToFloating)).bind("FloatCast")), - unless(hasAncestor( - expr(Exceptions, - hasAncestor(castExpr(equalsBoundNode("FloatCast"))))))) - .bind("IntDiv"), + traverse(ast_type_traits::TK_AsIs, + binaryOperator( + hasOperatorName("/"), hasLHS(expr(IntType)), + hasRHS(expr(IntType)), + hasAncestor(castExpr(hasCastKind(CK_IntegralToFloating)) + .bind("FloatCast")), + unless(hasAncestor(expr( + Exceptions, + hasAncestor(castExpr(equalsBoundNode("FloatCast"))))))) + .bind("IntDiv")), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.cpp @@ -57,16 +57,22 @@ hasInitializer(ignoringParenImpCasts( declRefExpr(hasDeclaration(Alloc1Func))))); - Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc0Func, Alloc0FuncPtr))), - hasArgument(0, BadArg)) - .bind("Alloc"), - this); - Finder->addMatcher(callExpr(callee(decl(anyOf(Alloc1Func, Alloc1FuncPtr))), - hasArgument(1, BadArg)) - .bind("Alloc"), - this); Finder->addMatcher( - cxxNewExpr(isArray(), hasArraySize(BadArg)).bind("Alloc"), this); + traverse(ast_type_traits::TK_AsIs, + callExpr(callee(decl(anyOf(Alloc0Func, Alloc0FuncPtr))), + hasArgument(0, BadArg)) + .bind("Alloc")), + this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + callExpr(callee(decl(anyOf(Alloc1Func, Alloc1FuncPtr))), + hasArgument(1, BadArg)) + .bind("Alloc")), + this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + cxxNewExpr(isArray(), hasArraySize(BadArg)).bind("Alloc")), + this); } void MisplacedOperatorInStrlenInAllocCheck::check( diff --git a/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp @@ -39,7 +39,9 @@ const auto ImplicitCast = implicitCastExpr(hasImplicitDestinationType(isInteger()), has(ignoringParenImpCasts(Calc))); - const auto Cast = expr(anyOf(ExplicitCast, ImplicitCast)).bind("Cast"); + const auto Cast = + traverse(ast_type_traits::TK_AsIs, + expr(anyOf(ExplicitCast, ImplicitCast)).bind("Cast")); Finder->addMatcher(varDecl(hasInitializer(Cast)), this); Finder->addMatcher(returnStmt(hasReturnValue(Cast)), this); diff --git a/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ParentVirtualCallCheck.cpp @@ -83,14 +83,16 @@ void ParentVirtualCallCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - cxxMemberCallExpr( - callee(memberExpr(hasDescendant(implicitCastExpr( - hasImplicitDestinationType(pointsTo( - type(anything()).bind("castToType"))), - hasSourceExpression(cxxThisExpr(hasType( - type(anything()).bind("thisType"))))))) - .bind("member")), - callee(cxxMethodDecl(isVirtual()))), + traverse( + ast_type_traits::TK_AsIs, + cxxMemberCallExpr( + callee(memberExpr(hasDescendant(implicitCastExpr( + hasImplicitDestinationType(pointsTo( + type(anything()).bind("castToType"))), + hasSourceExpression(cxxThisExpr(hasType( + type(anything()).bind("thisType"))))))) + .bind("member")), + callee(cxxMethodDecl(isVirtual())))), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp @@ -70,8 +70,9 @@ // We catch any type of casts to an integer. We need to have these cast // expressions explicitly to catch only those casts which are direct children // of the checked expressions. (e.g. assignment, declaration). - return expr(anyOf(ImplicitCastExpr, CStyleCastExpr, StaticCastExpr, - FunctionalCastExpr)); + return traverse(ast_type_traits::TK_AsIs, + expr(anyOf(ImplicitCastExpr, CStyleCastExpr, StaticCastExpr, + FunctionalCastExpr))); } void SignedCharMisuseCheck::registerMatchers(MatchFinder *Finder) { diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp @@ -22,6 +22,8 @@ const StringLiteral *Lit) { // String literals surrounded by parentheses are assumed to be on purpose. // i.e.: const char* Array[] = { ("a" "b" "c"), "d", [...] }; + + TraversalKindScope RAII(*Ctx, ast_type_traits::TK_AsIs); auto Parents = Ctx->getParents(*Lit); if (Parents.size() == 1 && Parents[0].get() != nullptr) return true; diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp @@ -135,9 +135,10 @@ // Detect suspicious cast to an inconsistant type (i.e. not integer type). Finder->addMatcher( - implicitCastExpr(unless(hasType(isInteger())), - hasSourceExpression(StringCompareCallExpr)) - .bind("invalid-conversion"), + traverse(ast_type_traits::TK_AsIs, + implicitCastExpr(unless(hasType(isInteger())), + hasSourceExpression(StringCompareCallExpr)) + .bind("invalid-conversion")), this); // Detect suspicious operator with string compare function as operand. diff --git a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp @@ -59,9 +59,10 @@ // We need to catch only those comparisons which contain any integer cast. StatementMatcher LoopVarConversionMatcher = - implicitCastExpr(hasImplicitDestinationType(isInteger()), - has(ignoringParenImpCasts(LoopVarMatcher))) - .bind(LoopVarCastName); + traverse(ast_type_traits::TK_AsIs, + implicitCastExpr(hasImplicitDestinationType(isInteger()), + has(ignoringParenImpCasts(LoopVarMatcher))) + .bind(LoopVarCastName)); // We are interested in only those cases when the loop bound is a variable // value (not const, enum, etc.). diff --git a/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.cpp @@ -55,14 +55,16 @@ // instantiations to reduce the number of duplicated warnings. Finder->addMatcher( - compoundStmt( - hasParent( - cxxConstructorDecl(ofClass(cxxRecordDecl().bind("parent")))), - forEach(ignoringTemporaryExpr( - cxxConstructExpr(hasDeclaration(cxxConstructorDecl(ofClass( + traverse( + ast_type_traits::TK_AsIs, + compoundStmt(hasParent(cxxConstructorDecl( + ofClass(cxxRecordDecl().bind("parent")))), + forEach(ignoringTemporaryExpr( + cxxConstructExpr( + hasDeclaration(cxxConstructorDecl(ofClass( cxxRecordDecl(baseOfBoundNode("parent")))))) - .bind("construct"))), - unless(isInTemplateInstantiation())), + .bind("construct"))), + unless(isInTemplateInstantiation()))), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnhandledSelfAssignmentCheck.cpp @@ -52,8 +52,9 @@ // In the non-template case, we can search for the copy constructor call. const auto HasNonTemplateSelfCopy = cxxMethodDecl( ofClass(cxxRecordDecl(unless(hasAncestor(classTemplateDecl())))), - hasDescendant(cxxConstructExpr(hasDeclaration(cxxConstructorDecl( - isCopyConstructor(), ofClass(equalsBoundNode("class"))))))); + traverse(ast_type_traits::TK_AsIs, + hasDescendant(cxxConstructExpr(hasDeclaration(cxxConstructorDecl( + isCopyConstructor(), ofClass(equalsBoundNode("class")))))))); // In the template case, we need to handle two separate cases: 1) a local // variable is created with the copy, 2) copy is created only as a temporary diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp @@ -31,13 +31,15 @@ cxxBindTemporaryExpr(unless(has(ignoringParenImpCasts(callExpr())))) .bind("temp"); Finder->addMatcher( - exprWithCleanups(unless(isInTemplateInstantiation()), - hasParent(compoundStmt().bind("compound")), - hasType(cxxRecordDecl(hasNonTrivialDestructor())), - anyOf(has(ignoringParenImpCasts(BindTemp)), - has(ignoringParenImpCasts(cxxFunctionalCastExpr( - has(ignoringParenImpCasts(BindTemp))))))) - .bind("expr"), + traverse(ast_type_traits::TK_AsIs, + exprWithCleanups( + unless(isInTemplateInstantiation()), + hasParent(compoundStmt().bind("compound")), + hasType(cxxRecordDecl(hasNonTrivialDestructor())), + anyOf(has(ignoringParenImpCasts(BindTemp)), + has(ignoringParenImpCasts(cxxFunctionalCastExpr( + has(ignoringParenImpCasts(BindTemp))))))) + .bind("expr")), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp @@ -275,7 +275,9 @@ unless(inDecltypeOrTemplateArg())) .bind("declref"); - addDeclRefs(match(findAll(DeclRefMatcher), *S->getStmt(), *Context)); + addDeclRefs( + match(traverse(ast_type_traits::TK_AsIs, findAll(DeclRefMatcher)), + *S->getStmt(), *Context)); addDeclRefs(match(findAll(cxxOperatorCallExpr( hasAnyOverloadedOperatorName("*", "->", "[]"), hasArgument(0, DeclRefMatcher)) @@ -340,7 +342,7 @@ // Passing variable to a function as a non-const lvalue reference // (unless that function is std::move()). callExpr(forEachArgumentWithParam( - DeclRefMatcher, + traverse(ast_type_traits::TK_AsIs, DeclRefMatcher), unless(parmVarDecl(hasType( references(qualType(isConstQualified())))))), unless(callee(functionDecl(hasName("::std::move"))))))) @@ -403,19 +405,22 @@ .bind("call-move"); Finder->addMatcher( - // To find the Stmt that we assume performs the actual move, we look for - // the direct ancestor of the std::move() that isn't one of the node - // types ignored by ignoringParenImpCasts(). - stmt(forEach(expr(ignoringParenImpCasts(CallMoveMatcher))), - // Don't allow an InitListExpr to be the moving call. An InitListExpr - // has both a syntactic and a semantic form, and the parent-child - // relationships are different between the two. This could cause an - // InitListExpr to be analyzed as the moving call in addition to the - // Expr that we actually want, resulting in two diagnostics with - // different code locations for the same move. - unless(initListExpr()), - unless(expr(ignoringParenImpCasts(equalsBoundNode("call-move"))))) - .bind("moving-call"), + traverse( + ast_type_traits::TK_AsIs, + // To find the Stmt that we assume performs the actual move, we look + // for the direct ancestor of the std::move() that isn't one of the + // node types ignored by ignoringParenImpCasts(). + stmt( + forEach(expr(ignoringParenImpCasts(CallMoveMatcher))), + // Don't allow an InitListExpr to be the moving call. An + // InitListExpr has both a syntactic and a semantic form, and the + // parent-child relationships are different between the two. This + // could cause an InitListExpr to be analyzed as the moving call + // in addition to the Expr that we actually want, resulting in two + // diagnostics with different code locations for the same move. + unless(initListExpr()), + unless(expr(ignoringParenImpCasts(equalsBoundNode("call-move"))))) + .bind("moving-call")), this); } diff --git a/clang-tools-extra/clang-tidy/cert/MutatingCopyCheck.cpp b/clang-tools-extra/clang-tidy/cert/MutatingCopyCheck.cpp --- a/clang-tools-extra/clang-tidy/cert/MutatingCopyCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/MutatingCopyCheck.cpp @@ -29,12 +29,13 @@ allOf(unless(hasDescendant(expr(unless(MemberExprOrSourceObject)))), MemberExprOrSourceObject); - const auto IsSourceMutatingAssignment = + const auto IsSourceMutatingAssignment = traverse( + ast_type_traits::TK_AsIs, expr(anyOf(binaryOperator(isAssignmentOperator(), hasLHS(IsPartOfSource)) .bind(MutatingOperatorName), cxxOperatorCallExpr(isAssignmentOperator(), hasArgument(0, IsPartOfSource)) - .bind(MutatingOperatorName))); + .bind(MutatingOperatorName)))); const auto MemberExprOrSelf = anyOf(memberExpr(), cxxThisExpr()); diff --git a/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp b/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp --- a/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp @@ -62,7 +62,9 @@ // std::mt19937 engine(x); // ^ Finder->addMatcher( - cxxConstructExpr(RandomGeneratorEngineTypeMatcher).bind("ctor"), this); + traverse(ast_type_traits::TK_AsIs, + cxxConstructExpr(RandomGeneratorEngineTypeMatcher).bind("ctor")), + this); // srand(); // ^ diff --git a/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.cpp b/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.cpp --- a/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/StaticObjectExceptionCheck.cpp @@ -21,7 +21,10 @@ // Match any static or thread_local variable declaration that has an // initializer that can throw. Finder->addMatcher( - varDecl(anyOf(hasThreadStorageDuration(), hasStaticStorageDuration()), + traverse( + ast_type_traits::TK_AsIs, + varDecl( + anyOf(hasThreadStorageDuration(), hasStaticStorageDuration()), unless(anyOf(isConstexpr(), hasType(cxxRecordDecl(isLambda())), hasAncestor(functionDecl()))), anyOf(hasDescendant(cxxConstructExpr(hasDeclaration( @@ -30,7 +33,7 @@ functionDecl(unless(isNoThrow())).bind("func")))), hasDescendant(callExpr(hasDeclaration( functionDecl(unless(isNoThrow())).bind("func")))))) - .bind("var"), + .bind("var")), this); } diff --git a/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp b/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp --- a/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp @@ -19,10 +19,12 @@ void ThrownExceptionTypeCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - cxxThrowExpr(has(ignoringParenImpCasts( - cxxConstructExpr(hasDeclaration(cxxConstructorDecl( - isCopyConstructor(), unless(isNoThrow())))) - .bind("expr")))), + traverse( + ast_type_traits::TK_AsIs, + cxxThrowExpr(has(ignoringParenImpCasts( + cxxConstructExpr(hasDeclaration(cxxConstructorDecl( + isCopyConstructor(), unless(isNoThrow())))) + .bind("expr"))))), this); } diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/InterfacesGlobalInitCheck.cpp @@ -27,11 +27,12 @@ const auto ReferencesUndefinedGlobalVar = declRefExpr(hasDeclaration( varDecl(GlobalVarDecl, unless(isDefinition())).bind("referencee"))); - Finder->addMatcher( - varDecl(GlobalVarDecl, isDefinition(), - hasInitializer(expr(hasDescendant(ReferencesUndefinedGlobalVar)))) - .bind("var"), - this); + Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, + varDecl(GlobalVarDecl, isDefinition(), + hasInitializer(expr(hasDescendant( + ReferencesUndefinedGlobalVar)))) + .bind("var")), + this); } void InterfacesGlobalInitCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp @@ -39,12 +39,14 @@ // i = 0.5; // void f(int); f(0.5); Finder->addMatcher( - implicitCastExpr(hasImplicitDestinationType(builtinType()), - hasSourceExpression(hasType(builtinType())), - unless(hasSourceExpression(IsCeilFloorCallExpr)), - unless(hasParent(castExpr())), - unless(isInTemplateInstantiation())) - .bind("cast"), + traverse( + ast_type_traits::TK_AsIs, + implicitCastExpr(hasImplicitDestinationType(builtinType()), + hasSourceExpression(hasType(builtinType())), + unless(hasSourceExpression(IsCeilFloorCallExpr)), + unless(hasParent(castExpr())), + unless(isInTemplateInstantiation())) + .bind("cast")), this); // Binary operators: diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp @@ -69,10 +69,10 @@ // Find delete expressions that delete non-owners. Finder->addMatcher( - cxxDeleteExpr( - hasDescendant( - declRefExpr(unless(ConsideredOwner)).bind("deleted_variable"))) - .bind("delete_expr"), + traverse(ast_type_traits::TK_AsIs, + cxxDeleteExpr(hasDescendant(declRefExpr(unless(ConsideredOwner)) + .bind("deleted_variable"))) + .bind("delete_expr")), this); // Ignoring the implicit casts is vital because the legacy owners do not work @@ -83,23 +83,29 @@ // resources. This check assumes that all pointer arguments of a legacy // functions shall be 'gsl::owner<>'. Finder->addMatcher( - callExpr(callee(LegacyOwnerConsumers), - hasAnyArgument(expr(unless(ignoringImpCasts(ConsideredOwner)), - hasType(pointerType())))) - .bind("legacy_consumer"), + traverse(ast_type_traits::TK_AsIs, + callExpr(callee(LegacyOwnerConsumers), + hasAnyArgument( + expr(unless(ignoringImpCasts(ConsideredOwner)), + hasType(pointerType())))) + .bind("legacy_consumer")), this); // Matching assignment to owners, with the rhs not being an owner nor creating // one. - Finder->addMatcher(binaryOperator(isAssignmentOperator(), hasLHS(IsOwnerType), - hasRHS(unless(ConsideredOwner))) - .bind("owner_assignment"), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + binaryOperator(isAssignmentOperator(), hasLHS(IsOwnerType), + hasRHS(unless(ConsideredOwner))) + .bind("owner_assignment")), + this); // Matching initialization of owners with non-owners, nor creating owners. Finder->addMatcher( - namedDecl(varDecl(hasInitializer(unless(ConsideredOwner)), IsOwnerType) - .bind("owner_initialization")), + traverse(ast_type_traits::TK_AsIs, + namedDecl( + varDecl(hasInitializer(unless(ConsideredOwner)), IsOwnerType) + .bind("owner_initialization"))), this); const auto HasConstructorInitializerForOwner = @@ -114,7 +120,9 @@ // Match class member initialization that expects owners, but does not get // them. - Finder->addMatcher(cxxRecordDecl(HasConstructorInitializerForOwner), this); + Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, + cxxRecordDecl(HasConstructorInitializerForOwner)), + this); // Matching on assignment operations where the RHS is a newly created owner, // but the LHS is not an owner. @@ -127,11 +135,14 @@ // Matching on initialization operations where the initial value is a newly // created owner, but the LHS is not an owner. Finder->addMatcher( - namedDecl(varDecl(eachOf(allOf(hasInitializer(CreatesOwner), - unless(IsOwnerType)), - allOf(hasInitializer(ConsideredOwner), - hasType(autoType().bind("deduced_type"))))) - .bind("bad_owner_creation_variable")), + traverse( + ast_type_traits::TK_AsIs, + namedDecl( + varDecl(eachOf(allOf(hasInitializer(CreatesOwner), + unless(IsOwnerType)), + allOf(hasInitializer(ConsideredOwner), + hasType(autoType().bind("deduced_type"))))) + .bind("bad_owner_creation_variable"))), this); // Match on all function calls that expect owners as arguments, but didn't diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp @@ -54,12 +54,13 @@ // 2) inside a range-for over an array // 3) if it converts a string literal to a pointer Finder->addMatcher( - implicitCastExpr( - unless(hasParent(arraySubscriptExpr())), - unless(hasParentIgnoringImpCasts(explicitCastExpr())), - unless(isInsideOfRangeBeginEndStmt()), - unless(hasSourceExpression(ignoringParens(stringLiteral())))) - .bind("cast"), + traverse(ast_type_traits::TK_AsIs, + implicitCastExpr( + unless(hasParent(arraySubscriptExpr())), + unless(hasParentIgnoringImpCasts(explicitCastExpr())), + unless(isInsideOfRangeBeginEndStmt()), + unless(hasSourceExpression(ignoringParens(stringLiteral())))) + .bind("cast")), this); } diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SlicingCheck.cpp @@ -63,7 +63,9 @@ unless(IsWithinDerivedCtor)); Finder->addMatcher( - expr(anyOf(SlicesObjectInAssignment, SlicesObjectInCtor)).bind("Call"), + traverse(ast_type_traits::TK_AsIs, + expr(anyOf(SlicesObjectInAssignment, SlicesObjectInCtor)) + .bind("Call")), this); } diff --git a/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp b/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp --- a/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp +++ b/clang-tools-extra/clang-tidy/fuchsia/StaticallyConstructedObjectsCheck.cpp @@ -28,17 +28,19 @@ // Constructing global, non-trivial objects with static storage is // disallowed, unless the object is statically initialized with a constexpr // constructor or has no explicit constructor. - Finder->addMatcher(varDecl( - // Match global, statically stored objects... - isGlobalStatic(), - // ... that have C++ constructors... - hasDescendant(cxxConstructExpr(unless(allOf( - // ... unless it is constexpr ... - hasDeclaration(cxxConstructorDecl(isConstexpr())), - // ... and is statically initialized. - isConstantInitializer()))))) - .bind("decl"), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + varDecl( + // Match global, statically stored objects... + isGlobalStatic(), + // ... that have C++ constructors... + hasDescendant(cxxConstructExpr(unless(allOf( + // ... unless it is constexpr ... + hasDeclaration(cxxConstructorDecl(isConstexpr())), + // ... and is statically initialized. + isConstantInitializer()))))) + .bind("decl")), + this); } void StaticallyConstructedObjectsCheck::check( diff --git a/clang-tools-extra/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp b/clang-tools-extra/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp --- a/clang-tools-extra/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/PreferIsaOrDynCastInConditionalsCheck.cpp @@ -52,15 +52,17 @@ .bind("rhs"); Finder->addMatcher( - stmt(anyOf(ifStmt(Any), whileStmt(Any), doStmt(Condition), - binaryOperator( - allOf(unless(isExpansionInFileMatching( - "llvm/include/llvm/Support/Casting.h")), - hasOperatorName("&&"), - hasLHS(implicitCastExpr().bind("lhs")), - hasRHS(anyOf(implicitCastExpr(has(CallExpression)), - CallExpression)))) - .bind("and"))), + traverse(ast_type_traits::TK_AsIs, + stmt(anyOf( + ifStmt(Any), whileStmt(Any), doStmt(Condition), + binaryOperator( + allOf(unless(isExpansionInFileMatching( + "llvm/include/llvm/Support/Casting.h")), + hasOperatorName("&&"), + hasLHS(implicitCastExpr().bind("lhs")), + hasRHS(anyOf(implicitCastExpr(has(CallExpression)), + CallExpression)))) + .bind("and")))), this); } diff --git a/clang-tools-extra/clang-tidy/llvm/PreferRegisterOverUnsignedCheck.cpp b/clang-tools-extra/clang-tidy/llvm/PreferRegisterOverUnsignedCheck.cpp --- a/clang-tools-extra/clang-tidy/llvm/PreferRegisterOverUnsignedCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/PreferRegisterOverUnsignedCheck.cpp @@ -21,13 +21,15 @@ cxxRecordDecl(hasName("::llvm::Register")).bind("registerClassDecl")); Finder->addMatcher( - valueDecl(allOf( - hasType(qualType(isUnsignedInteger()).bind("varType")), - varDecl(hasInitializer(exprWithCleanups(has(implicitCastExpr(has( - cxxMemberCallExpr(allOf(on(RegisterClassMatch), - has(memberExpr(hasDeclaration( - cxxConversionDecl()))))))))))) - .bind("var"))), + traverse(ast_type_traits::TK_AsIs, + valueDecl(allOf( + hasType(qualType(isUnsignedInteger()).bind("varType")), + varDecl(hasInitializer(exprWithCleanups( + has(implicitCastExpr(has(cxxMemberCallExpr( + allOf(on(RegisterClassMatch), + has(memberExpr(hasDeclaration( + cxxConversionDecl()))))))))))) + .bind("var")))), this); } diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp --- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp @@ -828,18 +828,20 @@ // Binary with equivalent operands, like (X != 2 && X != 2). Finder->addMatcher( - binaryOperator(anyOf(isComparisonOperator(), - hasAnyOperatorName("-", "/", "%", "|", "&", "^", - "&&", "||", "=")), - operandsAreEquivalent(), - // Filter noisy false positives. - unless(isInTemplateInstantiation()), - unless(binaryOperatorIsInMacro()), - unless(hasType(realFloatingPointType())), - unless(hasEitherOperand(hasType(realFloatingPointType()))), - unless(hasLHS(AnyLiteralExpr)), - unless(hasDescendant(BannedIntegerLiteral))) - .bind("binary"), + traverse(ast_type_traits::TK_AsIs, + binaryOperator( + anyOf(isComparisonOperator(), + hasAnyOperatorName("-", "/", "%", "|", "&", "^", "&&", + "||", "=")), + operandsAreEquivalent(), + // Filter noisy false positives. + unless(isInTemplateInstantiation()), + unless(binaryOperatorIsInMacro()), + unless(hasType(realFloatingPointType())), + unless(hasEitherOperand(hasType(realFloatingPointType()))), + unless(hasLHS(AnyLiteralExpr)), + unless(hasDescendant(BannedIntegerLiteral))) + .bind("binary")), this); // Logical or bitwise operator with equivalent nested operands, like (X && Y @@ -856,23 +858,27 @@ this); // Conditional (trenary) operator with equivalent operands, like (Y ? X : X). - Finder->addMatcher(conditionalOperator(expressionsAreEquivalent(), - // Filter noisy false positives. - unless(conditionalOperatorIsInMacro()), - unless(isInTemplateInstantiation())) - .bind("cond"), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + conditionalOperator(expressionsAreEquivalent(), + // Filter noisy false positives. + unless(conditionalOperatorIsInMacro()), + unless(isInTemplateInstantiation())) + .bind("cond")), + this); // Overloaded operators with equivalent operands. - Finder->addMatcher(cxxOperatorCallExpr( - hasAnyOverloadedOperatorName( - "-", "/", "%", "|", "&", "^", "==", "!=", "<", - "<=", ">", ">=", "&&", "||", "="), - parametersAreEquivalent(), - // Filter noisy false positives. - unless(isMacro()), unless(isInTemplateInstantiation())) - .bind("call"), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + cxxOperatorCallExpr( + hasAnyOverloadedOperatorName("-", "/", "%", "|", "&", "^", + "==", "!=", "<", "<=", ">", + ">=", "&&", "||", "="), + parametersAreEquivalent(), + // Filter noisy false positives. + unless(isMacro()), unless(isInTemplateInstantiation())) + .bind("call")), + this); // Overloaded operators with equivalent operands. Finder->addMatcher( @@ -886,30 +892,34 @@ // Match expressions like: !(1 | 2 | 3) Finder->addMatcher( - implicitCastExpr( - hasImplicitDestinationType(isInteger()), - has(unaryOperator( - hasOperatorName("!"), - hasUnaryOperand(ignoringParenImpCasts(binaryOperator( - hasAnyOperatorName("|", "&"), - hasLHS(anyOf(binaryOperator(hasAnyOperatorName("|", "&")), + traverse(ast_type_traits::TK_AsIs, + implicitCastExpr( + hasImplicitDestinationType(isInteger()), + has(unaryOperator( + hasOperatorName("!"), + hasUnaryOperand(ignoringParenImpCasts(binaryOperator( + hasAnyOperatorName("|", "&"), + hasLHS(anyOf( + binaryOperator(hasAnyOperatorName("|", "&")), integerLiteral())), - hasRHS(integerLiteral()))))) - .bind("logical-bitwise-confusion"))), + hasRHS(integerLiteral()))))) + .bind("logical-bitwise-confusion")))), this); - // Match expressions like: (X << 8) & 0xFF - Finder->addMatcher( + // Match expressions like: (X << 8) & 0xFF + Finder->addMatcher( + traverse( + ast_type_traits::TK_AsIs, binaryOperator( hasOperatorName("&"), hasOperands( ignoringParenImpCasts( binaryOperator(hasOperatorName("<<"), - hasRHS(ignoringParenImpCasts( + hasRHS(ignoringParenImpCasts( integerLiteral().bind("shift-const"))))), ignoringParenImpCasts(integerLiteral().bind("and-const")))) - .bind("left-right-shift-confusion"), - this); + .bind("left-right-shift-confusion")), + this); // Match common expressions and apply more checks to find redundant // sub-expressions. @@ -923,26 +933,32 @@ const auto SymRight = matchSymbolicExpr("rhs"); // Match expressions like: x 0xFF == 0xF00. - Finder->addMatcher(binaryOperator(isComparisonOperator(), - hasOperands(BinOpCstLeft, CstRight)) - .bind("binop-const-compare-to-const"), + Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, + binaryOperator(isComparisonOperator(), + hasOperands(BinOpCstLeft, + CstRight)) + .bind("binop-const-compare-to-const")), this); // Match expressions like: x 0xFF == x. Finder->addMatcher( - binaryOperator(isComparisonOperator(), - anyOf(allOf(hasLHS(BinOpCstLeft), hasRHS(SymRight)), - allOf(hasLHS(SymRight), hasRHS(BinOpCstLeft)))) - .bind("binop-const-compare-to-sym"), + traverse( + ast_type_traits::TK_AsIs, + binaryOperator(isComparisonOperator(), + anyOf(allOf(hasLHS(BinOpCstLeft), hasRHS(SymRight)), + allOf(hasLHS(SymRight), hasRHS(BinOpCstLeft)))) + .bind("binop-const-compare-to-sym")), this); // Match expressions like: x 10 == x 12. - Finder->addMatcher(binaryOperator(isComparisonOperator(), - hasLHS(BinOpCstLeft), hasRHS(BinOpCstRight), - // Already reported as redundant. - unless(operandsAreEquivalent())) - .bind("binop-const-compare-to-binop-const"), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + binaryOperator(isComparisonOperator(), hasLHS(BinOpCstLeft), + hasRHS(BinOpCstRight), + // Already reported as redundant. + unless(operandsAreEquivalent())) + .bind("binop-const-compare-to-binop-const")), + this); // Match relational expressions combined with logical operators and find // redundant sub-expressions. @@ -951,13 +967,14 @@ // Match expressions like: x < 2 && x > 2. const auto ComparisonLeft = matchRelationalIntegerConstantExpr("lhs"); const auto ComparisonRight = matchRelationalIntegerConstantExpr("rhs"); - Finder->addMatcher(binaryOperator(hasAnyOperatorName("||", "&&"), - hasLHS(ComparisonLeft), - hasRHS(ComparisonRight), - // Already reported as redundant. - unless(operandsAreEquivalent())) - .bind("comparisons-of-symbol-and-const"), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + binaryOperator(hasAnyOperatorName("||", "&&"), + hasLHS(ComparisonLeft), hasRHS(ComparisonRight), + // Already reported as redundant. + unless(operandsAreEquivalent())) + .bind("comparisons-of-symbol-and-const")), + this); } void RedundantExpressionCheck::checkArithmeticExpr( diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp @@ -489,9 +489,12 @@ } void LoopConvertCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(makeArrayLoopMatcher(), this); - Finder->addMatcher(makeIteratorLoopMatcher(), this); - Finder->addMatcher(makePseudoArrayLoopMatcher(), this); + Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, makeArrayLoopMatcher()), + this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, makeIteratorLoopMatcher()), this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, makePseudoArrayLoopMatcher()), this); } /// Given the range of a single declaration, such as: @@ -897,6 +900,7 @@ } // Find out which qualifiers we have to use in the loop range. + TraversalKindScope RAII(*Context, ast_type_traits::TK_AsIs); const UsageResult &Usages = Finder.getUsages(); determineRangeDescriptor(Context, Nodes, Loop, FixerKind, ContainerExpr, Usages, Descriptor); diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp @@ -83,27 +83,29 @@ auto IsPlacement = hasAnyPlacementArg(anything()); Finder->addMatcher( - cxxBindTemporaryExpr(has(ignoringParenImpCasts( - cxxConstructExpr( - hasType(getSmartPointerTypeMatcher()), argumentCountIs(1), - hasArgument(0, - cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType( - equalsBoundNode(PointerType))))), - CanCallCtor, unless(IsPlacement)) - .bind(NewExpression)), - unless(isInTemplateInstantiation())) - .bind(ConstructorCall)))), + traverse( + ast_type_traits::TK_AsIs, + cxxBindTemporaryExpr(has(ignoringParenImpCasts( + cxxConstructExpr( + hasType(getSmartPointerTypeMatcher()), argumentCountIs(1), + hasArgument( + 0, cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType( + equalsBoundNode(PointerType))))), + CanCallCtor, unless(IsPlacement)) + .bind(NewExpression)), + unless(isInTemplateInstantiation())) + .bind(ConstructorCall))))), this); Finder->addMatcher( - cxxMemberCallExpr( - thisPointerType(getSmartPointerTypeMatcher()), - callee(cxxMethodDecl(hasName("reset"))), - hasArgument( - 0, - cxxNewExpr(CanCallCtor, unless(IsPlacement)).bind(NewExpression)), - unless(isInTemplateInstantiation())) - .bind(ResetCall), + traverse(ast_type_traits::TK_AsIs, + cxxMemberCallExpr( + thisPointerType(getSmartPointerTypeMatcher()), + callee(cxxMethodDecl(hasName("reset"))), + hasArgument(0, cxxNewExpr(CanCallCtor, unless(IsPlacement)) + .bind(NewExpression)), + unless(isInTemplateInstantiation())) + .bind(ResetCall)), this); } @@ -255,6 +257,8 @@ const CXXNewExpr *New, SourceManager &SM, ASTContext *Ctx) { auto SkipParensParents = [&](const Expr *E) { + TraversalKindScope RAII(*Ctx, ast_type_traits::TK_AsIs); + for (const Expr *OldE = nullptr; E != OldE;) { OldE = E; for (const auto &Node : Ctx->getParents(*E)) { diff --git a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp @@ -133,33 +133,36 @@ void PassByValueCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - cxxConstructorDecl( - forEachConstructorInitializer( - cxxCtorInitializer( - unless(isBaseInitializer()), - // Clang builds a CXXConstructExpr only when it knows which - // constructor will be called. In dependent contexts a - // ParenListExpr is generated instead of a CXXConstructExpr, - // filtering out templates automatically for us. - withInitializer(cxxConstructExpr( - has(ignoringParenImpCasts(declRefExpr( - to(parmVarDecl( - hasType(qualType( - // Match only const-ref or a non-const - // value parameters. Rvalues, - // TemplateSpecializationValues and - // const-values shouldn't be modified. - ValuesOnly - ? nonConstValueType() - : anyOf(notTemplateSpecConstRefType(), - nonConstValueType())))) - .bind("Param"))))), - hasDeclaration(cxxConstructorDecl( - isCopyConstructor(), unless(isDeleted()), - hasDeclContext( - cxxRecordDecl(isMoveConstructible()))))))) - .bind("Initializer"))) - .bind("Ctor"), + traverse( + ast_type_traits::TK_AsIs, + cxxConstructorDecl( + forEachConstructorInitializer( + cxxCtorInitializer( + unless(isBaseInitializer()), + // Clang builds a CXXConstructExpr only when it knows + // which constructor will be called. In dependent contexts + // a ParenListExpr is generated instead of a + // CXXConstructExpr, filtering out templates automatically + // for us. + withInitializer(cxxConstructExpr( + has(ignoringParenImpCasts(declRefExpr(to( + parmVarDecl( + hasType(qualType( + // Match only const-ref or a non-const + // value parameters. Rvalues, + // TemplateSpecializationValues and + // const-values shouldn't be modified. + ValuesOnly + ? nonConstValueType() + : anyOf(notTemplateSpecConstRefType(), + nonConstValueType())))) + .bind("Param"))))), + hasDeclaration(cxxConstructorDecl( + isCopyConstructor(), unless(isDeleted()), + hasDeclContext( + cxxRecordDecl(isMoveConstructible()))))))) + .bind("Initializer"))) + .bind("Ctor")), this); } diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp @@ -123,9 +123,11 @@ callee(cxxMethodDecl(ofClass(AutoPtrDecl))), hasArgument(1, MovableArgumentMatcher)), this); - Finder->addMatcher(cxxConstructExpr(hasType(AutoPtrType), argumentCountIs(1), - hasArgument(0, MovableArgumentMatcher)), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + cxxConstructExpr(hasType(AutoPtrType), argumentCountIs(1), + hasArgument(0, MovableArgumentMatcher))), + this); } void ReplaceAutoPtrCheck::registerPPCallbacks(const SourceManager &SM, diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp @@ -32,11 +32,14 @@ const auto End = hasArgument(1, expr()); const auto RandomFunc = hasArgument(2, expr().bind("randomFunc")); Finder->addMatcher( - callExpr(anyOf(allOf(Begin, End, argumentCountIs(2)), - allOf(Begin, End, RandomFunc, argumentCountIs(3))), - hasDeclaration(functionDecl(hasName("::std::random_shuffle"))), - has(implicitCastExpr(has(declRefExpr().bind("name"))))) - .bind("match"), + traverse( + ast_type_traits::TK_AsIs, + callExpr( + anyOf(allOf(Begin, End, argumentCountIs(2)), + allOf(Begin, End, RandomFunc, argumentCountIs(3))), + hasDeclaration(functionDecl(hasName("::std::random_shuffle"))), + has(implicitCastExpr(has(declRefExpr().bind("name"))))) + .bind("match")), this); } diff --git a/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReturnBracedInitListCheck.cpp @@ -31,11 +31,13 @@ has(ConstructExpr), has(cxxFunctionalCastExpr(has(ConstructExpr))))); Finder->addMatcher( - functionDecl(isDefinition(), // Declarations don't have return statements. + traverse(ast_type_traits::TK_AsIs, + functionDecl( + isDefinition(), // Declarations don't have return statements. returns(unless(anyOf(builtinType(), autoType()))), hasDescendant(returnStmt(hasReturnValue( has(cxxConstructExpr(has(CtorAsArgument))))))) - .bind("fn"), + .bind("fn")), this); } diff --git a/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ShrinkToFitCheck.cpp @@ -42,7 +42,8 @@ on(hasType(hasCanonicalType(hasDeclaration(namedDecl( hasAnyName("std::basic_string", "std::deque", "std::vector")))))), callee(cxxMethodDecl(hasName("swap"))), - has(ignoringParenImpCasts(memberExpr(hasDescendant(CopyCtorCall)))), + has(ignoringParenImpCasts(memberExpr(traverse( + ast_type_traits::TK_AsIs, hasDescendant(CopyCtorCall))))), hasArgument(0, SwapParam.bind("ContainerToShrink")), unless(isInTemplateInstantiation())) .bind("CopyAndSwapTrick"), diff --git a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.cpp @@ -325,7 +325,8 @@ } void UseAutoCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(makeCombinedMatcher(), this); + Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, makeCombinedMatcher()), + this); } void UseAutoCheck::replaceIterators(const DeclStmt *D, ASTContext *Context) { diff --git a/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp @@ -24,22 +24,25 @@ void UseBoolLiteralsCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - implicitCastExpr( - has(ignoringParenImpCasts(integerLiteral().bind("literal"))), - hasImplicitDestinationType(qualType(booleanType())), - unless(isInTemplateInstantiation()), - anyOf(hasParent(explicitCastExpr().bind("cast")), anything())), + traverse( + ast_type_traits::TK_AsIs, + implicitCastExpr( + has(ignoringParenImpCasts(integerLiteral().bind("literal"))), + hasImplicitDestinationType(qualType(booleanType())), + unless(isInTemplateInstantiation()), + anyOf(hasParent(explicitCastExpr().bind("cast")), anything()))), this); Finder->addMatcher( - conditionalOperator( - hasParent(implicitCastExpr( - hasImplicitDestinationType(qualType(booleanType())), - unless(isInTemplateInstantiation()))), - eachOf(hasTrueExpression( - ignoringParenImpCasts(integerLiteral().bind("literal"))), - hasFalseExpression( - ignoringParenImpCasts(integerLiteral().bind("literal"))))), + traverse(ast_type_traits::TK_AsIs, + conditionalOperator( + hasParent(implicitCastExpr( + hasImplicitDestinationType(qualType(booleanType())), + unless(isInTemplateInstantiation()))), + eachOf(hasTrueExpression(ignoringParenImpCasts( + integerLiteral().bind("literal"))), + hasFalseExpression(ignoringParenImpCasts( + integerLiteral().bind("literal")))))), this); } diff --git a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp @@ -109,10 +109,12 @@ anyOf(has(MakeTuple), has(MakeTupleCtor), HasConstructExpr, has(cxxFunctionalCastExpr(HasConstructExpr)))); - Finder->addMatcher(cxxMemberCallExpr(CallPushBack, has(SoughtParam), - unless(isInTemplateInstantiation())) - .bind("call"), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + cxxMemberCallExpr(CallPushBack, has(SoughtParam), + unless(isInTemplateInstantiation())) + .bind("call")), + this); } void UseEmplaceCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp @@ -75,14 +75,17 @@ // The initialization of a base class should be a call to a copy // constructor of the base. if (match( - cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer( - isBaseInitializer(), - withInitializer(cxxConstructExpr( - hasType(equalsNode(Base)), - hasDeclaration(cxxConstructorDecl(isCopyConstructor())), - argumentCountIs(1), - hasArgument( - 0, declRefExpr(to(varDecl(equalsNode(Param)))))))))), + traverse(ast_type_traits::TK_AsIs, + cxxConstructorDecl( + forEachConstructorInitializer(cxxCtorInitializer( + isBaseInitializer(), + withInitializer(cxxConstructExpr( + hasType(equalsNode(Base)), + hasDeclaration( + cxxConstructorDecl(isCopyConstructor())), + argumentCountIs(1), + hasArgument(0, declRefExpr(to(varDecl( + equalsNode(Param))))))))))), *Ctor, *Context) .empty()) return false; @@ -92,17 +95,20 @@ for (const auto *Field : FieldsToInit) { auto AccessToFieldInParam = accessToFieldInVar(Field, Param); // The initialization is a CXXConstructExpr for class types. - if (match( - cxxConstructorDecl(forEachConstructorInitializer(cxxCtorInitializer( - isMemberInitializer(), forField(equalsNode(Field)), - withInitializer(anyOf( - AccessToFieldInParam, - initListExpr(has(AccessToFieldInParam)), - cxxConstructExpr( - hasDeclaration(cxxConstructorDecl(isCopyConstructor())), - argumentCountIs(1), - hasArgument(0, AccessToFieldInParam))))))), - *Ctor, *Context) + if (match(traverse( + ast_type_traits::TK_AsIs, + cxxConstructorDecl( + forEachConstructorInitializer(cxxCtorInitializer( + isMemberInitializer(), forField(equalsNode(Field)), + withInitializer(anyOf( + AccessToFieldInParam, + initListExpr(has(AccessToFieldInParam)), + cxxConstructExpr( + hasDeclaration( + cxxConstructorDecl(isCopyConstructor())), + argumentCountIs(1), + hasArgument(0, AccessToFieldInParam)))))))), + *Ctor, *Context) .empty()) return false; } @@ -130,8 +136,10 @@ // statement: // return *this; if (Compound->body_empty() || - match(returnStmt(has(ignoringParenImpCasts(unaryOperator( - hasOperatorName("*"), hasUnaryOperand(cxxThisExpr()))))), + match(traverse( + ast_type_traits::TK_AsIs, + returnStmt(has(ignoringParenImpCasts(unaryOperator( + hasOperatorName("*"), hasUnaryOperand(cxxThisExpr())))))), *Compound->body_back(), *Context) .empty()) return false; @@ -145,21 +153,23 @@ // ((Base*)this)->operator=((Base)Other); // // So we are looking for a member call that fulfills: - if (match( - compoundStmt(has(ignoringParenImpCasts(cxxMemberCallExpr( - // - The object is an implicit cast of 'this' to a pointer to - // a base class. - onImplicitObjectArgument( - implicitCastExpr(hasImplicitDestinationType( - pointsTo(type(equalsNode(Base)))), - hasSourceExpression(cxxThisExpr()))), - // - The called method is the operator=. - callee(cxxMethodDecl(isCopyAssignmentOperator())), - // - The argument is (an implicit cast to a Base of) the - // argument taken by "Operator". - argumentCountIs(1), - hasArgument(0, declRefExpr(to(varDecl(equalsNode(Param))))))))), - *Compound, *Context) + if (match(traverse(ast_type_traits::TK_AsIs, + compoundStmt(has(ignoringParenImpCasts(cxxMemberCallExpr( + // - The object is an implicit cast of 'this' to a + // pointer to + // a base class. + onImplicitObjectArgument(implicitCastExpr( + hasImplicitDestinationType( + pointsTo(type(equalsNode(Base)))), + hasSourceExpression(cxxThisExpr()))), + // - The called method is the operator=. + callee(cxxMethodDecl(isCopyAssignmentOperator())), + // - The argument is (an implicit cast to a Base of) + // the argument taken by "Operator". + argumentCountIs(1), + hasArgument(0, declRefExpr(to(varDecl( + equalsNode(Param)))))))))), + *Compound, *Context) .empty()) return false; } @@ -174,11 +184,13 @@ member(fieldDecl(equalsNode(Field)))); auto RHS = accessToFieldInVar(Field, Param); if (match( - compoundStmt(has(ignoringParenImpCasts(stmt(anyOf( - binaryOperator(hasOperatorName("="), hasLHS(LHS), hasRHS(RHS)), - cxxOperatorCallExpr(hasOverloadedOperatorName("="), - argumentCountIs(2), hasArgument(0, LHS), - hasArgument(1, RHS))))))), + traverse(ast_type_traits::TK_AsIs, + compoundStmt(has(ignoringParenImpCasts(stmt(anyOf( + binaryOperator(hasOperatorName("="), hasLHS(LHS), + hasRHS(RHS)), + cxxOperatorCallExpr( + hasOverloadedOperatorName("="), argumentCountIs(2), + hasArgument(0, LHS), hasArgument(1, RHS)))))))), *Compound, *Context) .empty()) return false; diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp @@ -41,10 +41,12 @@ unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType()))), unless(hasSourceExpression(hasType(sugaredNullptrType())))); - return castExpr(anyOf(ImplicitCastToNull, - explicitCastExpr(hasDescendant(ImplicitCastToNull))), - unless(hasAncestor(explicitCastExpr()))) - .bind(CastSequence); + return traverse( + ast_type_traits::TK_AsIs, + castExpr(anyOf(ImplicitCastToNull, + explicitCastExpr(hasDescendant(ImplicitCastToNull))), + unless(hasAncestor(explicitCastExpr()))) + .bind(CastSequence)); } bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc, diff --git a/clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp b/clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp --- a/clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp +++ b/clang-tools-extra/clang-tidy/objc/NSInvocationArgumentLifetimeCheck.cpp @@ -101,23 +101,26 @@ void NSInvocationArgumentLifetimeCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - objcMessageExpr( - hasReceiverType(asString("NSInvocation *")), - anyOf(hasSelector("getArgument:atIndex:"), - hasSelector("getReturnValue:")), - hasArgument( - 0, anyOf(hasDescendant(memberExpr(isObjCManagedLifetime())), - hasDescendant(objcIvarRefExpr(isObjCManagedLifetime())), - hasDescendant( - // Reference to variables, but when dereferencing - // to ivars/fields a more-descendent variable - // reference (e.g. self) may match with strong - // object lifetime, leading to an incorrect match. - // Exclude these conditions. - declRefExpr(to(varDecl().bind("var")), - unless(hasParent(implicitCastExpr())), - isObjCManagedLifetime()))))) - .bind("call"), + traverse( + ast_type_traits::TK_AsIs, + objcMessageExpr( + hasReceiverType(asString("NSInvocation *")), + anyOf(hasSelector("getArgument:atIndex:"), + hasSelector("getReturnValue:")), + hasArgument( + 0, + anyOf(hasDescendant(memberExpr(isObjCManagedLifetime())), + hasDescendant(objcIvarRefExpr(isObjCManagedLifetime())), + hasDescendant( + // Reference to variables, but when dereferencing + // to ivars/fields a more-descendent variable + // reference (e.g. self) may match with strong + // object lifetime, leading to an incorrect match. + // Exclude these conditions. + declRefExpr(to(varDecl().bind("var")), + unless(hasParent(implicitCastExpr())), + isObjCManagedLifetime()))))) + .bind("call")), this); } diff --git a/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp b/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp @@ -49,9 +49,11 @@ varDecl(HasReferenceOrPointerTypeOrIsAllowed, unless(hasInitializer(expr(hasDescendant(expr(anyOf( materializeTemporaryExpr(), IteratorReturnsValueType))))))); - Finder->addMatcher(cxxForRangeStmt(hasLoopVariable(LoopVar.bind("loopVar"))) - .bind("forRange"), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + cxxForRangeStmt(hasLoopVariable(LoopVar.bind("loopVar"))) + .bind("forRange")), + this); } void ForRangeCopyCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp b/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/ImplicitConversionInLoopCheck.cpp @@ -47,16 +47,19 @@ // CXXOperatorCallExpr, so it should not get caught by the // cxxOperatorCallExpr() matcher. Finder->addMatcher( - cxxForRangeStmt(hasLoopVariable( - varDecl( - hasType(qualType(references(qualType(isConstQualified())))), - hasInitializer( - expr(anyOf(hasDescendant( - cxxOperatorCallExpr().bind("operator-call")), - hasDescendant(unaryOperator(hasOperatorName("*")) - .bind("operator-call")))) - .bind("init"))) - .bind("faulty-var"))), + traverse( + ast_type_traits::TK_AsIs, + cxxForRangeStmt(hasLoopVariable( + varDecl( + hasType(qualType(references(qualType(isConstQualified())))), + hasInitializer( + expr(anyOf( + hasDescendant( + cxxOperatorCallExpr().bind("operator-call")), + hasDescendant(unaryOperator(hasOperatorName("*")) + .bind("operator-call")))) + .bind("init"))) + .bind("faulty-var")))), this); } diff --git a/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.cpp b/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/InefficientAlgorithmCheck.cpp @@ -35,7 +35,8 @@ "::std::unordered_set", "::std::unordered_map", "::std::unordered_multiset", "::std::unordered_multimap")); - const auto Matcher = + const auto Matcher = traverse( + ast_type_traits::TK_AsIs, callExpr( callee(functionDecl(Algorithms)), hasArgument( @@ -54,7 +55,7 @@ hasDeclaration(equalsBoundNode("IneffContObj"))))))))), hasArgument(2, expr().bind("AlgParam")), unless(isInTemplateInstantiation())) - .bind("IneffAlg"); + .bind("IneffAlg")); Finder->addMatcher(Matcher, this); } diff --git a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp @@ -51,8 +51,10 @@ MoveCallMatcher, parmVarDecl(hasType(references(isConstQualified())))); Finder->addMatcher(callExpr(ConstParamMatcher).bind("receiving-expr"), this); - Finder->addMatcher(cxxConstructExpr(ConstParamMatcher).bind("receiving-expr"), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + cxxConstructExpr(ConstParamMatcher).bind("receiving-expr")), + this); } void MoveConstArgCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp b/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp @@ -29,13 +29,15 @@ void MoveConstructorInitCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - cxxConstructorDecl( - unless(isImplicit()), isMoveConstructor(), - hasAnyConstructorInitializer( - cxxCtorInitializer( - withInitializer(cxxConstructExpr(hasDeclaration( - cxxConstructorDecl(isCopyConstructor()).bind("ctor"))))) - .bind("move-init"))), + traverse(ast_type_traits::TK_AsIs, + cxxConstructorDecl( + unless(isImplicit()), isMoveConstructor(), + hasAnyConstructorInitializer( + cxxCtorInitializer( + withInitializer(cxxConstructExpr(hasDeclaration( + cxxConstructorDecl(isCopyConstructor()) + .bind("ctor"))))) + .bind("move-init")))), this); } diff --git a/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp b/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp @@ -44,12 +44,14 @@ pointee(type(equalsBoundNode("SrcT"))))))))))); Finder->addMatcher( - returnStmt( - hasReturnValue(ignoringElidableConstructorCall(ignoringParenImpCasts( - cxxConstructExpr(hasDeclaration(LValueRefCtor), - hasArgument(0, ignoringParenImpCasts(declRefExpr( - to(ConstLocalVariable))))) - .bind("ctor_call"))))), + traverse(ast_type_traits::TK_AsIs, + returnStmt(hasReturnValue( + ignoringElidableConstructorCall(ignoringParenImpCasts( + cxxConstructExpr( + hasDeclaration(LValueRefCtor), + hasArgument(0, ignoringParenImpCasts(declRefExpr( + to(ConstLocalVariable))))) + .bind("ctor_call")))))), this); } diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp @@ -68,12 +68,13 @@ matchers::matchesAnyListedName( AllowedTypes)))))), unless(isImplicit()), - hasInitializer( + hasInitializer(traverse( + ast_type_traits::TK_AsIs, cxxConstructExpr( hasDeclaration(cxxConstructorDecl( isCopyConstructor())), hasArgument(0, CopyCtorArg)) - .bind("ctorCall"))) + .bind("ctorCall")))) .bind("newVarDecl"))) .bind("declStmt"))) .bind("blockStmt"); @@ -96,6 +97,8 @@ const auto *BlockStmt = Result.Nodes.getNodeAs("blockStmt"); const auto *CtorCall = Result.Nodes.getNodeAs("ctorCall"); + TraversalKindScope RAII(*Result.Context, ast_type_traits::TK_AsIs); + // Do not propose fixes if the DeclStmt has multiple VarDecls or in macros // since we cannot place them correctly. bool IssueFix = diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -41,12 +41,13 @@ bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl, ASTContext &Context) { - auto Matches = - match(decl(forEachDescendant(declRefExpr( - equalsNode(&DeclRef), - unless(hasAncestor(stmt(anyOf(forStmt(), cxxForRangeStmt(), - whileStmt(), doStmt()))))))), - Decl, Context); + auto Matches = match( + traverse(ast_type_traits::TK_AsIs, + decl(forEachDescendant(declRefExpr( + equalsNode(&DeclRef), + unless(hasAncestor(stmt(anyOf(forStmt(), cxxForRangeStmt(), + whileStmt(), doStmt())))))))), + Decl, Context); return Matches.empty(); } @@ -82,10 +83,12 @@ matchers::matchesAnyListedName(AllowedTypes))))))), decl().bind("param")); Finder->addMatcher( - functionDecl(hasBody(stmt()), isDefinition(), unless(isImplicit()), - unless(cxxMethodDecl(anyOf(isOverride(), isFinal()))), - has(typeLoc(forEach(ExpensiveValueParamDecl))), - unless(isInstantiated()), decl().bind("functionDecl")), + traverse( + ast_type_traits::TK_AsIs, + functionDecl(hasBody(stmt()), isDefinition(), unless(isImplicit()), + unless(cxxMethodDecl(anyOf(isOverride(), isFinal()))), + has(typeLoc(forEach(ExpensiveValueParamDecl))), + unless(isInstantiated()), decl().bind("functionDecl"))), this); } @@ -93,6 +96,8 @@ const auto *Param = Result.Nodes.getNodeAs("param"); const auto *Function = Result.Nodes.getNodeAs("functionDecl"); + TraversalKindScope RAII(*Result.Context, ast_type_traits::TK_AsIs); + FunctionParmMutationAnalyzer &Analyzer = MutationAnalyzers.try_emplace(Function, *Function, *Result.Context) .first->second; diff --git a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp @@ -39,18 +39,20 @@ .bind("empty"))) .bind("container"))))))); - const auto WrongUse = anyOf( - hasParent(binaryOperator( - isComparisonOperator(), - hasEitherOperand(ignoringImpCasts(anyOf( - integerLiteral(equals(1)), integerLiteral(equals(0)))))) - .bind("SizeBinaryOp")), - hasParent(implicitCastExpr( - hasImplicitDestinationType(booleanType()), - anyOf( - hasParent(unaryOperator(hasOperatorName("!")).bind("NegOnSize")), - anything()))), - hasParent(explicitCastExpr(hasDestinationType(booleanType())))); + const auto WrongUse = traverse( + ast_type_traits::TK_AsIs, + anyOf( + hasParent(binaryOperator(isComparisonOperator(), + hasEitherOperand(ignoringImpCasts( + anyOf(integerLiteral(equals(1)), + integerLiteral(equals(0)))))) + .bind("SizeBinaryOp")), + hasParent(implicitCastExpr( + hasImplicitDestinationType(booleanType()), + anyOf(hasParent( + unaryOperator(hasOperatorName("!")).bind("NegOnSize")), + anything()))), + hasParent(explicitCastExpr(hasDestinationType(booleanType()))))); Finder->addMatcher( cxxMemberCallExpr(on(expr(anyOf(hasType(ValidContainer), diff --git a/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp b/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp @@ -39,13 +39,15 @@ hasOperands(castExpr(hasCastKind(CK_NullToPointer)), PointerExpr)); Finder->addMatcher( - ifStmt(hasCondition(anyOf(PointerCondition, BinaryPointerCheckCondition)), - hasThen(anyOf( - DeleteExpr, DeleteMemberExpr, - compoundStmt(anyOf(has(DeleteExpr), has(DeleteMemberExpr)), - statementCountIs(1)) - .bind("compound")))) - .bind("ifWithDelete"), + traverse(ast_type_traits::TK_AsIs, + ifStmt(hasCondition( + anyOf(PointerCondition, BinaryPointerCheckCondition)), + hasThen(anyOf(DeleteExpr, DeleteMemberExpr, + compoundStmt(anyOf(has(DeleteExpr), + has(DeleteMemberExpr)), + statementCountIs(1)) + .bind("compound")))) + .bind("ifWithDelete")), this); } diff --git a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp @@ -221,6 +221,9 @@ ASTContext &Context) { std::queue Q; Q.push(Cast); + + TraversalKindScope RAII(Context, ast_type_traits::TK_AsIs); + while (!Q.empty()) { for (const auto &N : Context.getParents(*Q.front())) { const Stmt *S = N.get(); @@ -273,24 +276,25 @@ binaryOperator(hasOperatorName("^"), hasLHS(implicitCastFromBool), hasRHS(implicitCastFromBool)); Finder->addMatcher( - implicitCastExpr( - anyOf(hasCastKind(CK_IntegralToBoolean), - hasCastKind(CK_FloatingToBoolean), - hasCastKind(CK_PointerToBoolean), - hasCastKind(CK_MemberPointerToBoolean)), - // Exclude case of using if or while statements with variable - // declaration, e.g.: - // if (int var = functionCall()) {} - unless( - hasParent(stmt(anyOf(ifStmt(), whileStmt()), has(declStmt())))), - // Exclude cases common to implicit cast to and from bool. - unless(exceptionCases), unless(has(boolXor)), - // Retrieve also parent statement, to check if we need additional - // parens in replacement. - anyOf(hasParent(stmt().bind("parentStmt")), anything()), - unless(isInTemplateInstantiation()), - unless(hasAncestor(functionTemplateDecl()))) - .bind("implicitCastToBool"), + traverse(ast_type_traits::TK_AsIs, + implicitCastExpr( + anyOf(hasCastKind(CK_IntegralToBoolean), + hasCastKind(CK_FloatingToBoolean), + hasCastKind(CK_PointerToBoolean), + hasCastKind(CK_MemberPointerToBoolean)), + // Exclude case of using if or while statements with variable + // declaration, e.g.: + // if (int var = functionCall()) {} + unless(hasParent( + stmt(anyOf(ifStmt(), whileStmt()), has(declStmt())))), + // Exclude cases common to implicit cast to and from bool. + unless(exceptionCases), unless(has(boolXor)), + // Retrieve also parent statement, to check if we need + // additional parens in replacement. + anyOf(hasParent(stmt().bind("parentStmt")), anything()), + unless(isInTemplateInstantiation()), + unless(hasAncestor(functionTemplateDecl()))) + .bind("implicitCastToBool")), this); auto boolComparison = binaryOperator(hasAnyOperatorName("==", "!="), @@ -304,26 +308,30 @@ withInitializer(equalsBoundNode("implicitCastFromBool")), forField(hasBitWidth(1))))); Finder->addMatcher( - implicitCastExpr( - implicitCastFromBool, - // Exclude comparisons of bools, as they are always cast to integers - // in such context: - // bool_expr_a == bool_expr_b - // bool_expr_a != bool_expr_b - unless(hasParent(binaryOperator(anyOf( - boolComparison, boolXor, boolOpAssignment, bitfieldAssignment)))), - implicitCastExpr().bind("implicitCastFromBool"), - unless(hasParent(bitfieldConstruct)), - // Check also for nested casts, for example: bool -> int -> float. - anyOf(hasParent(implicitCastExpr().bind("furtherImplicitCast")), - anything()), - unless(isInTemplateInstantiation()), - unless(hasAncestor(functionTemplateDecl()))), + traverse( + ast_type_traits::TK_AsIs, + implicitCastExpr( + implicitCastFromBool, + // Exclude comparisons of bools, as they are always cast to + // integers in such context: + // bool_expr_a == bool_expr_b + // bool_expr_a != bool_expr_b + unless(hasParent( + binaryOperator(anyOf(boolComparison, boolXor, + boolOpAssignment, bitfieldAssignment)))), + implicitCastExpr().bind("implicitCastFromBool"), + unless(hasParent(bitfieldConstruct)), + // Check also for nested casts, for example: bool -> int -> float. + anyOf(hasParent(implicitCastExpr().bind("furtherImplicitCast")), + anything()), + unless(isInTemplateInstantiation()), + unless(hasAncestor(functionTemplateDecl())))), this); } void ImplicitBoolConversionCheck::check( const MatchFinder::MatchResult &Result) { + if (const auto *CastToBool = Result.Nodes.getNodeAs("implicitCastToBool")) { const auto *Parent = Result.Nodes.getNodeAs("parentStmt"); diff --git a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp @@ -119,6 +119,9 @@ } void MagicNumbersCheck::check(const MatchFinder::MatchResult &Result) { + + TraversalKindScope RAII(*Result.Context, ast_type_traits::TK_AsIs); + checkBoundMatch(Result, "integer"); checkBoundMatch(Result, "float"); } diff --git a/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp b/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/MakeMemberFunctionConstCheck.cpp @@ -210,21 +210,23 @@ void MakeMemberFunctionConstCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - cxxMethodDecl( - isDefinition(), isUserProvided(), - unless(anyOf( - isExpansionInSystemHeader(), isVirtual(), isConst(), isStatic(), - hasTrivialBody(), cxxConstructorDecl(), cxxDestructorDecl(), - isTemplate(), isDependentContext(), - ofClass(anyOf( - isLambda(), - hasAnyDependentBases()) // Method might become virtual - // depending on template base class. - ), - isInsideMacroDefinition(), - hasCanonicalDecl(isInsideMacroDefinition()))), - usesThisAsConst()) - .bind("x"), + traverse( + ast_type_traits::TK_AsIs, + cxxMethodDecl( + isDefinition(), isUserProvided(), + unless(anyOf( + isExpansionInSystemHeader(), isVirtual(), isConst(), + isStatic(), hasTrivialBody(), cxxConstructorDecl(), + cxxDestructorDecl(), isTemplate(), isDependentContext(), + ofClass(anyOf(isLambda(), + hasAnyDependentBases()) // Method might become + // virtual depending on + // template base class. + ), + isInsideMacroDefinition(), + hasCanonicalDecl(isInsideMacroDefinition()))), + usesThisAsConst()) + .bind("x")), this); } diff --git a/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.cpp b/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/MisplacedArrayIndexCheck.cpp @@ -19,10 +19,12 @@ namespace readability { void MisplacedArrayIndexCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(arraySubscriptExpr(hasLHS(hasType(isInteger())), - hasRHS(hasType(isAnyPointer()))) - .bind("expr"), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + arraySubscriptExpr(hasLHS(hasType(isInteger())), + hasRHS(hasType(isAnyPointer()))) + .bind("expr")), + this); } void MisplacedArrayIndexCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp @@ -28,11 +28,13 @@ Finder->addMatcher(declRefExpr().bind("Ref"), this); // Analyse parameter usage in function. - Finder->addMatcher(stmt(anyOf(unaryOperator(hasAnyOperatorName("++", "--")), - binaryOperator(), callExpr(), returnStmt(), - cxxConstructExpr())) - .bind("Mark"), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + stmt(anyOf(unaryOperator(hasAnyOperatorName("++", "--")), + binaryOperator(), callExpr(), returnStmt(), + cxxConstructExpr())) + .bind("Mark")), + this); Finder->addMatcher(varDecl(hasInitializer(anything())).bind("Mark"), this); } diff --git a/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantFunctionPtrDereferenceCheck.cpp @@ -17,10 +17,11 @@ namespace readability { void RedundantFunctionPtrDereferenceCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(unaryOperator(hasOperatorName("*"), - has(implicitCastExpr( - hasCastKind(CK_FunctionToPointerDecay)))) - .bind("op"), + Finder->addMatcher(traverse(ast_type_traits::TK_AsIs, + unaryOperator(hasOperatorName("*"), + has(implicitCastExpr(hasCastKind( + CK_FunctionToPointerDecay)))) + .bind("op")), this); } diff --git a/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp @@ -33,17 +33,19 @@ .bind("construct"); Finder->addMatcher( - cxxConstructorDecl( - unless(isDelegatingConstructor()), - ofClass(unless( - anyOf(isUnion(), ast_matchers::isTemplateInstantiation()))), - forEachConstructorInitializer( - cxxCtorInitializer( - isWritten(), withInitializer(ignoringImplicit(Construct)), - unless(forField(hasType(isConstQualified()))), - unless(forField(hasParent(recordDecl(isUnion()))))) - .bind("init"))) - .bind("constructor"), + traverse( + ast_type_traits::TK_AsIs, + cxxConstructorDecl( + unless(isDelegatingConstructor()), + ofClass(unless( + anyOf(isUnion(), ast_matchers::isTemplateInstantiation()))), + forEachConstructorInitializer( + cxxCtorInitializer( + isWritten(), withInitializer(ignoringImplicit(Construct)), + unless(forField(hasType(isConstQualified()))), + unless(forField(hasParent(recordDecl(isUnion()))))) + .bind("init"))) + .bind("constructor")), this); } diff --git a/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantStringCStrCheck.cpp @@ -96,11 +96,13 @@ // Detect redundant 'c_str()' calls through a string constructor. // If CxxConstructExpr is the part of some CallExpr we need to // check that matched ParamDecl of the ancestor CallExpr is not rvalue. - Finder->addMatcher(cxxConstructExpr(StringConstructorExpr, - hasArgument(0, StringCStrCallExpr), - unless(hasParent(materializeTemporaryExpr( - unless(isBoundToLValue()))))), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + cxxConstructExpr(StringConstructorExpr, + hasArgument(0, StringCStrCallExpr), + unless(hasParent(materializeTemporaryExpr( + unless(isBoundToLValue())))))), + this); // Detect: 's == str.c_str()' -> 's == str' Finder->addMatcher( @@ -153,20 +155,22 @@ // Detect redundant 'c_str()' calls through a StringRef constructor. Finder->addMatcher( - cxxConstructExpr( - // Implicit constructors of these classes are overloaded - // wrt. string types and they internally make a StringRef - // referring to the argument. Passing a string directly to - // them is preferred to passing a char pointer. - hasDeclaration(cxxMethodDecl(hasAnyName( - "::llvm::StringRef::StringRef", "::llvm::Twine::Twine"))), - argumentCountIs(1), - // The only argument must have the form x.c_str() or p->c_str() - // where the method is string::c_str(). StringRef also has - // a constructor from string which is more efficient (avoids - // strlen), so we can construct StringRef from the string - // directly. - hasArgument(0, StringCStrCallExpr)), + traverse( + ast_type_traits::TK_AsIs, + cxxConstructExpr( + // Implicit constructors of these classes are overloaded + // wrt. string types and they internally make a StringRef + // referring to the argument. Passing a string directly to + // them is preferred to passing a char pointer. + hasDeclaration(cxxMethodDecl(hasAnyName( + "::llvm::StringRef::StringRef", "::llvm::Twine::Twine"))), + argumentCountIs(1), + // The only argument must have the form x.c_str() or p->c_str() + // where the method is string::c_str(). StringRef also has + // a constructor from string which is more efficient (avoids + // strlen), so we can construct StringRef from the string + // directly. + hasArgument(0, StringCStrCallExpr))), this); } diff --git a/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp @@ -104,9 +104,10 @@ // string foo = ""; // string bar(""); Finder->addMatcher( - namedDecl( - varDecl(StringType, hasInitializer(EmptyStringInit)).bind("vardecl"), - unless(parmVarDecl())), + traverse(ast_type_traits::TK_AsIs, + namedDecl(varDecl(StringType, hasInitializer(EmptyStringInit)) + .bind("vardecl"), + unless(parmVarDecl()))), this); // Match a field declaration with an empty string literal as initializer. Finder->addMatcher( diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp @@ -31,10 +31,12 @@ callee(memberExpr().bind("str1"))); // First and second case: cast str.compare(str) to boolean. - Finder->addMatcher(implicitCastExpr(hasImplicitDestinationType(booleanType()), - has(StrCompare)) - .bind("match1"), - this); + Finder->addMatcher( + traverse(ast_type_traits::TK_AsIs, + implicitCastExpr(hasImplicitDestinationType(booleanType()), + has(StrCompare)) + .bind("match1")), + this); // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0. Finder->addMatcher( diff --git a/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp b/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp --- a/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp @@ -28,6 +28,7 @@ ASTContext *Context) { SmallVector Result; + TraversalKindScope RAII(*Context, ast_type_traits::TK_AsIs); DynTypedNodeList Parents = Context->getParents(*S); SmallVector NodesToProcess(Parents.begin(), diff --git a/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp b/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp --- a/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp +++ b/clang-tools-extra/clang-tidy/zircon/TemporaryObjectsCheck.cpp @@ -36,10 +36,11 @@ // Matcher for user-defined constructors. Finder->addMatcher( - cxxConstructExpr(hasParent(cxxFunctionalCastExpr()), - hasDeclaration(cxxConstructorDecl( - hasParent(cxxRecordDecl(matchesAnyName(Names)))))) - .bind("temps"), + traverse(ast_type_traits::TK_AsIs, + cxxConstructExpr(hasParent(cxxFunctionalCastExpr()), + hasDeclaration(cxxConstructorDecl(hasParent( + cxxRecordDecl(matchesAnyName(Names)))))) + .bind("temps")), this); }