Refactoring of Diagnostic class.

-Move the stuff of Diagnostic related to creating/querying diagnostic IDs into a new DiagnosticIDs class.
-DiagnosticIDs can be shared among multiple Diagnostics for multiple translation units.
-The rest of the state in Diagnostic object is considered related and tied to one translation unit.
-Have Diagnostic point to the SourceManager that is related with. Diagnostic can now accept just a
   SourceLocation instead of a FullSourceLoc.
-Reflect the changes to various interfaces.

llvm-svn: 119730
This commit is contained in:
Argyrios Kyrtzidis 2010-11-18 20:06:41 +00:00
parent 4fadc5b20a
commit d004064864
30 changed files with 948 additions and 808 deletions

View File

@ -49,9 +49,6 @@ namespace clang {
const FileSystemOptions &ToFileSystemOpts, &FromFileSystemOpts;
/// \brief The diagnostics object that we should use to emit diagnostics.
Diagnostic &Diags;
/// \brief Mapping from the already-imported types in the "from" context
/// to the corresponding types in the "to" context.
llvm::DenseMap<Type *, Type *> ImportedTypes;
@ -77,8 +74,7 @@ namespace clang {
NonEquivalentDeclSet NonEquivalentDecls;
public:
ASTImporter(Diagnostic &Diags,
ASTContext &ToContext, FileManager &ToFileManager,
ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
const FileSystemOptions &ToFileSystemOpts,
ASTContext &FromContext, FileManager &FromFileManager,
const FileSystemOptions &FromFileSystemOpts);
@ -217,9 +213,6 @@ namespace clang {
/// \brief Retrieve the file manager that AST nodes are being imported from.
FileManager &getFromFileManager() const { return FromFileManager; }
/// \brief Retrieve the diagnostic formatter.
Diagnostic &getDiags() const { return Diags; }
/// \brief Report a diagnostic in the "to" context.
DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID);

View File

@ -14,78 +14,22 @@
#ifndef LLVM_CLANG_DIAGNOSTIC_H
#define LLVM_CLANG_DIAGNOSTIC_H
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/type_traits.h"
#include "llvm/System/DataTypes.h"
#include <string>
#include <vector>
#include <cassert>
namespace llvm {
template <typename T> class SmallVectorImpl;
}
#include <vector>
namespace clang {
class DeclContext;
class DiagnosticBuilder;
class DiagnosticClient;
class FileManager;
class DiagnosticBuilder;
class IdentifierInfo;
class DeclContext;
class LangOptions;
class PartialDiagnostic;
class Preprocessor;
// Import the diagnostic enums themselves.
namespace diag {
// Start position for diagnostics.
enum {
DIAG_START_DRIVER = 300,
DIAG_START_FRONTEND = DIAG_START_DRIVER + 100,
DIAG_START_LEX = DIAG_START_FRONTEND + 100,
DIAG_START_PARSE = DIAG_START_LEX + 300,
DIAG_START_AST = DIAG_START_PARSE + 300,
DIAG_START_SEMA = DIAG_START_AST + 100,
DIAG_START_ANALYSIS = DIAG_START_SEMA + 1500,
DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
};
class CustomDiagInfo;
/// diag::kind - All of the diagnostics that can be emitted by the frontend.
typedef unsigned kind;
// Get typedefs for common diagnostics.
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM,
#include "clang/Basic/DiagnosticCommonKinds.inc"
NUM_BUILTIN_COMMON_DIAGNOSTICS
#undef DIAG
};
/// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
/// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
/// (emit as an error). It allows clients to map errors to
/// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this
/// one).
enum Mapping {
// NOTE: 0 means "uncomputed".
MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it.
MAP_WARNING = 2, //< Map this diagnostic to a warning.
MAP_ERROR = 3, //< Map this diagnostic to an error.
MAP_FATAL = 4, //< Map this diagnostic to a fatal error.
/// Map this diagnostic to "warning", but make it immune to -Werror. This
/// happens when you specify -Wno-error=foo.
MAP_WARNING_NO_WERROR = 5,
/// Map this diagnostic to "error", but make it immune to -Wfatal-errors.
/// This happens for -Wno-fatal-errors=foo.
MAP_ERROR_NO_WFATAL = 6
};
}
/// \brief Annotates a diagnostic with some code that should be
/// inserted, removed, or replaced to fix the problem.
///
@ -154,12 +98,17 @@ public:
/// Diagnostic - This concrete class is used by the front-end to report
/// problems and issues. It massages the diagnostics (e.g. handling things like
/// "report warnings as errors" and passes them off to the DiagnosticClient for
/// reporting to the user.
/// reporting to the user. Diagnostic is tied to one translation unit and
/// one SourceManager.
class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
public:
/// Level - The level of the diagnostic, after it has been through mapping.
enum Level {
Ignored, Note, Warning, Error, Fatal
Ignored = DiagnosticIDs::Ignored,
Note = DiagnosticIDs::Note,
Warning = DiagnosticIDs::Warning,
Error = DiagnosticIDs::Error,
Fatal = DiagnosticIDs::Fatal
};
/// ExtensionHandling - How do we handle otherwise-unmapped extension? This
@ -204,7 +153,10 @@ private:
unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
// 0 -> no limit.
ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
llvm::OwningPtr<DiagnosticClient> Client;
llvm::IntrusiveRefCntPtr<DiagnosticIDs> Diags;
DiagnosticClient *Client;
bool OwnsDiagClient;
SourceManager *SourceMgr;
/// DiagMappings - Mapping information for diagnostics. Mapping info is
/// packed into four bits per diagnostic. The low three bits are the mapping
@ -238,14 +190,11 @@ private:
/// LastDiagLevel - This is the level of the last diagnostic emitted. This is
/// used to emit continuation diagnostics with the same level as the
/// diagnostic that they follow.
Diagnostic::Level LastDiagLevel;
DiagnosticIDs::Level LastDiagLevel;
unsigned NumWarnings; // Number of warnings reported
unsigned NumErrors; // Number of errors reported
unsigned NumErrorsSuppressed; // Number of errors suppressed
/// CustomDiagInfo - Information for uniquing and looking up custom diags.
diag::CustomDiagInfo *CustomDiagInfo;
/// ArgToStringFn - A function pointer that converts an opaque diagnostic
/// argument to a strings. This takes the modifiers and argument that was
@ -278,20 +227,37 @@ private:
std::string DelayedDiagArg2;
public:
explicit Diagnostic(DiagnosticClient *client = 0);
explicit Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &Diags,
DiagnosticClient *client = 0,
bool ShouldOwnClient = true);
~Diagnostic();
const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
return Diags;
}
DiagnosticClient *getClient() { return Client; }
const DiagnosticClient *getClient() const { return Client; }
/// \brief Return the current diagnostic client along with ownership of that
/// client.
DiagnosticClient *takeClient() {
OwnsDiagClient = false;
return Client;
}
bool hasSourceManager() const { return SourceMgr != 0; }
SourceManager &getSourceManager() const {
assert(SourceMgr && "SourceManager not set!");
return *SourceMgr;
}
void setSourceManager(SourceManager *SrcMgr) { SourceMgr = SrcMgr; }
//===--------------------------------------------------------------------===//
// Diagnostic characterization methods, used by a client to customize how
// diagnostics are emitted.
//
DiagnosticClient *getClient() { return Client.get(); }
const DiagnosticClient *getClient() const { return Client.get(); }
/// \brief Return the current diagnostic client along with ownership of that
/// client.
DiagnosticClient *takeClient() { return Client.take(); }
/// pushMappings - Copies the current DiagMappings and pushes the new copy
/// onto the top of the stack.
void pushMappings();
@ -304,8 +270,12 @@ public:
/// \brief Set the diagnostic client associated with this diagnostic object.
///
/// The diagnostic object takes ownership of \c client.
void setClient(DiagnosticClient* client) { Client.reset(client); }
/// \param ShouldOwnClient true if the diagnostic object should take
/// ownership of \c client.
void setClient(DiagnosticClient *client, bool ShouldOwnClient = true) {
Client = client;
OwnsDiagClient = ShouldOwnClient;
}
/// setErrorLimit - Specify a limit for the number of errors we should
/// emit before giving up. Zero disables the limit.
@ -361,7 +331,7 @@ public:
/// \brief Pretend that the last diagnostic issued was ignored. This can
/// be used by clients who suppress diagnostics themselves.
void setLastDiagnosticIgnored() {
LastDiagLevel = Ignored;
LastDiagLevel = DiagnosticIDs::Ignored;
}
/// setExtensionHandlingBehavior - This controls whether otherwise-unmapped
@ -384,7 +354,7 @@ public:
void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map) {
assert(Diag < diag::DIAG_UPPER_LIMIT &&
"Can only map builtin diagnostics");
assert((isBuiltinWarningOrExtension(Diag) ||
assert((Diags->isBuiltinWarningOrExtension(Diag) ||
(Map == diag::MAP_FATAL || Map == diag::MAP_ERROR)) &&
"Cannot map errors into warnings!");
setDiagnosticMappingInternal(Diag, Map, true);
@ -393,7 +363,9 @@ public:
/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
/// "unknown-pragmas" to have the specified mapping. This returns true and
/// ignores the request if "Group" was unknown, false otherwise.
bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map);
bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map) {
return Diags->setDiagnosticGroupMapping(Group, Map, *this);
}
bool hasErrorOccurred() const { return ErrorOccurred; }
bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
@ -406,11 +378,16 @@ public:
this->NumWarnings = NumWarnings;
}
void setNumErrors(unsigned NumErrors) {
this->NumErrors = NumErrors;
}
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
unsigned getCustomDiagID(Level L, llvm::StringRef Message);
unsigned getCustomDiagID(Level L, llvm::StringRef Message) {
return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message);
}
/// ConvertArgToString - This method converts a diagnostic argument (as an
/// intptr_t) into the string that represents it.
@ -436,92 +413,19 @@ public:
// Diagnostic classification and reporting interfaces.
//
/// getDescription - Given a diagnostic ID, return a description of the
/// issue.
const char *getDescription(unsigned DiagID) const;
/// isNoteWarningOrExtension - Return true if the unmapped diagnostic
/// level of the specified diagnostic ID is a Warning or Extension.
/// This only works on builtin diagnostics, not custom ones, and is not legal to
/// call on NOTEs.
static bool isBuiltinWarningOrExtension(unsigned DiagID);
/// \brief Determine whether the given built-in diagnostic ID is a
/// Note.
static bool isBuiltinNote(unsigned DiagID);
/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
/// ID is for an extension of some sort.
///
static bool isBuiltinExtensionDiag(unsigned DiagID) {
bool ignored;
return isBuiltinExtensionDiag(DiagID, ignored);
}
/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
/// ID is for an extension of some sort. This also returns EnabledByDefault,
/// which is set to indicate whether the diagnostic is ignored by default (in
/// which case -pedantic enables it) or treated as a warning/error by default.
///
static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault);
/// getWarningOptionForDiag - Return the lowest-level warning option that
/// enables the specified diagnostic. If there is no -Wfoo flag that controls
/// the diagnostic, this returns null.
static const char *getWarningOptionForDiag(unsigned DiagID);
/// getWarningOptionForDiag - Return the category number that a specified
/// DiagID belongs to, or 0 if no category.
static unsigned getCategoryNumberForDiag(unsigned DiagID);
/// getCategoryNameFromID - Given a category ID, return the name of the
/// category.
static const char *getCategoryNameFromID(unsigned CategoryID);
/// \brief Enumeration describing how the the emission of a diagnostic should
/// be treated when it occurs during C++ template argument deduction.
enum SFINAEResponse {
/// \brief The diagnostic should not be reported, but it should cause
/// template argument deduction to fail.
///
/// The vast majority of errors that occur during template argument
/// deduction fall into this category.
SFINAE_SubstitutionFailure,
/// \brief The diagnostic should be suppressed entirely.
///
/// Warnings generally fall into this category.
SFINAE_Suppress,
/// \brief The diagnostic should be reported.
///
/// The diagnostic should be reported. Various fatal errors (e.g.,
/// template instantiation depth exceeded) fall into this category.
SFINAE_Report
};
/// \brief Determines whether the given built-in diagnostic ID is
/// for an error that is suppressed if it occurs during C++ template
/// argument deduction.
///
/// When an error is suppressed due to SFINAE, the template argument
/// deduction fails but no diagnostic is emitted. Certain classes of
/// errors, such as those errors that involve C++ access control,
/// are not SFINAE errors.
static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);
/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
Level getDiagnosticLevel(unsigned DiagID) const;
Level getDiagnosticLevel(unsigned DiagID) const {
return (Level)Diags->getDiagnosticLevel(DiagID, *this);
}
/// Report - Issue the message to the client. @c DiagID is a member of the
/// @c diag::kind enum. This actually returns aninstance of DiagnosticBuilder
/// which emits the diagnostics (through @c ProcessDiag) when it is destroyed.
/// @c Pos represents the source location associated with the diagnostic,
/// which can be an invalid location if no position information is available.
inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID);
inline DiagnosticBuilder Report(SourceLocation Pos, unsigned DiagID);
inline DiagnosticBuilder Report(unsigned DiagID);
/// \brief Determine whethere there is already a diagnostic in flight.
@ -572,23 +476,20 @@ private:
DiagMappingsStack.back().setMapping((diag::kind)DiagId, Map);
}
/// getDiagnosticLevel - This is an internal implementation helper used when
/// DiagClass is already known.
Level getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const;
// 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 DiagnosticIDs;
friend class DiagnosticBuilder;
friend class DiagnosticInfo;
friend class PartialDiagnostic;
/// CurDiagLoc - This is the location of the current diagnostic that is in
/// flight.
FullSourceLoc CurDiagLoc;
SourceLocation 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.
@ -640,7 +541,9 @@ private:
///
/// \returns true if the diagnostic was emitted, false if it was
/// suppressed.
bool ProcessDiag();
bool ProcessDiag() {
return Diags->ProcessDiag(*this);
}
friend class ASTReader;
friend class ASTWriter;
@ -835,14 +738,15 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &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){
inline DiagnosticBuilder Diagnostic::Report(SourceLocation Loc,
unsigned DiagID){
assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
CurDiagLoc = Loc;
CurDiagID = DiagID;
return DiagnosticBuilder(this);
}
inline DiagnosticBuilder Diagnostic::Report(unsigned DiagID) {
return Report(FullSourceLoc(), DiagID);
return Report(SourceLocation(), DiagID);
}
//===----------------------------------------------------------------------===//
@ -859,7 +763,9 @@ public:
const Diagnostic *getDiags() const { return DiagObj; }
unsigned getID() const { return DiagObj->CurDiagID; }
const FullSourceLoc &getLocation() const { return DiagObj->CurDiagLoc; }
const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; }
bool hasSourceManager() const { return DiagObj->hasSourceManager(); }
SourceManager &getSourceManager() const { return DiagObj->getSourceManager();}
unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }

View File

@ -0,0 +1,203 @@
//===--- DiagnosticIDs.h - Diagnostic IDs Handling --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Diagnostic IDs-related interfaces.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_DIAGNOSTICIDS_H
#define LLVM_CLANG_DIAGNOSTICIDS_H
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/StringRef.h"
namespace clang {
class Diagnostic;
// Import the diagnostic enums themselves.
namespace diag {
// Start position for diagnostics.
enum {
DIAG_START_DRIVER = 300,
DIAG_START_FRONTEND = DIAG_START_DRIVER + 100,
DIAG_START_LEX = DIAG_START_FRONTEND + 100,
DIAG_START_PARSE = DIAG_START_LEX + 300,
DIAG_START_AST = DIAG_START_PARSE + 300,
DIAG_START_SEMA = DIAG_START_AST + 100,
DIAG_START_ANALYSIS = DIAG_START_SEMA + 1500,
DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
};
class CustomDiagInfo;
/// diag::kind - All of the diagnostics that can be emitted by the frontend.
typedef unsigned kind;
// Get typedefs for common diagnostics.
enum {
#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,CATEGORY) ENUM,
#include "clang/Basic/DiagnosticCommonKinds.inc"
NUM_BUILTIN_COMMON_DIAGNOSTICS
#undef DIAG
};
/// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
/// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
/// (emit as an error). It allows clients to map errors to
/// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this
/// one).
enum Mapping {
// NOTE: 0 means "uncomputed".
MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it.
MAP_WARNING = 2, //< Map this diagnostic to a warning.
MAP_ERROR = 3, //< Map this diagnostic to an error.
MAP_FATAL = 4, //< Map this diagnostic to a fatal error.
/// Map this diagnostic to "warning", but make it immune to -Werror. This
/// happens when you specify -Wno-error=foo.
MAP_WARNING_NO_WERROR = 5,
/// Map this diagnostic to "error", but make it immune to -Wfatal-errors.
/// This happens for -Wno-fatal-errors=foo.
MAP_ERROR_NO_WFATAL = 6
};
}
/// \brief Used for handling and querying diagnostic IDs. Can be used and shared
/// by multiple Diagnostics for multiple translation units.
class DiagnosticIDs : public llvm::RefCountedBase<DiagnosticIDs> {
public:
/// Level - The level of the diagnostic, after it has been through mapping.
enum Level {
Ignored, Note, Warning, Error, Fatal
};
private:
/// CustomDiagInfo - Information for uniquing and looking up custom diags.
diag::CustomDiagInfo *CustomDiagInfo;
public:
DiagnosticIDs();
~DiagnosticIDs();
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
unsigned getCustomDiagID(Level L, llvm::StringRef Message);
//===--------------------------------------------------------------------===//
// Diagnostic classification and reporting interfaces.
//
/// getDescription - Given a diagnostic ID, return a description of the
/// issue.
const char *getDescription(unsigned DiagID) const;
/// isNoteWarningOrExtension - Return true if the unmapped diagnostic
/// level of the specified diagnostic ID is a Warning or Extension.
/// This only works on builtin diagnostics, not custom ones, and is not legal to
/// call on NOTEs.
static bool isBuiltinWarningOrExtension(unsigned DiagID);
/// \brief Determine whether the given built-in diagnostic ID is a
/// Note.
static bool isBuiltinNote(unsigned DiagID);
/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
/// ID is for an extension of some sort.
///
static bool isBuiltinExtensionDiag(unsigned DiagID) {
bool ignored;
return isBuiltinExtensionDiag(DiagID, ignored);
}
/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
/// ID is for an extension of some sort. This also returns EnabledByDefault,
/// which is set to indicate whether the diagnostic is ignored by default (in
/// which case -pedantic enables it) or treated as a warning/error by default.
///
static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault);
/// getWarningOptionForDiag - Return the lowest-level warning option that
/// enables the specified diagnostic. If there is no -Wfoo flag that controls
/// the diagnostic, this returns null.
static const char *getWarningOptionForDiag(unsigned DiagID);
/// getWarningOptionForDiag - Return the category number that a specified
/// DiagID belongs to, or 0 if no category.
static unsigned getCategoryNumberForDiag(unsigned DiagID);
/// getCategoryNameFromID - Given a category ID, return the name of the
/// category.
static const char *getCategoryNameFromID(unsigned CategoryID);
/// \brief Enumeration describing how the the emission of a diagnostic should
/// be treated when it occurs during C++ template argument deduction.
enum SFINAEResponse {
/// \brief The diagnostic should not be reported, but it should cause
/// template argument deduction to fail.
///
/// The vast majority of errors that occur during template argument
/// deduction fall into this category.
SFINAE_SubstitutionFailure,
/// \brief The diagnostic should be suppressed entirely.
///
/// Warnings generally fall into this category.
SFINAE_Suppress,
/// \brief The diagnostic should be reported.
///
/// The diagnostic should be reported. Various fatal errors (e.g.,
/// template instantiation depth exceeded) fall into this category.
SFINAE_Report
};
/// \brief Determines whether the given built-in diagnostic ID is
/// for an error that is suppressed if it occurs during C++ template
/// argument deduction.
///
/// When an error is suppressed due to SFINAE, the template argument
/// deduction fails but no diagnostic is emitted. Certain classes of
/// errors, such as those errors that involve C++ access control,
/// are not SFINAE errors.
static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);
private:
/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
/// "unknown-pragmas" to have the specified mapping. This returns true and
/// ignores the request if "Group" was unknown, false otherwise.
bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map,
Diagnostic &Diag) const;
/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID,
const Diagnostic &Diag) const;
/// getDiagnosticLevel - This is an internal implementation helper used when
/// DiagClass is already known.
DiagnosticIDs::Level getDiagnosticLevel(unsigned DiagID,
unsigned DiagClass,
const Diagnostic &Diag) const;
/// ProcessDiag - This is the method used to report a diagnostic that is
/// finally fully formed.
///
/// \returns true if the diagnostic was emitted, false if it was
/// suppressed.
bool ProcessDiag(Diagnostic &Diag) const;
friend class Diagnostic;
};
} // end namespace clang
#endif

View File

@ -432,12 +432,7 @@ class SourceManager {
void operator=(const SourceManager&);
public:
SourceManager(Diagnostic &Diag, FileManager &FileMgr,
const FileSystemOptions &FSOpts)
: Diag(Diag), FileMgr(FileMgr), FileSystemOpts(FSOpts),
ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
NumBinaryProbes(0) {
clearIDTables();
}
const FileSystemOptions &FSOpts);
~SourceManager();
void clearIDTables();

View File

@ -626,12 +626,11 @@ public:
/// the specified Token's location, translating the token's start
/// position in the current buffer into a SourcePosition object for rendering.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
return Diags->Report(FullSourceLoc(Loc, getSourceManager()), DiagID);
return Diags->Report(Loc, DiagID);
}
DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID) {
return Diags->Report(FullSourceLoc(Tok.getLocation(), getSourceManager()),
DiagID);
return Diags->Report(Tok.getLocation(), DiagID);
}
/// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a

View File

@ -99,7 +99,7 @@ public:
const DiagnosticInfo &Info);
/// \brief Emit a diagnostic via the adapted diagnostic client.
void Diag(FullSourceLoc Loc, unsigned DiagID);
void Diag(SourceLocation Loc, unsigned DiagID);
};
}

View File

@ -137,9 +137,6 @@ namespace {
/// \brief AST contexts for which we are checking structural equivalence.
ASTContext &C1, &C2;
/// \brief Diagnostic object used to emit diagnostics.
Diagnostic &Diags;
/// \brief The set of "tentative" equivalences between two canonical
/// declarations, mapping from a declaration in the first context to the
/// declaration in the second context that we believe to be equivalent.
@ -158,10 +155,9 @@ namespace {
bool StrictTypeSpelling;
StructuralEquivalenceContext(ASTContext &C1, ASTContext &C2,
Diagnostic &Diags,
llvm::DenseSet<std::pair<Decl *, Decl *> > &NonEquivalentDecls,
bool StrictTypeSpelling = false)
: C1(C1), C2(C2), Diags(Diags), NonEquivalentDecls(NonEquivalentDecls),
: C1(C1), C2(C2), NonEquivalentDecls(NonEquivalentDecls),
StrictTypeSpelling(StrictTypeSpelling) { }
/// \brief Determine whether the two declarations are structurally
@ -179,11 +175,11 @@ namespace {
public:
DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(FullSourceLoc(Loc, C1.getSourceManager()), DiagID);
return C1.getDiagnostics().Report(Loc, DiagID);
}
DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(FullSourceLoc(Loc, C2.getSourceManager()), DiagID);
return C2.getDiagnostics().Report(Loc, DiagID);
}
};
}
@ -1432,7 +1428,6 @@ bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
RecordDecl *ToRecord) {
StructuralEquivalenceContext Ctx(Importer.getFromContext(),
Importer.getToContext(),
Importer.getDiags(),
Importer.getNonEquivalentDecls());
return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord);
}
@ -1440,7 +1435,6 @@ bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) {
StructuralEquivalenceContext Ctx(Importer.getFromContext(),
Importer.getToContext(),
Importer.getDiags(),
Importer.getNonEquivalentDecls());
return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum);
}
@ -2983,15 +2977,13 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
Importer.Import(E->getRParenLoc()));
}
ASTImporter::ASTImporter(Diagnostic &Diags,
ASTContext &ToContext, FileManager &ToFileManager,
ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
const FileSystemOptions &ToFileSystemOpts,
ASTContext &FromContext, FileManager &FromFileManager,
const FileSystemOptions &FromFileSystemOpts)
: ToContext(ToContext), FromContext(FromContext),
ToFileManager(ToFileManager), FromFileManager(FromFileManager),
ToFileSystemOpts(ToFileSystemOpts), FromFileSystemOpts(FromFileSystemOpts),
Diags(Diags) {
ToFileSystemOpts(ToFileSystemOpts), FromFileSystemOpts(FromFileSystemOpts) {
ImportedDecls[FromContext.getTranslationUnitDecl()]
= ToContext.getTranslationUnitDecl();
}
@ -3167,7 +3159,8 @@ FileID ASTImporter::Import(FileID FromID) {
FromSLoc.getFile().getFileCharacteristic());
} else {
// FIXME: We want to re-use the existing MemoryBuffer!
const llvm::MemoryBuffer *FromBuf = Cache->getBuffer(getDiags(), FromSM);
const llvm::MemoryBuffer *
FromBuf = Cache->getBuffer(FromContext.getDiagnostics(), FromSM);
llvm::MemoryBuffer *ToBuf
= llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(),
FromBuf->getBufferIdentifier());
@ -3263,13 +3256,11 @@ DeclarationName ASTImporter::HandleNameConflict(DeclarationName Name,
}
DiagnosticBuilder ASTImporter::ToDiag(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(FullSourceLoc(Loc, ToContext.getSourceManager()),
DiagID);
return ToContext.getDiagnostics().Report(Loc, DiagID);
}
DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(FullSourceLoc(Loc, FromContext.getSourceManager()),
DiagID);
return FromContext.getDiagnostics().Report(Loc, DiagID);
}
Decl *ASTImporter::Imported(Decl *From, Decl *To) {
@ -3283,7 +3274,6 @@ bool ASTImporter::IsStructurallyEquivalent(QualType From, QualType To) {
if (Pos != ImportedTypes.end() && ToContext.hasSameType(Import(From), To))
return true;
StructuralEquivalenceContext Ctx(FromContext, ToContext, Diags,
NonEquivalentDecls);
StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls);
return Ctx.IsStructurallyEquivalent(From, To);
}

View File

@ -1633,8 +1633,7 @@ RecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) {
DiagnosticBuilder
RecordLayoutBuilder::Diag(SourceLocation Loc, unsigned DiagID) {
return Context.getDiagnostics().Report(
FullSourceLoc(Loc, Context.getSourceManager()), DiagID);
return Context.getDiagnostics().Report(Loc, DiagID);
}
namespace {

View File

@ -11,227 +11,13 @@
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTDiagnostic.h"
#include "clang/Analysis/AnalysisDiagnostic.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <vector>
#include <map>
#include <cstring>
using namespace clang;
//===----------------------------------------------------------------------===//
// Builtin Diagnostic information
//===----------------------------------------------------------------------===//
namespace {
// Diagnostic classes.
enum {
CLASS_NOTE = 0x01,
CLASS_WARNING = 0x02,
CLASS_EXTENSION = 0x03,
CLASS_ERROR = 0x04
};
struct StaticDiagInfoRec {
unsigned short DiagID;
unsigned Mapping : 3;
unsigned Class : 3;
bool SFINAE : 1;
unsigned Category : 5;
const char *Description;
const char *OptionGroup;
bool operator<(const StaticDiagInfoRec &RHS) const {
return DiagID < RHS.DiagID;
}
};
}
static const StaticDiagInfoRec StaticDiagInfo[] = {
#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE, CATEGORY) \
{ diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, CATEGORY, DESC, GROUP },
#include "clang/Basic/DiagnosticCommonKinds.inc"
#include "clang/Basic/DiagnosticDriverKinds.inc"
#include "clang/Basic/DiagnosticFrontendKinds.inc"
#include "clang/Basic/DiagnosticLexKinds.inc"
#include "clang/Basic/DiagnosticParseKinds.inc"
#include "clang/Basic/DiagnosticASTKinds.inc"
#include "clang/Basic/DiagnosticSemaKinds.inc"
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
{ 0, 0, 0, 0, 0, 0, 0}
};
#undef DIAG
/// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
/// or null if the ID is invalid.
static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
unsigned NumDiagEntries = sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
// If assertions are enabled, verify that the StaticDiagInfo array is sorted.
#ifndef NDEBUG
static bool IsFirst = true;
if (IsFirst) {
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
// Search the diagnostic table with a binary search.
StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0, 0 };
const StaticDiagInfoRec *Found =
std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find);
if (Found == StaticDiagInfo + NumDiagEntries ||
Found->DiagID != DiagID)
return 0;
return Found;
}
static unsigned GetDefaultDiagMapping(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->Mapping;
return diag::MAP_FATAL;
}
/// getWarningOptionForDiag - Return the lowest-level warning option that
/// enables the specified diagnostic. If there is no -Wfoo flag that controls
/// the diagnostic, this returns null.
const char *Diagnostic::getWarningOptionForDiag(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->OptionGroup;
return 0;
}
/// getWarningOptionForDiag - Return the category number that a specified
/// DiagID belongs to, or 0 if no category.
unsigned Diagnostic::getCategoryNumberForDiag(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->Category;
return 0;
}
/// getCategoryNameFromID - Given a category ID, return the name of the
/// category, an empty string if CategoryID is zero, or null if CategoryID is
/// invalid.
const char *Diagnostic::getCategoryNameFromID(unsigned CategoryID) {
// Second the table of options, sorted by name for fast binary lookup.
static const char *CategoryNameTable[] = {
#define GET_CATEGORY_TABLE
#define CATEGORY(X) X,
#include "clang/Basic/DiagnosticGroups.inc"
#undef GET_CATEGORY_TABLE
"<<END>>"
};
static const size_t CategoryNameTableSize =
sizeof(CategoryNameTable) / sizeof(CategoryNameTable[0])-1;
if (CategoryID >= CategoryNameTableSize) return 0;
return CategoryNameTable[CategoryID];
}
Diagnostic::SFINAEResponse
Diagnostic::getDiagnosticSFINAEResponse(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) {
if (!Info->SFINAE)
return SFINAE_Report;
if (Info->Class == CLASS_ERROR)
return SFINAE_SubstitutionFailure;
// Suppress notes, warnings, and extensions;
return SFINAE_Suppress;
}
return SFINAE_Report;
}
/// getDiagClass - Return the class field of the diagnostic.
///
static unsigned getBuiltinDiagClass(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->Class;
return ~0U;
}
//===----------------------------------------------------------------------===//
// Custom Diagnostic information
//===----------------------------------------------------------------------===//
namespace clang {
namespace diag {
class CustomDiagInfo {
typedef std::pair<Diagnostic::Level, std::string> DiagDesc;
std::vector<DiagDesc> DiagInfo;
std::map<DiagDesc, unsigned> DiagIDs;
public:
/// getDescription - Return the description of the specified custom
/// diagnostic.
const char *getDescription(unsigned DiagID) const {
assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
"Invalid diagnosic ID");
return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second.c_str();
}
/// getLevel - Return the level of the specified custom diagnostic.
Diagnostic::Level getLevel(unsigned DiagID) const {
assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
"Invalid diagnosic ID");
return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
}
unsigned getOrCreateDiagID(Diagnostic::Level L, llvm::StringRef Message,
Diagnostic &Diags) {
DiagDesc D(L, Message);
// Check to see if it already exists.
std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
if (I != DiagIDs.end() && I->first == D)
return I->second;
// If not, assign a new ID.
unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
DiagIDs.insert(std::make_pair(D, ID));
DiagInfo.push_back(D);
return ID;
}
};
} // end diag namespace
} // end clang namespace
//===----------------------------------------------------------------------===//
// Common Diagnostic implementation
//===----------------------------------------------------------------------===//
static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT,
const char *Modifier, unsigned ML,
const char *Argument, unsigned ArgLen,
@ -244,7 +30,10 @@ static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT,
}
Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
Diagnostic::Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &diags,
DiagnosticClient *client, bool ShouldOwnClient)
: Diags(diags), Client(client), OwnsDiagClient(ShouldOwnClient),
SourceMgr(0) {
ArgToStringFn = DummyArgToStringFn;
ArgToStringCookie = 0;
@ -259,7 +48,6 @@ Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
ErrorLimit = 0;
TemplateBacktraceLimit = 0;
CustomDiagInfo = 0;
// Set all mappings to 'unset'.
DiagMappingsStack.clear();
@ -269,7 +57,8 @@ Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
}
Diagnostic::~Diagnostic() {
delete CustomDiagInfo;
if (OwnsDiagClient)
delete Client;
}
@ -287,47 +76,6 @@ bool Diagnostic::popMappings() {
return true;
}
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
unsigned Diagnostic::getCustomDiagID(Level L, llvm::StringRef Message) {
if (CustomDiagInfo == 0)
CustomDiagInfo = new diag::CustomDiagInfo();
return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
}
/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
/// level of the specified diagnostic ID is a Warning or Extension.
/// This only works on builtin diagnostics, not custom ones, and is not legal to
/// call on NOTEs.
bool Diagnostic::isBuiltinWarningOrExtension(unsigned DiagID) {
return DiagID < diag::DIAG_UPPER_LIMIT &&
getBuiltinDiagClass(DiagID) != CLASS_ERROR;
}
/// \brief Determine whether the given built-in diagnostic ID is a
/// Note.
bool Diagnostic::isBuiltinNote(unsigned DiagID) {
return DiagID < diag::DIAG_UPPER_LIMIT &&
getBuiltinDiagClass(DiagID) == CLASS_NOTE;
}
/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
/// ID is for an extension of some sort. This also returns EnabledByDefault,
/// which is set to indicate whether the diagnostic is ignored by default (in
/// which case -pedantic enables it) or treated as a warning/error by default.
///
bool Diagnostic::isBuiltinExtensionDiag(unsigned DiagID,
bool &EnabledByDefault) {
if (DiagID >= diag::DIAG_UPPER_LIMIT ||
getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
return false;
EnabledByDefault = GetDefaultDiagMapping(DiagID) != diag::MAP_IGNORE;
return true;
}
void Diagnostic::Reset() {
ErrorOccurred = false;
FatalErrorOccurred = false;
@ -336,18 +84,14 @@ void Diagnostic::Reset() {
NumErrors = 0;
NumErrorsSuppressed = 0;
CurDiagID = ~0U;
LastDiagLevel = Ignored;
// Set LastDiagLevel to an "unset" state. If we set it to 'Ignored', notes
// using a Diagnostic associated to a translation unit that follow
// diagnostics from a Diagnostic associated to anoter t.u. will not be
// displayed.
LastDiagLevel = (DiagnosticIDs::Level)-1;
DelayedDiagID = 0;
}
/// getDescription - Given a diagnostic ID, return a description of the
/// issue.
const char *Diagnostic::getDescription(unsigned DiagID) const {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->Description;
return CustomDiagInfo->getDescription(DiagID);
}
void Diagnostic::SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1,
llvm::StringRef Arg2) {
if (DelayedDiagID)
@ -365,266 +109,6 @@ void Diagnostic::ReportDelayed() {
DelayedDiagArg2.clear();
}
/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const {
// Handle custom diagnostics, which cannot be mapped.
if (DiagID >= diag::DIAG_UPPER_LIMIT)
return CustomDiagInfo->getLevel(DiagID);
unsigned DiagClass = getBuiltinDiagClass(DiagID);
assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
return getDiagnosticLevel(DiagID, DiagClass);
}
/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
Diagnostic::Level
Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const {
// Specific non-error diagnostics may be mapped to various levels from ignored
// to error. Errors can only be mapped to fatal.
Diagnostic::Level Result = Diagnostic::Fatal;
// Get the mapping information, if unset, compute it lazily.
unsigned MappingInfo = getDiagnosticMappingInfo((diag::kind)DiagID);
if (MappingInfo == 0) {
MappingInfo = GetDefaultDiagMapping(DiagID);
setDiagnosticMappingInternal(DiagID, MappingInfo, false);
}
switch (MappingInfo & 7) {
default: assert(0 && "Unknown mapping!");
case diag::MAP_IGNORE:
// Ignore this, unless this is an extension diagnostic and we're mapping
// them onto warnings or errors.
if (!isBuiltinExtensionDiag(DiagID) || // Not an extension
ExtBehavior == Ext_Ignore || // Extensions ignored anyway
(MappingInfo & 8) != 0) // User explicitly mapped it.
return Diagnostic::Ignored;
Result = Diagnostic::Warning;
if (ExtBehavior == Ext_Error) Result = Diagnostic::Error;
if (Result == Diagnostic::Error && ErrorsAsFatal)
Result = Diagnostic::Fatal;
break;
case diag::MAP_ERROR:
Result = Diagnostic::Error;
if (ErrorsAsFatal)
Result = Diagnostic::Fatal;
break;
case diag::MAP_FATAL:
Result = Diagnostic::Fatal;
break;
case diag::MAP_WARNING:
// If warnings are globally mapped to ignore or error, do it.
if (IgnoreAllWarnings)
return Diagnostic::Ignored;
Result = Diagnostic::Warning;
// If this is an extension diagnostic and we're in -pedantic-error mode, and
// if the user didn't explicitly map it, upgrade to an error.
if (ExtBehavior == Ext_Error &&
(MappingInfo & 8) == 0 &&
isBuiltinExtensionDiag(DiagID))
Result = Diagnostic::Error;
if (WarningsAsErrors)
Result = Diagnostic::Error;
if (Result == Diagnostic::Error && ErrorsAsFatal)
Result = Diagnostic::Fatal;
break;
case diag::MAP_WARNING_NO_WERROR:
// Diagnostics specified with -Wno-error=foo should be set to warnings, but
// not be adjusted by -Werror or -pedantic-errors.
Result = Diagnostic::Warning;
// If warnings are globally mapped to ignore or error, do it.
if (IgnoreAllWarnings)
return Diagnostic::Ignored;
break;
case diag::MAP_ERROR_NO_WFATAL:
// Diagnostics specified as -Wno-fatal-error=foo should be errors, but
// unaffected by -Wfatal-errors.
Result = Diagnostic::Error;
break;
}
// Okay, we're about to return this as a "diagnostic to emit" one last check:
// if this is any sort of extension warning, and if we're in an __extension__
// block, silence it.
if (AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
return Diagnostic::Ignored;
return Result;
}
struct WarningOption {
const char *Name;
const short *Members;
const short *SubGroups;
};
#define GET_DIAG_ARRAYS
#include "clang/Basic/DiagnosticGroups.inc"
#undef GET_DIAG_ARRAYS
// Second the table of options, sorted by name for fast binary lookup.
static const WarningOption OptionTable[] = {
#define GET_DIAG_TABLE
#include "clang/Basic/DiagnosticGroups.inc"
#undef GET_DIAG_TABLE
};
static const size_t OptionTableSize =
sizeof(OptionTable) / sizeof(OptionTable[0]);
static bool WarningOptionCompare(const WarningOption &LHS,
const WarningOption &RHS) {
return strcmp(LHS.Name, RHS.Name) < 0;
}
static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
Diagnostic &Diags) {
// Option exists, poke all the members of its diagnostic set.
if (const short *Member = Group->Members) {
for (; *Member != -1; ++Member)
Diags.setDiagnosticMapping(*Member, Mapping);
}
// Enable/disable all subgroups along with this one.
if (const short *SubGroups = Group->SubGroups) {
for (; *SubGroups != (short)-1; ++SubGroups)
MapGroupMembers(&OptionTable[(short)*SubGroups], Mapping, Diags);
}
}
/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
/// "unknown-pragmas" to have the specified mapping. This returns true and
/// ignores the request if "Group" was unknown, false otherwise.
bool Diagnostic::setDiagnosticGroupMapping(const char *Group,
diag::Mapping Map) {
WarningOption Key = { Group, 0, 0 };
const WarningOption *Found =
std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key,
WarningOptionCompare);
if (Found == OptionTable + OptionTableSize ||
strcmp(Found->Name, Group) != 0)
return true; // Option not found.
MapGroupMembers(Found, Map, *this);
return false;
}
/// ProcessDiag - This is the method used to report a diagnostic that is
/// finally fully formed.
bool Diagnostic::ProcessDiag() {
DiagnosticInfo Info(this);
if (SuppressAllDiagnostics)
return false;
// Figure out the diagnostic level of this message.
Diagnostic::Level DiagLevel;
unsigned DiagID = Info.getID();
// ShouldEmitInSystemHeader - True if this diagnostic should be produced even
// in a system header.
bool ShouldEmitInSystemHeader;
if (DiagID >= diag::DIAG_UPPER_LIMIT) {
// Handle custom diagnostics, which cannot be mapped.
DiagLevel = CustomDiagInfo->getLevel(DiagID);
// Custom diagnostics always are emitted in system headers.
ShouldEmitInSystemHeader = true;
} else {
// Get the class of the diagnostic. If this is a NOTE, map it onto whatever
// the diagnostic level was for the previous diagnostic so that it is
// filtered the same as the previous diagnostic.
unsigned DiagClass = getBuiltinDiagClass(DiagID);
if (DiagClass == CLASS_NOTE) {
DiagLevel = Diagnostic::Note;
ShouldEmitInSystemHeader = false; // extra consideration is needed
} else {
// If this is not an error and we are in a system header, we ignore it.
// Check 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.
ShouldEmitInSystemHeader = DiagClass == CLASS_ERROR;
DiagLevel = getDiagnosticLevel(DiagID, DiagClass);
}
}
if (DiagLevel != Diagnostic::Note) {
// Record that a fatal error occurred only when we see a second
// non-note diagnostic. This allows notes to be attached to the
// fatal error, but suppresses any diagnostics that follow those
// notes.
if (LastDiagLevel == Diagnostic::Fatal)
FatalErrorOccurred = true;
LastDiagLevel = DiagLevel;
}
// If a fatal error has already been emitted, silence all subsequent
// diagnostics.
if (FatalErrorOccurred) {
if (DiagLevel >= Diagnostic::Error && Client->IncludeInDiagnosticCounts()) {
++NumErrors;
++NumErrorsSuppressed;
}
return false;
}
// If the client doesn't care about this message, don't issue it. If this is
// a note and the last real diagnostic was ignored, ignore it too.
if (DiagLevel == Diagnostic::Ignored ||
(DiagLevel == Diagnostic::Note && LastDiagLevel == Diagnostic::Ignored))
return false;
// If this diagnostic is in a system header and is not a clang error, suppress
// it.
if (SuppressSystemWarnings && !ShouldEmitInSystemHeader &&
Info.getLocation().isValid() &&
Info.getLocation().getInstantiationLoc().isInSystemHeader() &&
(DiagLevel != Diagnostic::Note || LastDiagLevel == Diagnostic::Ignored)) {
LastDiagLevel = Diagnostic::Ignored;
return false;
}
if (DiagLevel >= Diagnostic::Error) {
if (Client->IncludeInDiagnosticCounts()) {
ErrorOccurred = true;
++NumErrors;
}
// If we've emitted a lot of errors, emit a fatal error after it to stop a
// flood of bogus errors.
if (ErrorLimit && NumErrors >= ErrorLimit &&
DiagLevel == Diagnostic::Error)
SetDelayedDiagnostic(diag::fatal_too_many_errors);
}
// Finally, report it.
Client->HandleDiagnostic(DiagLevel, Info);
if (Client->IncludeInDiagnosticCounts()) {
if (DiagLevel == Diagnostic::Warning)
++NumWarnings;
}
CurDiagID = ~0U;
return true;
}
void DiagnosticBuilder::FlushCounts() {
DiagObj->NumDiagArgs = NumArgs;
DiagObj->NumDiagRanges = NumRanges;
@ -889,7 +373,7 @@ static void HandlePluralModifier(const DiagnosticInfo &DInfo, unsigned ValNo,
/// array.
void DiagnosticInfo::
FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {
const char *DiagStr = getDiags()->getDescription(getID());
const char *DiagStr = getDiags()->getDiagnosticIDs()->getDescription(getID());
const char *DiagEnd = DiagStr+strlen(DiagStr);
FormatDiagnostic(DiagStr, DiagEnd, OutStr);
@ -1059,7 +543,11 @@ StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level,
StoredDiagnostic::StoredDiagnostic(Diagnostic::Level Level,
const DiagnosticInfo &Info)
: Level(Level), Loc(Info.getLocation()) {
: Level(Level) {
assert((Info.getLocation().isInvalid() || Info.hasSourceManager()) &&
"Valid source location without setting a source manager for diagnostic");
if (Info.getLocation().isValid())
Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
llvm::SmallString<64> Message;
Info.FormatDiagnostic(Message);
this->Message.assign(Message.begin(), Message.end());

View File

@ -0,0 +1,547 @@
//===--- DiagnosticIDs.cpp - Diagnostic IDs Handling ----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Diagnostic IDs-related interfaces.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTDiagnostic.h"
#include "clang/Analysis/AnalysisDiagnostic.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/SemaDiagnostic.h"
#include <map>
using namespace clang;
//===----------------------------------------------------------------------===//
// Builtin Diagnostic information
//===----------------------------------------------------------------------===//
namespace {
// Diagnostic classes.
enum {
CLASS_NOTE = 0x01,
CLASS_WARNING = 0x02,
CLASS_EXTENSION = 0x03,
CLASS_ERROR = 0x04
};
struct StaticDiagInfoRec {
unsigned short DiagID;
unsigned Mapping : 3;
unsigned Class : 3;
bool SFINAE : 1;
unsigned Category : 5;
const char *Description;
const char *OptionGroup;
bool operator<(const StaticDiagInfoRec &RHS) const {
return DiagID < RHS.DiagID;
}
};
}
static const StaticDiagInfoRec StaticDiagInfo[] = {
#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE, CATEGORY) \
{ diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, CATEGORY, DESC, GROUP },
#include "clang/Basic/DiagnosticCommonKinds.inc"
#include "clang/Basic/DiagnosticDriverKinds.inc"
#include "clang/Basic/DiagnosticFrontendKinds.inc"
#include "clang/Basic/DiagnosticLexKinds.inc"
#include "clang/Basic/DiagnosticParseKinds.inc"
#include "clang/Basic/DiagnosticASTKinds.inc"
#include "clang/Basic/DiagnosticSemaKinds.inc"
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
{ 0, 0, 0, 0, 0, 0, 0}
};
#undef DIAG
/// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
/// or null if the ID is invalid.
static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
unsigned NumDiagEntries = sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
// If assertions are enabled, verify that the StaticDiagInfo array is sorted.
#ifndef NDEBUG
static bool IsFirst = true;
if (IsFirst) {
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
// Search the diagnostic table with a binary search.
StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0, 0 };
const StaticDiagInfoRec *Found =
std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find);
if (Found == StaticDiagInfo + NumDiagEntries ||
Found->DiagID != DiagID)
return 0;
return Found;
}
static unsigned GetDefaultDiagMapping(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->Mapping;
return diag::MAP_FATAL;
}
/// getWarningOptionForDiag - Return the lowest-level warning option that
/// enables the specified diagnostic. If there is no -Wfoo flag that controls
/// the diagnostic, this returns null.
const char *DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->OptionGroup;
return 0;
}
/// getWarningOptionForDiag - Return the category number that a specified
/// DiagID belongs to, or 0 if no category.
unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->Category;
return 0;
}
/// getCategoryNameFromID - Given a category ID, return the name of the
/// category, an empty string if CategoryID is zero, or null if CategoryID is
/// invalid.
const char *DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
// Second the table of options, sorted by name for fast binary lookup.
static const char *CategoryNameTable[] = {
#define GET_CATEGORY_TABLE
#define CATEGORY(X) X,
#include "clang/Basic/DiagnosticGroups.inc"
#undef GET_CATEGORY_TABLE
"<<END>>"
};
static const size_t CategoryNameTableSize =
sizeof(CategoryNameTable) / sizeof(CategoryNameTable[0])-1;
if (CategoryID >= CategoryNameTableSize) return 0;
return CategoryNameTable[CategoryID];
}
DiagnosticIDs::SFINAEResponse
DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) {
if (!Info->SFINAE)
return SFINAE_Report;
if (Info->Class == CLASS_ERROR)
return SFINAE_SubstitutionFailure;
// Suppress notes, warnings, and extensions;
return SFINAE_Suppress;
}
return SFINAE_Report;
}
/// getDiagClass - Return the class field of the diagnostic.
///
static unsigned getBuiltinDiagClass(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->Class;
return ~0U;
}
//===----------------------------------------------------------------------===//
// Custom Diagnostic information
//===----------------------------------------------------------------------===//
namespace clang {
namespace diag {
class CustomDiagInfo {
typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
std::vector<DiagDesc> DiagInfo;
std::map<DiagDesc, unsigned> DiagIDs;
public:
/// getDescription - Return the description of the specified custom
/// diagnostic.
const char *getDescription(unsigned DiagID) const {
assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
"Invalid diagnosic ID");
return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second.c_str();
}
/// getLevel - Return the level of the specified custom diagnostic.
DiagnosticIDs::Level getLevel(unsigned DiagID) const {
assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
"Invalid diagnosic ID");
return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
}
unsigned getOrCreateDiagID(DiagnosticIDs::Level L, llvm::StringRef Message,
DiagnosticIDs &Diags) {
DiagDesc D(L, Message);
// Check to see if it already exists.
std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
if (I != DiagIDs.end() && I->first == D)
return I->second;
// If not, assign a new ID.
unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
DiagIDs.insert(std::make_pair(D, ID));
DiagInfo.push_back(D);
return ID;
}
};
} // end diag namespace
} // end clang namespace
//===----------------------------------------------------------------------===//
// Common Diagnostic implementation
//===----------------------------------------------------------------------===//
DiagnosticIDs::DiagnosticIDs() {
CustomDiagInfo = 0;
}
DiagnosticIDs::~DiagnosticIDs() {
delete CustomDiagInfo;
}
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
unsigned DiagnosticIDs::getCustomDiagID(Level L, llvm::StringRef Message) {
if (CustomDiagInfo == 0)
CustomDiagInfo = new diag::CustomDiagInfo();
return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
}
/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
/// level of the specified diagnostic ID is a Warning or Extension.
/// This only works on builtin diagnostics, not custom ones, and is not legal to
/// call on NOTEs.
bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
return DiagID < diag::DIAG_UPPER_LIMIT &&
getBuiltinDiagClass(DiagID) != CLASS_ERROR;
}
/// \brief Determine whether the given built-in diagnostic ID is a
/// Note.
bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
return DiagID < diag::DIAG_UPPER_LIMIT &&
getBuiltinDiagClass(DiagID) == CLASS_NOTE;
}
/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
/// ID is for an extension of some sort. This also returns EnabledByDefault,
/// which is set to indicate whether the diagnostic is ignored by default (in
/// which case -pedantic enables it) or treated as a warning/error by default.
///
bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
bool &EnabledByDefault) {
if (DiagID >= diag::DIAG_UPPER_LIMIT ||
getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
return false;
EnabledByDefault = GetDefaultDiagMapping(DiagID) != diag::MAP_IGNORE;
return true;
}
/// getDescription - Given a diagnostic ID, return a description of the
/// issue.
const char *DiagnosticIDs::getDescription(unsigned DiagID) const {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
return Info->Description;
return CustomDiagInfo->getDescription(DiagID);
}
/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
DiagnosticIDs::Level DiagnosticIDs::getDiagnosticLevel(unsigned DiagID,
const Diagnostic &Diag) const {
// Handle custom diagnostics, which cannot be mapped.
if (DiagID >= diag::DIAG_UPPER_LIMIT)
return CustomDiagInfo->getLevel(DiagID);
unsigned DiagClass = getBuiltinDiagClass(DiagID);
assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
return getDiagnosticLevel(DiagID, DiagClass, Diag);
}
/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
DiagnosticIDs::Level
DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
const Diagnostic &Diag) const {
// Specific non-error diagnostics may be mapped to various levels from ignored
// to error. Errors can only be mapped to fatal.
DiagnosticIDs::Level Result = DiagnosticIDs::Fatal;
// Get the mapping information, if unset, compute it lazily.
unsigned MappingInfo = Diag.getDiagnosticMappingInfo((diag::kind)DiagID);
if (MappingInfo == 0) {
MappingInfo = GetDefaultDiagMapping(DiagID);
Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, false);
}
switch (MappingInfo & 7) {
default: assert(0 && "Unknown mapping!");
case diag::MAP_IGNORE:
// Ignore this, unless this is an extension diagnostic and we're mapping
// them onto warnings or errors.
if (!isBuiltinExtensionDiag(DiagID) || // Not an extension
Diag.ExtBehavior == Diagnostic::Ext_Ignore || // Ext ignored
(MappingInfo & 8) != 0) // User explicitly mapped it.
return DiagnosticIDs::Ignored;
Result = DiagnosticIDs::Warning;
if (Diag.ExtBehavior == Diagnostic::Ext_Error) Result = DiagnosticIDs::Error;
if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal)
Result = DiagnosticIDs::Fatal;
break;
case diag::MAP_ERROR:
Result = DiagnosticIDs::Error;
if (Diag.ErrorsAsFatal)
Result = DiagnosticIDs::Fatal;
break;
case diag::MAP_FATAL:
Result = DiagnosticIDs::Fatal;
break;
case diag::MAP_WARNING:
// If warnings are globally mapped to ignore or error, do it.
if (Diag.IgnoreAllWarnings)
return DiagnosticIDs::Ignored;
Result = DiagnosticIDs::Warning;
// If this is an extension diagnostic and we're in -pedantic-error mode, and
// if the user didn't explicitly map it, upgrade to an error.
if (Diag.ExtBehavior == Diagnostic::Ext_Error &&
(MappingInfo & 8) == 0 &&
isBuiltinExtensionDiag(DiagID))
Result = DiagnosticIDs::Error;
if (Diag.WarningsAsErrors)
Result = DiagnosticIDs::Error;
if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal)
Result = DiagnosticIDs::Fatal;
break;
case diag::MAP_WARNING_NO_WERROR:
// Diagnostics specified with -Wno-error=foo should be set to warnings, but
// not be adjusted by -Werror or -pedantic-errors.
Result = DiagnosticIDs::Warning;
// If warnings are globally mapped to ignore or error, do it.
if (Diag.IgnoreAllWarnings)
return DiagnosticIDs::Ignored;
break;
case diag::MAP_ERROR_NO_WFATAL:
// Diagnostics specified as -Wno-fatal-error=foo should be errors, but
// unaffected by -Wfatal-errors.
Result = DiagnosticIDs::Error;
break;
}
// Okay, we're about to return this as a "diagnostic to emit" one last check:
// if this is any sort of extension warning, and if we're in an __extension__
// block, silence it.
if (Diag.AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
return DiagnosticIDs::Ignored;
return Result;
}
struct WarningOption {
const char *Name;
const short *Members;
const short *SubGroups;
};
#define GET_DIAG_ARRAYS
#include "clang/Basic/DiagnosticGroups.inc"
#undef GET_DIAG_ARRAYS
// Second the table of options, sorted by name for fast binary lookup.
static const WarningOption OptionTable[] = {
#define GET_DIAG_TABLE
#include "clang/Basic/DiagnosticGroups.inc"
#undef GET_DIAG_TABLE
};
static const size_t OptionTableSize =
sizeof(OptionTable) / sizeof(OptionTable[0]);
static bool WarningOptionCompare(const WarningOption &LHS,
const WarningOption &RHS) {
return strcmp(LHS.Name, RHS.Name) < 0;
}
static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
Diagnostic &Diag) {
// Option exists, poke all the members of its diagnostic set.
if (const short *Member = Group->Members) {
for (; *Member != -1; ++Member)
Diag.setDiagnosticMapping(*Member, Mapping);
}
// Enable/disable all subgroups along with this one.
if (const short *SubGroups = Group->SubGroups) {
for (; *SubGroups != (short)-1; ++SubGroups)
MapGroupMembers(&OptionTable[(short)*SubGroups], Mapping, Diag);
}
}
/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
/// "unknown-pragmas" to have the specified mapping. This returns true and
/// ignores the request if "Group" was unknown, false otherwise.
bool DiagnosticIDs::setDiagnosticGroupMapping(const char *Group,
diag::Mapping Map,
Diagnostic &Diag) const {
WarningOption Key = { Group, 0, 0 };
const WarningOption *Found =
std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key,
WarningOptionCompare);
if (Found == OptionTable + OptionTableSize ||
strcmp(Found->Name, Group) != 0)
return true; // Option not found.
MapGroupMembers(Found, Map, Diag);
return false;
}
/// ProcessDiag - This is the method used to report a diagnostic that is
/// finally fully formed.
bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const {
DiagnosticInfo Info(&Diag);
if (Diag.SuppressAllDiagnostics)
return false;
assert(Diag.getClient() && "DiagnosticClient not set!");
// Figure out the diagnostic level of this message.
DiagnosticIDs::Level DiagLevel;
unsigned DiagID = Info.getID();
// ShouldEmitInSystemHeader - True if this diagnostic should be produced even
// in a system header.
bool ShouldEmitInSystemHeader;
if (DiagID >= diag::DIAG_UPPER_LIMIT) {
// Handle custom diagnostics, which cannot be mapped.
DiagLevel = CustomDiagInfo->getLevel(DiagID);
// Custom diagnostics always are emitted in system headers.
ShouldEmitInSystemHeader = true;
} else {
// Get the class of the diagnostic. If this is a NOTE, map it onto whatever
// the diagnostic level was for the previous diagnostic so that it is
// filtered the same as the previous diagnostic.
unsigned DiagClass = getBuiltinDiagClass(DiagID);
if (DiagClass == CLASS_NOTE) {
DiagLevel = DiagnosticIDs::Note;
ShouldEmitInSystemHeader = false; // extra consideration is needed
} else {
// If this is not an error and we are in a system header, we ignore it.
// Check 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.
ShouldEmitInSystemHeader = DiagClass == CLASS_ERROR;
DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Diag);
}
}
if (DiagLevel != DiagnosticIDs::Note) {
// Record that a fatal error occurred only when we see a second
// non-note diagnostic. This allows notes to be attached to the
// fatal error, but suppresses any diagnostics that follow those
// notes.
if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
Diag.FatalErrorOccurred = true;
Diag.LastDiagLevel = DiagLevel;
}
// If a fatal error has already been emitted, silence all subsequent
// diagnostics.
if (Diag.FatalErrorOccurred) {
if (DiagLevel >= DiagnosticIDs::Error &&
Diag.Client->IncludeInDiagnosticCounts()) {
++Diag.NumErrors;
++Diag.NumErrorsSuppressed;
}
return false;
}
// If the client doesn't care about this message, don't issue it. If this is
// a note and the last real diagnostic was ignored, ignore it too.
if (DiagLevel == DiagnosticIDs::Ignored ||
(DiagLevel == DiagnosticIDs::Note &&
Diag.LastDiagLevel == DiagnosticIDs::Ignored))
return false;
// If this diagnostic is in a system header and is not a clang error, suppress
// it.
if (Diag.SuppressSystemWarnings && !ShouldEmitInSystemHeader &&
Info.getLocation().isValid() &&
Diag.getSourceManager().isInSystemHeader(
Diag.getSourceManager().getInstantiationLoc(Info.getLocation())) &&
(DiagLevel != DiagnosticIDs::Note ||
Diag.LastDiagLevel == DiagnosticIDs::Ignored)) {
Diag.LastDiagLevel = DiagnosticIDs::Ignored;
return false;
}
if (DiagLevel >= DiagnosticIDs::Error) {
if (Diag.Client->IncludeInDiagnosticCounts()) {
Diag.ErrorOccurred = true;
++Diag.NumErrors;
}
// If we've emitted a lot of errors, emit a fatal error after it to stop a
// flood of bogus errors.
if (Diag.ErrorLimit && Diag.NumErrors >= Diag.ErrorLimit &&
DiagLevel == DiagnosticIDs::Error)
Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
}
// Finally, report it.
Diag.Client->HandleDiagnostic((Diagnostic::Level)DiagLevel, Info);
if (Diag.Client->IncludeInDiagnosticCounts()) {
if (DiagLevel == DiagnosticIDs::Warning)
++Diag.NumWarnings;
}
Diag.CurDiagID = ~0U;
return true;
}

View File

@ -100,7 +100,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
Diag.SetDelayedDiagnostic(diag::err_cannot_open_file,
Entry->getName(), ErrorStr);
else
Diag.Report(FullSourceLoc(Loc, SM), diag::err_cannot_open_file)
Diag.Report(Loc, diag::err_cannot_open_file)
<< Entry->getName() << ErrorStr;
Buffer.setInt(Buffer.getInt() | InvalidFlag);
@ -120,7 +120,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
Diag.SetDelayedDiagnostic(diag::err_file_modified,
Entry->getName());
else
Diag.Report(FullSourceLoc(Loc, SM), diag::err_file_modified)
Diag.Report(Loc, diag::err_file_modified)
<< Entry->getName();
Buffer.setInt(Buffer.getInt() | InvalidFlag);
@ -147,7 +147,7 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
.Default(0);
if (BOM) {
Diag.Report(FullSourceLoc(Loc, SM), diag::err_unsupported_bom)
Diag.Report(Loc, diag::err_unsupported_bom)
<< BOM << Entry->getName();
Buffer.setInt(1);
}
@ -342,6 +342,15 @@ LineTableInfo &SourceManager::getLineTable() {
// Private 'Create' methods.
//===----------------------------------------------------------------------===//
SourceManager::SourceManager(Diagnostic &Diag, FileManager &FileMgr,
const FileSystemOptions &FSOpts)
: Diag(Diag), FileMgr(FileMgr), FileSystemOpts(FSOpts),
ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
NumBinaryProbes(0) {
clearIDTables();
Diag.setSourceManager(this);
}
SourceManager::~SourceManager() {
delete LineTable;

View File

@ -104,7 +104,9 @@ void PathDiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
Info.FormatDiagnostic(StrC);
PathDiagnosticPiece *P =
new PathDiagnosticEventPiece(Info.getLocation(), StrC.str());
new PathDiagnosticEventPiece(FullSourceLoc(Info.getLocation(),
Info.getSourceManager()),
StrC.str());
for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i)
P->addRange(Info.getRange(i).getAsRange());

View File

@ -1529,7 +1529,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,
assert(Diag && "Fall through without a diagnostic?");
unsigned DiagID = CGM.getDiags().getCustomDiagID(Diagnostic::Error,
"debug information for %0 is not yet supported");
CGM.getDiags().Report(FullSourceLoc(), DiagID)
CGM.getDiags().Report(DiagID)
<< Diag;
return llvm::DIType();
}

View File

@ -209,8 +209,7 @@ void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
// issue as being an error in the source with a note showing the instantiated
// code.
if (LocCookie.isValid()) {
Diags.Report(FullSourceLoc(LocCookie, Context->getSourceManager()),
diag::err_fe_inline_asm).AddString(Message);
Diags.Report(LocCookie, diag::err_fe_inline_asm).AddString(Message);
if (D.getLoc().isValid())
Diags.Report(Loc, diag::note_fe_inline_asm_here);
@ -318,7 +317,7 @@ void CodeGenAction::ExecuteAction() {
unsigned DiagID = CI.getDiagnostics().getCustomDiagID(Diagnostic::Error,
Msg);
CI.getDiagnostics().Report(FullSourceLoc(Loc, SM), DiagID);
CI.getDiagnostics().Report(Loc, DiagID);
return;
}

View File

@ -525,7 +525,7 @@ void CXXNameMangler::mangleUnscopedTemplateName(TemplateName Template) {
Diagnostic &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
"cannot mangle dependent operator name");
Diags.Report(FullSourceLoc(), DiagID);
Diags.Report(DiagID);
return;
}
@ -1672,9 +1672,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
Diagnostic &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Error,
"cannot yet mangle expression type %0");
Diags.Report(FullSourceLoc(E->getExprLoc(),
getASTContext().getSourceManager()),
DiagID)
Diags.Report(E->getExprLoc(), DiagID)
<< E->getStmtClassName() << E->getSourceRange();
break;
}

View File

@ -404,7 +404,7 @@ void Driver::PrintVersion(const Compilation &C, llvm::raw_ostream &OS) const {
/// option.
static void PrintDiagnosticCategories(llvm::raw_ostream &OS) {
for (unsigned i = 1; // Skip the empty category.
const char *CategoryName = Diagnostic::getCategoryNameFromID(i); ++i)
const char *CategoryName = DiagnosticIDs::getCategoryNameFromID(i); ++i)
OS << i << ',' << CategoryName << '\n';
}

View File

@ -38,21 +38,18 @@ void ASTMergeAction::ExecuteAction() {
CI.getASTContext().getLangOptions());
CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
&CI.getASTContext());
llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics());
llvm::IntrusiveRefCntPtr<DiagnosticIDs>
DiagIDs(CI.getDiagnostics().getDiagnosticIDs());
for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
llvm::IntrusiveRefCntPtr<Diagnostic>
Diags(new Diagnostic(DiagIDs, CI.getDiagnostics().getClient(),
/*ShouldOwnClient=*/false));
ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags,
CI.getFileSystemOpts(), false);
if (!Unit)
continue;
// Reset the argument -> string function so that it has the AST
// context we want, since the Sema object created by
// LoadFromASTFile will override it.
CI.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument,
&CI.getASTContext());
ASTImporter Importer(CI.getDiagnostics(),
CI.getASTContext(),
ASTImporter Importer(CI.getASTContext(),
CI.getFileManager(),
CI.getFileSystemOpts(),
Unit->getASTContext(),
@ -72,6 +69,15 @@ void ASTMergeAction::ExecuteAction() {
Importer.Import(*D);
}
// Aggregate the number of warnings/errors from all diagnostics so
// that at CompilerInstance::ExecuteAction we can report the total numbers.
// FIXME: This is hacky, maybe keep track of total number of warnings/errors
// in DiagnosticClient and have CompilerInstance query that ?
CI.getDiagnostics().setNumWarnings(CI.getDiagnostics().getNumWarnings() +
Diags->getNumWarnings());
CI.getDiagnostics().setNumErrors(CI.getDiagnostics().getNumErrors() +
Diags->getNumErrors());
delete Unit;
}

View File

@ -122,7 +122,8 @@ llvm::IntrusiveRefCntPtr<Diagnostic>
CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
int Argc, const char* const *Argv,
DiagnosticClient *Client) {
llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic());
llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic(DiagID));
// Create the diagnostic client for reporting errors or for
// implementing -verify.

View File

@ -776,7 +776,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
// If the location is specified, print out a file/line/col and include trace
// if enabled.
if (Info.getLocation().isValid()) {
const SourceManager &SM = Info.getLocation().getManager();
const SourceManager &SM = Info.getSourceManager();
PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation());
if (PLoc.isInvalid())
return;
@ -884,7 +884,8 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
std::string OptionName;
if (DiagOpts->ShowOptionNames) {
if (const char *Opt = Diagnostic::getWarningOptionForDiag(Info.getID())) {
if (const char *
Opt = DiagnosticIDs::getWarningOptionForDiag(Info.getID())) {
OptionName = "-W";
OptionName += Opt;
} else if (Info.getID() == diag::fatal_too_many_errors) {
@ -893,7 +894,8 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
// If the diagnostic is an extension diagnostic and not enabled by default
// then it must have been turned on with -pedantic.
bool EnabledByDefault;
if (Diagnostic::isBuiltinExtensionDiag(Info.getID(), EnabledByDefault) &&
if (DiagnosticIDs::isBuiltinExtensionDiag(Info.getID(),
EnabledByDefault) &&
!EnabledByDefault)
OptionName = "-pedantic";
}
@ -902,7 +904,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
// If the user wants to see category information, include it too.
unsigned DiagCategory = 0;
if (DiagOpts->ShowCategories)
DiagCategory = Diagnostic::getCategoryNumberForDiag(Info.getID());
DiagCategory = DiagnosticIDs::getCategoryNumberForDiag(Info.getID());
// If there is any categorization information, include it.
if (!OptionName.empty() || DiagCategory != 0) {
@ -920,7 +922,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
OutStr += llvm::utostr(DiagCategory);
else {
assert(DiagOpts->ShowCategories == 2 && "Invalid ShowCategories value");
OutStr += Diagnostic::getCategoryNameFromID(DiagCategory);
OutStr += DiagnosticIDs::getCategoryNameFromID(DiagCategory);
}
}
@ -962,7 +964,7 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
(LastCaretDiagnosticWasNote && Level != Diagnostic::Note) ||
Info.getNumFixItHints())) {
// Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
LastLoc = Info.getLocation();
LastLoc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
LastCaretDiagnosticWasNote = (Level == Diagnostic::Note);
// Get the ranges into a local array we can hack on.

View File

@ -78,7 +78,7 @@ void PrettyStackTraceParserEntry::print(llvm::raw_ostream &OS) const {
DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(FullSourceLoc(Loc, PP.getSourceManager()), DiagID);
return Diags.Report(Loc, DiagID);
}
DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) {

View File

@ -141,7 +141,7 @@ void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel,
}
/// \brief Emit a diagnostic via the adapted diagnostic client.
void FixItRewriter::Diag(FullSourceLoc Loc, unsigned DiagID) {
void FixItRewriter::Diag(SourceLocation Loc, unsigned DiagID) {
// When producing this diagnostic, we temporarily bypass ourselves,
// clear out any current diagnostic, and let the downstream client
// format the diagnostic.

View File

@ -486,7 +486,8 @@ void html::HighlightMacros(Rewriter &R, FileID FID, const Preprocessor& PP) {
// Temporarily change the diagnostics object so that we ignore any generated
// diagnostics from this pass.
Diagnostic TmpDiags(new IgnoringDiagClient);
Diagnostic TmpDiags(PP.getDiagnostics().getDiagnosticIDs(),
new IgnoringDiagClient);
// FIXME: This is a huge hack; we reuse the input preprocessor because we want
// its state, but we aren't actually changing it (we hope). This should really

View File

@ -23,8 +23,8 @@ using namespace clang;
static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc,
SourceManager &SrcMgr, unsigned DiagID) {
return D.Report(FullSourceLoc(Loc, SrcMgr), DiagID);
unsigned DiagID) {
return D.Report(Loc, DiagID);
}
@ -512,28 +512,27 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
SaveStorageSpecifierAsWritten();
// Check the type specifier components first.
SourceManager &SrcMgr = PP.getSourceManager();
// Validate and finalize AltiVec vector declspec.
if (TypeAltiVecVector) {
if (TypeAltiVecBool) {
// Sign specifiers are not allowed with vector bool. (PIM 2.1)
if (TypeSpecSign != TSS_unspecified) {
Diag(D, TSSLoc, SrcMgr, diag::err_invalid_vector_bool_decl_spec)
Diag(D, TSSLoc, diag::err_invalid_vector_bool_decl_spec)
<< getSpecifierName((TSS)TypeSpecSign);
}
// Only char/int are valid with vector bool. (PIM 2.1)
if (((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) &&
(TypeSpecType != TST_int)) || TypeAltiVecPixel) {
Diag(D, TSTLoc, SrcMgr, diag::err_invalid_vector_bool_decl_spec)
Diag(D, TSTLoc, diag::err_invalid_vector_bool_decl_spec)
<< (TypeAltiVecPixel ? "__pixel" :
getSpecifierName((TST)TypeSpecType));
}
// Only 'short' is valid with vector bool. (PIM 2.1)
if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short))
Diag(D, TSWLoc, SrcMgr, diag::err_invalid_vector_bool_decl_spec)
Diag(D, TSWLoc, diag::err_invalid_vector_bool_decl_spec)
<< getSpecifierName((TSW)TypeSpecWidth);
// Elements of vector bool are interpreted as unsigned. (PIM 2.1)
@ -557,7 +556,7 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int.
else if (TypeSpecType != TST_int &&
TypeSpecType != TST_char && TypeSpecType != TST_wchar) {
Diag(D, TSSLoc, SrcMgr, diag::err_invalid_sign_spec)
Diag(D, TSSLoc, diag::err_invalid_sign_spec)
<< getSpecifierName((TST)TypeSpecType);
// signed double -> double.
TypeSpecSign = TSS_unspecified;
@ -572,7 +571,7 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // short -> short int, long long -> long long int.
else if (TypeSpecType != TST_int) {
Diag(D, TSWLoc, SrcMgr,
Diag(D, TSWLoc,
TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec
: diag::err_invalid_longlong_spec)
<< getSpecifierName((TST)TypeSpecType);
@ -584,7 +583,7 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
if (TypeSpecType == TST_unspecified)
TypeSpecType = TST_int; // long -> long int.
else if (TypeSpecType != TST_int && TypeSpecType != TST_double) {
Diag(D, TSWLoc, SrcMgr, diag::err_invalid_long_spec)
Diag(D, TSWLoc, diag::err_invalid_long_spec)
<< getSpecifierName((TST)TypeSpecType);
TypeSpecType = TST_int;
TypeSpecOwned = false;
@ -596,16 +595,16 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
// disallow their use. Need information about the backend.
if (TypeSpecComplex != TSC_unspecified) {
if (TypeSpecType == TST_unspecified) {
Diag(D, TSCLoc, SrcMgr, diag::ext_plain_complex)
Diag(D, TSCLoc, diag::ext_plain_complex)
<< FixItHint::CreateInsertion(
PP.getLocForEndOfToken(getTypeSpecComplexLoc()),
" double");
TypeSpecType = TST_double; // _Complex -> _Complex double.
} else if (TypeSpecType == TST_int || TypeSpecType == TST_char) {
// Note that this intentionally doesn't include _Complex _Bool.
Diag(D, TSTLoc, SrcMgr, diag::ext_integer_complex);
Diag(D, TSTLoc, diag::ext_integer_complex);
} else if (TypeSpecType != TST_float && TypeSpecType != TST_double) {
Diag(D, TSCLoc, SrcMgr, diag::err_invalid_complex_spec)
Diag(D, TSCLoc, diag::err_invalid_complex_spec)
<< getSpecifierName((TST)TypeSpecType);
TypeSpecComplex = TSC_unspecified;
}
@ -621,7 +620,7 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
SourceLocation SCLoc = getStorageClassSpecLoc();
SourceLocation SCEndLoc = SCLoc.getFileLocWithOffset(strlen(SpecName));
Diag(D, SCLoc, SrcMgr, diag::err_friend_storage_spec)
Diag(D, SCLoc, diag::err_friend_storage_spec)
<< SpecName
<< FixItHint::CreateRemoval(SourceRange(SCLoc, SCEndLoc));

View File

@ -438,12 +438,12 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
return;
if (TemplateDeductionInfo *Info = SemaRef.isSFINAEContext()) {
switch (Diagnostic::getDiagnosticSFINAEResponse(getDiagID())) {
case Diagnostic::SFINAE_Report:
switch (DiagnosticIDs::getDiagnosticSFINAEResponse(getDiagID())) {
case DiagnosticIDs::SFINAE_Report:
// Fall through; we'll report the diagnostic below.
break;
case Diagnostic::SFINAE_SubstitutionFailure:
case DiagnosticIDs::SFINAE_SubstitutionFailure:
// Count this failure so that we know that template argument deduction
// has failed.
++SemaRef.NumSFINAEErrors;
@ -452,7 +452,7 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
Clear();
return;
case Diagnostic::SFINAE_Suppress:
case DiagnosticIDs::SFINAE_Suppress:
// Make a copy of this suppressed diagnostic and store it with the
// template-deduction information;
FlushCounts();
@ -478,7 +478,7 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
// that is different from the last template instantiation where
// we emitted an error, print a template instantiation
// backtrace.
if (!SemaRef.Diags.isBuiltinNote(DiagID) &&
if (!DiagnosticIDs::isBuiltinNote(DiagID) &&
!SemaRef.ActiveTemplateInstantiations.empty() &&
SemaRef.ActiveTemplateInstantiations.back()
!= SemaRef.LastTemplateInstantiationErrorContext) {
@ -489,7 +489,7 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
}
Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID) {
DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
DiagnosticBuilder DB = Diags.Report(Loc, DiagID);
return SemaDiagnosticBuilder(DB, *this, DiagID);
}

View File

@ -382,7 +382,7 @@ void Sema::PrintInstantiationStack() {
if (InstantiationIdx >= SkipStart && InstantiationIdx < SkipEnd) {
if (InstantiationIdx == SkipStart) {
// Note that we're skipping instantiations.
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
Diags.Report(Active->PointOfInstantiation,
diag::note_instantiation_contexts_suppressed)
<< unsigned(ActiveTemplateInstantiations.size() - Limit);
}
@ -396,8 +396,7 @@ void Sema::PrintInstantiationStack() {
unsigned DiagID = diag::note_template_member_class_here;
if (isa<ClassTemplateSpecializationDecl>(Record))
DiagID = diag::note_template_class_instantiation_here;
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
DiagID)
Diags.Report(Active->PointOfInstantiation, DiagID)
<< Context.getTypeDeclType(Record)
<< Active->InstantiationRange;
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
@ -406,12 +405,11 @@ void Sema::PrintInstantiationStack() {
DiagID = diag::note_function_template_spec_here;
else
DiagID = diag::note_template_member_function_here;
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
DiagID)
Diags.Report(Active->PointOfInstantiation, DiagID)
<< Function
<< Active->InstantiationRange;
} else {
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
Diags.Report(Active->PointOfInstantiation,
diag::note_template_static_data_member_def_here)
<< cast<VarDecl>(D)
<< Active->InstantiationRange;
@ -426,7 +424,7 @@ void Sema::PrintInstantiationStack() {
Active->TemplateArgs,
Active->NumTemplateArgs,
Context.PrintingPolicy);
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
Diags.Report(Active->PointOfInstantiation,
diag::note_default_arg_instantiation_here)
<< (Template->getNameAsString() + TemplateArgsStr)
<< Active->InstantiationRange;
@ -436,7 +434,7 @@ void Sema::PrintInstantiationStack() {
case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: {
FunctionTemplateDecl *FnTmpl
= cast<FunctionTemplateDecl>((Decl *)Active->Entity);
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
Diags.Report(Active->PointOfInstantiation,
diag::note_explicit_template_arg_substitution_here)
<< FnTmpl
<< getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
@ -450,7 +448,7 @@ void Sema::PrintInstantiationStack() {
if (ClassTemplatePartialSpecializationDecl *PartialSpec
= dyn_cast<ClassTemplatePartialSpecializationDecl>(
(Decl *)Active->Entity)) {
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
Diags.Report(Active->PointOfInstantiation,
diag::note_partial_spec_deduct_instantiation_here)
<< Context.getTypeDeclType(PartialSpec)
<< getTemplateArgumentBindingsText(
@ -461,7 +459,7 @@ void Sema::PrintInstantiationStack() {
} else {
FunctionTemplateDecl *FnTmpl
= cast<FunctionTemplateDecl>((Decl *)Active->Entity);
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
Diags.Report(Active->PointOfInstantiation,
diag::note_function_template_deduction_instantiation_here)
<< FnTmpl
<< getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
@ -480,7 +478,7 @@ void Sema::PrintInstantiationStack() {
Active->TemplateArgs,
Active->NumTemplateArgs,
Context.PrintingPolicy);
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
Diags.Report(Active->PointOfInstantiation,
diag::note_default_function_arg_instantiation_here)
<< (FD->getNameAsString() + TemplateArgsStr)
<< Active->InstantiationRange;
@ -493,7 +491,7 @@ void Sema::PrintInstantiationStack() {
if (!Parm->getName().empty())
Name = std::string(" '") + Parm->getName().str() + "'";
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
Diags.Report(Active->PointOfInstantiation,
diag::note_prior_template_arg_substitution)
<< isa<TemplateTemplateParmDecl>(Parm)
<< Name
@ -506,7 +504,7 @@ void Sema::PrintInstantiationStack() {
}
case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: {
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
Diags.Report(Active->PointOfInstantiation,
diag::note_template_default_arg_checking)
<< getTemplateArgumentBindingsText(
Active->Template->getTemplateParameters(),

View File

@ -4383,7 +4383,7 @@ DiagnosticBuilder ASTReader::Diag(unsigned DiagID) {
}
DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
return Diags.Report(Loc, DiagID);
}
/// \brief Retrieve the identifier table associated with the

View File

@ -116,13 +116,14 @@ static int cc1_test(Diagnostic &Diags,
int cc1_main(const char **ArgBegin, const char **ArgEnd,
const char *Argv0, void *MainAddr) {
llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance());
llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
Clang->setLLVMContext(new llvm::LLVMContext());
// Run clang -cc1 test.
if (ArgBegin != ArgEnd && llvm::StringRef(ArgBegin[0]) == "-cc1test") {
Diagnostic Diags(new TextDiagnosticPrinter(llvm::errs(),
DiagnosticOptions()));
Diagnostic Diags(DiagID, new TextDiagnosticPrinter(llvm::errs(),
DiagnosticOptions()));
return cc1_test(Diags, ArgBegin + 1, ArgEnd);
}
@ -134,7 +135,7 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
// Buffer diagnostics from argument parsing so that we can output them using a
// well formed diagnostic object.
TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
Diagnostic Diags(DiagsBuffer);
Diagnostic Diags(DiagID, DiagsBuffer);
CompilerInvocation::CreateFromArgs(Clang->getInvocation(), ArgBegin, ArgEnd,
Diags);

View File

@ -326,7 +326,8 @@ int cc1as_main(const char **ArgBegin, const char **ArgEnd,
TextDiagnosticPrinter *DiagClient
= new TextDiagnosticPrinter(errs(), DiagnosticOptions());
DiagClient->setPrefix("clang -cc1as");
Diagnostic Diags(DiagClient);
llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
Diagnostic Diags(DiagID, DiagClient);
// Set an error handler, so that any LLVM backend diagnostics go through our
// error handler.

View File

@ -288,7 +288,8 @@ int main(int argc_, const char **argv_) {
TextDiagnosticPrinter *DiagClient
= new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
DiagClient->setPrefix(Path.getBasename());
Diagnostic Diags(DiagClient);
llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
Diagnostic Diags(DiagID, DiagClient);
#ifdef CLANG_IS_PRODUCTION
const bool IsProduction = true;

View File

@ -258,7 +258,9 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
static unsigned CodeCompletionResultObjects;
AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
: CXCodeCompleteResults(), Diag(new Diagnostic),
: CXCodeCompleteResults(),
Diag(new Diagnostic(
llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs))),
SourceMgr(*Diag, FileMgr, FileSystemOpts) {
if (getenv("LIBCLANG_OBJTRACKING")) {
++CodeCompletionResultObjects;