diff options
Diffstat (limited to 'lib/Basic/Diagnostic.cpp')
-rw-r--r-- | lib/Basic/Diagnostic.cpp | 51 |
1 files changed, 37 insertions, 14 deletions
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp index 4a29997..fbc7313 100644 --- a/lib/Basic/Diagnostic.cpp +++ b/lib/Basic/Diagnostic.cpp @@ -25,6 +25,7 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" #include <vector> #include <map> #include <cstring> @@ -82,9 +83,14 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { #ifndef NDEBUG static bool IsFirst = true; if (IsFirst) { - for (unsigned i = 1; i != NumDiagEntries; ++i) + for (unsigned i = 1; i != NumDiagEntries; ++i) { + assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID && + "Diag ID conflict, the enums at the start of clang::diag (in " + "Diagnostic.h) probably need to be increased"); + assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] && "Improperly sorted diag info"); + } IsFirst = false; } #endif @@ -184,6 +190,8 @@ namespace clang { static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT, const char *Modifier, unsigned ML, const char *Argument, unsigned ArgLen, + const Diagnostic::ArgumentValue *PrevArgs, + unsigned NumPrevArgs, llvm::SmallVectorImpl<char> &Output, void *Cookie) { const char *Str = "<can't format argument>"; @@ -222,6 +230,8 @@ Diagnostic::~Diagnostic() { void Diagnostic::pushMappings() { + // Avoids undefined behavior when the stack has to resize. + DiagMappingsStack.reserve(DiagMappingsStack.size() + 1); DiagMappingsStack.push_back(DiagMappingsStack.back()); } @@ -679,6 +689,12 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { const char *DiagStr = getDiags()->getDescription(getID()); const char *DiagEnd = DiagStr+strlen(DiagStr); + /// FormattedArgs - Keep track of all of the arguments formatted by + /// ConvertArgToString and pass them into subsequent calls to + /// ConvertArgToString, allowing the implementation to avoid redundancies in + /// obvious cases. + llvm::SmallVector<Diagnostic::ArgumentValue, 8> FormattedArgs; + while (DiagStr != DiagEnd) { if (DiagStr[0] != '%') { // Append non-%0 substrings to Str if we have one. @@ -726,7 +742,9 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic"); unsigned ArgNo = *DiagStr++ - '0'; - switch (getArgKind(ArgNo)) { + Diagnostic::ArgumentKind Kind = getArgKind(ArgNo); + + switch (Kind) { // ---- STRINGS ---- case Diagnostic::ak_std_string: { const std::string &S = getArgStdStr(ArgNo); @@ -757,9 +775,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr); } else { assert(ModifierLen == 0 && "Unknown integer modifier"); - // FIXME: Optimize - std::string S = llvm::itostr(Val); - OutStr.append(S.begin(), S.end()); + llvm::raw_svector_ostream(OutStr) << Val; } break; } @@ -774,10 +790,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr); } else { assert(ModifierLen == 0 && "Unknown integer modifier"); - - // FIXME: Optimize - std::string S = llvm::utostr_32(Val); - OutStr.append(S.begin(), S.end()); + llvm::raw_svector_ostream(OutStr) << Val; } break; } @@ -793,9 +806,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { continue; } - OutStr.push_back('\''); - OutStr.append(II->getName(), II->getName() + II->getLength()); - OutStr.push_back('\''); + llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\''; break; } case Diagnostic::ak_qualtype: @@ -803,11 +814,23 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { case Diagnostic::ak_nameddecl: case Diagnostic::ak_nestednamespec: case Diagnostic::ak_declcontext: - getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo), + getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo), Modifier, ModifierLen, - Argument, ArgumentLen, OutStr); + Argument, ArgumentLen, + FormattedArgs.data(), FormattedArgs.size(), + OutStr); break; } + + // Remember this argument info for subsequent formatting operations. Turn + // std::strings into a null terminated string to make it be the same case as + // all the other ones. + if (Kind != Diagnostic::ak_std_string) + FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo))); + else + FormattedArgs.push_back(std::make_pair(Diagnostic::ak_c_string, + (intptr_t)getArgStdStr(ArgNo).c_str())); + } } |