Skip to content

Commit

Permalink
Add Clang driver flags equivalent to cl's /MD, /MT, /MDd, /MTd.
Browse files Browse the repository at this point in the history
This will allow selecting the MS C runtime library without having to use
cc1 flags.

Differential Revision: https://reviews.llvm.org/D133457
  • Loading branch information
amykhuang committed Sep 15, 2022
1 parent 644dfba commit fda44be
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 51 deletions.
8 changes: 8 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2211,6 +2211,14 @@ def fms_compatibility_version
HelpText<"Dot-separated value representing the Microsoft compiler "
"version number to report in _MSC_VER (0 = don't define it "
"(default))">;
def fms_runtime_lib_EQ : Joined<["-"], "fms-runtime-lib=">, Group<f_Group>,
Flags<[NoXarchOption, CoreOption]>, Values<"static,static_dbg,dll,dll_dbg">,
HelpText<"Select Windows run-time library">,
DocBrief<[{
Specify Visual Studio C runtime library. "static" and "static_dbg" correspond
to the cl flags /MT and /MTd which use the multithread, static version. "dll"
and "dll_dbg" correspond to the cl flags /MD and /MDd which use the multithread,
dll version.}]>;
defm delayed_template_parsing : BoolFOption<"delayed-template-parsing",
LangOpts<"DelayedTemplateParsing">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Parse templated function definitions at the end of the translation unit">,
Expand Down
120 changes: 69 additions & 51 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4437,6 +4437,71 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
RenderDebugInfoCompressionArgs(Args, CmdArgs, D, TC);
}

static void ProcessVSRuntimeLibrary(const ArgList &Args,
ArgStringList &CmdArgs) {
unsigned RTOptionID = options::OPT__SLASH_MT;

if (Args.hasArg(options::OPT__SLASH_LDd))
// The /LDd option implies /MTd. The dependent lib part can be overridden,
// but defining _DEBUG is sticky.
RTOptionID = options::OPT__SLASH_MTd;

if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
RTOptionID = A->getOption().getID();

if (Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
RTOptionID = llvm::StringSwitch<unsigned>(A->getValue())
.Case("static", options::OPT__SLASH_MT)
.Case("static_dbg", options::OPT__SLASH_MTd)
.Case("dll", options::OPT__SLASH_MD)
.Case("dll_dbg", options::OPT__SLASH_MDd)
.Default(options::OPT__SLASH_MT);
}

StringRef FlagForCRT;
switch (RTOptionID) {
case options::OPT__SLASH_MD:
if (Args.hasArg(options::OPT__SLASH_LDd))
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-D_DLL");
FlagForCRT = "--dependent-lib=msvcrt";
break;
case options::OPT__SLASH_MDd:
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-D_DLL");
FlagForCRT = "--dependent-lib=msvcrtd";
break;
case options::OPT__SLASH_MT:
if (Args.hasArg(options::OPT__SLASH_LDd))
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-flto-visibility-public-std");
FlagForCRT = "--dependent-lib=libcmt";
break;
case options::OPT__SLASH_MTd:
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-flto-visibility-public-std");
FlagForCRT = "--dependent-lib=libcmtd";
break;
default:
llvm_unreachable("Unexpected option ID.");
}

if (Args.hasArg(options::OPT__SLASH_Zl)) {
CmdArgs.push_back("-D_VC_NODEFAULTLIB");
} else {
CmdArgs.push_back(FlagForCRT.data());

// This provides POSIX compatibility (maps 'open' to '_open'), which most
// users want. The /Za flag to cl.exe turns this off, but it's not
// implemented in clang.
CmdArgs.push_back("--dependent-lib=oldnames");
}
}

void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, const char *LinkingOutput) const {
Expand Down Expand Up @@ -6478,6 +6543,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (IsMSVCCompat)
CmdArgs.push_back("-fms-compatibility");

if (Triple.isWindowsMSVCEnvironment() && !D.IsCLMode())
ProcessVSRuntimeLibrary(Args, CmdArgs);

// Handle -fgcc-version, if present.
VersionTuple GNUCVer;
if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) {
Expand Down Expand Up @@ -7528,59 +7596,9 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
ArgStringList &CmdArgs,
codegenoptions::DebugInfoKind *DebugInfoKind,
bool *EmitCodeView) const {
unsigned RTOptionID = options::OPT__SLASH_MT;
bool isNVPTX = getToolChain().getTriple().isNVPTX();

if (Args.hasArg(options::OPT__SLASH_LDd))
// The /LDd option implies /MTd. The dependent lib part can be overridden,
// but defining _DEBUG is sticky.
RTOptionID = options::OPT__SLASH_MTd;

if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
RTOptionID = A->getOption().getID();

StringRef FlagForCRT;
switch (RTOptionID) {
case options::OPT__SLASH_MD:
if (Args.hasArg(options::OPT__SLASH_LDd))
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-D_DLL");
FlagForCRT = "--dependent-lib=msvcrt";
break;
case options::OPT__SLASH_MDd:
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-D_DLL");
FlagForCRT = "--dependent-lib=msvcrtd";
break;
case options::OPT__SLASH_MT:
if (Args.hasArg(options::OPT__SLASH_LDd))
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-flto-visibility-public-std");
FlagForCRT = "--dependent-lib=libcmt";
break;
case options::OPT__SLASH_MTd:
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-flto-visibility-public-std");
FlagForCRT = "--dependent-lib=libcmtd";
break;
default:
llvm_unreachable("Unexpected option ID.");
}

if (Args.hasArg(options::OPT__SLASH_Zl)) {
CmdArgs.push_back("-D_VC_NODEFAULTLIB");
} else {
CmdArgs.push_back(FlagForCRT.data());

// This provides POSIX compatibility (maps 'open' to '_open'), which most
// users want. The /Za flag to cl.exe turns this off, but it's not
// implemented in clang.
CmdArgs.push_back("--dependent-lib=oldnames");
}
ProcessVSRuntimeLibrary(Args, CmdArgs);

if (Arg *ShowIncludes =
Args.getLastArg(options::OPT__SLASH_showIncludes,
Expand Down
8 changes: 8 additions & 0 deletions clang/test/Driver/cl-runtime-flags.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

// RUN: %clang_cl -### -- %s 2>&1 | FileCheck -check-prefix=CHECK-MT %s
// RUN: %clang_cl -### /MT -- %s 2>&1 | FileCheck -check-prefix=CHECK-MT %s
// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static -- %s \
// RUN: 2>&1 | FileCheck -check-prefix=CHECK-MT %s
// CHECK-MT-NOT: "-D_DEBUG"
// CHECK-MT: "-D_MT"
// CHECK-MT-NOT: "-D_DLL"
Expand All @@ -19,6 +21,8 @@

// RUN: %clang_cl -### /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
// RUN: %clang_cl -### /LD /MTd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=static_dbg \
// RUN: -- %s 2>&1 | FileCheck -check-prefix=CHECK-MTd %s
// CHECK-MTd: "-D_DEBUG"
// CHECK-MTd: "-D_MT"
// CHECK-MTd-NOT: "-D_DLL"
Expand All @@ -27,13 +31,17 @@
// CHECK-MTd: "--dependent-lib=oldnames"

// RUN: %clang_cl -### /MD -- %s 2>&1 | FileCheck -check-prefix=CHECK-MD %s
// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll -- %s \
// RUN: 2>&1 | FileCheck -check-prefix=CHECK-MD %s
// CHECK-MD-NOT: "-D_DEBUG"
// CHECK-MD: "-D_MT"
// CHECK-MD: "-D_DLL"
// CHECK-MD: "--dependent-lib=msvcrt"
// CHECK-MD: "--dependent-lib=oldnames"

// RUN: %clang_cl -### /MDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll_dbg -- \
// RUN: %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
// CHECK-MDd: "-D_DEBUG"
// CHECK-MDd: "-D_MT"
// CHECK-MDd: "-D_DLL"
Expand Down

0 comments on commit fda44be

Please sign in to comment.