Index: clang/include/clang/Driver/ToolChain.h =================================================================== --- clang/include/clang/Driver/ToolChain.h +++ clang/include/clang/Driver/ToolChain.h @@ -166,6 +166,10 @@ EffectiveTriple = std::move(ET); } + mutable llvm::Optional cxxStdlibType; + mutable llvm::Optional runtimeLibType; + mutable llvm::Optional unwindLibType; + protected: MultilibSet Multilibs; Multilib SelectedMultilib; Index: clang/lib/Driver/ToolChain.cpp =================================================================== --- clang/lib/Driver/ToolChain.cpp +++ clang/lib/Driver/ToolChain.cpp @@ -884,66 +884,86 @@ ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( const ArgList &Args) const { + if (runtimeLibType) + return *runtimeLibType; + const Arg* A = Args.getLastArg(options::OPT_rtlib_EQ); StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_RTLIB; // Only use "platform" in tests to override CLANG_DEFAULT_RTLIB! if (LibName == "compiler-rt") - return ToolChain::RLT_CompilerRT; + runtimeLibType = ToolChain::RLT_CompilerRT; else if (LibName == "libgcc") - return ToolChain::RLT_Libgcc; + runtimeLibType = ToolChain::RLT_Libgcc; else if (LibName == "platform") - return GetDefaultRuntimeLibType(); + runtimeLibType = GetDefaultRuntimeLibType(); + else { + if (A) + getDriver().Diag(diag::err_drv_invalid_rtlib_name) + << A->getAsString(Args); - if (A) - getDriver().Diag(diag::err_drv_invalid_rtlib_name) << A->getAsString(Args); + runtimeLibType = GetDefaultRuntimeLibType(); + } - return GetDefaultRuntimeLibType(); + return *runtimeLibType; } ToolChain::UnwindLibType ToolChain::GetUnwindLibType( const ArgList &Args) const { + if (unwindLibType) + return *unwindLibType; + const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ); StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_UNWINDLIB; if (LibName == "none") - return ToolChain::UNW_None; + unwindLibType = ToolChain::UNW_None; else if (LibName == "platform" || LibName == "") { ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args); if (RtLibType == ToolChain::RLT_CompilerRT) - return ToolChain::UNW_None; + unwindLibType = ToolChain::UNW_None; else if (RtLibType == ToolChain::RLT_Libgcc) - return ToolChain::UNW_Libgcc; + unwindLibType = ToolChain::UNW_Libgcc; } else if (LibName == "libunwind") { if (GetRuntimeLibType(Args) == RLT_Libgcc) getDriver().Diag(diag::err_drv_incompatible_unwindlib); - return ToolChain::UNW_CompilerRT; + unwindLibType = ToolChain::UNW_CompilerRT; } else if (LibName == "libgcc") - return ToolChain::UNW_Libgcc; + unwindLibType = ToolChain::UNW_Libgcc; + else { + if (A) + getDriver().Diag(diag::err_drv_invalid_unwindlib_name) + << A->getAsString(Args); - if (A) - getDriver().Diag(diag::err_drv_invalid_unwindlib_name) - << A->getAsString(Args); + unwindLibType = GetDefaultUnwindLibType(); + } - return GetDefaultUnwindLibType(); + return *unwindLibType; } ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ + if (cxxStdlibType) + return *cxxStdlibType; + const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ); StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB; // Only use "platform" in tests to override CLANG_DEFAULT_CXX_STDLIB! if (LibName == "libc++") - return ToolChain::CST_Libcxx; + cxxStdlibType = ToolChain::CST_Libcxx; else if (LibName == "libstdc++") - return ToolChain::CST_Libstdcxx; + cxxStdlibType = ToolChain::CST_Libstdcxx; else if (LibName == "platform") - return GetDefaultCXXStdlibType(); + cxxStdlibType = GetDefaultCXXStdlibType(); + else { + if (A) + getDriver().Diag(diag::err_drv_invalid_stdlib_name) + << A->getAsString(Args); - if (A) - getDriver().Diag(diag::err_drv_invalid_stdlib_name) << A->getAsString(Args); + cxxStdlibType = GetDefaultCXXStdlibType(); + } - return GetDefaultCXXStdlibType(); + return *cxxStdlibType; } /// Utility function to add a system include directory to CC1 arguments. Index: clang/test/Driver/undefined-libs.cpp =================================================================== --- /dev/null +++ clang/test/Driver/undefined-libs.cpp @@ -0,0 +1,15 @@ + +// Check that all the following options print a warning when given a non-existent +// value. But only one warning. + +// RUN: not %clangxx -stdlib=nostdlib %s 2>&1 | FileCheck --check-prefix=STDLIB %s +// STDLIB: error: invalid library name in argument '-stdlib=nostdlib' +// STDLIB-EMPTY: +// +// RUN: not %clangxx -rtlib=nortlib %s 2>&1 | FileCheck --check-prefix=RTLIB %s +// RTLIB: error: invalid runtime library name in argument '-rtlib=nortlib' +// RTLIB-EMPTY: +// +// RUN: not %clangxx -unwindlib=nounwindlib %s 2>&1 | FileCheck --check-prefix=UNWINDLIB %s +// UNWINDLIB: error: invalid unwind library name in argument '-unwindlib=nounwindlib' +// UNWINDLIB-EMPTY: