Created a macro for function overloads like loc() to hide the declaration of the overload function pointer. Updated and reran the doc dumper.
Hi klimek, http://llvm-reviews.chandlerc.com/D2928 CHANGE SINCE LAST DIFF http://llvm-reviews.chandlerc.com/D2928?vs=7474&id=7692#toc BRANCH loc ARCANIST PROJECT clang Files: docs/LibASTMatchersReference.html docs/tools/dump_ast_matchers.py include/clang/ASTMatchers/ASTMatchers.h include/clang/ASTMatchers/ASTMatchersMacros.h include/clang/ASTMatchers/Dynamic/VariantValue.h lib/ASTMatchers/Dynamic/Registry.cpp lib/ASTMatchers/Dynamic/VariantValue.cpp unittests/ASTMatchers/Dynamic/RegistryTest.cpp
Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -3213,12 +3213,6 @@ </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('loc1')"><a name="loc1Anchor">loc</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="loc1"><pre>Matches NestedNameSpecifierLocs for which the given inner -NestedNameSpecifier-matcher matches. -</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('specifiesTypeLoc0')"><a name="specifiesTypeLoc0Anchor">specifiesTypeLoc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="specifiesTypeLoc0"><pre>Matches nested name specifier locs that specify a type matching the given TypeLoc. @@ -3613,12 +3607,6 @@ </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>></td><td class="name" onclick="toggle('loc0')"><a name="loc0Anchor">loc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="loc0"><pre>Matches TypeLocs for which the given inner -QualType-matcher matches. -</pre></td></tr> - - <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefType.html">TypedefType</a>></td><td class="name" onclick="toggle('hasDeclaration1')"><a name="hasDeclaration1Anchor">hasDeclaration</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasDeclaration1"><pre>Matches a node if the declaration associated with that node matches the given matcher. @@ -3778,6 +3766,18 @@ if (true) {} </pre></td></tr> + +<tr><td>Matcher<internal::BindableMatcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1NestedNameSpecifierLoc.html">NestedNameSpecifierLoc</a>>></td><td class="name" onclick="toggle('loc1')"><a name="loc1Anchor">loc</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="loc1"><pre>Matches NestedNameSpecifierLocs for which the given inner +NestedNameSpecifier-matcher matches. +</pre></td></tr> + + +<tr><td>Matcher<internal::BindableMatcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>>></td><td class="name" onclick="toggle('loc0')"><a name="loc0Anchor">loc</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="loc0"><pre>Matches TypeLocs for which the given inner +QualType-matcher matches. +</pre></td></tr> + <!--END_TRAVERSAL_MATCHERS --> </table> Index: docs/tools/dump_ast_matchers.py =================================================================== --- docs/tools/dump_ast_matchers.py +++ docs/tools/dump_ast_matchers.py @@ -204,6 +204,25 @@ add_matcher(result_type, name, args, comment) return + m = re.match(r"""^\s*AST_MATCHER_FUNCTION(_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()[0:4] + args = m.groups()[4:] + if n not in ['', '2']: + raise Exception('Cannot parse "%s"' % declaration) + args = ', '.join('%s %s' % (args[i], args[i+1]) + for i in range(0, len(args), 2) if args[i]) + add_matcher(result, name, args, comment) + return + m = re.match(r"""^\s*AST_MATCHER(_P)?(.?)(?:_OVERLOAD)?\( (?:\s*([^\s,]+)\s*,)? \s*([^\s,]+)\s* Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -2869,8 +2869,8 @@ /// \brief Matches \c TypeLocs for which the given inner /// QualType-matcher matches. -inline internal::BindableMatcher<TypeLoc> loc( - const internal::Matcher<QualType> &InnerMatcher) { +AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc, + internal::Matcher<QualType>, InnerMatcher, 0) { return internal::BindableMatcher<TypeLoc>( new internal::TypeLocTypeMatcher(InnerMatcher)); } @@ -3353,8 +3353,9 @@ /// \brief Matches \c NestedNameSpecifierLocs for which the given inner /// NestedNameSpecifier-matcher matches. -inline internal::BindableMatcher<NestedNameSpecifierLoc> loc( - const internal::Matcher<NestedNameSpecifier> &InnerMatcher) { +AST_MATCHER_FUNCTION_P_OVERLOAD( + internal::BindableMatcher<NestedNameSpecifierLoc>, loc, + internal::Matcher<NestedNameSpecifier>, InnerMatcher, 1) { return internal::BindableMatcher<NestedNameSpecifierLoc>( new internal::LocMatcher<NestedNameSpecifierLoc, NestedNameSpecifier>( InnerMatcher)); @@ -3390,7 +3391,7 @@ /// matches "A::" AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc, internal::Matcher<TypeLoc>, InnerMatcher) { - return InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder); + return Node && InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder); } /// \brief Matches on the prefix of a \c NestedNameSpecifier. Index: include/clang/ASTMatchers/ASTMatchersMacros.h =================================================================== --- include/clang/ASTMatchers/ASTMatchersMacros.h +++ include/clang/ASTMatchers/ASTMatchersMacros.h @@ -37,6 +37,25 @@ #ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H #define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H +/// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) { +/// defines a single-parameter function named DefineMatcher() that returns a +/// ReturnType object. +/// +/// The code between the curly braces has access to the following variables: +/// +/// Param: the parameter passed to the function; its type +/// is ParamType. +/// +/// The code should return an instance of ReturnType. +#define AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) \ + AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, Param, \ + 0) +#define AST_MATCHER_FUNCTION_P_OVERLOAD(ReturnType, DefineMatcher, ParamType, \ + Param, OverloadId) \ + inline ReturnType DefineMatcher(const ParamType &Param); \ + typedef ReturnType (&DefineMatcher##_Type##OverloadId)(const ParamType &); \ + inline ReturnType DefineMatcher(const ParamType &Param) + /// \brief AST_MATCHER(Type, DefineMatcher) { ... } /// defines a zero parameter function named DefineMatcher() that returns a /// Matcher<Type> object. Index: include/clang/ASTMatchers/Dynamic/VariantValue.h =================================================================== --- include/clang/ASTMatchers/Dynamic/VariantValue.h +++ include/clang/ASTMatchers/Dynamic/VariantValue.h @@ -50,7 +50,8 @@ class MatcherOps { public: virtual ~MatcherOps(); - virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const = 0; + virtual bool canConstructFrom(const DynTypedMatcher &Matcher, + bool &IsExactMatch) const = 0; virtual void constructFrom(const DynTypedMatcher &Matcher) = 0; virtual void constructVariadicOperator( ast_matchers::internal::VariadicOperatorFunction Func, @@ -145,7 +146,10 @@ public: typedef ast_matchers::internal::Matcher<T> MatcherT; - virtual bool canConstructFrom(const DynTypedMatcher &Matcher) const { + virtual bool canConstructFrom(const DynTypedMatcher &Matcher, + bool &IsExactMatch) const { + IsExactMatch = Matcher.getSupportedKind().isSame( + ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); return Matcher.canConvertTo<T>(); } Index: lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- lib/ASTMatchers/Dynamic/Registry.cpp +++ lib/ASTMatchers/Dynamic/Registry.cpp @@ -80,15 +80,15 @@ // findAll // // Other: - // loc // equals // equalsNode REGISTER_OVERLOADED_2(callee); REGISTER_OVERLOADED_2(hasPrefix); REGISTER_OVERLOADED_2(hasType); REGISTER_OVERLOADED_2(isDerivedFrom); REGISTER_OVERLOADED_2(isSameOrDerivedFrom); + REGISTER_OVERLOADED_2(loc); REGISTER_OVERLOADED_2(pointsTo); REGISTER_OVERLOADED_2(references); REGISTER_OVERLOADED_2(thisPointerType); Index: lib/ASTMatchers/Dynamic/VariantValue.cpp =================================================================== --- lib/ASTMatchers/Dynamic/VariantValue.cpp +++ lib/ASTMatchers/Dynamic/VariantValue.cpp @@ -37,7 +37,8 @@ } virtual void makeTypedMatcher(MatcherOps &Ops) const { - if (Ops.canConstructFrom(Matcher)) + bool Ignore; + if (Ops.canConstructFrom(Matcher, Ignore)) Ops.constructFrom(Matcher); } @@ -69,15 +70,25 @@ } virtual void makeTypedMatcher(MatcherOps &Ops) const { + bool FoundIsExact = false; const DynTypedMatcher *Found = NULL; + int NumFound = 0; for (size_t i = 0, e = Matchers.size(); i != e; ++i) { - if (Ops.canConstructFrom(Matchers[i])) { - if (Found) - return; + bool IsExactMatch; + if (Ops.canConstructFrom(Matchers[i], IsExactMatch)) { + if (Found) { + if (FoundIsExact) { + assert(!IsExactMatch && "We should not have two exact matches."); + continue; + } + } Found = &Matchers[i]; + FoundIsExact = IsExactMatch; + ++NumFound; } } - if (Found) + // We only succeed if we found exactly one, or if we found an exact match. + if (Found && (FoundIsExact || NumFound == 1)) Ops.constructFrom(*Found); } Index: unittests/ASTMatchers/Dynamic/RegistryTest.cpp =================================================================== --- unittests/ASTMatchers/Dynamic/RegistryTest.cpp +++ unittests/ASTMatchers/Dynamic/RegistryTest.cpp @@ -66,7 +66,7 @@ VariantMatcher Out; if (Ctor) Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error); - EXPECT_EQ("", DummyError.toStringFull()); + EXPECT_EQ("", DummyError.toStringFull()) << MatcherName; return Out; } @@ -211,6 +211,25 @@ Code = "class Z { public: void z() { this->z(); } };"; EXPECT_TRUE(matches(Code, CallExpr0)); EXPECT_FALSE(matches(Code, CallExpr1)); + + Matcher<Decl> DeclDecl = declaratorDecl(hasTypeLoc( + constructMatcher( + "loc", constructMatcher("asString", std::string("const double *"))) + .getTypedMatcher<TypeLoc>())); + + Matcher<NestedNameSpecifierLoc> NNSL = + constructMatcher( + "loc", VariantMatcher::SingleMatcher(nestedNameSpecifier( + specifiesType(hasDeclaration(recordDecl(hasName("A"))))))) + .getTypedMatcher<NestedNameSpecifierLoc>(); + + Code = "const double * x = 0;"; + EXPECT_TRUE(matches(Code, DeclDecl)); + EXPECT_FALSE(matches(Code, NNSL)); + + Code = "struct A { struct B {}; }; A::B a_b;"; + EXPECT_FALSE(matches(Code, DeclDecl)); + EXPECT_TRUE(matches(Code, NNSL)); } TEST_F(RegistryTest, PolymorphicMatchers) {
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
