Index: include/clang/Basic/LangOptions.def =================================================================== --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -181,6 +181,7 @@ "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(MSCVersionEx, 32, 0, "Microsoft Visual C/C++ Extended 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 @@ -577,6 +577,8 @@ HelpText<"Enable full Microsoft Visual C++ compatibility">; def fmsc_version : Joined<["-"], "fmsc-version=">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Microsoft compiler version number to report in _MSC_VER (0 = don't define it (default))">; +def fmsc_version_ex : Joined<["-"], "fmsc-version-ex=">, 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 @@ -587,11 +587,13 @@ 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.MSCVersionEx) { + Builder.defineMacro("_MSC_VER", Twine(Opts.MSCVersionEx / 100000)); + Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCVersionEx)); // FIXME We cannot encode the revision information into 32-bits Builder.defineMacro("_MSC_BUILD", Twine(1)); + } else if (Opts.MSCVersion != 0) { + Builder.defineMacro("_MSC_VER", Twine(Opts.MSCVersion)); } if (Opts.MicrosoftExt) { Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -3723,14 +3723,29 @@ true)))) CmdArgs.push_back("-fms-compatibility"); - // -fmsc-version=1700 is default. + // -fmsc-version-ex=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"); - else - CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + msc_ver)); + IsWindowsMSVC) || Args.hasArg(options::OPT_fmsc_version) || + Args.hasArg(options::OPT_fmsc_version_ex)) { + if (Args.hasArg(options::OPT_fmsc_version) && + Args.hasArg(options::OPT_fmsc_version_ex)) + D.Diag(diag::err_drv_argument_not_allowed_with) + << Args.getArgString(options::OPT_fmsc_version) + << Args.getArgString(options::OPT_fmsc_version_ex); + + if (Args.hasArg(options::OPT_fmsc_version_ex)) { + StringRef MSCVerEx = Args.getLastArgValue(options::OPT_fmsc_version_ex); + if (MSCVerEx.empty()) + CmdArgs.push_back("-fmsc-version-ex=17.00"); + else + CmdArgs.push_back(Args.MakeArgString("-fmsc-version-ex=" + MSCVerEx)); + } else { + StringRef MSCVer = Args.getLastArgValue(options::OPT_fmsc_version); + if (MSCVer.empty()) + CmdArgs.push_back("-fmsc-version-ex=17.00"); + else + CmdArgs.push_back(Args.MakeArgString("-fmsc-version=" + MSCVer)); + } } 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_fmsc_version_ex); 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,8 @@ 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.MSCVersion = getLastArgIntValue(Args, OPT_fmsc_version, 0, Diags); + Opts.MSCVersionEx = 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.MSCVersion && LangOpts.MSCVersion < 1700) || + (LangOpts.MSCVersionEx && LangOpts.MSCVersionEx < 170000000)) ColNo--; } else OS << ':'; Index: test/Driver/msc-version.c =================================================================== --- test/Driver/msc-version.c +++ test/Driver/msc-version.c @@ -4,37 +4,25 @@ // CHECK-NO-MSC-VERSION: _MSC_FULL_VER 170000000 // CHECK-NO-MSC-VERSION: _MSC_VER 1700 -// RUN: %clang -target i686-windows -fms-compatibility -fmsc-version=1600 -dM -E - &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 -fmsc-version-ex=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 -fmsc-version-ex=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 -fmsc-version-ex=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 -fmsc-version-ex=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;