Index: clang/lib/Driver/ToolChains/CommonArgs.h =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.h +++ clang/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: clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.cpp +++ clang/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: clang/lib/Driver/ToolChains/Fuchsia.cpp =================================================================== --- clang/lib/Driver/ToolChains/Fuchsia.cpp +++ clang/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,42 @@ llvm::sys::path::append(P, "lib"); getFilePaths().push_back(P.str()); } + + auto RuntimeDir = [&D](const Multilib &M) -> std::string { + SmallString<128> P(D.ResourceDir); + llvm::sys::path::append(P, D.getTargetTriple(), "lib", M.gccSuffix()); + return P.str(); + }; + + Multilib Default; + // Use the noexcept variant with -fno-exceptions to avoid the extra overhead. + Multilib NoExcept = Multilib("/noexcept", {}, {}, 1) + .flag("-fexceptions") + .flag("+fno-exceptions"); + // ASan has higher priority because we always want the instrumentated version. + Multilib ASan = Multilib("/asan", {}, {}, 2) + .flag("+fsanitize=address"); + Multilibs.push_back(Default); + Multilibs.push_back(NoExcept); + Multilibs.push_back(ASan); + Multilibs.FilterOut([&](const Multilib &M) { + return !getVFS().exists(RuntimeDir(M)); + }); + + Multilib::flags_list Flags; + addMultilibFlag( + Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true), + "fexceptions", Flags); + addMultilibFlag(getSanitizerArgs().needsAsanRt(), "fsanitize=address", Flags); + Multilibs.select(Flags, SelectedMultilib); + Multilibs.setFilePathsCallback([&](const Multilib &M) { + return std::vector({RuntimeDir(M)}); + }); + + // We need to prepend the multilib path to ensure it takes precedence. + if (const auto &PathsCallback = Multilibs.filePathsCallback()) + for (const auto &Path : PathsCallback(SelectedMultilib)) + getLibraryPaths().insert(getLibraryPaths().begin(), Path); } std::string Fuchsia::ComputeEffectiveClangTriple(const ArgList &Args, Index: clang/lib/Driver/ToolChains/Gnu.cpp =================================================================== --- clang/lib/Driver/ToolChains/Gnu.cpp +++ clang/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: clang/test/Driver/fuchsia.cpp =================================================================== --- clang/test/Driver/fuchsia.cpp +++ clang/test/Driver/fuchsia.cpp @@ -49,3 +49,26 @@ // 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=MULTILIB-X86,NO-ASAN-X86,NO-NOEXCEPT-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=MULTILIB-X86,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=MULTILIB-X86,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=MULTILIB-X86,ASAN-X86,NO-NOEXCEPT-X86 +// MULTILIB-X86: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// NOEXCEPT-X86: "-L[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}noexcept" +// NO-NOEXCEPT-X86-NOT: "-L[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}noexcept" +// ASAN-X86: "-L[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}asan" +// NO-ASAN-X86-NOT: "-L[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib{{/|\\\\}}asan" +// MULTILIB-X86: "-L[[RESOURCE_DIR]]{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}lib"