]> granicus.if.org Git - clang/commitdiff
Separated RecursiveASTVisitorTest into multiple files.
authorManuel Klimek <klimek@google.com>
Thu, 9 Oct 2014 15:02:06 +0000 (15:02 +0000)
committerManuel Klimek <klimek@google.com>
Thu, 9 Oct 2014 15:02:06 +0000 (15:02 +0000)
Patch by Marek Kurdej.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@219410 91177308-0d34-0410-b5e6-96231b3b80d8

unittests/Tooling/CMakeLists.txt
unittests/Tooling/RecursiveASTVisitorTest.cpp
unittests/Tooling/RecursiveASTVisitorTestCallVisitor.cpp [new file with mode: 0644]
unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp [new file with mode: 0644]
unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp [new file with mode: 0644]
unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp [new file with mode: 0644]
unittests/Tooling/TestVisitor.h

index a41d87c6ea821bbf422fd5ef7741769baa2d289c..70de1314be7a6a6b1d689110310e27d749293a49 100644 (file)
@@ -7,6 +7,10 @@ add_clang_unittest(ToolingTests
   CompilationDatabaseTest.cpp
   ToolingTest.cpp
   RecursiveASTVisitorTest.cpp
+  RecursiveASTVisitorTestCallVisitor.cpp
+  RecursiveASTVisitorTestDeclVisitor.cpp
+  RecursiveASTVisitorTestExprVisitor.cpp
+  RecursiveASTVisitorTestTypeLocVisitor.cpp
   RefactoringTest.cpp
   RewriterTest.cpp
   RefactoringCallbacksTest.cpp
index a1a93a59c79b490499bc5d9566e852396fbc411a..c28704532a6edb141476ece4f9983fcdd81549d4 100644 (file)
@@ -14,85 +14,6 @@ using namespace clang;
 
 namespace {
 
-class TypeLocVisitor : public ExpectedLocationVisitor<TypeLocVisitor> {
-public:
-  bool VisitTypeLoc(TypeLoc TypeLocation) {
-    Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc());
-    return true;
-  }
-};
-
-class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
-public:
-  bool VisitDeclRefExpr(DeclRefExpr *Reference) {
-    Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
-    return true;
-  }
-};
-
-class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> {
-public:
- bool VisitVarDecl(VarDecl *Variable) {
-   Match(Variable->getNameAsString(), Variable->getLocStart());
-   return true;
- }
-};
-
-class ParmVarDeclVisitorForImplicitCode :
-  public ExpectedLocationVisitor<ParmVarDeclVisitorForImplicitCode> {
-public:
-  bool shouldVisitImplicitCode() const { return true; }
-
-  bool VisitParmVarDecl(ParmVarDecl *ParamVar) {
-    Match(ParamVar->getNameAsString(), ParamVar->getLocStart());
-    return true;
-  }
-};
-
-class CXXMemberCallVisitor
-  : public ExpectedLocationVisitor<CXXMemberCallVisitor> {
-public:
-  bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) {
-    Match(Call->getMethodDecl()->getQualifiedNameAsString(),
-          Call->getLocStart());
-    return true;
-  }
-};
-
-class NamedDeclVisitor
-  : public ExpectedLocationVisitor<NamedDeclVisitor> {
-public:
-  bool VisitNamedDecl(NamedDecl *Decl) {
-    std::string NameWithTemplateArgs;
-    llvm::raw_string_ostream OS(NameWithTemplateArgs);
-    Decl->getNameForDiagnostic(OS,
-                               Decl->getASTContext().getPrintingPolicy(),
-                               true);
-    Match(OS.str(), Decl->getLocation());
-    return true;
-  }
-};
-
-class CXXOperatorCallExprTraverser
-  : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> {
-public:
-  // Use Traverse, not Visit, to check that data recursion optimization isn't
-  // bypassing the call of this function.
-  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
-    Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc());
-    return ExpectedLocationVisitor<CXXOperatorCallExprTraverser>::
-        TraverseCXXOperatorCallExpr(CE);
-  }
-};
-
-class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> {
-public:
-  bool VisitParenExpr(ParenExpr *Parens) {
-    Match("", Parens->getExprLoc());
-    return true;
-  }
-};
-
 class LambdaExprVisitor : public ExpectedLocationVisitor<LambdaExprVisitor> {
 public:
   bool VisitLambdaExpr(LambdaExpr *Lambda) {
@@ -117,429 +38,6 @@ private:
   std::stack<LambdaExpr *> PendingBodies;
 };
 
-// Matches the (optional) capture-default of a lambda-introducer.
-class LambdaDefaultCaptureVisitor
-  : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
-public:
-  bool VisitLambdaExpr(LambdaExpr *Lambda) {
-    if (Lambda->getCaptureDefault() != LCD_None) {
-      Match("", Lambda->getCaptureDefaultLoc());
-    }
-    return true;
-  }
-};
-
-class TemplateArgumentLocTraverser
-  : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> {
-public:
-  bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
-    std::string ArgStr;
-    llvm::raw_string_ostream Stream(ArgStr);
-    const TemplateArgument &Arg = ArgLoc.getArgument();
-
-    Arg.print(Context->getPrintingPolicy(), Stream);
-    Match(Stream.str(), ArgLoc.getLocation());
-    return ExpectedLocationVisitor<TemplateArgumentLocTraverser>::
-      TraverseTemplateArgumentLoc(ArgLoc);
-  }
-};
-
-class CXXBoolLiteralExprVisitor 
-  : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> {
-public:
-  bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) {
-    if (BE->getValue())
-      Match("true", BE->getLocation());
-    else
-      Match("false", BE->getLocation());
-    return true;
-  }
-};
-
-// Test RAV visits parameter variable declaration of the implicit
-// copy assignment operator and implicit copy constructor.
-TEST(RecursiveASTVisitor, VisitsParmVarDeclForImplicitCode) {
-  ParmVarDeclVisitorForImplicitCode Visitor;
-  // Match parameter variable name of implicit copy assignment operator and
-  // implicit copy constructor.
-  // This parameter name does not have a valid IdentifierInfo, and shares
-  // same SourceLocation with its class declaration, so we match an empty name
-  // with the class' source location.
-  Visitor.ExpectMatch("", 1, 7);
-  Visitor.ExpectMatch("", 3, 7);
-  EXPECT_TRUE(Visitor.runOver(
-    "class X {};\n"
-    "void foo(X a, X b) {a = b;}\n"
-    "class Y {};\n"
-    "void bar(Y a) {Y b = a;}"));
-}
-
-TEST(RecursiveASTVisitor, VisitsBaseClassDeclarations) {
-  TypeLocVisitor Visitor;
-  Visitor.ExpectMatch("class X", 1, 30);
-  EXPECT_TRUE(Visitor.runOver("class X {}; class Y : public X {};"));
-}
-
-TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfForwardDeclaredClass) {
-  TypeLocVisitor Visitor;
-  Visitor.ExpectMatch("class X", 3, 18);
-  EXPECT_TRUE(Visitor.runOver(
-    "class Y;\n"
-    "class X {};\n"
-    "class Y : public X {};"));
-}
-
-TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersWithIncompleteInnerClass) {
-  TypeLocVisitor Visitor;
-  Visitor.ExpectMatch("class X", 2, 18);
-  EXPECT_TRUE(Visitor.runOver(
-    "class X {};\n"
-    "class Y : public X { class Z; };"));
-}
-
-TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfSelfReferentialType) {
-  TypeLocVisitor Visitor;
-  Visitor.ExpectMatch("X<class Y>", 2, 18);
-  EXPECT_TRUE(Visitor.runOver(
-    "template<typename T> class X {};\n"
-    "class Y : public X<Y> {};"));
-}
-
-TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
-  DeclRefExprVisitor Visitor;
-  Visitor.ExpectMatch("x", 2, 3);
-  EXPECT_TRUE(Visitor.runOver(
-    "void x(); template <void (*T)()> class X {};\nX<x> y;"));
-}
-
-TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) {
-  DeclRefExprVisitor Visitor;
-  Visitor.ExpectMatch("x", 2, 25);
-  Visitor.ExpectMatch("x", 2, 30);
-  EXPECT_TRUE(Visitor.runOver(
-    "int x[5];\n"
-    "void f() { for (int i : x) { x[0] = 1; } }",
-    DeclRefExprVisitor::Lang_CXX11));
-}
-
-TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) {
-  VarDeclVisitor Visitor;
-  Visitor.ExpectMatch("i", 2, 17);
-  EXPECT_TRUE(Visitor.runOver(
-    "int x[5];\n"
-    "void f() { for (int i : x) {} }",
-    VarDeclVisitor::Lang_CXX11));
-}
-
-TEST(RecursiveASTVisitor, VisitsCallExpr) {
-  DeclRefExprVisitor Visitor;
-  Visitor.ExpectMatch("x", 1, 22);
-  EXPECT_TRUE(Visitor.runOver(
-    "void x(); void y() { x(); }"));
-}
-
-TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) {
-  CXXMemberCallVisitor Visitor;
-  Visitor.ExpectMatch("Y::x", 3, 3);
-  EXPECT_TRUE(Visitor.runOver(
-    "struct Y { void x(); };\n"
-    "template<typename T> void y(T t) {\n"
-    "  t.x();\n"
-    "}\n"
-    "void foo() { y<Y>(Y()); }"));
-}
-
-TEST(RecursiveASTVisitor, VisitsCallInNestedFunctionTemplateInstantiation) {
-  CXXMemberCallVisitor Visitor;
-  Visitor.ExpectMatch("Y::x", 4, 5);
-  EXPECT_TRUE(Visitor.runOver(
-    "struct Y { void x(); };\n"
-    "template<typename T> struct Z {\n"
-    "  template<typename U> static void f() {\n"
-    "    T().x();\n"
-    "  }\n"
-    "};\n"
-    "void foo() { Z<Y>::f<int>(); }"));
-}
-
-TEST(RecursiveASTVisitor, VisitsCallInNestedClassTemplateInstantiation) {
-  CXXMemberCallVisitor Visitor;
-  Visitor.ExpectMatch("A::x", 5, 7);
-  EXPECT_TRUE(Visitor.runOver(
-    "template <typename T1> struct X {\n"
-    "  template <typename T2> struct Y {\n"
-    "    void f() {\n"
-    "      T2 y;\n"
-    "      y.x();\n"
-    "    }\n"
-    "  };\n"
-    "};\n"
-    "struct A { void x(); };\n"
-    "int main() {\n"
-    "  (new X<A>::Y<A>())->f();\n"
-    "}"));
-}
-
-/* FIXME: According to Richard Smith this is a bug in the AST.
-TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
-  DeclRefExprVisitor Visitor;
-  Visitor.ExpectMatch("x", 3, 43);
-  EXPECT_TRUE(Visitor.runOver(
-    "template <typename T> void x();\n"
-    "template <void (*T)()> class X {};\n"
-    "template <typename T> class Y : public X< x<T> > {};\n"
-    "Y<int> y;"));
-}
-*/
-
-TEST(RecursiveASTVisitor, VisitsCallInPartialTemplateSpecialization) {
-  CXXMemberCallVisitor Visitor;
-  Visitor.ExpectMatch("A::x", 6, 20);
-  EXPECT_TRUE(Visitor.runOver(
-    "template <typename T1> struct X {\n"
-    "  template <typename T2, bool B> struct Y { void g(); };\n"
-    "};\n"
-    "template <typename T1> template <typename T2>\n"
-    "struct X<T1>::Y<T2, true> {\n"
-    "  void f() { T2 y; y.x(); }\n"
-    "};\n"
-    "struct A { void x(); };\n"
-    "int main() {\n"
-    "  (new X<A>::Y<A, true>())->f();\n"
-    "}\n"));
-}
-
-TEST(RecursiveASTVisitor, VisitsExplicitTemplateSpecialization) {
-  CXXMemberCallVisitor Visitor;
-  Visitor.ExpectMatch("A::f", 4, 5);
-  EXPECT_TRUE(Visitor.runOver(
-    "struct A {\n"
-    "  void f() const {}\n"
-    "  template<class T> void g(const T& t) const {\n"
-    "    t.f();\n"
-    "  }\n"
-    "};\n"
-    "template void A::g(const A& a) const;\n"));
-}
-
-TEST(RecursiveASTVisitor, VisitsPartialTemplateSpecialization) {
-  // From cfe-commits/Week-of-Mon-20100830/033998.html
-  // Contrary to the approach suggested in that email, we visit all
-  // specializations when we visit the primary template.  Visiting them when we
-  // visit the associated specialization is problematic for specializations of
-  // template members of class templates.
-  NamedDeclVisitor Visitor;
-  Visitor.ExpectMatch("A<bool>", 1, 26);
-  Visitor.ExpectMatch("A<char *>", 2, 26);
-  EXPECT_TRUE(Visitor.runOver(
-    "template <class T> class A {};\n"
-    "template <class T> class A<T*> {};\n"
-    "A<bool> ab;\n"
-    "A<char*> acp;\n"));
-}
-
-TEST(RecursiveASTVisitor, VisitsUndefinedClassTemplateSpecialization) {
-  NamedDeclVisitor Visitor;
-  Visitor.ExpectMatch("A<int>", 1, 29);
-  EXPECT_TRUE(Visitor.runOver(
-    "template<typename T> struct A;\n"
-    "A<int> *p;\n"));
-}
-
-TEST(RecursiveASTVisitor, VisitsNestedUndefinedClassTemplateSpecialization) {
-  NamedDeclVisitor Visitor;
-  Visitor.ExpectMatch("A<int>::B<char>", 2, 31);
-  EXPECT_TRUE(Visitor.runOver(
-    "template<typename T> struct A {\n"
-    "  template<typename U> struct B;\n"
-    "};\n"
-    "A<int>::B<char> *p;\n"));
-}
-
-TEST(RecursiveASTVisitor, VisitsUndefinedFunctionTemplateSpecialization) {
-  NamedDeclVisitor Visitor;
-  Visitor.ExpectMatch("A<int>", 1, 26);
-  EXPECT_TRUE(Visitor.runOver(
-    "template<typename T> int A();\n"
-    "int k = A<int>();\n"));
-}
-
-TEST(RecursiveASTVisitor, VisitsNestedUndefinedFunctionTemplateSpecialization) {
-  NamedDeclVisitor Visitor;
-  Visitor.ExpectMatch("A<int>::B<char>", 2, 35);
-  EXPECT_TRUE(Visitor.runOver(
-    "template<typename T> struct A {\n"
-    "  template<typename U> static int B();\n"
-    "};\n"
-    "int k = A<int>::B<char>();\n"));
-}
-
-TEST(RecursiveASTVisitor, NoRecursionInSelfFriend) {
-  // From cfe-commits/Week-of-Mon-20100830/033977.html
-  NamedDeclVisitor Visitor;
-  Visitor.ExpectMatch("vector_iterator<int>", 2, 7);
-  EXPECT_TRUE(Visitor.runOver(
-    "template<typename Container>\n"
-    "class vector_iterator {\n"
-    "    template <typename C> friend class vector_iterator;\n"
-    "};\n"
-    "vector_iterator<int> it_int;\n"));
-}
-
-TEST(RecursiveASTVisitor, TraversesOverloadedOperator) {
-  CXXOperatorCallExprTraverser Visitor;
-  Visitor.ExpectMatch("()", 4, 9);
-  EXPECT_TRUE(Visitor.runOver(
-    "struct A {\n"
-    "  int operator()();\n"
-    "} a;\n"
-    "int k = a();\n"));
-}
-
-TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) {
-  ParenExprVisitor Visitor;
-  Visitor.ExpectMatch("", 1, 9);
-  EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n"));
-}
-
-TEST(RecursiveASTVisitor, VisitsClassTemplateNonTypeParmDefaultArgument) {
-  CXXBoolLiteralExprVisitor Visitor;
-  Visitor.ExpectMatch("true", 2, 19);
-  EXPECT_TRUE(Visitor.runOver(
-    "template<bool B> class X;\n"
-    "template<bool B = true> class Y;\n"
-    "template<bool B> class Y {};\n"));
-}
-
-TEST(RecursiveASTVisitor, VisitsClassTemplateTypeParmDefaultArgument) {
-  TypeLocVisitor Visitor;
-  Visitor.ExpectMatch("class X", 2, 23);
-  EXPECT_TRUE(Visitor.runOver(
-    "class X;\n"
-    "template<typename T = X> class Y;\n"
-    "template<typename T> class Y {};\n"));
-}
-
-TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) {
-  TemplateArgumentLocTraverser Visitor;
-  Visitor.ExpectMatch("X", 2, 40);
-  EXPECT_TRUE(Visitor.runOver(
-    "template<typename T> class X;\n"
-    "template<template <typename> class T = X> class Y;\n"
-    "template<template <typename> class T> class Y {};\n"));
-}
-
-// A visitor that visits implicit declarations and matches constructors.
-class ImplicitCtorVisitor
-    : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
-public:
-  bool shouldVisitImplicitCode() const { return true; }
-
-  bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) {
-    if (Ctor->isImplicit()) {  // Was not written in source code
-      if (const CXXRecordDecl* Class = Ctor->getParent()) {
-        Match(Class->getName(), Ctor->getLocation());
-      }
-    }
-    return true;
-  }
-};
-
-TEST(RecursiveASTVisitor, VisitsImplicitCopyConstructors) {
-  ImplicitCtorVisitor Visitor;
-  Visitor.ExpectMatch("Simple", 2, 8);
-  // Note: Clang lazily instantiates implicit declarations, so we need
-  // to use them in order to force them to appear in the AST.
-  EXPECT_TRUE(Visitor.runOver(
-      "struct WithCtor { WithCtor(); }; \n"
-      "struct Simple { Simple(); WithCtor w; }; \n"
-      "int main() { Simple s; Simple t(s); }\n"));
-}
-
-/// \brief A visitor that optionally includes implicit code and matches
-/// CXXConstructExpr.
-///
-/// The name recorded for the match is the name of the class whose constructor
-/// is invoked by the CXXConstructExpr, not the name of the class whose
-/// constructor the CXXConstructExpr is contained in.
-class ConstructExprVisitor
-    : public ExpectedLocationVisitor<ConstructExprVisitor> {
-public:
-  ConstructExprVisitor() : ShouldVisitImplicitCode(false) {}
-
-  bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
-
-  void setShouldVisitImplicitCode(bool NewValue) {
-    ShouldVisitImplicitCode = NewValue;
-  }
-
-  bool VisitCXXConstructExpr(CXXConstructExpr* Expr) {
-    if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) {
-      if (const CXXRecordDecl* Class = Ctor->getParent()) {
-        Match(Class->getName(), Expr->getLocation());
-      }
-    }
-    return true;
-  }
-
- private:
-  bool ShouldVisitImplicitCode;
-};
-
-TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
-  ConstructExprVisitor Visitor;
-  Visitor.setShouldVisitImplicitCode(true);
-  Visitor.ExpectMatch("WithCtor", 2, 8);
-  // Simple has a constructor that implicitly initializes 'w'.  Test
-  // that a visitor that visits implicit code visits that initialization.
-  // Note: Clang lazily instantiates implicit declarations, so we need
-  // to use them in order to force them to appear in the AST.
-  EXPECT_TRUE(Visitor.runOver(
-      "struct WithCtor { WithCtor(); }; \n"
-      "struct Simple { WithCtor w; }; \n"
-      "int main() { Simple s; }\n"));
-}
-
-// The same as CanVisitImplicitMemberInitializations, but checking that the
-// visits are omitted when the visitor does not include implicit code.
-TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
-  ConstructExprVisitor Visitor;
-  Visitor.setShouldVisitImplicitCode(false);
-  Visitor.DisallowMatch("WithCtor", 2, 8);
-  // Simple has a constructor that implicitly initializes 'w'.  Test
-  // that a visitor that skips implicit code skips that initialization.
-  // Note: Clang lazily instantiates implicit declarations, so we need
-  // to use them in order to force them to appear in the AST.
-  EXPECT_TRUE(Visitor.runOver(
-      "struct WithCtor { WithCtor(); }; \n"
-      "struct Simple { WithCtor w; }; \n"
-      "int main() { Simple s; }\n"));
-}
-
-TEST(RecursiveASTVisitor, VisitsExtension) {
-  DeclRefExprVisitor Visitor;
-  Visitor.ExpectMatch("s", 1, 24);
-  EXPECT_TRUE(Visitor.runOver(
-    "int s = __extension__ (s);\n"));
-}
-
-TEST(RecursiveASTVisitor, VisitsCompoundLiteralType) {
-  TypeLocVisitor Visitor;
-  Visitor.ExpectMatch("struct S", 1, 26);
-  EXPECT_TRUE(Visitor.runOver(
-      "int f() { return (struct S { int a; }){.a = 0}.a; }",
-      TypeLocVisitor::Lang_C));
-}
-
-TEST(RecursiveASTVisitor, VisitsObjCPropertyType) {
-  TypeLocVisitor Visitor;
-  Visitor.ExpectMatch("NSNumber", 2, 33);
-  EXPECT_TRUE(Visitor.runOver(
-      "@class NSNumber; \n"
-      "@interface A @property (retain) NSNumber *x; @end\n",
-      TypeLocVisitor::Lang_OBJC));
-}
-
 TEST(RecursiveASTVisitor, VisitsLambdaExpr) {
   LambdaExprVisitor Visitor;
   Visitor.ExpectMatch("", 1, 12);
@@ -554,6 +52,18 @@ TEST(RecursiveASTVisitor, TraverseLambdaBodyCanBeOverridden) {
   EXPECT_TRUE(Visitor.allBodiesHaveBeenTraversed());
 }
 
+// Matches the (optional) capture-default of a lambda-introducer.
+class LambdaDefaultCaptureVisitor
+  : public ExpectedLocationVisitor<LambdaDefaultCaptureVisitor> {
+public:
+  bool VisitLambdaExpr(LambdaExpr *Lambda) {
+    if (Lambda->getCaptureDefault() != LCD_None) {
+      Match("", Lambda->getCaptureDefaultLoc());
+    }
+    return true;
+  }
+};
+
 TEST(RecursiveASTVisitor, HasCaptureDefaultLoc) {
   LambdaDefaultCaptureVisitor Visitor;
   Visitor.ExpectMatch("", 1, 20);
@@ -561,16 +71,6 @@ TEST(RecursiveASTVisitor, HasCaptureDefaultLoc) {
                               LambdaDefaultCaptureVisitor::Lang_CXX11));
 }
 
-TEST(RecursiveASTVisitor, VisitsCopyExprOfBlockDeclCapture) {
-  DeclRefExprVisitor Visitor;
-  Visitor.ExpectMatch("x", 3, 24);
-  EXPECT_TRUE(Visitor.runOver("void f(int(^)(int)); \n"
-                              "void g() { \n"
-                              "  f([&](int x){ return x; }); \n"
-                              "}",
-                              DeclRefExprVisitor::Lang_OBJCXX11));
-}
-
 // Checks for lambda classes that are not marked as implicitly-generated.
 // (There should be none.)
 class ClassVisitor : public ExpectedLocationVisitor<ClassVisitor> {
@@ -598,7 +98,6 @@ TEST(RecursiveASTVisitor, LambdaClosureTypesAreImplicit) {
 }
 
 
-
 // Check to ensure that attributes and expressions within them are being
 // visited.
 class AttrVisitor : public ExpectedLocationVisitor<AttrVisitor> {
diff --git a/unittests/Tooling/RecursiveASTVisitorTestCallVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestCallVisitor.cpp
new file mode 100644 (file)
index 0000000..f8ff5bd
--- /dev/null
@@ -0,0 +1,121 @@
+//===- unittest/Tooling/RecursiveASTVisitorTestCallVisitor.cpp ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+#include <stack>
+
+using namespace clang;
+
+namespace {
+
+class CXXMemberCallVisitor
+  : public ExpectedLocationVisitor<CXXMemberCallVisitor> {
+public:
+  bool VisitCXXMemberCallExpr(CXXMemberCallExpr *Call) {
+    Match(Call->getMethodDecl()->getQualifiedNameAsString(),
+          Call->getLocStart());
+    return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsCallInTemplateInstantiation) {
+  CXXMemberCallVisitor Visitor;
+  Visitor.ExpectMatch("Y::x", 3, 3);
+  EXPECT_TRUE(Visitor.runOver(
+    "struct Y { void x(); };\n"
+    "template<typename T> void y(T t) {\n"
+    "  t.x();\n"
+    "}\n"
+    "void foo() { y<Y>(Y()); }"));
+}
+
+TEST(RecursiveASTVisitor, VisitsCallInNestedFunctionTemplateInstantiation) {
+  CXXMemberCallVisitor Visitor;
+  Visitor.ExpectMatch("Y::x", 4, 5);
+  EXPECT_TRUE(Visitor.runOver(
+    "struct Y { void x(); };\n"
+    "template<typename T> struct Z {\n"
+    "  template<typename U> static void f() {\n"
+    "    T().x();\n"
+    "  }\n"
+    "};\n"
+    "void foo() { Z<Y>::f<int>(); }"));
+}
+
+TEST(RecursiveASTVisitor, VisitsCallInNestedClassTemplateInstantiation) {
+  CXXMemberCallVisitor Visitor;
+  Visitor.ExpectMatch("A::x", 5, 7);
+  EXPECT_TRUE(Visitor.runOver(
+    "template <typename T1> struct X {\n"
+    "  template <typename T2> struct Y {\n"
+    "    void f() {\n"
+    "      T2 y;\n"
+    "      y.x();\n"
+    "    }\n"
+    "  };\n"
+    "};\n"
+    "struct A { void x(); };\n"
+    "int main() {\n"
+    "  (new X<A>::Y<A>())->f();\n"
+    "}"));
+}
+
+TEST(RecursiveASTVisitor, VisitsCallInPartialTemplateSpecialization) {
+  CXXMemberCallVisitor Visitor;
+  Visitor.ExpectMatch("A::x", 6, 20);
+  EXPECT_TRUE(Visitor.runOver(
+    "template <typename T1> struct X {\n"
+    "  template <typename T2, bool B> struct Y { void g(); };\n"
+    "};\n"
+    "template <typename T1> template <typename T2>\n"
+    "struct X<T1>::Y<T2, true> {\n"
+    "  void f() { T2 y; y.x(); }\n"
+    "};\n"
+    "struct A { void x(); };\n"
+    "int main() {\n"
+    "  (new X<A>::Y<A, true>())->f();\n"
+    "}\n"));
+}
+
+TEST(RecursiveASTVisitor, VisitsExplicitTemplateSpecialization) {
+  CXXMemberCallVisitor Visitor;
+  Visitor.ExpectMatch("A::f", 4, 5);
+  EXPECT_TRUE(Visitor.runOver(
+    "struct A {\n"
+    "  void f() const {}\n"
+    "  template<class T> void g(const T& t) const {\n"
+    "    t.f();\n"
+    "  }\n"
+    "};\n"
+    "template void A::g(const A& a) const;\n"));
+}
+
+class CXXOperatorCallExprTraverser
+  : public ExpectedLocationVisitor<CXXOperatorCallExprTraverser> {
+public:
+  // Use Traverse, not Visit, to check that data recursion optimization isn't
+  // bypassing the call of this function.
+  bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *CE) {
+    Match(getOperatorSpelling(CE->getOperator()), CE->getExprLoc());
+    return ExpectedLocationVisitor<CXXOperatorCallExprTraverser>::
+        TraverseCXXOperatorCallExpr(CE);
+  }
+};
+
+TEST(RecursiveASTVisitor, TraversesOverloadedOperator) {
+  CXXOperatorCallExprTraverser Visitor;
+  Visitor.ExpectMatch("()", 4, 9);
+  EXPECT_TRUE(Visitor.runOver(
+    "struct A {\n"
+    "  int operator()();\n"
+    "} a;\n"
+    "int k = a();\n"));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp
new file mode 100644 (file)
index 0000000..02676a7
--- /dev/null
@@ -0,0 +1,141 @@
+//===- unittest/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+#include <stack>
+
+using namespace clang;
+
+namespace {
+
+class VarDeclVisitor : public ExpectedLocationVisitor<VarDeclVisitor> {
+public:
+ bool VisitVarDecl(VarDecl *Variable) {
+   Match(Variable->getNameAsString(), Variable->getLocStart());
+   return true;
+ }
+};
+
+TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtLoopVariable) {
+  VarDeclVisitor Visitor;
+  Visitor.ExpectMatch("i", 2, 17);
+  EXPECT_TRUE(Visitor.runOver(
+    "int x[5];\n"
+    "void f() { for (int i : x) {} }",
+    VarDeclVisitor::Lang_CXX11));
+}
+
+class ParmVarDeclVisitorForImplicitCode :
+  public ExpectedLocationVisitor<ParmVarDeclVisitorForImplicitCode> {
+public:
+  bool shouldVisitImplicitCode() const { return true; }
+
+  bool VisitParmVarDecl(ParmVarDecl *ParamVar) {
+    Match(ParamVar->getNameAsString(), ParamVar->getLocStart());
+    return true;
+  }
+};
+
+// Test RAV visits parameter variable declaration of the implicit
+// copy assignment operator and implicit copy constructor.
+TEST(RecursiveASTVisitor, VisitsParmVarDeclForImplicitCode) {
+  ParmVarDeclVisitorForImplicitCode Visitor;
+  // Match parameter variable name of implicit copy assignment operator and
+  // implicit copy constructor.
+  // This parameter name does not have a valid IdentifierInfo, and shares
+  // same SourceLocation with its class declaration, so we match an empty name
+  // with the class' source location.
+  Visitor.ExpectMatch("", 1, 7);
+  Visitor.ExpectMatch("", 3, 7);
+  EXPECT_TRUE(Visitor.runOver(
+    "class X {};\n"
+    "void foo(X a, X b) {a = b;}\n"
+    "class Y {};\n"
+    "void bar(Y a) {Y b = a;}"));
+}
+
+class NamedDeclVisitor
+  : public ExpectedLocationVisitor<NamedDeclVisitor> {
+public:
+  bool VisitNamedDecl(NamedDecl *Decl) {
+    std::string NameWithTemplateArgs;
+    llvm::raw_string_ostream OS(NameWithTemplateArgs);
+    Decl->getNameForDiagnostic(OS,
+                               Decl->getASTContext().getPrintingPolicy(),
+                               true);
+    Match(OS.str(), Decl->getLocation());
+    return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsPartialTemplateSpecialization) {
+  // From cfe-commits/Week-of-Mon-20100830/033998.html
+  // Contrary to the approach suggested in that email, we visit all
+  // specializations when we visit the primary template.  Visiting them when we
+  // visit the associated specialization is problematic for specializations of
+  // template members of class templates.
+  NamedDeclVisitor Visitor;
+  Visitor.ExpectMatch("A<bool>", 1, 26);
+  Visitor.ExpectMatch("A<char *>", 2, 26);
+  EXPECT_TRUE(Visitor.runOver(
+    "template <class T> class A {};\n"
+    "template <class T> class A<T*> {};\n"
+    "A<bool> ab;\n"
+    "A<char*> acp;\n"));
+}
+
+TEST(RecursiveASTVisitor, VisitsUndefinedClassTemplateSpecialization) {
+  NamedDeclVisitor Visitor;
+  Visitor.ExpectMatch("A<int>", 1, 29);
+  EXPECT_TRUE(Visitor.runOver(
+    "template<typename T> struct A;\n"
+    "A<int> *p;\n"));
+}
+
+TEST(RecursiveASTVisitor, VisitsNestedUndefinedClassTemplateSpecialization) {
+  NamedDeclVisitor Visitor;
+  Visitor.ExpectMatch("A<int>::B<char>", 2, 31);
+  EXPECT_TRUE(Visitor.runOver(
+    "template<typename T> struct A {\n"
+    "  template<typename U> struct B;\n"
+    "};\n"
+    "A<int>::B<char> *p;\n"));
+}
+
+TEST(RecursiveASTVisitor, VisitsUndefinedFunctionTemplateSpecialization) {
+  NamedDeclVisitor Visitor;
+  Visitor.ExpectMatch("A<int>", 1, 26);
+  EXPECT_TRUE(Visitor.runOver(
+    "template<typename T> int A();\n"
+    "int k = A<int>();\n"));
+}
+
+TEST(RecursiveASTVisitor, VisitsNestedUndefinedFunctionTemplateSpecialization) {
+  NamedDeclVisitor Visitor;
+  Visitor.ExpectMatch("A<int>::B<char>", 2, 35);
+  EXPECT_TRUE(Visitor.runOver(
+    "template<typename T> struct A {\n"
+    "  template<typename U> static int B();\n"
+    "};\n"
+    "int k = A<int>::B<char>();\n"));
+}
+
+TEST(RecursiveASTVisitor, NoRecursionInSelfFriend) {
+  // From cfe-commits/Week-of-Mon-20100830/033977.html
+  NamedDeclVisitor Visitor;
+  Visitor.ExpectMatch("vector_iterator<int>", 2, 7);
+  EXPECT_TRUE(Visitor.runOver(
+    "template<typename Container>\n"
+    "class vector_iterator {\n"
+    "    template <typename C> friend class vector_iterator;\n"
+    "};\n"
+    "vector_iterator<int> it_int;\n"));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp
new file mode 100644 (file)
index 0000000..6af5906
--- /dev/null
@@ -0,0 +1,224 @@
+//===- unittest/Tooling/RecursiveASTVisitorTestExprVisitor.cpp ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+#include <stack>
+
+using namespace clang;
+
+namespace {
+
+class ParenExprVisitor : public ExpectedLocationVisitor<ParenExprVisitor> {
+public:
+  bool VisitParenExpr(ParenExpr *Parens) {
+    Match("", Parens->getExprLoc());
+    return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsParensDuringDataRecursion) {
+  ParenExprVisitor Visitor;
+  Visitor.ExpectMatch("", 1, 9);
+  EXPECT_TRUE(Visitor.runOver("int k = (4) + 9;\n"));
+}
+
+class TemplateArgumentLocTraverser
+  : public ExpectedLocationVisitor<TemplateArgumentLocTraverser> {
+public:
+  bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
+    std::string ArgStr;
+    llvm::raw_string_ostream Stream(ArgStr);
+    const TemplateArgument &Arg = ArgLoc.getArgument();
+
+    Arg.print(Context->getPrintingPolicy(), Stream);
+    Match(Stream.str(), ArgLoc.getLocation());
+    return ExpectedLocationVisitor<TemplateArgumentLocTraverser>::
+      TraverseTemplateArgumentLoc(ArgLoc);
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsClassTemplateTemplateParmDefaultArgument) {
+  TemplateArgumentLocTraverser Visitor;
+  Visitor.ExpectMatch("X", 2, 40);
+  EXPECT_TRUE(Visitor.runOver(
+    "template<typename T> class X;\n"
+    "template<template <typename> class T = X> class Y;\n"
+    "template<template <typename> class T> class Y {};\n"));
+}
+
+class CXXBoolLiteralExprVisitor 
+  : public ExpectedLocationVisitor<CXXBoolLiteralExprVisitor> {
+public:
+  bool VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *BE) {
+    if (BE->getValue())
+      Match("true", BE->getLocation());
+    else
+      Match("false", BE->getLocation());
+    return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsClassTemplateNonTypeParmDefaultArgument) {
+  CXXBoolLiteralExprVisitor Visitor;
+  Visitor.ExpectMatch("true", 2, 19);
+  EXPECT_TRUE(Visitor.runOver(
+    "template<bool B> class X;\n"
+    "template<bool B = true> class Y;\n"
+    "template<bool B> class Y {};\n"));
+}
+
+// A visitor that visits implicit declarations and matches constructors.
+class ImplicitCtorVisitor
+    : public ExpectedLocationVisitor<ImplicitCtorVisitor> {
+public:
+  bool shouldVisitImplicitCode() const { return true; }
+
+  bool VisitCXXConstructorDecl(CXXConstructorDecl* Ctor) {
+    if (Ctor->isImplicit()) {  // Was not written in source code
+      if (const CXXRecordDecl* Class = Ctor->getParent()) {
+        Match(Class->getName(), Ctor->getLocation());
+      }
+    }
+    return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsImplicitCopyConstructors) {
+  ImplicitCtorVisitor Visitor;
+  Visitor.ExpectMatch("Simple", 2, 8);
+  // Note: Clang lazily instantiates implicit declarations, so we need
+  // to use them in order to force them to appear in the AST.
+  EXPECT_TRUE(Visitor.runOver(
+      "struct WithCtor { WithCtor(); }; \n"
+      "struct Simple { Simple(); WithCtor w; }; \n"
+      "int main() { Simple s; Simple t(s); }\n"));
+}
+
+/// \brief A visitor that optionally includes implicit code and matches
+/// CXXConstructExpr.
+///
+/// The name recorded for the match is the name of the class whose constructor
+/// is invoked by the CXXConstructExpr, not the name of the class whose
+/// constructor the CXXConstructExpr is contained in.
+class ConstructExprVisitor
+    : public ExpectedLocationVisitor<ConstructExprVisitor> {
+public:
+  ConstructExprVisitor() : ShouldVisitImplicitCode(false) {}
+
+  bool shouldVisitImplicitCode() const { return ShouldVisitImplicitCode; }
+
+  void setShouldVisitImplicitCode(bool NewValue) {
+    ShouldVisitImplicitCode = NewValue;
+  }
+
+  bool VisitCXXConstructExpr(CXXConstructExpr* Expr) {
+    if (const CXXConstructorDecl* Ctor = Expr->getConstructor()) {
+      if (const CXXRecordDecl* Class = Ctor->getParent()) {
+        Match(Class->getName(), Expr->getLocation());
+      }
+    }
+    return true;
+  }
+
+ private:
+  bool ShouldVisitImplicitCode;
+};
+
+TEST(RecursiveASTVisitor, CanVisitImplicitMemberInitializations) {
+  ConstructExprVisitor Visitor;
+  Visitor.setShouldVisitImplicitCode(true);
+  Visitor.ExpectMatch("WithCtor", 2, 8);
+  // Simple has a constructor that implicitly initializes 'w'.  Test
+  // that a visitor that visits implicit code visits that initialization.
+  // Note: Clang lazily instantiates implicit declarations, so we need
+  // to use them in order to force them to appear in the AST.
+  EXPECT_TRUE(Visitor.runOver(
+      "struct WithCtor { WithCtor(); }; \n"
+      "struct Simple { WithCtor w; }; \n"
+      "int main() { Simple s; }\n"));
+}
+
+// The same as CanVisitImplicitMemberInitializations, but checking that the
+// visits are omitted when the visitor does not include implicit code.
+TEST(RecursiveASTVisitor, CanSkipImplicitMemberInitializations) {
+  ConstructExprVisitor Visitor;
+  Visitor.setShouldVisitImplicitCode(false);
+  Visitor.DisallowMatch("WithCtor", 2, 8);
+  // Simple has a constructor that implicitly initializes 'w'.  Test
+  // that a visitor that skips implicit code skips that initialization.
+  // Note: Clang lazily instantiates implicit declarations, so we need
+  // to use them in order to force them to appear in the AST.
+  EXPECT_TRUE(Visitor.runOver(
+      "struct WithCtor { WithCtor(); }; \n"
+      "struct Simple { WithCtor w; }; \n"
+      "int main() { Simple s; }\n"));
+}
+
+class DeclRefExprVisitor : public ExpectedLocationVisitor<DeclRefExprVisitor> {
+public:
+  bool VisitDeclRefExpr(DeclRefExpr *Reference) {
+    Match(Reference->getNameInfo().getAsString(), Reference->getLocation());
+    return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArguments) {
+  DeclRefExprVisitor Visitor;
+  Visitor.ExpectMatch("x", 2, 3);
+  EXPECT_TRUE(Visitor.runOver(
+    "void x(); template <void (*T)()> class X {};\nX<x> y;"));
+}
+
+TEST(RecursiveASTVisitor, VisitsCXXForRangeStmtRange) {
+  DeclRefExprVisitor Visitor;
+  Visitor.ExpectMatch("x", 2, 25);
+  Visitor.ExpectMatch("x", 2, 30);
+  EXPECT_TRUE(Visitor.runOver(
+    "int x[5];\n"
+    "void f() { for (int i : x) { x[0] = 1; } }",
+    DeclRefExprVisitor::Lang_CXX11));
+}
+
+TEST(RecursiveASTVisitor, VisitsCallExpr) {
+  DeclRefExprVisitor Visitor;
+  Visitor.ExpectMatch("x", 1, 22);
+  EXPECT_TRUE(Visitor.runOver(
+    "void x(); void y() { x(); }"));
+}
+
+/* FIXME: According to Richard Smith this is a bug in the AST.
+TEST(RecursiveASTVisitor, VisitsBaseClassTemplateArgumentsInInstantiation) {
+  DeclRefExprVisitor Visitor;
+  Visitor.ExpectMatch("x", 3, 43);
+  EXPECT_TRUE(Visitor.runOver(
+    "template <typename T> void x();\n"
+    "template <void (*T)()> class X {};\n"
+    "template <typename T> class Y : public X< x<T> > {};\n"
+    "Y<int> y;"));
+}
+*/
+
+TEST(RecursiveASTVisitor, VisitsExtension) {
+  DeclRefExprVisitor Visitor;
+  Visitor.ExpectMatch("s", 1, 24);
+  EXPECT_TRUE(Visitor.runOver(
+    "int s = __extension__ (s);\n"));
+}
+
+TEST(RecursiveASTVisitor, VisitsCopyExprOfBlockDeclCapture) {
+  DeclRefExprVisitor Visitor;
+  Visitor.ExpectMatch("x", 3, 24);
+  EXPECT_TRUE(Visitor.runOver("void f(int(^)(int)); \n"
+                              "void g() { \n"
+                              "  f([&](int x){ return x; }); \n"
+                              "}",
+                              DeclRefExprVisitor::Lang_OBJCXX11));
+}
+
+} // end anonymous namespace
diff --git a/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp b/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp
new file mode 100644 (file)
index 0000000..22c5883
--- /dev/null
@@ -0,0 +1,82 @@
+//===- unittest/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp ---------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+#include <stack>
+
+using namespace clang;
+
+namespace {
+
+class TypeLocVisitor : public ExpectedLocationVisitor<TypeLocVisitor> {
+public:
+  bool VisitTypeLoc(TypeLoc TypeLocation) {
+    Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc());
+    return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsBaseClassDeclarations) {
+  TypeLocVisitor Visitor;
+  Visitor.ExpectMatch("class X", 1, 30);
+  EXPECT_TRUE(Visitor.runOver("class X {}; class Y : public X {};"));
+}
+
+TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfForwardDeclaredClass) {
+  TypeLocVisitor Visitor;
+  Visitor.ExpectMatch("class X", 3, 18);
+  EXPECT_TRUE(Visitor.runOver(
+    "class Y;\n"
+    "class X {};\n"
+    "class Y : public X {};"));
+}
+
+TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersWithIncompleteInnerClass) {
+  TypeLocVisitor Visitor;
+  Visitor.ExpectMatch("class X", 2, 18);
+  EXPECT_TRUE(Visitor.runOver(
+    "class X {};\n"
+    "class Y : public X { class Z; };"));
+}
+
+TEST(RecursiveASTVisitor, VisitsCXXBaseSpecifiersOfSelfReferentialType) {
+  TypeLocVisitor Visitor;
+  Visitor.ExpectMatch("X<class Y>", 2, 18);
+  EXPECT_TRUE(Visitor.runOver(
+    "template<typename T> class X {};\n"
+    "class Y : public X<Y> {};"));
+}
+
+TEST(RecursiveASTVisitor, VisitsClassTemplateTypeParmDefaultArgument) {
+  TypeLocVisitor Visitor;
+  Visitor.ExpectMatch("class X", 2, 23);
+  EXPECT_TRUE(Visitor.runOver(
+    "class X;\n"
+    "template<typename T = X> class Y;\n"
+    "template<typename T> class Y {};\n"));
+}
+
+TEST(RecursiveASTVisitor, VisitsCompoundLiteralType) {
+  TypeLocVisitor Visitor;
+  Visitor.ExpectMatch("struct S", 1, 26);
+  EXPECT_TRUE(Visitor.runOver(
+      "int f() { return (struct S { int a; }){.a = 0}.a; }",
+      TypeLocVisitor::Lang_C));
+}
+
+TEST(RecursiveASTVisitor, VisitsObjCPropertyType) {
+  TypeLocVisitor Visitor;
+  Visitor.ExpectMatch("NSNumber", 2, 33);
+  EXPECT_TRUE(Visitor.runOver(
+      "@class NSNumber; \n"
+      "@interface A @property (retain) NSNumber *x; @end\n",
+      TypeLocVisitor::Lang_OBJC));
+}
+
+} // end anonymous namespace
index 7680d075477e8dbcbbd9462cd2cca81673bc284f..d4416950f226351f81a3a1728a54743ae5cf1d94 100644 (file)
@@ -231,4 +231,4 @@ protected:
 };
 }
 
-#endif /* LLVM_CLANG_TEST_VISITOR_H */
+#endif