Index: lib/Driver/ToolChains/CommonArgs.h =================================================================== --- lib/Driver/ToolChains/CommonArgs.h +++ lib/Driver/ToolChains/CommonArgs.h @@ -11,6 +11,7 @@ #include "InputInfo.h" #include "clang/Driver/Driver.h" +#include "clang/Driver/Multilib.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "llvm/Support/CodeGen.h" @@ -31,10 +32,6 @@ bool addSanitizerRuntimes(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs); -void addSanitizerPathLibArgs(const ToolChain &TC, - const llvm::opt::ArgList &Args, - llvm::opt::ArgStringList &CmdArgs); - void linkSanitizerRuntimeDeps(const ToolChain &TC, llvm::opt::ArgStringList &CmdArgs); @@ -121,6 +118,12 @@ SmallString<128> getStatsFileName(const llvm::opt::ArgList &Args, const InputInfo &Output, const InputInfo &Input, const Driver &D); + +/// \p Flag must be a flag accepted by the driver with its leading '-' removed, +// otherwise '-print-multi-lib' will not emit them correctly. +void addMultilibFlag(bool Enabled, const char *const Flag, + Multilib::flags_list &Flags); + } // end namespace tools } // end namespace driver } // end namespace clang Index: lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- lib/Driver/ToolChains/CommonArgs.cpp +++ lib/Driver/ToolChains/CommonArgs.cpp @@ -570,40 +570,6 @@ return false; } -static void addSanitizerLibPath(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs, StringRef Name) { - for (const auto &LibPath : TC.getLibraryPaths()) { - if (!LibPath.empty()) { - SmallString<128> P(LibPath); - llvm::sys::path::append(P, Name); - if (TC.getVFS().exists(P)) - CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + P)); - } - } -} - -void tools::addSanitizerPathLibArgs(const ToolChain &TC, const ArgList &Args, - ArgStringList &CmdArgs) { - const SanitizerArgs &SanArgs = TC.getSanitizerArgs(); - if (SanArgs.needsAsanRt()) { - addSanitizerLibPath(TC, Args, CmdArgs, "asan"); - } - if (SanArgs.needsHwasanRt()) { - addSanitizerLibPath(TC, Args, CmdArgs, "hwasan"); - } - if (SanArgs.needsLsanRt()) { - addSanitizerLibPath(TC, Args, CmdArgs, "lsan"); - } - if (SanArgs.needsMsanRt()) { - addSanitizerLibPath(TC, Args, CmdArgs, "msan"); - } - if (SanArgs.needsTsanRt()) { - addSanitizerLibPath(TC, Args, CmdArgs, "tsan"); - } -} - - - void tools::linkSanitizerRuntimeDeps(const ToolChain &TC, ArgStringList &CmdArgs) { // Force linking against the system libraries sanitizers depends on @@ -1535,3 +1501,8 @@ llvm::sys::path::replace_extension(StatsFile, "stats"); return StatsFile; } + +void tools::addMultilibFlag(bool Enabled, const char *const Flag, + Multilib::flags_list &Flags) { + Flags.push_back(std::string(Enabled ? "+" : "-") + Flag); +} Index: lib/Driver/ToolChains/Fuchsia.cpp =================================================================== --- lib/Driver/ToolChains/Fuchsia.cpp +++ lib/Driver/ToolChains/Fuchsia.cpp @@ -15,7 +15,9 @@ #include "clang/Driver/Options.h" #include "clang/Driver/SanitizerArgs.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" using namespace clang::driver; using namespace clang::driver::toolchains; @@ -23,6 +25,8 @@ using namespace clang; using namespace llvm::opt; +using tools::addMultilibFlag; + void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -98,8 +102,6 @@ Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_u); - addSanitizerPathLibArgs(ToolChain, Args, CmdArgs); - ToolChain.AddFilePathLibArgs(Args, CmdArgs); if (D.isUsingLTO()) { @@ -169,6 +171,52 @@ llvm::sys::path::append(P, "lib"); getFilePaths().push_back(P.str()); } + + auto RuntimeDirs = [&](const Multilib &M) -> std::vector { + SmallString<128> P; + std::vector RD; + + P.assign(D.ResourceDir); + llvm::sys::path::append(P, D.getTargetTriple(), "lib", M.gccSuffix()); + if (getVFS().exists(P)) + RD.push_back(P.str()); + + P.assign(D.ResourceDir); + llvm::sys::path::append(P, Triple.str(), "lib", M.gccSuffix()); + if (getVFS().exists(P)) + RD.push_back(P.str()); + + return RD; + }; + + Multilibs.push_back(Multilib()); + // Use the noexcept variant with -fno-exceptions to avoid the extra overhead. + Multilibs.push_back(Multilib("noexcept", {}, {}, 1) + .flag("-fexceptions") + .flag("+fno-exceptions")); + // ASan has higher priority because we always want the instrumentated version. + Multilibs.push_back(Multilib("asan", {}, {}, 2) + .flag("+fsanitize=address")); + Multilibs.FilterOut([&](const Multilib &M) { + std::vector RD = RuntimeDirs(M); + return std::all_of(RD.begin(), RD.end(), [&](std::string P) { + return !getVFS().exists(P); + }); + }); + + Multilib::flags_list Flags; + addMultilibFlag( + Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true), + "fexceptions", Flags); + addMultilibFlag(getSanitizerArgs().needsAsanRt(), "fsanitize=address", Flags); + Multilibs.setFilePathsCallback(RuntimeDirs); + + if (Multilibs.select(Flags, SelectedMultilib)) + if (!SelectedMultilib.isDefault()) + if (const auto &PathsCallback = Multilibs.filePathsCallback()) + for (const auto &Path : PathsCallback(SelectedMultilib)) + // We need to prepend the multilib path to ensure it takes precedence. + getLibraryPaths().insert(getLibraryPaths().begin(), Path); } std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args, Index: lib/Driver/ToolChains/Gnu.cpp =================================================================== --- lib/Driver/ToolChains/Gnu.cpp +++ lib/Driver/ToolChains/Gnu.cpp @@ -33,6 +33,8 @@ using namespace clang; using namespace llvm::opt; +using tools::addMultilibFlag; + void tools::GnuTool::anchor() {} static bool forwardToGCC(const Option &O) { @@ -871,16 +873,6 @@ A->getValue() == StringRef("soft")); } -/// \p Flag must be a flag accepted by the driver with its leading '-' removed, -// otherwise '-print-multi-lib' will not emit them correctly. -static void addMultilibFlag(bool Enabled, const char *const Flag, - std::vector &Flags) { - if (Enabled) - Flags.push_back(std::string("+") + Flag); - else - Flags.push_back(std::string("-") + Flag); -} - static bool isArmOrThumbArch(llvm::Triple::ArchType Arch) { return Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb; } Index: test/Driver/fuchsia.cpp =================================================================== --- test/Driver/fuchsia.cpp +++ test/Driver/fuchsia.cpp @@ -49,3 +49,24 @@ // CHECK-NOSTDLIBXX-NOT: "-lc++" // CHECK-NOSTDLIBXX-NOT: "-lm" // CHECK-NOSTDLIBXX: "-lc" + +// RUN: %clang %s -### --target=x86_64-fuchsia \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ +// RUN: -fuse-ld=lld 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86 +// RUN: %clang %s -### --target=x86_64-fuchsia -fsanitize=address \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ +// RUN: -fuse-ld=lld 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-ASAN-X86 +// RUN: %clang %s -### --target=x86_64-fuchsia -fno-exceptions \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ +// RUN: -fuse-ld=lld 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-NOEXCEPT-X86 +// RUN: %clang %s -### --target=x86_64-fuchsia -fsanitize=address -fno-exceptions \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ +// RUN: -fuse-ld=lld 2>&1\ +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-ASAN-X86 +// CHECK-MULTILIB-X86: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-MULTILIB-ASAN-X86: "-L[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}asan" +// CHECK-MULTILIB-NOEXCEPT-X86: "-L[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}noexcept" +// CHECK-MULTILIB-X86: "-L[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib"