malcolm.parsons created this revision. malcolm.parsons added reviewers: sbenza, bkramer, klimek. malcolm.parsons added a subscriber: cfe-commits.
I needed to know whether a FieldDecl had an in-class initializer for https://reviews.llvm.org/D26453. I used a narrowing matcher there, but a traversal matcher might be generally useful. VarDecl has a hasInitializer traversal matcher. ForStmt has a withLoopInit traversal matcher. CXXCtorInitializer has a withInitializer traversal matcher. EnumConstantDecl doesn't have a traversal matcher for its initializer. IfStmt doesn't have a traversal matcher for its initializer. https://reviews.llvm.org/D28034 Files: docs/LibASTMatchersReference.html include/clang/ASTMatchers/ASTMatchers.h lib/ASTMatchers/Dynamic/Registry.cpp unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1404,6 +1404,16 @@ fieldDecl(isBitField(), hasBitWidth(2), hasName("a")))); } +TEST(Member, InClassInitializer) { + EXPECT_TRUE( + matches("class C { int a = 2; int b; };", + fieldDecl(hasInClassInitializer(integerLiteral(equals(2))), + hasName("a")))); + EXPECT_TRUE( + notMatches("class C { int a = 2; int b; };", + fieldDecl(hasInClassInitializer(anything()), hasName("b")))); +} + TEST(Member, UnderstandsAccess) { EXPECT_TRUE(matches( "struct A { int i; };", fieldDecl(isPublic(), hasName("i")))); Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -232,6 +232,7 @@ REGISTER_MATCHER(hasFalseExpression); REGISTER_MATCHER(hasGlobalStorage); REGISTER_MATCHER(hasImplicitDestinationType); + REGISTER_MATCHER(hasInClassInitializer); REGISTER_MATCHER(hasIncrement); REGISTER_MATCHER(hasIndex); REGISTER_MATCHER(hasInitializer); Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -533,7 +533,8 @@ return Node.isBitField(); } -/// \brief Matches non-static data members that are bit-fields. +/// \brief Matches non-static data members that are bit-fields of the specified +/// bit width. /// /// Given /// \code @@ -543,13 +544,31 @@ /// int c : 2; /// }; /// \endcode -/// fieldDecl(isBitField()) +/// fieldDecl(hasBitWidth(2)) /// matches 'int a;' and 'int c;' but not 'int b;'. AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) { return Node.isBitField() && Node.getBitWidthValue(Finder->getASTContext()) == Width; } +/// \brief Matches non-static data members that have an in-class initializer. +/// +/// Given +/// \code +/// class C { +/// int a = 2; +/// int b = 3; +/// }; +/// \endcode +/// fieldDecl(hasInClassInitializer(integerLiteral(equals(2)))) +/// matches 'int a;' but not 'int b;'. +AST_MATCHER_P(FieldDecl, hasInClassInitializer, internal::Matcher<Expr>, + InnerMatcher) { + const Expr *Initializer = Node.getInClassInitializer(); + return (Initializer != nullptr && + InnerMatcher.matches(*Initializer, Finder, Builder)); +} + /// \brief Matches a declaration that has been implicitly added /// by the compiler (eg. implicit default/copy constructors). AST_MATCHER(Decl, isImplicit) { Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -2430,15 +2430,16 @@ <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>></td><td class="name" onclick="toggle('hasBitWidth0')"><a name="hasBitWidth0Anchor">hasBitWidth</a></td><td>unsigned Width</td></tr> -<tr><td colspan="4" class="doc" id="hasBitWidth0"><pre>Matches non-static data members that are bit-fields. +<tr><td colspan="4" class="doc" id="hasBitWidth0"><pre>Matches non-static data members that are bit-fields of the specified +bit width. Given class C { int a : 2; int b : 4; int c : 2; }; -fieldDecl(isBitField()) +fieldDecl(hasBitWidth(2)) matches 'int a;' and 'int c;' but not 'int b;'. </pre></td></tr> @@ -4750,6 +4751,19 @@ </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>></td><td class="name" onclick="toggle('hasInClassInitializer0')"><a name="hasInClassInitializer0Anchor">hasInClassInitializer</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasInClassInitializer0"><pre>Matches non-static data members that have an in-class initializer. + +Given + class C { + int a = 2; + int b = 3; + }; +fieldDecl(hasInClassInitializer(integerLiteral(equals(2)))) + matches 'int a;' but not 'int b;'. +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ForStmt.html">ForStmt</a>></td><td class="name" onclick="toggle('hasBody1')"><a name="hasBody1Anchor">hasBody</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasBody1"><pre>Matches a 'for', 'while', 'do while' statement or a function definition that has a given body.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits