diff options
-rw-r--r-- | docs/UsersManual.rst | 12 | ||||
-rw-r--r-- | include/clang/Driver/CLCompatOptions.td | 2 | ||||
-rw-r--r-- | include/clang/Driver/Driver.h | 3 | ||||
-rw-r--r-- | lib/Driver/Driver.cpp | 53 | ||||
-rw-r--r-- | test/Driver/cl-options.c | 14 |
5 files changed, 70 insertions, 14 deletions
diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst index e0dc31f432..abf7f3a87d 100644 --- a/docs/UsersManual.rst +++ b/docs/UsersManual.rst @@ -2777,6 +2777,7 @@ Execute ``clang-cl /?`` to see a list of supported options: /arch:<value> Set architecture for code generation /Brepro- Emit an object file which cannot be reproduced over time /Brepro Emit an object file which can be reproduced over time + /clang:<arg> Pass <arg> to the clang driver /C Don't discard comments when preprocessing /c Compile only /d1PP Retain macro definitions in /E mode @@ -3012,6 +3013,17 @@ Execute ``clang-cl /?`` to see a list of supported options: -W<warning> Enable the specified warning -Xclang <arg> Pass <arg> to the clang compiler +The /clang: Option +^^^^^^^^^^^^^^^^^^ + +When clang-cl is run with a set of ``/clang:<arg>`` options, it will gather all +of the ``<arg>`` arguments and process them as if they were passed to the clang +driver. This mechanism allows you to pass flags that are not exposed in the +clang-cl options or flags that have a different meaning when passed to the clang +driver. Regardless of where they appear in the command line, the ``/clang:`` +arguments are treated as if they were passed at the end of the clang-cl command +line. + The /fallback Option ^^^^^^^^^^^^^^^^^^^^ diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td index 78667851ca..a51e53c59e 100644 --- a/include/clang/Driver/CLCompatOptions.td +++ b/include/clang/Driver/CLCompatOptions.td @@ -289,6 +289,8 @@ def _SLASH_vmv : CLFlag<"vmv">, def _SLASH_volatile_ms : Option<["/", "-"], "volatile:ms", KIND_FLAG>, Group<_SLASH_volatile_Group>, Flags<[CLOption, DriverOption]>, HelpText<"Volatile loads and stores have acquire and release semantics">; +def _SLASH_clang : CLJoined<"clang:">, + HelpText<"Pass <arg> to the clang driver">, MetaVarName<"<arg>">; def _SLASH_Zl : CLFlag<"Zl">, HelpText<"Don't mention any default libraries in the object file">; diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index b7b8022211..ec712585e8 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -363,6 +363,7 @@ public: /// ParseArgStrings - Parse the given list of strings into an /// ArgList. llvm::opt::InputArgList ParseArgStrings(ArrayRef<const char *> Args, + bool IsClCompatMode, bool &ContainsError); /// BuildInputs - Construct the list of inputs and their types from @@ -553,7 +554,7 @@ private: /// Get bitmasks for which option flags to include and exclude based on /// the driver mode. - std::pair<unsigned, unsigned> getIncludeExcludeOptionFlagMasks() const; + std::pair<unsigned, unsigned> getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const; /// Helper used in BuildJobsForAction. Doesn't use the cache when building /// jobs specifically for the given action, but will use the cache when diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 952a716cb6..1a2455d198 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -164,6 +164,7 @@ void Driver::setDriverModeFromOption(StringRef Opt) { } InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings, + bool IsClCompatMode, bool &ContainsError) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); ContainsError = false; @@ -171,7 +172,7 @@ InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings, unsigned IncludedFlagsBitmask; unsigned ExcludedFlagsBitmask; std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = - getIncludeExcludeOptionFlagMasks(); + getIncludeExcludeOptionFlagMasks(IsClCompatMode); unsigned MissingArgIndex, MissingArgCount; InputArgList Args = @@ -705,7 +706,7 @@ bool Driver::readConfigFile(StringRef FileName) { ConfigFile = CfgFileName.str(); bool ContainErrors; CfgOptions = llvm::make_unique<InputArgList>( - ParseArgStrings(NewCfgArgs, ContainErrors)); + ParseArgStrings(NewCfgArgs, IsCLMode(), ContainErrors)); if (ContainErrors) { CfgOptions.reset(); return true; @@ -899,7 +900,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { // Arguments specified in command line. bool ContainsError; CLOptions = llvm::make_unique<InputArgList>( - ParseArgStrings(ArgList.slice(1), ContainsError)); + ParseArgStrings(ArgList.slice(1), IsCLMode(), ContainsError)); // Try parsing configuration file. if (!ContainsError) @@ -909,21 +910,47 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { // All arguments, from both config file and command line. InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions) : std::move(*CLOptions)); - if (HasConfigFile) - for (auto *Opt : *CLOptions) { - if (Opt->getOption().matches(options::OPT_config)) - continue; + + auto appendOneArg = [&Args](const Arg *Opt, const Arg *BaseArg) { unsigned Index = Args.MakeIndex(Opt->getSpelling()); - const Arg *BaseArg = &Opt->getBaseArg(); - if (BaseArg == Opt) - BaseArg = nullptr; Arg *Copy = new llvm::opt::Arg(Opt->getOption(), Opt->getSpelling(), Index, BaseArg); Copy->getValues() = Opt->getValues(); if (Opt->isClaimed()) Copy->claim(); Args.append(Copy); + }; + + if (HasConfigFile) + for (auto *Opt : *CLOptions) { + if (Opt->getOption().matches(options::OPT_config)) + continue; + const Arg *BaseArg = &Opt->getBaseArg(); + if (BaseArg == Opt) + BaseArg = nullptr; + appendOneArg(Opt, BaseArg); + } + + // In CL mode, look for any pass-through arguments + if (IsCLMode() && !ContainsError) { + SmallVector<const char *, 16> CLModePassThroughArgList; + for (const auto *A : Args.filtered(options::OPT__SLASH_clang)) { + A->claim(); + CLModePassThroughArgList.push_back(A->getValue()); + } + + if (!CLModePassThroughArgList.empty()) { + // Parse any pass through args using default clang processing rather + // than clang-cl processing. + auto CLModePassThroughOptions = llvm::make_unique<InputArgList>( + ParseArgStrings(CLModePassThroughArgList, false, ContainsError)); + + if (!ContainsError) + for (auto *Opt : *CLModePassThroughOptions) { + appendOneArg(Opt, nullptr); + } } + } // FIXME: This stuff needs to go into the Compilation, not the driver. bool CCCPrintPhases; @@ -1417,7 +1444,7 @@ void Driver::PrintHelp(bool ShowHidden) const { unsigned IncludedFlagsBitmask; unsigned ExcludedFlagsBitmask; std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = - getIncludeExcludeOptionFlagMasks(); + getIncludeExcludeOptionFlagMasks(IsCLMode()); ExcludedFlagsBitmask |= options::NoDriverOption; if (!ShowHidden) @@ -4508,11 +4535,11 @@ bool Driver::GetReleaseVersion(StringRef Str, return false; } -std::pair<unsigned, unsigned> Driver::getIncludeExcludeOptionFlagMasks() const { +std::pair<unsigned, unsigned> Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const { unsigned IncludedFlagsBitmask = 0; unsigned ExcludedFlagsBitmask = options::NoDriverOption; - if (Mode == CLMode) { + if (IsClCompatMode) { // Include CL and Core options. IncludedFlagsBitmask |= options::CLOption; IncludedFlagsBitmask |= options::CoreOption; diff --git a/test/Driver/cl-options.c b/test/Driver/cl-options.c index 9aa6ced349..eb606afed8 100644 --- a/test/Driver/cl-options.c +++ b/test/Driver/cl-options.c @@ -600,5 +600,19 @@ // RUN: --version \ // RUN: -Werror /Zs -- %s 2>&1 +// Accept clang options under the /clang: flag. +// The first test case ensures that the SLP vectorizer is on by default and that +// it's being turned off by the /clang:-fno-slp-vectorize flag. + +// RUN: %clang_cl -O2 -### -- %s 2>&1 | FileCheck -check-prefix=NOCLANG %s +// NOCLANG: "--dependent-lib=libcmt" +// NOCLANG-SAME: "-vectorize-slp" +// NOCLANG-NOT: "--dependent-lib=msvcrt" + +// RUN: %clang_cl -O2 -MD /clang:-fno-slp-vectorize /clang:-MD /clang:-MF /clang:my_dependency_file.dep -### -- %s 2>&1 | FileCheck -check-prefix=CLANG %s +// CLANG: "--dependent-lib=msvcrt" +// CLANG-SAME: "-dependency-file" "my_dependency_file.dep" +// CLANG-NOT: "--dependent-lib=libcmt" +// CLANG-NOT: "-vectorize-slp" void f() { } |