Author: aaronballman Date: Wed Aug 5 07:11:30 2015 New Revision: 244036 URL: http://llvm.org/viewvc/llvm-project?rev=244036&view=rev Log: Add AST matchers for narrowing constructors that are default, copy, or move constructors, as well as functionality to determine whether a ctor initializer is a base initializer.
Modified: cfe/trunk/docs/LibASTMatchersReference.html cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Modified: cfe/trunk/docs/LibASTMatchersReference.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=244036&r1=244035&r2=244036&view=diff ============================================================================== --- cfe/trunk/docs/LibASTMatchersReference.html (original) +++ cfe/trunk/docs/LibASTMatchersReference.html Wed Aug 5 07:11:30 2015 @@ -1460,6 +1460,58 @@ Example matches f(0, 0) (matcher = callE </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>></td><td class="name" onclick="toggle('isCopyConstructor1')"><a name="isCopyConstructor1Anchor">isCopyConstructor</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isCopyConstructor1"><pre>Matches constructor declarations that are copy constructors. + +Example matches #2, but not #1 or #3 (matcher = constructorDecl(isCopyConstructor()) + struct S { + S(); // #1 + S(const S &); // #2 + S(S &&); // #3 + }; +</pre></td></tr> + +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>></td><td class="name" onclick="toggle('isDefaultConstructor1')"><a name="isDefaultConstructor1Anchor">isDefaultConstructor</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isDefaultConstructor1"><pre>Matches constructor declarations that are default constructors. + +Example matches #1, but not #2 or #3 (matcher = constructorDecl(isDefaultConstructor()) + struct S { + S(); // #1 + S(const S &); // #2 + S(S &&); // #3 + }; +</pre></td></tr> + + +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructorDecl.html">CXXConstructorDecl</a>></td><td class="name" onclick="toggle('isMoveConstructor1')"><a name="isMoveConstructor1Anchor">isMoveConstructor</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isMoveConstructor1"><pre>Matches constructor declarations that are move constructors. + +Example matches #3, but not #1 or #2 (matcher = constructorDecl(isMoveConstructor()) + struct S { + S(); // #1 + S(const S &); // #2 + S(S &&); // #3 + }; +</pre></td></tr> + + +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>></td><td class="name" onclick="toggle('isBaseInitializer0')"><a name="isBaseInitializer0Anchor">isBaseInitializer</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isBaseInitializer0"><pre>Matches a constructor initializer if it is initializing a base, as opposed to a member. + +Given + struct B {}; + struct D : B { + int I; + D(int i) : I(i) {} + }; + struct E : B { + E() : B() {} + }; +constructorDecl(hasAnyConstructorInitializer(isBaseInitializer())) + will match E(), but not match D(int). +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>></td><td class="name" onclick="toggle('isWritten0')"><a name="isWritten0Anchor">isWritten</a></td><td></td></tr> <tr><td colspan="4" class="doc" id="isWritten0"><pre>Matches a constructor initializer if it is explicitly written in code (as opposed to implicitly added by the compiler). Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=244036&r1=244035&r2=244036&view=diff ============================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Wed Aug 5 07:11:30 2015 @@ -2632,6 +2632,26 @@ AST_MATCHER(CXXCtorInitializer, isWritte return Node.isWritten(); } +/// \brief Matches a constructor initializer if it is initializing a base, as +/// opposed to a member. +/// +/// Given +/// \code +/// struct B {}; +/// struct D : B { +/// int I; +/// D(int i) : I(i) {} +/// }; +/// struct E : B { +/// E() : B() {} +/// }; +/// \endcode +/// constructorDecl(hasAnyConstructorInitializer(isBaseInitializer())) +/// will match E(), but not match D(int). +AST_MATCHER(CXXCtorInitializer, isBaseInitializer) { + return Node.isBaseInitializer(); +} + /// \brief Matches any argument of a call expression or a constructor call /// expression. /// @@ -4104,6 +4124,51 @@ AST_MATCHER_P(CXXConstructorDecl, forEac return Matched; } +/// \brief Matches constructor declarations that are copy constructors. +/// +/// Given +/// \code +/// struct S { +/// S(); // #1 +/// S(const S &); // #2 +/// S(S &&); // #3 +/// }; +/// \endcode +/// constructorDecl(isCopyConstructor()) will match #2, but not #1 or #3. +AST_MATCHER(CXXConstructorDecl, isCopyConstructor) { + return Node.isCopyConstructor(); +} + +/// \brief Matches constructor declarations that are move constructors. +/// +/// Given +/// \code +/// struct S { +/// S(); // #1 +/// S(const S &); // #2 +/// S(S &&); // #3 +/// }; +/// \endcode +/// constructorDecl(isMoveConstructor()) will match #3, but not #1 or #2. +AST_MATCHER(CXXConstructorDecl, isMoveConstructor) { + return Node.isMoveConstructor(); +} + +/// \brief Matches constructor declarations that are default constructors. +/// +/// Given +/// \code +/// struct S { +/// S(); // #1 +/// S(const S &); // #2 +/// S(S &&); // #3 +/// }; +/// \endcode +/// constructorDecl(isDefaultConstructor()) will match #1, but not #2 or #3. +AST_MATCHER(CXXConstructorDecl, isDefaultConstructor) { + return Node.isDefaultConstructor(); +} + /// \brief If the given case statement does not use the GNU case range /// extension, matches the constant given in the statement. /// Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=244036&r1=244035&r2=244036&view=diff ============================================================================== --- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original) +++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Wed Aug 5 07:11:30 2015 @@ -240,9 +240,12 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(innerType); REGISTER_MATCHER(integerLiteral); REGISTER_MATCHER(isArrow); + REGISTER_MATCHER(isBaseInitializer); REGISTER_MATCHER(isCatchAll); REGISTER_MATCHER(isConst); REGISTER_MATCHER(isConstQualified); + REGISTER_MATCHER(isCopyConstructor); + REGISTER_MATCHER(isDefaultConstructor); REGISTER_MATCHER(isDefinition); REGISTER_MATCHER(isDeleted); REGISTER_MATCHER(isExceptionVariable); @@ -259,6 +262,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isIntegral); REGISTER_MATCHER(isInTemplateInstantiation); REGISTER_MATCHER(isListInitialization); + REGISTER_MATCHER(isMoveConstructor); REGISTER_MATCHER(isOverride); REGISTER_MATCHER(isPrivate); REGISTER_MATCHER(isProtected); Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=244036&r1=244035&r2=244036&view=diff ============================================================================== --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original) +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Wed Aug 5 07:11:30 2015 @@ -1992,6 +1992,29 @@ TEST(ConstructorDeclaration, IsImplicit) methodDecl(isImplicit(), hasName("operator=")))); } +TEST(ConstructorDeclaration, Kinds) { + EXPECT_TRUE(matches("struct S { S(); };", + constructorDecl(isDefaultConstructor()))); + EXPECT_TRUE(notMatches("struct S { S(); };", + constructorDecl(isCopyConstructor()))); + EXPECT_TRUE(notMatches("struct S { S(); };", + constructorDecl(isMoveConstructor()))); + + EXPECT_TRUE(notMatches("struct S { S(const S&); };", + constructorDecl(isDefaultConstructor()))); + EXPECT_TRUE(matches("struct S { S(const S&); };", + constructorDecl(isCopyConstructor()))); + EXPECT_TRUE(notMatches("struct S { S(const S&); };", + constructorDecl(isMoveConstructor()))); + + EXPECT_TRUE(notMatches("struct S { S(S&&); };", + constructorDecl(isDefaultConstructor()))); + EXPECT_TRUE(notMatches("struct S { S(S&&); };", + constructorDecl(isCopyConstructor()))); + EXPECT_TRUE(matches("struct S { S(S&&); };", + constructorDecl(isMoveConstructor()))); +} + TEST(DestructorDeclaration, MatchesVirtualDestructor) { EXPECT_TRUE(matches("class Foo { virtual ~Foo(); };", destructorDecl(ofClass(hasName("Foo"))))); @@ -2058,6 +2081,24 @@ TEST(HasAnyConstructorInitializer, IsWri allOf(forField(hasName("bar_")), unless(isWritten())))))); } +TEST(HasAnyConstructorInitializer, IsBaseInitializer) { + static const char Code[] = + "struct B {};" + "struct D : B {" + " int I;" + " D(int i) : I(i) {}" + "};" + "struct E : B {" + " E() : B() {}" + "};"; + EXPECT_TRUE(matches(Code, constructorDecl(allOf( + hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())), + hasName("E"))))); + EXPECT_TRUE(notMatches(Code, constructorDecl(allOf( + hasAnyConstructorInitializer(allOf(isBaseInitializer(), isWritten())), + hasName("D"))))); +} + TEST(Matcher, NewExpression) { StatementMatcher New = newExpr(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits