brintos

brintos / llvm-project-archived public Read only

0
0
Text · 36.6 KiB · 8f53379 Raw
950 lines · cpp
1//===- unittests/Driver/ToolChainTest.cpp --- ToolChain tests -------------===//2//3// 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-exception6//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"17#include "clang/Basic/TargetInfo.h"18#include "clang/Basic/TargetOptions.h"19#include "clang/Driver/Compilation.h"20#include "clang/Driver/CreateInvocationFromArgs.h"21#include "clang/Driver/Driver.h"22#include "clang/Frontend/CompilerInstance.h"23#include "llvm/ADT/ArrayRef.h"24#include "llvm/ADT/StringExtras.h"25#include "llvm/Frontend/Debug/Options.h"26#include "llvm/MC/TargetRegistry.h"27#include "llvm/Support/TargetSelect.h"28#include "llvm/Support/VirtualFileSystem.h"29#include "llvm/Support/raw_ostream.h"30#include "gmock/gmock.h"31#include "gtest/gtest.h"32#include <memory>33 34#include "SimpleDiagnosticConsumer.h"35 36using namespace clang;37using namespace clang::driver;38 39namespace {40 41TEST(ToolChainTest, VFSGCCInstallation) {42  DiagnosticOptions DiagOpts;43 44  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();45  struct TestDiagnosticConsumer : public DiagnosticConsumer {};46  auto InMemoryFileSystem =47      llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();48 49  const char *EmptyFiles[] = {50      "foo.cpp",51      "/bin/clang",52      "/usr/lib/gcc/arm-linux-gnueabi/4.6.1/crtbegin.o",53      "/usr/lib/gcc/arm-linux-gnueabi/4.6.1/crtend.o",54      "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3/crtbegin.o",55      "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3/crtend.o",56      "/usr/lib/arm-linux-gnueabi/crt1.o",57      "/usr/lib/arm-linux-gnueabi/crti.o",58      "/usr/lib/arm-linux-gnueabi/crtn.o",59      "/usr/lib/arm-linux-gnueabihf/crt1.o",60      "/usr/lib/arm-linux-gnueabihf/crti.o",61      "/usr/lib/arm-linux-gnueabihf/crtn.o",62      "/usr/include/arm-linux-gnueabi/.keep",63      "/usr/include/arm-linux-gnueabihf/.keep",64      "/lib/arm-linux-gnueabi/.keep",65      "/lib/arm-linux-gnueabihf/.keep",66 67      "/sysroot/usr/lib/gcc/arm-linux-gnueabi/4.5.1/crtbegin.o",68      "/sysroot/usr/lib/gcc/arm-linux-gnueabi/4.5.1/crtend.o",69      "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3/crtbegin.o",70      "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3/crtend.o",71      "/sysroot/usr/lib/arm-linux-gnueabi/crt1.o",72      "/sysroot/usr/lib/arm-linux-gnueabi/crti.o",73      "/sysroot/usr/lib/arm-linux-gnueabi/crtn.o",74      "/sysroot/usr/lib/arm-linux-gnueabihf/crt1.o",75      "/sysroot/usr/lib/arm-linux-gnueabihf/crti.o",76      "/sysroot/usr/lib/arm-linux-gnueabihf/crtn.o",77      "/sysroot/usr/include/arm-linux-gnueabi/.keep",78      "/sysroot/usr/include/arm-linux-gnueabihf/.keep",79      "/sysroot/lib/arm-linux-gnueabi/.keep",80      "/sysroot/lib/arm-linux-gnueabihf/.keep",81  };82 83  for (const char *Path : EmptyFiles)84    InMemoryFileSystem->addFile(Path, 0,85                                llvm::MemoryBuffer::getMemBuffer("\n"));86 87  {88    DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);89    Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags,90                     "clang LLVM compiler", InMemoryFileSystem);91    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(92        {"-fsyntax-only", "--gcc-toolchain=", "--sysroot=", "foo.cpp"}));93    ASSERT_TRUE(C);94    std::string S;95    {96      llvm::raw_string_ostream OS(S);97      C->getDefaultToolChain().printVerboseInfo(OS);98    }99    if (is_style_windows(llvm::sys::path::Style::native))100      llvm::replace(S, '\\', '/');101    EXPECT_EQ(102        "Found candidate GCC installation: "103        "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n"104        "Selected GCC installation: /usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n"105        "Candidate multilib: .;@m32\n"106        "Selected multilib: .;@m32\n",107        S);108  }109 110  {111    DiagnosticOptions DiagOpts;112    DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);113    Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags,114                     "clang LLVM compiler", InMemoryFileSystem);115    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(116        {"-fsyntax-only", "--gcc-toolchain=", "--sysroot=/sysroot",117         "foo.cpp"}));118    ASSERT_TRUE(C);119    std::string S;120    {121      llvm::raw_string_ostream OS(S);122      C->getDefaultToolChain().printVerboseInfo(OS);123    }124    if (is_style_windows(llvm::sys::path::Style::native))125      llvm::replace(S, '\\', '/');126    // Test that 4.5.3 from --sysroot is not overridden by 4.6.3 (larger127    // version) from /usr.128    EXPECT_EQ("Found candidate GCC installation: "129              "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3\n"130              "Selected GCC installation: "131              "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3\n"132              "Candidate multilib: .;@m32\n"133              "Selected multilib: .;@m32\n",134              S);135  }136}137 138TEST(ToolChainTest, VFSGCCInstallationRelativeDir) {139  DiagnosticOptions DiagOpts;140 141  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();142  struct TestDiagnosticConsumer : public DiagnosticConsumer {};143  DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);144  auto InMemoryFileSystem =145      llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();146  Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,147                   "clang LLVM compiler", InMemoryFileSystem);148 149  const char *EmptyFiles[] = {150      "foo.cpp", "/home/test/lib/gcc/arm-linux-gnueabi/4.6.1/crtbegin.o",151      "/home/test/include/arm-linux-gnueabi/.keep"};152 153  for (const char *Path : EmptyFiles)154    InMemoryFileSystem->addFile(Path, 0,155                                llvm::MemoryBuffer::getMemBuffer("\n"));156 157  std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(158      {"-fsyntax-only", "--gcc-toolchain=", "foo.cpp"}));159  EXPECT_TRUE(C);160 161  std::string S;162  {163    llvm::raw_string_ostream OS(S);164    C->getDefaultToolChain().printVerboseInfo(OS);165  }166  if (is_style_windows(llvm::sys::path::Style::native))167    llvm::replace(S, '\\', '/');168  EXPECT_EQ("Found candidate GCC installation: "169            "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n"170            "Selected GCC installation: "171            "/home/test/bin/../lib/gcc/arm-linux-gnueabi/4.6.1\n"172            "Candidate multilib: .;@m32\n"173            "Selected multilib: .;@m32\n",174            S);175}176 177TEST(ToolChainTest, VFSSolarisMultiGCCInstallation) {178  DiagnosticOptions DiagOpts;179 180  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();181  struct TestDiagnosticConsumer : public DiagnosticConsumer {};182  auto InMemoryFileSystem =183      llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();184 185  const char *EmptyFiles[] = {186      // Sort entries so the latest version doesn't come first.187      "/usr/gcc/7/lib/gcc/sparcv9-sun-solaris2.11/7.5.0/32/crtbegin.o",188      "/usr/gcc/7/lib/gcc/sparcv9-sun-solaris2.11/7.5.0/crtbegin.o",189      "/usr/gcc/7/lib/gcc/x86_64-pc-solaris2.11/7.5.0/32/crtbegin.o",190      "/usr/gcc/7/lib/gcc/x86_64-pc-solaris2.11/7.5.0/crtbegin.o",191      "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0/crtbegin.o",192      "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0/sparcv8plus/crtbegin.o",193      "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0/32/crtbegin.o",194      "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0/crtbegin.o",195      "/usr/gcc/4.7/lib/gcc/i386-pc-solaris2.11/4.7.3/amd64/crtbegin.o",196      "/usr/gcc/4.7/lib/gcc/i386-pc-solaris2.11/4.7.3/crtbegin.o",197      "/usr/gcc/4.7/lib/gcc/sparc-sun-solaris2.11/4.7.3/crtbegin.o",198      "/usr/gcc/4.7/lib/gcc/sparc-sun-solaris2.11/4.7.3/sparcv9/crtbegin.o",199  };200 201  for (const char *Path : EmptyFiles)202    InMemoryFileSystem->addFile(Path, 0,203                                llvm::MemoryBuffer::getMemBuffer("\n"));204 205  {206    DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);207    Driver TheDriver("/bin/clang", "i386-pc-solaris2.11", Diags,208                     "clang LLVM compiler", InMemoryFileSystem);209    std::unique_ptr<Compilation> C(210        TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="}));211    ASSERT_TRUE(C);212    std::string S;213    {214      llvm::raw_string_ostream OS(S);215      C->getDefaultToolChain().printVerboseInfo(OS);216    }217    if (is_style_windows(llvm::sys::path::Style::native))218      llvm::replace(S, '\\', '/');219    EXPECT_EQ("Found candidate GCC installation: "220              "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n"221              "Selected GCC installation: "222              "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n"223              "Candidate multilib: .;@m64\n"224              "Candidate multilib: 32;@m32\n"225              "Selected multilib: 32;@m32\n",226              S);227  }228 229  {230    DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);231    Driver TheDriver("/bin/clang", "amd64-pc-solaris2.11", Diags,232                     "clang LLVM compiler", InMemoryFileSystem);233    std::unique_ptr<Compilation> C(234        TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="}));235    ASSERT_TRUE(C);236    std::string S;237    {238      llvm::raw_string_ostream OS(S);239      C->getDefaultToolChain().printVerboseInfo(OS);240    }241    if (is_style_windows(llvm::sys::path::Style::native))242      llvm::replace(S, '\\', '/');243    EXPECT_EQ("Found candidate GCC installation: "244              "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n"245              "Selected GCC installation: "246              "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n"247              "Candidate multilib: .;@m64\n"248              "Candidate multilib: 32;@m32\n"249              "Selected multilib: .;@m64\n",250              S);251  }252 253  {254    DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);255    Driver TheDriver("/bin/clang", "x86_64-pc-solaris2.11", Diags,256                     "clang LLVM compiler", InMemoryFileSystem);257    std::unique_ptr<Compilation> C(258        TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="}));259    ASSERT_TRUE(C);260    std::string S;261    {262      llvm::raw_string_ostream OS(S);263      C->getDefaultToolChain().printVerboseInfo(OS);264    }265    if (is_style_windows(llvm::sys::path::Style::native))266      llvm::replace(S, '\\', '/');267    EXPECT_EQ("Found candidate GCC installation: "268              "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n"269              "Selected GCC installation: "270              "/usr/gcc/11/lib/gcc/x86_64-pc-solaris2.11/11.4.0\n"271              "Candidate multilib: .;@m64\n"272              "Candidate multilib: 32;@m32\n"273              "Selected multilib: .;@m64\n",274              S);275  }276 277  {278    DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);279    Driver TheDriver("/bin/clang", "sparc-sun-solaris2.11", Diags,280                     "clang LLVM compiler", InMemoryFileSystem);281    std::unique_ptr<Compilation> C(282        TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="}));283    ASSERT_TRUE(C);284    std::string S;285    {286      llvm::raw_string_ostream OS(S);287      C->getDefaultToolChain().printVerboseInfo(OS);288    }289    if (is_style_windows(llvm::sys::path::Style::native))290      llvm::replace(S, '\\', '/');291    EXPECT_EQ("Found candidate GCC installation: "292              "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0\n"293              "Selected GCC installation: "294              "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0\n"295              "Candidate multilib: .;@m64\n"296              "Candidate multilib: sparcv8plus;@m32\n"297              "Selected multilib: sparcv8plus;@m32\n",298              S);299  }300  {301    DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);302    Driver TheDriver("/bin/clang", "sparcv9-sun-solaris2.11", Diags,303                     "clang LLVM compiler", InMemoryFileSystem);304    std::unique_ptr<Compilation> C(305        TheDriver.BuildCompilation({"-v", "--gcc-toolchain=", "--sysroot="}));306    ASSERT_TRUE(C);307    std::string S;308    {309      llvm::raw_string_ostream OS(S);310      C->getDefaultToolChain().printVerboseInfo(OS);311    }312    if (is_style_windows(llvm::sys::path::Style::native))313      llvm::replace(S, '\\', '/');314    EXPECT_EQ("Found candidate GCC installation: "315              "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0\n"316              "Selected GCC installation: "317              "/usr/gcc/11/lib/gcc/sparcv9-sun-solaris2.11/11.4.0\n"318              "Candidate multilib: .;@m64\n"319              "Candidate multilib: sparcv8plus;@m32\n"320              "Selected multilib: .;@m64\n",321              S);322  }323}324 325MATCHER_P(jobHasArgs, Substr, "") {326  const driver::Command &C = arg;327  std::string Args = "";328  llvm::ListSeparator Sep(" ");329  for (const char *Arg : C.getArguments()) {330    Args += Sep;331    Args += Arg;332  }333  if (is_style_windows(llvm::sys::path::Style::native))334    llvm::replace(Args, '\\', '/');335  if (llvm::StringRef(Args).contains(Substr))336    return true;337  *result_listener << "whose args are '" << Args << "'";338  return false;339}340 341TEST(ToolChainTest, VFSGnuLibcxxPathNoSysroot) {342  DiagnosticOptions DiagOpts;343 344  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();345  struct TestDiagnosticConsumer : public DiagnosticConsumer {};346  auto InMemoryFileSystem =347      llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();348 349  const char *EmptyFiles[] = {350      "foo.cpp",351      "/bin/clang",352      "/usr/include/c++/v1/cstdio",353  };354 355  for (const char *Path : EmptyFiles)356    InMemoryFileSystem->addFile(Path, 0,357                                llvm::MemoryBuffer::getMemBuffer("\n"));358 359  {360    DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);361    Driver TheDriver("/bin/clang", "x86_64-unknown-linux-gnu", Diags,362                     "clang LLVM compiler", InMemoryFileSystem);363    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(364        {"/bin/clang", "-fsyntax-only", "-stdlib=libc++",365         "--sysroot=", "foo.cpp"}));366    ASSERT_TRUE(C);367    EXPECT_THAT(C->getJobs(), testing::ElementsAre(jobHasArgs(368                                  "-internal-isystem /usr/include/c++/v1")));369  }370}371 372TEST(ToolChainTest, DefaultDriverMode) {373  DiagnosticOptions DiagOpts;374 375  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();376  struct TestDiagnosticConsumer : public DiagnosticConsumer {};377  DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);378  auto InMemoryFileSystem =379      llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();380 381  Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,382                  "clang LLVM compiler", InMemoryFileSystem);383  CCDriver.setCheckInputsExist(false);384  Driver CXXDriver("/home/test/bin/clang++", "arm-linux-gnueabi", Diags,385                   "clang LLVM compiler", InMemoryFileSystem);386  CXXDriver.setCheckInputsExist(false);387  Driver CLDriver("/home/test/bin/clang-cl", "arm-linux-gnueabi", Diags,388                  "clang LLVM compiler", InMemoryFileSystem);389  CLDriver.setCheckInputsExist(false);390 391  std::unique_ptr<Compilation> CC(CCDriver.BuildCompilation(392      { "/home/test/bin/clang", "foo.cpp"}));393  std::unique_ptr<Compilation> CXX(CXXDriver.BuildCompilation(394      { "/home/test/bin/clang++", "foo.cpp"}));395  std::unique_ptr<Compilation> CL(CLDriver.BuildCompilation(396      { "/home/test/bin/clang-cl", "foo.cpp"}));397 398  EXPECT_TRUE(CC);399  EXPECT_TRUE(CXX);400  EXPECT_TRUE(CL);401  EXPECT_TRUE(CCDriver.CCCIsCC());402  EXPECT_TRUE(CXXDriver.CCCIsCXX());403  EXPECT_TRUE(CLDriver.IsCLMode());404}405TEST(ToolChainTest, InvalidArgument) {406  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();407  struct TestDiagnosticConsumer : public DiagnosticConsumer {};408  DiagnosticOptions DiagOpts;409  DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);410  Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags);411  std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(412      {"-fsyntax-only", "-fan-unknown-option", "foo.cpp"}));413  EXPECT_TRUE(C);414  EXPECT_TRUE(C->containsError());415}416 417TEST(ToolChainTest, ParsedClangName) {418  ParsedClangName Empty;419  EXPECT_TRUE(Empty.TargetPrefix.empty());420  EXPECT_TRUE(Empty.ModeSuffix.empty());421  EXPECT_TRUE(Empty.DriverMode == nullptr);422  EXPECT_FALSE(Empty.TargetIsValid);423 424  ParsedClangName DriverOnly("clang", nullptr);425  EXPECT_TRUE(DriverOnly.TargetPrefix.empty());426  EXPECT_TRUE(DriverOnly.ModeSuffix == "clang");427  EXPECT_TRUE(DriverOnly.DriverMode == nullptr);428  EXPECT_FALSE(DriverOnly.TargetIsValid);429 430  ParsedClangName DriverOnly2("clang++", "--driver-mode=g++");431  EXPECT_TRUE(DriverOnly2.TargetPrefix.empty());432  EXPECT_TRUE(DriverOnly2.ModeSuffix == "clang++");433  EXPECT_STREQ(DriverOnly2.DriverMode, "--driver-mode=g++");434  EXPECT_FALSE(DriverOnly2.TargetIsValid);435 436  ParsedClangName TargetAndMode("i386", "clang-g++", "--driver-mode=g++", true);437  EXPECT_TRUE(TargetAndMode.TargetPrefix == "i386");438  EXPECT_TRUE(TargetAndMode.ModeSuffix == "clang-g++");439  EXPECT_STREQ(TargetAndMode.DriverMode, "--driver-mode=g++");440  EXPECT_TRUE(TargetAndMode.TargetIsValid);441}442 443TEST(ToolChainTest, GetTargetAndMode) {444  llvm::InitializeAllTargets();445  std::string IgnoredError;446  if (!llvm::TargetRegistry::lookupTarget(llvm::Triple("x86_64"), IgnoredError))447    GTEST_SKIP();448 449  ParsedClangName Res = ToolChain::getTargetAndModeFromProgramName("clang");450  EXPECT_TRUE(Res.TargetPrefix.empty());451  EXPECT_TRUE(Res.ModeSuffix == "clang");452  EXPECT_TRUE(Res.DriverMode == nullptr);453  EXPECT_FALSE(Res.TargetIsValid);454 455  Res = ToolChain::getTargetAndModeFromProgramName("clang++");456  EXPECT_TRUE(Res.TargetPrefix.empty());457  EXPECT_TRUE(Res.ModeSuffix == "clang++");458  EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");459  EXPECT_FALSE(Res.TargetIsValid);460 461  Res = ToolChain::getTargetAndModeFromProgramName("clang++6.0");462  EXPECT_TRUE(Res.TargetPrefix.empty());463  EXPECT_TRUE(Res.ModeSuffix == "clang++");464  EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");465  EXPECT_FALSE(Res.TargetIsValid);466 467  Res = ToolChain::getTargetAndModeFromProgramName("clang++-release");468  EXPECT_TRUE(Res.TargetPrefix.empty());469  EXPECT_TRUE(Res.ModeSuffix == "clang++");470  EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");471  EXPECT_FALSE(Res.TargetIsValid);472 473  Res = ToolChain::getTargetAndModeFromProgramName("x86_64-clang++");474  EXPECT_TRUE(Res.TargetPrefix == "x86_64");475  EXPECT_TRUE(Res.ModeSuffix == "clang++");476  EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");477  EXPECT_TRUE(Res.TargetIsValid);478 479  Res = ToolChain::getTargetAndModeFromProgramName(480      "x86_64-linux-gnu-clang-c++");481  EXPECT_TRUE(Res.TargetPrefix == "x86_64-linux-gnu");482  EXPECT_TRUE(Res.ModeSuffix == "clang-c++");483  EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");484  EXPECT_TRUE(Res.TargetIsValid);485 486  Res = ToolChain::getTargetAndModeFromProgramName(487      "x86_64-linux-gnu-clang-c++-tot");488  EXPECT_TRUE(Res.TargetPrefix == "x86_64-linux-gnu");489  EXPECT_TRUE(Res.ModeSuffix == "clang-c++");490  EXPECT_STREQ(Res.DriverMode, "--driver-mode=g++");491  EXPECT_TRUE(Res.TargetIsValid);492 493  Res = ToolChain::getTargetAndModeFromProgramName("qqq");494  EXPECT_TRUE(Res.TargetPrefix.empty());495  EXPECT_TRUE(Res.ModeSuffix.empty());496  EXPECT_TRUE(Res.DriverMode == nullptr);497  EXPECT_FALSE(Res.TargetIsValid);498 499  Res = ToolChain::getTargetAndModeFromProgramName("x86_64-qqq");500  EXPECT_TRUE(Res.TargetPrefix.empty());501  EXPECT_TRUE(Res.ModeSuffix.empty());502  EXPECT_TRUE(Res.DriverMode == nullptr);503  EXPECT_FALSE(Res.TargetIsValid);504 505  Res = ToolChain::getTargetAndModeFromProgramName("qqq-clang-cl");506  EXPECT_TRUE(Res.TargetPrefix == "qqq");507  EXPECT_TRUE(Res.ModeSuffix == "clang-cl");508  EXPECT_STREQ(Res.DriverMode, "--driver-mode=cl");509  EXPECT_FALSE(Res.TargetIsValid);510 511  Res = ToolChain::getTargetAndModeFromProgramName("clang-dxc");512  EXPECT_TRUE(Res.TargetPrefix.empty());513  EXPECT_TRUE(Res.ModeSuffix == "clang-dxc");514  EXPECT_STREQ(Res.DriverMode, "--driver-mode=dxc");515  EXPECT_FALSE(Res.TargetIsValid);516}517 518TEST(ToolChainTest, CommandOutput) {519  DiagnosticOptions DiagOpts;520 521  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();522  struct TestDiagnosticConsumer : public DiagnosticConsumer {};523  DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);524  auto InMemoryFileSystem =525      llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();526 527  Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,528                  "clang LLVM compiler", InMemoryFileSystem);529  CCDriver.setCheckInputsExist(false);530  std::unique_ptr<Compilation> CC(531      CCDriver.BuildCompilation({"/home/test/bin/clang", "foo.cpp"}));532  const JobList &Jobs = CC->getJobs();533 534  const auto &CmdCompile = Jobs.getJobs().front();535  const auto &InFile = CmdCompile->getInputInfos().front().getFilename();536  EXPECT_STREQ(InFile, "foo.cpp");537  auto ObjFile = CmdCompile->getOutputFilenames().front();538  EXPECT_TRUE(StringRef(ObjFile).ends_with(".o"));539 540  const auto &CmdLink = Jobs.getJobs().back();541  const auto LinkInFile = CmdLink->getInputInfos().front().getFilename();542  EXPECT_EQ(ObjFile, LinkInFile);543  auto ExeFile = CmdLink->getOutputFilenames().front();544  EXPECT_EQ("a.out", ExeFile);545}546 547TEST(ToolChainTest, PostCallback) {548  DiagnosticOptions DiagOpts;549  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();550  struct TestDiagnosticConsumer : public DiagnosticConsumer {};551  DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);552  auto InMemoryFileSystem =553      llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();554 555  // The executable path must not exist.556  Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,557                  "clang LLVM compiler", InMemoryFileSystem);558  CCDriver.setCheckInputsExist(false);559  std::unique_ptr<Compilation> CC(560      CCDriver.BuildCompilation({"/home/test/bin/clang", "foo.cpp"}));561  bool CallbackHasCalled = false;562  CC->setPostCallback(563      [&](const Command &C, int Ret) { CallbackHasCalled = true; });564  const JobList &Jobs = CC->getJobs();565  auto &CmdCompile = Jobs.getJobs().front();566  const Command *FailingCmd = nullptr;567  CC->ExecuteCommand(*CmdCompile, FailingCmd);568  EXPECT_TRUE(CallbackHasCalled);569}570 571TEST(CompilerInvocation, SplitSwarfSingleCrash) {572  static constexpr const char *Args[] = {573      "clang",     "--target=arm-linux-gnueabi",574      "-gdwarf-4", "-gsplit-dwarf=single",575      "-c",        "foo.cpp"};576  CreateInvocationOptions CIOpts;577  std::unique_ptr<CompilerInvocation> CI = createInvocation(Args, CIOpts);578  EXPECT_TRUE(CI); // no-crash579}580 581TEST(ToolChainTest, UEFICallingConventionTest) {582  clang::CompilerInstance compiler;583  compiler.setVirtualFileSystem(llvm::vfs::getRealFileSystem());584  compiler.createDiagnostics();585 586  std::string TrStr = "x86_64-unknown-uefi";587  llvm::Triple Tr(TrStr);588  Tr.setOS(llvm::Triple::OSType::UEFI);589  Tr.setVendor(llvm::Triple::VendorType::UnknownVendor);590  Tr.setEnvironment(llvm::Triple::EnvironmentType::UnknownEnvironment);591  Tr.setArch(llvm::Triple::ArchType::x86_64);592 593  compiler.getTargetOpts().Triple = Tr.getTriple();594  compiler.setTarget(clang::TargetInfo::CreateTargetInfo(595      compiler.getDiagnostics(), compiler.getTargetOpts()));596 597  EXPECT_EQ(compiler.getTarget().getCallingConvKind(true),598            TargetInfo::CallingConvKind::CCK_MicrosoftWin64);599}600 601TEST(ToolChainTest, UEFIDefaultDebugFormatTest) {602  DiagnosticOptions DiagOpts;603  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();604  struct TestDiagnosticConsumer : public DiagnosticConsumer {};605  DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);606  auto InMemoryFileSystem =607      llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();608  Driver CCDriver("/home/test/bin/clang", "x86_64-unknown-uefi", Diags,609                  "clang LLVM compiler", InMemoryFileSystem);610  CCDriver.setCheckInputsExist(false);611  std::unique_ptr<Compilation> CC(612      CCDriver.BuildCompilation({"/home/test/bin/clang", "foo.cpp"}));613  EXPECT_EQ(CC->getDefaultToolChain().getDefaultDebugFormat(),614            llvm::codegenoptions::DIF_CodeView);615}616 617TEST(GetDriverMode, PrefersLastDriverMode) {618  static constexpr const char *Args[] = {"clang-cl", "--driver-mode=foo",619                                         "--driver-mode=bar", "foo.cpp"};620  EXPECT_EQ(getDriverMode(Args[0], llvm::ArrayRef(Args).slice(1)), "bar");621}622 623struct SimpleDiagnosticConsumer : public DiagnosticConsumer {624  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,625                        const Diagnostic &Info) override {626    if (DiagLevel == DiagnosticsEngine::Level::Error) {627      Errors.emplace_back();628      Info.FormatDiagnostic(Errors.back());629    } else {630      Msgs.emplace_back();631      Info.FormatDiagnostic(Msgs.back());632    }633  }634  void clear() override {635    Msgs.clear();636    Errors.clear();637    DiagnosticConsumer::clear();638  }639  std::vector<SmallString<32>> Msgs;640  std::vector<SmallString<32>> Errors;641};642 643TEST(ToolChainTest, ConfigFileSearch) {644  DiagnosticOptions DiagOpts;645  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();646  struct TestDiagnosticConsumer : public DiagnosticConsumer {};647  DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);648  auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();649 650#ifdef _WIN32651  const char *TestRoot = "C:\\";652#else653  const char *TestRoot = "/";654#endif655  FS->setCurrentWorkingDirectory(TestRoot);656 657  FS->addFile(658      "/opt/sdk/root.cfg", 0,659      llvm::MemoryBuffer::getMemBuffer("--sysroot=/opt/sdk/platform0\n"));660  FS->addFile(661      "/home/test/sdk/root.cfg", 0,662      llvm::MemoryBuffer::getMemBuffer("--sysroot=/opt/sdk/platform1\n"));663  FS->addFile(664      "/home/test/bin/root.cfg", 0,665      llvm::MemoryBuffer::getMemBuffer("--sysroot=/opt/sdk/platform2\n"));666 667  {668    Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,669                     "clang LLVM compiler", FS);670    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(671        {"/home/test/bin/clang", "--config", "root.cfg",672         "--config-system-dir=/opt/sdk", "--config-user-dir=/home/test/sdk"}));673    ASSERT_TRUE(C);674    ASSERT_FALSE(C->containsError());675    EXPECT_EQ("/opt/sdk/platform1", TheDriver.SysRoot);676  }677  {678    Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,679                     "clang LLVM compiler", FS);680    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(681        {"/home/test/bin/clang", "--config", "root.cfg",682         "--config-system-dir=/opt/sdk", "--config-user-dir="}));683    ASSERT_TRUE(C);684    ASSERT_FALSE(C->containsError());685    EXPECT_EQ("/opt/sdk/platform0", TheDriver.SysRoot);686  }687  {688    Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,689                     "clang LLVM compiler", FS);690    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(691        {"/home/test/bin/clang", "--config", "root.cfg",692         "--config-system-dir=", "--config-user-dir="}));693    ASSERT_TRUE(C);694    ASSERT_FALSE(C->containsError());695    EXPECT_EQ("/opt/sdk/platform2", TheDriver.SysRoot);696  }697}698 699struct FileSystemWithError : public llvm::vfs::FileSystem {700  llvm::ErrorOr<llvm::vfs::Status> status(const Twine &Path) override {701    return std::make_error_code(std::errc::no_such_file_or_directory);702  }703  llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>704  openFileForRead(const Twine &Path) override {705    return std::make_error_code(std::errc::permission_denied);706  }707  llvm::vfs::directory_iterator dir_begin(const Twine &Dir,708                                          std::error_code &EC) override {709    return llvm::vfs::directory_iterator();710  }711  std::error_code setCurrentWorkingDirectory(const Twine &Path) override {712    return std::make_error_code(std::errc::permission_denied);713  }714  llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {715    return std::make_error_code(std::errc::permission_denied);716  }717};718 719TEST(ToolChainTest, ConfigFileError) {720  DiagnosticOptions DiagOpts;721  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();722  std::unique_ptr<SimpleDiagnosticConsumer> DiagConsumer(723      new SimpleDiagnosticConsumer());724  DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer.get(), false);725  auto FS = llvm::makeIntrusiveRefCnt<FileSystemWithError>();726 727  Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,728                   "clang LLVM compiler", FS);729  std::unique_ptr<Compilation> C(730      TheDriver.BuildCompilation({"/home/test/bin/clang", "--no-default-config",731                                  "--config", "./root.cfg", "--version"}));732  ASSERT_TRUE(C);733  ASSERT_TRUE(C->containsError());734  EXPECT_EQ(1U, Diags.getNumErrors());735  EXPECT_STREQ("configuration file './root.cfg' cannot be opened: cannot get "736               "absolute path",737               DiagConsumer->Errors[0].c_str());738}739 740TEST(ToolChainTest, BadConfigFile) {741  DiagnosticOptions DiagOpts;742  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();743  std::unique_ptr<SimpleDiagnosticConsumer> DiagConsumer(744      new SimpleDiagnosticConsumer());745  DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer.get(), false);746  auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();747 748#ifdef _WIN32749  const char *TestRoot = "C:\\";750#define FILENAME "C:/opt/root.cfg"751#define DIRNAME "C:/opt"752#else753  const char *TestRoot = "/";754#define FILENAME "/opt/root.cfg"755#define DIRNAME "/opt"756#endif757  // UTF-16 string must be aligned on 2-byte boundary. Strings and char arrays758  // do not provide necessary alignment, so copy constant string into properly759  // allocated memory in heap.760  llvm::BumpPtrAllocator Alloc;761  char *StrBuff = (char *)Alloc.Allocate(16, 4);762  std::memset(StrBuff, 0, 16);763  std::memcpy(StrBuff, "\xFF\xFE\x00\xD8\x00\x00", 6);764  StringRef BadUTF(StrBuff, 6);765  FS->setCurrentWorkingDirectory(TestRoot);766  FS->addFile("/opt/root.cfg", 0, llvm::MemoryBuffer::getMemBuffer(BadUTF));767  FS->addFile("/home/user/test.cfg", 0,768              llvm::MemoryBuffer::getMemBuffer("@file.rsp"));769 770  {771    Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,772                     "clang LLVM compiler", FS);773    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(774        {"/home/test/bin/clang", "--config", "/opt/root.cfg", "--version"}));775    ASSERT_TRUE(C);776    ASSERT_TRUE(C->containsError());777    EXPECT_EQ(1U, DiagConsumer->Errors.size());778    EXPECT_STREQ("cannot read configuration file '" FILENAME779                 "': Could not convert UTF16 to UTF8",780                 DiagConsumer->Errors[0].c_str());781  }782  DiagConsumer->clear();783  {784    Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,785                     "clang LLVM compiler", FS);786    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(787        {"/home/test/bin/clang", "--config", "/opt", "--version"}));788    ASSERT_TRUE(C);789    ASSERT_TRUE(C->containsError());790    EXPECT_EQ(1U, DiagConsumer->Errors.size());791    EXPECT_STREQ("configuration file '" DIRNAME792                 "' cannot be opened: not a regular file",793                 DiagConsumer->Errors[0].c_str());794  }795  DiagConsumer->clear();796  {797    Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,798                     "clang LLVM compiler", FS);799    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(800        {"/home/test/bin/clang", "--config", "root",801         "--config-system-dir=", "--config-user-dir=", "--version"}));802    ASSERT_TRUE(C);803    ASSERT_TRUE(C->containsError());804    EXPECT_EQ(1U, DiagConsumer->Errors.size());805    EXPECT_STREQ("configuration file 'root' cannot be found",806                 DiagConsumer->Errors[0].c_str());807  }808 809#undef FILENAME810#undef DIRNAME811}812 813TEST(ToolChainTest, ConfigInexistentInclude) {814  DiagnosticOptions DiagOpts;815  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();816  std::unique_ptr<SimpleDiagnosticConsumer> DiagConsumer(817      new SimpleDiagnosticConsumer());818  DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer.get(), false);819  auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();820 821#ifdef _WIN32822  const char *TestRoot = "C:\\";823#define USERCONFIG "C:\\home\\user\\test.cfg"824#define UNEXISTENT "C:\\home\\user\\file.rsp"825#else826  const char *TestRoot = "/";827#define USERCONFIG "/home/user/test.cfg"828#define UNEXISTENT "/home/user/file.rsp"829#endif830  FS->setCurrentWorkingDirectory(TestRoot);831  FS->addFile("/home/user/test.cfg", 0,832              llvm::MemoryBuffer::getMemBuffer("@file.rsp"));833 834  {835    Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,836                     "clang LLVM compiler", FS);837    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(838        {"/home/test/bin/clang", "--config", "test.cfg",839         "--config-system-dir=", "--config-user-dir=/home/user", "--version"}));840    ASSERT_TRUE(C);841    ASSERT_TRUE(C->containsError());842    EXPECT_EQ(1U, DiagConsumer->Errors.size());843    EXPECT_STRCASEEQ("cannot read configuration file '" USERCONFIG844                     "': cannot not open file '" UNEXISTENT845                     "': no such file or directory",846                     DiagConsumer->Errors[0].c_str());847  }848 849#undef USERCONFIG850#undef UNEXISTENT851}852 853TEST(ToolChainTest, ConfigRecursiveInclude) {854  DiagnosticOptions DiagOpts;855  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();856  std::unique_ptr<SimpleDiagnosticConsumer> DiagConsumer(857      new SimpleDiagnosticConsumer());858  DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer.get(), false);859  auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();860 861#ifdef _WIN32862  const char *TestRoot = "C:\\";863#define USERCONFIG "C:\\home\\user\\test.cfg"864#define INCLUDED1 "C:\\home\\user\\file1.cfg"865#else866  const char *TestRoot = "/";867#define USERCONFIG "/home/user/test.cfg"868#define INCLUDED1 "/home/user/file1.cfg"869#endif870  FS->setCurrentWorkingDirectory(TestRoot);871  FS->addFile("/home/user/test.cfg", 0,872              llvm::MemoryBuffer::getMemBuffer("@file1.cfg"));873  FS->addFile("/home/user/file1.cfg", 0,874              llvm::MemoryBuffer::getMemBuffer("@file2.cfg"));875  FS->addFile("/home/user/file2.cfg", 0,876              llvm::MemoryBuffer::getMemBuffer("@file3.cfg"));877  FS->addFile("/home/user/file3.cfg", 0,878              llvm::MemoryBuffer::getMemBuffer("@file1.cfg"));879 880  {881    Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags,882                     "clang LLVM compiler", FS);883    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(884        {"/home/test/bin/clang", "--config", "test.cfg",885         "--config-system-dir=", "--config-user-dir=/home/user", "--version"}));886    ASSERT_TRUE(C);887    ASSERT_TRUE(C->containsError());888    EXPECT_EQ(1U, DiagConsumer->Errors.size());889    EXPECT_STREQ("cannot read configuration file '" USERCONFIG890                 "': recursive expansion of: '" INCLUDED1 "'",891                 DiagConsumer->Errors[0].c_str());892  }893 894#undef USERCONFIG895#undef INCLUDED1896}897 898TEST(ToolChainTest, NestedConfigFile) {899  DiagnosticOptions DiagOpts;900  IntrusiveRefCntPtr<DiagnosticIDs> DiagID = DiagnosticIDs::create();901  struct TestDiagnosticConsumer : public DiagnosticConsumer {};902  DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer);903  auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();904 905#ifdef _WIN32906  const char *TestRoot = "C:\\";907#else908  const char *TestRoot = "/";909#endif910  FS->setCurrentWorkingDirectory(TestRoot);911 912  FS->addFile("/opt/sdk/root.cfg", 0,913              llvm::MemoryBuffer::getMemBuffer("--config=platform.cfg\n"));914  FS->addFile("/opt/sdk/platform.cfg", 0,915              llvm::MemoryBuffer::getMemBuffer("--sysroot=/platform-sys\n"));916  FS->addFile("/home/test/bin/platform.cfg", 0,917              llvm::MemoryBuffer::getMemBuffer("--sysroot=/platform-bin\n"));918 919  SmallString<128> ClangExecutable("/home/test/bin/clang");920  FS->makeAbsolute(ClangExecutable);921 922  // User file is absent - use system definitions.923  {924    Driver TheDriver(ClangExecutable, "arm-linux-gnueabi", Diags,925                     "clang LLVM compiler", FS);926    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(927        {"/home/test/bin/clang", "--config", "root.cfg",928         "--config-system-dir=/opt/sdk", "--config-user-dir=/home/test/sdk"}));929    ASSERT_TRUE(C);930    ASSERT_FALSE(C->containsError());931    EXPECT_EQ("/platform-sys", TheDriver.SysRoot);932  }933 934  // User file overrides system definitions.935  FS->addFile("/home/test/sdk/platform.cfg", 0,936              llvm::MemoryBuffer::getMemBuffer("--sysroot=/platform-user\n"));937  {938    Driver TheDriver(ClangExecutable, "arm-linux-gnueabi", Diags,939                     "clang LLVM compiler", FS);940    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(941        {"/home/test/bin/clang", "--config", "root.cfg",942         "--config-system-dir=/opt/sdk", "--config-user-dir=/home/test/sdk"}));943    ASSERT_TRUE(C);944    ASSERT_FALSE(C->containsError());945    EXPECT_EQ("/platform-user", TheDriver.SysRoot);946  }947}948 949} // end anonymous namespace.950