Index: clang-tidy/cert/ThrownExceptionTypeCheck.cpp =================================================================== --- clang-tidy/cert/ThrownExceptionTypeCheck.cpp +++ clang-tidy/cert/ThrownExceptionTypeCheck.cpp @@ -23,10 +23,10 @@ return; Finder->addMatcher( - cxxThrowExpr( - has(cxxConstructExpr(hasDeclaration(cxxConstructorDecl( - isCopyConstructor(), unless(isNoThrow())))) - .bind("expr"))), + cxxThrowExpr(has(ignoringParenImpCasts( + cxxConstructExpr(hasDeclaration(cxxConstructorDecl( + isCopyConstructor(), unless(isNoThrow())))) + .bind("expr")))), this); } Index: clang-tidy/misc/BoolPointerImplicitConversionCheck.cpp =================================================================== --- clang-tidy/misc/BoolPointerImplicitConversionCheck.cpp +++ clang-tidy/misc/BoolPointerImplicitConversionCheck.cpp @@ -47,15 +47,18 @@ auto DeclRef = ignoringParenImpCasts(declRefExpr(to(equalsNode(D)))); if (!match(findAll( unaryOperator(hasOperatorName("*"), hasUnaryOperand(DeclRef))), - *If, *Result.Context).empty() || + *If, *Result.Context) + .empty() || !match(findAll(arraySubscriptExpr(hasBase(DeclRef))), *If, - *Result.Context).empty() || + *Result.Context) + .empty() || // FIXME: We should still warn if the paremater is implicitly converted to // bool. !match(findAll(callExpr(hasAnyArgument(ignoringParenImpCasts(DeclRef)))), *If, *Result.Context) .empty() || - !match(findAll(cxxDeleteExpr(has(expr(DeclRef)))), *If, *Result.Context) + !match(findAll(cxxDeleteExpr(has(ignoringParenImpCasts(expr(DeclRef))))), + *If, *Result.Context) .empty()) return; Index: clang-tidy/misc/DanglingHandleCheck.cpp =================================================================== --- clang-tidy/misc/DanglingHandleCheck.cpp +++ clang-tidy/misc/DanglingHandleCheck.cpp @@ -103,15 +103,17 @@ Finder->addMatcher( varDecl(hasType(cxxRecordDecl(IsAHandle)), hasInitializer( - exprWithCleanups(has(ConvertedHandle)).bind("bad_stmt"))), + exprWithCleanups(has(ignoringParenImpCasts(ConvertedHandle))) + .bind("bad_stmt"))), this); // Find 'Handle foo = ReturnsAValue();' Finder->addMatcher( - varDecl(hasType(cxxRecordDecl(IsAHandle)), unless(parmVarDecl()), - hasInitializer( - exprWithCleanups(has(handleFrom(IsAHandle, ConvertedHandle))) - .bind("bad_stmt"))), + varDecl( + hasType(cxxRecordDecl(IsAHandle)), unless(parmVarDecl()), + hasInitializer(exprWithCleanups(has(ignoringParenImpCasts(handleFrom( + IsAHandle, ConvertedHandle)))) + .bind("bad_stmt"))), this); // Find 'foo = ReturnsAValue(); // foo is Handle' Finder->addMatcher( @@ -133,7 +135,7 @@ // 1. Value to Handle conversion. // 2. Handle copy construction. // We have to match both. - has(handleFrom( + has(ignoringParenImpCasts(handleFrom( IsAHandle, handleFrom(IsAHandle, declRefExpr(to(varDecl( // Is function scope ... @@ -141,7 +143,7 @@ // ... and it is a local array or Value. anyOf(hasType(arrayType()), hasType(recordDecl( - unless(IsAHandle)))))))))), + unless(IsAHandle))))))))))), // Temporary fix for false positives inside lambdas. unless(hasAncestor(lambdaExpr()))) .bind("bad_stmt"), @@ -149,8 +151,9 @@ // Return a temporary. Finder->addMatcher( - returnStmt(has(exprWithCleanups(has(handleFrom( - IsAHandle, handleFromTemporaryValue(IsAHandle)))))) + returnStmt( + has(ignoringParenImpCasts(exprWithCleanups(has(ignoringParenImpCasts( + handleFrom(IsAHandle, handleFromTemporaryValue(IsAHandle)))))))) .bind("bad_stmt"), this); } Index: clang-tidy/misc/InaccurateEraseCheck.cpp =================================================================== --- clang-tidy/misc/InaccurateEraseCheck.cpp +++ clang-tidy/misc/InaccurateEraseCheck.cpp @@ -25,19 +25,20 @@ return; const auto CheckForEndCall = hasArgument( - 1, anyOf(cxxConstructExpr( - has(cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end")))) - .bind("InaccEndCall"))), + 1, anyOf(cxxConstructExpr(has(ignoringParenImpCasts( + cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end")))) + .bind("InaccEndCall")))), anything())); Finder->addMatcher( cxxMemberCallExpr( on(hasType(namedDecl(matchesName("^::std::")))), callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1), - hasArgument(0, has(callExpr(callee(functionDecl(matchesName( + hasArgument(0, has(ignoringParenImpCasts( + callExpr(callee(functionDecl(matchesName( "^::std::(remove(_if)?|unique)$"))), CheckForEndCall) - .bind("InaccAlgCall"))), + .bind("InaccAlgCall")))), unless(isInTemplateInstantiation())) .bind("InaccErase"), this); Index: clang-tidy/misc/IncorrectRoundings.cpp =================================================================== --- clang-tidy/misc/IncorrectRoundings.cpp +++ clang-tidy/misc/IncorrectRoundings.cpp @@ -42,7 +42,8 @@ // Match a floating literal of 0.5 or a floating literal of 0.5 implicitly. // cast to floating type. auto FloatOrCastHalf = - anyOf(FloatHalf, implicitCastExpr(FloatType, has(FloatHalf))); + anyOf(FloatHalf, + implicitCastExpr(FloatType, has(ignoringParenImpCasts(FloatHalf)))); // Match if either the LHS or RHS is a floating literal of 0.5 or a floating // literal of 0.5 and the other is of type double or vice versa. Index: clang-tidy/misc/InefficientAlgorithmCheck.cpp =================================================================== --- clang-tidy/misc/InefficientAlgorithmCheck.cpp +++ clang-tidy/misc/InefficientAlgorithmCheck.cpp @@ -45,18 +45,19 @@ callExpr( callee(functionDecl(Algorithms)), hasArgument( - 0, cxxConstructExpr(has(cxxMemberCallExpr( + 0, cxxConstructExpr(has(ignoringParenImpCasts(cxxMemberCallExpr( callee(cxxMethodDecl(hasName("begin"))), on(declRefExpr( hasDeclaration(decl().bind("IneffContObj")), anyOf(hasType(ContainerMatcher.bind("IneffCont")), hasType(pointsTo( ContainerMatcher.bind("IneffContPtr"))))) - .bind("IneffContExpr")))))), - hasArgument(1, cxxConstructExpr(has(cxxMemberCallExpr( - callee(cxxMethodDecl(hasName("end"))), - on(declRefExpr(hasDeclaration( - equalsBoundNode("IneffContObj")))))))), + .bind("IneffContExpr"))))))), + hasArgument( + 1, cxxConstructExpr(has(ignoringParenImpCasts(cxxMemberCallExpr( + callee(cxxMethodDecl(hasName("end"))), + on(declRefExpr( + hasDeclaration(equalsBoundNode("IneffContObj"))))))))), hasArgument(2, expr().bind("AlgParam")), unless(isInTemplateInstantiation())) .bind("IneffAlg"); Index: clang-tidy/misc/MisplacedWideningCastCheck.cpp =================================================================== --- clang-tidy/misc/MisplacedWideningCastCheck.cpp +++ clang-tidy/misc/MisplacedWideningCastCheck.cpp @@ -37,10 +37,11 @@ hasType(isInteger())) .bind("Calc"); - const auto ExplicitCast = - explicitCastExpr(hasDestinationType(isInteger()), has(Calc)); + const auto ExplicitCast = explicitCastExpr(hasDestinationType(isInteger()), + has(ignoringParenImpCasts(Calc))); const auto ImplicitCast = - implicitCastExpr(hasImplicitDestinationType(isInteger()), has(Calc)); + implicitCastExpr(hasImplicitDestinationType(isInteger()), + has(ignoringParenImpCasts(Calc))); const auto Cast = expr(anyOf(ExplicitCast, ImplicitCast)).bind("Cast"); Finder->addMatcher(varDecl(hasInitializer(Cast)), this); Index: clang-tidy/misc/SizeofContainerCheck.cpp =================================================================== --- clang-tidy/misc/SizeofContainerCheck.cpp +++ clang-tidy/misc/SizeofContainerCheck.cpp @@ -20,12 +20,12 @@ void SizeofContainerCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( expr(unless(isInTemplateInstantiation()), - expr(sizeOfExpr(has( + expr(sizeOfExpr(has(ignoringParenImpCasts( expr(hasType(hasCanonicalType(hasDeclaration(cxxRecordDecl( matchesName("^(::std::|::string)"), unless(matchesName("^::std::(bitset|array)$")), hasMethod(cxxMethodDecl(hasName("size"), isPublic(), - isConst())))))))))) + isConst()))))))))))) .bind("sizeof"), // Ignore ARRAYSIZE() pattern. unless(hasAncestor(binaryOperator( Index: clang-tidy/misc/SizeofExpressionCheck.cpp =================================================================== --- clang-tidy/misc/SizeofExpressionCheck.cpp +++ clang-tidy/misc/SizeofExpressionCheck.cpp @@ -81,21 +81,23 @@ const auto SizeOfExpr = expr(anyOf(sizeOfExpr(has(type())), sizeOfExpr(has(expr())))); const auto SizeOfZero = expr( - sizeOfExpr(has(expr(ignoringParenImpCasts(integerLiteral(equals(0))))))); + sizeOfExpr(has(ignoringParenImpCasts(expr(integerLiteral(equals(0))))))); // Detect expression like: sizeof(ARRAYLEN); // Note: The expression 'sizeof(sizeof(0))' is a portable trick used to know // the sizeof size_t. if (WarnOnSizeOfConstant) { - Finder->addMatcher(expr(sizeOfExpr(has(ConstantExpr)), unless(SizeOfZero)) - .bind("sizeof-constant"), - this); + Finder->addMatcher( + expr(sizeOfExpr(has(ignoringParenImpCasts(ConstantExpr))), + unless(SizeOfZero)) + .bind("sizeof-constant"), + this); } // Detect expression like: sizeof(this); if (WarnOnSizeOfThis) { Finder->addMatcher( - expr(sizeOfExpr(has(expr(ignoringParenImpCasts(cxxThisExpr()))))) + expr(sizeOfExpr(has(ignoringParenImpCasts(expr(cxxThisExpr()))))) .bind("sizeof-this"), this); } @@ -105,12 +107,12 @@ const auto ConstStrLiteralDecl = varDecl(isDefinition(), hasType(qualType(hasCanonicalType(CharPtrType))), hasInitializer(ignoringParenImpCasts(stringLiteral()))); - Finder->addMatcher( - expr(sizeOfExpr(has(expr(hasType(qualType(hasCanonicalType(CharPtrType))), - ignoringParenImpCasts(declRefExpr( - hasDeclaration(ConstStrLiteralDecl))))))) - .bind("sizeof-charp"), - this); + Finder->addMatcher(expr(sizeOfExpr(has(ignoringParenImpCasts(expr( + hasType(qualType(hasCanonicalType(CharPtrType))), + ignoringParenImpCasts(declRefExpr( + hasDeclaration(ConstStrLiteralDecl)))))))) + .bind("sizeof-charp"), + this); // Detect sizeof(ptr) where ptr points to an aggregate (i.e. sizeof(&S)). const auto ArrayExpr = expr(ignoringParenImpCasts( @@ -188,10 +190,11 @@ // Detect strange double-sizeof expression like: sizeof(sizeof(...)); // Note: The expression 'sizeof(sizeof(0))' is accepted. - Finder->addMatcher(expr(sizeOfExpr(has(expr(hasSizeOfDescendant( - 8, expr(SizeOfExpr, unless(SizeOfZero))))))) - .bind("sizeof-sizeof-expr"), - this); + Finder->addMatcher( + expr(sizeOfExpr(has(ignoringParenImpCasts(expr( + hasSizeOfDescendant(8, expr(SizeOfExpr, unless(SizeOfZero)))))))) + .bind("sizeof-sizeof-expr"), + this); } void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) { Index: clang-tidy/misc/StaticAssertCheck.cpp =================================================================== --- clang-tidy/misc/StaticAssertCheck.cpp +++ clang-tidy/misc/StaticAssertCheck.cpp @@ -33,12 +33,13 @@ if (!(getLangOpts().CPlusPlus11 || getLangOpts().C11)) return; - auto IsAlwaysFalse = expr(ignoringParenImpCasts( + auto IsAlwaysFalse = expr(anyOf(cxxBoolLiteral(equals(false)), integerLiteral(equals(0)), cxxNullPtrLiteralExpr(), gnuNullExpr())) - .bind("isAlwaysFalse"))); + .bind("isAlwaysFalse"); auto IsAlwaysFalseWithCast = ignoringParenImpCasts(anyOf( - IsAlwaysFalse, cStyleCastExpr(has(IsAlwaysFalse)).bind("castExpr"))); + IsAlwaysFalse, cStyleCastExpr(has(ignoringParenImpCasts(IsAlwaysFalse))) + .bind("castExpr"))); auto AssertExprRoot = anyOf( binaryOperator( anyOf(hasOperatorName("&&"), hasOperatorName("==")), Index: clang-tidy/misc/SuspiciousMissingCommaCheck.cpp =================================================================== --- clang-tidy/misc/SuspiciousMissingCommaCheck.cpp +++ clang-tidy/misc/SuspiciousMissingCommaCheck.cpp @@ -88,7 +88,7 @@ const auto StringsInitializerList = initListExpr(hasType(constantArrayType()), - has(expr(ignoringImpCasts(ConcatenatedStringLiteral)))); + has(ignoringParenImpCasts(expr(ConcatenatedStringLiteral)))); Finder->addMatcher(StringsInitializerList.bind("list"), this); } Index: clang-tidy/misc/SuspiciousStringCompareCheck.cpp =================================================================== --- clang-tidy/misc/SuspiciousStringCompareCheck.cpp +++ clang-tidy/misc/SuspiciousStringCompareCheck.cpp @@ -156,8 +156,9 @@ // Detect comparison to invalid constant: 'strcmp() == -1'. const auto InvalidLiteral = ignoringParenImpCasts( anyOf(integerLiteral(unless(equals(0))), - unaryOperator(hasOperatorName("-"), - has(integerLiteral(unless(equals(0))))), + unaryOperator( + hasOperatorName("-"), + has(ignoringParenImpCasts(integerLiteral(unless(equals(0)))))), characterLiteral(), cxxBoolLiteral())); Finder->addMatcher(binaryOperator(matchers::isComparisonOperator(), Index: clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp =================================================================== --- clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp +++ clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp @@ -56,8 +56,8 @@ cxxMethodDecl(IsSelfAssign, anyOf(isConst(), isVirtual())).bind("cv"), this); - const auto IsBadReturnStatement = returnStmt(unless(has( - unaryOperator(hasOperatorName("*"), hasUnaryOperand(cxxThisExpr()))))); + const auto IsBadReturnStatement = returnStmt(unless(has(ignoringParenImpCasts( + unaryOperator(hasOperatorName("*"), hasUnaryOperand(cxxThisExpr())))))); const auto IsGoodAssign = cxxMethodDecl(IsAssign, HasGoodReturnType); Finder->addMatcher(returnStmt(IsBadReturnStatement, forFunction(IsGoodAssign)) Index: clang-tidy/misc/UniqueptrResetReleaseCheck.cpp =================================================================== --- clang-tidy/misc/UniqueptrResetReleaseCheck.cpp +++ clang-tidy/misc/UniqueptrResetReleaseCheck.cpp @@ -30,13 +30,13 @@ cxxMethodDecl(hasName("reset"), ofClass(cxxRecordDecl(hasName("::std::unique_ptr"), decl().bind("left_class"))))), - has(cxxMemberCallExpr( + has(ignoringParenImpCasts(cxxMemberCallExpr( on(expr().bind("right")), callee(memberExpr().bind("release_member")), callee(cxxMethodDecl( hasName("release"), ofClass(cxxRecordDecl(hasName("::std::unique_ptr"), - decl().bind("right_class")))))))) + decl().bind("right_class"))))))))) .bind("reset_call"), this); } Index: clang-tidy/misc/UnusedRAIICheck.cpp =================================================================== --- clang-tidy/misc/UnusedRAIICheck.cpp +++ clang-tidy/misc/UnusedRAIICheck.cpp @@ -33,13 +33,16 @@ // Look for temporaries that are constructed in-place and immediately // destroyed. Look for temporaries created by a functional cast but not for // those returned from a call. - auto BindTemp = cxxBindTemporaryExpr(unless(has(callExpr()))).bind("temp"); + auto BindTemp = + cxxBindTemporaryExpr(unless(has(ignoringParenImpCasts(callExpr())))) + .bind("temp"); Finder->addMatcher( - exprWithCleanups( - unless(isInTemplateInstantiation()), - hasParent(compoundStmt().bind("compound")), - hasType(cxxRecordDecl(hasNonTrivialDestructor())), - anyOf(has(BindTemp), has(cxxFunctionalCastExpr(has(BindTemp))))) + exprWithCleanups(unless(isInTemplateInstantiation()), + hasParent(compoundStmt().bind("compound")), + hasType(cxxRecordDecl(hasNonTrivialDestructor())), + anyOf(has(ignoringParenImpCasts(BindTemp)), + has(ignoringParenImpCasts(cxxFunctionalCastExpr( + has(ignoringParenImpCasts(BindTemp))))))) .bind("expr"), this); } Index: clang-tidy/modernize/MakeSmartPtrCheck.cpp =================================================================== --- clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ clang-tidy/modernize/MakeSmartPtrCheck.cpp @@ -30,14 +30,14 @@ return; Finder->addMatcher( - cxxBindTemporaryExpr( - has(cxxConstructExpr( - hasType(getSmartPointerTypeMatcher()), argumentCountIs(1), - hasArgument( - 0, cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType( - equalsBoundNode(PointerType)))))) - .bind(NewExpression))) - .bind(ConstructorCall))), + cxxBindTemporaryExpr(has(ignoringParenImpCasts( + cxxConstructExpr( + hasType(getSmartPointerTypeMatcher()), argumentCountIs(1), + hasArgument(0, + cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType( + equalsBoundNode(PointerType)))))) + .bind(NewExpression))) + .bind(ConstructorCall)))), this); } Index: clang-tidy/modernize/PassByValueCheck.cpp =================================================================== --- clang-tidy/modernize/PassByValueCheck.cpp +++ clang-tidy/modernize/PassByValueCheck.cpp @@ -141,14 +141,14 @@ // ParenListExpr is generated instead of a CXXConstructExpr, // filtering out templates automatically for us. withInitializer(cxxConstructExpr( - has(declRefExpr(to( + has(ignoringParenImpCasts(declRefExpr(to( parmVarDecl( hasType(qualType( // Match only const-ref or a non-const value // parameters. Rvalues and const-values // shouldn't be modified. anyOf(constRefType(), nonConstValueType())))) - .bind("Param")))), + .bind("Param"))))), hasDeclaration(cxxConstructorDecl( isCopyConstructor(), unless(isDeleted()), hasDeclContext( Index: clang-tidy/modernize/ShrinkToFitCheck.cpp =================================================================== --- clang-tidy/modernize/ShrinkToFitCheck.cpp +++ clang-tidy/modernize/ShrinkToFitCheck.cpp @@ -26,24 +26,26 @@ memberExpr(member(valueDecl().bind("ContainerDecl"))); const auto ShrinkableAsDecl = declRefExpr(hasDeclaration(valueDecl().bind("ContainerDecl"))); - const auto CopyCtorCall = cxxConstructExpr( - hasArgument(0, anyOf(ShrinkableAsMember, ShrinkableAsDecl, - unaryOperator(has(ShrinkableAsMember)), - unaryOperator(has(ShrinkableAsDecl))))); - const auto SwapParam = expr(anyOf( - memberExpr(member(equalsBoundNode("ContainerDecl"))), - declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl"))), - unaryOperator(has(memberExpr(member(equalsBoundNode("ContainerDecl"))))), - unaryOperator( - has(declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl"))))))); + const auto CopyCtorCall = cxxConstructExpr(hasArgument( + 0, anyOf(ShrinkableAsMember, ShrinkableAsDecl, + unaryOperator(has(ignoringParenImpCasts(ShrinkableAsMember))), + unaryOperator(has(ignoringParenImpCasts(ShrinkableAsDecl)))))); + const auto SwapParam = + expr(anyOf(memberExpr(member(equalsBoundNode("ContainerDecl"))), + declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl"))), + unaryOperator(has(ignoringParenImpCasts( + memberExpr(member(equalsBoundNode("ContainerDecl")))))), + unaryOperator(has(ignoringParenImpCasts(declRefExpr( + hasDeclaration(equalsBoundNode("ContainerDecl")))))))); Finder->addMatcher( - cxxMemberCallExpr(on(hasType(namedDecl( - hasAnyName("std::basic_string", "std::deque", "std::vector")))), - callee(cxxMethodDecl(hasName("swap"))), - has(memberExpr(hasDescendant(CopyCtorCall))), - hasArgument(0, SwapParam.bind("ContainerToShrink")), - unless(isInTemplateInstantiation())) + cxxMemberCallExpr( + on(hasType(namedDecl( + hasAnyName("std::basic_string", "std::deque", "std::vector")))), + callee(cxxMethodDecl(hasName("swap"))), + has(ignoringParenImpCasts(memberExpr(hasDescendant(CopyCtorCall)))), + hasArgument(0, SwapParam.bind("ContainerToShrink")), + unless(isInTemplateInstantiation())) .bind("CopyAndSwapTrick"), this); } Index: clang-tidy/modernize/UseBoolLiteralsCheck.cpp =================================================================== --- clang-tidy/modernize/UseBoolLiteralsCheck.cpp +++ clang-tidy/modernize/UseBoolLiteralsCheck.cpp @@ -24,7 +24,7 @@ Finder->addMatcher( implicitCastExpr( - has(integerLiteral().bind("literal")), + has(ignoringParenImpCasts(integerLiteral().bind("literal"))), hasImplicitDestinationType(qualType(booleanType())), unless(isInTemplateInstantiation()), anyOf(hasParent(explicitCastExpr().bind("cast")), anything())), Index: clang-tidy/modernize/UseDefaultCheck.cpp =================================================================== --- clang-tidy/modernize/UseDefaultCheck.cpp +++ clang-tidy/modernize/UseDefaultCheck.cpp @@ -160,8 +160,8 @@ // statement: // return *this; if (Compound->body_empty() || - match(returnStmt(has(unaryOperator(hasOperatorName("*"), - hasUnaryOperand(cxxThisExpr())))), + match(returnStmt(has(ignoringParenImpCasts(unaryOperator( + hasOperatorName("*"), hasUnaryOperand(cxxThisExpr()))))), *Compound->body_back(), *Context) .empty()) return false; @@ -175,21 +175,21 @@ // ((Base*)this)->operator=((Base)Other); // // So we are looking for a member call that fulfills: - if (match( - compoundStmt(has(cxxMemberCallExpr(allOf( - // - 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(compoundStmt(has(ignoringParenImpCasts(cxxMemberCallExpr(allOf( + // - 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; } @@ -204,11 +204,11 @@ member(fieldDecl(equalsNode(Field)))); auto RHS = accessToFieldInVar(Field, Param); if (match( - compoundStmt(has(stmt(anyOf( + compoundStmt(has(ignoringParenImpCasts(stmt(anyOf( binaryOperator(hasOperatorName("="), hasLHS(LHS), hasRHS(RHS)), cxxOperatorCallExpr(hasOverloadedOperatorName("="), argumentCountIs(2), hasArgument(0, LHS), - hasArgument(1, RHS)))))), + hasArgument(1, RHS))))))), *Compound, *Context) .empty()) return false; Index: clang-tidy/readability/SimplifyBooleanExprCheck.cpp =================================================================== --- clang-tidy/readability/SimplifyBooleanExprCheck.cpp +++ clang-tidy/readability/SimplifyBooleanExprCheck.cpp @@ -461,7 +461,8 @@ compoundStmt(allOf(hasAnySubstatement(ifStmt(hasThen(returnsBool(Value)), unless(hasElse(stmt())))), hasAnySubstatement( - returnStmt(has(cxxBoolLiteral(equals(!Value)))) + returnStmt(has(ignoringParenImpCasts( + cxxBoolLiteral(equals(!Value))))) .bind(CompoundReturnId)))) .bind(Id), this); Index: clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp =================================================================== --- clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp +++ clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp @@ -28,11 +28,11 @@ hasName("std::default_delete"))))))); Finder->addMatcher( - cxxDeleteExpr( - has(cxxMemberCallExpr(on(expr(hasType(UniquePtrWithDefaultDelete), - unless(hasType(IsSusbstituted))) - .bind("uptr")), - callee(cxxMethodDecl(hasName("release")))))) + cxxDeleteExpr(has(ignoringParenImpCasts(cxxMemberCallExpr( + on(expr(hasType(UniquePtrWithDefaultDelete), + unless(hasType(IsSusbstituted))) + .bind("uptr")), + callee(cxxMethodDecl(hasName("release"))))))) .bind("delete"), this); } Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -170,11 +170,13 @@ AST Matchers ------------ -- hasAnyArgument: Matcher no longer ignores parentheses and implicit casts on - the argument before applying the inner matcher. The fix was done to allow for - greater control by the user. In all existing checkers that use this matcher - all instances of code ``hasAnyArgument()`` must be changed to - ``hasAnyArgument(ignoringParenImpCasts())``. +- has and hasAnyArgument: Matchers no longer ignores parentheses and implicit + casts on the argument before applying the inner matcher. The fix was done to + allow for greater control by the user. In all existing checkers that use this + matcher all instances of code ``hasAnyArgument()`` or + ``has()`` must be changed to + ``hasAnyArgument(ignoringParenImpCasts())`` or + ``has(ignoringParenImpCasts())``. ... Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -2169,6 +2169,10 @@ /// ChildT must be an AST base type. /// /// Usable as: Any Matcher +/// Note that has is direct matcher, so it also matches things like implicit +/// casts and paren casts. If you are matching with expr then you should +/// probably consider using ignoringParenImpCasts like: +/// has(ignoringParenImpCasts(expr())). const internal::ArgumentAdaptingMatcherFunc LLVM_ATTRIBUTE_UNUSED has = {}; Index: include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- include/clang/ASTMatchers/ASTMatchersInternal.h +++ include/clang/ASTMatchers/ASTMatchersInternal.h @@ -1165,8 +1165,6 @@ /// ChildT must be an AST base type. template class HasMatcher : public WrapperMatcherInterface { - static_assert(IsBaseType::value, - "has only accepts base type matcher"); public: explicit HasMatcher(const Matcher &ChildMatcher) @@ -1174,10 +1172,9 @@ bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const override { - return Finder->matchesChildOf( - Node, this->InnerMatcher, Builder, - ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses, - ASTMatchFinder::BK_First); + return Finder->matchesChildOf(Node, this->InnerMatcher, Builder, + ASTMatchFinder::TK_AsIs, + ASTMatchFinder::BK_First); } }; Index: include/clang/CMakeLists.txt =================================================================== --- include/clang/CMakeLists.txt +++ include/clang/CMakeLists.txt @@ -5,3 +5,4 @@ add_subdirectory(Sema) add_subdirectory(Serialization) add_subdirectory(StaticAnalyzer/Checkers) +add_subdirectory(ASTMatchers) Index: unittests/AST/ASTImporterTest.cpp =================================================================== --- unittests/AST/ASTImporterTest.cpp +++ unittests/AST/ASTImporterTest.cpp @@ -225,20 +225,14 @@ TEST(ImportExpr, ImportAtomicExpr) { MatchVerifier Verifier; - EXPECT_TRUE( - testImport( - "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }", - Lang_CXX, "", Lang_CXX, Verifier, - functionDecl( - hasBody( - compoundStmt( - has( - atomicExpr( - has(declRefExpr( - hasDeclaration(varDecl(hasName("ptr"))), - hasType(asString("int *")))), - has(integerLiteral(equals(1), hasType(asString("int")))) - ))))))); + EXPECT_TRUE(testImport( + "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }", Lang_CXX, + "", Lang_CXX, Verifier, + functionDecl(hasBody(compoundStmt(has(atomicExpr( + has(ignoringParenImpCasts( + declRefExpr(hasDeclaration(varDecl(hasName("ptr"))), + hasType(asString("int *"))))), + has(integerLiteral(equals(1), hasType(asString("int"))))))))))); } TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) { Index: unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -122,8 +122,8 @@ TEST(StatementMatcher, Has) { StatementMatcher HasVariableI = - expr(hasType(pointsTo(recordDecl(hasName("X")))), - has(declRefExpr(to(varDecl(hasName("i")))))); + expr(hasType(pointsTo(recordDecl(hasName("X")))), + has(ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("i"))))))); EXPECT_TRUE(matches( "class X; X *x(int); void c() { int i; x(i); }", HasVariableI));