diff options
author | dim <dim@FreeBSD.org> | 2011-02-20 13:06:31 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-02-20 13:06:31 +0000 |
commit | 39fcc9a984e2820e4ea0fa2ac4abd17d9f3a31df (patch) | |
tree | a9243275843fbeaa590afc07ee888e006b8d54ea /include/clang/Basic/Diagnostic.h | |
parent | 69b4eca4a4255ba43baa5c1d9bbdec3ec17f479e (diff) | |
download | FreeBSD-src-39fcc9a984e2820e4ea0fa2ac4abd17d9f3a31df.zip FreeBSD-src-39fcc9a984e2820e4ea0fa2ac4abd17d9f3a31df.tar.gz |
Vendor import of clang trunk r126079:
http://llvm.org/svn/llvm-project/cfe/trunk@126079
Diffstat (limited to 'include/clang/Basic/Diagnostic.h')
-rw-r--r-- | include/clang/Basic/Diagnostic.h | 440 |
1 files changed, 225 insertions, 215 deletions
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 37d2694..19e7c91 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -14,76 +14,24 @@ #ifndef LLVM_CLANG_DIAGNOSTIC_H #define LLVM_CLANG_DIAGNOSTIC_H +#include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/StringRef.h" #include "llvm/Support/type_traits.h" -#include <string> -#include <vector> -#include <cassert> -namespace llvm { - template <typename T> class SmallVectorImpl; -} +#include <vector> +#include <list> 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 - }; - } + class DiagnosticErrorTrap; /// \brief Annotates a diagnostic with some code that should be /// inserted, removed, or replaced to fix the problem. @@ -153,12 +101,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 @@ -203,33 +156,94 @@ 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; - - /// DiagMappings - Mapping information for diagnostics. Mapping info is + llvm::IntrusiveRefCntPtr<DiagnosticIDs> Diags; + DiagnosticClient *Client; + bool OwnsDiagClient; + SourceManager *SourceMgr; + + /// \brief Mapping information for diagnostics. Mapping info is /// packed into four bits per diagnostic. The low three bits are the mapping /// (an instance of diag::Mapping), or zero if unset. The high bit is set /// when the mapping was established as a user mapping. If the high bit is /// clear, then the low bits are set to the default value, and should be /// mapped with -pedantic, -Werror, etc. - class DiagMappings { - unsigned char Values[diag::DIAG_UPPER_LIMIT/2]; + /// + /// A new DiagState is created and kept around when diagnostic pragmas modify + /// the state so that we know what is the diagnostic state at any given + /// source location. + class DiagState { + llvm::DenseMap<unsigned, unsigned> DiagMap; public: - DiagMappings() { - memset(Values, 0, diag::DIAG_UPPER_LIMIT/2); - } + typedef llvm::DenseMap<unsigned, unsigned>::const_iterator iterator; - void setMapping(diag::kind Diag, unsigned Map) { - size_t Shift = (Diag & 1)*4; - Values[Diag/2] = (Values[Diag/2] & ~(15 << Shift)) | (Map << Shift); - } + void setMapping(diag::kind Diag, unsigned Map) { DiagMap[Diag] = Map; } diag::Mapping getMapping(diag::kind Diag) const { - return (diag::Mapping)((Values[Diag/2] >> (Diag & 1)*4) & 15); + iterator I = DiagMap.find(Diag); + if (I != DiagMap.end()) + return (diag::Mapping)I->second; + return diag::Mapping(); + } + + iterator begin() const { return DiagMap.begin(); } + iterator end() const { return DiagMap.end(); } + }; + + /// \brief Keeps and automatically disposes all DiagStates that we create. + std::list<DiagState> DiagStates; + + /// \brief Represents a point in source where the diagnostic state was + /// modified because of a pragma. 'Loc' can be null if the point represents + /// the diagnostic state modifications done through the command-line. + struct DiagStatePoint { + DiagState *State; + FullSourceLoc Loc; + DiagStatePoint(DiagState *State, FullSourceLoc Loc) + : State(State), Loc(Loc) { } + + bool operator<(const DiagStatePoint &RHS) const { + // If Loc is invalid it means it came from <command-line>, in which case + // we regard it as coming before any valid source location. + if (RHS.Loc.isInvalid()) + return false; + if (Loc.isInvalid()) + return true; + return Loc.isBeforeInTranslationUnitThan(RHS.Loc); } }; - mutable std::vector<DiagMappings> DiagMappingsStack; + /// \brief A vector of all DiagStatePoints representing changes in diagnostic + /// state due to diagnostic pragmas. The vector is always sorted according to + /// the SourceLocation of the DiagStatePoint. + typedef std::vector<DiagStatePoint> DiagStatePointsTy; + mutable DiagStatePointsTy DiagStatePoints; + + /// \brief Keeps the DiagState that was active during each diagnostic 'push' + /// so we can get back at it when we 'pop'. + std::vector<DiagState *> DiagStateOnPushStack; + + DiagState *GetCurDiagState() const { + assert(!DiagStatePoints.empty()); + return DiagStatePoints.back().State; + } + + void PushDiagStatePoint(DiagState *State, SourceLocation L) { + FullSourceLoc Loc(L, *SourceMgr); + // Make sure that DiagStatePoints is always sorted according to Loc. + assert((Loc.isValid() || DiagStatePoints.empty()) && + "Adding invalid loc point after another point"); + assert((Loc.isInvalid() || DiagStatePoints.empty() || + DiagStatePoints.back().Loc.isInvalid() || + DiagStatePoints.back().Loc.isBeforeInTranslationUnitThan(Loc)) && + "Previous point loc comes after or is the same as new one"); + DiagStatePoints.push_back(DiagStatePoint(State, + FullSourceLoc(Loc, *SourceMgr))); + } + + /// \brief Finds the DiagStatePoint that contains the diagnostic state of + /// the given source location. + DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const; /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or /// fatal error is emitted, and is sticky. @@ -239,14 +253,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 @@ -279,34 +290,52 @@ private: std::string DelayedDiagArg2; public: - explicit Diagnostic(DiagnosticClient *client = 0); + explicit Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &Diags, + DiagnosticClient *client = 0, + bool ShouldOwnClient = true); ~Diagnostic(); - //===--------------------------------------------------------------------===// - // Diagnostic characterization methods, used by a client to customize how - // + const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const { + return Diags; + } + + DiagnosticClient *getClient() { return Client; } + const DiagnosticClient *getClient() const { return Client; } - 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(); } + 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. + // /// pushMappings - Copies the current DiagMappings and pushes the new copy /// onto the top of the stack. - void pushMappings(); + void pushMappings(SourceLocation Loc); /// popMappings - Pops the current DiagMappings off the top of the stack /// causing the new top of the stack to be the active mappings. Returns /// true if the pop happens, false if there is only one DiagMapping on the /// stack. - bool popMappings(); + bool popMappings(SourceLocation Loc); /// \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); /// setErrorLimit - Specify a limit for the number of errors we should /// emit before giving up. Zero disables the limit. @@ -362,7 +391,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 @@ -379,28 +408,29 @@ public: void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; } bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; } - /// setDiagnosticMapping - This allows the client to specify that certain + /// \brief This allows the client to specify that certain /// warnings are ignored. Notes can never be mapped, errors can only be /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily. - void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map) { - assert(Diag < diag::DIAG_UPPER_LIMIT && - "Can only map builtin diagnostics"); - assert((isBuiltinWarningOrExtension(Diag) || - (Map == diag::MAP_FATAL || Map == diag::MAP_ERROR)) && - "Cannot map errors into warnings!"); - setDiagnosticMappingInternal(Diag, Map, true); - } + /// + /// \param Loc The source location that this change of diagnostic state should + /// take affect. It can be null if we are setting the latest state. + void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map, + SourceLocation Loc); /// 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); + /// + /// 'Loc' is the source location that this change of diagnostic state should + /// take affect. It can be null if we are setting the state from command-line. + bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map, + SourceLocation Loc = SourceLocation()) { + return Diags->setDiagnosticGroupMapping(Group, Map, Loc, *this); + } bool hasErrorOccurred() const { return ErrorOccurred; } bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } - unsigned getNumErrors() const { return NumErrors; } - unsigned getNumErrorsSuppressed() const { return NumErrorsSuppressed; } unsigned getNumWarnings() const { return NumWarnings; } void setNumWarnings(unsigned NumWarnings) { @@ -410,8 +440,9 @@ public: /// 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. @@ -437,92 +468,22 @@ 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 + /// \brief 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; + /// + /// \param Loc The source location we are interested in finding out the + /// diagnostic state. Can be null in order to query the latest state. + Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const { + return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *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. @@ -563,32 +524,34 @@ private: /// getDiagnosticMappingInfo - Return the mapping info currently set for the /// specified builtin diagnostic. This returns the high bit encoding, or zero /// if the field is completely uninitialized. - diag::Mapping getDiagnosticMappingInfo(diag::kind Diag) const { - return DiagMappingsStack.back().getMapping(Diag); + diag::Mapping getDiagnosticMappingInfo(diag::kind Diag, + DiagState *State) const { + return State->getMapping(Diag); } void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map, - bool isUser) const { + DiagState *State, + bool isUser, bool isPragma) const { if (isUser) Map |= 8; // Set the high bit for user mappings. - DiagMappingsStack.back().setMapping((diag::kind)DiagId, Map); + if (isPragma) Map |= 0x10; // Set the bit for diagnostic pragma mappings. + State->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; + friend class DiagnosticErrorTrap; + /// 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 +603,33 @@ 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; +}; + +/// \brief RAII class that determines when any errors have occurred +/// between the time the instance was created and the time it was +/// queried. +class DiagnosticErrorTrap { + Diagnostic &Diag; + unsigned PrevErrors; + +public: + explicit DiagnosticErrorTrap(Diagnostic &Diag) + : Diag(Diag), PrevErrors(Diag.NumErrors) {} + + /// \brief Determine whether any errors have occurred since this + /// object instance was created. + bool hasErrorOccurred() const { + return Diag.NumErrors > PrevErrors; + } + + // Set to initial state of "no errors occurred". + void reset() { PrevErrors = Diag.NumErrors; } }; //===----------------------------------------------------------------------===// @@ -667,6 +656,11 @@ class DiagnosticBuilder { explicit DiagnosticBuilder(Diagnostic *diagObj) : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixItHints(0) {} + friend class PartialDiagnostic; + +protected: + void FlushCounts(); + public: /// Copy constructor. When copied, this "takes" the diagnostic info from the /// input and neuters it. @@ -703,6 +697,17 @@ public: /// isActive - Determine whether this diagnostic is still active. bool isActive() const { return DiagObj != 0; } + /// \brief Retrieve the active diagnostic ID. + /// + /// \pre \c isActive() + unsigned getDiagID() const { + assert(isActive() && "Diagnostic is inactive"); + return DiagObj->CurDiagID; + } + + /// \brief Clear out the current diagnostic. + void Clear() { DiagObj = 0; } + /// Operator bool: conversion of DiagnosticBuilder to bool always returns /// true. This allows is to be used in boolean error contexts like: /// return Diag(...); @@ -816,14 +821,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); } //===----------------------------------------------------------------------===// @@ -840,7 +846,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; } @@ -930,10 +938,11 @@ public: }; /** - * \brief Represents a diagnostic in a form that can be serialized and - * deserialized. + * \brief Represents a diagnostic in a form that can be retained until its + * corresponding source manager is destroyed. */ class StoredDiagnostic { + unsigned ID; Diagnostic::Level Level; FullSourceLoc Loc; std::string Message; @@ -943,12 +952,14 @@ class StoredDiagnostic { public: StoredDiagnostic(); StoredDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info); - StoredDiagnostic(Diagnostic::Level Level, llvm::StringRef Message); + StoredDiagnostic(Diagnostic::Level Level, unsigned ID, + llvm::StringRef Message); ~StoredDiagnostic(); /// \brief Evaluates true when this object stores a diagnostic. operator bool() const { return Message.size() > 0; } + unsigned getID() const { return ID; } Diagnostic::Level getLevel() const { return Level; } const FullSourceLoc &getLocation() const { return Loc; } llvm::StringRef getMessage() const { return Message; } @@ -964,25 +975,21 @@ public: fixit_iterator fixit_begin() const { return FixIts.begin(); } fixit_iterator fixit_end() const { return FixIts.end(); } unsigned fixit_size() const { return FixIts.size(); } - - /// Serialize - Serialize the given diagnostic (with its diagnostic - /// level) to the given stream. Serialization is a lossy operation, - /// since the specific diagnostic ID and any macro-instantiation - /// information is lost. - void Serialize(llvm::raw_ostream &OS) const; - - /// Deserialize - Deserialize the first diagnostic within the memory - /// [Memory, MemoryEnd), producing a new diagnostic builder describing the - /// deserialized diagnostic. If the memory does not contain a - /// diagnostic, returns a diagnostic builder with no diagnostic ID. - static StoredDiagnostic Deserialize(FileManager &FM, SourceManager &SM, - const char *&Memory, const char *MemoryEnd); }; /// DiagnosticClient - This is an abstract interface implemented by clients of /// the front-end, which formats and prints fully processed diagnostics. class DiagnosticClient { +protected: + unsigned NumWarnings; // Number of warnings reported + unsigned NumErrors; // Number of errors reported + public: + DiagnosticClient() : NumWarnings(0), NumErrors(0) { } + + unsigned getNumErrors() const { return NumErrors; } + unsigned getNumWarnings() const { return NumWarnings; } + virtual ~DiagnosticClient(); /// BeginSourceFile - Callback to inform the diagnostic client that processing @@ -1012,8 +1019,11 @@ public: /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or /// capturing it to a log as needed. + /// + /// Default implementation just keeps track of the total number of warnings + /// and errors. virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, - const DiagnosticInfo &Info) = 0; + const DiagnosticInfo &Info); }; } // end namespace clang |