Skip to content
Snippets Groups Projects
Commit 52380602 authored by Edwin Vane's avatar Edwin Vane
Browse files

Support in hasDeclaration for types with getDecl()

    
Using a new metafunction for detecting the presence of the member
'getDecl' in a type T, added support to hasDeclaration for any such type
T. This allows hasDecl() to be replaced and enables several other
subclasses of clang::Type to use hasDeclaration.

Updated unittests and LibASTMatchersReference.html.

Reviewers: klimek


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175532 91177308-0d34-0410-b5e6-96231b3b80d8
parent 3b41a100
No related branches found
No related tags found
No related merge requests found
...@@ -1979,12 +1979,16 @@ Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockP ...@@ -1979,12 +1979,16 @@ Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockP
</pre></td></tr> </pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration1')"><a name="hasDeclaration1Anchor">hasDeclaration</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr> <tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration2')"><a name="hasDeclaration2Anchor">hasDeclaration</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration1"><pre>Matches a type if the declaration of the type matches the given <tr><td colspan="4" class="doc" id="hasDeclaration2"><pre>Matches a type if the declaration of the type matches the given
matcher. matcher.
In addition to being usable as Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, also usable as
Matcher&lt;T&gt; for any T supporting the getDecl() member function. e.g. various
subtypes of clang::Type.
Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;,
Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt; Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;
</pre></td></tr> </pre></td></tr>
...@@ -2130,12 +2134,16 @@ Example matches y in x(y) ...@@ -2130,12 +2134,16 @@ Example matches y in x(y)
</pre></td></tr> </pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration2')"><a name="hasDeclaration2Anchor">hasDeclaration</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr> <tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration3')"><a name="hasDeclaration3Anchor">hasDeclaration</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration2"><pre>Matches a type if the declaration of the type matches the given <tr><td colspan="4" class="doc" id="hasDeclaration3"><pre>Matches a type if the declaration of the type matches the given
matcher. matcher.
In addition to being usable as Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, also usable as
Matcher&lt;T&gt; for any T supporting the getDecl() member function. e.g. various
subtypes of clang::Type.
Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;,
Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt; Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;
</pre></td></tr> </pre></td></tr>
...@@ -2523,12 +2531,16 @@ FIXME: Unit test this matcher ...@@ -2523,12 +2531,16 @@ FIXME: Unit test this matcher
</pre></td></tr> </pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration0')"><a name="hasDeclaration0Anchor">hasDeclaration</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr> <tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration1')"><a name="hasDeclaration1Anchor">hasDeclaration</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration0"><pre>Matches a type if the declaration of the type matches the given <tr><td colspan="4" class="doc" id="hasDeclaration1"><pre>Matches a type if the declaration of the type matches the given
matcher. matcher.
In addition to being usable as Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, also usable as
Matcher&lt;T&gt; for any T supporting the getDecl() member function. e.g. various
subtypes of clang::Type.
Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;,
Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt; Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;
</pre></td></tr> </pre></td></tr>
...@@ -2689,12 +2701,16 @@ Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockP ...@@ -2689,12 +2701,16 @@ Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockP
</pre></td></tr> </pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration3')"><a name="hasDeclaration3Anchor">hasDeclaration</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr> <tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration4')"><a name="hasDeclaration4Anchor">hasDeclaration</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDeclaration3"><pre>Matches a type if the declaration of the type matches the given <tr><td colspan="4" class="doc" id="hasDeclaration4"><pre>Matches a type if the declaration of the type matches the given
matcher. matcher.
In addition to being usable as Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, also usable as
Matcher&lt;T&gt; for any T supporting the getDecl() member function. e.g. various
subtypes of clang::Type.
Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;, Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;,
Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt; Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;
</pre></td></tr> </pre></td></tr>
...@@ -2785,9 +2801,16 @@ QualType-matcher matches. ...@@ -2785,9 +2801,16 @@ QualType-matcher matches.
</pre></td></tr> </pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;</td><td class="name" onclick="toggle('hasDecl0')"><a name="hasDecl0Anchor">hasDecl</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefNameDecl.html">TypedefNameDecl</a>&gt; InnerMatcher</td></tr> <tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;</td><td class="name" onclick="toggle('hasDeclaration0')"><a name="hasDeclaration0Anchor">hasDeclaration</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt; InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasDecl0"><pre>Matches TypedefTypes referring to a specific <tr><td colspan="4" class="doc" id="hasDeclaration0"><pre>Matches a type if the declaration of the type matches the given
TypedefNameDecl. matcher.
In addition to being usable as Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;, also usable as
Matcher&lt;T&gt; for any T supporting the getDecl() member function. e.g. various
subtypes of clang::Type.
Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>&gt;,
Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1MemberExpr.html">MemberExpr</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>&gt;
</pre></td></tr> </pre></td></tr>
......
...@@ -1561,8 +1561,12 @@ unless(const M &InnerMatcher) { ...@@ -1561,8 +1561,12 @@ unless(const M &InnerMatcher) {
/// \brief Matches a type if the declaration of the type matches the given /// \brief Matches a type if the declaration of the type matches the given
/// matcher. /// matcher.
/// ///
/// In addition to being usable as Matcher<TypedefType>, also usable as
/// Matcher<T> for any T supporting the getDecl() member function. e.g. various
/// subtypes of clang::Type.
///
/// Usable as: Matcher<QualType>, Matcher<CallExpr>, Matcher<CXXConstructExpr>, /// Usable as: Matcher<QualType>, Matcher<CallExpr>, Matcher<CXXConstructExpr>,
/// Matcher<MemberExpr> /// Matcher<MemberExpr>, Matcher<TypedefType>
inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher,
internal::Matcher<Decl> > internal::Matcher<Decl> >
hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) { hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) {
...@@ -2846,13 +2850,6 @@ AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee); ...@@ -2846,13 +2850,6 @@ AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee);
/// matches "typedef int X" /// matches "typedef int X"
AST_TYPE_MATCHER(TypedefType, typedefType); AST_TYPE_MATCHER(TypedefType, typedefType);
/// \brief Matches \c TypedefTypes referring to a specific
/// \c TypedefNameDecl.
AST_MATCHER_P(TypedefType, hasDecl,
internal::Matcher<TypedefNameDecl>, InnerMatcher) {
return InnerMatcher.matches(*Node.getDecl(), Finder, Builder);
}
/// \brief Matches nested name specifiers. /// \brief Matches nested name specifiers.
/// ///
/// Given /// Given
......
...@@ -353,6 +353,18 @@ inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) { ...@@ -353,6 +353,18 @@ inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) {
return Matcher<T>(Implementation); return Matcher<T>(Implementation);
} }
/// \brief Metafunction to determine if type T has a member called getDecl.
template <typename T> struct has_getDecl {
typedef char yes[1];
typedef char no[2];
template <typename TestType>
static yes &test(char[sizeof(&TestType::getDecl)]);
template <typename> static no &test(...);
static bool const value = sizeof(test<T>(0)) == sizeof(yes);
};
/// \brief Matches declarations for QualType and CallExpr. /// \brief Matches declarations for QualType and CallExpr.
/// ///
/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but /// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
...@@ -373,6 +385,15 @@ public: ...@@ -373,6 +385,15 @@ public:
} }
private: private:
/// \brief If getDecl exists as a member of U, returns whether the inner
/// matcher matches Node.getDecl().
template <typename U>
bool matchesSpecialized(
const U &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
typename llvm::enable_if<has_getDecl<U>, int>::type = 0) const {
return matchesDecl(Node.getDecl(), Finder, Builder);
}
/// \brief Extracts the CXXRecordDecl or EnumDecl of a QualType and returns /// \brief Extracts the CXXRecordDecl or EnumDecl of a QualType and returns
/// whether the inner matcher matches on it. /// whether the inner matcher matches on it.
bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder, bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder,
......
...@@ -818,6 +818,14 @@ TEST(HasDeclaration, HasDeclarationOfEnumType) { ...@@ -818,6 +818,14 @@ TEST(HasDeclaration, HasDeclarationOfEnumType) {
qualType(hasDeclaration(enumDecl(hasName("X"))))))))); qualType(hasDeclaration(enumDecl(hasName("X")))))))));
} }
TEST(HasDeclaration, HasDeclarationOfTypeWithDecl) {
EXPECT_TRUE(matches("typedef int X; X a;",
varDecl(hasName("a"),
hasType(typedefType(hasDeclaration(decl()))))));
// FIXME: Add tests for other types with getDecl() (e.g. RecordType)
}
TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) { TEST(HasType, TakesQualTypeMatcherAndMatchesExpr) {
TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X"))); TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));
EXPECT_TRUE( EXPECT_TRUE(
...@@ -3350,10 +3358,6 @@ TEST(TypeMatching, MatchesPointersToConstTypes) { ...@@ -3350,10 +3358,6 @@ TEST(TypeMatching, MatchesPointersToConstTypes) {
TEST(TypeMatching, MatchesTypedefTypes) { TEST(TypeMatching, MatchesTypedefTypes) {
EXPECT_TRUE(matches("typedef int X; X a;", varDecl(hasName("a"), EXPECT_TRUE(matches("typedef int X; X a;", varDecl(hasName("a"),
hasType(typedefType())))); hasType(typedefType()))));
EXPECT_TRUE(matches("typedef int X; X a;",
varDecl(hasName("a"),
hasType(typedefType(hasDecl(decl()))))));
} }
TEST(NNS, MatchesNestedNameSpecifiers) { TEST(NNS, MatchesNestedNameSpecifiers) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment