1 //===- unittests/Driver/ToolChainTest.cpp --- ToolChain tests -------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Unit tests for ToolChains. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Driver/ToolChain.h" 15 #include "clang/Basic/DiagnosticIDs.h" 16 #include "clang/Basic/DiagnosticOptions.h" 17 #include "clang/Basic/LLVM.h" 18 #include "clang/Driver/Compilation.h" 19 #include "clang/Driver/Driver.h" 20 #include "llvm/Support/TargetRegistry.h" 21 #include "llvm/Support/TargetSelect.h" 22 #include "llvm/Support/VirtualFileSystem.h" 23 #include "llvm/Support/raw_ostream.h" 24 #include "gtest/gtest.h" 25 using namespace clang; 26 using namespace clang::driver; 27 28 namespace { 29 30 TEST(ToolChainTest, VFSGCCInstallation) { 31 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 32 33 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 34 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 35 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 36 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 37 new llvm::vfs::InMemoryFileSystem); 38 Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags, 39 InMemoryFileSystem); 40 41 const char *EmptyFiles[] = { 42 "foo.cpp", 43 "/bin/clang", 44 "/usr/lib/gcc/arm-linux-gnueabi/4.6.1/crtbegin.o", 45 "/usr/lib/gcc/arm-linux-gnueabi/4.6.1/crtend.o", 46 "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3/crtbegin.o", 47 "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3/crtend.o", 48 "/usr/lib/arm-linux-gnueabi/crt1.o", 49 "/usr/lib/arm-linux-gnueabi/crti.o", 50 "/usr/lib/arm-linux-gnueabi/crtn.o", 51 "/usr/lib/arm-linux-gnueabihf/crt1.o", 52 "/usr/lib/arm-linux-gnueabihf/crti.o", 53 "/usr/lib/arm-linux-gnueabihf/crtn.o", 54 "/usr/include/arm-linux-gnueabi/.keep", 55 "/usr/include/arm-linux-gnueabihf/.keep", 56 "/lib/arm-linux-gnueabi/.keep", 57 "/lib/arm-linux-gnueabihf/.keep"}; 58 59 for (const char *Path : EmptyFiles) 60 InMemoryFileSystem->addFile(Path, 0, 61 llvm::MemoryBuffer::getMemBuffer("\n")); 62 63 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 64 {"-fsyntax-only", "--gcc-toolchain=", "foo.cpp"})); 65 EXPECT_TRUE(C); 66 67 std::string S; 68 { 69 llvm::raw_string_ostream OS(S); 70 C->getDefaultToolChain().printVerboseInfo(OS); 71 } 72 #if _WIN32 73 std::replace(S.begin(), S.end(), '\\', '/'); 74 #endif 75 EXPECT_EQ( 76 "Found candidate GCC installation: " 77 "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n" 78 "Selected GCC installation: /usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n" 79 "Candidate multilib: .;@m32\n" 80 "Selected multilib: .;@m32\n", 81 S); 82 } 83 84 TEST(ToolChainTest, VFSGCCInstallationRelativeDir) { 85 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 86 87 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 88 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 89 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 90 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 91 new llvm::vfs::InMemoryFileSystem); 92 Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 93 InMemoryFileSystem); 94 95 const char *EmptyFiles[] = { 96 "foo.cpp", "/home/test/lib/gcc/arm-linux-gnueabi/4.6.1/crtbegin.o", 97 "/home/test/include/arm-linux-gnueabi/.keep"}; 98 99 for (const char *Path : EmptyFiles) 100 InMemoryFileSystem->addFile(Path, 0, 101 llvm::MemoryBuffer::getMemBuffer("\n")); 102 103 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 104 {"-fsyntax-only", "--gcc-toolchain=", "foo.cpp"})); 105 EXPECT_TRUE(C); 106 107 std::string S; 108 { 109 llvm::raw_string_ostream OS(S); 110 C->getDefaultToolChain().printVerboseInfo(OS); 111 } 112 #if _WIN32 113 std::replace(S.begin(), S.end(), '\\', '/'); 114 #endif 115 EXPECT_EQ("Found candidate GCC installation: " 116 "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n" 117 "Selected GCC installation: " 118 "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n" 119 "Candidate multilib: .;@m32\n" 120 "Selected multilib: .;@m32\n", 121 S); 122 } 123 124 TEST(ToolChainTest, DefaultDriverMode) { 125 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 126 127 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 128 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 129 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 130 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 131 new llvm::vfs::InMemoryFileSystem); 132 133 Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, 134 InMemoryFileSystem); 135 CCDriver.setCheckInputsExist(false); 136 Driver CXXDriver("/home/test/bin/clang++", "arm-linux-gnueabi", Diags, 137 InMemoryFileSystem); 138 CXXDriver.setCheckInputsExist(false); 139 Driver CLDriver("/home/test/bin/clang-cl", "arm-linux-gnueabi", Diags, 140 InMemoryFileSystem); 141 CLDriver.setCheckInputsExist(false); 142 143 std::unique_ptr<Compilation> CC(CCDriver.BuildCompilation( 144 { "/home/test/bin/clang", "foo.cpp"})); 145 std::unique_ptr<Compilation> CXX(CXXDriver.BuildCompilation( 146 { "/home/test/bin/clang++", "foo.cpp"})); 147 std::unique_ptr<Compilation> CL(CLDriver.BuildCompilation( 148 { "/home/test/bin/clang-cl", "foo.cpp"})); 149 150 EXPECT_TRUE(CC); 151 EXPECT_TRUE(CXX); 152 EXPECT_TRUE(CL); 153 EXPECT_TRUE(CCDriver.CCCIsCC()); 154 EXPECT_TRUE(CXXDriver.CCCIsCXX()); 155 EXPECT_TRUE(CLDriver.IsCLMode()); 156 } 157 TEST(ToolChainTest, InvalidArgument) { 158 IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 159 struct TestDiagnosticConsumer : public DiagnosticConsumer {}; 160 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 161 DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); 162 Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags); 163 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 164 {"-fsyntax-only", "-fan-unknown-option", "foo.cpp"})); 165 EXPECT_TRUE(C); 166 EXPECT_TRUE(C->containsError()); 167 } 168 169 TEST(ToolChainTest, ParsedClangName) { 170 ParsedClangName Empty; 171 EXPECT_TRUE(Empty.TargetPrefix.empty()); 172 EXPECT_TRUE(Empty.ModeSuffix.empty()); 173 EXPECT_TRUE(Empty.DriverMode == nullptr); 174 EXPECT_FALSE(Empty.TargetIsValid); 175 176 ParsedClangName DriverOnly("clang", nullptr); 177 EXPECT_TRUE(DriverOnly.TargetPrefix.empty()); 178 EXPECT_TRUE(DriverOnly.ModeSuffix == "clang"); 179 EXPECT_TRUE(DriverOnly.DriverMode == nullptr); 180 EXPECT_FALSE(DriverOnly.TargetIsValid); 181 182 ParsedClangName DriverOnly2("clang++", "--driver-mode=g++"); 183 EXPECT_TRUE(DriverOnly2.TargetPrefix.empty()); 184 EXPECT_TRUE(DriverOnly2.ModeSuffix == "clang++"); 185 EXPECT_STREQ(DriverOnly2.DriverMode, "--driver-mode=g++"); 186 EXPECT_FALSE(DriverOnly2.TargetIsValid); 187 188 ParsedClangName TargetAndMode("i386", "clang-g++", "--driver-mode=g++", true); 189 EXPECT_TRUE(TargetAndMode.TargetPrefix == "i386"); 190 EXPECT_TRUE(TargetAndMode.ModeSuffix == "clang-g++"); 191 EXPECT_STREQ(TargetAndMode.DriverMode, "--driver-mode=g++"); 192 EXPECT_TRUE(TargetAndMode.TargetIsValid); 193 } 194 195 TEST(ToolChainTest, GetTargetAndMode) { 196 llvm::InitializeAllTargets(); 197 std::string IgnoredError; 198 if (!llvm::TargetRegistry::lookupTarget("x86_64", IgnoredError)) 199 return; 200 201 ParsedClangName Res = ToolChain::getTargetAndModeFromProgramName("clang"); 202 EXPECT_TRUE(Res.TargetPrefix.empty()); 203 EXPECT_TRUE(Res.ModeSuffix == "clang"); 204 EXPECT_TRUE(Res.DriverMode == nullptr); 205 EXPECT_FALSE(Res.TargetIsValid); 206 207 Res = ToolChain::getTargetAndModeFromProgramName("clang++"); 208 EXPECT_TRUE(Res.TargetPrefix.empty()); 209 EXPECT_TRUE(Res.ModeSuffix == "clang++"); 210 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 211 EXPECT_FALSE(Res.TargetIsValid); 212 213 Res = ToolChain::getTargetAndModeFromProgramName("clang++6.0"); 214 EXPECT_TRUE(Res.TargetPrefix.empty()); 215 EXPECT_TRUE(Res.ModeSuffix == "clang++"); 216 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 217 EXPECT_FALSE(Res.TargetIsValid); 218 219 Res = ToolChain::getTargetAndModeFromProgramName("clang++-release"); 220 EXPECT_TRUE(Res.TargetPrefix.empty()); 221 EXPECT_TRUE(Res.ModeSuffix == "clang++"); 222 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 223 EXPECT_FALSE(Res.TargetIsValid); 224 225 Res = ToolChain::getTargetAndModeFromProgramName("x86_64-clang++"); 226 EXPECT_TRUE(Res.TargetPrefix == "x86_64"); 227 EXPECT_TRUE(Res.ModeSuffix == "clang++"); 228 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 229 EXPECT_TRUE(Res.TargetIsValid); 230 231 Res = ToolChain::getTargetAndModeFromProgramName( 232 "x86_64-linux-gnu-clang-c++"); 233 EXPECT_TRUE(Res.TargetPrefix == "x86_64-linux-gnu"); 234 EXPECT_TRUE(Res.ModeSuffix == "clang-c++"); 235 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 236 EXPECT_TRUE(Res.TargetIsValid); 237 238 Res = ToolChain::getTargetAndModeFromProgramName( 239 "x86_64-linux-gnu-clang-c++-tot"); 240 EXPECT_TRUE(Res.TargetPrefix == "x86_64-linux-gnu"); 241 EXPECT_TRUE(Res.ModeSuffix == "clang-c++"); 242 EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++"); 243 EXPECT_TRUE(Res.TargetIsValid); 244 245 Res = ToolChain::getTargetAndModeFromProgramName("qqq"); 246 EXPECT_TRUE(Res.TargetPrefix.empty()); 247 EXPECT_TRUE(Res.ModeSuffix.empty()); 248 EXPECT_TRUE(Res.DriverMode == nullptr); 249 EXPECT_FALSE(Res.TargetIsValid); 250 251 Res = ToolChain::getTargetAndModeFromProgramName("x86_64-qqq"); 252 EXPECT_TRUE(Res.TargetPrefix.empty()); 253 EXPECT_TRUE(Res.ModeSuffix.empty()); 254 EXPECT_TRUE(Res.DriverMode == nullptr); 255 EXPECT_FALSE(Res.TargetIsValid); 256 257 Res = ToolChain::getTargetAndModeFromProgramName("qqq-clang-cl"); 258 EXPECT_TRUE(Res.TargetPrefix == "qqq"); 259 EXPECT_TRUE(Res.ModeSuffix == "clang-cl"); 260 EXPECT_STREQ(Res.DriverMode, "--driver-mode=cl"); 261 EXPECT_FALSE(Res.TargetIsValid); 262 } 263 } // end anonymous namespace. 264