diff options
Diffstat (limited to 'include/clang/ASTMatchers')
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchFinder.h | 85 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchers.h | 573 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchersInternal.h | 241 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchersMacros.h | 284 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTTypeTraits.h | 209 |
5 files changed, 872 insertions, 520 deletions
diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h index 30b4050..870a39b 100644 --- a/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -56,6 +56,10 @@ namespace ast_matchers { /// that will trigger the callbacks specified via addMatcher(...) when a match /// is found. /// +/// The order of matches is guaranteed to be equivalent to doing a pre-order +/// traversal on the AST, and applying the matchers in the order in which they +/// were added to the MatchFinder. +/// /// See ASTMatchers.h for more information about how to create matchers. /// /// Not intended to be subclassed. @@ -130,11 +134,17 @@ public: /// \brief Creates a clang ASTConsumer that finds all matches. clang::ASTConsumer *newASTConsumer(); - /// \brief Finds all matches on the given \c Node. + /// \brief Calls the registered callbacks on all matches on the given \p Node. + /// + /// Note that there can be multiple matches on a single node, for + /// example when using decl(forEachDescendant(stmt())). /// /// @{ - void findAll(const Decl &Node, ASTContext &Context); - void findAll(const Stmt &Node, ASTContext &Context); + template <typename T> void match(const T &Node, ASTContext &Context) { + match(clang::ast_type_traits::DynTypedNode::create(Node), Context); + } + void match(const clang::ast_type_traits::DynTypedNode &Node, + ASTContext &Context); /// @} /// \brief Registers a callback to notify the end of parsing. @@ -154,6 +164,75 @@ private: ParsingDoneTestCallback *ParsingDone; }; +/// \brief Returns the results of matching \p Matcher on \p Node. +/// +/// Collects the \c BoundNodes of all callback invocations when matching +/// \p Matcher on \p Node and returns the collected results. +/// +/// Multiple results occur when using matchers like \c forEachDescendant, +/// which generate a result for each sub-match. +/// +/// \see selectFirst +/// @{ +template <typename MatcherT, typename NodeT> +SmallVector<BoundNodes, 1> +match(MatcherT Matcher, const NodeT &Node, ASTContext &Context); + +template <typename MatcherT> +SmallVector<BoundNodes, 1> +match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, + ASTContext &Context); +/// @} + +/// \brief Returns the first result of type \c NodeT bound to \p BoundTo. +/// +/// Returns \c NULL if there is no match, or if the matching node cannot be +/// casted to \c NodeT. +/// +/// This is useful in combanation with \c match(): +/// \code +/// Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"), +/// Node, Context)); +/// \endcode +template <typename NodeT> +NodeT * +selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) { + for (SmallVectorImpl<BoundNodes>::const_iterator I = Results.begin(), + E = Results.end(); + I != E; ++I) { + if (NodeT *Node = I->getNodeAs<NodeT>(BoundTo)) + return Node; + } + return NULL; +} + +namespace internal { +class CollectMatchesCallback : public MatchFinder::MatchCallback { +public: + virtual void run(const MatchFinder::MatchResult &Result) { + Nodes.push_back(Result.Nodes); + } + SmallVector<BoundNodes, 1> Nodes; +}; +} + +template <typename MatcherT> +SmallVector<BoundNodes, 1> +match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, + ASTContext &Context) { + internal::CollectMatchesCallback Callback; + MatchFinder Finder; + Finder.addMatcher(Matcher, &Callback); + Finder.match(Node, Context); + return Callback.Nodes; +} + +template <typename MatcherT, typename NodeT> +SmallVector<BoundNodes, 1> +match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) { + return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context); +} + } // end namespace ast_matchers } // end namespace clang diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index a70dd5c..f10addc 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -142,7 +142,7 @@ inline internal::PolymorphicMatcherWithParam0<internal::TrueMatcher> anything() /// friend X; /// }; /// \endcode -const internal::VariadicDynCastAllOfMatcher<Decl, Decl> decl; +const internal::VariadicAllOfMatcher<Decl> decl; /// \brief Matches a declaration of anything that could have a name. /// @@ -192,6 +192,69 @@ const internal::VariadicDynCastAllOfMatcher< Decl, ClassTemplateSpecializationDecl> classTemplateSpecializationDecl; +/// \brief Matches C++ access specifier declarations. +/// +/// Given +/// \code +/// class C { +/// public: +/// int a; +/// }; +/// \endcode +/// accessSpecDecl() +/// matches 'public:' +const internal::VariadicDynCastAllOfMatcher< + Decl, + AccessSpecDecl> accessSpecDecl; + +/// \brief Matches public C++ declarations. +/// +/// Given +/// \code +/// class C { +/// public: int a; +/// protected: int b; +/// private: int c; +/// }; +/// \endcode +/// fieldDecl(isPublic()) +/// matches 'int a;' +AST_MATCHER(Decl, isPublic) { + return Node.getAccess() == AS_public; +} + +/// \brief Matches protected C++ declarations. +/// +/// Given +/// \code +/// class C { +/// public: int a; +/// protected: int b; +/// private: int c; +/// }; +/// \endcode +/// fieldDecl(isProtected()) +/// matches 'int b;' +AST_MATCHER(Decl, isProtected) { + return Node.getAccess() == AS_protected; +} + +/// \brief Matches private C++ declarations. +/// +/// Given +/// \code +/// class C { +/// public: int a; +/// protected: int b; +/// private: int c; +/// }; +/// \endcode +/// fieldDecl(isPrivate()) +/// matches 'int c;' +AST_MATCHER(Decl, isPrivate) { + return Node.getAccess() == AS_private; +} + /// \brief Matches classTemplateSpecializations that have at least one /// TemplateArgument matching the given InnerMatcher. /// @@ -453,7 +516,7 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode /// stmt() /// matches both the compound statement '{ ++a; }' and '++a'. -const internal::VariadicDynCastAllOfMatcher<Stmt, Stmt> stmt; +const internal::VariadicAllOfMatcher<Stmt> stmt; /// \brief Matches declaration statements. /// @@ -922,6 +985,16 @@ const internal::VariadicDynCastAllOfMatcher< Stmt, UserDefinedLiteral> userDefinedLiteral; +/// \brief Matches compound (i.e. non-scalar) literals +/// +/// Example match: {1}, (1, 2) +/// \code +/// int array[4] = {1}; vector int myvec = (vector int)(1, 2); +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CompoundLiteralExpr> compoundLiteralExpr; + /// \brief Matches nullptr literal. const internal::VariadicDynCastAllOfMatcher< Stmt, @@ -1090,10 +1163,36 @@ const internal::VariadicDynCastAllOfMatcher< const internal::VariadicAllOfMatcher<QualType> qualType; /// \brief Matches \c Types in the clang AST. -const internal::VariadicDynCastAllOfMatcher<Type, Type> type; +const internal::VariadicAllOfMatcher<Type> type; /// \brief Matches \c TypeLocs in the clang AST. -const internal::VariadicDynCastAllOfMatcher<TypeLoc, TypeLoc> typeLoc; +const internal::VariadicAllOfMatcher<TypeLoc> typeLoc; + +/// \brief Matches if any of the given matchers matches. +/// +/// Unlike \c anyOf, \c eachOf will generate a match result for each +/// matching submatcher. +/// +/// For example, in: +/// \code +/// class A { int a; int b; }; +/// \endcode +/// The matcher: +/// \code +/// recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")), +/// has(fieldDecl(hasName("b")).bind("v")))) +/// \endcode +/// will generate two results binding "v", the first of which binds +/// the field declaration of \c a, the second the field declaration of +/// \c b. +/// +/// Usable as: Any Matcher +template <typename M1, typename M2> +internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher, M1, M2> +eachOf(const M1 &P1, const M2 &P2) { + return internal::PolymorphicMatcherWithParam2<internal::EachOfMatcher, M1, + M2>(P1, P2); +} /// \brief Various overloads for the anyOf matcher. /// @{ @@ -1139,18 +1238,40 @@ anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) { /// \brief Matches if all given matchers match. /// /// Usable as: Any Matcher -template<typename M1, typename M2> +template <typename M1, typename M2> internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, M2> allOf(const M1 &P1, const M2 &P2) { - return internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, - M1, M2>(P1, P2); + return internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, M2>( + P1, P2); } -template<typename M1, typename M2, typename M3> -internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M1, +template <typename M1, typename M2, typename M3> +internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M1, internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M2, M3> > allOf(const M1 &P1, const M2 &P2, const M3 &P3) { return allOf(P1, allOf(P2, P3)); } +template <typename M1, typename M2, typename M3, typename M4> +internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M1, + internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M2, internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M3, M4> > > +allOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) { + return allOf(P1, allOf(P2, P3, P4)); +} +template <typename M1, typename M2, typename M3, typename M4, typename M5> +internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M1, + internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M2, + internal::PolymorphicMatcherWithParam2< + internal::AllOfMatcher, M3, + internal::PolymorphicMatcherWithParam2<internal::AllOfMatcher, M4, + M5> > > > +allOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) { + return allOf(P1, allOf(P2, P3, P4, P5)); +} /// @} @@ -1198,7 +1319,7 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) { /// alignof. inline internal::Matcher<Stmt> alignOfExpr( const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) { - return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf( + return stmt(unaryExprOrTypeTraitExpr(allOf( ofKind(UETT_AlignOf), InnerMatcher))); } @@ -1206,8 +1327,8 @@ inline internal::Matcher<Stmt> alignOfExpr( /// sizeof. inline internal::Matcher<Stmt> sizeOfExpr( const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) { - return internal::Matcher<Stmt>(unaryExprOrTypeTraitExpr(allOf( - ofKind(UETT_SizeOf), InnerMatcher))); + return stmt(unaryExprOrTypeTraitExpr( + allOf(ofKind(UETT_SizeOf), InnerMatcher))); } /// \brief Matches NamedDecl nodes that have the specified name. @@ -1228,8 +1349,8 @@ inline internal::Matcher<Stmt> sizeOfExpr( AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { assert(!Name.empty()); const std::string FullNameString = "::" + Node.getQualifiedNameAsString(); - const llvm::StringRef FullName = FullNameString; - const llvm::StringRef Pattern = Name; + const StringRef FullName = FullNameString; + const StringRef Pattern = Name; if (Pattern.startswith("::")) { return FullName == Pattern; } else { @@ -1237,8 +1358,8 @@ AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { } } -/// \brief Matches NamedDecl nodes whose full names partially match the -/// given RegExp. +/// \brief Matches NamedDecl nodes whose fully qualified names contain +/// a substring matched by the given RegExp. /// /// Supports specifying enclosing namespaces or classes by /// prefixing the name with '<enclosing>::'. Does not match typedefs @@ -1263,18 +1384,26 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { /// \brief Matches overloaded operator names. /// /// Matches overloaded operator names specified in strings without the -/// "operator" prefix, such as "<<", for OverloadedOperatorCall's. +/// "operator" prefix: e.g. "<<". /// -/// Example matches a << b -/// (matcher == operatorCallExpr(hasOverloadedOperatorName("<<"))) +/// Given: /// \code -/// a << b; -/// c && d; // assuming both operator<< -/// // and operator&& are overloaded somewhere. +/// class A { int operator*(); }; +/// const A &operator<<(const A &a, const A &b); +/// A a; +/// a << a; // <-- This matches /// \endcode -AST_MATCHER_P(CXXOperatorCallExpr, - hasOverloadedOperatorName, std::string, Name) { - return getOperatorSpelling(Node.getOperator()) == Name; +/// +/// \c operatorCallExpr(hasOverloadedOperatorName("<<"))) matches the specified +/// line and \c recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches +/// the declaration of \c A. +/// +/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<CXXMethodDecl> +inline internal::PolymorphicMatcherWithParam1< + internal::HasOverloadedOperatorNameMatcher, StringRef> +hasOverloadedOperatorName(const StringRef Name) { + return internal::PolymorphicMatcherWithParam1< + internal::HasOverloadedOperatorNameMatcher, StringRef>(Name); } /// \brief Matches C++ classes that are directly or indirectly derived from @@ -1324,6 +1453,27 @@ inline internal::Matcher<CXXRecordDecl> isSameOrDerivedFrom( return isSameOrDerivedFrom(hasName(BaseName)); } +/// \brief Matches the first method of a class or struct that satisfies \c +/// InnerMatcher. +/// +/// Given: +/// \code +/// class A { void func(); }; +/// class B { void member(); }; +/// \code +/// +/// \c recordDecl(hasMethod(hasName("func"))) matches the declaration of \c A +/// but not \c B. +AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>, + InnerMatcher) { + for (CXXRecordDecl::method_iterator I = Node.method_begin(), + E = Node.method_end(); + I != E; ++I) + if (InnerMatcher.matches(**I, Finder, Builder)) + return true; + return false; +} + /// \brief Matches AST nodes that have child AST nodes that match the /// provided matcher. /// @@ -1424,6 +1574,29 @@ forEachDescendant( DescendantT>(DescendantMatcher); } +/// \brief Matches if the node or any descendant matches. +/// +/// Generates results for each match. +/// +/// For example, in: +/// \code +/// class A { class B {}; class C {}; }; +/// \endcode +/// The matcher: +/// \code +/// recordDecl(hasName("::A"), findAll(recordDecl(isDefinition()).bind("m"))) +/// \endcode +/// will generate results for \c A, \c B and \c C. +/// +/// Usable as: Any Matcher +template <typename T> +internal::PolymorphicMatcherWithParam2< + internal::EachOfMatcher, internal::Matcher<T>, + internal::ArgumentAdaptingMatcher<internal::ForEachDescendantMatcher, T> > +findAll(const internal::Matcher<T> &Matcher) { + return eachOf(Matcher, forEachDescendant(Matcher)); +} + /// \brief Matches AST nodes that have a parent that matches the provided /// matcher. /// @@ -1480,8 +1653,13 @@ unless(const M &InnerMatcher) { /// \brief Matches a type if the declaration of the type matches the given /// 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>, -/// Matcher<MemberExpr> +/// Matcher<MemberExpr>, Matcher<TypedefType>, +/// Matcher<TemplateSpecializationType> inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, internal::Matcher<Decl> > hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) { @@ -1501,9 +1679,8 @@ inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, /// FIXME: Overload to allow directly matching types? AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>, InnerMatcher) { - const Expr *ExprNode = const_cast<CXXMemberCallExpr&>(Node) - .getImplicitObjectArgument() - ->IgnoreParenImpCasts(); + const Expr *ExprNode = Node.getImplicitObjectArgument() + ->IgnoreParenImpCasts(); return (ExprNode != NULL && InnerMatcher.matches(*ExprNode, Finder, Builder)); } @@ -1541,7 +1718,7 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>, /// \endcode inline internal::Matcher<CallExpr> callee( const internal::Matcher<Decl> &InnerMatcher) { - return internal::Matcher<CallExpr>(hasDeclaration(InnerMatcher)); + return callExpr(hasDeclaration(InnerMatcher)); } /// \brief Matches if the expression's or declaration's type matches a type @@ -1579,11 +1756,10 @@ AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher<QualType>, /// /// Usable as: Matcher<Expr>, Matcher<ValueDecl> inline internal::PolymorphicMatcherWithParam1< - internal::matcher_hasTypeMatcher, + internal::matcher_hasType0Matcher, internal::Matcher<QualType> > hasType(const internal::Matcher<Decl> &InnerMatcher) { - return hasType(internal::Matcher<QualType>( - hasDeclaration(InnerMatcher))); + return hasType(qualType(hasDeclaration(InnerMatcher))); } /// \brief Matches if the matched type is represented by the given string. @@ -1618,8 +1794,7 @@ AST_MATCHER_P( /// \brief Overloaded to match the pointee type's declaration. inline internal::Matcher<QualType> pointsTo( const internal::Matcher<Decl> &InnerMatcher) { - return pointsTo(internal::Matcher<QualType>( - hasDeclaration(InnerMatcher))); + return pointsTo(qualType(hasDeclaration(InnerMatcher))); } /// \brief Matches if the matched type is a reference type and the referenced @@ -1640,17 +1815,32 @@ AST_MATCHER_P(QualType, references, internal::Matcher<QualType>, InnerMatcher.matches(Node->getPointeeType(), Finder, Builder)); } +/// \brief Matches QualTypes whose canonical type matches InnerMatcher. +/// +/// Given: +/// \code +/// typedef int &int_ref; +/// int a; +/// int_ref b = a; +/// \code +/// +/// \c varDecl(hasType(qualType(referenceType()))))) will not match the +/// declaration of b but \c +/// varDecl(hasType(qualType(hasCanonicalType(referenceType())))))) does. +AST_MATCHER_P(QualType, hasCanonicalType, internal::Matcher<QualType>, + InnerMatcher) { + return InnerMatcher.matches(Node.getCanonicalType(), Finder, Builder); +} + /// \brief Overloaded to match the referenced type's declaration. inline internal::Matcher<QualType> references( const internal::Matcher<Decl> &InnerMatcher) { - return references(internal::Matcher<QualType>( - hasDeclaration(InnerMatcher))); + return references(qualType(hasDeclaration(InnerMatcher))); } AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument, internal::Matcher<Expr>, InnerMatcher) { - const Expr *ExprNode = - const_cast<CXXMemberCallExpr&>(Node).getImplicitObjectArgument(); + const Expr *ExprNode = Node.getImplicitObjectArgument(); return (ExprNode != NULL && InnerMatcher.matches(*ExprNode, Finder, Builder)); } @@ -1705,8 +1895,7 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>, AST_MATCHER_P(DeclRefExpr, throughUsingDecl, internal::Matcher<UsingShadowDecl>, InnerMatcher) { const NamedDecl *FoundDecl = Node.getFoundDecl(); - if (const UsingShadowDecl *UsingDecl = - llvm::dyn_cast<UsingShadowDecl>(FoundDecl)) + if (const UsingShadowDecl *UsingDecl = dyn_cast<UsingShadowDecl>(FoundDecl)) return InnerMatcher.matches(*UsingDecl, Finder, Builder); return false; } @@ -1974,6 +2163,19 @@ AST_MATCHER_P(FunctionDecl, hasAnyParameter, return false; } +/// \brief Matches \c FunctionDecls that have a specific parameter count. +/// +/// Given +/// \code +/// void f(int i) {} +/// void g(int i, int j) {} +/// \endcode +/// functionDecl(parameterCountIs(2)) +/// matches g(int i, int j) {} +AST_MATCHER_P(FunctionDecl, parameterCountIs, unsigned, N) { + return Node.getNumParams() == N; +} + /// \brief Matches the return type of a function declaration. /// /// Given: @@ -2279,10 +2481,13 @@ AST_MATCHER_P(ConditionalOperator, hasFalseExpression, /// \endcode /// /// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl> -inline internal::PolymorphicMatcherWithParam0<internal::IsDefinitionMatcher> -isDefinition() { - return internal::PolymorphicMatcherWithParam0< - internal::IsDefinitionMatcher>(); +AST_POLYMORPHIC_MATCHER(isDefinition) { + TOOLING_COMPILE_ASSERT( + (llvm::is_base_of<TagDecl, NodeType>::value) || + (llvm::is_base_of<VarDecl, NodeType>::value) || + (llvm::is_base_of<FunctionDecl, NodeType>::value), + is_definition_requires_isThisDeclarationADefinition_method); + return Node.isThisDeclarationADefinition(); } /// \brief Matches the class declaration that the given method declaration @@ -2324,8 +2529,8 @@ AST_MATCHER_P(CXXMethodDecl, ofClass, /// \endcode /// memberExpr(isArrow()) /// matches this->x, x, y.x, a, this->b -inline internal::Matcher<MemberExpr> isArrow() { - return makeMatcher(new internal::IsArrowMatcher()); +AST_MATCHER(MemberExpr, isArrow) { + return Node.isArrow(); } /// \brief Matches QualType nodes that are of integer type. @@ -2357,8 +2562,25 @@ AST_MATCHER(QualType, isInteger) { /// matches "void b(int const)", "void c(const int)" and /// "void e(int const) {}". It does not match d as there /// is no top-level const on the parameter type "const int *". -inline internal::Matcher<QualType> isConstQualified() { - return makeMatcher(new internal::IsConstQualifiedMatcher()); +AST_MATCHER(QualType, isConstQualified) { + return Node.isConstQualified(); +} + +/// \brief Matches QualType nodes that have local CV-qualifiers attached to +/// the node, not hidden within a typedef. +/// +/// Given +/// \code +/// typedef const int const_int; +/// const_int i; +/// int *const j; +/// int *volatile k; +/// int m; +/// \endcode +/// \c varDecl(hasType(hasLocalQualifiers())) matches only \c j and \c k. +/// \c i is const-qualified but the qualifier is not local. +AST_MATCHER(QualType, hasLocalQualifiers) { + return Node.hasLocalQualifiers(); } /// \brief Matches a member expression where the member is matched by a @@ -2454,11 +2676,14 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl, /// does not match, as X<A> is an explicit template specialization. /// /// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl> -inline internal::PolymorphicMatcherWithParam0< - internal::IsTemplateInstantiationMatcher> -isTemplateInstantiation() { - return internal::PolymorphicMatcherWithParam0< - internal::IsTemplateInstantiationMatcher>(); +AST_POLYMORPHIC_MATCHER(isTemplateInstantiation) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) || + (llvm::is_base_of<VarDecl, NodeType>::value) || + (llvm::is_base_of<CXXRecordDecl, NodeType>::value), + requires_getTemplateSpecializationKind_method); + return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation || + Node.getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition); } /// \brief Matches explicit template specializations of function, class, or @@ -2473,11 +2698,12 @@ isTemplateInstantiation() { /// matches the specialization A<int>(). /// /// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl> -inline internal::PolymorphicMatcherWithParam0< - internal::IsExplicitTemplateSpecializationMatcher> -isExplicitTemplateSpecialization() { - return internal::PolymorphicMatcherWithParam0< - internal::IsExplicitTemplateSpecializationMatcher>(); +AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization) { + TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, NodeType>::value) || + (llvm::is_base_of<VarDecl, NodeType>::value) || + (llvm::is_base_of<CXXRecordDecl, NodeType>::value), + requires_getTemplateSpecializationKind_method); + return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization); } /// \brief Matches \c TypeLocs for which the given inner @@ -2685,6 +2911,32 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType); /// matches "int (*f)(int)" and the type of "g". AST_TYPE_MATCHER(FunctionType, functionType); +/// \brief Matches \c ParenType nodes. +/// +/// Given +/// \code +/// int (*ptr_to_array)[4]; +/// int *array_of_ptrs[4]; +/// \endcode +/// +/// \c varDecl(hasType(pointsTo(parenType()))) matches \c ptr_to_array but not +/// \c array_of_ptrs. +AST_TYPE_MATCHER(ParenType, parenType); + +/// \brief Matches \c ParenType nodes where the inner type is a specific type. +/// +/// Given +/// \code +/// int (*ptr_to_array)[4]; +/// int (*ptr_to_func)(int); +/// \endcode +/// +/// \c varDecl(hasType(pointsTo(parenType(innerType(functionType()))))) matches +/// \c ptr_to_func but not \c ptr_to_array. +/// +/// Usable as: Matcher<ParenType> +AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType); + /// \brief Matches block pointer types, i.e. types syntactically represented as /// "void (^)(int)". /// @@ -2713,18 +2965,56 @@ AST_TYPE_MATCHER(MemberPointerType, memberPointerType); /// matches "int *a" AST_TYPE_MATCHER(PointerType, pointerType); -/// \brief Matches reference types. +/// \brief Matches both lvalue and rvalue reference types. /// /// Given /// \code /// int *a; /// int &b = *a; -/// int c = 5; +/// int &&c = 1; +/// auto &d = b; +/// auto &&e = c; +/// auto &&f = 2; +/// int g = 5; /// \endcode -/// pointerType() -/// matches "int &b" +/// +/// \c referenceType() matches the types of \c b, \c c, \c d, \c e, and \c f. AST_TYPE_MATCHER(ReferenceType, referenceType); +/// \brief Matches lvalue reference types. +/// +/// Given: +/// \code +/// int *a; +/// int &b = *a; +/// int &&c = 1; +/// auto &d = b; +/// auto &&e = c; +/// auto &&f = 2; +/// int g = 5; +/// \endcode +/// +/// \c lValueReferenceType() matches the types of \c b, \c d, and \c e. \c e is +/// matched since the type is deduced as int& by reference collapsing rules. +AST_TYPE_MATCHER(LValueReferenceType, lValueReferenceType); + +/// \brief Matches rvalue reference types. +/// +/// Given: +/// \code +/// int *a; +/// int &b = *a; +/// int &&c = 1; +/// auto &d = b; +/// auto &&e = c; +/// auto &&f = 2; +/// int g = 5; +/// \endcode +/// +/// \c rValueReferenceType() matches the types of \c c and \c f. \c e is not +/// matched as it is deduced to int& by reference collapsing rules. +AST_TYPE_MATCHER(RValueReferenceType, rValueReferenceType); + /// \brief Narrows PointerType (and similar) matchers to those where the /// \c pointee matches a given matcher. /// @@ -2751,11 +3041,116 @@ AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee); /// matches "typedef int X" 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 template specialization types. +/// +/// Given +/// \code +/// template <typename T> +/// class C { }; +/// +/// template class C<int>; // A +/// C<char> var; // B +/// \code +/// +/// \c templateSpecializationType() matches the type of the explicit +/// 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 if the qualifier exists. +/// +/// 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) { + if (const NestedNameSpecifier *Qualifier = Node.getQualifier()) + return InnerMatcher.matches(*Qualifier, Finder, Builder); + + return false; +} + +/// \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. @@ -2828,10 +3223,13 @@ AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc, /// \endcode /// nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A")))) and /// matches "A::" -inline internal::Matcher<NestedNameSpecifier> hasPrefix( - const internal::Matcher<NestedNameSpecifier> &InnerMatcher) { - return internal::makeMatcher( - new internal::NestedNameSpecifierPrefixMatcher(InnerMatcher)); +AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix, + internal::Matcher<NestedNameSpecifier>, InnerMatcher, + 0) { + NestedNameSpecifier *NextNode = Node.getPrefix(); + if (NextNode == NULL) + return false; + return InnerMatcher.matches(*NextNode, Finder, Builder); } /// \brief Matches on the prefix of a \c NestedNameSpecifierLoc. @@ -2843,10 +3241,13 @@ inline internal::Matcher<NestedNameSpecifier> hasPrefix( /// \endcode /// nestedNameSpecifierLoc(hasPrefix(loc(specifiesType(asString("struct A"))))) /// matches "A::" -inline internal::Matcher<NestedNameSpecifierLoc> hasPrefix( - const internal::Matcher<NestedNameSpecifierLoc> &InnerMatcher) { - return internal::makeMatcher( - new internal::NestedNameSpecifierLocPrefixMatcher(InnerMatcher)); +AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix, + internal::Matcher<NestedNameSpecifierLoc>, InnerMatcher, + 1) { + NestedNameSpecifierLoc NextNode = Node.getPrefix(); + if (!NextNode) + return false; + return InnerMatcher.matches(NextNode, Finder, Builder); } /// \brief Matches nested name specifiers that specify a namespace matching the @@ -2866,6 +3267,26 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace, return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder); } +/// \brief Overloads for the \c equalsNode matcher. +/// FIXME: Implement for other node types. +/// @{ + +/// \brief Matches if a node equals another node. +/// +/// \c Decl has pointer identity in the AST. +AST_MATCHER_P_OVERLOAD(Decl, equalsNode, Decl*, Other, 0) { + return &Node == Other; +} +/// \brief Matches if a node equals another node. +/// +/// \c Stmt has pointer identity in the AST. +/// +AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, Stmt*, Other, 1) { + return &Node == Other; +} + +/// @} + } // end namespace ast_matchers } // end namespace clang diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index e5365ff..30691ad 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -35,13 +35,13 @@ #ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H #define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H -#include "clang/AST/Decl.h" +#include "clang/AST/ASTTypeTraits.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/Decl.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" +#include "clang/AST/Stmt.h" #include "clang/AST/Type.h" -#include "clang/ASTMatchers/ASTTypeTraits.h" #include "llvm/ADT/VariadicFunction.h" #include "llvm/Support/type_traits.h" #include <map> @@ -193,7 +193,7 @@ class ASTMatchFinder; /// current node and doesn't care about its children or descendants, /// implement SingleNodeMatcherInterface instead. template <typename T> -class MatcherInterface : public llvm::RefCountedBaseVPTR { +class MatcherInterface : public RefCountedBaseVPTR { public: virtual ~MatcherInterface() {} @@ -343,7 +343,7 @@ private: const Matcher<Base> From; }; - llvm::IntrusiveRefCntPtr< MatcherInterface<T> > Implementation; + IntrusiveRefCntPtr< MatcherInterface<T> > Implementation; }; // class Matcher /// \brief A convenient helper for creating a Matcher<T> without specifying @@ -353,6 +353,61 @@ inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) { return Matcher<T>(Implementation); } +/// \brief Metafunction to determine if type T has a member called getDecl. +template <typename T> struct has_getDecl { + struct Default { int getDecl; }; + struct Derived : T, Default { }; + + template<typename C, C> struct CheckT; + + // If T::getDecl exists, an ambiguity arises and CheckT will + // not be instantiable. This makes f(...) the only available + // overload. + template<typename C> + static char (&f(CheckT<int Default::*, &C::getDecl>*))[1]; + template<typename C> static char (&f(...))[2]; + + static bool const value = sizeof(f<Derived>(0)) == 2; +}; + +/// \brief Matches overloaded operators with a specific name. +/// +/// The type argument ArgT is not used by this matcher but is used by +/// PolymorphicMatcherWithParam1 and should be StringRef. +template <typename T, typename ArgT> +class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> { + TOOLING_COMPILE_ASSERT((llvm::is_same<T, CXXOperatorCallExpr>::value || + llvm::is_same<T, CXXMethodDecl>::value), + unsupported_class_for_matcher); + TOOLING_COMPILE_ASSERT((llvm::is_same<ArgT, StringRef>::value), + argument_type_must_be_StringRef); +public: + explicit HasOverloadedOperatorNameMatcher(const StringRef Name) + : SingleNodeMatcherInterface<T>(), Name(Name) {} + + virtual bool matchesNode(const T &Node) const LLVM_OVERRIDE { + return matchesSpecialized(Node); + } + +private: + + /// \brief CXXOperatorCallExpr exist only for calls to overloaded operators + /// so this function returns true if the call is to an operator of the given + /// name. + bool matchesSpecialized(const CXXOperatorCallExpr &Node) const { + return getOperatorSpelling(Node.getOperator()) == Name; + } + + /// \brief Returns true only if CXXMethodDecl represents an overloaded + /// operator and has the given operator name. + bool matchesSpecialized(const CXXMethodDecl &Node) const { + return Node.isOverloadedOperator() && + getOperatorSpelling(Node.getOverloadedOperator()) == Name; + } + + std::string Name; +}; + /// \brief Matches declarations for QualType and CallExpr. /// /// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but @@ -373,16 +428,36 @@ public: } private: - /// \brief Extracts the CXXRecordDecl of a QualType and returns whether the - /// inner matcher matches on it. + /// \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 + /// whether the inner matcher matches on it. bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { /// FIXME: Add other ways to convert... if (Node.isNull()) return false; + if (const EnumType *AsEnum = dyn_cast<EnumType>(Node.getTypePtr())) + return matchesDecl(AsEnum->getDecl(), Finder, Builder); return matchesDecl(Node->getAsCXXRecordDecl(), Finder, Builder); } + /// \brief Gets the TemplateDecl from a TemplateSpecializationType + /// and returns whether the inner matches on it. + bool matchesSpecialized(const TemplateSpecializationType &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return matchesDecl(Node.getTemplateName().getAsTemplateDecl(), + Finder, Builder); + } + /// \brief Extracts the Decl of the callee of a CallExpr and returns whether /// the inner matcher matches on it. bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder, @@ -537,6 +612,8 @@ public: Matcher, Builder, MatchMode); } + virtual ASTContext &getASTContext() const = 0; + protected: virtual bool matchesChildOf(const ast_type_traits::DynTypedNode &Node, const DynTypedMatcher &Matcher, @@ -672,7 +749,7 @@ public: virtual bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { - const To *InnerMatchValue = llvm::dyn_cast<To>(&Node); + const To *InnerMatchValue = dyn_cast<To>(&Node); return InnerMatchValue != NULL && InnerMatcher.matches(*InnerMatchValue, Finder, Builder); } @@ -828,21 +905,56 @@ private: /// used. They will always be instantiated with types convertible to /// Matcher<T>. template <typename T, typename MatcherT1, typename MatcherT2> +class EachOfMatcher : public MatcherInterface<T> { +public: + EachOfMatcher(const Matcher<T> &InnerMatcher1, + const Matcher<T> &InnerMatcher2) + : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) { + } + + virtual bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + BoundNodesTreeBuilder Builder1; + bool Matched1 = InnerMatcher1.matches(Node, Finder, &Builder1); + if (Matched1) + Builder->addMatch(Builder1.build()); + + BoundNodesTreeBuilder Builder2; + bool Matched2 = InnerMatcher2.matches(Node, Finder, &Builder2); + if (Matched2) + Builder->addMatch(Builder2.build()); + + return Matched1 || Matched2; + } + +private: + const Matcher<T> InnerMatcher1; + const Matcher<T> InnerMatcher2; +}; + +/// \brief Matches nodes of type T for which at least one of the two provided +/// matchers matches. +/// +/// Type arguments MatcherT1 and MatcherT2 are +/// required by PolymorphicMatcherWithParam2 but not actually +/// used. They will always be instantiated with types convertible to +/// Matcher<T>. +template <typename T, typename MatcherT1, typename MatcherT2> class AnyOfMatcher : public MatcherInterface<T> { public: AnyOfMatcher(const Matcher<T> &InnerMatcher1, const Matcher<T> &InnerMatcher2) - : InnerMatcher1(InnerMatcher1), InnertMatcher2(InnerMatcher2) {} + : InnerMatcher1(InnerMatcher1), InnerMatcher2(InnerMatcher2) {} virtual bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return InnerMatcher1.matches(Node, Finder, Builder) || - InnertMatcher2.matches(Node, Finder, Builder); + InnerMatcher2.matches(Node, Finder, Builder); } private: const Matcher<T> InnerMatcher1; - const Matcher<T> InnertMatcher2; + const Matcher<T> InnerMatcher2; }; /// \brief Creates a Matcher<T> that matches if all inner matchers match. @@ -989,69 +1101,6 @@ private: const ValueT ExpectedValue; }; -template <typename T> -class IsDefinitionMatcher : public SingleNodeMatcherInterface<T> { - TOOLING_COMPILE_ASSERT( - (llvm::is_base_of<TagDecl, T>::value) || - (llvm::is_base_of<VarDecl, T>::value) || - (llvm::is_base_of<FunctionDecl, T>::value), - is_definition_requires_isThisDeclarationADefinition_method); -public: - virtual bool matchesNode(const T &Node) const { - return Node.isThisDeclarationADefinition(); - } -}; - -/// \brief Matches on template instantiations for FunctionDecl, VarDecl or -/// CXXRecordDecl nodes. -template <typename T> -class IsTemplateInstantiationMatcher : public MatcherInterface<T> { - TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, T>::value) || - (llvm::is_base_of<VarDecl, T>::value) || - (llvm::is_base_of<CXXRecordDecl, T>::value), - requires_getTemplateSpecializationKind_method); - public: - virtual bool matches(const T& Node, - ASTMatchFinder* Finder, - BoundNodesTreeBuilder* Builder) const { - return (Node.getTemplateSpecializationKind() == - TSK_ImplicitInstantiation || - Node.getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDefinition); - } -}; - -/// \brief Matches on explicit template specializations for FunctionDecl, -/// VarDecl or CXXRecordDecl nodes. -template <typename T> -class IsExplicitTemplateSpecializationMatcher : public MatcherInterface<T> { - TOOLING_COMPILE_ASSERT((llvm::is_base_of<FunctionDecl, T>::value) || - (llvm::is_base_of<VarDecl, T>::value) || - (llvm::is_base_of<CXXRecordDecl, T>::value), - requires_getTemplateSpecializationKind_method); - public: - virtual bool matches(const T& Node, - ASTMatchFinder* Finder, - BoundNodesTreeBuilder* Builder) const { - return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization); - } -}; - -class IsArrowMatcher : public SingleNodeMatcherInterface<MemberExpr> { -public: - virtual bool matchesNode(const MemberExpr &Node) const { - return Node.isArrow(); - } -}; - -class IsConstQualifiedMatcher - : public SingleNodeMatcherInterface<QualType> { - public: - virtual bool matchesNode(const QualType& Node) const { - return Node.isConstQualified(); - } -}; - /// \brief A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a /// variadic functor that takes a number of Matcher<TargetT> and returns a /// Matcher<SourceT> that matches TargetT nodes that are matched by all of the @@ -1115,50 +1164,6 @@ private: const Matcher<T> InnerMatcher; }; -/// \brief Matches \c NestedNameSpecifiers with a prefix matching another -/// \c Matcher<NestedNameSpecifier>. -class NestedNameSpecifierPrefixMatcher - : public MatcherInterface<NestedNameSpecifier> { -public: - explicit NestedNameSpecifierPrefixMatcher( - const Matcher<NestedNameSpecifier> &InnerMatcher) - : InnerMatcher(InnerMatcher) {} - - virtual bool matches(const NestedNameSpecifier &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - NestedNameSpecifier *NextNode = Node.getPrefix(); - if (NextNode == NULL) - return false; - return InnerMatcher.matches(*NextNode, Finder, Builder); - } - -private: - const Matcher<NestedNameSpecifier> InnerMatcher; -}; - -/// \brief Matches \c NestedNameSpecifierLocs with a prefix matching another -/// \c Matcher<NestedNameSpecifierLoc>. -class NestedNameSpecifierLocPrefixMatcher - : public MatcherInterface<NestedNameSpecifierLoc> { -public: - explicit NestedNameSpecifierLocPrefixMatcher( - const Matcher<NestedNameSpecifierLoc> &InnerMatcher) - : InnerMatcher(InnerMatcher) {} - - virtual bool matches(const NestedNameSpecifierLoc &Node, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - NestedNameSpecifierLoc NextNode = Node.getPrefix(); - if (!NextNode) - return false; - return InnerMatcher.matches(NextNode, Finder, Builder); - } - -private: - const Matcher<NestedNameSpecifierLoc> InnerMatcher; -}; - /// \brief Matches \c TypeLocs based on an inner matcher matching a certain /// \c QualType. /// diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h index 953abc2..f5ca26b 100644 --- a/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -49,21 +49,23 @@ /// /// The code should return true if 'Node' matches. #define AST_MATCHER(Type, DefineMatcher) \ + AST_MATCHER_OVERLOAD(Type, DefineMatcher, 0) + +#define AST_MATCHER_OVERLOAD(Type, DefineMatcher, OverloadId) \ namespace internal { \ - class matcher_##DefineMatcher##Matcher \ + class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface<Type> { \ - public: \ - explicit matcher_##DefineMatcher##Matcher() {} \ - virtual bool matches( \ - const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ + public: \ + explicit matcher_##DefineMatcher##OverloadId##Matcher() {} \ + virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ }; \ } \ inline internal::Matcher<Type> DefineMatcher() { \ return internal::makeMatcher( \ - new internal::matcher_##DefineMatcher##Matcher()); \ + new internal::matcher_##DefineMatcher##OverloadId##Matcher()); \ } \ - inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ + inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ const Type &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const @@ -81,24 +83,29 @@ /// /// The code should return true if 'Node' matches. #define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) \ + AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, 0) + +#define AST_MATCHER_P_OVERLOAD(Type, DefineMatcher, ParamType, Param, \ + OverloadId) \ namespace internal { \ - class matcher_##DefineMatcher##Matcher \ + class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface<Type> { \ - public: \ - explicit matcher_##DefineMatcher##Matcher( \ - const ParamType &A##Param) : Param(A##Param) {} \ - virtual bool matches( \ - const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ - private: \ + public: \ + explicit matcher_##DefineMatcher##OverloadId##Matcher( \ + const ParamType &A##Param) \ + : Param(A##Param) { \ + } \ + virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + private: \ const ParamType Param; \ }; \ } \ inline internal::Matcher<Type> DefineMatcher(const ParamType &Param) { \ return internal::makeMatcher( \ - new internal::matcher_##DefineMatcher##Matcher(Param)); \ + new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param)); \ } \ - inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ + inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ const Type &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const @@ -116,33 +123,67 @@ /// Builder: a BoundNodesTreeBuilder*. /// /// The code should return true if 'Node' matches. -#define AST_MATCHER_P2( \ - Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) \ +#define AST_MATCHER_P2(Type, DefineMatcher, ParamType1, Param1, ParamType2, \ + Param2) \ + AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, ParamType2, \ + Param2, 0) + +#define AST_MATCHER_P2_OVERLOAD(Type, DefineMatcher, ParamType1, Param1, \ + ParamType2, Param2, OverloadId) \ namespace internal { \ - class matcher_##DefineMatcher##Matcher \ + class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface<Type> { \ - public: \ - matcher_##DefineMatcher##Matcher( \ - const ParamType1 &A##Param1, const ParamType2 &A##Param2) \ - : Param1(A##Param1), Param2(A##Param2) {} \ - virtual bool matches( \ - const Type &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ - private: \ + public: \ + matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \ + const ParamType2 &A##Param2) \ + : Param1(A##Param1), Param2(A##Param2) { \ + } \ + virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + private: \ const ParamType1 Param1; \ const ParamType2 Param2; \ }; \ } \ - inline internal::Matcher<Type> DefineMatcher( \ - const ParamType1 &Param1, const ParamType2 &Param2) { \ + inline internal::Matcher<Type> \ + DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \ return internal::makeMatcher( \ - new internal::matcher_##DefineMatcher##Matcher( \ - Param1, Param2)); \ + new internal::matcher_##DefineMatcher##OverloadId##Matcher(Param1, \ + Param2)); \ } \ - inline bool internal::matcher_##DefineMatcher##Matcher::matches( \ + inline bool internal::matcher_##DefineMatcher##OverloadId##Matcher::matches( \ const Type &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const +/// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... } +/// defines a single-parameter function named DefineMatcher() that is +/// polymorphic in the return type. +/// +/// The variables are the same as for AST_MATCHER, but NodeType will be deduced +/// from the calling context. +#define AST_POLYMORPHIC_MATCHER(DefineMatcher) \ + AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, 0) + +#define AST_POLYMORPHIC_MATCHER_OVERLOAD(DefineMatcher, OverloadId) \ + namespace internal { \ + template <typename NodeType> \ + class matcher_##DefineMatcher##OverloadId##Matcher \ + : public MatcherInterface<NodeType> { \ + public: \ + virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + }; \ + } \ + inline internal::PolymorphicMatcherWithParam0< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher> DefineMatcher() {\ + return internal::PolymorphicMatcherWithParam0< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher>(); \ + } \ + template <typename NodeType> \ + bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ + NodeType>::matches(const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const + /// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... } /// defines a single-parameter function named DefineMatcher() that is /// polymorphic in the return type. @@ -153,32 +194,36 @@ /// /// FIXME: Pull out common code with above macro? #define AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) \ + AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, 0) + +#define AST_POLYMORPHIC_MATCHER_P_OVERLOAD(DefineMatcher, ParamType, Param, \ + OverloadId) \ namespace internal { \ template <typename NodeType, typename ParamT> \ - class matcher_##DefineMatcher##Matcher \ + class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface<NodeType> { \ - public: \ - explicit matcher_##DefineMatcher##Matcher( \ - const ParamType &A##Param) : Param(A##Param) {} \ - virtual bool matches( \ - const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ - private: \ + public: \ + explicit matcher_##DefineMatcher##OverloadId##Matcher( \ + const ParamType &A##Param) \ + : Param(A##Param) { \ + } \ + virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + private: \ const ParamType Param; \ }; \ } \ inline internal::PolymorphicMatcherWithParam1< \ - internal::matcher_##DefineMatcher##Matcher, \ - ParamType > \ - DefineMatcher(const ParamType &Param) { \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType> \ + DefineMatcher(const ParamType &Param) { \ return internal::PolymorphicMatcherWithParam1< \ - internal::matcher_##DefineMatcher##Matcher, \ - ParamType >(Param); \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType>( \ + Param); \ } \ template <typename NodeType, typename ParamT> \ - bool internal::matcher_##DefineMatcher##Matcher<NodeType, ParamT>::matches( \ - const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const + bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ + NodeType, ParamT>::matches(const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const /// \brief AST_POLYMORPHIC_MATCHER_P2( /// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... } @@ -188,35 +233,39 @@ /// The variables are the same as for AST_MATCHER_P2, with the /// addition of NodeType, which specifies the node type of the matcher /// Matcher<NodeType> returned by the function DefineMatcher(). -#define AST_POLYMORPHIC_MATCHER_P2( \ - DefineMatcher, ParamType1, Param1, ParamType2, Param2) \ +#define AST_POLYMORPHIC_MATCHER_P2(DefineMatcher, ParamType1, Param1, \ + ParamType2, Param2) \ + AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \ + ParamType2, Param2, 0) + +#define AST_POLYMORPHIC_MATCHER_P2_OVERLOAD(DefineMatcher, ParamType1, Param1, \ + ParamType2, Param2, OverloadId) \ namespace internal { \ template <typename NodeType, typename ParamT1, typename ParamT2> \ - class matcher_##DefineMatcher##Matcher \ + class matcher_##DefineMatcher##OverloadId##Matcher \ : public MatcherInterface<NodeType> { \ - public: \ - matcher_##DefineMatcher##Matcher( \ - const ParamType1 &A##Param1, const ParamType2 &A##Param2) \ - : Param1(A##Param1), Param2(A##Param2) {} \ - virtual bool matches( \ - const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const; \ - private: \ + public: \ + matcher_##DefineMatcher##OverloadId##Matcher(const ParamType1 &A##Param1, \ + const ParamType2 &A##Param2) \ + : Param1(A##Param1), Param2(A##Param2) { \ + } \ + virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const; \ + private: \ const ParamType1 Param1; \ const ParamType2 Param2; \ }; \ } \ inline internal::PolymorphicMatcherWithParam2< \ - internal::matcher_##DefineMatcher##Matcher, \ - ParamType1, ParamType2 > \ - DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ + ParamType2> \ + DefineMatcher(const ParamType1 &Param1, const ParamType2 &Param2) { \ return internal::PolymorphicMatcherWithParam2< \ - internal::matcher_##DefineMatcher##Matcher, \ - ParamType1, ParamType2 >( \ - Param1, Param2); \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ + ParamType2>(Param1, Param2); \ } \ template <typename NodeType, typename ParamT1, typename ParamT2> \ - bool internal::matcher_##DefineMatcher##Matcher< \ + bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ NodeType, ParamT1, ParamT2>::matches( \ const NodeType &Node, ASTMatchFinder *Finder, \ BoundNodesTreeBuilder *Builder) const @@ -224,9 +273,9 @@ /// \brief Creates a variadic matcher for both a specific \c Type as well as /// the corresponding \c TypeLoc. #define AST_TYPE_MATCHER(NodeType, MatcherName) \ - const internal::VariadicDynCastAllOfMatcher<Type, NodeType> MatcherName; \ - const internal::VariadicDynCastAllOfMatcher<TypeLoc, \ - NodeType##Loc> MatcherName##Loc + const internal::VariadicDynCastAllOfMatcher<Type, NodeType> MatcherName +// FIXME: add a matcher for TypeLoc derived classes using its custom casting +// API (no longer dyn_cast) if/when we need such matching /// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines /// the matcher \c MatcherName that can be used to traverse from one \c Type @@ -236,54 +285,61 @@ /// \c SpecificType::FunctionName. The existance of such a function determines /// whether a corresponding matcher can be used on \c SpecificType. #define AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) \ -class Polymorphic##MatcherName##TypeMatcher { \ -public: \ - Polymorphic##MatcherName##TypeMatcher( \ - const internal::Matcher<QualType> &InnerMatcher) \ - : InnerMatcher(InnerMatcher) {} \ - template <typename T> operator internal::Matcher<T>() { \ - return internal::Matcher<T>(new internal::TypeTraverseMatcher<T>( \ - InnerMatcher, &T::FunctionName)); \ + class Polymorphic##MatcherName##TypeMatcher { \ + public: \ + Polymorphic##MatcherName##TypeMatcher( \ + const internal::Matcher<QualType> &InnerMatcher) \ + : InnerMatcher(InnerMatcher) { \ + } \ + template <typename T> operator internal:: Matcher< T>() { \ + return internal::Matcher<T>(new internal::TypeTraverseMatcher<T>( \ + InnerMatcher, &T::FunctionName)); \ + } \ + private: \ + const internal::Matcher<QualType> InnerMatcher; \ } \ -private: \ - const internal::Matcher<QualType> InnerMatcher; \ -}; \ -class Variadic##MatcherName##TypeTraverseMatcher \ - : public llvm::VariadicFunction< \ - Polymorphic##MatcherName##TypeMatcher, \ - internal::Matcher<QualType>, \ - internal::makeTypeAllOfComposite< \ - Polymorphic##MatcherName##TypeMatcher, QualType> > { \ -public: \ - Variadic##MatcherName##TypeTraverseMatcher() {} \ -}; \ -const Variadic##MatcherName##TypeTraverseMatcher MatcherName + ; \ + class Variadic##MatcherName##TypeTraverseMatcher \ + : public llvm::VariadicFunction< \ + Polymorphic##MatcherName##TypeMatcher, internal::Matcher<QualType>, \ + internal::makeTypeAllOfComposite< \ + Polymorphic##MatcherName##TypeMatcher, QualType> > { \ + public: \ + Variadic##MatcherName##TypeTraverseMatcher() { \ + } \ + } \ + ; \ + const Variadic##MatcherName##TypeTraverseMatcher MatcherName /// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works /// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs. #define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) \ -class Polymorphic##MatcherName##TypeLocMatcher { \ -public: \ - Polymorphic##MatcherName##TypeLocMatcher( \ - const internal::Matcher<TypeLoc> &InnerMatcher) \ - : InnerMatcher(InnerMatcher) {} \ - template <typename T> operator internal::Matcher<T>() { \ - return internal::Matcher<T>(new internal::TypeLocTraverseMatcher<T>( \ - InnerMatcher, &T::FunctionName##Loc)); \ + class Polymorphic##MatcherName##TypeLocMatcher { \ + public: \ + Polymorphic##MatcherName##TypeLocMatcher( \ + const internal::Matcher<TypeLoc> &InnerMatcher) \ + : InnerMatcher(InnerMatcher) { \ + } \ + template <typename T> operator internal:: Matcher< T>() { \ + return internal::Matcher<T>( \ + new internal::TypeLocTraverseMatcher<T>(InnerMatcher, \ + &T::FunctionName##Loc)); \ + } \ + private: \ + const internal::Matcher<TypeLoc> InnerMatcher; \ + } \ + ; \ + class Variadic##MatcherName##TypeLocTraverseMatcher \ + : public llvm::VariadicFunction< \ + Polymorphic##MatcherName##TypeLocMatcher, internal::Matcher<TypeLoc>,\ + internal::makeTypeAllOfComposite< \ + Polymorphic##MatcherName##TypeLocMatcher, TypeLoc> > { \ + public: \ + Variadic##MatcherName##TypeLocTraverseMatcher() { \ + } \ } \ -private: \ - const internal::Matcher<TypeLoc> InnerMatcher; \ -}; \ -class Variadic##MatcherName##TypeLocTraverseMatcher \ - : public llvm::VariadicFunction< \ - Polymorphic##MatcherName##TypeLocMatcher, \ - internal::Matcher<TypeLoc>, \ - internal::makeTypeAllOfComposite< \ - Polymorphic##MatcherName##TypeLocMatcher, TypeLoc> > { \ -public: \ - Variadic##MatcherName##TypeLocTraverseMatcher() {} \ -}; \ -const Variadic##MatcherName##TypeLocTraverseMatcher MatcherName##Loc; \ -AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type) + ; \ + const Variadic##MatcherName##TypeLocTraverseMatcher MatcherName##Loc; \ + AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type) #endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H diff --git a/include/clang/ASTMatchers/ASTTypeTraits.h b/include/clang/ASTMatchers/ASTTypeTraits.h deleted file mode 100644 index bda53ea..0000000 --- a/include/clang/ASTMatchers/ASTTypeTraits.h +++ /dev/null @@ -1,209 +0,0 @@ -//===--- ASTMatchersTypeTraits.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Provides a dynamically typed node container that can be used to store -// an AST base node at runtime in the same storage in a type safe way. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H -#define LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H - -#include "clang/AST/Decl.h" -#include "clang/AST/Stmt.h" -#include "llvm/Support/AlignOf.h" - -namespace clang { -namespace ast_type_traits { - -/// \brief A dynamically typed AST node container. -/// -/// Stores an AST node in a type safe way. This allows writing code that -/// works with different kinds of AST nodes, despite the fact that they don't -/// have a common base class. -/// -/// Use \c create(Node) to create a \c DynTypedNode from an AST node, -/// and \c get<T>() to retrieve the node as type T if the types match. -/// -/// See \c NodeTypeTag for which node base types are currently supported; -/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of -/// the supported base types. -class DynTypedNode { -public: - /// \brief Creates a \c DynTypedNode from \c Node. - template <typename T> - static DynTypedNode create(const T &Node) { - return BaseConverter<T>::create(Node); - } - - /// \brief Retrieve the stored node as type \c T. - /// - /// Returns NULL if the stored node does not have a type that is - /// convertible to \c T. - /// - /// For types that have identity via their pointer in the AST - /// (like \c Stmt and \c Decl) the returned pointer points to the - /// referenced AST node. - /// For other types (like \c QualType) the value is stored directly - /// in the \c DynTypedNode, and the returned pointer points at - /// the storage inside DynTypedNode. For those nodes, do not - /// use the pointer outside the scope of the DynTypedNode. - template <typename T> - const T *get() const { - return BaseConverter<T>::get(Tag, Storage.buffer); - } - - /// \brief Returns a pointer that identifies the stored AST node. - /// - /// Note that this is not supported by all AST nodes. For AST nodes - /// that don't have a pointer-defined identity inside the AST, this - /// method returns NULL. - const void *getMemoizationData() const; - -private: - /// \brief Takes care of converting from and to \c T. - template <typename T, typename EnablerT = void> struct BaseConverter; - - /// \brief Supported base node types. - enum NodeTypeTag { - NT_Decl, - NT_Stmt, - NT_NestedNameSpecifier, - NT_NestedNameSpecifierLoc, - NT_QualType, - NT_Type, - NT_TypeLoc - } Tag; - - /// \brief Stores the data of the node. - /// - /// Note that we can store \c Decls and \c Stmts by pointer as they are - /// guaranteed to be unique pointers pointing to dedicated storage in the - /// AST. \c QualTypes on the other hand do not have storage or unique - /// pointers and thus need to be stored by value. - llvm::AlignedCharArrayUnion<Decl*, QualType, TypeLoc, NestedNameSpecifierLoc> - Storage; -}; - -// FIXME: Pull out abstraction for the following. -template<typename T> struct DynTypedNode::BaseConverter<T, - typename llvm::enable_if<llvm::is_base_of<Decl, T> >::type> { - static const T *get(NodeTypeTag Tag, const char Storage[]) { - if (Tag == NT_Decl) - return dyn_cast<T>(*reinterpret_cast<Decl*const*>(Storage)); - return NULL; - } - static DynTypedNode create(const Decl &Node) { - DynTypedNode Result; - Result.Tag = NT_Decl; - new (Result.Storage.buffer) const Decl*(&Node); - return Result; - } -}; -template<typename T> struct DynTypedNode::BaseConverter<T, - typename llvm::enable_if<llvm::is_base_of<Stmt, T> >::type> { - static const T *get(NodeTypeTag Tag, const char Storage[]) { - if (Tag == NT_Stmt) - return dyn_cast<T>(*reinterpret_cast<Stmt*const*>(Storage)); - return NULL; - } - static DynTypedNode create(const Stmt &Node) { - DynTypedNode Result; - Result.Tag = NT_Stmt; - new (Result.Storage.buffer) const Stmt*(&Node); - return Result; - } -}; -template<typename T> struct DynTypedNode::BaseConverter<T, - typename llvm::enable_if<llvm::is_base_of<Type, T> >::type> { - static const T *get(NodeTypeTag Tag, const char Storage[]) { - if (Tag == NT_Type) - return dyn_cast<T>(*reinterpret_cast<Type*const*>(Storage)); - return NULL; - } - static DynTypedNode create(const Type &Node) { - DynTypedNode Result; - Result.Tag = NT_Type; - new (Result.Storage.buffer) const Type*(&Node); - return Result; - } -}; -template<> struct DynTypedNode::BaseConverter<NestedNameSpecifier, void> { - static const NestedNameSpecifier *get(NodeTypeTag Tag, const char Storage[]) { - if (Tag == NT_NestedNameSpecifier) - return *reinterpret_cast<NestedNameSpecifier*const*>(Storage); - return NULL; - } - static DynTypedNode create(const NestedNameSpecifier &Node) { - DynTypedNode Result; - Result.Tag = NT_NestedNameSpecifier; - new (Result.Storage.buffer) const NestedNameSpecifier*(&Node); - return Result; - } -}; -template<> struct DynTypedNode::BaseConverter<NestedNameSpecifierLoc, void> { - static const NestedNameSpecifierLoc *get(NodeTypeTag Tag, - const char Storage[]) { - if (Tag == NT_NestedNameSpecifierLoc) - return reinterpret_cast<const NestedNameSpecifierLoc*>(Storage); - return NULL; - } - static DynTypedNode create(const NestedNameSpecifierLoc &Node) { - DynTypedNode Result; - Result.Tag = NT_NestedNameSpecifierLoc; - new (Result.Storage.buffer) NestedNameSpecifierLoc(Node); - return Result; - } -}; -template<> struct DynTypedNode::BaseConverter<QualType, void> { - static const QualType *get(NodeTypeTag Tag, const char Storage[]) { - if (Tag == NT_QualType) - return reinterpret_cast<const QualType*>(Storage); - return NULL; - } - static DynTypedNode create(const QualType &Node) { - DynTypedNode Result; - Result.Tag = NT_QualType; - new (Result.Storage.buffer) QualType(Node); - return Result; - } -}; -template<> struct DynTypedNode::BaseConverter<TypeLoc, void> { - static const TypeLoc *get(NodeTypeTag Tag, const char Storage[]) { - if (Tag == NT_TypeLoc) - return reinterpret_cast<const TypeLoc*>(Storage); - return NULL; - } - static DynTypedNode create(const TypeLoc &Node) { - DynTypedNode Result; - Result.Tag = NT_TypeLoc; - new (Result.Storage.buffer) TypeLoc(Node); - return Result; - } -}; -// The only operation we allow on unsupported types is \c get. -// This allows to conveniently use \c DynTypedNode when having an arbitrary -// AST node that is not supported, but prevents misuse - a user cannot create -// a DynTypedNode from arbitrary types. -template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter { - static const T *get(NodeTypeTag Tag, const char Storage[]) { return NULL; } -}; - -inline const void *DynTypedNode::getMemoizationData() const { - switch (Tag) { - case NT_Decl: return BaseConverter<Decl>::get(Tag, Storage.buffer); - case NT_Stmt: return BaseConverter<Stmt>::get(Tag, Storage.buffer); - default: return NULL; - }; -} - -} // end namespace ast_type_traits -} // end namespace clang - -#endif // LLVM_CLANG_AST_MATCHERS_AST_TYPE_TRAITS_H |