[PATCH] Add loc() to the dynamic registry.

Samuel Benzaquen sbenza at google.com
Mon Mar 3 07:48:12 PST 2014


Hi klimek,

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.

http://llvm-reviews.chandlerc.com/D2928

Files:
  include/clang/ASTMatchers/ASTMatchers.h
  include/clang/ASTMatchers/Dynamic/VariantValue.h
  lib/ASTMatchers/Dynamic/Registry.cpp
  lib/ASTMatchers/Dynamic/VariantValue.cpp
  unittests/ASTMatchers/Dynamic/RegistryTest.cpp

Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -2824,6 +2824,9 @@
   return internal::BindableMatcher<TypeLoc>(
       new internal::TypeLocTypeMatcher(InnerMatcher));
 }
+/// Signature for the registry.
+typedef internal::BindableMatcher<TypeLoc>(&loc_Type0)(
+    const internal::Matcher<QualType> &);
 
 /// \brief Matches builtin Types.
 ///
@@ -3309,6 +3312,9 @@
       new internal::LocMatcher<NestedNameSpecifierLoc, NestedNameSpecifier>(
           InnerMatcher));
 }
+/// Signature for the registry.
+typedef internal::BindableMatcher<NestedNameSpecifierLoc>(&loc_Type1)(
+    const internal::Matcher<NestedNameSpecifier> &);
 
 /// \brief Matches nested name specifiers that specify a type matching the
 /// given \c QualType matcher without qualifiers.
@@ -3340,7 +3346,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/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
@@ -79,15 +79,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
@@ -38,7 +38,8 @@
   }
 
   virtual void makeTypedMatcher(MatcherOps &Ops) const {
-    if (Ops.canConstructFrom(Matcher))
+    bool Ignore;
+    if (Ops.canConstructFrom(Matcher, Ignore))
       Ops.constructFrom(Matcher);
   }
 
@@ -70,15 +71,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
@@ -67,7 +67,7 @@
     VariantMatcher Out;
     if (Ctor)
       Out = Registry::constructMatcher(*Ctor, SourceRange(), Args(Arg1), Error);
-    EXPECT_EQ("", DummyError.toStringFull());
+    EXPECT_EQ("", DummyError.toStringFull()) << MatcherName;
     return Out;
   }
 
@@ -168,6 +168,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) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2928.1.patch
Type: text/x-patch
Size: 5853 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140303/d64171a8/attachment.bin>


More information about the cfe-commits mailing list