Author: sbenza Date: Mon Mar 10 10:40:23 2014 New Revision: 203467 URL: http://llvm.org/viewvc/llvm-project?rev=203467&view=rev Log: Add loc() to the dynamic registry.
Summary: Add loc() to the dynamic registry. Other fixes: - Fix the polymorphic variant value to accept an exact match, even if there are other possible conversions. - Fix specifiesTypeLoc() to not crash on an empty NestedNameSpecifierLoc. Reviewers: klimek CC: cfe-commits, klimek Differential Revision: http://llvm-reviews.chandlerc.com/D2928 Modified: cfe/trunk/docs/LibASTMatchersReference.html cfe/trunk/docs/tools/dump_ast_matchers.py cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp Modified: cfe/trunk/docs/LibASTMatchersReference.html URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=203467&r1=203466&r2=203467&view=diff ============================================================================== --- cfe/trunk/docs/LibASTMatchersReference.html (original) +++ cfe/trunk/docs/LibASTMatchersReference.html Mon Mar 10 10:40:23 2014 @@ -3213,12 +3213,6 @@ nestedNameSpecifierLoc(hasPrefix(loc(spe </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 @@ Usable as: Any Matcher </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 @@ Example matches true (matcher = hasCondi 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> Modified: cfe/trunk/docs/tools/dump_ast_matchers.py URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/tools/dump_ast_matchers.py?rev=203467&r1=203466&r2=203467&view=diff ============================================================================== --- cfe/trunk/docs/tools/dump_ast_matchers.py (original) +++ cfe/trunk/docs/tools/dump_ast_matchers.py Mon Mar 10 10:40:23 2014 @@ -204,6 +204,25 @@ def act_on_decl(declaration, comment, al 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* Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=203467&r1=203466&r2=203467&view=diff ============================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Mon Mar 10 10:40:23 2014 @@ -2869,8 +2869,8 @@ AST_POLYMORPHIC_MATCHER( /// \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 @@ const internal::VariadicAllOfMatcher< /// \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 @@ AST_MATCHER_P(NestedNameSpecifier, speci /// 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. Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h?rev=203467&r1=203466&r2=203467&view=diff ============================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h (original) +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersMacros.h Mon Mar 10 10:40:23 2014 @@ -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. Modified: cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h?rev=203467&r1=203466&r2=203467&view=diff ============================================================================== --- cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h (original) +++ cfe/trunk/include/clang/ASTMatchers/Dynamic/VariantValue.h Mon Mar 10 10:40:23 2014 @@ -49,7 +49,8 @@ class VariantMatcher { 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, @@ -144,7 +145,10 @@ private: 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>(); } Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=203467&r1=203466&r2=203467&view=diff ============================================================================== --- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original) +++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Mon Mar 10 10:40:23 2014 @@ -80,7 +80,6 @@ RegistryMaps::RegistryMaps() { // findAll // // Other: - // loc // equals // equalsNode @@ -89,6 +88,7 @@ RegistryMaps::RegistryMaps() { 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); Modified: cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp?rev=203467&r1=203466&r2=203467&view=diff ============================================================================== --- cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp (original) +++ cfe/trunk/lib/ASTMatchers/Dynamic/VariantValue.cpp Mon Mar 10 10:40:23 2014 @@ -37,7 +37,8 @@ public: } virtual void makeTypedMatcher(MatcherOps &Ops) const { - if (Ops.canConstructFrom(Matcher)) + bool Ignore; + if (Ops.canConstructFrom(Matcher, Ignore)) Ops.constructFrom(Matcher); } @@ -69,15 +70,25 @@ public: } 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); } Modified: cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp?rev=203467&r1=203466&r2=203467&view=diff ============================================================================== --- cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp (original) +++ cfe/trunk/unittests/ASTMatchers/Dynamic/RegistryTest.cpp Mon Mar 10 10:40:23 2014 @@ -66,7 +66,7 @@ public: 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 @@ TEST_F(RegistryTest, OverloadedMatchers) 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
