nick updated this revision to Diff 331955.
nick added a comment.
Forgot to remove a duplicated test
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D69218/new/
https://reviews.llvm.org/D69218
Files:
clang/docs/LibASTMatchersReference.html
clang/include/clang/ASTMatchers/ASTMatchers.h
clang/lib/ASTMatchers/ASTMatchersInternal.cpp
clang/lib/ASTMatchers/Dynamic/Registry.cpp
clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
Index: clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
+++ clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
@@ -297,6 +297,17 @@
EXPECT_TRUE(matches("int b[7];", M));
}
+TEST_F(RegistryTest, CXXBaseSpecifier) {
+ // TODO: rewrite with top-level cxxBaseSpecifier matcher when available
+ DeclarationMatcher ClassHasAnyDirectBase =
+ constructMatcher("cxxRecordDecl",
+ constructMatcher("hasDirectBase",
+ constructMatcher("cxxBaseSpecifier")))
+ .getTypedMatcher<Decl>();
+ EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasAnyDirectBase));
+ EXPECT_TRUE(notMatches("class X {};", ClassHasAnyDirectBase));
+}
+
TEST_F(RegistryTest, CXXCtorInitializer) {
Matcher<Decl> CtorDecl = constructMatcher(
"cxxConstructorDecl",
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -320,6 +320,15 @@
varDecl(hasType(pointsTo(ClassX)))));
}
+TEST(HasType, TakesQualTypeMatcherAndMatchesCXXBaseSpecifier) {
+ TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X")));
+ CXXBaseSpecifierMatcher BaseClassX = cxxBaseSpecifier(hasType(ClassX));
+ DeclarationMatcher ClassHasBaseClassX =
+ cxxRecordDecl(hasDirectBase(BaseClassX));
+ EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasBaseClassX));
+ EXPECT_TRUE(notMatches("class Z {}; class Y : Z {};", ClassHasBaseClassX));
+}
+
TEST(HasType, TakesDeclMatcherAndMatchesExpr) {
DeclarationMatcher ClassX = recordDecl(hasName("X"));
EXPECT_TRUE(
@@ -337,6 +346,15 @@
notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX))));
}
+TEST(HasType, TakesDeclMatcherAndMatchesCXXBaseSpecifier) {
+ DeclarationMatcher ClassX = recordDecl(hasName("X"));
+ CXXBaseSpecifierMatcher BaseClassX = cxxBaseSpecifier(hasType(ClassX));
+ DeclarationMatcher ClassHasBaseClassX =
+ cxxRecordDecl(hasDirectBase(BaseClassX));
+ EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasBaseClassX));
+ EXPECT_TRUE(notMatches("class Z {}; class Y : Z {};", ClassHasBaseClassX));
+}
+
TEST(HasType, MatchesTypedefDecl) {
EXPECT_TRUE(matches("typedef int X;", typedefDecl(hasType(asString("int")))));
EXPECT_TRUE(matches("typedef const int T;",
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -4400,6 +4400,13 @@
return;
}
+ DeclarationMatcher ClassHasAnyDirectBase =
+ cxxRecordDecl(hasDirectBase(cxxBaseSpecifier()));
+ EXPECT_TRUE(notMatches("class X {};", ClassHasAnyDirectBase));
+ EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasAnyDirectBase));
+ EXPECT_TRUE(matches("class X {}; class Y : public virtual X {};",
+ ClassHasAnyDirectBase));
+
EXPECT_TRUE(matches(
R"cc(
class Base {};
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===================================================================
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -179,6 +179,7 @@
REGISTER_MATCHER(cxxConstructExpr);
REGISTER_MATCHER(cxxConstructorDecl);
REGISTER_MATCHER(cxxConversionDecl);
+ REGISTER_MATCHER(cxxBaseSpecifier);
REGISTER_MATCHER(cxxCtorInitializer);
REGISTER_MATCHER(cxxDeductionGuideDecl);
REGISTER_MATCHER(cxxDefaultArgExpr);
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===================================================================
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -756,6 +756,7 @@
const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl;
const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl>
accessSpecDecl;
+const internal::VariadicAllOfMatcher<CXXBaseSpecifier> cxxBaseSpecifier;
const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer;
const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
const internal::VariadicAllOfMatcher<TemplateArgumentLoc> templateArgumentLoc;
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -144,6 +144,7 @@
using TypeLocMatcher = internal::Matcher<TypeLoc>;
using NestedNameSpecifierMatcher = internal::Matcher<NestedNameSpecifier>;
using NestedNameSpecifierLocMatcher = internal::Matcher<NestedNameSpecifierLoc>;
+using CXXBaseSpecifierMatcher = internal::Matcher<CXXBaseSpecifier>;
using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>;
using TemplateArgumentMatcher = internal::Matcher<TemplateArgument>;
using TemplateArgumentLocMatcher = internal::Matcher<TemplateArgumentLoc>;
@@ -516,6 +517,16 @@
extern const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl>
accessSpecDecl;
+/// Matches class bases.
+///
+/// Examples matches \c public virtual B.
+/// \code
+/// class B {};
+/// class C : public virtual B {};
+/// \endcode
+extern const internal::VariadicAllOfMatcher<CXXBaseSpecifier>
+ cxxBaseSpecifier;
+
/// Matches constructor initializers.
///
/// Examples matches \c i(42).
@@ -3790,16 +3801,19 @@
/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
/// and U (matcher = typedefDecl(hasType(asString("int")))
/// and friend class X (matcher = friendDecl(hasType("X"))
+/// and public virtual X (matcher = cxxBaseSpecifier(hasType(
+/// asString("class X")))
/// \code
/// class X {};
/// void y(X &x) { x; X z; }
/// typedef int U;
/// class Y { friend class X; };
+/// class Z : public virtual X {};
/// \endcode
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
hasType,
AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, TypedefNameDecl,
- ValueDecl),
+ ValueDecl, CXXBaseSpecifier),
internal::Matcher<QualType>, InnerMatcher, 0) {
QualType QT = internal::getUnderlyingType(Node);
if (!QT.isNull())
@@ -3819,10 +3833,13 @@
/// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
/// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
/// and friend class X (matcher = friendDecl(hasType("X"))
+/// and public virtual X (matcher = cxxBaseSpecifier(hasType(
+/// cxxRecordDecl(hasName("X"))))
/// \code
/// class X {};
/// void y(X &x) { x; X z; }
/// class Y { friend class X; };
+/// class Z : public virtual X {};
/// \endcode
///
/// Example matches class Derived
Index: clang/docs/LibASTMatchersReference.html
===================================================================
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -573,6 +573,15 @@
<tr style="text-align:left"><th>Return type</th><th>Name</th><th>Parameters</th></tr>
<!-- START_DECL_MATCHERS -->
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>></td><td class="name" onclick="toggle('cxxBaseSpecifier0')"><a name="cxxBaseSpecifier0Anchor">cxxBaseSpecifier</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>>...</td></tr>
+<tr><td colspan="4" class="doc" id="cxxBaseSpecifier0"><pre>Matches class bases.
+
+Examples matches public virtual B.
+ class B {};
+ class C : public virtual B {};
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>></td><td class="name" onclick="toggle('cxxCtorInitializer0')"><a name="cxxCtorInitializer0Anchor">cxxCtorInitializer</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXCtorInitializer.html">CXXCtorInitializer</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="cxxCtorInitializer0"><pre>Matches constructor initializers.
@@ -6109,8 +6118,8 @@
</pre></td></tr>
-<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>></td><td class="name" onclick="toggle('hasType7')"><a name="hasType7Anchor">hasType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasType7"><pre>Overloaded to match the declaration of the expression's or value
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>></td><td class="name" onclick="toggle('hasType8')"><a name="hasType8Anchor">hasType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasType8"><pre>Overloaded to match the declaration of the expression's or value
declaration's type.
In case of a value declaration (for example a variable declaration),
@@ -6122,9 +6131,12 @@
Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ cxxRecordDecl(hasName("X"))))
class X {};
void y(X &x) { x; X z; }
class Y { friend class X; };
+ class Z : public virtual X {};
Example matches class Derived
(matcher = cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base"))))))
@@ -6136,6 +6148,24 @@
</pre></td></tr>
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html">CXXBaseSpecifier</a>></td><td class="name" onclick="toggle('hasType4')"><a name="hasType4Anchor">hasType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasType4"><pre>Matches if the expression's or declaration's type matches a type
+matcher.
+
+Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
+ and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
+ and U (matcher = typedefDecl(hasType(asString("int")))
+ and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ asString("class X")))
+ class X {};
+ void y(X &x) { x; X z; }
+ typedef int U;
+ class Y { friend class X; };
+ class Z : public virtual X {};
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXConstructExpr.html">CXXConstructExpr</a>></td><td class="name" onclick="toggle('forEachArgumentWithParam1')"><a name="forEachArgumentWithParam1Anchor">forEachArgumentWithParam</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> ArgMatcher, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ParmVarDecl.html">ParmVarDecl</a>> ParamMatcher</td></tr>
<tr><td colspan="4" class="doc" id="forEachArgumentWithParam1"><pre>Matches all arguments and their respective ParmVarDecl.
@@ -7247,8 +7277,8 @@
</pre></td></tr>
-<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>></td><td class="name" onclick="toggle('hasType4')"><a name="hasType4Anchor">hasType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasType4"><pre>Overloaded to match the declaration of the expression's or value
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>></td><td class="name" onclick="toggle('hasType5')"><a name="hasType5Anchor">hasType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasType5"><pre>Overloaded to match the declaration of the expression's or value
declaration's type.
In case of a value declaration (for example a variable declaration),
@@ -7260,9 +7290,12 @@
Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ cxxRecordDecl(hasName("X"))))
class X {};
void y(X &x) { x; X z; }
class Y { friend class X; };
+ class Z : public virtual X {};
Example matches class Derived
(matcher = cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base"))))))
@@ -7282,10 +7315,13 @@
and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
and U (matcher = typedefDecl(hasType(asString("int")))
and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ asString("class X")))
class X {};
void y(X &x) { x; X z; }
typedef int U;
class Y { friend class X; };
+ class Z : public virtual X {};
</pre></td></tr>
@@ -7458,8 +7494,8 @@
</pre></td></tr>
-<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>></td><td class="name" onclick="toggle('hasType5')"><a name="hasType5Anchor">hasType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasType5"><pre>Overloaded to match the declaration of the expression's or value
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1FriendDecl.html">FriendDecl</a>></td><td class="name" onclick="toggle('hasType6')"><a name="hasType6Anchor">hasType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasType6"><pre>Overloaded to match the declaration of the expression's or value
declaration's type.
In case of a value declaration (for example a variable declaration),
@@ -7471,9 +7507,12 @@
Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ cxxRecordDecl(hasName("X"))))
class X {};
void y(X &x) { x; X z; }
class Y { friend class X; };
+ class Z : public virtual X {};
Example matches class Derived
(matcher = cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base"))))))
@@ -7493,10 +7532,13 @@
and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
and U (matcher = typedefDecl(hasType(asString("int")))
and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ asString("class X")))
class X {};
void y(X &x) { x; X z; }
typedef int U;
class Y { friend class X; };
+ class Z : public virtual X {};
</pre></td></tr>
@@ -8715,10 +8757,13 @@
and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
and U (matcher = typedefDecl(hasType(asString("int")))
and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ asString("class X")))
class X {};
void y(X &x) { x; X z; }
typedef int U;
class Y { friend class X; };
+ class Z : public virtual X {};
</pre></td></tr>
@@ -8861,8 +8906,8 @@
matches using X::b but not using X::a </pre></td></tr>
-<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>></td><td class="name" onclick="toggle('hasType6')"><a name="hasType6Anchor">hasType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
-<tr><td colspan="4" class="doc" id="hasType6"><pre>Overloaded to match the declaration of the expression's or value
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html">ValueDecl</a>></td><td class="name" onclick="toggle('hasType7')"><a name="hasType7Anchor">hasType</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasType7"><pre>Overloaded to match the declaration of the expression's or value
declaration's type.
In case of a value declaration (for example a variable declaration),
@@ -8874,9 +8919,12 @@
Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X")))))
and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ cxxRecordDecl(hasName("X"))))
class X {};
void y(X &x) { x; X z; }
class Y { friend class X; };
+ class Z : public virtual X {};
Example matches class Derived
(matcher = cxxRecordDecl(hasAnyBase(hasType(cxxRecordDecl(hasName("Base"))))))
@@ -8896,10 +8944,13 @@
and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X")))))
and U (matcher = typedefDecl(hasType(asString("int")))
and friend class X (matcher = friendDecl(hasType("X"))
+ and public virtual X (matcher = cxxBaseSpecifier(hasType(
+ asString("class X")))
class X {};
void y(X &x) { x; X z; }
typedef int U;
class Y { friend class X; };
+ class Z : public virtual X {};
</pre></td></tr>
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits