r176047 - Various additions to ASTMatcher library:
Edwin Vane
edwin.vane at intel.com
Mon Feb 25 12:43:32 PST 2013
Author: revane
Date: Mon Feb 25 14:43:32 2013
New Revision: 176047
URL: http://llvm.org/viewvc/llvm-project?rev=176047&view=rev
Log:
Various additions to ASTMatcher library:
New type matchers:
* recordType
* elaboratedType
New narrowing matchers:
* hasQualifier
* namesType
* hasDeclContext
Added tests and updated LibASTMatchersReference.
Reviewers: klimek
Modified:
cfe/trunk/docs/LibASTMatchersReference.html
cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
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=176047&r1=176046&r2=176047&view=diff
==============================================================================
--- cfe/trunk/docs/LibASTMatchersReference.html (original)
+++ cfe/trunk/docs/LibASTMatchersReference.html Mon Feb 25 14:43:32 2013
@@ -930,6 +930,26 @@ dependentSizedArrayType
</pre></td></tr>
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td><td class="name" onclick="toggle('elaboratedTypeLoc0')"><a name="elaboratedTypeLoc0Anchor">elaboratedTypeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ElaboratedTypeLoc.html">ElaboratedTypeLoc</a>>...</td></tr>
+<tr><td colspan="4" class="doc" id="elaboratedTypeLoc0"><pre>Matches types specified with an elaborated type keyword or with a
+qualified name.
+
+Given
+ namespace N {
+ namespace M {
+ class D {};
+ }
+ }
+ class C {};
+
+ class C c;
+ N::M::D d;
+
+elaboratedType() matches the type of the variable declarations of both
+c and d.
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td><td class="name" onclick="toggle('functionTypeLoc0')"><a name="functionTypeLoc0Anchor">functionTypeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionTypeLoc.html">FunctionTypeLoc</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="functionTypeLoc0"><pre>Matches FunctionType nodes.
@@ -975,6 +995,21 @@ pointerType()
</pre></td></tr>
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td><td class="name" onclick="toggle('recordTypeLoc0')"><a name="recordTypeLoc0Anchor">recordTypeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordTypeLoc.html">RecordTypeLoc</a>>...</td></tr>
+<tr><td colspan="4" class="doc" id="recordTypeLoc0"><pre>Matches record types (e.g. structs, classes).
+
+Given
+ class C {};
+ struct S {};
+
+ C c;
+ S s;
+
+recordType() matches the type of the variable declarations of both c
+and s.
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td><td class="name" onclick="toggle('referenceTypeLoc0')"><a name="referenceTypeLoc0Anchor">referenceTypeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceTypeLoc.html">ReferenceTypeLoc</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="referenceTypeLoc0"><pre>Matches reference types.
@@ -1124,6 +1159,26 @@ dependentSizedArrayType
</pre></td></tr>
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('elaboratedType0')"><a name="elaboratedType0Anchor">elaboratedType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ElaboratedType.html">ElaboratedType</a>>...</td></tr>
+<tr><td colspan="4" class="doc" id="elaboratedType0"><pre>Matches types specified with an elaborated type keyword or with a
+qualified name.
+
+Given
+ namespace N {
+ namespace M {
+ class D {};
+ }
+ }
+ class C {};
+
+ class C c;
+ N::M::D d;
+
+elaboratedType() matches the type of the variable declarations of both
+c and d.
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('functionType0')"><a name="functionType0Anchor">functionType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionType.html">FunctionType</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="functionType0"><pre>Matches FunctionType nodes.
@@ -1169,6 +1224,21 @@ pointerType()
</pre></td></tr>
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('recordType0')"><a name="recordType0Anchor">recordType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1RecordType.html">RecordType</a>>...</td></tr>
+<tr><td colspan="4" class="doc" id="recordType0"><pre>Matches record types (e.g. structs, classes).
+
+Given
+ class C {};
+ struct S {};
+
+ C c;
+ S s;
+
+recordType() matches the type of the variable declarations of both c
+and s.
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>></td><td class="name" onclick="toggle('referenceType0')"><a name="referenceType0Anchor">referenceType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ReferenceType.html">ReferenceType</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="referenceType0"><pre>Matches reference types.
@@ -2399,6 +2469,22 @@ declStmt(hasSingleDecl(anything()))
</pre></td></tr>
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('hasDeclContext0')"><a name="hasDeclContext0Anchor">hasDeclContext</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasDeclContext0"><pre>Matches declarations whose declaration context, interpreted as a
+Decl, matches InnerMatcher.
+
+Given
+ namespace N {
+ namespace M {
+ class D {};
+ }
+ }
+
+recordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the
+declaration of class D.
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1DoStmt.html">DoStmt</a>></td><td class="name" onclick="toggle('hasBody0')"><a name="hasBody0Anchor">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="hasBody0"><pre>Matches a 'for', 'while', or 'do while' statement that has
a given body.
@@ -2421,6 +2507,40 @@ Example matches true (matcher = hasCondi
</pre></td></tr>
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ElaboratedType.html">ElaboratedType</a>></td><td class="name" onclick="toggle('hasQualifier0')"><a name="hasQualifier0Anchor">hasQualifier</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasQualifier0"><pre>Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier,
+matches InnerMatcher.
+
+Given
+ namespace N {
+ namespace M {
+ class D {};
+ }
+ }
+ N::M::D d;
+
+elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N"))))
+matches the type of the variable declaration of d.
+</pre></td></tr>
+
+
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ElaboratedType.html">ElaboratedType</a>></td><td class="name" onclick="toggle('namesType0')"><a name="namesType0Anchor">namesType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="namesType0"><pre>Matches ElaboratedTypes whose named type matches InnerMatcher.
+
+Given
+ namespace N {
+ namespace M {
+ class D {};
+ }
+ }
+ N::M::D d;
+
+elaboratedType(namesType(recordType(
+hasDeclaration(namedDecl(hasName("D")))))) matches the type of the variable
+declaration of d.
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ExplicitCastExpr.html">ExplicitCastExpr</a>></td><td class="name" onclick="toggle('hasDestinationType0')"><a name="hasDestinationType0Anchor">hasDestinationType</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDestinationType0"><pre>Matches casts whose destination type matches a given matcher.
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=176047&r1=176046&r2=176047&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Mon Feb 25 14:43:32 2013
@@ -2929,6 +2929,100 @@ AST_TYPE_MATCHER(TypedefType, typedefTyp
/// instantiation in \c A and the type of the variable declaration in \c B.
AST_TYPE_MATCHER(TemplateSpecializationType, templateSpecializationType);
+/// \brief Matches record types (e.g. structs, classes).
+///
+/// Given
+/// \code
+/// class C {};
+/// struct S {};
+///
+/// C c;
+/// S s;
+/// \code
+///
+/// \c recordType() matches the type of the variable declarations of both \c c
+/// and \c s.
+AST_TYPE_MATCHER(RecordType, recordType);
+
+/// \brief Matches types specified with an elaborated type keyword or with a
+/// qualified name.
+///
+/// Given
+/// \code
+/// namespace N {
+/// namespace M {
+/// class D {};
+/// }
+/// }
+/// class C {};
+///
+/// class C c;
+/// N::M::D d;
+/// \code
+///
+/// \c elaboratedType() matches the type of the variable declarations of both
+/// \c c and \c d.
+AST_TYPE_MATCHER(ElaboratedType, elaboratedType);
+
+/// \brief Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier,
+/// matches \c InnerMatcher.
+///
+/// Given
+/// \code
+/// namespace N {
+/// namespace M {
+/// class D {};
+/// }
+/// }
+/// N::M::D d;
+/// \code
+///
+/// \c elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N"))))
+/// matches the type of the variable declaration of \c d.
+AST_MATCHER_P(ElaboratedType, hasQualifier,
+ internal::Matcher<NestedNameSpecifier>, InnerMatcher) {
+ return InnerMatcher.matches(*Node.getQualifier(), Finder, Builder);
+}
+
+/// \brief Matches ElaboratedTypes whose named type matches \c InnerMatcher.
+///
+/// Given
+/// \code
+/// namespace N {
+/// namespace M {
+/// class D {};
+/// }
+/// }
+/// N::M::D d;
+/// \code
+///
+/// \c elaboratedType(namesType(recordType(
+/// hasDeclaration(namedDecl(hasName("D")))))) matches the type of the variable
+/// declaration of \c d.
+AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>,
+ InnerMatcher) {
+ return InnerMatcher.matches(Node.getNamedType(), Finder, Builder);
+}
+
+/// \brief Matches declarations whose declaration context, interpreted as a
+/// Decl, matches \c InnerMatcher.
+///
+/// Given
+/// \code
+/// namespace N {
+/// namespace M {
+/// class D {};
+/// }
+/// }
+/// \code
+///
+/// \c recordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the
+/// declaration of \c class \c D.
+AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) {
+ return InnerMatcher.matches(*Decl::castFromDeclContext(Node.getDeclContext()),
+ Finder, Builder);
+}
+
/// \brief Matches nested name specifiers.
///
/// Given
Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=176047&r1=176046&r2=176047&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Mon Feb 25 14:43:32 2013
@@ -323,6 +323,23 @@ TEST(DeclarationMatcher, ClassDerivedFro
recordDecl(hasName("B"), isDerivedFrom(recordDecl()))));
}
+TEST(DeclarationMatcher, hasDeclContext) {
+ EXPECT_TRUE(matches(
+ "namespace N {"
+ " namespace M {"
+ " class D {};"
+ " }"
+ "}",
+ recordDecl(hasDeclContext(namedDecl(hasName("M"))))));
+ EXPECT_TRUE(notMatches(
+ "namespace N {"
+ " namespace M {"
+ " class D {};"
+ " }"
+ "}",
+ recordDecl(hasDeclContext(namedDecl(hasName("N"))))));
+}
+
TEST(ClassTemplate, DoesNotMatchClass) {
DeclarationMatcher ClassX = classTemplateDecl(hasName("X"));
EXPECT_TRUE(notMatches("class X;", ClassX));
@@ -3413,10 +3430,63 @@ TEST(TypeMatching, MatchesTypedefTypes)
}
TEST(TypeMatching, MatchesTemplateSpecializationType) {
- EXPECT_TRUE(matches("template <typename T> class A{}; A<int>a;",
+ EXPECT_TRUE(matches("template <typename T> class A{}; A<int> a;",
templateSpecializationType()));
}
+TEST(TypeMatching, MatchesRecordType) {
+ EXPECT_TRUE(matches("class C{}; C c;", recordType()));
+ EXPECT_TRUE(matches("struct S{}; S s;", recordType()));
+ EXPECT_TRUE(notMatches("int i;", recordType()));
+}
+
+TEST(TypeMatching, MatchesElaboratedType) {
+ EXPECT_TRUE(matches(
+ "namespace N {"
+ " namespace M {"
+ " class D {};"
+ " }"
+ "}"
+ "N::M::D d;", elaboratedType()));
+ EXPECT_TRUE(matches("class C {} c;", elaboratedType()));
+ EXPECT_TRUE(notMatches("class C {}; C c;", elaboratedType()));
+}
+
+TEST(ElaboratedTypeNarrowing, hasQualifier) {
+ EXPECT_TRUE(matches(
+ "namespace N {"
+ " namespace M {"
+ " class D {};"
+ " }"
+ "}"
+ "N::M::D d;",
+ elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));
+ EXPECT_TRUE(notMatches(
+ "namespace M {"
+ " class D {};"
+ "}"
+ "M::D d;",
+ elaboratedType(hasQualifier(hasPrefix(specifiesNamespace(hasName("N")))))));
+}
+
+TEST(ElaboratedTypeNarrowing, namesType) {
+ EXPECT_TRUE(matches(
+ "namespace N {"
+ " namespace M {"
+ " class D {};"
+ " }"
+ "}"
+ "N::M::D d;",
+ elaboratedType(elaboratedType(namesType(recordType(
+ hasDeclaration(namedDecl(hasName("D")))))))));
+ EXPECT_TRUE(notMatches(
+ "namespace M {"
+ " class D {};"
+ "}"
+ "M::D d;",
+ elaboratedType(elaboratedType(namesType(typedefType())))));
+}
+
TEST(NNS, MatchesNestedNameSpecifiers) {
EXPECT_TRUE(matches("namespace ns { struct A {}; } ns::A a;",
nestedNameSpecifier()));
More information about the cfe-commits
mailing list