Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -2347,7 +2347,7 @@ private: int c; }; fieldDecl(isPrivate()) - matches 'int c;' + matches 'int c;' @@ -2361,7 +2361,7 @@ private: int c; }; fieldDecl(isProtected()) - matches 'int b;' + matches 'int b;' @@ -2375,7 +2375,7 @@ private: int c; }; fieldDecl(isPublic()) - matches 'int a;' + matches 'int a;' @@ -4455,6 +4455,25 @@ +
Matches expressions that match InnerMatcher after any implicit AST +nodes are stripped off. + +Parentheses and explicit casts are not discarded. +Given + class C {}; + C a = C(); + C b; + C c = b; +The matchers + varDecl(hasInitializer(ignoringImplicit(cxxConstructExpr()))) +would match the declarations for a, b, and c. +While + varDecl(hasInitializer(cxxConstructExpr())) +only match the declarations for b and c. +
Matches expressions that match InnerMatcher after parentheses and casts are stripped off. Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -548,6 +548,32 @@ Builder); } +/// \brief Matches expressions that match InnerMatcher after any implicit AST +/// nodes are stripped off. +/// +/// Parentheses and explicit casts are not discarded. +/// Given +/// \code +/// class C {}; +/// C a = C(); +/// C b; +/// C c = b; +/// \endcode +/// The matchers +/// \code +/// varDecl(hasInitializer(ignoringImplicit(cxxConstructExpr()))) +/// \endcode +/// would match the declarations for a, b, and c. +/// While +/// \code +/// varDecl(hasInitializer(cxxConstructExpr())) +/// \endcode +/// only match the declarations for b and c. +AST_MATCHER_P(Expr, ignoringImplicit, ast_matchers::internal::Matcher, + InnerMatcher) { + return InnerMatcher.matches(*Node.IgnoreImplicit(), Finder, Builder); +} + /// \brief Matches expressions that match InnerMatcher after any implicit casts /// are stripped off. /// Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -265,6 +265,7 @@ REGISTER_MATCHER(hasUnarySelector); REGISTER_MATCHER(hasValueType); REGISTER_MATCHER(ifStmt); + REGISTER_MATCHER(ignoringImplicit); REGISTER_MATCHER(ignoringImpCasts); REGISTER_MATCHER(ignoringParenCasts); REGISTER_MATCHER(ignoringParenImpCasts); Index: unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1088,6 +1088,16 @@ unless(anything()))))); } +TEST(IgnoringImplicit, MatchesImplicit) { + EXPECT_TRUE(matches("class C {}; C a = C();", + varDecl(has(ignoringImplicit(cxxConstructExpr()))))); +} + +TEST(IgnoringImplicit, DoesNotMatchIncorrectly) { + EXPECT_TRUE( + notMatches("class C {}; C a = C();", varDecl(has(cxxConstructExpr())))); +} + TEST(IgnoringImpCasts, MatchesImpCasts) { // This test checks that ignoringImpCasts matches when implicit casts are // present and its inner matcher alone does not match.