diff options
Diffstat (limited to 'clang/lib/Driver/Tools.cpp')
| -rw-r--r-- | clang/lib/Driver/Tools.cpp | 77 |
1 files changed, 76 insertions, 1 deletions
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index da27a941a1b..a9d3acc2da4 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -3565,7 +3565,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // Finally add the compile command to the compilation. - C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + if (Args.hasArg(options::OPT__SLASH_fallback)) { + tools::visualstudio::Compile CL(getToolChain()); + Command *CLCommand = CL.GetCommand(C, JA, Output, Inputs, Args, + LinkingOutput); + C.addCommand(new FallbackCommand(JA, *this, Exec, CmdArgs, CLCommand)); + } else { + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + } + // Handle the debug info splitting at object creation time if we're // creating an object. @@ -6638,3 +6646,70 @@ void visualstudio::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString(getToolChain().GetProgramPath("link.exe")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } + +void visualstudio::Compile::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput)); +} + +Command *visualstudio::Compile::GetCommand(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + ArgStringList CmdArgs; + CmdArgs.push_back("/c"); // Compile only. + CmdArgs.push_back("/W0"); // No warnings. + + // The goal is to be able to invoke this tool correctly based on + // any flag accepted by clang-cl. + + // These are spelled the same way in clang and cl.exe,. + Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U); + Args.AddAllArgs(CmdArgs, options::OPT_I); + Args.AddLastArg(CmdArgs, options::OPT_O, options::OPT_O0); + + // Flags for which clang-cl have an alias. + // FIXME: How can we ensure this stays in sync with relevant clang-cl options? + + if (Arg *A = Args.getLastArg(options::OPT_frtti, options::OPT_fno_rtti)) + CmdArgs.push_back(A->getOption().getID() == options::OPT_frtti ? "/GR" + : "/GR-"); + if (Args.hasArg(options::OPT_fsyntax_only)) + CmdArgs.push_back("/Zs"); + + // Flags that can simply be passed through. + Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD); + Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd); + + // The order of these flags is relevant, so pick the last one. + if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd, + options::OPT__SLASH_MT, options::OPT__SLASH_MTd)) + A->render(Args, CmdArgs); + + + // Input filename. + assert(Inputs.size() == 1); + const InputInfo &II = Inputs[0]; + assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX); + CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : "/Tp"); + if (II.isFilename()) + CmdArgs.push_back(II.getFilename()); + else + II.getInputArg().renderAsInput(Args, CmdArgs); + + // Output filename. + assert(Output.getType() == types::TY_Object); + const char *Fo = Args.MakeArgString(std::string("/Fo") + + Output.getFilename()); + CmdArgs.push_back(Fo); + + // FIXME: If we've put clang-cl as cl.exe on the path, we have a problem. + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath("cl.exe")); + + return new Command(JA, *this, Exec, CmdArgs); +} |

