summaryrefslogtreecommitdiffstats
path: root/clang/include
diff options
context:
space:
mode:
Diffstat (limited to 'clang/include')
-rw-r--r--clang/include/clang/Analysis/PathSensitive/BugReporter.h10
-rw-r--r--clang/include/clang/Basic/Diagnostic.h266
-rw-r--r--clang/include/clang/Lex/Lexer.h4
-rw-r--r--clang/include/clang/Lex/Preprocessor.h4
-rw-r--r--clang/include/clang/Parse/Action.h4
-rw-r--r--clang/include/clang/Parse/Parser.h6
6 files changed, 161 insertions, 133 deletions
diff --git a/clang/include/clang/Analysis/PathSensitive/BugReporter.h b/clang/include/clang/Analysis/PathSensitive/BugReporter.h
index d9969efb9cb..ef8321f2142 100644
--- a/clang/include/clang/Analysis/PathSensitive/BugReporter.h
+++ b/clang/include/clang/Analysis/PathSensitive/BugReporter.h
@@ -318,19 +318,19 @@ public:
for (unsigned i = 0, e = Info.getNumArgs(); i != e; ++i) {
switch (Info.getArgKind(i)) {
- case DiagnosticInfo::ak_std_string:
+ case Diagnostic::ak_std_string:
R.addString(Info.getArgStdStr(i));
break;
- case DiagnosticInfo::ak_c_string:
+ case Diagnostic::ak_c_string:
R.addString(Info.getArgCStr(i));
break;
- case DiagnosticInfo::ak_sint:
+ case Diagnostic::ak_sint:
R.addString(llvm::itostr(Info.getArgSInt(i)));
break;
- case DiagnosticInfo::ak_uint:
+ case Diagnostic::ak_uint:
R.addString(llvm::utostr_32(Info.getArgUInt(i)));
break;
- case DiagnosticInfo::ak_identifierinfo:
+ case Diagnostic::ak_identifierinfo:
R.addString(Info.getArgIdentifier(i)->getName());
break;
diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h
index 79d6c1b6fb9..ad1eb750049 100644
--- a/clang/include/clang/Basic/Diagnostic.h
+++ b/clang/include/clang/Basic/Diagnostic.h
@@ -26,7 +26,7 @@ namespace clang {
class DiagnosticClient;
class SourceRange;
class SourceManager;
- class DiagnosticInfo;
+ class DiagnosticBuilder;
class IdentifierInfo;
// Import the diagnostic enums themselves.
@@ -170,17 +170,18 @@ public:
/// Report - Issue the message to the client. DiagID is a member of the
- /// diag::kind enum. This actually returns a new instance of DiagnosticInfo
+ /// diag::kind enum. This actually returns aninstance of DiagnosticBuilder
/// which emits the diagnostics (through ProcessDiag) when it is destroyed.
- inline DiagnosticInfo Report(FullSourceLoc Pos, unsigned DiagID);
+ inline DiagnosticBuilder 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
+ // This is private state used by DiagnosticBuilder. We put it here instead of
+ // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
// 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 DiagnosticBuilder;
friend class DiagnosticInfo;
/// CurDiagLoc - This is the location of the current diagnostic that is in
@@ -188,6 +189,7 @@ private:
FullSourceLoc CurDiagLoc;
/// CurDiagID - This is the ID of the current diagnostic that is in flight.
+ /// This is set to ~0U when there is no diagnostic in flight.
unsigned CurDiagID;
enum {
@@ -197,8 +199,7 @@ private:
MaxArguments = 10
};
- /// NumDiagArgs - This is set to -1 when no diag is in flight. Otherwise it
- /// is the number of entries in Arguments.
+ /// NumDiagArgs - This contains the number of entries in Arguments.
signed char NumDiagArgs;
/// NumRanges - This is the number of ranges in the DiagRanges array.
unsigned char NumDiagRanges;
@@ -225,22 +226,7 @@ private:
/// 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 {
- mutable Diagnostic *DiagObj;
- void operator=(const DiagnosticInfo&); // DO NOT IMPLEMENT
+ void ProcessDiag();
public:
enum ArgumentKind {
ak_std_string, // std::string
@@ -249,85 +235,190 @@ public:
ak_uint, // unsigned
ak_identifierinfo // IdentifierInfo
};
+};
+
+//===----------------------------------------------------------------------===//
+// DiagnosticBuilder
+//===----------------------------------------------------------------------===//
+
+/// DiagnosticBuilder - This is a little helper class used to produce
+/// diagnostics. This is constructed by the Diagnostic::Report method, and
+/// allows insertion of extra information (arguments and source ranges) into the
+/// currently "in flight" diagnostic. When the temporary for the builder is
+/// destroyed, the diagnostic is issued.
+///
+/// Note that many of these will be created as temporary objects (many call
+/// sites), so we want them to be small and we never want their address taken.
+/// This ensures that compilers with somewhat reasonable optimizers will promote
+/// the common fields to registers, eliminating increments of the NumArgs field,
+/// for example.
+class DiagnosticBuilder {
+ mutable Diagnostic *DiagObj;
+ mutable unsigned NumArgs, NumRanges;
-
- DiagnosticInfo(Diagnostic *diagObj, FullSourceLoc Loc, unsigned DiagID) :
- DiagObj(diagObj) {
- if (DiagObj == 0) return;
- assert(DiagObj->NumDiagArgs == -1 &&
- "Multiple diagnostics in flight at once!");
- DiagObj->NumDiagArgs = DiagObj->NumDiagRanges = 0;
- DiagObj->CurDiagLoc = Loc;
- DiagObj->CurDiagID = DiagID;
- }
+ void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT
+ friend class Diagnostic;
+ explicit DiagnosticBuilder(Diagnostic *diagObj)
+ : DiagObj(diagObj), NumArgs(0), NumRanges(0) {}
+public:
+ DiagnosticBuilder() : DiagObj(0) {}
/// Copy constructor. When copied, this "takes" the diagnostic info from the
/// input and neuters it.
- DiagnosticInfo(const DiagnosticInfo &D) {
+ DiagnosticBuilder(const DiagnosticBuilder &D) {
DiagObj = D.DiagObj;
D.DiagObj = 0;
}
/// Destructor - The dtor emits the diagnostic.
- ~DiagnosticInfo() {
+ ~DiagnosticBuilder() {
// If DiagObj is null, then its soul was stolen by the copy ctor.
- if (!DiagObj) return;
+ if (DiagObj == 0) return;
+
- DiagObj->ProcessDiag(*this);
+ DiagObj->NumDiagArgs = NumArgs;
+ DiagObj->NumDiagRanges = NumRanges;
+
+ DiagObj->ProcessDiag();
// This diagnostic is no longer in flight.
- DiagObj->NumDiagArgs = -1;
+ DiagObj->CurDiagID = ~0U;
+ }
+
+ /// Operator bool: conversion of DiagnosticBuilder to bool always returns
+ /// true. This allows is to be used in boolean error contexts like:
+ /// return Diag(...);
+ operator bool() const { return true; }
+
+ void AddString(const std::string &S) const {
+ assert(NumArgs < Diagnostic::MaxArguments &&
+ "Too many arguments to diagnostic!");
+ DiagObj->DiagArgumentsKind[NumArgs] = Diagnostic::ak_std_string;
+ DiagObj->DiagArgumentsStr[NumArgs++] = S;
+ }
+
+ void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const {
+ assert(NumArgs < Diagnostic::MaxArguments &&
+ "Too many arguments to diagnostic!");
+ DiagObj->DiagArgumentsKind[NumArgs] = Kind;
+ DiagObj->DiagArgumentsVal[NumArgs++] = V;
}
+ void AddSourceRange(const SourceRange &R) const {
+ assert(NumRanges <
+ sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
+ "Too many arguments to diagnostic!");
+ DiagObj->DiagRanges[NumRanges++] = &R;
+ }
+};
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const std::string &S) {
+ DB.AddString(S);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const char *Str) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
+ Diagnostic::ak_c_string);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
+ DB.AddTaggedVal(I, Diagnostic::ak_sint);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ unsigned I) {
+ DB.AddTaggedVal(I, Diagnostic::ak_uint);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const IdentifierInfo *II) {
+ DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
+ Diagnostic::ak_identifierinfo);
+ return DB;
+}
+
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const SourceRange &R) {
+ DB.AddSourceRange(R);
+ return DB;
+}
+
+
+/// Report - Issue the message to the client. DiagID is a member of the
+/// diag::kind enum. This actually returns a new instance of DiagnosticBuilder
+/// which emits the diagnostics (through ProcessDiag) when it is destroyed.
+inline DiagnosticBuilder Diagnostic::Report(FullSourceLoc Loc, unsigned DiagID){
+ assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
+ CurDiagLoc = Loc;
+ CurDiagID = DiagID;
+ return DiagnosticBuilder(this);
+}
+
+//===----------------------------------------------------------------------===//
+// DiagnosticInfo
+//===----------------------------------------------------------------------===//
+
+/// DiagnosticInfo - This is a little helper class (which is basically a smart
+/// pointer that forward info from Diagnostic) that allows clients ot enquire
+/// about the currently in-flight diagnostic.
+class DiagnosticInfo {
+ const Diagnostic *DiagObj;
+public:
+ explicit DiagnosticInfo(const Diagnostic *DO) : DiagObj(DO) {}
+
const Diagnostic *getDiags() const { return DiagObj; }
unsigned getID() const { return DiagObj->CurDiagID; }
const FullSourceLoc &getLocation() const { return DiagObj->CurDiagLoc; }
- /// Operator bool: conversion of DiagnosticInfo to bool always returns true.
- /// This allows is to be used in boolean error contexts like:
- /// return Diag(...);
- operator bool() const { return true; }
-
unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
-
/// getArgKind - Return the kind of the specified index. Based on the kind
/// of argument, the accessors below can be used to get the value.
- ArgumentKind getArgKind(unsigned Idx) const {
- assert((signed char)Idx < DiagObj->NumDiagArgs &&
- "Argument index out of range!");
- return (ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
+ Diagnostic::ArgumentKind getArgKind(unsigned Idx) const {
+ assert(Idx < getNumArgs() && "Argument index out of range!");
+ return (Diagnostic::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
}
/// getArgStdStr - Return the provided argument string specified by Idx.
const std::string &getArgStdStr(unsigned Idx) const {
- assert(getArgKind(Idx) == ak_std_string && "invalid argument accessor!");
+ assert(getArgKind(Idx) == Diagnostic::ak_std_string &&
+ "invalid argument accessor!");
return DiagObj->DiagArgumentsStr[Idx];
}
-
+
/// getArgCStr - Return the specified C string argument.
const char *getArgCStr(unsigned Idx) const {
- assert(getArgKind(Idx) == ak_c_string && "invalid argument accessor!");
+ assert(getArgKind(Idx) == Diagnostic::ak_c_string &&
+ "invalid argument accessor!");
return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
}
/// getArgSInt - Return the specified signed integer argument.
int getArgSInt(unsigned Idx) const {
- assert(getArgKind(Idx) == ak_sint && "invalid argument accessor!");
+ assert(getArgKind(Idx) == Diagnostic::ak_sint &&
+ "invalid argument accessor!");
return (int)DiagObj->DiagArgumentsVal[Idx];
}
-
+
/// getArgUInt - Return the specified unsigned integer argument.
unsigned getArgUInt(unsigned Idx) const {
- assert(getArgKind(Idx) == ak_uint && "invalid argument accessor!");
+ assert(getArgKind(Idx) == Diagnostic::ak_uint &&
+ "invalid argument accessor!");
return (unsigned)DiagObj->DiagArgumentsVal[Idx];
}
/// getArgIdentifier - Return the specified IdentifierInfo argument.
const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
- assert(getArgKind(Idx) == ak_identifierinfo &&"invalid argument accessor!");
+ assert(getArgKind(Idx) == Diagnostic::ak_identifierinfo &&
+ "invalid argument accessor!");
return reinterpret_cast<const IdentifierInfo*>(
- DiagObj->DiagArgumentsVal[Idx]);
+ DiagObj->DiagArgumentsVal[Idx]);
}
/// getNumRanges - Return the number of source ranges associated with this
@@ -341,75 +432,12 @@ public:
return *DiagObj->DiagRanges[Idx];
}
- void AddString(const std::string &S) const {
- assert((unsigned)DiagObj->NumDiagArgs < Diagnostic::MaxArguments &&
- "Too many arguments to diagnostic!");
- DiagObj->DiagArgumentsKind[DiagObj->NumDiagArgs] = ak_std_string;
- DiagObj->DiagArgumentsStr[DiagObj->NumDiagArgs++] = S;
- }
-
- void AddTaggedVal(intptr_t V, ArgumentKind Kind) const {
- assert((unsigned)DiagObj->NumDiagArgs < Diagnostic::MaxArguments &&
- "Too many arguments to diagnostic!");
- DiagObj->DiagArgumentsKind[DiagObj->NumDiagArgs] = Kind;
- DiagObj->DiagArgumentsVal[DiagObj->NumDiagArgs++] = V;
- }
-
- void AddSourceRange(const SourceRange &R) const {
- assert((unsigned)DiagObj->NumDiagArgs <
- sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
- "Too many arguments to diagnostic!");
- DiagObj->DiagRanges[DiagObj->NumDiagRanges++] = &R;
- }
/// 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;
};
-
-inline const DiagnosticInfo &operator<<(const DiagnosticInfo &DI,
- const std::string &S) {
- DI.AddString(S);
- return DI;
-}
-
-inline const DiagnosticInfo &operator<<(const DiagnosticInfo &DI,
- const char *Str) {
- DI.AddTaggedVal(reinterpret_cast<intptr_t>(Str), DiagnosticInfo::ak_c_string);
- return DI;
-}
-
-inline const DiagnosticInfo &operator<<(const DiagnosticInfo &DI, int I) {
- DI.AddTaggedVal(I, DiagnosticInfo::ak_sint);
- return DI;
-}
-
-inline const DiagnosticInfo &operator<<(const DiagnosticInfo &DI, unsigned I) {
- DI.AddTaggedVal(I, DiagnosticInfo::ak_uint);
- return DI;
-}
-
-inline const DiagnosticInfo &operator<<(const DiagnosticInfo &DI,
- const IdentifierInfo *II){
- DI.AddTaggedVal(reinterpret_cast<intptr_t>(II),
- DiagnosticInfo::ak_identifierinfo);
- return DI;
-}
-
-inline const DiagnosticInfo &operator<<(const DiagnosticInfo &DI,
- const SourceRange &R) {
- DI.AddSourceRange(R);
- return DI;
-}
-
-
-/// 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) {
- return DiagnosticInfo(this, Pos, DiagID);
-}
/// DiagnosticClient - This is an abstract interface implemented by clients of
diff --git a/clang/include/clang/Lex/Lexer.h b/clang/include/clang/Lex/Lexer.h
index 019153695a0..77399e6d56a 100644
--- a/clang/include/clang/Lex/Lexer.h
+++ b/clang/include/clang/Lex/Lexer.h
@@ -25,7 +25,7 @@ namespace clang {
class Diagnostic;
class SourceManager;
class Preprocessor;
-class DiagnosticInfo;
+class DiagnosticBuilder;
/// Lexer - This provides a simple interface that turns a text buffer into a
/// stream of tokens. This provides no support for file reading or buffering,
@@ -172,7 +172,7 @@ public:
/// Diag - Forwarding function for diagnostics. This translate a source
/// position in the current buffer into a SourceLocation object for rendering.
- DiagnosticInfo Diag(const char *Loc, unsigned DiagID) const;
+ DiagnosticBuilder Diag(const char *Loc, unsigned DiagID) const;
/// getSourceLocation - Return a source location identifier for the specified
/// offset in the current file.
diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h
index fb2cb1d33b2..829a7ada811 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -408,8 +408,8 @@ public:
/// Diag - Forwarding function for diagnostics. This emits a diagnostic at
/// the specified Token's location, translating the token's start
/// position in the current buffer into a SourcePosition object for rendering.
- DiagnosticInfo Diag(SourceLocation Loc, unsigned DiagID);
- DiagnosticInfo Diag(const Token &Tok, unsigned DiagID);
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+ DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID);
/// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a
/// token is the characters used to represent the token in the source file
diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h
index 9a7b41b9e5c..3058ce3aba4 100644
--- a/clang/include/clang/Parse/Action.h
+++ b/clang/include/clang/Parse/Action.h
@@ -35,7 +35,7 @@ namespace clang {
class Preprocessor;
class Token;
// Basic.
- class DiagnosticInfo;
+ class DiagnosticBuilder;
/// Action - As the parser reads the input file and recognizes the productions
/// of the grammar, it invokes methods on this class to turn the parsed input
@@ -76,7 +76,7 @@ public:
ActionResult(bool Invalid = false) : Val(0), isInvalid(Invalid) {}
template<typename ActualExprTy>
ActionResult(ActualExprTy *val) : Val(val), isInvalid(false) {}
- ActionResult(const DiagnosticInfo &) : Val(0), isInvalid(true) {}
+ ActionResult(const DiagnosticBuilder &) : Val(0), isInvalid(true) {}
const ActionResult &operator=(void *RHS) {
Val = RHS;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 76edfc14146..e505e4d9caf 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -27,7 +27,7 @@ namespace clang {
class ObjCDeclSpec;
class PragmaHandler;
class Scope;
- class DiagnosticInfo;
+ class DiagnosticBuilder;
/// Parser - This implements a parser for the C family of languages. After
/// parsing units of the grammar, productions are invoked to handle whatever has
@@ -313,8 +313,8 @@ private:
//===--------------------------------------------------------------------===//
// Diagnostic Emission and Error recovery.
- DiagnosticInfo Diag(SourceLocation Loc, unsigned DiagID);
- DiagnosticInfo Diag(const Token &Tok, unsigned DiagID);
+ DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID);
+ DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID);
/// SkipUntil - Read tokens until we get to the specified token, then consume
/// it (unless DontConsume is true). Because we cannot guarantee that the
OpenPOWER on IntegriCloud