nick updated this revision to Diff 225770. nick added a comment. Regenerated the docs, added more tests.
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D69218/new/ https://reviews.llvm.org/D69218 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/AST/ASTTypeTraits.h clang/include/clang/ASTMatchers/ASTMatchers.h clang/include/clang/ASTMatchers/ASTMatchersInternal.h clang/lib/AST/ASTTypeTraits.cpp clang/unittests/AST/ASTTypeTraitsTest.cpp clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -320,6 +320,14 @@ varDecl(hasType(pointsTo(ClassX))))); } +TEST(HasType, TakesQualTypeMatcherAndMatchesCXXBaseSpecifier) { + DeclarationMatcher ClassX = recordDecl(hasName("X")); + CXXBaseSpecifierMatcher BaseClassX = cxxBaseSpecifier(hasType(ClassX)); + DeclarationMatcher ClassHasBaseClassX = cxxRecordDecl(hasBase(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 +345,14 @@ notMatches("class X {}; void y() { X *x; }", varDecl(hasType(ClassX)))); } +TEST(HasType, TakesDeclMatcherAndMatchesCXXBaseSpecifier) { + TypeMatcher ClassX = hasDeclaration(recordDecl(hasName("X"))); + CXXBaseSpecifierMatcher BaseClassX = cxxBaseSpecifier(hasType(ClassX)); + DeclarationMatcher ClassHasBaseClassX = cxxRecordDecl(hasBase(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 @@ -678,6 +678,29 @@ "@interface Z : A @end", ZIsDirectlyDerivedFromX)); } +TEST(DeclarationMatcher, ClassHasBase) { + DeclarationMatcher ClassHasAnyBase = + cxxRecordDecl(hasBase(cxxBaseSpecifier())); + EXPECT_TRUE(notMatches("class X {};", ClassHasAnyBase)); + EXPECT_TRUE(matches("class X {}; class Y : X {};", ClassHasAnyBase)); + + TypeMatcher ClassX = asString("class X"); + CXXBaseSpecifierMatcher BaseClassX = cxxBaseSpecifier(hasType(ClassX)); + DeclarationMatcher ClassHasBaseClassX = cxxRecordDecl(hasBase(BaseClassX)); + EXPECT_TRUE(matches("class X {}; class Y {}; class Z : X, Y {};", + ClassHasBaseClassX)); + EXPECT_TRUE(matches("class X {}; class Y {}; class Z : Y, X {};", + ClassHasBaseClassX)); + EXPECT_TRUE(notMatches("class W {}; class Y {}; class Z : W, Y {};", + ClassHasBaseClassX)); + DeclarationMatcher ClassZHasBaseClassX = + cxxRecordDecl(hasName("Z"), hasBase(BaseClassX)); + EXPECT_TRUE(matches("class X {}; class Y : X {}; class Z : X {};", + ClassZHasBaseClassX)); + EXPECT_TRUE(notMatches("class X {}; class Y : X {}; class Z : Y {};", + ClassZHasBaseClassX)); +} + TEST(DeclarationMatcher, IsLambda) { const auto IsLambda = cxxMethodDecl(ofClass(cxxRecordDecl(isLambda()))); EXPECT_TRUE(matches("auto x = []{};", IsLambda)); Index: clang/unittests/AST/ASTTypeTraitsTest.cpp =================================================================== --- clang/unittests/AST/ASTTypeTraitsTest.cpp +++ clang/unittests/AST/ASTTypeTraitsTest.cpp @@ -112,6 +112,7 @@ VERIFY_NAME(NestedNameSpecifierLoc); VERIFY_NAME(QualType); VERIFY_NAME(TypeLoc); + VERIFY_NAME(CXXBaseSpecifier); VERIFY_NAME(CXXCtorInitializer); VERIFY_NAME(NestedNameSpecifier); VERIFY_NAME(Decl); @@ -141,6 +142,15 @@ EXPECT_TRUE(Verifier.match("void f() {}", typeLoc(loc(functionType())))); } +#if 0 // Cannot be used as a top level matcher at the time +TEST(DynTypedNode, CXXBaseSpecifierSourceRange) { + RangeVerifier<DynTypedNode> Verifier; + Verifier.expectRange(1, 23, 1, 39); + EXPECT_TRUE(Verifier.match("class B {}; class C : public virtual B {};", + cxxBaseSpecifier())); +} +#endif + TEST(DynTypedNode, NNSLocSourceRange) { RangeVerifier<DynTypedNode> Verifier; Verifier.expectRange(1, 33, 1, 34); Index: clang/lib/AST/ASTTypeTraits.cpp =================================================================== --- clang/lib/AST/ASTTypeTraits.cpp +++ clang/lib/AST/ASTTypeTraits.cpp @@ -27,6 +27,7 @@ { NKI_None, "NestedNameSpecifierLoc" }, { NKI_None, "QualType" }, { NKI_None, "TypeLoc" }, + { NKI_None, "CXXBaseSpecifier" }, { NKI_None, "CXXCtorInitializer" }, { NKI_None, "NestedNameSpecifier" }, { NKI_None, "Decl" }, @@ -163,6 +164,8 @@ } SourceRange DynTypedNode::getSourceRange() const { + if (const CXXBaseSpecifier *CBS = get<CXXBaseSpecifier>()) + return CBS->getSourceRange(); if (const CXXCtorInitializer *CCI = get<CXXCtorInitializer>()) return CCI->getSourceRange(); if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -130,6 +130,9 @@ return TSI->getType(); return QualType(); } +inline QualType getUnderlyingType(const CXXBaseSpecifier &Node) { + return Node.getType(); +} /// Unifies obtaining the FunctionProtoType pointer from both /// FunctionProtoType and FunctionDecl nodes.. @@ -926,6 +929,7 @@ std::is_same<T, TypeLoc>::value || std::is_same<T, NestedNameSpecifier>::value || std::is_same<T, NestedNameSpecifierLoc>::value || + std::is_same<T, CXXBaseSpecifier>::value || std::is_same<T, CXXCtorInitializer>::value; }; template <typename T> @@ -1094,7 +1098,7 @@ /// Useful for matchers like \c anything and \c unless. using AllNodeBaseTypes = TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType, - Type, TypeLoc, CXXCtorInitializer>; + Type, TypeLoc, CXXBaseSpecifier, CXXCtorInitializer>; /// Helper meta-function to extract the argument out of a function of /// type void(Arg). Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -140,6 +140,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>; /// @} @@ -468,6 +469,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). @@ -2602,6 +2613,23 @@ AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>(Name); } +/// Matches C++ classes that have a direct base class matching \c Base. +/// +/// Example matches X (Base == cxxBaseSpecifier()) +/// \code +/// class X; +/// class Y : X {}; +/// \endcode +AST_MATCHER_P_OVERLOAD(CXXRecordDecl, hasBase, + internal::Matcher<CXXBaseSpecifier>, Base, 1) { + if (!Node.hasDefinition()) + return false; + for (const CXXBaseSpecifier &BaseSpec : Node.bases()) + if (Base.matches(BaseSpec, Finder, Builder)) + return true; + return false; +} + /// Matches C++ classes that are directly or indirectly derived from a class /// matching \c Base, or Objective-C classes that directly or indirectly /// subclass a class matching \c Base. @@ -3258,16 +3286,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()) @@ -3287,15 +3318,20 @@ /// 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 /// /// Usable as: Matcher<Expr>, Matcher<ValueDecl> AST_POLYMORPHIC_MATCHER_P_OVERLOAD( - hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, ValueDecl), + hasType, + AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, ValueDecl, + CXXBaseSpecifier), internal::Matcher<Decl>, InnerMatcher, 1) { QualType QT = internal::getUnderlyingType(Node); if (!QT.isNull()) Index: clang/include/clang/AST/ASTTypeTraits.h =================================================================== --- clang/include/clang/AST/ASTTypeTraits.h +++ clang/include/clang/AST/ASTTypeTraits.h @@ -138,6 +138,7 @@ NKI_QualType, NKI_TypeLoc, NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc, + NKI_CXXBaseSpecifier, NKI_CXXCtorInitializer, NKI_NestedNameSpecifier, NKI_Decl, @@ -189,6 +190,7 @@ template <> struct ASTNodeKind::KindToKindId<Class> { \ static const NodeKindId Id = NKI_##Class; \ }; +KIND_TO_KIND_ID(CXXBaseSpecifier) KIND_TO_KIND_ID(CXXCtorInitializer) KIND_TO_KIND_ID(TemplateArgument) KIND_TO_KIND_ID(TemplateName) @@ -487,6 +489,10 @@ struct DynTypedNode::BaseConverter< NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {}; +template <> +struct DynTypedNode::BaseConverter< + CXXBaseSpecifier, void> : public PtrConverter<CXXBaseSpecifier> {}; + template <> struct DynTypedNode::BaseConverter< CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {}; Index: clang/docs/LibASTMatchersReference.html =================================================================== --- clang/docs/LibASTMatchersReference.html +++ clang/docs/LibASTMatchersReference.html @@ -100,6 +100,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. @@ -4741,8 +4750,8 @@ </pre></td></tr> -<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html";>ArraySubscriptExpr</a>></td><td class="name" onclick="toggle('hasBase0')"><a name="hasBase0Anchor">hasBase</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasBase0"><pre>Matches the base expression of an array subscript expression. +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ArraySubscriptExpr.html";>ArraySubscriptExpr</a>></td><td class="name" onclick="toggle('hasBase1')"><a name="hasBase1Anchor">hasBase</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasBase1"><pre>Matches the base expression of an array subscript expression. Given int i[5]; @@ -4911,6 +4920,48 @@ </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('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), +this resolves one layer of indirection. For example, in the value +declaration "X x;", cxxRecordDecl(hasName("X")) matches the declaration of +X, while varDecl(hasType(cxxRecordDecl(hasName("X")))) matches the +declaration of x. + +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 {}; + +Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html";>ValueDecl</a>> +</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. @@ -5251,6 +5302,15 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html";>CXXRecordDecl</a>></td><td class="name" onclick="toggle('hasBase0')"><a name="hasBase0Anchor">hasBase</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html";>CXXBaseSpecifier</a>> Base</td></tr> +<tr><td colspan="4" class="doc" id="hasBase0"><pre>Matches C++ classes that have a direct base class matching Base. + +Example matches X (Base == cxxBaseSpecifier()) + class X; + class Y : X {}; +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html";>CXXRecordDecl</a>></td><td class="name" onclick="toggle('hasMethod0')"><a name="hasMethod0Anchor">hasMethod</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html";>CXXMethodDecl</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasMethod0"><pre>Matches the first method of a class or struct that satisfies InnerMatcher. @@ -5791,8 +5851,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), @@ -5804,9 +5864,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 {}; Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html";>ValueDecl</a>> </pre></td></tr> @@ -5820,10 +5883,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> @@ -6005,8 +6071,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), @@ -6018,9 +6084,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 {}; Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html";>ValueDecl</a>> </pre></td></tr> @@ -6034,10 +6103,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> @@ -7178,10 +7250,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> @@ -7324,8 +7399,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), @@ -7337,9 +7412,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 {}; Usable as: Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr</a>>, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ValueDecl.html";>ValueDecl</a>> </pre></td></tr> @@ -7353,10 +7431,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 cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits