Skip to content

Commit fda44be

Browse files
committed
Add Clang driver flags equivalent to cl's /MD, /MT, /MDd, /MTd.
This will allow selecting the MS C runtime library without having to use cc1 flags. Differential Revision: https://reviews.llvm.org/D133457
1 parent 644dfba commit fda44be

File tree

3 files changed

+85
-51
lines changed

3 files changed

+85
-51
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2211,6 +2211,14 @@ def fms_compatibility_version
22112211
HelpText<"Dot-separated value representing the Microsoft compiler "
22122212
"version number to report in _MSC_VER (0 = don't define it "
22132213
"(default))">;
2214+
def fms_runtime_lib_EQ : Joined<["-"], "fms-runtime-lib=">, Group<f_Group>,
2215+
Flags<[NoXarchOption, CoreOption]>, Values<"static,static_dbg,dll,dll_dbg">,
2216+
HelpText<"Select Windows run-time library">,
2217+
DocBrief<[{
2218+
Specify Visual Studio C runtime library. "static" and "static_dbg" correspond
2219+
to the cl flags /MT and /MTd which use the multithread, static version. "dll"
2220+
and "dll_dbg" correspond to the cl flags /MD and /MDd which use the multithread,
2221+
dll version.}]>;
22142222
defm delayed_template_parsing : BoolFOption<"delayed-template-parsing",
22152223
LangOpts<"DelayedTemplateParsing">, DefaultFalse,
22162224
PosFlag<SetTrue, [CC1Option], "Parse templated function definitions at the end of the translation unit">,

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 69 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4437,6 +4437,71 @@ static void renderDebugOptions(const ToolChain &TC, const Driver &D,
44374437
RenderDebugInfoCompressionArgs(Args, CmdArgs, D, TC);
44384438
}
44394439

4440+
static void ProcessVSRuntimeLibrary(const ArgList &Args,
4441+
ArgStringList &CmdArgs) {
4442+
unsigned RTOptionID = options::OPT__SLASH_MT;
4443+
4444+
if (Args.hasArg(options::OPT__SLASH_LDd))
4445+
// The /LDd option implies /MTd. The dependent lib part can be overridden,
4446+
// but defining _DEBUG is sticky.
4447+
RTOptionID = options::OPT__SLASH_MTd;
4448+
4449+
if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
4450+
RTOptionID = A->getOption().getID();
4451+
4452+
if (Arg *A = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
4453+
RTOptionID = llvm::StringSwitch<unsigned>(A->getValue())
4454+
.Case("static", options::OPT__SLASH_MT)
4455+
.Case("static_dbg", options::OPT__SLASH_MTd)
4456+
.Case("dll", options::OPT__SLASH_MD)
4457+
.Case("dll_dbg", options::OPT__SLASH_MDd)
4458+
.Default(options::OPT__SLASH_MT);
4459+
}
4460+
4461+
StringRef FlagForCRT;
4462+
switch (RTOptionID) {
4463+
case options::OPT__SLASH_MD:
4464+
if (Args.hasArg(options::OPT__SLASH_LDd))
4465+
CmdArgs.push_back("-D_DEBUG");
4466+
CmdArgs.push_back("-D_MT");
4467+
CmdArgs.push_back("-D_DLL");
4468+
FlagForCRT = "--dependent-lib=msvcrt";
4469+
break;
4470+
case options::OPT__SLASH_MDd:
4471+
CmdArgs.push_back("-D_DEBUG");
4472+
CmdArgs.push_back("-D_MT");
4473+
CmdArgs.push_back("-D_DLL");
4474+
FlagForCRT = "--dependent-lib=msvcrtd";
4475+
break;
4476+
case options::OPT__SLASH_MT:
4477+
if (Args.hasArg(options::OPT__SLASH_LDd))
4478+
CmdArgs.push_back("-D_DEBUG");
4479+
CmdArgs.push_back("-D_MT");
4480+
CmdArgs.push_back("-flto-visibility-public-std");
4481+
FlagForCRT = "--dependent-lib=libcmt";
4482+
break;
4483+
case options::OPT__SLASH_MTd:
4484+
CmdArgs.push_back("-D_DEBUG");
4485+
CmdArgs.push_back("-D_MT");
4486+
CmdArgs.push_back("-flto-visibility-public-std");
4487+
FlagForCRT = "--dependent-lib=libcmtd";
4488+
break;
4489+
default:
4490+
llvm_unreachable("Unexpected option ID.");
4491+
}
4492+
4493+
if (Args.hasArg(options::OPT__SLASH_Zl)) {
4494+
CmdArgs.push_back("-D_VC_NODEFAULTLIB");
4495+
} else {
4496+
CmdArgs.push_back(FlagForCRT.data());
4497+
4498+
// This provides POSIX compatibility (maps 'open' to '_open'), which most
4499+
// users want. The /Za flag to cl.exe turns this off, but it's not
4500+
// implemented in clang.
4501+
CmdArgs.push_back("--dependent-lib=oldnames");
4502+
}
4503+
}
4504+
44404505
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
44414506
const InputInfo &Output, const InputInfoList &Inputs,
44424507
const ArgList &Args, const char *LinkingOutput) const {
@@ -6478,6 +6543,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
64786543
if (IsMSVCCompat)
64796544
CmdArgs.push_back("-fms-compatibility");
64806545

6546+
if (Triple.isWindowsMSVCEnvironment() && !D.IsCLMode())
6547+
ProcessVSRuntimeLibrary(Args, CmdArgs);
6548+
64816549
// Handle -fgcc-version, if present.
64826550
VersionTuple GNUCVer;
64836551
if (Arg *A = Args.getLastArg(options::OPT_fgnuc_version_EQ)) {
@@ -7528,59 +7596,9 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
75287596
ArgStringList &CmdArgs,
75297597
codegenoptions::DebugInfoKind *DebugInfoKind,
75307598
bool *EmitCodeView) const {
7531-
unsigned RTOptionID = options::OPT__SLASH_MT;
75327599
bool isNVPTX = getToolChain().getTriple().isNVPTX();
75337600

7534-
if (Args.hasArg(options::OPT__SLASH_LDd))
7535-
// The /LDd option implies /MTd. The dependent lib part can be overridden,
7536-
// but defining _DEBUG is sticky.
7537-
RTOptionID = options::OPT__SLASH_MTd;
7538-
7539-
if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
7540-
RTOptionID = A->getOption().getID();
7541-
7542-
StringRef FlagForCRT;
7543-
switch (RTOptionID) {
7544-
case options::OPT__SLASH_MD:
7545-
if (Args.hasArg(options::OPT__SLASH_LDd))
7546-
CmdArgs.push_back("-D_DEBUG");
7547-
CmdArgs.push_back("-D_MT");
7548-
CmdArgs.push_back("-D_DLL");
7549-
FlagForCRT = "--dependent-lib=msvcrt";
7550-
break;
7551-
case options::OPT__SLASH_MDd:
7552-
CmdArgs.push_back("-D_DEBUG");
7553-
CmdArgs.push_back("-D_MT");
7554-
CmdArgs.push_back("-D_DLL");
7555-
FlagForCRT = "--dependent-lib=msvcrtd";
7556-
break;
7557-
case options::OPT__SLASH_MT:
7558-
if (Args.hasArg(options::OPT__SLASH_LDd))
7559-
CmdArgs.push_back("-D_DEBUG");
7560-
CmdArgs.push_back("-D_MT");
7561-
CmdArgs.push_back("-flto-visibility-public-std");
7562-
FlagForCRT = "--dependent-lib=libcmt";
7563-
break;
7564-
case options::OPT__SLASH_MTd:
7565-
CmdArgs.push_back("-D_DEBUG");
7566-
CmdArgs.push_back("-D_MT");
7567-
CmdArgs.push_back("-flto-visibility-public-std");
7568-
FlagForCRT = "--dependent-lib=libcmtd";
7569-
break;
7570-
default:
7571-
llvm_unreachable("Unexpected option ID.");
7572-
}
7573-
7574-
if (Args.hasArg(options::OPT__SLASH_Zl)) {
7575-
CmdArgs.push_back("-D_VC_NODEFAULTLIB");
7576-
} else {
7577-
CmdArgs.push_back(FlagForCRT.data());
7578-
7579-
// This provides POSIX compatibility (maps 'open' to '_open'), which most
7580-
// users want. The /Za flag to cl.exe turns this off, but it's not
7581-
// implemented in clang.
7582-
CmdArgs.push_back("--dependent-lib=oldnames");
7583-
}
7601+
ProcessVSRuntimeLibrary(Args, CmdArgs);
75847602

75857603
if (Arg *ShowIncludes =
75867604
Args.getLastArg(options::OPT__SLASH_showIncludes,

clang/test/Driver/cl-runtime-flags.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

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

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

2933
// RUN: %clang_cl -### /MD -- %s 2>&1 | FileCheck -check-prefix=CHECK-MD %s
34+
// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll -- %s \
35+
// RUN: 2>&1 | FileCheck -check-prefix=CHECK-MD %s
3036
// CHECK-MD-NOT: "-D_DEBUG"
3137
// CHECK-MD: "-D_MT"
3238
// CHECK-MD: "-D_DLL"
3339
// CHECK-MD: "--dependent-lib=msvcrt"
3440
// CHECK-MD: "--dependent-lib=oldnames"
3541

3642
// RUN: %clang_cl -### /MDd -- %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
43+
// RUN: %clang -### --target=x86_64-windows-msvc -fms-runtime-lib=dll_dbg -- \
44+
// RUN: %s 2>&1 | FileCheck -check-prefix=CHECK-MDd %s
3745
// CHECK-MDd: "-D_DEBUG"
3846
// CHECK-MDd: "-D_MT"
3947
// CHECK-MDd: "-D_DLL"

0 commit comments

Comments
 (0)