From 82e08bd77609fe8523086177aedd1f0220093811 Mon Sep 17 00:00:00 2001 From: "David L. Jones" Date: Mon, 18 Jun 2018 09:23:08 +0000 Subject: [PATCH] [ASTMatchers] Add support for matching the type of a friend decl. This allows matchers like: friendDecl(hasType(cxxRecordDecl(...))) friendDecl(hasType(asString(...))) It seems that hasType is probably the most reasonable narrowing matcher to overload, since it is already used to narrow to other declaration kinds. Differential Revision: https://reviews.llvm.org/D48242 Reviewers: klimek, aaron.ballman Subscribers: cfe-commits llvm-svn: 334930 --- clang/include/clang/ASTMatchers/ASTMatchers.h | 21 ++++++++++++------- .../clang/ASTMatchers/ASTMatchersInternal.h | 7 ++++++- .../ASTMatchers/ASTMatchersNodeTest.cpp | 10 +++++++++ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index d8a40a9af6d7..87a971082b32 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -2860,13 +2860,17 @@ AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher, InnerMatcher, /// 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")) /// \code /// class X {}; /// void y(X &x) { x; X z; } /// typedef int U; +/// class Y { friend class X; }; /// \endcode AST_POLYMORPHIC_MATCHER_P_OVERLOAD( - hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, TypedefNameDecl, ValueDecl), + hasType, + AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, TypedefNameDecl, + ValueDecl), internal::Matcher, InnerMatcher, 0) { QualType QT = internal::getUnderlyingType(Node); if (!QT.isNull()) @@ -2885,18 +2889,21 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD( /// /// 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")) /// \code /// class X {}; /// void y(X &x) { x; X z; } +/// class Y { friend class X; }; /// \endcode /// /// Usable as: Matcher, Matcher -AST_POLYMORPHIC_MATCHER_P_OVERLOAD(hasType, - AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, - ValueDecl), - internal::Matcher, InnerMatcher, 1) { - return qualType(hasDeclaration(InnerMatcher)) - .matches(Node.getType(), Finder, Builder); +AST_POLYMORPHIC_MATCHER_P_OVERLOAD( + hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, ValueDecl), + internal::Matcher, InnerMatcher, 1) { + QualType QT = internal::getUnderlyingType(Node); + if (!QT.isNull()) + return qualType(hasDeclaration(InnerMatcher)).matches(QT, Finder, Builder); + return false; } /// Matches if the type location of the declarator decl's type matches diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index ead0f83c011c..c5ca6188a222 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -38,6 +38,7 @@ #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclFriend.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -120,10 +121,14 @@ inline QualType getUnderlyingType(const Expr &Node) { return Node.getType(); } inline QualType getUnderlyingType(const ValueDecl &Node) { return Node.getType(); } - inline QualType getUnderlyingType(const TypedefNameDecl &Node) { return Node.getUnderlyingType(); } +inline QualType getUnderlyingType(const FriendDecl &Node) { + if (const TypeSourceInfo *TSI = Node.getFriendType()) + return TSI->getType(); + return QualType(); +} /// Unifies obtaining the FunctionProtoType pointer from both /// FunctionProtoType and FunctionDecl nodes.. diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 6b701bfb7bb3..8947ccde7a47 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -160,6 +160,16 @@ TEST(ValueDecl, Matches) { valueDecl(hasType(asString("void (void)"))))); } +TEST(FriendDecl, Matches) { + EXPECT_TRUE(matches("class Y { friend class X; };", + friendDecl(hasType(asString("class X"))))); + EXPECT_TRUE(matches("class Y { friend class X; };", + friendDecl(hasType(recordDecl(hasName("X")))))); + + EXPECT_TRUE(matches("class Y { friend void f(); };", + functionDecl(hasName("f"), hasParent(friendDecl())))); +} + TEST(Enum, DoesNotMatchClasses) { EXPECT_TRUE(notMatches("class X {};", enumDecl(hasName("X")))); }