blob: f84e508b6cbdb90e7f684fa5688c35fdd4db2cea [file] [log] [blame]
Benjamin Kramerd45b2052015-10-07 15:48:01 +00001//===- unittests/Driver/ToolChainTest.cpp --- ToolChain tests -------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Benjamin Kramerd45b2052015-10-07 15:48:01 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Unit tests for ToolChains.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/Driver/ToolChain.h"
14#include "clang/Basic/DiagnosticIDs.h"
15#include "clang/Basic/DiagnosticOptions.h"
16#include "clang/Basic/LLVM.h"
Benjamin Kramerd45b2052015-10-07 15:48:01 +000017#include "clang/Driver/Compilation.h"
18#include "clang/Driver/Driver.h"
Serge Pavlov4e769842017-08-29 05:22:26 +000019#include "llvm/Support/TargetRegistry.h"
20#include "llvm/Support/TargetSelect.h"
Jonas Devliegherefc514902018-10-10 13:27:25 +000021#include "llvm/Support/VirtualFileSystem.h"
Benjamin Kramerd45b2052015-10-07 15:48:01 +000022#include "llvm/Support/raw_ostream.h"
23#include "gtest/gtest.h"
24using namespace clang;
25using namespace clang::driver;
26
27namespace {
28
29TEST(ToolChainTest, VFSGCCInstallation) {
30 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
31
32 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
33 struct TestDiagnosticConsumer : public DiagnosticConsumer {};
34 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
Jonas Devliegherefc514902018-10-10 13:27:25 +000035 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
36 new llvm::vfs::InMemoryFileSystem);
Benjamin Kramerf420dda2015-10-13 15:19:32 +000037 Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags,
Benjamin Kramerd45b2052015-10-07 15:48:01 +000038 InMemoryFileSystem);
39
40 const char *EmptyFiles[] = {
41 "foo.cpp",
Benjamin Kramerf420dda2015-10-13 15:19:32 +000042 "/bin/clang",
Benjamin Kramerd45b2052015-10-07 15:48:01 +000043 "/usr/lib/gcc/arm-linux-gnueabi/4.6.1/crtbegin.o",
44 "/usr/lib/gcc/arm-linux-gnueabi/4.6.1/crtend.o",
45 "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3/crtbegin.o",
46 "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3/crtend.o",
47 "/usr/lib/arm-linux-gnueabi/crt1.o",
48 "/usr/lib/arm-linux-gnueabi/crti.o",
49 "/usr/lib/arm-linux-gnueabi/crtn.o",
50 "/usr/lib/arm-linux-gnueabihf/crt1.o",
51 "/usr/lib/arm-linux-gnueabihf/crti.o",
52 "/usr/lib/arm-linux-gnueabihf/crtn.o",
53 "/usr/include/arm-linux-gnueabi/.keep",
54 "/usr/include/arm-linux-gnueabihf/.keep",
55 "/lib/arm-linux-gnueabi/.keep",
56 "/lib/arm-linux-gnueabihf/.keep"};
57
58 for (const char *Path : EmptyFiles)
59 InMemoryFileSystem->addFile(Path, 0,
60 llvm::MemoryBuffer::getMemBuffer("\n"));
61
Samuel Antao4c1f1c32015-10-27 22:20:26 +000062 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(
Serge Pavlov4bc05622019-09-28 12:21:06 +000063 {"-fsyntax-only", "--gcc-toolchain=", "--sysroot=", "foo.cpp"}));
Serge Pavlovb43573b2017-05-24 14:57:17 +000064 EXPECT_TRUE(C);
Benjamin Kramerd45b2052015-10-07 15:48:01 +000065
66 std::string S;
67 {
68 llvm::raw_string_ostream OS(S);
69 C->getDefaultToolChain().printVerboseInfo(OS);
70 }
Nico Weber1865df42018-04-27 19:11:14 +000071#if _WIN32
Reid Kleckner04ab1162015-10-09 16:48:52 +000072 std::replace(S.begin(), S.end(), '\\', '/');
73#endif
Benjamin Kramerc5862f02015-10-09 13:03:18 +000074 EXPECT_EQ(
75 "Found candidate GCC installation: "
76 "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n"
77 "Selected GCC installation: /usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n"
78 "Candidate multilib: .;@m32\n"
79 "Selected multilib: .;@m32\n",
80 S);
Benjamin Kramerd45b2052015-10-07 15:48:01 +000081}
82
Benjamin Kramerf420dda2015-10-13 15:19:32 +000083TEST(ToolChainTest, VFSGCCInstallationRelativeDir) {
84 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
85
86 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
87 struct TestDiagnosticConsumer : public DiagnosticConsumer {};
88 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
Jonas Devliegherefc514902018-10-10 13:27:25 +000089 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
90 new llvm::vfs::InMemoryFileSystem);
Benjamin Kramerf420dda2015-10-13 15:19:32 +000091 Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,
92 InMemoryFileSystem);
93
94 const char *EmptyFiles[] = {
95 "foo.cpp", "/home/test/lib/gcc/arm-linux-gnueabi/4.6.1/crtbegin.o",
96 "/home/test/include/arm-linux-gnueabi/.keep"};
97
98 for (const char *Path : EmptyFiles)
99 InMemoryFileSystem->addFile(Path, 0,
100 llvm::MemoryBuffer::getMemBuffer("\n"));
101
Samuel Antao4c1f1c32015-10-27 22:20:26 +0000102 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(
103 {"-fsyntax-only", "--gcc-toolchain=", "foo.cpp"}));
Serge Pavlovb43573b2017-05-24 14:57:17 +0000104 EXPECT_TRUE(C);
Benjamin Kramerf420dda2015-10-13 15:19:32 +0000105
106 std::string S;
107 {
108 llvm::raw_string_ostream OS(S);
109 C->getDefaultToolChain().printVerboseInfo(OS);
110 }
Nico Weber1865df42018-04-27 19:11:14 +0000111#if _WIN32
Benjamin Kramerf420dda2015-10-13 15:19:32 +0000112 std::replace(S.begin(), S.end(), '\\', '/');
113#endif
114 EXPECT_EQ("Found candidate GCC installation: "
Simon Marchiddbabc62018-08-06 21:48:20 +0000115 "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n"
Benjamin Kramerf420dda2015-10-13 15:19:32 +0000116 "Selected GCC installation: "
117 "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n"
118 "Candidate multilib: .;@m32\n"
119 "Selected multilib: .;@m32\n",
120 S);
121}
122
Zachary Turneraff19c32016-08-12 17:47:52 +0000123TEST(ToolChainTest, DefaultDriverMode) {
124 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
125
126 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
127 struct TestDiagnosticConsumer : public DiagnosticConsumer {};
128 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
Jonas Devliegherefc514902018-10-10 13:27:25 +0000129 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
130 new llvm::vfs::InMemoryFileSystem);
Zachary Turneraff19c32016-08-12 17:47:52 +0000131
132 Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,
133 InMemoryFileSystem);
Serge Pavlovb43573b2017-05-24 14:57:17 +0000134 CCDriver.setCheckInputsExist(false);
Zachary Turneraff19c32016-08-12 17:47:52 +0000135 Driver CXXDriver("/home/test/bin/clang++", "arm-linux-gnueabi", Diags,
136 InMemoryFileSystem);
Serge Pavlovb43573b2017-05-24 14:57:17 +0000137 CXXDriver.setCheckInputsExist(false);
Zachary Turneraff19c32016-08-12 17:47:52 +0000138 Driver CLDriver("/home/test/bin/clang-cl", "arm-linux-gnueabi", Diags,
139 InMemoryFileSystem);
Serge Pavlovb43573b2017-05-24 14:57:17 +0000140 CLDriver.setCheckInputsExist(false);
Zachary Turneraff19c32016-08-12 17:47:52 +0000141
Serge Pavlovb43573b2017-05-24 14:57:17 +0000142 std::unique_ptr<Compilation> CC(CCDriver.BuildCompilation(
143 { "/home/test/bin/clang", "foo.cpp"}));
144 std::unique_ptr<Compilation> CXX(CXXDriver.BuildCompilation(
145 { "/home/test/bin/clang++", "foo.cpp"}));
146 std::unique_ptr<Compilation> CL(CLDriver.BuildCompilation(
147 { "/home/test/bin/clang-cl", "foo.cpp"}));
Zachary Turneraff19c32016-08-12 17:47:52 +0000148
Serge Pavlovb43573b2017-05-24 14:57:17 +0000149 EXPECT_TRUE(CC);
150 EXPECT_TRUE(CXX);
151 EXPECT_TRUE(CL);
Zachary Turneraff19c32016-08-12 17:47:52 +0000152 EXPECT_TRUE(CCDriver.CCCIsCC());
153 EXPECT_TRUE(CXXDriver.CCCIsCXX());
154 EXPECT_TRUE(CLDriver.IsCLMode());
155}
Benjamin Kramer43c0f482017-06-30 13:21:27 +0000156TEST(ToolChainTest, InvalidArgument) {
157 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
158 struct TestDiagnosticConsumer : public DiagnosticConsumer {};
159 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
160 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer);
161 Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags);
162 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(
163 {"-fsyntax-only", "-fan-unknown-option", "foo.cpp"}));
164 EXPECT_TRUE(C);
165 EXPECT_TRUE(C->containsError());
166}
Zachary Turneraff19c32016-08-12 17:47:52 +0000167
Serge Pavlov4e769842017-08-29 05:22:26 +0000168TEST(ToolChainTest, ParsedClangName) {
169 ParsedClangName Empty;
170 EXPECT_TRUE(Empty.TargetPrefix.empty());
171 EXPECT_TRUE(Empty.ModeSuffix.empty());
172 EXPECT_TRUE(Empty.DriverMode == nullptr);
173 EXPECT_FALSE(Empty.TargetIsValid);
174
175 ParsedClangName DriverOnly("clang", nullptr);
176 EXPECT_TRUE(DriverOnly.TargetPrefix.empty());
177 EXPECT_TRUE(DriverOnly.ModeSuffix == "clang");
178 EXPECT_TRUE(DriverOnly.DriverMode == nullptr);
179 EXPECT_FALSE(DriverOnly.TargetIsValid);
180
181 ParsedClangName DriverOnly2("clang++", "--driver-mode=g++");
182 EXPECT_TRUE(DriverOnly2.TargetPrefix.empty());
183 EXPECT_TRUE(DriverOnly2.ModeSuffix == "clang++");
184 EXPECT_STREQ(DriverOnly2.DriverMode, "--driver-mode=g++");
185 EXPECT_FALSE(DriverOnly2.TargetIsValid);
186
187 ParsedClangName TargetAndMode("i386", "clang-g++", "--driver-mode=g++", true);
188 EXPECT_TRUE(TargetAndMode.TargetPrefix == "i386");
189 EXPECT_TRUE(TargetAndMode.ModeSuffix == "clang-g++");
190 EXPECT_STREQ(TargetAndMode.DriverMode, "--driver-mode=g++");
191 EXPECT_TRUE(TargetAndMode.TargetIsValid);
192}
193
194TEST(ToolChainTest, GetTargetAndMode) {
195 llvm::InitializeAllTargets();
196 std::string IgnoredError;
197 if (!llvm::TargetRegistry::lookupTarget("x86_64", IgnoredError))
198 return;
199
200 ParsedClangName Res = ToolChain::getTargetAndModeFromProgramName("clang");
201 EXPECT_TRUE(Res.TargetPrefix.empty());
202 EXPECT_TRUE(Res.ModeSuffix == "clang");
203 EXPECT_TRUE(Res.DriverMode == nullptr);
204 EXPECT_FALSE(Res.TargetIsValid);
205
206 Res = ToolChain::getTargetAndModeFromProgramName("clang++");
207 EXPECT_TRUE(Res.TargetPrefix.empty());
208 EXPECT_TRUE(Res.ModeSuffix == "clang++");
209 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");
210 EXPECT_FALSE(Res.TargetIsValid);
211
212 Res = ToolChain::getTargetAndModeFromProgramName("clang++6.0");
213 EXPECT_TRUE(Res.TargetPrefix.empty());
214 EXPECT_TRUE(Res.ModeSuffix == "clang++");
215 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");
216 EXPECT_FALSE(Res.TargetIsValid);
217
218 Res = ToolChain::getTargetAndModeFromProgramName("clang++-release");
219 EXPECT_TRUE(Res.TargetPrefix.empty());
220 EXPECT_TRUE(Res.ModeSuffix == "clang++");
221 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");
222 EXPECT_FALSE(Res.TargetIsValid);
223
224 Res = ToolChain::getTargetAndModeFromProgramName("x86_64-clang++");
225 EXPECT_TRUE(Res.TargetPrefix == "x86_64");
226 EXPECT_TRUE(Res.ModeSuffix == "clang++");
227 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");
228 EXPECT_TRUE(Res.TargetIsValid);
229
230 Res = ToolChain::getTargetAndModeFromProgramName(
231 "x86_64-linux-gnu-clang-c++");
232 EXPECT_TRUE(Res.TargetPrefix == "x86_64-linux-gnu");
233 EXPECT_TRUE(Res.ModeSuffix == "clang-c++");
234 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");
235 EXPECT_TRUE(Res.TargetIsValid);
236
237 Res = ToolChain::getTargetAndModeFromProgramName(
238 "x86_64-linux-gnu-clang-c++-tot");
239 EXPECT_TRUE(Res.TargetPrefix == "x86_64-linux-gnu");
240 EXPECT_TRUE(Res.ModeSuffix == "clang-c++");
241 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");
242 EXPECT_TRUE(Res.TargetIsValid);
243
244 Res = ToolChain::getTargetAndModeFromProgramName("qqq");
245 EXPECT_TRUE(Res.TargetPrefix.empty());
246 EXPECT_TRUE(Res.ModeSuffix.empty());
247 EXPECT_TRUE(Res.DriverMode == nullptr);
248 EXPECT_FALSE(Res.TargetIsValid);
249
250 Res = ToolChain::getTargetAndModeFromProgramName("x86_64-qqq");
251 EXPECT_TRUE(Res.TargetPrefix.empty());
252 EXPECT_TRUE(Res.ModeSuffix.empty());
253 EXPECT_TRUE(Res.DriverMode == nullptr);
254 EXPECT_FALSE(Res.TargetIsValid);
255
256 Res = ToolChain::getTargetAndModeFromProgramName("qqq-clang-cl");
257 EXPECT_TRUE(Res.TargetPrefix == "qqq");
258 EXPECT_TRUE(Res.ModeSuffix == "clang-cl");
259 EXPECT_STREQ(Res.DriverMode, "--driver-mode=cl");
260 EXPECT_FALSE(Res.TargetIsValid);
261}
Manoj Guptae025ebb2017-04-18 17:34:46 +0000262} // end anonymous namespace.