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:
parent
4fadc5b20a
commit
d004064864
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue