Enhancements for the DynTypedMatcher system.
- Added conversion routines and checks in Matcher<T> that take a DynTypedMatcher.
- Added type information on the error messages for the marshallers.
- Allows future work on Polymorphic/overloaded matchers. We should be
  able to disambiguate at runtime and choose the appropriate overload.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184429 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/unittests/ASTMatchers/Dynamic/ParserTest.cpp b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
index b20c1ac..d7973c9 100644
--- a/unittests/ASTMatchers/Dynamic/ParserTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/ParserTest.cpp
@@ -49,6 +49,9 @@
 
   StringRef boundID() const { return BoundID; }
 
+  virtual ast_type_traits::ASTNodeKind getSupportedKind() const {
+    return ast_type_traits::ASTNodeKind();
+  }
 private:
   uint64_t ID;
   std::string BoundID;
@@ -172,15 +175,19 @@
 using ast_matchers::internal::Matcher;
 
 TEST(ParserTest, FullParserTest) {
-  OwningPtr<DynTypedMatcher> Matcher(Parser::parseMatcherExpression(
-      "hasInitializer(binaryOperator(hasLHS(integerLiteral())))", NULL));
-  EXPECT_TRUE(matchesDynamic("int x = 1 + false;", *Matcher));
-  EXPECT_FALSE(matchesDynamic("int x = true + 1;", *Matcher));
+  OwningPtr<DynTypedMatcher> VarDecl(Parser::parseMatcherExpression(
+      "varDecl(hasInitializer(binaryOperator(hasLHS(integerLiteral()))))",
+      NULL));
+  Matcher<Decl> M = Matcher<Decl>::constructFrom(*VarDecl);
+  EXPECT_TRUE(matches("int x = 1 + false;", M));
+  EXPECT_FALSE(matches("int x = true + 1;", M));
 
-  Matcher.reset(
-      Parser::parseMatcherExpression("hasParameter(1, hasName(\"x\"))", NULL));
-  EXPECT_TRUE(matchesDynamic("void f(int a, int x);", *Matcher));
-  EXPECT_FALSE(matchesDynamic("void f(int x, int a);", *Matcher));
+  OwningPtr<DynTypedMatcher> HasParameter(Parser::parseMatcherExpression(
+      "functionDecl(hasParameter(1, hasName(\"x\")))", NULL));
+  M = Matcher<Decl>::constructFrom(*HasParameter);
+
+  EXPECT_TRUE(matches("void f(int a, int x);", M));
+  EXPECT_FALSE(matches("void f(int x, int a);", M));
 
   Diagnostics Error;
   EXPECT_TRUE(Parser::parseMatcherExpression(
@@ -188,7 +195,8 @@
   EXPECT_EQ("1:1: Error parsing argument 1 for matcher hasInitializer.\n"
             "2:5: Error parsing argument 1 for matcher binaryOperator.\n"
             "2:20: Error building matcher hasLHS.\n"
-            "2:27: Incorrect type on function hasLHS for arg 1.",
+            "2:27: Incorrect type for arg 1. "
+            "(Expected = Matcher<Expr>) != (Actual = String)",
             Error.ToStringFull());
 }
 
diff --git a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
index 1055233..fd6eaef 100644
--- a/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
@@ -20,98 +20,131 @@
 
 using ast_matchers::internal::Matcher;
 
-DynTypedMatcher *constructMatcher(StringRef MatcherName, Diagnostics *Error) {
-  const std::vector<ParserValue> Args;
-  return Registry::constructMatcher(MatcherName, SourceRange(), Args, Error);
-}
+class RegistryTest : public ::testing::Test {
+public:
+  std::vector<ParserValue> Args() { return std::vector<ParserValue>(); }
+  std::vector<ParserValue> Args(const VariantValue &Arg1) {
+    std::vector<ParserValue> Out(1);
+    Out[0].Value = Arg1;
+    return Out;
+  }
+  std::vector<ParserValue> Args(const VariantValue &Arg1,
+                                const VariantValue &Arg2) {
+    std::vector<ParserValue> Out(2);
+    Out[0].Value = Arg1;
+    Out[1].Value = Arg2;
+    return Out;
+  }
 
-DynTypedMatcher *constructMatcher(StringRef MatcherName,
-                                  const VariantValue &Arg1,
-                                  Diagnostics *Error) {
-  std::vector<ParserValue> Args(1);
-  Args[0].Value = Arg1;
-  return Registry::constructMatcher(MatcherName, SourceRange(), Args, Error);
-}
+  template <class T>
+  Matcher<T> constructMatcher(StringRef MatcherName, Diagnostics *Error) {
+    OwningPtr<DynTypedMatcher> Out(
+        Registry::constructMatcher(MatcherName, SourceRange(), Args(), Error));
+    return Matcher<T>::constructFrom(*Out);
+  }
 
-DynTypedMatcher *constructMatcher(StringRef MatcherName,
-                                  const VariantValue &Arg1,
-                                  const VariantValue &Arg2,
-                                  Diagnostics *Error) {
-  std::vector<ParserValue> Args(2);
-  Args[0].Value = Arg1;
-  Args[1].Value = Arg2;
-  return Registry::constructMatcher(MatcherName, SourceRange(), Args, Error);
-}
+  template <class T>
+  Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
+                              Diagnostics *Error) {
+    OwningPtr<DynTypedMatcher> Out(Registry::constructMatcher(
+        MatcherName, SourceRange(), Args(Arg1), Error));
+    return Matcher<T>::constructFrom(*Out);
+  }
 
-TEST(RegistryTest, CanConstructNoArgs) {
-  OwningPtr<DynTypedMatcher> IsArrowValue(constructMatcher("isArrow", NULL));
-  OwningPtr<DynTypedMatcher> BoolValue(constructMatcher("boolLiteral", NULL));
+  template <class T>
+  Matcher<T> constructMatcher(StringRef MatcherName, const VariantValue &Arg1,
+                              const VariantValue &Arg2, Diagnostics *Error) {
+    OwningPtr<DynTypedMatcher> Out(Registry::constructMatcher(
+        MatcherName, SourceRange(), Args(Arg1, Arg2), Error));
+    return Matcher<T>::constructFrom(*Out);
+  }
+};
+
+TEST_F(RegistryTest, CanConstructNoArgs) {
+  Matcher<Stmt> IsArrowValue = constructMatcher<Stmt>(
+      "memberExpr", constructMatcher<MemberExpr>("isArrow", NULL), NULL);
+  Matcher<Stmt> BoolValue = constructMatcher<Stmt>("boolLiteral", NULL);
 
   const std::string ClassSnippet = "struct Foo { int x; };\n"
                                    "Foo *foo = new Foo;\n"
                                    "int i = foo->x;\n";
   const std::string BoolSnippet = "bool Foo = true;\n";
 
-  EXPECT_TRUE(matchesDynamic(ClassSnippet, *IsArrowValue));
-  EXPECT_TRUE(matchesDynamic(BoolSnippet, *BoolValue));
-  EXPECT_FALSE(matchesDynamic(ClassSnippet, *BoolValue));
-  EXPECT_FALSE(matchesDynamic(BoolSnippet, *IsArrowValue));
+  EXPECT_TRUE(matches(ClassSnippet, IsArrowValue));
+  EXPECT_TRUE(matches(BoolSnippet, BoolValue));
+  EXPECT_FALSE(matches(ClassSnippet, BoolValue));
+  EXPECT_FALSE(matches(BoolSnippet, IsArrowValue));
 }
 
-TEST(RegistryTest, ConstructWithSimpleArgs) {
-  OwningPtr<DynTypedMatcher> Value(
-      constructMatcher("hasName", std::string("X"), NULL));
-  EXPECT_TRUE(matchesDynamic("class X {};", *Value));
-  EXPECT_FALSE(matchesDynamic("int x;", *Value));
+TEST_F(RegistryTest, ConstructWithSimpleArgs) {
+  Matcher<Decl> Value = constructMatcher<Decl>(
+      "namedDecl",
+      constructMatcher<NamedDecl>("hasName", std::string("X"), NULL), NULL);
+  EXPECT_TRUE(matches("class X {};", Value));
+  EXPECT_FALSE(matches("int x;", Value));
 
-  Value.reset(constructMatcher("parameterCountIs", 2, NULL));
-  EXPECT_TRUE(matchesDynamic("void foo(int,int);", *Value));
-  EXPECT_FALSE(matchesDynamic("void foo(int);", *Value));
+  Value =
+      functionDecl(constructMatcher<FunctionDecl>("parameterCountIs", 2, NULL));
+  EXPECT_TRUE(matches("void foo(int,int);", Value));
+  EXPECT_FALSE(matches("void foo(int);", Value));
 }
 
-TEST(RegistryTest, ConstructWithMatcherArgs) {
-  OwningPtr<DynTypedMatcher> HasInitializerSimple(
-      constructMatcher("hasInitializer", stmt(), NULL));
-  OwningPtr<DynTypedMatcher> HasInitializerComplex(
-      constructMatcher("hasInitializer", callExpr(), NULL));
+TEST_F(RegistryTest, ConstructWithMatcherArgs) {
+  Matcher<Decl> HasInitializerSimple = constructMatcher<Decl>(
+      "varDecl", constructMatcher<VarDecl>("hasInitializer", stmt(), NULL),
+      NULL);
+  Matcher<Decl> HasInitializerComplex = constructMatcher<Decl>(
+      "varDecl", constructMatcher<VarDecl>("hasInitializer", callExpr(), NULL),
+      NULL);
 
   std::string code = "int i;";
-  EXPECT_FALSE(matchesDynamic(code, *HasInitializerSimple));
-  EXPECT_FALSE(matchesDynamic(code, *HasInitializerComplex));
+  EXPECT_FALSE(matches(code, HasInitializerSimple));
+  EXPECT_FALSE(matches(code, HasInitializerComplex));
 
   code = "int i = 1;";
-  EXPECT_TRUE(matchesDynamic(code, *HasInitializerSimple));
-  EXPECT_FALSE(matchesDynamic(code, *HasInitializerComplex));
+  EXPECT_TRUE(matches(code, HasInitializerSimple));
+  EXPECT_FALSE(matches(code, HasInitializerComplex));
 
   code = "int y(); int i = y();";
-  EXPECT_TRUE(matchesDynamic(code, *HasInitializerSimple));
-  EXPECT_TRUE(matchesDynamic(code, *HasInitializerComplex));
+  EXPECT_TRUE(matches(code, HasInitializerSimple));
+  EXPECT_TRUE(matches(code, HasInitializerComplex));
 
-  OwningPtr<DynTypedMatcher> HasParameter(
-      constructMatcher("hasParameter", 1, hasName("x"), NULL));
-  EXPECT_TRUE(matchesDynamic("void f(int a, int x);", *HasParameter));
-  EXPECT_FALSE(matchesDynamic("void f(int x, int a);", *HasParameter));
+  Matcher<Decl> HasParameter = functionDecl(
+      constructMatcher<FunctionDecl>("hasParameter", 1, hasName("x"), NULL));
+  EXPECT_TRUE(matches("void f(int a, int x);", HasParameter));
+  EXPECT_FALSE(matches("void f(int x, int a);", HasParameter));
 }
 
-TEST(RegistryTest, Errors) {
+TEST_F(RegistryTest, Errors) {
   // Incorrect argument count.
   OwningPtr<Diagnostics> Error(new Diagnostics());
-  EXPECT_TRUE(NULL == constructMatcher("hasInitializer", Error.get()));
+  EXPECT_TRUE(NULL ==
+              Registry::constructMatcher("hasInitializer", SourceRange(),
+                                         Args(), Error.get()));
   EXPECT_EQ("Incorrect argument count. (Expected = 1) != (Actual = 0)",
             Error->ToString());
   Error.reset(new Diagnostics());
-  EXPECT_TRUE(NULL == constructMatcher("isArrow", std::string(), Error.get()));
+  EXPECT_TRUE(NULL ==
+              Registry::constructMatcher("isArrow", SourceRange(),
+                                         Args(std::string()), Error.get()));
   EXPECT_EQ("Incorrect argument count. (Expected = 0) != (Actual = 1)",
             Error->ToString());
 
   // Bad argument type
   Error.reset(new Diagnostics());
-  EXPECT_TRUE(NULL == constructMatcher("ofClass", std::string(), Error.get()));
-  EXPECT_EQ("Incorrect type on function ofClass for arg 1.", Error->ToString());
+  EXPECT_TRUE(NULL ==
+              Registry::constructMatcher("ofClass", SourceRange(),
+                                         Args(std::string()), Error.get()));
+  EXPECT_EQ("Incorrect type for arg 1. (Expected = Matcher<CXXRecordDecl>) != "
+            "(Actual = String)",
+            Error->ToString());
   Error.reset(new Diagnostics());
-  EXPECT_TRUE(NULL == constructMatcher("recordDecl", recordDecl(),
-                                       ::std::string(), Error.get()));
-  EXPECT_EQ("Incorrect type on function recordDecl for arg 2.",
+  EXPECT_TRUE(NULL ==
+              Registry::constructMatcher(
+                  "recordDecl", SourceRange(),
+                  Args(recordDecl(), parameterCountIs(3)), Error.get()));
+  EXPECT_EQ("Incorrect type for arg 2. (Expected = Matcher<CXXRecordDecl>) != "
+            "(Actual = Matcher<FunctionDecl>)",
             Error->ToString());
 }
 
diff --git a/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp b/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
index 2aa0e42..8206d00 100644
--- a/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
+++ b/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
@@ -28,8 +28,8 @@
 
   EXPECT_FALSE(Value.isString());
   EXPECT_FALSE(Value.isMatcher());
-  EXPECT_FALSE(Value.isTypedMatcher<clang::Decl>());
-  EXPECT_FALSE(Value.isTypedMatcher<clang::UnaryOperator>());
+  EXPECT_FALSE(Value.hasTypedMatcher<clang::Decl>());
+  EXPECT_FALSE(Value.hasTypedMatcher<clang::UnaryOperator>());
 }
 
 TEST(VariantValueTest, String) {
@@ -38,11 +38,12 @@
 
   EXPECT_TRUE(Value.isString());
   EXPECT_EQ(kString, Value.getString());
+  EXPECT_EQ("String", Value.getTypeAsString());
 
   EXPECT_FALSE(Value.isUnsigned());
   EXPECT_FALSE(Value.isMatcher());
-  EXPECT_FALSE(Value.isTypedMatcher<clang::Decl>());
-  EXPECT_FALSE(Value.isTypedMatcher<clang::UnaryOperator>());
+  EXPECT_FALSE(Value.hasTypedMatcher<clang::Decl>());
+  EXPECT_FALSE(Value.hasTypedMatcher<clang::UnaryOperator>());
 }
 
 TEST(VariantValueTest, DynTypedMatcher) {
@@ -52,22 +53,25 @@
   EXPECT_FALSE(Value.isString());
 
   EXPECT_TRUE(Value.isMatcher());
-  EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());
-  EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());
+  EXPECT_FALSE(Value.hasTypedMatcher<clang::Decl>());
+  EXPECT_TRUE(Value.hasTypedMatcher<clang::UnaryOperator>());
+  EXPECT_EQ("Matcher<Stmt>", Value.getTypeAsString());
 
-  // Conversion to any type of matcher works.
-  // If they are not compatible it would just return a matcher that matches
-  // nothing. We test this below.
+  // Can only convert to compatible matchers.
   Value = recordDecl();
   EXPECT_TRUE(Value.isMatcher());
-  EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());
-  EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());
+  EXPECT_TRUE(Value.hasTypedMatcher<clang::Decl>());
+  EXPECT_FALSE(Value.hasTypedMatcher<clang::UnaryOperator>());
+  EXPECT_EQ("Matcher<Decl>", Value.getTypeAsString());
 
-  Value = unaryOperator();
+  Value = ignoringImpCasts(expr());
   EXPECT_TRUE(Value.isMatcher());
-  EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());
-  EXPECT_TRUE(Value.isTypedMatcher<clang::Stmt>());
-  EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());
+  EXPECT_FALSE(Value.hasTypedMatcher<clang::Decl>());
+  EXPECT_FALSE(Value.hasTypedMatcher<clang::Stmt>());
+  EXPECT_TRUE(Value.hasTypedMatcher<clang::Expr>());
+  EXPECT_TRUE(Value.hasTypedMatcher<clang::IntegerLiteral>());
+  EXPECT_FALSE(Value.hasTypedMatcher<clang::GotoStmt>());
+  EXPECT_EQ("Matcher<Expr>", Value.getTypeAsString());
 }
 
 TEST(VariantValueTest, Assignment) {
@@ -76,13 +80,15 @@
   EXPECT_EQ("A", Value.getString());
   EXPECT_FALSE(Value.isUnsigned());
   EXPECT_FALSE(Value.isMatcher());
+  EXPECT_EQ("String", Value.getTypeAsString());
 
   Value = recordDecl();
   EXPECT_FALSE(Value.isUnsigned());
   EXPECT_FALSE(Value.isString());
   EXPECT_TRUE(Value.isMatcher());
-  EXPECT_TRUE(Value.isTypedMatcher<clang::Decl>());
-  EXPECT_TRUE(Value.isTypedMatcher<clang::UnaryOperator>());
+  EXPECT_TRUE(Value.hasTypedMatcher<clang::Decl>());
+  EXPECT_FALSE(Value.hasTypedMatcher<clang::UnaryOperator>());
+  EXPECT_EQ("Matcher<Decl>", Value.getTypeAsString());
 
   Value = 17;
   EXPECT_TRUE(Value.isUnsigned());
@@ -94,25 +100,28 @@
   EXPECT_FALSE(Value.isUnsigned());
   EXPECT_FALSE(Value.isString());
   EXPECT_FALSE(Value.isMatcher());
+  EXPECT_EQ("Nothing", Value.getTypeAsString());
 }
 
 TEST(GeneicValueTest, Matcher) {
-  EXPECT_TRUE(matchesDynamic(
-      "class X {};", VariantValue(recordDecl(hasName("X"))).getMatcher()));
-  EXPECT_TRUE(matchesDynamic(
-      "int x;", VariantValue(varDecl()).getTypedMatcher<clang::Decl>()));
-  EXPECT_TRUE(matchesDynamic("int foo() { return 1 + 1; }",
-                             VariantValue(functionDecl()).getMatcher()));
-  // Going through the wrong Matcher<T> will fail to match, even if the
-  // underlying matcher is correct.
-  EXPECT_FALSE(matchesDynamic(
-      "int x;", VariantValue(varDecl()).getTypedMatcher<clang::Stmt>()));
+  EXPECT_TRUE(matches("class X {};", VariantValue(recordDecl(hasName("X")))
+                                         .getTypedMatcher<Decl>()));
+  EXPECT_TRUE(
+      matches("int x;", VariantValue(varDecl()).getTypedMatcher<Decl>()));
+  EXPECT_TRUE(matches("int foo() { return 1 + 1; }",
+                      VariantValue(functionDecl()).getTypedMatcher<Decl>()));
+  // Can't get the wrong matcher.
+  EXPECT_FALSE(VariantValue(varDecl()).hasTypedMatcher<Stmt>());
+#if GTEST_HAS_DEATH_TEST and DEBUG
+  // Trying to get the wrong matcher fails an assertion in Matcher<T>.
+  EXPECT_DEATH(VariantValue(varDecl()).getTypedMatcher<Stmt>(),
+               "canConstructFrom");
+#endif
 
   EXPECT_FALSE(
-      matchesDynamic("int x;", VariantValue(functionDecl()).getMatcher()));
-  EXPECT_FALSE(matchesDynamic(
-      "int foo() { return 1 + 1; }",
-      VariantValue(declRefExpr()).getTypedMatcher<clang::DeclRefExpr>()));
+      matches("int x;", VariantValue(functionDecl()).getTypedMatcher<Decl>()));
+  EXPECT_FALSE(matches("int foo() { return 1 + 1; }",
+                       VariantValue(declRefExpr()).getTypedMatcher<Stmt>()));
 }
 
 } // end anonymous namespace