From 9d45e77dca6d6442bb4d3e9d5df18f2ad5228892 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 20 Jun 2014 22:58:35 +0000 Subject: [PATCH] Driver: enhance MSC version compatibility The version information for Visual Studio is spread over multiple variables. The newer Windows SDK has started making use of some of the extended versioning variables that were previously undefined. Enhance our compatibility definitions for these cases. _MSC_VER is defined to be the Major * 100 + Minor. _MSC_FULL_VER is defined to be Major * 10000000 + Minor * 100000 + Build. And _MSC_BUILD is the build revision of the compiler. Extend the -fmsc-version option in a compatible manner. If the value is the previous form of MMmm, then we assume that the build number is 0. Otherwise, a specific build number may be passed by using the form MMmmbbbbb. Due to bitwidth limitations of the option, it is currently not possible to define a revision value. The version information can be passed as either the decimal encoded value (_MSC_FULL_VER or _MSC_VER) or as a dot-delimited value. The change to the TextDiagnostic is to deal with the updated encoding of the version information. llvm-svn: 211420 --- clang/lib/Basic/Targets.cpp | 8 +++- clang/lib/Frontend/CompilerInvocation.cpp | 53 ++++++++++++++++++++++- clang/lib/Frontend/TextDiagnostic.cpp | 2 +- clang/test/Driver/msc-version.c | 36 +++++++++++++++ 4 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 clang/test/Driver/msc-version.c diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index ae3e486d2788..4fdbc2447719 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -587,8 +587,12 @@ protected: if (Opts.POSIXThreads) Builder.defineMacro("_MT"); - if (Opts.MSCVersion != 0) - Builder.defineMacro("_MSC_VER", Twine(Opts.MSCVersion)); + if (Opts.MSCVersion != 0) { + Builder.defineMacro("_MSC_VER", Twine(Opts.MSCVersion / 100000)); + Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCVersion)); + // FIXME We cannot encode the revision information into 32-bits + Builder.defineMacro("_MSC_BUILD", Twine(1)); + } if (Opts.MicrosoftExt) { Builder.defineMacro("_MSC_EXTENSIONS"); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 4647179d6f42..9174e4fb704e 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -20,6 +20,7 @@ #include "clang/Serialization/ASTReader.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" @@ -1194,6 +1195,56 @@ static Visibility parseVisibility(Arg *arg, ArgList &args, return DefaultVisibility; } +static unsigned parseMSCVersion(ArgList &Args, DiagnosticsEngine &Diags) { + auto Arg = Args.getLastArg(OPT_fmsc_version); + if (!Arg) + return 0; + + // The MSC versioning scheme involves four versioning components: + // - Major + // - Minor + // - Build + // - Patch + // + // We accept either the old style (_MSC_VER) value, or a _MSC_FULL_VER value. + // Additionally, the value may be provided in the form of a more readable + // MM.mm.bbbbb.pp version. + // + // 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; + } + return (Version < 100000) ? Version * 100000 : Version; + } + + // parse the dot-delimited component version + unsigned VC[4] = {0}; + SmallVector Components; + + Value.split(Components, ".", llvm::array_lengthof(VC)); + for (unsigned CI = 0, + CE = std::min(Components.size(), llvm::array_lengthof(VC)); + CI < CE; ++CI) { + if (Components[CI].getAsInteger(10, VC[CI])) { + Diags.Report(diag::err_drv_invalid_value) + << Arg->getAsString(Args) << Value; + return 0; + } + } + + // FIXME we cannot encode the patch level + return VC[0] * 10000000 + VC[1] * 100000 + VC[2]; +} + static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, DiagnosticsEngine &Diags) { // FIXME: Cleanup per-file based stuff. @@ -1363,7 +1414,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, 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 = getLastArgIntValue(Args, OPT_fmsc_version, 0, Diags); + Opts.MSCVersion = 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); diff --git a/clang/lib/Frontend/TextDiagnostic.cpp b/clang/lib/Frontend/TextDiagnostic.cpp index 4c90d01918c2..7d39c74cea5a 100644 --- a/clang/lib/Frontend/TextDiagnostic.cpp +++ b/clang/lib/Frontend/TextDiagnostic.cpp @@ -813,7 +813,7 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, if (DiagOpts->getFormat() == DiagnosticOptions::Msvc) { OS << ','; // Visual Studio 2010 or earlier expects column number to be off by one - if (LangOpts.MSCVersion && LangOpts.MSCVersion < 1700) + if (LangOpts.MSCVersion && LangOpts.MSCVersion < 170000000) ColNo--; } else OS << ':'; diff --git a/clang/test/Driver/msc-version.c b/clang/test/Driver/msc-version.c new file mode 100644 index 000000000000..09115c9fe93f --- /dev/null +++ b/clang/test/Driver/msc-version.c @@ -0,0 +1,36 @@ +// RUN: %clang -target i686-windows -fms-compatibility -dM -E -