Index: lib/Support/SourceMgr.cpp =================================================================== --- lib/Support/SourceMgr.cpp +++ lib/Support/SourceMgr.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/Locale.h" #include "llvm/Support/MemoryBuffer.h" @@ -35,6 +36,40 @@ using namespace llvm; +enum DiagnosticsFormats { Clang, MSVC, Vi }; + +enum MsvcVersions { + MSVC40 = 1000, + MSVC97 = 1100, + MSVC60 = 1200, + MSVC2002 = 1300, + MSVC2003 = 1310, + MSVC2005 = 1400, + MSVC2008 = 1500, + MSVC2010 = 1600, + MSVC2012 = 1700, + MSVC2013 = 1800, + MSVC2015 = 1900, + MSVC2017 = 1910 +}; + +static cl::opt DiagnosticsFormatOpt( + "diagnostics-format", + cl::desc( + "Change diagnostic formatting to match IDE and command line tools"), + cl::init("clang"), cl::Hidden); + +static cl::opt + MsvcVersionOpt("ms-compatibility-version", + cl::desc("Specify Microsoft Visual Studio compatibility " + "version for diagnostics formatting"), + cl::init("19.00"), cl::Hidden); + +static cl::opt ShowColumnOpt( + "show-column", + cl::desc("Enable or disable showing column number for diagnostics message"), + cl::init(true), cl::Hidden); + static const size_t TabStop = 8; unsigned SourceMgr::AddIncludeFile(const std::string &Filename, @@ -365,8 +400,62 @@ return c & 0x80; } +// Convert a std::string to upper case +static void toUp(std::string &S) { + for (size_t i = 0; i < S.length(); ++i) { + S[i] = ::toupper(S[i]); + } +} + +// Convert string to integer value. +static unsigned toInt(const std::string &S) { + if (S.empty()) + return 0; + for (size_t i = 0; i < S.length(); ++i) { + if (!::isdigit(S[i])) + return -1; + } + return ::atoi(S.c_str()); +} + +// Parse MSVC version option string, convert it to integer value. +static unsigned parseMsvcVersionOption() { + static unsigned MsvcVersion = UINT_MAX; + unsigned Major = 0, Minor = 0; + if (MsvcVersion != UINT_MAX) + return MsvcVersion; + size_t Pos = MsvcVersionOpt.find('.'); + if (Pos != std::string::npos) { + Major = toInt(MsvcVersionOpt.substr(0, Pos)); + Minor = toInt(MsvcVersionOpt.substr(Pos + 1)); + } else + Major = toInt(MsvcVersionOpt); + MsvcVersion = (Major * 100) + Minor; + return MsvcVersion; +} + +// Parse diagnostics format option string, convert it to integer. +static unsigned parseDiagnosticsFormatOption() { + static unsigned DiagsFormat = UINT_MAX; + if (DiagsFormat != UINT_MAX) + return DiagsFormat; + std::string DF(DiagnosticsFormatOpt); + toUp(DF); + if (DF == "CLANG") + DiagsFormat = DiagnosticsFormats::Clang; + else if (DF == "MSVC") + DiagsFormat = DiagnosticsFormats::MSVC; + else if (DF == "VI") + DiagsFormat = DiagnosticsFormats::Vi; + return DiagsFormat; +} + void SMDiagnostic::print(const char *ProgName, raw_ostream &S, bool ShowColors, bool ShowKindLabel) const { + + unsigned DiagnosticsFormat = parseDiagnosticsFormatOption(); + unsigned MsvcVersion = parseMsvcVersionOption(); + // Display colors only if OS supports colors. ShowColors &= S.has_colors(); @@ -382,12 +471,55 @@ else S << Filename; - if (LineNo != -1) { - S << ':' << LineNo; - if (ColumnNo != -1) - S << ':' << (ColumnNo+1); + if (DiagnosticsFormat > DiagnosticsFormats::Vi) { + if (LineNo != -1) { + S << ':' << LineNo; + if (ColumnNo != -1) + S << ':' << (ColumnNo + 1); + } + } else if (LineNo != -1) { + switch (DiagnosticsFormat) { + default: + case DiagnosticsFormats::Clang: + S << ':' << LineNo; + break; + case DiagnosticsFormats::MSVC: + S << '(' << LineNo; + break; + case DiagnosticsFormats::Vi: + S << " +" << LineNo; + break; + } + if (ShowColumnOpt && (ColumnNo != -1)) { + int ColumnNoOffs = 0; + if (DiagnosticsFormat == DiagnosticsFormats::MSVC) { + S << ','; + // Visual Studio 2010 or earlier expects column number to be off by + // one + if (MsvcVersion <= MsvcVersions::MSVC2010) + ColumnNoOffs = 1; + } else + S << ':'; + S << ((ColumnNo + 1) - ColumnNoOffs); + } + switch (DiagnosticsFormat) { + default: + case DiagnosticsFormats::Clang: + case DiagnosticsFormats::Vi: + S << ": "; + break; + case DiagnosticsFormats::MSVC: + // MSVC2013 and before print 'file(4) : error'. MSVC2015 gets rid of the + // space and prints 'file(4): error'. + if (MsvcVersion < MsvcVersions::MSVC2015) + S << ") : "; + else + S << "): "; + break; + } + } else { + S << ": "; } - S << ": "; } if (ShowKindLabel) {