зеркало из https://github.com/microsoft/clang.git
This reworks some of the Diagnostic interfaces a bit to change how diagnostics
are formed. In particular, a diagnostic with all its strings and ranges is now packaged up and sent to DiagnosticClients as a DiagnosticInfo instead of as a ton of random stuff. This has the benefit of simplifying the interface, making it more extensible, and allowing us to do more checking for things like access past the end of the various arrays passed in. In addition to introducing DiagnosticInfo, this also substantially changes how Diagnostic::Report works. Instead of being passed in all of the info required to issue a diagnostic, Report now takes only the required info (a location and ID) and returns a fresh DiagnosticInfo *by value*. The caller is then free to stuff strings and ranges into the DiagnosticInfo with the << operator. When the dtor runs on the DiagnosticInfo object (which should happen at the end of the statement), the diagnostic is actually emitted with all of the accumulated information. This is a somewhat tricky dance, but it means that the accumulated DiagnosticInfo is allowed to keep pointers to other expression temporaries without those pointers getting invalidated. This is just the minimal change to get this stuff working, but this will allow us to eliminate the zillions of variant "Diag" methods scattered throughout (e.g.) sema. For example, instead of calling: Diag(BuiltinLoc, diag::err_overload_no_match, typeNames, SourceRange(BuiltinLoc, RParenLoc)); We will soon be able to just do: Diag(BuiltinLoc, diag::err_overload_no_match) << typeNames << SourceRange(BuiltinLoc, RParenLoc)); This scales better to support arbitrary types being passed in (not just strings) in a type-safe way. Go operator overloading?! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59502 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
46bbacac37
Коммит
0a14eee528
|
@ -132,9 +132,8 @@ namespace {
|
|||
if (!Rewrite.ReplaceStmt(Old, New) || SilenceRewriteMacroWarning)
|
||||
return;
|
||||
|
||||
SourceRange Range = Old->getSourceRange();
|
||||
Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag,
|
||||
0, 0, &Range, 1);
|
||||
Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
|
||||
<< Old->getSourceRange();
|
||||
}
|
||||
|
||||
void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen,
|
||||
|
|
|
@ -197,14 +197,8 @@ public:
|
|||
PathDiagnosticClient() {}
|
||||
virtual ~PathDiagnosticClient() {}
|
||||
|
||||
virtual void HandleDiagnostic(Diagnostic &Diags,
|
||||
Diagnostic::Level DiagLevel,
|
||||
FullSourceLoc Pos,
|
||||
diag::kind ID,
|
||||
const std::string **Strs,
|
||||
unsigned NumStrs,
|
||||
const SourceRange *Ranges,
|
||||
unsigned NumRanges);
|
||||
virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
|
||||
const DiagnosticInfo &Info);
|
||||
|
||||
virtual void HandlePathDiagnostic(const PathDiagnostic* D) = 0;
|
||||
};
|
||||
|
|
|
@ -303,26 +303,20 @@ public:
|
|||
|
||||
virtual ~DiagCollector() {}
|
||||
|
||||
virtual void HandleDiagnostic(Diagnostic &Diags,
|
||||
Diagnostic::Level DiagLevel,
|
||||
FullSourceLoc Pos,
|
||||
diag::kind ID,
|
||||
const std::string **Strs,
|
||||
unsigned NumStrs,
|
||||
const SourceRange *Ranges,
|
||||
unsigned NumRanges) {
|
||||
virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
|
||||
const DiagnosticInfo &Info) {
|
||||
|
||||
// FIXME: Use a map from diag::kind to BugType, instead of having just
|
||||
// one BugType.
|
||||
|
||||
Reports.push_back(DiagBugReport(Diags.getDescription(ID), D, Pos));
|
||||
const char *Desc = Info.getDiags()->getDescription(Info.getID());
|
||||
Reports.push_back(DiagBugReport(Desc, D, Info.getLocation()));
|
||||
DiagBugReport& R = Reports.back();
|
||||
|
||||
for ( ; NumRanges ; --NumRanges, ++Ranges)
|
||||
R.addRange(*Ranges);
|
||||
for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i)
|
||||
R.addRange(Info.getRange(i));
|
||||
|
||||
for ( ; NumStrs ; --NumStrs, ++Strs)
|
||||
R.addString(**Strs);
|
||||
for (unsigned i = 0, e = Info.getNumArgs(); i != e; ++i)
|
||||
R.addString(Info.getArgStr(i));
|
||||
}
|
||||
|
||||
// Iterators.
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace clang {
|
|||
class DiagnosticClient;
|
||||
class SourceRange;
|
||||
class SourceManager;
|
||||
class DiagnosticInfo;
|
||||
|
||||
// Import the diagnostic enums themselves.
|
||||
namespace diag {
|
||||
|
@ -150,7 +151,7 @@ public:
|
|||
|
||||
/// getDescription - Given a diagnostic ID, return a description of the
|
||||
/// issue.
|
||||
const char *getDescription(unsigned DiagID);
|
||||
const char *getDescription(unsigned DiagID) const;
|
||||
|
||||
/// isBuiltinNoteWarningOrExtension - Return true if the unmapped diagnostic
|
||||
/// level of the specified diagnostic ID is a Note, Warning, or Extension.
|
||||
|
@ -162,41 +163,146 @@ public:
|
|||
/// the DiagnosticClient.
|
||||
Level getDiagnosticLevel(unsigned DiagID) const;
|
||||
|
||||
/// Report - Issue the message to the client. DiagID is a member of the
|
||||
/// diag::kind enum.
|
||||
void Report(FullSourceLoc Pos, unsigned DiagID,
|
||||
const std::string **Strs = 0, unsigned NumStrs = 0,
|
||||
const SourceRange *Ranges = 0, unsigned NumRanges = 0) {
|
||||
Report(NULL, Pos, DiagID, Strs, NumStrs, Ranges, NumRanges);
|
||||
}
|
||||
|
||||
/// Report - Issue the message to the specified client.
|
||||
/// DiagID is a member of the diag::kind enum.
|
||||
void Report(DiagnosticClient* C, FullSourceLoc Pos, unsigned DiagID,
|
||||
const std::string **Strs = 0, unsigned NumStrs = 0,
|
||||
const SourceRange *Ranges = 0, unsigned NumRanges = 0);
|
||||
/// Report - Issue the message to the client. DiagID is a member of the
|
||||
/// diag::kind enum. This actually returns a new instance of DiagnosticInfo
|
||||
/// which emits the diagnostics (through ProcessDiag) when it is destroyed.
|
||||
inline DiagnosticInfo Report(FullSourceLoc Pos, unsigned DiagID);
|
||||
|
||||
private:
|
||||
// This is private state used by DiagnosticInfo. We put it here instead of
|
||||
// in DiagnosticInfo in order to keep DiagnosticInfo a small light-weight
|
||||
// object. This implementation choice means that we can only have one
|
||||
// diagnostic "in flight" at a time, but this seems to be a reasonable
|
||||
// tradeoff to keep these objects small. Assertions verify that only one
|
||||
// diagnostic is in flight at a time.
|
||||
friend class DiagnosticInfo;
|
||||
|
||||
/// DiagArguments - The values for the various substitution positions. It
|
||||
/// currently only support 10 arguments (%0-%9).
|
||||
const std::string *DiagArguments[10];
|
||||
/// DiagRanges - The list of ranges added to this diagnostic. It currently
|
||||
/// only support 10 ranges, could easily be extended if needed.
|
||||
const SourceRange *DiagRanges[10];
|
||||
|
||||
/// NumDiagArgs - This is set to -1 when no diag is in flight. Otherwise it
|
||||
/// is the number of entries in Arguments.
|
||||
signed char NumDiagArgs;
|
||||
/// NumRanges - This is the number of ranges in the DiagRanges array.
|
||||
unsigned char NumDiagRanges;
|
||||
|
||||
/// ProcessDiag - This is the method used to report a diagnostic that is
|
||||
/// finally fully formed.
|
||||
void ProcessDiag(const DiagnosticInfo &Info);
|
||||
};
|
||||
|
||||
/// DiagnosticInfo - This is a little helper class used to produce diagnostics.
|
||||
/// This is constructed with an ID and location, and then has some number of
|
||||
/// arguments (for %0 substitution) and SourceRanges added to it with the
|
||||
/// overloaded operator<<. Once it is destroyed, it emits the diagnostic with
|
||||
/// the accumulated information.
|
||||
///
|
||||
/// Note that many of these will be created as temporary objects (many call
|
||||
/// sites), so we want them to be small to reduce stack space usage etc. For
|
||||
/// this reason, we stick state in the Diagnostic class, see the comment there
|
||||
/// for more info.
|
||||
class DiagnosticInfo {
|
||||
Diagnostic *DiagObj;
|
||||
FullSourceLoc Loc;
|
||||
unsigned DiagID;
|
||||
void operator=(const DiagnosticInfo&); // DO NOT IMPLEMENT
|
||||
public:
|
||||
DiagnosticInfo(Diagnostic *diagObj, FullSourceLoc loc, unsigned diagID) :
|
||||
DiagObj(diagObj), Loc(loc), DiagID(diagID) {
|
||||
assert(DiagObj->NumDiagArgs == -1 &&
|
||||
"Multiple diagnostics in flight at once!");
|
||||
DiagObj->NumDiagArgs = DiagObj->NumDiagRanges = 0;
|
||||
}
|
||||
|
||||
/// Copy constructor. When copied, this "takes" the diagnostic info from the
|
||||
/// input and neuters it.
|
||||
DiagnosticInfo(DiagnosticInfo &D) {
|
||||
DiagObj = D.DiagObj;
|
||||
Loc = D.Loc;
|
||||
DiagID = D.DiagID;
|
||||
D.DiagObj = 0;
|
||||
}
|
||||
|
||||
/// Destructor - The dtor emits the diagnostic.
|
||||
~DiagnosticInfo() {
|
||||
// If DiagObj is null, then its soul was stolen by the copy ctor.
|
||||
if (!DiagObj) return;
|
||||
|
||||
DiagObj->ProcessDiag(*this);
|
||||
|
||||
// This diagnostic is no longer in flight.
|
||||
DiagObj->NumDiagArgs = -1;
|
||||
}
|
||||
|
||||
const Diagnostic *getDiags() const { return DiagObj; }
|
||||
unsigned getID() const { return DiagID; }
|
||||
const FullSourceLoc &getLocation() const { return Loc; }
|
||||
|
||||
unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
|
||||
|
||||
/// getArgStr - Return the provided argument string specified by Idx.
|
||||
const std::string &getArgStr(unsigned Idx) const {
|
||||
assert((signed char)Idx < DiagObj->NumDiagArgs &&
|
||||
"Argument out of range!");
|
||||
return *DiagObj->DiagArguments[Idx];
|
||||
}
|
||||
|
||||
/// getNumRanges - Return the number of source ranges associated with this
|
||||
/// diagnostic.
|
||||
unsigned getNumRanges() const {
|
||||
return DiagObj->NumDiagRanges;
|
||||
}
|
||||
|
||||
const SourceRange &getRange(unsigned Idx) const {
|
||||
assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
|
||||
return *DiagObj->DiagRanges[Idx];
|
||||
}
|
||||
|
||||
DiagnosticInfo &operator<<(const std::string &S) {
|
||||
assert((unsigned)DiagObj->NumDiagArgs <
|
||||
sizeof(DiagObj->DiagArguments)/sizeof(DiagObj->DiagArguments[0]) &&
|
||||
"Too many arguments to diagnostic!");
|
||||
DiagObj->DiagArguments[DiagObj->NumDiagArgs++] = &S;
|
||||
return *this;
|
||||
}
|
||||
|
||||
DiagnosticInfo &operator<<(const SourceRange &R) {
|
||||
assert((unsigned)DiagObj->NumDiagArgs <
|
||||
sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
|
||||
"Too many arguments to diagnostic!");
|
||||
DiagObj->DiagRanges[DiagObj->NumDiagRanges++] = &R;
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/// Report - Issue the message to the client. DiagID is a member of the
|
||||
/// 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;
|
||||
}
|
||||
|
||||
|
||||
/// 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(Diagnostic &Diags, Diagnostic::Level Level,
|
||||
diag::kind ID,
|
||||
const std::string **Strs, unsigned NumStrs);
|
||||
std::string FormatDiagnostic(const DiagnosticInfo &Info);
|
||||
public:
|
||||
virtual ~DiagnosticClient();
|
||||
|
||||
/// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
|
||||
/// capturing it to a log as needed.
|
||||
virtual void HandleDiagnostic(Diagnostic &Diags,
|
||||
Diagnostic::Level DiagLevel,
|
||||
FullSourceLoc Pos,
|
||||
diag::kind ID,
|
||||
const std::string **Strs,
|
||||
unsigned NumStrs,
|
||||
const SourceRange *Ranges,
|
||||
unsigned NumRanges) = 0;
|
||||
virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
|
||||
const DiagnosticInfo &Info) = 0;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -39,14 +39,8 @@ public:
|
|||
const_iterator note_begin() const { return Notes.begin(); }
|
||||
const_iterator note_end() const { return Notes.end(); }
|
||||
|
||||
virtual void HandleDiagnostic(Diagnostic &Diags,
|
||||
Diagnostic::Level DiagLevel,
|
||||
FullSourceLoc Pos,
|
||||
diag::kind ID,
|
||||
const std::string **Strs,
|
||||
unsigned NumStrs,
|
||||
const SourceRange *Ranges,
|
||||
unsigned NumRanges);
|
||||
virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
|
||||
const DiagnosticInfo &Info);
|
||||
};
|
||||
|
||||
} // end namspace clang
|
||||
|
|
|
@ -36,19 +36,13 @@ public:
|
|||
void PrintIncludeStack(FullSourceLoc Pos);
|
||||
|
||||
void HighlightRange(const SourceRange &R,
|
||||
SourceManager& SrcMgr,
|
||||
const SourceManager& SrcMgr,
|
||||
unsigned LineNo, unsigned FileID,
|
||||
std::string &CaretLine,
|
||||
const std::string &SourceLine);
|
||||
|
||||
virtual void HandleDiagnostic(Diagnostic &Diags,
|
||||
Diagnostic::Level DiagLevel,
|
||||
FullSourceLoc Pos,
|
||||
diag::kind ID,
|
||||
const std::string **Strs,
|
||||
unsigned NumStrs,
|
||||
const SourceRange *Ranges,
|
||||
unsigned NumRanges);
|
||||
virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
|
||||
const DiagnosticInfo &Info);
|
||||
};
|
||||
|
||||
} // end namspace clang
|
||||
|
|
|
@ -773,21 +773,26 @@ void BugReporter::EmitWarning(BugReport& R) {
|
|||
|
||||
D->push_back(piece);
|
||||
PD->HandlePathDiagnostic(D.take());
|
||||
return;
|
||||
}
|
||||
else {
|
||||
std::ostringstream os;
|
||||
std::string str;
|
||||
|
||||
if (D->empty())
|
||||
os << R.getDescription();
|
||||
str = R.getDescription();
|
||||
else
|
||||
os << D->back()->getString();
|
||||
|
||||
str = D->back()->getString();
|
||||
|
||||
Diagnostic& Diag = getDiagnostic();
|
||||
unsigned ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning,
|
||||
os.str().c_str());
|
||||
unsigned ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, str.c_str());
|
||||
|
||||
Diag.Report(L, ErrorDiag, NULL, 0, Beg, End - Beg);
|
||||
switch (End-Beg) {
|
||||
default: assert(0 && "Don't handle this many ranges yet!");
|
||||
case 0: Diag.Report(L, ErrorDiag); break;
|
||||
case 1: Diag.Report(L, ErrorDiag) << Beg[0]; break;
|
||||
case 2: Diag.Report(L, ErrorDiag) << Beg[0] << Beg[1]; break;
|
||||
case 3: Diag.Report(L, ErrorDiag) << Beg[0] << Beg[1] << Beg[2]; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -807,9 +812,17 @@ void BugReporter::EmitBasicReport(const char* name, const char* category,
|
|||
|
||||
DiagnosticClient *OldClient = Diag.getClient();
|
||||
Diag.setClient(&C);
|
||||
Diag.Report(getContext().getFullLoc(Loc),
|
||||
Diag.getCustomDiagID(Diagnostic::Warning, str),
|
||||
0, 0, RBeg, NumRanges);
|
||||
FullSourceLoc L = getContext().getFullLoc(Loc);
|
||||
unsigned DiagID = Diag.getCustomDiagID(Diagnostic::Warning, str);
|
||||
|
||||
switch (NumRanges) {
|
||||
default: assert(0 && "Don't handle this many ranges yet!");
|
||||
case 0: Diag.Report(L, DiagID); break;
|
||||
case 1: Diag.Report(L, DiagID) << RBeg[0]; break;
|
||||
case 2: Diag.Report(L, DiagID) << RBeg[0] << RBeg[1]; break;
|
||||
case 3: Diag.Report(L, DiagID) << RBeg[0] << RBeg[1] << RBeg[2]; break;
|
||||
}
|
||||
|
||||
Diag.setClient(OldClient);
|
||||
|
||||
for (DiagCollector::iterator I = C.begin(), E = C.end(); I != E; ++I)
|
||||
|
|
|
@ -20,14 +20,8 @@ PathDiagnostic::~PathDiagnostic() {
|
|||
for (iterator I = begin(), E = end(); I != E; ++I) delete &*I;
|
||||
}
|
||||
|
||||
void PathDiagnosticClient::HandleDiagnostic(Diagnostic &Diags,
|
||||
Diagnostic::Level DiagLevel,
|
||||
FullSourceLoc Pos,
|
||||
diag::kind ID,
|
||||
const std::string **Strs,
|
||||
unsigned NumStrs,
|
||||
const SourceRange *Ranges,
|
||||
unsigned NumRanges) {
|
||||
void PathDiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
|
||||
const DiagnosticInfo &Info) {
|
||||
|
||||
// Create a PathDiagnostic with a single piece.
|
||||
|
||||
|
@ -42,16 +36,13 @@ void PathDiagnosticClient::HandleDiagnostic(Diagnostic &Diags,
|
|||
case Diagnostic::Fatal: LevelStr = "fatal error: "; break;
|
||||
}
|
||||
|
||||
std::string Msg = FormatDiagnostic(Diags, DiagLevel, ID, Strs, NumStrs);
|
||||
std::string Msg = FormatDiagnostic(Info);
|
||||
|
||||
PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, LevelStr+Msg);
|
||||
|
||||
while (NumRanges) {
|
||||
P->addRange(*Ranges);
|
||||
--NumRanges;
|
||||
++Ranges;
|
||||
}
|
||||
PathDiagnosticPiece *P =
|
||||
new PathDiagnosticPiece(Info.getLocation(), LevelStr+Msg);
|
||||
|
||||
for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i)
|
||||
P->addRange(Info.getRange(i));
|
||||
D->push_front(P);
|
||||
|
||||
HandlePathDiagnostic(D);
|
||||
|
|
|
@ -127,6 +127,7 @@ Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
|
|||
NumDiagnostics = 0;
|
||||
NumErrors = 0;
|
||||
CustomDiagInfo = 0;
|
||||
NumDiagArgs = -1;
|
||||
}
|
||||
|
||||
Diagnostic::~Diagnostic() {
|
||||
|
@ -154,7 +155,7 @@ bool Diagnostic::isBuiltinNoteWarningOrExtension(unsigned DiagID) {
|
|||
|
||||
/// getDescription - Given a diagnostic ID, return a description of the
|
||||
/// issue.
|
||||
const char *Diagnostic::getDescription(unsigned DiagID) {
|
||||
const char *Diagnostic::getDescription(unsigned DiagID) const {
|
||||
if (DiagID < diag::NUM_BUILTIN_DIAGNOSTICS)
|
||||
return DiagnosticText[DiagID];
|
||||
else
|
||||
|
@ -210,66 +211,51 @@ Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const {
|
|||
}
|
||||
}
|
||||
|
||||
/// Report - Issue the message to the client.
|
||||
/// DiagID is a member of the diag::kind enum.
|
||||
void Diagnostic::Report(DiagnosticClient* C,
|
||||
FullSourceLoc Loc, unsigned DiagID,
|
||||
const std::string **Strs, unsigned NumStrs,
|
||||
const SourceRange *Ranges, unsigned NumRanges) {
|
||||
|
||||
/// ProcessDiag - This is the method used to report a diagnostic that is
|
||||
/// finally fully formed.
|
||||
void Diagnostic::ProcessDiag(const DiagnosticInfo &Info) {
|
||||
// Figure out the diagnostic level of this message.
|
||||
Diagnostic::Level DiagLevel = getDiagnosticLevel(DiagID);
|
||||
Diagnostic::Level DiagLevel = getDiagnosticLevel(Info.getID());
|
||||
|
||||
// If the client doesn't care about this message, don't issue it.
|
||||
if (DiagLevel == Diagnostic::Ignored)
|
||||
return;
|
||||
|
||||
// Set the diagnostic client if it isn't set already.
|
||||
if (!C) C = Client;
|
||||
|
||||
// If this is not an error and we are in a system header, ignore it. We
|
||||
// have to check on the original DiagID here, because we also want to
|
||||
// have to check on the original Diag ID here, because we also want to
|
||||
// ignore extensions and warnings in -Werror and -pedantic-errors modes,
|
||||
// which *map* warnings/extensions to errors.
|
||||
if (SuppressSystemWarnings &&
|
||||
DiagID < diag::NUM_BUILTIN_DIAGNOSTICS &&
|
||||
getBuiltinDiagClass(DiagID) != ERROR &&
|
||||
Loc.isValid() && Loc.getPhysicalLoc().isInSystemHeader())
|
||||
Info.getID() < diag::NUM_BUILTIN_DIAGNOSTICS &&
|
||||
getBuiltinDiagClass(Info.getID()) != ERROR &&
|
||||
Info.getLocation().isValid() &&
|
||||
Info.getLocation().getPhysicalLoc().isInSystemHeader())
|
||||
return;
|
||||
|
||||
if (DiagLevel >= Diagnostic::Error) {
|
||||
ErrorOccurred = true;
|
||||
|
||||
if (C != 0 && C == Client)
|
||||
++NumErrors;
|
||||
++NumErrors;
|
||||
}
|
||||
|
||||
// Finally, report it.
|
||||
|
||||
if (C != 0)
|
||||
C->HandleDiagnostic(*this, DiagLevel, Loc, (diag::kind)DiagID,
|
||||
Strs, NumStrs, Ranges, NumRanges);
|
||||
|
||||
if (C != 0 && C == Client)
|
||||
++NumDiagnostics;
|
||||
Client->HandleDiagnostic(DiagLevel, Info);
|
||||
++NumDiagnostics;
|
||||
}
|
||||
|
||||
|
||||
DiagnosticClient::~DiagnosticClient() {}
|
||||
|
||||
std::string DiagnosticClient::FormatDiagnostic(Diagnostic &Diags,
|
||||
Diagnostic::Level Level,
|
||||
diag::kind ID,
|
||||
const std::string **Strs,
|
||||
unsigned NumStrs) {
|
||||
std::string Msg = Diags.getDescription(ID);
|
||||
std::string DiagnosticClient::FormatDiagnostic(const DiagnosticInfo &Info) {
|
||||
std::string Msg = Info.getDiags()->getDescription(Info.getID());
|
||||
|
||||
// Replace all instances of %0 in Msg with 'Extra'.
|
||||
// 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) +
|
||||
(StrNo < NumStrs ? *Strs[StrNo] : "<<<INTERNAL ERROR>>>") +
|
||||
Info.getArgStr(StrNo) +
|
||||
std::string(Msg.begin() + i + 2, Msg.end());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -303,10 +303,9 @@ void CodeGenFunction::EmitObjCPropertySet(const ObjCPropertyRefExpr *E,
|
|||
S = Setter->getSelector();
|
||||
} else {
|
||||
// FIXME: This should be diagnosed by sema.
|
||||
SourceRange Range = E->getSourceRange();
|
||||
CGM.getDiags().Report(getContext().getFullLoc(E->getLocStart()),
|
||||
diag::err_typecheck_assign_const, 0, 0,
|
||||
&Range, 1);
|
||||
diag::err_typecheck_assign_const)
|
||||
<< E->getSourceRange();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -106,11 +106,9 @@ void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type,
|
|||
return;
|
||||
unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Error,
|
||||
"cannot codegen this %0 yet");
|
||||
SourceRange Range = S->getSourceRange();
|
||||
std::string Msg = Type;
|
||||
const std::string *Strs[] = { &Msg };
|
||||
getDiags().Report(Context.getFullLoc(S->getLocStart()), DiagID,
|
||||
Strs, 1, &Range, 1);
|
||||
getDiags().Report(Context.getFullLoc(S->getLocStart()), DiagID)
|
||||
<< Msg << S->getSourceRange();
|
||||
}
|
||||
|
||||
/// ErrorUnsupported - Print out an error that codegen doesn't support the
|
||||
|
@ -122,8 +120,7 @@ void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type,
|
|||
unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Error,
|
||||
"cannot codegen this %0 yet");
|
||||
std::string Msg = Type;
|
||||
const std::string *Strs[] = { &Msg };
|
||||
getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID, Strs, 1);
|
||||
getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg;
|
||||
}
|
||||
|
||||
/// setGlobalVisibility - Set the visibility for the given LLVM
|
||||
|
|
|
@ -17,30 +17,21 @@ using namespace clang;
|
|||
/// HandleDiagnostic - Store the errors, warnings, and notes that are
|
||||
/// reported.
|
||||
///
|
||||
void TextDiagnosticBuffer::HandleDiagnostic(Diagnostic &Diags,
|
||||
Diagnostic::Level Level,
|
||||
FullSourceLoc Pos,
|
||||
diag::kind ID,
|
||||
const std::string **Strs,
|
||||
unsigned NumStrs,
|
||||
const SourceRange *,
|
||||
unsigned) {
|
||||
void TextDiagnosticBuffer::HandleDiagnostic(Diagnostic::Level Level,
|
||||
const DiagnosticInfo &Info) {
|
||||
switch (Level) {
|
||||
default: assert(0 && "Diagnostic not handled during diagnostic buffering!");
|
||||
case Diagnostic::Note:
|
||||
Notes.push_back(std::make_pair(Pos.getLocation(),
|
||||
FormatDiagnostic(Diags, Level, ID,
|
||||
Strs, NumStrs)));
|
||||
Notes.push_back(std::make_pair(Info.getLocation().getLocation(),
|
||||
FormatDiagnostic(Info)));
|
||||
break;
|
||||
case Diagnostic::Warning:
|
||||
Warnings.push_back(std::make_pair(Pos.getLocation(),
|
||||
FormatDiagnostic(Diags, Level, ID,
|
||||
Strs, NumStrs)));
|
||||
Warnings.push_back(std::make_pair(Info.getLocation().getLocation(),
|
||||
FormatDiagnostic(Info)));
|
||||
break;
|
||||
case Diagnostic::Error:
|
||||
Errors.push_back(std::make_pair(Pos.getLocation(),
|
||||
FormatDiagnostic(Diags, Level, ID,
|
||||
Strs, NumStrs)));
|
||||
Errors.push_back(std::make_pair(Info.getLocation().getLocation(),
|
||||
FormatDiagnostic(Info)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ PrintIncludeStack(FullSourceLoc Pos) {
|
|||
/// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s)
|
||||
/// any characters in LineNo that intersect the SourceRange.
|
||||
void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,
|
||||
SourceManager& SourceMgr,
|
||||
const SourceManager& SourceMgr,
|
||||
unsigned LineNo, unsigned FileID,
|
||||
std::string &CaretLine,
|
||||
const std::string &SourceLine) {
|
||||
|
@ -92,17 +92,12 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,
|
|||
CaretLine[i] = '~';
|
||||
}
|
||||
|
||||
void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic &Diags,
|
||||
Diagnostic::Level Level,
|
||||
FullSourceLoc Pos,
|
||||
diag::kind ID,
|
||||
const std::string **Strs,
|
||||
unsigned NumStrs,
|
||||
const SourceRange *Ranges,
|
||||
unsigned NumRanges) {
|
||||
void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
|
||||
const DiagnosticInfo &Info) {
|
||||
unsigned LineNo = 0, ColNo = 0;
|
||||
unsigned FileID = 0;
|
||||
const char *LineStart = 0, *LineEnd = 0;
|
||||
const FullSourceLoc &Pos = Info.getLocation();
|
||||
|
||||
if (Pos.isValid()) {
|
||||
FullSourceLoc LPos = Pos.getLogicalLoc();
|
||||
|
@ -146,9 +141,10 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic &Diags,
|
|||
break;
|
||||
}
|
||||
|
||||
OS << FormatDiagnostic(Diags, Level, ID, Strs, NumStrs) << "\n";
|
||||
OS << FormatDiagnostic(Info) << "\n";
|
||||
|
||||
if (CaretDiagnostics && Pos.isValid() && ((LastLoc != Pos) || Ranges)) {
|
||||
if (CaretDiagnostics && Pos.isValid() && ((LastLoc != Pos) ||
|
||||
Info.getNumRanges())) {
|
||||
// Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
|
||||
LastLoc = Pos;
|
||||
|
||||
|
@ -160,8 +156,8 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic &Diags,
|
|||
std::string CaretLine(LineEnd-LineStart, ' ');
|
||||
|
||||
// Highlight all of the characters covered by Ranges with ~ characters.
|
||||
for (unsigned i = 0; i != NumRanges; ++i)
|
||||
HighlightRange(Ranges[i], Pos.getManager(), LineNo, FileID,
|
||||
for (unsigned i = 0; i != Info.getNumRanges(); ++i)
|
||||
HighlightRange(Info.getRange(i), Pos.getManager(), LineNo, FileID,
|
||||
CaretLine, SourceLine);
|
||||
|
||||
// Next, insert the caret itself.
|
||||
|
|
|
@ -124,28 +124,24 @@ void Preprocessor::Diag(SourceLocation Loc, unsigned DiagID) {
|
|||
|
||||
void Preprocessor::Diag(SourceLocation Loc, unsigned DiagID,
|
||||
const std::string &Msg) {
|
||||
const std::string *Strs[] = { &Msg };
|
||||
Diags.Report(getFullLoc(Loc), DiagID, Strs, 1);
|
||||
Diags.Report(getFullLoc(Loc), DiagID) << Msg;
|
||||
}
|
||||
|
||||
void Preprocessor::Diag(SourceLocation Loc, unsigned DiagID,
|
||||
const std::string &Msg,
|
||||
const SourceRange &R1, const SourceRange &R2) {
|
||||
const std::string *Strs[] = { &Msg };
|
||||
SourceRange R[] = {R1, R2};
|
||||
Diags.Report(getFullLoc(Loc), DiagID, Strs, 1, R, 2);
|
||||
Diags.Report(getFullLoc(Loc), DiagID) << Msg << R1 << R2;
|
||||
}
|
||||
|
||||
|
||||
void Preprocessor::Diag(SourceLocation Loc, unsigned DiagID,
|
||||
const SourceRange &R) {
|
||||
Diags.Report(getFullLoc(Loc), DiagID, 0, 0, &R, 1);
|
||||
Diags.Report(getFullLoc(Loc), DiagID) << R;
|
||||
}
|
||||
|
||||
void Preprocessor::Diag(SourceLocation Loc, unsigned DiagID,
|
||||
const SourceRange &R1, const SourceRange &R2) {
|
||||
SourceRange R[] = {R1, R2};
|
||||
Diags.Report(getFullLoc(Loc), DiagID, 0, 0, R, 2);
|
||||
Diags.Report(getFullLoc(Loc), DiagID) << R1 << R2;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -311,7 +311,6 @@ void DeclSpec::Diag(Diagnostic &D, SourceLocation Loc, SourceManager& SrcMgr,
|
|||
}
|
||||
|
||||
void DeclSpec::Diag(Diagnostic &D, SourceLocation Loc, SourceManager& SrcMgr,
|
||||
unsigned DiagID, const std::string &Info) {
|
||||
const std::string *Strs[] = { &Info };
|
||||
D.Report(FullSourceLoc(Loc,SrcMgr), DiagID, Strs, 1);
|
||||
unsigned DiagID, const std::string &Info) {
|
||||
D.Report(FullSourceLoc(Loc,SrcMgr), DiagID) << Info;
|
||||
}
|
||||
|
|
|
@ -43,21 +43,18 @@ Action::~Action() {}
|
|||
|
||||
bool Parser::Diag(SourceLocation Loc, unsigned DiagID,
|
||||
const std::string &Msg) {
|
||||
const std::string *Strs[] = { &Msg };
|
||||
Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID, Strs, 1);
|
||||
Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID) << Msg;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Parser::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
|
||||
const SourceRange& Range) {
|
||||
const std::string *Strs[] = { &Msg };
|
||||
Diags.Report(PP.getFullLoc(Loc), DiagID, Strs, 1, &Range,1);
|
||||
Diags.Report(PP.getFullLoc(Loc), DiagID) << Msg << Range;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Parser::Diag(SourceLocation Loc, unsigned DiagID, const SourceRange &R) {
|
||||
Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID, 0, 0,
|
||||
&R, 1);
|
||||
Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID) << R;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,11 +18,9 @@
|
|||
#include "clang/AST/Expr.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name)
|
||||
{
|
||||
static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name) {
|
||||
if (C.getLangOptions().CPlusPlus)
|
||||
return CXXRecordDecl::Create(C, TagDecl::TK_struct,
|
||||
C.getTranslationUnitDecl(),
|
||||
|
@ -176,66 +174,58 @@ bool Sema::Diag(SourceLocation Loc, unsigned DiagID) {
|
|||
}
|
||||
|
||||
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg) {
|
||||
const std::string *Strs[] = { &Msg };
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, Strs, 1);
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << Msg;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
|
||||
const std::string &Msg2) {
|
||||
const std::string *MsgArr[] = { &Msg1, &Msg2 };
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 2);
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << Msg1 << Msg2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const SourceRange& Range) {
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, 0, 0, &Range,1);
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << Range;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
|
||||
const SourceRange& Range) {
|
||||
const std::string *Strs[] = { &Msg };
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, Strs, 1, &Range,1);
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << Msg << Range;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
|
||||
const std::string &Msg2, const SourceRange& Range) {
|
||||
const std::string *MsgArr[] = { &Msg1, &Msg2 };
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 2, &Range, 1);
|
||||
const std::string &Msg2, const SourceRange &R) {
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << Msg1 << Msg2 << R;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
|
||||
const std::string &Msg2, const std::string &Msg3,
|
||||
const SourceRange &R1) {
|
||||
const std::string *MsgArr[] = { &Msg1, &Msg2, &Msg3 };
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 3, &R1, 1);
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID)
|
||||
<< Msg1 << Msg2 << Msg3 << R1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sema::Diag(SourceLocation Loc, unsigned DiagID,
|
||||
const SourceRange& R1, const SourceRange& R2) {
|
||||
SourceRange RangeArr[] = { R1, R2 };
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, 0, 0, RangeArr, 2);
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << R1 << R2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
|
||||
const SourceRange& R1, const SourceRange& R2) {
|
||||
SourceRange RangeArr[] = { R1, R2 };
|
||||
const std::string *Strs[] = { &Msg };
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, Strs, 1, RangeArr, 2);
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << Msg << R1 << R2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sema::Diag(SourceLocation Range, unsigned DiagID, const std::string &Msg1,
|
||||
const std::string &Msg2, const SourceRange& R1,
|
||||
const SourceRange& R2) {
|
||||
const std::string *MsgArr[] = { &Msg1, &Msg2 };
|
||||
SourceRange RangeArr[] = { R1, R2 };
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Range),DiagID, MsgArr,2,RangeArr, 2);
|
||||
PP.getDiagnostics().Report(PP.getFullLoc(Range),DiagID)
|
||||
<< Msg1 << Msg2 << R1 << R2;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче