Index: include/clang/Basic/LangOptions.def =================================================================== --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -180,8 +180,7 @@ "maximum bracket nesting depth") BENIGN_LANGOPT(NumLargeByValueCopy, 32, 0, "if non-zero, warn about parameter or return Warn if parameter/return value is larger in bytes than this setting. 0 is no check.") -VALUE_LANGOPT(MSCVersion, 32, 0, - "version of Microsoft Visual C/C++") +VALUE_LANGOPT(MSCompatibilityVersion, 32, 0, "Microsoft Visual C/C++ Version") VALUE_LANGOPT(VtorDispMode, 2, 1, "How many vtordisps to insert") LANGOPT(ApplePragmaPack, 1, 0, "Apple gcc-compatible #pragma pack handling") Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -585,8 +585,11 @@ HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">; def fms_compatibility : Flag<["-"], "fms-compatibility">, Group, Flags<[CC1Option]>, HelpText<"Enable full Microsoft Visual C++ compatibility">; -def fmsc_version : Joined<["-"], "fmsc-version=">, Group, Flags<[CC1Option, CoreOption]>, +def fmsc_version : Joined<["-"], "fmsc-version=">, Group, Flags<[DriverOption]>, HelpText<"Microsoft compiler version number to report in _MSC_VER (0 = don't define it (default))">; +def fms_compatibility_version : Joined<["-"], "fms-compatibility-version=">, + Group, Flags<[CC1Option, CoreOption]>, + HelpText<"Extended Microsoft compiler version">; def fdelayed_template_parsing : Flag<["-"], "fdelayed-template-parsing">, Group, HelpText<"Parse templated function definitions at the end of the " "translation unit">, Flags<[CC1Option]>; Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -586,9 +586,10 @@ if (Opts.POSIXThreads) Builder.defineMacro("_MT"); - if (Opts.MSCVersion != 0) { - Builder.defineMacro("_MSC_VER", Twine(Opts.MSCVersion / 100000)); - Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCVersion)); + if (Opts.MSCompatibilityVersion) { + Builder.defineMacro("_MSC_VER", + Twine(Opts.MSCompatibilityVersion / 100000)); + Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion)); // FIXME We cannot encode the revision information into 32-bits Builder.defineMacro("_MSC_BUILD", Twine(1)); } Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -2232,6 +2232,26 @@ CmdArgs.push_back(types::getTypeName(Input.getType())); } +static std::string getMSCompatibilityVersion(const char *VersionStr) { + unsigned Version; + if (StringRef(VersionStr).getAsInteger(10, Version)) + return "0"; + + if (Version < 100) + return llvm::utostr_32(Version) + ".0"; + + if (Version < 10000) + return llvm::utostr_32(Version / 100) + "." + + llvm::utostr_32(Version % 100); + + unsigned Build = 0, Factor = 1; + for ( ; Version > 10000; Version = Version / 10, Factor = Factor * 10) + Build = Build + (Version % 10) * Factor; + return llvm::utostr_32(Version / 100) + "." + + llvm::utostr_32(Version % 100) + "." + + llvm::utostr_32(Build); +} + void Clang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -3741,17 +3761,31 @@ true)))) CmdArgs.push_back("-fms-compatibility"); - // -fmsc-version=1700 is default. + // -fms-compatibility-version=17.00 is default. if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, - IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version)) { - StringRef msc_ver = Args.getLastArgValue(options::OPT_fmsc_version); - if (msc_ver.empty()) - CmdArgs.push_back("-fmsc-version=1700"); + IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version) || + Args.hasArg(options::OPT_fms_compatibility_version)) { + const Arg *MSCVersion = Args.getLastArg(options::OPT_fmsc_version); + const Arg *MSCompatibilityVersion = + Args.getLastArg(options::OPT_fms_compatibility_version); + + if (MSCVersion && MSCompatibilityVersion) + D.Diag(diag::err_drv_argument_not_allowed_with) + << MSCVersion->getAsString(Args) + << MSCompatibilityVersion->getAsString(Args); + + std::string Ver; + if (MSCompatibilityVersion) + Ver = Args.getLastArgValue(options::OPT_fms_compatibility_version); + else if (MSCVersion) + Ver = getMSCompatibilityVersion(MSCVersion->getValue()); + + if (Ver.empty()) + CmdArgs.push_back("-fms-compatibility-version=17.00"); else - CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + msc_ver)); + CmdArgs.push_back(Args.MakeArgString("-fms-compatibility-version=" + Ver)); } - // -fno-borland-extensions is default. if (Args.hasFlag(options::OPT_fborland_extensions, options::OPT_fno_borland_extensions, false)) Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1208,7 +1208,7 @@ } static unsigned parseMSCVersion(ArgList &Args, DiagnosticsEngine &Diags) { - auto Arg = Args.getLastArg(OPT_fmsc_version); + auto Arg = Args.getLastArg(OPT_fms_compatibility_version); if (!Arg) return 0; @@ -1225,25 +1225,8 @@ // Unfortunately, due to the bit-width limitations, we cannot currently encode // the value for the patch level. - StringRef Value = Arg->getValue(); - - // parse the compatible old form of _MSC_VER or the newer _MSC_FULL_VER - if (Value.find('.') == StringRef::npos) { - unsigned Version = 0; - if (Value.getAsInteger(10, Version)) { - Diags.Report(diag::err_drv_invalid_value) - << Arg->getAsString(Args) << Value; - return 0; - } - if (Version < 100) - Version = Version * 100; // major -> major.minor - if (Version < 100000) - Version = Version * 100000; // major.minor -> major.minor.build - return Version; - } - - // parse the dot-delimited component version unsigned VC[4] = {0}; + StringRef Value = Arg->getValue(); SmallVector Components; Value.split(Components, ".", llvm::array_lengthof(VC)); @@ -1430,7 +1413,7 @@ Opts.MSVCCompat = Args.hasArg(OPT_fms_compatibility); Opts.MicrosoftExt = Opts.MSVCCompat || Args.hasArg(OPT_fms_extensions); Opts.AsmBlocks = Args.hasArg(OPT_fasm_blocks) || Opts.MicrosoftExt; - Opts.MSCVersion = parseMSCVersion(Args, Diags); + Opts.MSCompatibilityVersion = parseMSCVersion(Args, Diags); Opts.VtorDispMode = getLastArgIntValue(Args, OPT_vtordisp_mode_EQ, 1, Diags); Opts.Borland = Args.hasArg(OPT_fborland_extensions); Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); Index: lib/Frontend/TextDiagnostic.cpp =================================================================== --- lib/Frontend/TextDiagnostic.cpp +++ lib/Frontend/TextDiagnostic.cpp @@ -808,7 +808,8 @@ if (DiagOpts->getFormat() == DiagnosticOptions::Msvc) { OS << ','; // Visual Studio 2010 or earlier expects column number to be off by one - if (LangOpts.MSCVersion && LangOpts.MSCVersion < 170000000) + if (LangOpts.MSCompatibilityVersion && + LangOpts.MSCompatibilityVersion < 170000000) ColNo--; } else OS << ':'; Index: test/Driver/msc-version.c =================================================================== --- test/Driver/msc-version.c +++ test/Driver/msc-version.c @@ -1,42 +1,68 @@ +// +// Verify defaults +// + // RUN: %clang -target i686-windows -fms-compatibility -dM -E - &1 | FileCheck %s -check-prefix CHECK-BASIC-EXTENDED-DIAGNOSTIC + +// CHECK-BASIC-EXTENDED-DIAGNOSTIC: invalid argument '-fmsc-version={{.*}}' not allowed with '-fms-compatibility-version={{.*}}' + + +// +// Verify -fmsc-version to -fms-compatibility-version conversion +// + +// RUN: %clang -### -target i686-windows -fms-compatibility -fmsc-version=17 -E - &1 | FileCheck %s -check-prefix CHECK-MSC-17 + +// CHECK-MSC-17-NOT: "-fmsc-version=1700" +// CHECK-MSC-17: "-fms-compatibility-version=17.0" + +// RUN: %clang -### -target i686-windows -fms-compatibility -fmsc-version=1600 -E - &1 | FileCheck %s -check-prefix CHECK-MSC-16 + +// CHECK-MSC-16-NOT: "-fmsc-version=1600" +// CHECK-MSC-16: "-fms-compatibility-version=16.0" + +// RUN: %clang -### -target i686-windows -fms-compatibility -fmsc-version=150020706 -E - &1 | FileCheck %s -check-prefix CHECK-MSC-15 + +// CHECK-MSC-15-NOT: "-fmsc-version=150020706" +// CHECK-MSC-15: "-fms-compatibility-version=15.0.20706" + Index: test/Headers/c11.c =================================================================== --- test/Headers/c11.c +++ test/Headers/c11.c @@ -2,7 +2,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c11 %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c11 -fmodules -fmodules-cache-path=%t %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c11 -ffreestanding %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c11 -triple i686-pc-win32 -fmsc-version=1700 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c11 -triple i686-pc-win32 -fms-compatibility-version=17.00 %s noreturn int f(); // expected-error 1+{{}} Index: test/Headers/ms-intrin.cpp =================================================================== --- test/Headers/ms-intrin.cpp +++ test/Headers/ms-intrin.cpp @@ -1,16 +1,16 @@ // RUN: %clang_cc1 -triple i386-pc-win32 -target-cpu pentium4 \ -// RUN: -fms-extensions -fms-compatibility -fmsc-version=1700 \ +// RUN: -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ // RUN: -ffreestanding -fsyntax-only -Werror \ // RUN: -isystem %S/Inputs/include %s // RUN: %clang_cc1 -triple x86_64-pc-win32 \ -// RUN: -fms-extensions -fms-compatibility -fmsc-version=1700 \ +// RUN: -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ // RUN: -ffreestanding -fsyntax-only -Werror \ // RUN: -isystem %S/Inputs/include %s // RUN: %clang_cc1 -triple thumbv7--windows \ -// RUN: -ffreestanding -fsyntax-only -fms-compatibility -fmsc-version=1700 \ -// RUN: -Werror \ +// RUN: -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -ffreestanding -fsyntax-only -Werror \ // RUN: -isystem %S/Inputs/include %s // Intrin.h needs size_t, but -ffreestanding prevents us from getting it from Index: test/Headers/ms-null-ms-header-vs-stddef.cpp =================================================================== --- test/Headers/ms-null-ms-header-vs-stddef.cpp +++ test/Headers/ms-null-ms-header-vs-stddef.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -triple i686-pc-win32 -fms-compatibility -fmsc-version=1700 %s +// RUN: %clang_cc1 -fsyntax-only -triple i686-pc-win32 -fms-compatibility -fms-compatibility-version=17.00 %s // RUN: %clang_cc1 -fsyntax-only -triple i386-mingw32 %s // Something in MSVC's headers (pulled in e.g. by ) defines __null Index: test/Misc/diag-format.c =================================================================== --- test/Misc/diag-format.c +++ test/Misc/diag-format.c @@ -3,10 +3,13 @@ // RUN: %clang -fsyntax-only -fdiagnostics-format=clang -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=DEFAULT // // RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 // RUN: %clang -fsyntax-only -fdiagnostics-format=msvc %s 2>&1 | FileCheck %s -check-prefix=MSVC // RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 // RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC // RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 // RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC // // RUN: %clang -fsyntax-only -fdiagnostics-format=vi %s 2>&1 | FileCheck %s -check-prefix=VI @@ -16,6 +19,7 @@ // RUN: %clang -fsyntax-only -fno-show-column %s 2>&1 | FileCheck %s -check-prefix=NO_COLUMN // // RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1300 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010-FALLBACK +// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010-FALLBACK // RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback %s 2>&1 | FileCheck %s -check-prefix=MSVC-FALLBACK @@ -30,12 +34,12 @@ #ifdef foo #endif bad // extension! -// DEFAULT: {{.*}}:32:8: warning: extra tokens at end of #endif directive [-Wextra-tokens] -// MSVC2010: {{.*}}(32,7) : warning: extra tokens at end of #endif directive [-Wextra-tokens] -// MSVC: {{.*}}(32,8) : warning: extra tokens at end of #endif directive [-Wextra-tokens] -// VI: {{.*}} +32:8: warning: extra tokens at end of #endif directive [-Wextra-tokens] -// MSVC_ORIG: {{.*}}(32) : warning: extra tokens at end of #endif directive [-Wextra-tokens] -// NO_COLUMN: {{.*}}:32: warning: extra tokens at end of #endif directive [-Wextra-tokens] -// MSVC2010-FALLBACK: {{.*}}(32,7) : error(clang): extra tokens at end of #endif directive -// MSVC-FALLBACK: {{.*}}(32,8) : error(clang): extra tokens at end of #endif directive +// DEFAULT: {{.*}}:36:8: warning: extra tokens at end of #endif directive [-Wextra-tokens] +// MSVC2010: {{.*}}(36,7) : warning: extra tokens at end of #endif directive [-Wextra-tokens] +// MSVC: {{.*}}(36,8) : warning: extra tokens at end of #endif directive [-Wextra-tokens] +// VI: {{.*}} +36:8: warning: extra tokens at end of #endif directive [-Wextra-tokens] +// MSVC_ORIG: {{.*}}(36) : warning: extra tokens at end of #endif directive [-Wextra-tokens] +// NO_COLUMN: {{.*}}:36: warning: extra tokens at end of #endif directive [-Wextra-tokens] +// MSVC2010-FALLBACK: {{.*}}(36,7) : error(clang): extra tokens at end of #endif directive +// MSVC-FALLBACK: {{.*}}(36,8) : error(clang): extra tokens at end of #endif directive int x; Index: test/Preprocessor/predefined-macros.c =================================================================== --- test/Preprocessor/predefined-macros.c +++ test/Preprocessor/predefined-macros.c @@ -1,7 +1,7 @@ // This test verifies that the correct macros are predefined. // // RUN: %clang_cc1 %s -E -dM -triple i686-pc-win32 -fms-extensions -fms-compatibility \ -// RUN: -fmsc-version=1300 -o - | FileCheck %s --check-prefix=CHECK-MS +// RUN: -fms-compatibility-version=13.00 -o - | FileCheck %s --check-prefix=CHECK-MS // CHECK-MS: #define _INTEGRAL_MAX_BITS 64 // CHECK-MS: #define _MSC_EXTENSIONS 1 // CHECK-MS: #define _MSC_VER 1300 @@ -14,7 +14,7 @@ // CHECK-MS-NOT: GXX // // RUN: %clang_cc1 %s -E -dM -triple x86_64-pc-win32 -fms-extensions -fms-compatibility \ -// RUN: -fmsc-version=1300 -o - | FileCheck %s --check-prefix=CHECK-MS64 +// RUN: -fms-compatibility-version=13.00 -o - | FileCheck %s --check-prefix=CHECK-MS64 // CHECK-MS64: #define _INTEGRAL_MAX_BITS 64 // CHECK-MS64: #define _MSC_EXTENSIONS 1 // CHECK-MS64: #define _MSC_VER 1300