From dae4ac4fe56ec60fc93b3e3c9f51e79e682084b9 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" <bigcheesegs@gmail.com> Date: Thu, 21 Oct 2010 05:21:48 +0000 Subject: [PATCH] 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 --- docs/UsersManual.html | 6 ++ docs/tools/clang.pod | 4 + include/clang/Basic/LangOptions.h | 5 ++ include/clang/Driver/CC1Options.td | 2 + include/clang/Driver/Options.td | 1 + lib/Basic/Targets.cpp | 129 ++++++++++++++++------------ lib/Driver/Tools.cpp | 12 +++ lib/Frontend/CompilerInvocation.cpp | 3 + lib/Serialization/ASTReader.cpp | 1 + lib/Serialization/ASTWriter.cpp | 2 + 10 files changed, 110 insertions(+), 55 deletions(-) diff --git a/docs/UsersManual.html b/docs/UsersManual.html index 154cf86add8..a271dc32bf6 100644 --- a/docs/UsersManual.html +++ b/docs/UsersManual.html @@ -922,6 +922,12 @@ support is incomplete; enabling Microsoft extensions will silently drop 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 b99eb8f7a72..9f7a4483019 100644 --- a/docs/tools/clang.pod +++ b/docs/tools/clang.pod @@ -175,6 +175,10 @@ Enable support for Pascal-style strings with "\pfoo". 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 a9c99352765..dd1dc20c09c 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -122,6 +122,11 @@ private: 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 d801c900aea..8a967d033a3 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -425,6 +425,8 @@ def fmath_errno : Flag<"-fmath-errno">, 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 8ee43955c3b..da762becb64 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -304,6 +304,7 @@ def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>; 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 96012102120..b6eb15c85e2 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -405,6 +405,54 @@ public: // 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 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, 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 @@ public: 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 @@ public: 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 @@ public: } 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 @@ static TargetInfo *AllocateTarget(const std::string &T) { 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 @@ static TargetInfo *AllocateTarget(const std::string &T) { 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 d4ba92cdb64..021c7cb7d37 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1314,6 +1314,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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 b7ad08b8b2b..3ed859a87bf 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -529,6 +529,8 @@ static void LangOptsToArgs(const LangOptions &Opts, 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 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, !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 ada41b446ca..4461703f522 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -74,6 +74,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { 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 d0e4802524b..4d0ec990749 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -828,6 +828,8 @@ void ASTWriter::WriteLanguageOptions(const LangOptions &LangOpts) { 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. -- GitLab