1*67e74705SXin Li //===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li
10*67e74705SXin Li #include "clang/AST/ASTConsumer.h"
11*67e74705SXin Li #include "clang/AST/DeclCXX.h"
12*67e74705SXin Li #include "clang/AST/DeclGroup.h"
13*67e74705SXin Li #include "clang/Frontend/ASTUnit.h"
14*67e74705SXin Li #include "clang/Frontend/CompilerInstance.h"
15*67e74705SXin Li #include "clang/Frontend/FrontendAction.h"
16*67e74705SXin Li #include "clang/Frontend/FrontendActions.h"
17*67e74705SXin Li #include "clang/Tooling/CompilationDatabase.h"
18*67e74705SXin Li #include "clang/Tooling/Tooling.h"
19*67e74705SXin Li #include "llvm/ADT/STLExtras.h"
20*67e74705SXin Li #include "llvm/Config/llvm-config.h"
21*67e74705SXin Li #include "llvm/Support/TargetSelect.h"
22*67e74705SXin Li #include "llvm/Support/TargetRegistry.h"
23*67e74705SXin Li #include "gtest/gtest.h"
24*67e74705SXin Li #include <algorithm>
25*67e74705SXin Li #include <string>
26*67e74705SXin Li
27*67e74705SXin Li namespace clang {
28*67e74705SXin Li namespace tooling {
29*67e74705SXin Li
30*67e74705SXin Li namespace {
31*67e74705SXin Li /// Takes an ast consumer and returns it from CreateASTConsumer. This only
32*67e74705SXin Li /// works with single translation unit compilations.
33*67e74705SXin Li class TestAction : public clang::ASTFrontendAction {
34*67e74705SXin Li public:
35*67e74705SXin Li /// Takes ownership of TestConsumer.
TestAction(std::unique_ptr<clang::ASTConsumer> TestConsumer)36*67e74705SXin Li explicit TestAction(std::unique_ptr<clang::ASTConsumer> TestConsumer)
37*67e74705SXin Li : TestConsumer(std::move(TestConsumer)) {}
38*67e74705SXin Li
39*67e74705SXin Li protected:
40*67e74705SXin Li std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance & compiler,StringRef dummy)41*67e74705SXin Li CreateASTConsumer(clang::CompilerInstance &compiler,
42*67e74705SXin Li StringRef dummy) override {
43*67e74705SXin Li /// TestConsumer will be deleted by the framework calling us.
44*67e74705SXin Li return std::move(TestConsumer);
45*67e74705SXin Li }
46*67e74705SXin Li
47*67e74705SXin Li private:
48*67e74705SXin Li std::unique_ptr<clang::ASTConsumer> TestConsumer;
49*67e74705SXin Li };
50*67e74705SXin Li
51*67e74705SXin Li class FindTopLevelDeclConsumer : public clang::ASTConsumer {
52*67e74705SXin Li public:
FindTopLevelDeclConsumer(bool * FoundTopLevelDecl)53*67e74705SXin Li explicit FindTopLevelDeclConsumer(bool *FoundTopLevelDecl)
54*67e74705SXin Li : FoundTopLevelDecl(FoundTopLevelDecl) {}
HandleTopLevelDecl(clang::DeclGroupRef DeclGroup)55*67e74705SXin Li bool HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) override {
56*67e74705SXin Li *FoundTopLevelDecl = true;
57*67e74705SXin Li return true;
58*67e74705SXin Li }
59*67e74705SXin Li private:
60*67e74705SXin Li bool * const FoundTopLevelDecl;
61*67e74705SXin Li };
62*67e74705SXin Li } // end namespace
63*67e74705SXin Li
TEST(runToolOnCode,FindsNoTopLevelDeclOnEmptyCode)64*67e74705SXin Li TEST(runToolOnCode, FindsNoTopLevelDeclOnEmptyCode) {
65*67e74705SXin Li bool FoundTopLevelDecl = false;
66*67e74705SXin Li EXPECT_TRUE(
67*67e74705SXin Li runToolOnCode(new TestAction(llvm::make_unique<FindTopLevelDeclConsumer>(
68*67e74705SXin Li &FoundTopLevelDecl)),
69*67e74705SXin Li ""));
70*67e74705SXin Li EXPECT_FALSE(FoundTopLevelDecl);
71*67e74705SXin Li }
72*67e74705SXin Li
73*67e74705SXin Li namespace {
74*67e74705SXin Li class FindClassDeclXConsumer : public clang::ASTConsumer {
75*67e74705SXin Li public:
FindClassDeclXConsumer(bool * FoundClassDeclX)76*67e74705SXin Li FindClassDeclXConsumer(bool *FoundClassDeclX)
77*67e74705SXin Li : FoundClassDeclX(FoundClassDeclX) {}
HandleTopLevelDecl(clang::DeclGroupRef GroupRef)78*67e74705SXin Li bool HandleTopLevelDecl(clang::DeclGroupRef GroupRef) override {
79*67e74705SXin Li if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(
80*67e74705SXin Li *GroupRef.begin())) {
81*67e74705SXin Li if (Record->getName() == "X") {
82*67e74705SXin Li *FoundClassDeclX = true;
83*67e74705SXin Li }
84*67e74705SXin Li }
85*67e74705SXin Li return true;
86*67e74705SXin Li }
87*67e74705SXin Li private:
88*67e74705SXin Li bool *FoundClassDeclX;
89*67e74705SXin Li };
FindClassDeclX(ASTUnit * AST)90*67e74705SXin Li bool FindClassDeclX(ASTUnit *AST) {
91*67e74705SXin Li for (std::vector<Decl *>::iterator i = AST->top_level_begin(),
92*67e74705SXin Li e = AST->top_level_end();
93*67e74705SXin Li i != e; ++i) {
94*67e74705SXin Li if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(*i)) {
95*67e74705SXin Li if (Record->getName() == "X") {
96*67e74705SXin Li return true;
97*67e74705SXin Li }
98*67e74705SXin Li }
99*67e74705SXin Li }
100*67e74705SXin Li return false;
101*67e74705SXin Li }
102*67e74705SXin Li } // end namespace
103*67e74705SXin Li
TEST(runToolOnCode,FindsClassDecl)104*67e74705SXin Li TEST(runToolOnCode, FindsClassDecl) {
105*67e74705SXin Li bool FoundClassDeclX = false;
106*67e74705SXin Li EXPECT_TRUE(
107*67e74705SXin Li runToolOnCode(new TestAction(llvm::make_unique<FindClassDeclXConsumer>(
108*67e74705SXin Li &FoundClassDeclX)),
109*67e74705SXin Li "class X;"));
110*67e74705SXin Li EXPECT_TRUE(FoundClassDeclX);
111*67e74705SXin Li
112*67e74705SXin Li FoundClassDeclX = false;
113*67e74705SXin Li EXPECT_TRUE(
114*67e74705SXin Li runToolOnCode(new TestAction(llvm::make_unique<FindClassDeclXConsumer>(
115*67e74705SXin Li &FoundClassDeclX)),
116*67e74705SXin Li "class Y;"));
117*67e74705SXin Li EXPECT_FALSE(FoundClassDeclX);
118*67e74705SXin Li }
119*67e74705SXin Li
TEST(buildASTFromCode,FindsClassDecl)120*67e74705SXin Li TEST(buildASTFromCode, FindsClassDecl) {
121*67e74705SXin Li std::unique_ptr<ASTUnit> AST = buildASTFromCode("class X;");
122*67e74705SXin Li ASSERT_TRUE(AST.get());
123*67e74705SXin Li EXPECT_TRUE(FindClassDeclX(AST.get()));
124*67e74705SXin Li
125*67e74705SXin Li AST = buildASTFromCode("class Y;");
126*67e74705SXin Li ASSERT_TRUE(AST.get());
127*67e74705SXin Li EXPECT_FALSE(FindClassDeclX(AST.get()));
128*67e74705SXin Li }
129*67e74705SXin Li
TEST(newFrontendActionFactory,CreatesFrontendActionFactoryFromType)130*67e74705SXin Li TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromType) {
131*67e74705SXin Li std::unique_ptr<FrontendActionFactory> Factory(
132*67e74705SXin Li newFrontendActionFactory<SyntaxOnlyAction>());
133*67e74705SXin Li std::unique_ptr<FrontendAction> Action(Factory->create());
134*67e74705SXin Li EXPECT_TRUE(Action.get() != nullptr);
135*67e74705SXin Li }
136*67e74705SXin Li
137*67e74705SXin Li struct IndependentFrontendActionCreator {
newASTConsumerclang::tooling::IndependentFrontendActionCreator138*67e74705SXin Li std::unique_ptr<ASTConsumer> newASTConsumer() {
139*67e74705SXin Li return llvm::make_unique<FindTopLevelDeclConsumer>(nullptr);
140*67e74705SXin Li }
141*67e74705SXin Li };
142*67e74705SXin Li
TEST(newFrontendActionFactory,CreatesFrontendActionFactoryFromFactoryType)143*67e74705SXin Li TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromFactoryType) {
144*67e74705SXin Li IndependentFrontendActionCreator Creator;
145*67e74705SXin Li std::unique_ptr<FrontendActionFactory> Factory(
146*67e74705SXin Li newFrontendActionFactory(&Creator));
147*67e74705SXin Li std::unique_ptr<FrontendAction> Action(Factory->create());
148*67e74705SXin Li EXPECT_TRUE(Action.get() != nullptr);
149*67e74705SXin Li }
150*67e74705SXin Li
TEST(ToolInvocation,TestMapVirtualFile)151*67e74705SXin Li TEST(ToolInvocation, TestMapVirtualFile) {
152*67e74705SXin Li llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
153*67e74705SXin Li new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
154*67e74705SXin Li llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
155*67e74705SXin Li new vfs::InMemoryFileSystem);
156*67e74705SXin Li OverlayFileSystem->pushOverlay(InMemoryFileSystem);
157*67e74705SXin Li llvm::IntrusiveRefCntPtr<FileManager> Files(
158*67e74705SXin Li new FileManager(FileSystemOptions(), OverlayFileSystem));
159*67e74705SXin Li std::vector<std::string> Args;
160*67e74705SXin Li Args.push_back("tool-executable");
161*67e74705SXin Li Args.push_back("-Idef");
162*67e74705SXin Li Args.push_back("-fsyntax-only");
163*67e74705SXin Li Args.push_back("test.cpp");
164*67e74705SXin Li clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction,
165*67e74705SXin Li Files.get());
166*67e74705SXin Li InMemoryFileSystem->addFile(
167*67e74705SXin Li "test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("#include <abc>\n"));
168*67e74705SXin Li InMemoryFileSystem->addFile("def/abc", 0,
169*67e74705SXin Li llvm::MemoryBuffer::getMemBuffer("\n"));
170*67e74705SXin Li EXPECT_TRUE(Invocation.run());
171*67e74705SXin Li }
172*67e74705SXin Li
TEST(ToolInvocation,TestVirtualModulesCompilation)173*67e74705SXin Li TEST(ToolInvocation, TestVirtualModulesCompilation) {
174*67e74705SXin Li // FIXME: Currently, this only tests that we don't exit with an error if a
175*67e74705SXin Li // mapped module.map is found on the include path. In the future, expand this
176*67e74705SXin Li // test to run a full modules enabled compilation, so we make sure we can
177*67e74705SXin Li // rerun modules compilations with a virtual file system.
178*67e74705SXin Li llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
179*67e74705SXin Li new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
180*67e74705SXin Li llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
181*67e74705SXin Li new vfs::InMemoryFileSystem);
182*67e74705SXin Li OverlayFileSystem->pushOverlay(InMemoryFileSystem);
183*67e74705SXin Li llvm::IntrusiveRefCntPtr<FileManager> Files(
184*67e74705SXin Li new FileManager(FileSystemOptions(), OverlayFileSystem));
185*67e74705SXin Li std::vector<std::string> Args;
186*67e74705SXin Li Args.push_back("tool-executable");
187*67e74705SXin Li Args.push_back("-Idef");
188*67e74705SXin Li Args.push_back("-fsyntax-only");
189*67e74705SXin Li Args.push_back("test.cpp");
190*67e74705SXin Li clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction,
191*67e74705SXin Li Files.get());
192*67e74705SXin Li InMemoryFileSystem->addFile(
193*67e74705SXin Li "test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("#include <abc>\n"));
194*67e74705SXin Li InMemoryFileSystem->addFile("def/abc", 0,
195*67e74705SXin Li llvm::MemoryBuffer::getMemBuffer("\n"));
196*67e74705SXin Li // Add a module.map file in the include directory of our header, so we trigger
197*67e74705SXin Li // the module.map header search logic.
198*67e74705SXin Li InMemoryFileSystem->addFile("def/module.map", 0,
199*67e74705SXin Li llvm::MemoryBuffer::getMemBuffer("\n"));
200*67e74705SXin Li EXPECT_TRUE(Invocation.run());
201*67e74705SXin Li }
202*67e74705SXin Li
203*67e74705SXin Li struct VerifyEndCallback : public SourceFileCallbacks {
VerifyEndCallbackclang::tooling::VerifyEndCallback204*67e74705SXin Li VerifyEndCallback() : BeginCalled(0), EndCalled(0), Matched(false) {}
handleBeginSourceclang::tooling::VerifyEndCallback205*67e74705SXin Li bool handleBeginSource(CompilerInstance &CI, StringRef Filename) override {
206*67e74705SXin Li ++BeginCalled;
207*67e74705SXin Li return true;
208*67e74705SXin Li }
handleEndSourceclang::tooling::VerifyEndCallback209*67e74705SXin Li void handleEndSource() override { ++EndCalled; }
newASTConsumerclang::tooling::VerifyEndCallback210*67e74705SXin Li std::unique_ptr<ASTConsumer> newASTConsumer() {
211*67e74705SXin Li return llvm::make_unique<FindTopLevelDeclConsumer>(&Matched);
212*67e74705SXin Li }
213*67e74705SXin Li unsigned BeginCalled;
214*67e74705SXin Li unsigned EndCalled;
215*67e74705SXin Li bool Matched;
216*67e74705SXin Li };
217*67e74705SXin Li
218*67e74705SXin Li #if !defined(LLVM_ON_WIN32)
TEST(newFrontendActionFactory,InjectsSourceFileCallbacks)219*67e74705SXin Li TEST(newFrontendActionFactory, InjectsSourceFileCallbacks) {
220*67e74705SXin Li VerifyEndCallback EndCallback;
221*67e74705SXin Li
222*67e74705SXin Li FixedCompilationDatabase Compilations("/", std::vector<std::string>());
223*67e74705SXin Li std::vector<std::string> Sources;
224*67e74705SXin Li Sources.push_back("/a.cc");
225*67e74705SXin Li Sources.push_back("/b.cc");
226*67e74705SXin Li ClangTool Tool(Compilations, Sources);
227*67e74705SXin Li
228*67e74705SXin Li Tool.mapVirtualFile("/a.cc", "void a() {}");
229*67e74705SXin Li Tool.mapVirtualFile("/b.cc", "void b() {}");
230*67e74705SXin Li
231*67e74705SXin Li std::unique_ptr<FrontendActionFactory> Action(
232*67e74705SXin Li newFrontendActionFactory(&EndCallback, &EndCallback));
233*67e74705SXin Li Tool.run(Action.get());
234*67e74705SXin Li
235*67e74705SXin Li EXPECT_TRUE(EndCallback.Matched);
236*67e74705SXin Li EXPECT_EQ(2u, EndCallback.BeginCalled);
237*67e74705SXin Li EXPECT_EQ(2u, EndCallback.EndCalled);
238*67e74705SXin Li }
239*67e74705SXin Li #endif
240*67e74705SXin Li
241*67e74705SXin Li struct SkipBodyConsumer : public clang::ASTConsumer {
242*67e74705SXin Li /// Skip the 'skipMe' function.
shouldSkipFunctionBodyclang::tooling::SkipBodyConsumer243*67e74705SXin Li bool shouldSkipFunctionBody(Decl *D) override {
244*67e74705SXin Li NamedDecl *F = dyn_cast<NamedDecl>(D);
245*67e74705SXin Li return F && F->getNameAsString() == "skipMe";
246*67e74705SXin Li }
247*67e74705SXin Li };
248*67e74705SXin Li
249*67e74705SXin Li struct SkipBodyAction : public clang::ASTFrontendAction {
CreateASTConsumerclang::tooling::SkipBodyAction250*67e74705SXin Li std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
251*67e74705SXin Li StringRef) override {
252*67e74705SXin Li Compiler.getFrontendOpts().SkipFunctionBodies = true;
253*67e74705SXin Li return llvm::make_unique<SkipBodyConsumer>();
254*67e74705SXin Li }
255*67e74705SXin Li };
256*67e74705SXin Li
TEST(runToolOnCode,TestSkipFunctionBody)257*67e74705SXin Li TEST(runToolOnCode, TestSkipFunctionBody) {
258*67e74705SXin Li std::vector<std::string> Args = {"-std=c++11"};
259*67e74705SXin Li std::vector<std::string> Args2 = {"-fno-delayed-template-parsing"};
260*67e74705SXin Li
261*67e74705SXin Li EXPECT_TRUE(runToolOnCode(new SkipBodyAction,
262*67e74705SXin Li "int skipMe() { an_error_here }"));
263*67e74705SXin Li EXPECT_FALSE(runToolOnCode(new SkipBodyAction,
264*67e74705SXin Li "int skipMeNot() { an_error_here }"));
265*67e74705SXin Li
266*67e74705SXin Li // Test constructors with initializers
267*67e74705SXin Li EXPECT_TRUE(runToolOnCodeWithArgs(
268*67e74705SXin Li new SkipBodyAction,
269*67e74705SXin Li "struct skipMe { skipMe() : an_error() { more error } };", Args));
270*67e74705SXin Li EXPECT_TRUE(runToolOnCodeWithArgs(
271*67e74705SXin Li new SkipBodyAction, "struct skipMe { skipMe(); };"
272*67e74705SXin Li "skipMe::skipMe() : an_error([](){;}) { more error }",
273*67e74705SXin Li Args));
274*67e74705SXin Li EXPECT_TRUE(runToolOnCodeWithArgs(
275*67e74705SXin Li new SkipBodyAction, "struct skipMe { skipMe(); };"
276*67e74705SXin Li "skipMe::skipMe() : an_error{[](){;}} { more error }",
277*67e74705SXin Li Args));
278*67e74705SXin Li EXPECT_TRUE(runToolOnCodeWithArgs(
279*67e74705SXin Li new SkipBodyAction,
280*67e74705SXin Li "struct skipMe { skipMe(); };"
281*67e74705SXin Li "skipMe::skipMe() : a<b<c>(e)>>(), f{}, g() { error }",
282*67e74705SXin Li Args));
283*67e74705SXin Li EXPECT_TRUE(runToolOnCodeWithArgs(
284*67e74705SXin Li new SkipBodyAction, "struct skipMe { skipMe() : bases()... { error } };",
285*67e74705SXin Li Args));
286*67e74705SXin Li
287*67e74705SXin Li EXPECT_FALSE(runToolOnCodeWithArgs(
288*67e74705SXin Li new SkipBodyAction, "struct skipMeNot { skipMeNot() : an_error() { } };",
289*67e74705SXin Li Args));
290*67e74705SXin Li EXPECT_FALSE(runToolOnCodeWithArgs(new SkipBodyAction,
291*67e74705SXin Li "struct skipMeNot { skipMeNot(); };"
292*67e74705SXin Li "skipMeNot::skipMeNot() : an_error() { }",
293*67e74705SXin Li Args));
294*67e74705SXin Li
295*67e74705SXin Li // Try/catch
296*67e74705SXin Li EXPECT_TRUE(runToolOnCode(
297*67e74705SXin Li new SkipBodyAction,
298*67e74705SXin Li "void skipMe() try { an_error() } catch(error) { error };"));
299*67e74705SXin Li EXPECT_TRUE(runToolOnCode(
300*67e74705SXin Li new SkipBodyAction,
301*67e74705SXin Li "struct S { void skipMe() try { an_error() } catch(error) { error } };"));
302*67e74705SXin Li EXPECT_TRUE(
303*67e74705SXin Li runToolOnCode(new SkipBodyAction,
304*67e74705SXin Li "void skipMe() try { an_error() } catch(error) { error; }"
305*67e74705SXin Li "catch(error) { error } catch (error) { }"));
306*67e74705SXin Li EXPECT_FALSE(runToolOnCode(
307*67e74705SXin Li new SkipBodyAction,
308*67e74705SXin Li "void skipMe() try something;")); // don't crash while parsing
309*67e74705SXin Li
310*67e74705SXin Li // Template
311*67e74705SXin Li EXPECT_TRUE(runToolOnCode(
312*67e74705SXin Li new SkipBodyAction, "template<typename T> int skipMe() { an_error_here }"
313*67e74705SXin Li "int x = skipMe<int>();"));
314*67e74705SXin Li EXPECT_FALSE(runToolOnCodeWithArgs(
315*67e74705SXin Li new SkipBodyAction,
316*67e74705SXin Li "template<typename T> int skipMeNot() { an_error_here }", Args2));
317*67e74705SXin Li }
318*67e74705SXin Li
TEST(runToolOnCodeWithArgs,TestNoDepFile)319*67e74705SXin Li TEST(runToolOnCodeWithArgs, TestNoDepFile) {
320*67e74705SXin Li llvm::SmallString<32> DepFilePath;
321*67e74705SXin Li ASSERT_FALSE(
322*67e74705SXin Li llvm::sys::fs::createTemporaryFile("depfile", "d", DepFilePath));
323*67e74705SXin Li std::vector<std::string> Args;
324*67e74705SXin Li Args.push_back("-MMD");
325*67e74705SXin Li Args.push_back("-MT");
326*67e74705SXin Li Args.push_back(DepFilePath.str());
327*67e74705SXin Li Args.push_back("-MF");
328*67e74705SXin Li Args.push_back(DepFilePath.str());
329*67e74705SXin Li EXPECT_TRUE(runToolOnCodeWithArgs(new SkipBodyAction, "", Args));
330*67e74705SXin Li EXPECT_FALSE(llvm::sys::fs::exists(DepFilePath.str()));
331*67e74705SXin Li EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str()));
332*67e74705SXin Li }
333*67e74705SXin Li
TEST(ClangToolTest,ArgumentAdjusters)334*67e74705SXin Li TEST(ClangToolTest, ArgumentAdjusters) {
335*67e74705SXin Li FixedCompilationDatabase Compilations("/", std::vector<std::string>());
336*67e74705SXin Li
337*67e74705SXin Li ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
338*67e74705SXin Li Tool.mapVirtualFile("/a.cc", "void a() {}");
339*67e74705SXin Li
340*67e74705SXin Li std::unique_ptr<FrontendActionFactory> Action(
341*67e74705SXin Li newFrontendActionFactory<SyntaxOnlyAction>());
342*67e74705SXin Li
343*67e74705SXin Li bool Found = false;
344*67e74705SXin Li bool Ran = false;
345*67e74705SXin Li ArgumentsAdjuster CheckSyntaxOnlyAdjuster =
346*67e74705SXin Li [&Found, &Ran](const CommandLineArguments &Args, StringRef /*unused*/) {
347*67e74705SXin Li Ran = true;
348*67e74705SXin Li if (std::find(Args.begin(), Args.end(), "-fsyntax-only") != Args.end())
349*67e74705SXin Li Found = true;
350*67e74705SXin Li return Args;
351*67e74705SXin Li };
352*67e74705SXin Li Tool.appendArgumentsAdjuster(CheckSyntaxOnlyAdjuster);
353*67e74705SXin Li Tool.run(Action.get());
354*67e74705SXin Li EXPECT_TRUE(Ran);
355*67e74705SXin Li EXPECT_TRUE(Found);
356*67e74705SXin Li
357*67e74705SXin Li Ran = Found = false;
358*67e74705SXin Li Tool.clearArgumentsAdjusters();
359*67e74705SXin Li Tool.appendArgumentsAdjuster(CheckSyntaxOnlyAdjuster);
360*67e74705SXin Li Tool.appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster());
361*67e74705SXin Li Tool.run(Action.get());
362*67e74705SXin Li EXPECT_TRUE(Ran);
363*67e74705SXin Li EXPECT_FALSE(Found);
364*67e74705SXin Li }
365*67e74705SXin Li
366*67e74705SXin Li namespace {
367*67e74705SXin Li /// Find a target name such that looking for it in TargetRegistry by that name
368*67e74705SXin Li /// returns the same target. We expect that there is at least one target
369*67e74705SXin Li /// configured with this property.
getAnyTarget()370*67e74705SXin Li std::string getAnyTarget() {
371*67e74705SXin Li llvm::InitializeAllTargets();
372*67e74705SXin Li for (const auto &Target : llvm::TargetRegistry::targets()) {
373*67e74705SXin Li std::string Error;
374*67e74705SXin Li StringRef TargetName(Target.getName());
375*67e74705SXin Li if (TargetName == "x86-64")
376*67e74705SXin Li TargetName = "x86_64";
377*67e74705SXin Li if (llvm::TargetRegistry::lookupTarget(TargetName, Error) == &Target) {
378*67e74705SXin Li return TargetName;
379*67e74705SXin Li }
380*67e74705SXin Li }
381*67e74705SXin Li return "";
382*67e74705SXin Li }
383*67e74705SXin Li }
384*67e74705SXin Li
TEST(addTargetAndModeForProgramName,AddsTargetAndMode)385*67e74705SXin Li TEST(addTargetAndModeForProgramName, AddsTargetAndMode) {
386*67e74705SXin Li std::string Target = getAnyTarget();
387*67e74705SXin Li ASSERT_FALSE(Target.empty());
388*67e74705SXin Li
389*67e74705SXin Li std::vector<std::string> Args = {"clang", "-foo"};
390*67e74705SXin Li addTargetAndModeForProgramName(Args, "");
391*67e74705SXin Li EXPECT_EQ((std::vector<std::string>{"clang", "-foo"}), Args);
392*67e74705SXin Li addTargetAndModeForProgramName(Args, Target + "-g++");
393*67e74705SXin Li EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target,
394*67e74705SXin Li "--driver-mode=g++", "-foo"}),
395*67e74705SXin Li Args);
396*67e74705SXin Li }
397*67e74705SXin Li
TEST(addTargetAndModeForProgramName,PathIgnored)398*67e74705SXin Li TEST(addTargetAndModeForProgramName, PathIgnored) {
399*67e74705SXin Li std::string Target = getAnyTarget();
400*67e74705SXin Li ASSERT_FALSE(Target.empty());
401*67e74705SXin Li
402*67e74705SXin Li SmallString<32> ToolPath;
403*67e74705SXin Li llvm::sys::path::append(ToolPath, "foo", "bar", Target + "-g++");
404*67e74705SXin Li
405*67e74705SXin Li std::vector<std::string> Args = {"clang", "-foo"};
406*67e74705SXin Li addTargetAndModeForProgramName(Args, ToolPath);
407*67e74705SXin Li EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target,
408*67e74705SXin Li "--driver-mode=g++", "-foo"}),
409*67e74705SXin Li Args);
410*67e74705SXin Li }
411*67e74705SXin Li
TEST(addTargetAndModeForProgramName,IgnoresExistingTarget)412*67e74705SXin Li TEST(addTargetAndModeForProgramName, IgnoresExistingTarget) {
413*67e74705SXin Li std::string Target = getAnyTarget();
414*67e74705SXin Li ASSERT_FALSE(Target.empty());
415*67e74705SXin Li
416*67e74705SXin Li std::vector<std::string> Args = {"clang", "-foo", "-target", "something"};
417*67e74705SXin Li addTargetAndModeForProgramName(Args, Target + "-g++");
418*67e74705SXin Li EXPECT_EQ((std::vector<std::string>{"clang", "--driver-mode=g++", "-foo",
419*67e74705SXin Li "-target", "something"}),
420*67e74705SXin Li Args);
421*67e74705SXin Li
422*67e74705SXin Li std::vector<std::string> ArgsAlt = {"clang", "-foo", "-target=something"};
423*67e74705SXin Li addTargetAndModeForProgramName(ArgsAlt, Target + "-g++");
424*67e74705SXin Li EXPECT_EQ((std::vector<std::string>{"clang", "--driver-mode=g++", "-foo",
425*67e74705SXin Li "-target=something"}),
426*67e74705SXin Li ArgsAlt);
427*67e74705SXin Li }
428*67e74705SXin Li
TEST(addTargetAndModeForProgramName,IgnoresExistingMode)429*67e74705SXin Li TEST(addTargetAndModeForProgramName, IgnoresExistingMode) {
430*67e74705SXin Li std::string Target = getAnyTarget();
431*67e74705SXin Li ASSERT_FALSE(Target.empty());
432*67e74705SXin Li
433*67e74705SXin Li std::vector<std::string> Args = {"clang", "-foo", "--driver-mode=abc"};
434*67e74705SXin Li addTargetAndModeForProgramName(Args, Target + "-g++");
435*67e74705SXin Li EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target, "-foo",
436*67e74705SXin Li "--driver-mode=abc"}),
437*67e74705SXin Li Args);
438*67e74705SXin Li
439*67e74705SXin Li std::vector<std::string> ArgsAlt = {"clang", "-foo", "--driver-mode", "abc"};
440*67e74705SXin Li addTargetAndModeForProgramName(ArgsAlt, Target + "-g++");
441*67e74705SXin Li EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target, "-foo",
442*67e74705SXin Li "--driver-mode", "abc"}),
443*67e74705SXin Li ArgsAlt);
444*67e74705SXin Li }
445*67e74705SXin Li
446*67e74705SXin Li #ifndef LLVM_ON_WIN32
TEST(ClangToolTest,BuildASTs)447*67e74705SXin Li TEST(ClangToolTest, BuildASTs) {
448*67e74705SXin Li FixedCompilationDatabase Compilations("/", std::vector<std::string>());
449*67e74705SXin Li
450*67e74705SXin Li std::vector<std::string> Sources;
451*67e74705SXin Li Sources.push_back("/a.cc");
452*67e74705SXin Li Sources.push_back("/b.cc");
453*67e74705SXin Li ClangTool Tool(Compilations, Sources);
454*67e74705SXin Li
455*67e74705SXin Li Tool.mapVirtualFile("/a.cc", "void a() {}");
456*67e74705SXin Li Tool.mapVirtualFile("/b.cc", "void b() {}");
457*67e74705SXin Li
458*67e74705SXin Li std::vector<std::unique_ptr<ASTUnit>> ASTs;
459*67e74705SXin Li EXPECT_EQ(0, Tool.buildASTs(ASTs));
460*67e74705SXin Li EXPECT_EQ(2u, ASTs.size());
461*67e74705SXin Li }
462*67e74705SXin Li
463*67e74705SXin Li struct TestDiagnosticConsumer : public DiagnosticConsumer {
TestDiagnosticConsumerclang::tooling::TestDiagnosticConsumer464*67e74705SXin Li TestDiagnosticConsumer() : NumDiagnosticsSeen(0) {}
HandleDiagnosticclang::tooling::TestDiagnosticConsumer465*67e74705SXin Li void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
466*67e74705SXin Li const Diagnostic &Info) override {
467*67e74705SXin Li ++NumDiagnosticsSeen;
468*67e74705SXin Li }
469*67e74705SXin Li unsigned NumDiagnosticsSeen;
470*67e74705SXin Li };
471*67e74705SXin Li
TEST(ClangToolTest,InjectDiagnosticConsumer)472*67e74705SXin Li TEST(ClangToolTest, InjectDiagnosticConsumer) {
473*67e74705SXin Li FixedCompilationDatabase Compilations("/", std::vector<std::string>());
474*67e74705SXin Li ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
475*67e74705SXin Li Tool.mapVirtualFile("/a.cc", "int x = undeclared;");
476*67e74705SXin Li TestDiagnosticConsumer Consumer;
477*67e74705SXin Li Tool.setDiagnosticConsumer(&Consumer);
478*67e74705SXin Li std::unique_ptr<FrontendActionFactory> Action(
479*67e74705SXin Li newFrontendActionFactory<SyntaxOnlyAction>());
480*67e74705SXin Li Tool.run(Action.get());
481*67e74705SXin Li EXPECT_EQ(1u, Consumer.NumDiagnosticsSeen);
482*67e74705SXin Li }
483*67e74705SXin Li
TEST(ClangToolTest,InjectDiagnosticConsumerInBuildASTs)484*67e74705SXin Li TEST(ClangToolTest, InjectDiagnosticConsumerInBuildASTs) {
485*67e74705SXin Li FixedCompilationDatabase Compilations("/", std::vector<std::string>());
486*67e74705SXin Li ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
487*67e74705SXin Li Tool.mapVirtualFile("/a.cc", "int x = undeclared;");
488*67e74705SXin Li TestDiagnosticConsumer Consumer;
489*67e74705SXin Li Tool.setDiagnosticConsumer(&Consumer);
490*67e74705SXin Li std::vector<std::unique_ptr<ASTUnit>> ASTs;
491*67e74705SXin Li Tool.buildASTs(ASTs);
492*67e74705SXin Li EXPECT_EQ(1u, ASTs.size());
493*67e74705SXin Li EXPECT_EQ(1u, Consumer.NumDiagnosticsSeen);
494*67e74705SXin Li }
495*67e74705SXin Li #endif
496*67e74705SXin Li
497*67e74705SXin Li } // end namespace tooling
498*67e74705SXin Li } // end namespace clang
499