diff options
Diffstat (limited to 'unittests/Tooling')
-rw-r--r-- | unittests/Tooling/CMakeLists.txt | 5 | ||||
-rw-r--r-- | unittests/Tooling/Makefile | 3 | ||||
-rw-r--r-- | unittests/Tooling/RecursiveASTVisitorTest.cpp | 525 | ||||
-rw-r--r-- | unittests/Tooling/RecursiveASTVisitorTestCallVisitor.cpp | 121 | ||||
-rw-r--r-- | unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp | 141 | ||||
-rw-r--r-- | unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp | 224 | ||||
-rw-r--r-- | unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp | 93 | ||||
-rw-r--r-- | unittests/Tooling/RefactoringTest.cpp | 23 | ||||
-rw-r--r-- | unittests/Tooling/RewriterTestContext.h | 17 | ||||
-rw-r--r-- | unittests/Tooling/TestVisitor.h | 12 | ||||
-rw-r--r-- | unittests/Tooling/ToolingTest.cpp | 85 |
11 files changed, 667 insertions, 582 deletions
diff --git a/unittests/Tooling/CMakeLists.txt b/unittests/Tooling/CMakeLists.txt index a41d87c..469e6a9 100644 --- a/unittests/Tooling/CMakeLists.txt +++ b/unittests/Tooling/CMakeLists.txt @@ -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 @@ -21,4 +25,5 @@ target_link_libraries(ToolingTests clangLex clangRewrite clangTooling + clangToolingCore ) diff --git a/unittests/Tooling/Makefile b/unittests/Tooling/Makefile index 46af8a1..514e80b 100644 --- a/unittests/Tooling/Makefile +++ b/unittests/Tooling/Makefile @@ -11,7 +11,8 @@ CLANG_LEVEL = ../.. TESTNAME = Tooling include $(CLANG_LEVEL)/../../Makefile.config LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option -USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \ +USEDLIBS = clangTooling.a clangToolingCore.a clangFrontend.a \ + clangSerialization.a clangDriver.a \ clangParse.a clangRewrite.a clangRewriteFrontend.a \ clangSema.a clangAnalysis.a clangEdit.a \ clangAST.a clangASTMatchers.a clangLex.a clangBasic.a diff --git a/unittests/Tooling/RecursiveASTVisitorTest.cpp b/unittests/Tooling/RecursiveASTVisitorTest.cpp index a1a93a5..c287045 100644 --- a/unittests/Tooling/RecursiveASTVisitorTest.cpp +++ b/unittests/Tooling/RecursiveASTVisitorTest.cpp @@ -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 index 0000000..f8ff5bd --- /dev/null +++ b/unittests/Tooling/RecursiveASTVisitorTestCallVisitor.cpp @@ -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 index 0000000..02676a7 --- /dev/null +++ b/unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp @@ -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 index 0000000..6af5906 --- /dev/null +++ b/unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp @@ -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 index 0000000..63e2e8b --- /dev/null +++ b/unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp @@ -0,0 +1,93 @@ +//===- 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)); +} + +TEST(RecursiveASTVisitor, VisitInvalidType) { + TypeLocVisitor Visitor; + // FIXME: It would be nice to have information about subtypes of invalid type + //Visitor.ExpectMatch("typeof(struct F *) []", 1, 1); + // Even if the full type is invalid, it should still find sub types + //Visitor.ExpectMatch("struct F", 1, 19); + EXPECT_FALSE(Visitor.runOver( + "__typeof__(struct F*) var[invalid];\n", + TypeLocVisitor::Lang_C)); +} + +} // end anonymous namespace diff --git a/unittests/Tooling/RefactoringTest.cpp b/unittests/Tooling/RefactoringTest.cpp index ddb974a..a026a94 100644 --- a/unittests/Tooling/RefactoringTest.cpp +++ b/unittests/Tooling/RefactoringTest.cpp @@ -237,7 +237,8 @@ public: const FileEntry *File = Context.Files.getFile(Path); assert(File != nullptr); - StringRef Found = TemporaryFiles.GetOrCreateValue(Name, Path.str()).second; + StringRef Found = + TemporaryFiles.insert(std::make_pair(Name, Path.str())).first->second; assert(Found == Path); (void)Found; return Context.Sources.createFileID(File, SourceLocation(), SrcMgr::C_User); @@ -251,9 +252,8 @@ public: // descriptor, which might not see the changes made. // FIXME: Figure out whether there is a way to get the SourceManger to // reopen the file. - std::unique_ptr<const llvm::MemoryBuffer> FileBuffer( - Context.Files.getBufferForFile(Path, nullptr)); - return FileBuffer->getBuffer(); + auto FileBuffer = Context.Files.getBufferForFile(Path); + return (*FileBuffer)->getBuffer(); } llvm::StringMap<std::string> TemporaryFiles; @@ -299,11 +299,12 @@ private: public: TestAction(TestVisitor *Visitor) : Visitor(Visitor) {} - virtual clang::ASTConsumer* CreateASTConsumer( - clang::CompilerInstance& compiler, llvm::StringRef dummy) { + virtual std::unique_ptr<clang::ASTConsumer> + CreateASTConsumer(clang::CompilerInstance &compiler, + llvm::StringRef dummy) { Visitor->SM = &compiler.getSourceManager(); /// TestConsumer will be deleted by the framework calling us. - return new FindConsumer(Visitor); + return llvm::make_unique<FindConsumer>(Visitor); } private: @@ -392,6 +393,8 @@ TEST(DeduplicateTest, removesDuplicates) { Input.push_back(Replacement("fileA", 50, 0, " foo ")); // Duplicate Input.push_back(Replacement("fileA", 51, 3, " bar ")); Input.push_back(Replacement("fileB", 51, 3, " bar ")); // Filename differs! + Input.push_back(Replacement("fileB", 60, 1, " bar ")); + Input.push_back(Replacement("fileA", 60, 2, " bar ")); Input.push_back(Replacement("fileA", 51, 3, " moo ")); // Replacement text // differs! @@ -402,12 +405,14 @@ TEST(DeduplicateTest, removesDuplicates) { Expected.push_back(Replacement("fileA", 50, 0, " foo ")); Expected.push_back(Replacement("fileA", 51, 3, " bar ")); Expected.push_back(Replacement("fileA", 51, 3, " moo ")); - Expected.push_back(Replacement("fileB", 51, 3, " bar ")); + Expected.push_back(Replacement("fileB", 60, 1, " bar ")); + Expected.push_back(Replacement("fileA", 60, 2, " bar ")); std::vector<Range> Conflicts; // Ignored for this test deduplicate(Input, Conflicts); - ASSERT_TRUE(Expected == Input); + EXPECT_EQ(3U, Conflicts.size()); + EXPECT_EQ(Expected, Input); } TEST(DeduplicateTest, detectsConflicts) { diff --git a/unittests/Tooling/RewriterTestContext.h b/unittests/Tooling/RewriterTestContext.h index fe108ad..112efac 100644 --- a/unittests/Tooling/RewriterTestContext.h +++ b/unittests/Tooling/RewriterTestContext.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_REWRITER_TEST_CONTEXT_H -#define LLVM_CLANG_REWRITER_TEST_CONTEXT_H +#ifndef LLVM_CLANG_UNITTESTS_TOOLING_REWRITERTESTCONTEXT_H +#define LLVM_CLANG_UNITTESTS_TOOLING_REWRITERTESTCONTEXT_H #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" @@ -48,10 +48,11 @@ class RewriterTestContext { ~RewriterTestContext() {} FileID createInMemoryFile(StringRef Name, StringRef Content) { - llvm::MemoryBuffer *Source = llvm::MemoryBuffer::getMemBuffer(Content); + std::unique_ptr<llvm::MemoryBuffer> Source = + llvm::MemoryBuffer::getMemBuffer(Content); const FileEntry *Entry = Files.getVirtualFile(Name, Source->getBufferSize(), 0); - Sources.overrideFileContents(Entry, Source); + Sources.overrideFileContents(Entry, std::move(Source)); assert(Entry != nullptr); return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User); } @@ -71,7 +72,8 @@ class RewriterTestContext { const FileEntry *File = Files.getFile(Path); assert(File != nullptr); - StringRef Found = TemporaryFiles.GetOrCreateValue(Name, Path.str()).second; + StringRef Found = + TemporaryFiles.insert(std::make_pair(Name, Path.str())).first->second; assert(Found == Path); (void)Found; return Sources.createFileID(File, SourceLocation(), SrcMgr::C_User); @@ -100,9 +102,8 @@ class RewriterTestContext { // descriptor, which might not see the changes made. // FIXME: Figure out whether there is a way to get the SourceManger to // reopen the file. - std::unique_ptr<const llvm::MemoryBuffer> FileBuffer( - Files.getBufferForFile(Path, nullptr)); - return FileBuffer->getBuffer(); + auto FileBuffer = Files.getBufferForFile(Path); + return (*FileBuffer)->getBuffer(); } IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; diff --git a/unittests/Tooling/TestVisitor.h b/unittests/Tooling/TestVisitor.h index 205a0aa..d441695 100644 --- a/unittests/Tooling/TestVisitor.h +++ b/unittests/Tooling/TestVisitor.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TEST_VISITOR_H -#define LLVM_CLANG_TEST_VISITOR_H +#ifndef LLVM_CLANG_UNITTESTS_TOOLING_TESTVISITOR_H +#define LLVM_CLANG_UNITTESTS_TOOLING_TESTVISITOR_H #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" @@ -95,10 +95,10 @@ protected: public: TestAction(TestVisitor *Visitor) : Visitor(Visitor) {} - virtual clang::ASTConsumer* CreateASTConsumer( - CompilerInstance&, llvm::StringRef dummy) { + virtual std::unique_ptr<clang::ASTConsumer> + CreateASTConsumer(CompilerInstance &, llvm::StringRef dummy) { /// TestConsumer will be deleted by the framework calling us. - return new FindConsumer(Visitor); + return llvm::make_unique<FindConsumer>(Visitor); } protected: @@ -231,4 +231,4 @@ protected: }; } -#endif /* LLVM_CLANG_TEST_VISITOR_H */ +#endif diff --git a/unittests/Tooling/ToolingTest.cpp b/unittests/Tooling/ToolingTest.cpp index 9aede04..5a93e38 100644 --- a/unittests/Tooling/ToolingTest.cpp +++ b/unittests/Tooling/ToolingTest.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Config/llvm-config.h" #include "gtest/gtest.h" +#include <algorithm> #include <string> namespace clang { @@ -28,20 +29,20 @@ namespace { /// Takes an ast consumer and returns it from CreateASTConsumer. This only /// works with single translation unit compilations. class TestAction : public clang::ASTFrontendAction { - public: +public: /// Takes ownership of TestConsumer. - explicit TestAction(clang::ASTConsumer *TestConsumer) - : TestConsumer(TestConsumer) {} + explicit TestAction(std::unique_ptr<clang::ASTConsumer> TestConsumer) + : TestConsumer(std::move(TestConsumer)) {} - protected: - virtual clang::ASTConsumer* CreateASTConsumer( - clang::CompilerInstance& compiler, StringRef dummy) { +protected: + virtual std::unique_ptr<clang::ASTConsumer> + CreateASTConsumer(clang::CompilerInstance &compiler, StringRef dummy) { /// TestConsumer will be deleted by the framework calling us. - return TestConsumer; + return std::move(TestConsumer); } - private: - clang::ASTConsumer * const TestConsumer; +private: + std::unique_ptr<clang::ASTConsumer> TestConsumer; }; class FindTopLevelDeclConsumer : public clang::ASTConsumer { @@ -59,8 +60,10 @@ class FindTopLevelDeclConsumer : public clang::ASTConsumer { TEST(runToolOnCode, FindsNoTopLevelDeclOnEmptyCode) { bool FoundTopLevelDecl = false; - EXPECT_TRUE(runToolOnCode( - new TestAction(new FindTopLevelDeclConsumer(&FoundTopLevelDecl)), "")); + EXPECT_TRUE( + runToolOnCode(new TestAction(llvm::make_unique<FindTopLevelDeclConsumer>( + &FoundTopLevelDecl)), + "")); EXPECT_FALSE(FoundTopLevelDecl); } @@ -97,13 +100,17 @@ bool FindClassDeclX(ASTUnit *AST) { TEST(runToolOnCode, FindsClassDecl) { bool FoundClassDeclX = false; - EXPECT_TRUE(runToolOnCode(new TestAction( - new FindClassDeclXConsumer(&FoundClassDeclX)), "class X;")); + EXPECT_TRUE( + runToolOnCode(new TestAction(llvm::make_unique<FindClassDeclXConsumer>( + &FoundClassDeclX)), + "class X;")); EXPECT_TRUE(FoundClassDeclX); FoundClassDeclX = false; - EXPECT_TRUE(runToolOnCode(new TestAction( - new FindClassDeclXConsumer(&FoundClassDeclX)), "class Y;")); + EXPECT_TRUE( + runToolOnCode(new TestAction(llvm::make_unique<FindClassDeclXConsumer>( + &FoundClassDeclX)), + "class Y;")); EXPECT_FALSE(FoundClassDeclX); } @@ -125,8 +132,8 @@ TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromType) { } struct IndependentFrontendActionCreator { - ASTConsumer *newASTConsumer() { - return new FindTopLevelDeclConsumer(nullptr); + std::unique_ptr<ASTConsumer> newASTConsumer() { + return llvm::make_unique<FindTopLevelDeclConsumer>(nullptr); } }; @@ -182,11 +189,11 @@ struct VerifyEndCallback : public SourceFileCallbacks { ++BeginCalled; return true; } - virtual void handleEndSource() { + virtual void handleEndSource() override { ++EndCalled; } - ASTConsumer *newASTConsumer() { - return new FindTopLevelDeclConsumer(&Matched); + std::unique_ptr<ASTConsumer> newASTConsumer() { + return llvm::make_unique<FindTopLevelDeclConsumer>(&Matched); } unsigned BeginCalled; unsigned EndCalled; @@ -225,10 +232,10 @@ struct SkipBodyConsumer : public clang::ASTConsumer { }; struct SkipBodyAction : public clang::ASTFrontendAction { - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &Compiler, - StringRef) { + virtual std::unique_ptr<ASTConsumer> + CreateASTConsumer(CompilerInstance &Compiler, StringRef) { Compiler.getFrontendOpts().SkipFunctionBodies = true; - return new SkipBodyConsumer; + return llvm::make_unique<SkipBodyConsumer>(); } }; @@ -254,25 +261,6 @@ TEST(runToolOnCodeWithArgs, TestNoDepFile) { EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str())); } -struct CheckSyntaxOnlyAdjuster: public ArgumentsAdjuster { - bool &Found; - bool &Ran; - - CheckSyntaxOnlyAdjuster(bool &Found, bool &Ran) : Found(Found), Ran(Ran) { } - - virtual CommandLineArguments - Adjust(const CommandLineArguments &Args) override { - Ran = true; - for (unsigned I = 0, E = Args.size(); I != E; ++I) { - if (Args[I] == "-fsyntax-only") { - Found = true; - break; - } - } - return Args; - } -}; - TEST(ClangToolTest, ArgumentAdjusters) { FixedCompilationDatabase Compilations("/", std::vector<std::string>()); @@ -284,15 +272,22 @@ TEST(ClangToolTest, ArgumentAdjusters) { bool Found = false; bool Ran = false; - Tool.appendArgumentsAdjuster(new CheckSyntaxOnlyAdjuster(Found, Ran)); + ArgumentsAdjuster CheckSyntaxOnlyAdjuster = + [&Found, &Ran](const CommandLineArguments &Args) { + Ran = true; + if (std::find(Args.begin(), Args.end(), "-fsyntax-only") != Args.end()) + Found = true; + return Args; + }; + Tool.appendArgumentsAdjuster(CheckSyntaxOnlyAdjuster); Tool.run(Action.get()); EXPECT_TRUE(Ran); EXPECT_TRUE(Found); Ran = Found = false; Tool.clearArgumentsAdjusters(); - Tool.appendArgumentsAdjuster(new CheckSyntaxOnlyAdjuster(Found, Ran)); - Tool.appendArgumentsAdjuster(new ClangSyntaxOnlyAdjuster()); + Tool.appendArgumentsAdjuster(CheckSyntaxOnlyAdjuster); + Tool.appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster()); Tool.run(Action.get()); EXPECT_TRUE(Ran); EXPECT_FALSE(Found); |