зеркало из https://github.com/microsoft/clang.git
rewrite FormatDiagnostic to be less gross and a lot more efficient.
This also makes it illegal to have bare '%'s in diagnostics. If you want a % in a diagnostic, use %%. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59596 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
0293d540ba
Коммит
f4c8396577
|
@ -18,6 +18,10 @@
|
|||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
template <typename T> class SmallVectorImpl;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class DiagnosticClient;
|
||||
class SourceRange;
|
||||
|
@ -334,6 +338,10 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
/// FormatDiagnostic - Format this diagnostic into a string, substituting the
|
||||
/// formal arguments into the %0 slots. The result is appended onto the Str
|
||||
/// array.
|
||||
void FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -341,16 +349,13 @@ public:
|
|||
/// diag::kind enum. This actually returns a new instance of DiagnosticInfo
|
||||
/// which emits the diagnostics (through ProcessDiag) when it is destroyed.
|
||||
inline DiagnosticInfo Diagnostic::Report(FullSourceLoc Pos, unsigned DiagID) {
|
||||
DiagnosticInfo D(this, Pos, DiagID);
|
||||
return D;
|
||||
return DiagnosticInfo(this, Pos, DiagID);
|
||||
}
|
||||
|
||||
|
||||
/// DiagnosticClient - This is an abstract interface implemented by clients of
|
||||
/// the front-end, which formats and prints fully processed diagnostics.
|
||||
class DiagnosticClient {
|
||||
protected:
|
||||
std::string FormatDiagnostic(const DiagnosticInfo &Info);
|
||||
public:
|
||||
virtual ~DiagnosticClient();
|
||||
|
||||
|
|
|
@ -1392,11 +1392,11 @@ DIAG(warn_not_compound_assign, WARNING,
|
|||
DIAG(warn_printf_not_string_constant, WARNING,
|
||||
"format string is not a string literal (potentially insecure)")
|
||||
DIAG(warn_printf_write_back, WARNING,
|
||||
"use of '%n' in format string discouraged (potentially insecure)")
|
||||
"use of '%%n' in format string discouraged (potentially insecure)")
|
||||
DIAG(warn_printf_insufficient_data_args, WARNING,
|
||||
"more '%' conversions than data arguments")
|
||||
"more '%%' conversions than data arguments")
|
||||
DIAG(warn_printf_too_many_data_args, WARNING,
|
||||
"more data arguments than '%' conversions")
|
||||
"more data arguments than '%%' conversions")
|
||||
DIAG(warn_printf_invalid_conversion, WARNING,
|
||||
"invalid conversion '%0'")
|
||||
DIAG(warn_printf_missing_format_string, WARNING,
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/PathDiagnostic.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace clang;
|
||||
|
||||
PathDiagnostic::~PathDiagnostic() {
|
||||
|
@ -36,10 +36,13 @@ void PathDiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
|
|||
case Diagnostic::Fatal: LevelStr = "fatal error: "; break;
|
||||
}
|
||||
|
||||
std::string Msg = FormatDiagnostic(Info);
|
||||
llvm::SmallString<100> StrC;
|
||||
StrC += LevelStr;
|
||||
Info.FormatDiagnostic(StrC);
|
||||
|
||||
PathDiagnosticPiece *P =
|
||||
new PathDiagnosticPiece(Info.getLocation(), LevelStr+Msg);
|
||||
new PathDiagnosticPiece(Info.getLocation(),
|
||||
std::string(StrC.begin(), StrC.end()));
|
||||
|
||||
for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i)
|
||||
P->addRange(Info.getRange(i));
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include <cassert>
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cstring>
|
||||
|
@ -246,20 +246,41 @@ void Diagnostic::ProcessDiag(const DiagnosticInfo &Info) {
|
|||
|
||||
DiagnosticClient::~DiagnosticClient() {}
|
||||
|
||||
std::string DiagnosticClient::FormatDiagnostic(const DiagnosticInfo &Info) {
|
||||
std::string Msg = Info.getDiags()->getDescription(Info.getID());
|
||||
|
||||
/// FormatDiagnostic - Format this diagnostic into a string, substituting the
|
||||
/// formal arguments into the %0 slots. The result is appended onto the Str
|
||||
/// array.
|
||||
void DiagnosticInfo::
|
||||
FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
|
||||
const char *DiagStr = getDiags()->getDescription(getID());
|
||||
const char *DiagEnd = DiagStr+strlen(DiagStr);
|
||||
|
||||
// Replace all instances of %0 in Msg with 'Extra'. This is a pretty horrible
|
||||
// and inefficient way to do this, we could improve this a lot if we care.
|
||||
for (unsigned i = 0; i < Msg.size() - 1; ++i) {
|
||||
if (Msg[i] == '%' && isdigit(Msg[i + 1])) {
|
||||
unsigned StrNo = Msg[i + 1] - '0';
|
||||
Msg = std::string(Msg.begin(), Msg.begin() + i) +
|
||||
(Info.getArgKind(StrNo) == DiagnosticInfo::ak_std_string ?
|
||||
Info.getArgStdStr(StrNo) : std::string(Info.getArgCStr(StrNo))) +
|
||||
std::string(Msg.begin() + i + 2, Msg.end());
|
||||
while (DiagStr != DiagEnd) {
|
||||
if (DiagStr[0] != '%') {
|
||||
// Append non-%0 substrings to Str if we have one.
|
||||
const char *StrEnd = std::find(DiagStr, DiagEnd, '%');
|
||||
OutStr.append(DiagStr, StrEnd);
|
||||
DiagStr = StrEnd;
|
||||
} else if (DiagStr[1] == '%') {
|
||||
OutStr.push_back('%'); // %% -> %.
|
||||
DiagStr += 2;
|
||||
} else {
|
||||
assert(isdigit(DiagStr[1]) && "Must escape % with %%");
|
||||
unsigned StrNo = DiagStr[1] - '0';
|
||||
|
||||
switch (getArgKind(StrNo)) {
|
||||
case DiagnosticInfo::ak_std_string: {
|
||||
const std::string &S = getArgStdStr(StrNo);
|
||||
OutStr.append(S.begin(), S.end());
|
||||
break;
|
||||
}
|
||||
case DiagnosticInfo::ak_c_string: {
|
||||
const char *S = getArgCStr(StrNo);
|
||||
OutStr.append(S, S + strlen(S));
|
||||
break;
|
||||
}
|
||||
}
|
||||
DiagStr += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return Msg;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Driver/TextDiagnosticBuffer.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
using namespace clang;
|
||||
|
||||
/// HandleDiagnostic - Store the errors, warnings, and notes that are
|
||||
|
@ -19,19 +20,19 @@ using namespace clang;
|
|||
///
|
||||
void TextDiagnosticBuffer::HandleDiagnostic(Diagnostic::Level Level,
|
||||
const DiagnosticInfo &Info) {
|
||||
llvm::SmallString<100> StrC;
|
||||
Info.FormatDiagnostic(StrC);
|
||||
std::string Str(StrC.begin(), StrC.end());
|
||||
switch (Level) {
|
||||
default: assert(0 && "Diagnostic not handled during diagnostic buffering!");
|
||||
case Diagnostic::Note:
|
||||
Notes.push_back(std::make_pair(Info.getLocation().getLocation(),
|
||||
FormatDiagnostic(Info)));
|
||||
Notes.push_back(std::make_pair(Info.getLocation().getLocation(), Str));
|
||||
break;
|
||||
case Diagnostic::Warning:
|
||||
Warnings.push_back(std::make_pair(Info.getLocation().getLocation(),
|
||||
FormatDiagnostic(Info)));
|
||||
Warnings.push_back(std::make_pair(Info.getLocation().getLocation(), Str));
|
||||
break;
|
||||
case Diagnostic::Error:
|
||||
Errors.push_back(std::make_pair(Info.getLocation().getLocation(),
|
||||
FormatDiagnostic(Info)));
|
||||
Errors.push_back(std::make_pair(Info.getLocation().getLocation(), Str));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
using namespace clang;
|
||||
|
||||
void TextDiagnosticPrinter::
|
||||
|
@ -138,13 +139,15 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
|
|||
case Diagnostic::Warning: OS << "warning: "; break;
|
||||
case Diagnostic::Error: OS << "error: "; break;
|
||||
case Diagnostic::Fatal: OS << "fatal error: "; break;
|
||||
break;
|
||||
}
|
||||
|
||||
OS << FormatDiagnostic(Info) << "\n";
|
||||
llvm::SmallString<100> OutStr;
|
||||
Info.FormatDiagnostic(OutStr);
|
||||
OS.write(OutStr.begin(), OutStr.size());
|
||||
OS << '\n';
|
||||
|
||||
if (CaretDiagnostics && Pos.isValid() && ((LastLoc != Pos) ||
|
||||
Info.getNumRanges())) {
|
||||
if (CaretDiagnostics && Pos.isValid() &&
|
||||
((LastLoc != Pos) || Info.getNumRanges())) {
|
||||
// Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
|
||||
LastLoc = Pos;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче