summaryrefslogtreecommitdiffstats
path: root/lib/Basic/Diagnostic.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Basic/Diagnostic.cpp')
-rw-r--r--lib/Basic/Diagnostic.cpp51
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()));
+
}
}
OpenPOWER on IntegriCloud