Reorganize predefined macros for all Windows targets.
This adds an option to set the _MSC_VER macro without
recompiling. This is very useful when testing compatibility
with the Windows SDK and c++stdlib headers.
-fmsc-version=<version> (defaults to VS2003 (1300))
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116999 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/docs/UsersManual.html b/docs/UsersManual.html
index 154cf86..a271dc3 100644
--- a/docs/UsersManual.html
+++ b/docs/UsersManual.html
@@ -922,6 +922,12 @@
certain constructs (including __declspec and Microsoft-style asm statements).
</p>
+<li>clang allows setting _MCS_VER with -fmsc-version=. It defaults to 1300 which
+is the same as Visual C/C++ 2003. Any number is supported and can greatly affect
+what Windows SDK and c++stdlib headers clang can compile. This option will be
+removed when clang supports the full set of MS extensions required for these
+headers.</li>
+
<li>clang does not support the Microsoft extension where anonymous
record members can be declared using user defined typedefs.</li>
diff --git a/docs/tools/clang.pod b/docs/tools/clang.pod
index b99eb8f..9f7a448 100644
--- a/docs/tools/clang.pod
+++ b/docs/tools/clang.pod
@@ -175,6 +175,10 @@
Enable support for Microsoft extensions.
+=item B<-fmsc-version=>
+
+Set _MSC_VER. Defaults to 1300 on Windows. Not set otherwise.
+
=item B<-fborland-extensions>
Enable support for Borland extensions.
diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h
index a9c9935..dd1dc20 100644
--- a/include/clang/Basic/LangOptions.h
+++ b/include/clang/Basic/LangOptions.h
@@ -122,6 +122,11 @@
public:
unsigned InstantiationDepth; // Maximum template instantiation depth.
+ // Version of Microsoft Visual C/C++ we are pretending to be. This is
+ // temporary until we support all MS extensions used in Windows SDK and stdlib
+ // headers. Sets _MSC_VER.
+ unsigned MSCVersion;
+
std::string ObjCConstantStringClass;
enum GCMode { NonGC, GCOnly, HybridGC };
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index d801c90..8a967d0 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -425,6 +425,8 @@
HelpText<"Require math functions to indicate errors by setting errno">;
def fms_extensions : Flag<"-fms-extensions">,
HelpText<"Accept some non-standard constructs used in Microsoft header files ">;
+def fmsc_version : Joined<"-fmsc-version=">,
+ HelpText<"Version of the Microsoft C/C++ compiler to report in _MSC_VER (0 = don't define it (default))">;
def fborland_extensions : Flag<"-fborland-extensions">,
HelpText<"Accept non-standard constructs supported by the Borland compiler">;
def main_file_name : Separate<"-main-file-name">,
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index 8ee4395..da762be 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -304,6 +304,7 @@
def fmerge_all_constants : Flag<"-fmerge-all-constants">, Group<f_Group>;
def fmessage_length_EQ : Joined<"-fmessage-length=">, Group<f_Group>;
def fms_extensions : Flag<"-fms-extensions">, Group<f_Group>;
+def fmsc_version : Joined<"-fmsc-version=">, Group<f_Group>;
def fmudflapth : Flag<"-fmudflapth">, Group<f_Group>;
def fmudflap : Flag<"-fmudflap">, Group<f_Group>;
def fnested_functions : Flag<"-fnested-functions">, Group<f_Group>;
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 9601210..b6eb15c 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -405,6 +405,54 @@
// FIXME: WIntType should be SignedLong
}
};
+
+// Windows target
+template<typename Target>
+class WindowsTargetInfo : public OSTargetInfo<Target> {
+protected:
+ virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const {
+ if (Opts.CPlusPlus) {
+ if (Opts.RTTI)
+ Builder.defineMacro("_CPPRTTI");
+
+ if (Opts.Exceptions)
+ Builder.defineMacro("_CPPUNWIND");
+ }
+
+ if (!Opts.CharIsSigned)
+ Builder.defineMacro("_CHAR_UNSIGNED");
+
+ // FIXME: POSIXThreads isn't exactly the option this should be defined for,
+ // but it works for now.
+ if (Opts.POSIXThreads)
+ Builder.defineMacro("_MT");
+
+ if (Opts.MSCVersion != 0)
+ Builder.defineMacro("_MSC_VER", llvm::Twine(Opts.MSCVersion));
+
+ if (Opts.Microsoft) {
+ Builder.defineMacro("_MSC_EXTENSIONS");
+
+ if (Opts.CPlusPlus0x) {
+ Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED");
+ Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED");
+ Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED");
+ }
+ }
+
+ Builder.defineMacro("_INTEGRAL_MAX_BITS", "64");
+ Builder.defineMacro("_WIN32");
+ }
+
+ virtual const char *getVAListDeclaration() const {
+ return "typedef char* __builtin_va_list;";
+ }
+public:
+ WindowsTargetInfo(const std::string &triple)
+ : OSTargetInfo<Target>(triple) {}
+};
+
} // end anonymous namespace.
//===----------------------------------------------------------------------===//
@@ -1185,6 +1233,21 @@
break;
}
+ if (Opts.Microsoft && PointerWidth == 32) {
+ Builder.defineMacro("_M_IX86", "600");
+
+ switch (SSELevel) {
+ case SSE2:
+ Builder.defineMacro("_M_IX86_FP", llvm::Twine(2));
+ break;
+ case SSE1:
+ Builder.defineMacro("_M_IX86_FP", llvm::Twine(1));
+ break;
+ default:
+ Builder.defineMacro("_M_IX86_FP", llvm::Twine(0));
+ }
+ }
+
// Each case falls through to the previous one here.
switch (AMD3DNowLevel) {
case AMD3DNowAthlon:
@@ -1325,49 +1388,19 @@
namespace {
// x86-32 Windows target
-class WindowsX86_32TargetInfo : public X86_32TargetInfo {
+class WindowsX86_32TargetInfo : public WindowsTargetInfo<X86_32TargetInfo> {
public:
WindowsX86_32TargetInfo(const std::string& triple)
- : X86_32TargetInfo(triple) {
+ : WindowsTargetInfo<X86_32TargetInfo>(triple) {
TLSSupported = false;
WCharType = UnsignedShort;
DoubleAlign = LongLongAlign = 64;
+ LongDoubleWidth = 64;
+ LongDoubleFormat = &llvm::APFloat::IEEEdouble;
DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
"i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-"
"v128:128:128-a0:0:64-f80:32:32-n8:16:32";
}
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- X86_32TargetInfo::getTargetDefines(Opts, Builder);
- // This list is based off of the the list of things MingW defines
- Builder.defineMacro("_WIN32");
- DefineStd(Builder, "WIN32", Opts);
- DefineStd(Builder, "WINNT", Opts);
- Builder.defineMacro("_X86_");
- }
-};
-} // end anonymous namespace
-
-namespace {
-
-// x86-32 Windows Visual Studio target
-class VisualStudioWindowsX86_32TargetInfo : public WindowsX86_32TargetInfo {
-public:
- VisualStudioWindowsX86_32TargetInfo(const std::string& triple)
- : WindowsX86_32TargetInfo(triple) {
- LongDoubleWidth = 64;
- LongDoubleFormat = &llvm::APFloat::IEEEdouble;
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
- // The value of the following reflects processor type.
- // 300=386, 400=486, 500=Pentium, 600=Blend (default)
- // We lost the original triple, so we use the default.
- Builder.defineMacro("_M_IX86", "600");
- Builder.defineMacro("_INTEGRAL_MAX_BITS", "64");
- Builder.defineMacro("_STDCALL_SUPPORTED");
- }
};
} // end anonymous namespace
@@ -1474,10 +1507,10 @@
namespace {
// x86-64 Windows target
-class WindowsX86_64TargetInfo : public X86_64TargetInfo {
+class WindowsX86_64TargetInfo : public WindowsTargetInfo<X86_64TargetInfo> {
public:
WindowsX86_64TargetInfo(const std::string& triple)
- : X86_64TargetInfo(triple) {
+ : WindowsTargetInfo<X86_64TargetInfo>(triple) {
TLSSupported = false;
WCharType = UnsignedShort;
LongWidth = LongAlign = 32;
@@ -1491,25 +1524,11 @@
}
virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
- X86_64TargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("_WIN64");
- DefineStd(Builder, "WIN64", Opts);
- }
-};
-} // end anonymous namespace
+ WindowsTargetInfo<X86_64TargetInfo>::getTargetDefines(Opts, Builder);
-namespace {
-// x86-64 Windows Visual Studio target
-class VisualStudioWindowsX86_64TargetInfo : public WindowsX86_64TargetInfo {
-public:
- VisualStudioWindowsX86_64TargetInfo(const std::string& triple)
- : WindowsX86_64TargetInfo(triple) {
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
+ Builder.defineMacro("_WIN64");
Builder.defineMacro("_M_X64");
- Builder.defineMacro("_INTEGRAL_MAX_BITS", "64");
+ Builder.defineMacro("_M_AMD64");
}
virtual const char *getVAListDeclaration() const {
return "typedef char* __builtin_va_list;";
@@ -2523,7 +2542,7 @@
case llvm::Triple::MinGW32:
return new MinGWX86_32TargetInfo(T);
case llvm::Triple::Win32:
- return new VisualStudioWindowsX86_32TargetInfo(T);
+ return new WindowsX86_32TargetInfo(T);
case llvm::Triple::Haiku:
return new HaikuX86_32TargetInfo(T);
default:
@@ -2551,7 +2570,7 @@
case llvm::Triple::MinGW64:
return new MinGWX86_64TargetInfo(T);
case llvm::Triple::Win32: // This is what Triple.h supports now.
- return new VisualStudioWindowsX86_64TargetInfo(T);
+ return new WindowsX86_64TargetInfo(T);
default:
return new X86_64TargetInfo(T);
}
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index d4ba92c..021c7cb 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -1314,6 +1314,18 @@
getToolChain().getTriple().getOS() == llvm::Triple::Win32))
CmdArgs.push_back("-fms-extensions");
+ // -fmsc-version=1300 is default.
+ if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
+ getToolChain().getTriple().getOS() == llvm::Triple::Win32) ||
+ Args.hasArg(options::OPT_fmsc_version)) {
+ llvm::StringRef msc_ver = Args.getLastArgValue(options::OPT_fmsc_version);
+ if (msc_ver.empty())
+ CmdArgs.push_back("-fmsc-version=1300");
+ else
+ CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + msc_ver));
+ }
+
+
// -fborland-extensions=0 is default.
if (Args.hasFlag(options::OPT_fborland_extensions,
options::OPT_fno_borland_extensions, false))
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index b7ad08b..3ed859a 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -529,6 +529,8 @@
Res.push_back("-fgnu-keywords");
if (Opts.Microsoft)
Res.push_back("-fms-extensions");
+ if (Opts.MSCVersion != 0)
+ Res.push_back("-fmsc-version=" + llvm::utostr(Opts.MSCVersion));
if (Opts.Borland)
Res.push_back("-fborland-extensions");
if (Opts.ObjCNonFragileABI)
@@ -1334,6 +1336,7 @@
!Opts.AsmPreprocessor);
Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings);
Opts.Microsoft = Args.hasArg(OPT_fms_extensions);
+ Opts.MSCVersion = Args.getLastArgIntValue(OPT_fmsc_version, 0, Diags);
Opts.Borland = Args.hasArg(OPT_fborland_extensions);
Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings);
Opts.ConstStrings = Args.hasArg(OPT_Wwrite_strings);
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index ada41b4..4461703 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -74,6 +74,7 @@
PARSE_LANGOPT_BENIGN(HexFloats);
PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
+ PARSE_LANGOPT_BENIGN(MSCVersion);
PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
PARSE_LANGOPT_BENIGN(CXXOperatorName);
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index d0e4802..4d0ec99 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -828,6 +828,8 @@
Record.push_back(LangOpts.HexFloats); // C99 Hexadecimal float constants.
Record.push_back(LangOpts.C99); // C99 Support
Record.push_back(LangOpts.Microsoft); // Microsoft extensions.
+ // LangOpts.MSCVersion is ignored because all it does it set a macro, which is
+ // already saved elsewhere.
Record.push_back(LangOpts.CPlusPlus); // C++ Support
Record.push_back(LangOpts.CPlusPlus0x); // C++0x Support
Record.push_back(LangOpts.CXXOperatorNames); // Treat C++ operator names as keywords.