Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -2430,7 +2430,8 @@
Matches non-static data members that are bit-fields. +@@ -4750,6 +4751,19 @@ Matches non-static data members that are bit-fields of the specified +bit width. Given class C { @@ -2438,7 +2439,7 @@ int b : 4; int c : 2; }; -fieldDecl(isBitField()) +fieldDecl(hasBitWidth(2)) matches 'int a;' and 'int c;' but not 'int b;'.
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;'. +
Matches a 'for', 'while', 'do while' statement or a function definition that has a given body. 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, + 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: 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: 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"))));