diff options
author | Manuel Klimek <klimek@google.com> | 2013-02-06 20:36:22 +0000 |
---|---|---|
committer | Manuel Klimek <klimek@google.com> | 2013-02-06 20:36:22 +0000 |
commit | 415514d5fbc2761b7f2938aa9112b079249820d6 (patch) | |
tree | 317560e0edd34b305545de75fb25f4f25693d38a | |
parent | 15417ef20e3cda668351c67cc580587913f6bee8 (diff) |
Cleanup of ASTMatcher macros and adding support for overloaded matchers.
This is in preparation for adding other overloaded matchers. This change
alone is a net win in LOC.
I went through all matchers and looked whether we could now encode them
as macro, or simplify them with the matcher atoms that were not
available before.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174540 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/LibASTMatchersReference.html | 36 | ||||
-rw-r--r-- | docs/tools/dump_ast_matchers.py | 3 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchers.h | 84 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchersInternal.h | 107 | ||||
-rw-r--r-- | include/clang/ASTMatchers/ASTMatchersMacros.h | 128 |
5 files changed, 164 insertions, 194 deletions
diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 672c12d9b9..30270835ad 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -361,6 +361,14 @@ Example matches 'a', L'a' </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('compoundLiteralExpr0')"><a name="compoundLiteralExpr0Anchor">compoundLiteralExpr</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>...</td></tr> +<tr><td colspan="4" class="doc" id="compoundLiteralExpr0"><pre>Matches compound (i.e. non-scalar) literals + +Example match: {1}, (1, 2) + int array[4] = {1}; vector int myvec = (vector int)(1, 2); +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('compoundStmt0')"><a name="compoundStmt0Anchor">compoundStmt</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CompoundStmt.html">CompoundStmt</a>>...</td></tr> <tr><td colspan="4" class="doc" id="compoundStmt0"><pre>Matches compound statements. @@ -1291,8 +1299,8 @@ Example matches a << b </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('isExplicitTemplateSpecialization0')"><a name="isExplicitTemplateSpecialization0Anchor">isExplicitTemplateSpecialization</a></td><td></td></tr> -<tr><td colspan="4" class="doc" id="isExplicitTemplateSpecialization0"><pre>Matches explicit template specializations of function, class, or +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('isExplicitTemplateSpecialization2')"><a name="isExplicitTemplateSpecialization2Anchor">isExplicitTemplateSpecialization</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isExplicitTemplateSpecialization2"><pre>Matches explicit template specializations of function, class, or static member variable template instantiations. Given @@ -1311,8 +1319,8 @@ isSameOrDerivedFrom(hasName(...)). </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('isTemplateInstantiation0')"><a name="isTemplateInstantiation0Anchor">isTemplateInstantiation</a></td><td></td></tr> -<tr><td colspan="4" class="doc" id="isTemplateInstantiation0"><pre>Matches template instantiations of function, class, or static +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('isTemplateInstantiation2')"><a name="isTemplateInstantiation2Anchor">isTemplateInstantiation</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isTemplateInstantiation2"><pre>Matches template instantiations of function, class, or static member variable template instantiations. Given @@ -1401,8 +1409,8 @@ Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Charac </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('isDefinition0')"><a name="isDefinition0Anchor">isDefinition</a></td><td></td></tr> -<tr><td colspan="4" class="doc" id="isDefinition0"><pre>Matches if a declaration has a body attached. +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('isDefinition2')"><a name="isDefinition2Anchor">isDefinition</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isDefinition2"><pre>Matches if a declaration has a body attached. Example matches A, va, fa class A {}; @@ -1416,8 +1424,8 @@ Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TagDec </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('isExplicitTemplateSpecialization2')"><a name="isExplicitTemplateSpecialization2Anchor">isExplicitTemplateSpecialization</a></td><td></td></tr> -<tr><td colspan="4" class="doc" id="isExplicitTemplateSpecialization2"><pre>Matches explicit template specializations of function, class, or +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('isExplicitTemplateSpecialization0')"><a name="isExplicitTemplateSpecialization0Anchor">isExplicitTemplateSpecialization</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isExplicitTemplateSpecialization0"><pre>Matches explicit template specializations of function, class, or static member variable template instantiations. Given @@ -1442,8 +1450,8 @@ functionDecl(isExternC()) </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('isTemplateInstantiation2')"><a name="isTemplateInstantiation2Anchor">isTemplateInstantiation</a></td><td></td></tr> -<tr><td colspan="4" class="doc" id="isTemplateInstantiation2"><pre>Matches template instantiations of function, class, or static +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>></td><td class="name" onclick="toggle('isTemplateInstantiation0')"><a name="isTemplateInstantiation0Anchor">isTemplateInstantiation</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isTemplateInstantiation0"><pre>Matches template instantiations of function, class, or static member variable template instantiations. Given @@ -1573,8 +1581,8 @@ matches "a(int)", "b(long)", but not "c(double)". </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>></td><td class="name" onclick="toggle('isDefinition2')"><a name="isDefinition2Anchor">isDefinition</a></td><td></td></tr> -<tr><td colspan="4" class="doc" id="isDefinition2"><pre>Matches if a declaration has a body attached. +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>></td><td class="name" onclick="toggle('isDefinition0')"><a name="isDefinition0Anchor">isDefinition</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isDefinition0"><pre>Matches if a declaration has a body attached. Example matches A, va, fa class A {}; @@ -2569,7 +2577,7 @@ Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1BlockP </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>></td><td class="name" onclick="toggle('hasPrefix1')"><a name="hasPrefix1Anchor">hasPrefix</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>> InnerMatcher</td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>></td><td class="name" onclick="toggle('hasPrefix1')"><a name="hasPrefix1Anchor">hasPrefix</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasPrefix1"><pre>Matches on the prefix of a NestedNameSpecifierLoc. Given @@ -2599,7 +2607,7 @@ nestedNameSpecifierLoc(specifiesTypeLoc(loc(type( </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>></td><td class="name" onclick="toggle('hasPrefix0')"><a name="hasPrefix0Anchor">hasPrefix</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>> InnerMatcher</td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>></td><td class="name" onclick="toggle('hasPrefix0')"><a name="hasPrefix0Anchor">hasPrefix</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifier.html">NestedNameSpecifier</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasPrefix0"><pre>Matches on the prefix of a NestedNameSpecifier. Given diff --git a/docs/tools/dump_ast_matchers.py b/docs/tools/dump_ast_matchers.py index cd7ab0b74f..4ed6822be1 100644 --- a/docs/tools/dump_ast_matchers.py +++ b/docs/tools/dump_ast_matchers.py @@ -175,13 +175,14 @@ def act_on_decl(declaration, comment, allowed_types): comment) return - m = re.match(r"""^\s*AST_(POLYMORPHIC_)?MATCHER(_P)?(.?)\( + m = re.match(r"""^\s*AST_(POLYMORPHIC_)?MATCHER(_P)?(.?)(?:_OVERLOAD)?\( (?:\s*([^\s,]+)\s*,)? \s*([^\s,]+)\s* (?:,\s*([^\s,]+)\s* ,\s*([^\s,]+)\s*)? (?:,\s*([^\s,]+)\s* ,\s*([^\s,]+)\s*)? + (?:,\s*\d+\s*)? \)\s*{\s*$""", declaration, flags=re.X) if m: p, n, result, name = m.groups()[1:5] diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 61a0ab2559..15c9565d39 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -1234,7 +1234,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))); } @@ -1242,8 +1242,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. @@ -1599,7 +1599,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 @@ -1637,11 +1637,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. @@ -1676,8 +1675,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 @@ -1701,8 +1699,7 @@ AST_MATCHER_P(QualType, references, internal::Matcher<QualType>, /// \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, @@ -2348,10 +2345,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 @@ -2393,8 +2393,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. @@ -2426,8 +2426,8 @@ 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 a member expression where the member is matched by a @@ -2523,11 +2523,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 @@ -2542,11 +2545,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 @@ -2897,10 +2901,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. @@ -2912,10 +2919,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 diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index a6661f5d31..b41a74ce83 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -1028,69 +1028,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 @@ -1154,50 +1091,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 0a470d0392..b2629c6627 100644 --- a/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -49,20 +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 : public MatcherInterface<Type> { \ + class matcher_##DefineMatcher##OverloadId##Matcher \ + : public MatcherInterface<Type> { \ public: \ - explicit matcher_##DefineMatcher##Matcher() { \ - } \ + 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 @@ -80,10 +83,16 @@ /// /// 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 : public MatcherInterface<Type> { \ + class matcher_##DefineMatcher##OverloadId##Matcher \ + : public MatcherInterface<Type> { \ public: \ - explicit matcher_##DefineMatcher##Matcher(const ParamType &A##Param) \ + explicit matcher_##DefineMatcher##OverloadId##Matcher( \ + const ParamType &A##Param) \ : Param(A##Param) { \ } \ virtual bool matches(const Type &Node, ASTMatchFinder *Finder, \ @@ -94,9 +103,9 @@ } \ 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,11 +125,17 @@ /// The code should return true if 'Node' matches. #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 : public MatcherInterface<Type> { \ + class matcher_##DefineMatcher##OverloadId##Matcher \ + : public MatcherInterface<Type> { \ public: \ - matcher_##DefineMatcher##Matcher(const ParamType1 &A##Param1, \ - const ParamType2 &A##Param2) \ + 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, \ @@ -130,15 +145,45 @@ 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. @@ -149,11 +194,17 @@ /// /// 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 : public MatcherInterface<NodeType> { \ + class matcher_##DefineMatcher##OverloadId##Matcher \ + : public MatcherInterface<NodeType> { \ public: \ - explicit matcher_##DefineMatcher##Matcher(const ParamType &A##Param) \ + explicit matcher_##DefineMatcher##OverloadId##Matcher( \ + const ParamType &A##Param) \ : Param(A##Param) { \ } \ virtual bool matches(const NodeType &Node, ASTMatchFinder *Finder, \ @@ -163,15 +214,16 @@ }; \ } \ 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) { ... } @@ -183,12 +235,18 @@ /// Matcher<NodeType> returned by the function DefineMatcher(). #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 : public MatcherInterface<NodeType> { \ + class matcher_##DefineMatcher##OverloadId##Matcher \ + : public MatcherInterface<NodeType> { \ public: \ - matcher_##DefineMatcher##Matcher(const ParamType1 &A##Param1, \ - const ParamType2 &A##Param2) \ + 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, \ @@ -199,18 +257,18 @@ }; \ } \ 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, \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ ParamType2>(Param1, Param2); \ } \ template <typename NodeType, typename ParamT1, typename ParamT2> \ - bool internal::matcher_##DefineMatcher##Matcher< \ - NodeType, ParamT1, \ - ParamT2>::matches(const NodeType &Node, ASTMatchFinder *Finder, \ - BoundNodesTreeBuilder *Builder) const + bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ + NodeType, ParamT1, ParamT2>::matches( \ + const NodeType &Node, ASTMatchFinder *Finder, \ + BoundNodesTreeBuilder *Builder) const /// \brief Creates a variadic matcher for both a specific \c Type as well as /// the corresponding \c TypeLoc. |