zcov: / include/clang/Basic/Diagnostic.h


Files: 1 Branches Taken: 67.6% 23 / 34
Generated: 2010-02-10 01:31 Branches Executed: 79.4% 27 / 34
Line Coverage: 99.5% 181 / 182


Programs: 163 Runs 269563


       1                 : //===--- Diagnostic.h - C Language Family Diagnostic Handling ---*- C++ -*-===//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : //  This file defines the Diagnostic-related interfaces.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #ifndef LLVM_CLANG_DIAGNOSTIC_H
      15                 : #define LLVM_CLANG_DIAGNOSTIC_H
      16                 : 
      17                 : #include "clang/Basic/SourceLocation.h"
      18                 : #include "llvm/ADT/StringRef.h"
      19                 : #include "llvm/Support/type_traits.h"
      20                 : #include <string>
      21                 : #include <vector>
      22                 : #include <cassert>
      23                 : 
      24                 : namespace llvm {
      25                 :   template <typename T> class SmallVectorImpl;
      26                 :   class raw_ostream;
      27                 : }
      28                 : 
      29                 : namespace clang {
      30                 :   class DeclContext;
      31                 :   class DiagnosticBuilder;
      32                 :   class DiagnosticClient;
      33                 :   class FileManager;
      34                 :   class IdentifierInfo;
      35                 :   class LangOptions;
      36                 :   class PartialDiagnostic;
      37                 :   class Preprocessor;
      38                 :   class SourceManager;
      39                 :   class SourceRange;
      40                 : 
      41                 :   // Import the diagnostic enums themselves.
      42                 :   namespace diag {
      43                 :     // Start position for diagnostics.
      44                 :     enum {
      45                 :       DIAG_START_DRIVER   =                        300,
      46                 :       DIAG_START_FRONTEND = DIAG_START_DRIVER   +  100,
      47                 :       DIAG_START_LEX      = DIAG_START_FRONTEND +  100,
      48                 :       DIAG_START_PARSE    = DIAG_START_LEX      +  300,
      49                 :       DIAG_START_AST      = DIAG_START_PARSE    +  300,
      50                 :       DIAG_START_SEMA     = DIAG_START_AST      +  100,
      51                 :       DIAG_START_ANALYSIS = DIAG_START_SEMA     + 1500,
      52                 :       DIAG_UPPER_LIMIT    = DIAG_START_ANALYSIS +  100
      53                 :     };
      54                 : 
      55                 :     class CustomDiagInfo;
      56                 : 
      57                 :     /// diag::kind - All of the diagnostics that can be emitted by the frontend.
      58                 :     typedef unsigned kind;
      59                 : 
      60                 :     // Get typedefs for common diagnostics.
      61                 :     enum {
      62                 : #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM,
      63                 : #include "clang/Basic/DiagnosticCommonKinds.inc"
      64                 :       NUM_BUILTIN_COMMON_DIAGNOSTICS
      65                 : #undef DIAG
      66                 :     };
      67                 : 
      68                 :     /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
      69                 :     /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
      70                 :     /// (emit as an error).  It allows clients to map errors to
      71                 :     /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this
      72                 :     /// one).
      73                 :     enum Mapping {
      74                 :       // NOTE: 0 means "uncomputed".
      75                 :       MAP_IGNORE  = 1,     //< Map this diagnostic to nothing, ignore it.
      76                 :       MAP_WARNING = 2,     //< Map this diagnostic to a warning.
      77                 :       MAP_ERROR   = 3,     //< Map this diagnostic to an error.
      78                 :       MAP_FATAL   = 4,     //< Map this diagnostic to a fatal error.
      79                 : 
      80                 :       /// Map this diagnostic to "warning", but make it immune to -Werror.  This
      81                 :       /// happens when you specify -Wno-error=foo.
      82                 :       MAP_WARNING_NO_WERROR = 5,
      83                 :       /// Map this diagnostic to "error", but make it immune to -Wfatal-errors.
      84                 :       /// This happens for -Wno-fatal-errors=foo.
      85                 :       MAP_ERROR_NO_WFATAL = 6
      86                 :     };
      87                 :   }
      88                 : 
      89                 : /// \brief Annotates a diagnostic with some code that should be
      90                 : /// inserted, removed, or replaced to fix the problem.
      91                 : ///
      92                 : /// This kind of hint should be used when we are certain that the
      93                 : /// introduction, removal, or modification of a particular (small!)
      94                 : /// amount of code will correct a compilation error. The compiler
      95                 : /// should also provide full recovery from such errors, such that
      96                 : /// suppressing the diagnostic output can still result in successful
      97                 : /// compilation.
      98           258521: class CodeModificationHint {
      99                 : public:
     100                 :   /// \brief Tokens that should be removed to correct the error.
     101                 :   SourceRange RemoveRange;
     102                 : 
     103                 :   /// \brief The location at which we should insert code to correct
     104                 :   /// the error.
     105                 :   SourceLocation InsertionLoc;
     106                 : 
     107                 :   /// \brief The actual code to insert at the insertion location, as a
     108                 :   /// string.
     109                 :   std::string CodeToInsert;
     110                 : 
     111                 :   /// \brief Empty code modification hint, indicating that no code
     112                 :   /// modification is known.
     113           257216:   CodeModificationHint() : RemoveRange(), InsertionLoc() { }
     114                 : 
     115              898:   bool isNull() const {
                      594: branch 1 taken
                      304: branch 2 taken
                      298: branch 4 taken
                      296: branch 5 taken
     116              898:     return !RemoveRange.isValid() && !InsertionLoc.isValid();
     117                 :   }
     118                 :   
     119                 :   /// \brief Create a code modification hint that inserts the given
     120                 :   /// code string at a specific location.
     121                 :   static CodeModificationHint CreateInsertion(SourceLocation InsertionLoc,
     122              287:                                               llvm::StringRef Code) {
     123              287:     CodeModificationHint Hint;
     124              287:     Hint.InsertionLoc = InsertionLoc;
     125              287:     Hint.CodeToInsert = Code;
     126                 :     return Hint;
     127                 :   }
     128                 : 
     129                 :   /// \brief Create a code modification hint that removes the given
     130                 :   /// source range.
     131              177:   static CodeModificationHint CreateRemoval(SourceRange RemoveRange) {
     132              177:     CodeModificationHint Hint;
     133              177:     Hint.RemoveRange = RemoveRange;
     134                 :     return Hint;
     135                 :   }
     136                 : 
     137                 :   /// \brief Create a code modification hint that replaces the given
     138                 :   /// source range with the given code string.
     139                 :   static CodeModificationHint CreateReplacement(SourceRange RemoveRange,
     140              121:                                                 llvm::StringRef Code) {
     141              121:     CodeModificationHint Hint;
     142              121:     Hint.RemoveRange = RemoveRange;
     143              121:     Hint.InsertionLoc = RemoveRange.getBegin();
     144              121:     Hint.CodeToInsert = Code;
     145                 :     return Hint;
     146                 :   }
     147                 : };
     148                 : 
     149                 : /// Diagnostic - This concrete class is used by the front-end to report
     150                 : /// problems and issues.  It massages the diagnostics (e.g. handling things like
     151                 : /// "report warnings as errors" and passes them off to the DiagnosticClient for
     152                 : /// reporting to the user.
     153                 : class Diagnostic {
     154                 : public:
     155                 :   /// Level - The level of the diagnostic, after it has been through mapping.
     156                 :   enum Level {
     157                 :     Ignored, Note, Warning, Error, Fatal
     158                 :   };
     159                 : 
     160                 :   /// ExtensionHandling - How do we handle otherwise-unmapped extension?  This
     161                 :   /// is controlled by -pedantic and -pedantic-errors.
     162                 :   enum ExtensionHandling {
     163                 :     Ext_Ignore, Ext_Warn, Ext_Error
     164                 :   };
     165                 : 
     166                 :   enum ArgumentKind {
     167                 :     ak_std_string,      // std::string
     168                 :     ak_c_string,        // const char *
     169                 :     ak_sint,            // int
     170                 :     ak_uint,            // unsigned
     171                 :     ak_identifierinfo,  // IdentifierInfo
     172                 :     ak_qualtype,        // QualType
     173                 :     ak_declarationname, // DeclarationName
     174                 :     ak_nameddecl,       // NamedDecl *
     175                 :     ak_nestednamespec,  // NestedNameSpecifier *
     176                 :     ak_declcontext      // DeclContext *
     177                 :   };
     178                 :   
     179                 :   /// ArgumentValue - This typedef represents on argument value, which is a
     180                 :   /// union discriminated by ArgumentKind, with a value.
     181                 :   typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;
     182                 : 
     183                 : private:
     184                 :   unsigned char AllExtensionsSilenced; // Used by __extension__
     185                 :   bool IgnoreAllWarnings;        // Ignore all warnings: -w
     186                 :   bool WarningsAsErrors;         // Treat warnings like errors:
     187                 :   bool ErrorsAsFatal;            // Treat errors like fatal errors.
     188                 :   bool SuppressSystemWarnings;   // Suppress warnings in system headers.
     189                 :   bool SuppressAllDiagnostics;   // Suppress all diagnostics.
     190                 :   ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
     191                 :   DiagnosticClient *Client;
     192                 : 
     193                 :   /// DiagMappings - Mapping information for diagnostics.  Mapping info is
     194                 :   /// packed into four bits per diagnostic.  The low three bits are the mapping
     195                 :   /// (an instance of diag::Mapping), or zero if unset.  The high bit is set
     196                 :   /// when the mapping was established as a user mapping.  If the high bit is
     197                 :   /// clear, then the low bits are set to the default value, and should be
     198                 :   /// mapped with -pedantic, -Werror, etc.
     199                 : 
     200                 :   typedef std::vector<unsigned char> DiagMappings;
     201                 :   mutable std::vector<DiagMappings> DiagMappingsStack;
     202                 : 
     203                 :   /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
     204                 :   /// fatal error is emitted, and is sticky.
     205                 :   bool ErrorOccurred;
     206                 :   bool FatalErrorOccurred;
     207                 : 
     208                 :   /// LastDiagLevel - This is the level of the last diagnostic emitted.  This is
     209                 :   /// used to emit continuation diagnostics with the same level as the
     210                 :   /// diagnostic that they follow.
     211                 :   Diagnostic::Level LastDiagLevel;
     212                 : 
     213                 :   unsigned NumDiagnostics;    // Number of diagnostics reported
     214                 :   unsigned NumErrors;         // Number of diagnostics that are errors
     215                 : 
     216                 :   /// CustomDiagInfo - Information for uniquing and looking up custom diags.
     217                 :   diag::CustomDiagInfo *CustomDiagInfo;
     218                 : 
     219                 :   /// ArgToStringFn - A function pointer that converts an opaque diagnostic
     220                 :   /// argument to a strings.  This takes the modifiers and argument that was
     221                 :   /// present in the diagnostic.
     222                 :   ///
     223                 :   /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous
     224                 :   /// arguments formatted for this diagnostic.  Implementations of this function
     225                 :   /// can use this information to avoid redundancy across arguments.
     226                 :   ///
     227                 :   /// This is a hack to avoid a layering violation between libbasic and libsema.
     228                 :   typedef void (*ArgToStringFnTy)(ArgumentKind Kind, intptr_t Val,
     229                 :                                   const char *Modifier, unsigned ModifierLen,
     230                 :                                   const char *Argument, unsigned ArgumentLen,
     231                 :                                   const ArgumentValue *PrevArgs,
     232                 :                                   unsigned NumPrevArgs,
     233                 :                                   llvm::SmallVectorImpl<char> &Output,
     234                 :                                   void *Cookie);
     235                 :   void *ArgToStringCookie;
     236                 :   ArgToStringFnTy ArgToStringFn;
     237                 : public:
     238                 :   explicit Diagnostic(DiagnosticClient *client = 0);
     239                 :   ~Diagnostic();
     240                 : 
     241                 :   //===--------------------------------------------------------------------===//
     242                 :   //  Diagnostic characterization methods, used by a client to customize how
     243                 :   //
     244                 : 
     245             6558:   DiagnosticClient *getClient() { return Client; }
     246                 :   const DiagnosticClient *getClient() const { return Client; }
     247                 : 
     248                 :   /// pushMappings - Copies the current DiagMappings and pushes the new copy
     249                 :   /// onto the top of the stack.
     250                 :   void pushMappings();
     251                 : 
     252                 :   /// popMappings - Pops the current DiagMappings off the top of the stack
     253                 :   /// causing the new top of the stack to be the active mappings. Returns
     254                 :   /// true if the pop happens, false if there is only one DiagMapping on the
     255                 :   /// stack.
     256                 :   bool popMappings();
     257                 : 
     258            10676:   void setClient(DiagnosticClient* client) { Client = client; }
     259                 : 
     260                 :   /// setIgnoreAllWarnings - When set to true, any unmapped warnings are
     261                 :   /// ignored.  If this and WarningsAsErrors are both set, then this one wins.
     262             2583:   void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
     263                 :   bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }
     264                 : 
     265                 :   /// setWarningsAsErrors - When set to true, any warnings reported are issued
     266                 :   /// as errors.
     267              210:   void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
     268                 :   bool getWarningsAsErrors() const { return WarningsAsErrors; }
     269                 : 
     270                 :   /// setErrorsAsFatal - When set to true, any error reported is made a
     271                 :   /// fatal error.
     272                0:   void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; }
     273                 :   bool getErrorsAsFatal() const { return ErrorsAsFatal; }
     274                 : 
     275                 :   /// setSuppressSystemWarnings - When set to true mask warnings that
     276                 :   /// come from system headers.
     277             2583:   void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
     278              595:   bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
     279                 : 
     280                 :   /// \brief Suppress all diagnostics, to silence the front end when we 
     281                 :   /// know that we don't want any more diagnostics to be passed along to the
     282                 :   /// client
     283               87:   void setSuppressAllDiagnostics(bool Val = true) { 
     284               87:     SuppressAllDiagnostics = Val; 
     285               87:   }
     286                 :   bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }
     287                 :   
     288                 :   /// \brief Pretend that the last diagnostic issued was ignored. This can
     289                 :   /// be used by clients who suppress diagnostics themselves.
     290               24:   void setLastDiagnosticIgnored() {
     291               24:     LastDiagLevel = Ignored;
     292               24:   }
     293                 :   
     294                 :   /// setExtensionHandlingBehavior - This controls whether otherwise-unmapped
     295                 :   /// extension diagnostics are mapped onto ignore/warning/error.  This
     296                 :   /// corresponds to the GCC -pedantic and -pedantic-errors option.
     297             2583:   void setExtensionHandlingBehavior(ExtensionHandling H) {
     298             2583:     ExtBehavior = H;
     299             2583:   }
     300                 : 
     301                 :   /// AllExtensionsSilenced - This is a counter bumped when an __extension__
     302                 :   /// block is encountered.  When non-zero, all extension diagnostics are
     303                 :   /// entirely silenced, no matter how they are mapped.
     304              549:   void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; }
     305              549:   void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
     306            82058:   bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; }
     307                 : 
     308                 :   /// setDiagnosticMapping - This allows the client to specify that certain
     309                 :   /// warnings are ignored.  Notes can never be mapped, errors can only be
     310                 :   /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily.
     311              698:   void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map) {
     312                 :     assert(Diag < diag::DIAG_UPPER_LIMIT &&
                        0: branch 0 not taken
                      698: branch 1 taken
     313              698:            "Can only map builtin diagnostics");
     314                 :     assert((isBuiltinWarningOrExtension(Diag) || Map == diag::MAP_FATAL) &&
                        0: branch 1 not taken
                      698: branch 2 taken
                      698: branch 3 taken
                      698: branch 4 taken
     315              698:            "Cannot map errors!");
     316              698:     setDiagnosticMappingInternal(Diag, Map, true);
     317              698:   }
     318                 : 
     319                 :   /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
     320                 :   /// "unknown-pragmas" to have the specified mapping.  This returns true and
     321                 :   /// ignores the request if "Group" was unknown, false otherwise.
     322                 :   bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map);
     323                 : 
     324            39275:   bool hasErrorOccurred() const { return ErrorOccurred; }
     325              206:   bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
     326                 : 
     327             6662:   unsigned getNumErrors() const { return NumErrors; }
     328             2511:   unsigned getNumDiagnostics() const { return NumDiagnostics; }
     329                 : 
     330                 :   /// getCustomDiagID - Return an ID for a diagnostic with the specified message
     331                 :   /// and level.  If this is the first request for this diagnosic, it is
     332                 :   /// registered and created, otherwise the existing ID is returned.
     333                 :   unsigned getCustomDiagID(Level L, llvm::StringRef Message);
     334                 : 
     335                 : 
     336                 :   /// ConvertArgToString - This method converts a diagnostic argument (as an
     337                 :   /// intptr_t) into the string that represents it.
     338                 :   void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
     339                 :                           const char *Modifier, unsigned ModLen,
     340                 :                           const char *Argument, unsigned ArgLen,
     341                 :                           const ArgumentValue *PrevArgs, unsigned NumPrevArgs,
     342             4577:                           llvm::SmallVectorImpl<char> &Output) const {
     343                 :     ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen,
     344             4577:                   PrevArgs, NumPrevArgs, Output, ArgToStringCookie);
     345             4577:   }
     346                 : 
     347             2239:   void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
     348             2239:     ArgToStringFn = Fn;
     349             2239:     ArgToStringCookie = Cookie;
     350             2239:   }
     351                 : 
     352                 :   //===--------------------------------------------------------------------===//
     353                 :   // Diagnostic classification and reporting interfaces.
     354                 :   //
     355                 : 
     356                 :   /// getDescription - Given a diagnostic ID, return a description of the
     357                 :   /// issue.
     358                 :   const char *getDescription(unsigned DiagID) const;
     359                 : 
     360                 :   /// isNoteWarningOrExtension - Return true if the unmapped diagnostic
     361                 :   /// level of the specified diagnostic ID is a Warning or Extension.
     362                 :   /// This only works on builtin diagnostics, not custom ones, and is not legal to
     363                 :   /// call on NOTEs.
     364                 :   static bool isBuiltinWarningOrExtension(unsigned DiagID);
     365                 : 
     366                 :   /// \brief Determine whether the given built-in diagnostic ID is a
     367                 :   /// Note.
     368                 :   static bool isBuiltinNote(unsigned DiagID);
     369                 : 
     370                 :   /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
     371                 :   /// ID is for an extension of some sort.
     372                 :   ///
     373                 :   static bool isBuiltinExtensionDiag(unsigned DiagID);
     374                 : 
     375                 :   /// getWarningOptionForDiag - Return the lowest-level warning option that
     376                 :   /// enables the specified diagnostic.  If there is no -Wfoo flag that controls
     377                 :   /// the diagnostic, this returns null.
     378                 :   static const char *getWarningOptionForDiag(unsigned DiagID);
     379                 : 
     380                 :   /// \brief Determines whether the given built-in diagnostic ID is
     381                 :   /// for an error that is suppressed if it occurs during C++ template
     382                 :   /// argument deduction.
     383                 :   ///
     384                 :   /// When an error is suppressed due to SFINAE, the template argument
     385                 :   /// deduction fails but no diagnostic is emitted. Certain classes of
     386                 :   /// errors, such as those errors that involve C++ access control,
     387                 :   /// are not SFINAE errors.
     388                 :   static bool isBuiltinSFINAEDiag(unsigned DiagID);
     389                 : 
     390                 :   /// getDiagnosticLevel - Based on the way the client configured the Diagnostic
     391                 :   /// object, classify the specified diagnostic ID into a Level, consumable by
     392                 :   /// the DiagnosticClient.
     393                 :   Level getDiagnosticLevel(unsigned DiagID) const;
     394                 : 
     395                 :   /// Report - Issue the message to the client.  @c DiagID is a member of the
     396                 :   /// @c diag::kind enum.  This actually returns aninstance of DiagnosticBuilder
     397                 :   /// which emits the diagnostics (through @c ProcessDiag) when it is destroyed.
     398                 :   /// @c Pos represents the source location associated with the diagnostic,
     399                 :   /// which can be an invalid location if no position information is available.
     400                 :   inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID);
     401                 :   inline DiagnosticBuilder Report(unsigned DiagID);
     402                 : 
     403                 :   /// \brief Clear out the current diagnostic.
     404            18948:   void Clear() { CurDiagID = ~0U; }
     405                 : 
     406                 :   /// Deserialize - Deserialize the first diagnostic within the memory
     407                 :   /// [Memory, MemoryEnd), producing a new diagnostic builder describing the
     408                 :   /// deserialized diagnostic. If the memory does not contain a
     409                 :   /// diagnostic, returns a diagnostic builder with no diagnostic ID.
     410                 :   DiagnosticBuilder Deserialize(FileManager &FM, SourceManager &SM, 
     411                 :                                 const char *&Memory, const char *MemoryEnd);
     412                 : 
     413                 : private:
     414                 :   /// getDiagnosticMappingInfo - Return the mapping info currently set for the
     415                 :   /// specified builtin diagnostic.  This returns the high bit encoding, or zero
     416                 :   /// if the field is completely uninitialized.
     417            41421:   unsigned getDiagnosticMappingInfo(diag::kind Diag) const {
     418            41421:     const DiagMappings &currentMappings = DiagMappingsStack.back();
     419            41421:     return (diag::Mapping)((currentMappings[Diag/2] >> (Diag & 1)*4) & 15);
     420                 :   }
     421                 : 
     422                 :   void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map,
     423            13663:                                     bool isUser) const {
                      698: branch 0 taken
                    12965: branch 1 taken
     424            13663:     if (isUser) Map |= 8;  // Set the high bit for user mappings.
     425            13663:     unsigned char &Slot = DiagMappingsStack.back()[DiagId/2];
     426            13663:     unsigned Shift = (DiagId & 1)*4;
     427            13663:     Slot &= ~(15 << Shift);
     428            13663:     Slot |= Map << Shift;
     429            13663:   }
     430                 : 
     431                 :   /// getDiagnosticLevel - This is an internal implementation helper used when
     432                 :   /// DiagClass is already known.
     433                 :   Level getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const;
     434                 : 
     435                 :   // This is private state used by DiagnosticBuilder.  We put it here instead of
     436                 :   // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
     437                 :   // object.  This implementation choice means that we can only have one
     438                 :   // diagnostic "in flight" at a time, but this seems to be a reasonable
     439                 :   // tradeoff to keep these objects small.  Assertions verify that only one
     440                 :   // diagnostic is in flight at a time.
     441                 :   friend class DiagnosticBuilder;
     442                 :   friend class DiagnosticInfo;
     443                 : 
     444                 :   /// CurDiagLoc - This is the location of the current diagnostic that is in
     445                 :   /// flight.
     446                 :   FullSourceLoc CurDiagLoc;
     447                 : 
     448                 :   /// CurDiagID - This is the ID of the current diagnostic that is in flight.
     449                 :   /// This is set to ~0U when there is no diagnostic in flight.
     450                 :   unsigned CurDiagID;
     451                 : 
     452                 :   enum {
     453                 :     /// MaxArguments - The maximum number of arguments we can hold. We currently
     454                 :     /// only support up to 10 arguments (%0-%9).  A single diagnostic with more
     455                 :     /// than that almost certainly has to be simplified anyway.
     456                 :     MaxArguments = 10
     457                 :   };
     458                 : 
     459                 :   /// NumDiagArgs - This contains the number of entries in Arguments.
     460                 :   signed char NumDiagArgs;
     461                 :   /// NumRanges - This is the number of ranges in the DiagRanges array.
     462                 :   unsigned char NumDiagRanges;
     463                 :   /// \brief The number of code modifications hints in the
     464                 :   /// CodeModificationHints array.
     465                 :   unsigned char NumCodeModificationHints;
     466                 : 
     467                 :   /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
     468                 :   /// values, with one for each argument.  This specifies whether the argument
     469                 :   /// is in DiagArgumentsStr or in DiagArguments.
     470                 :   unsigned char DiagArgumentsKind[MaxArguments];
     471                 : 
     472                 :   /// DiagArgumentsStr - This holds the values of each string argument for the
     473                 :   /// current diagnostic.  This value is only used when the corresponding
     474                 :   /// ArgumentKind is ak_std_string.
     475                 :   std::string DiagArgumentsStr[MaxArguments];
     476                 : 
     477                 :   /// DiagArgumentsVal - The values for the various substitution positions. This
     478                 :   /// is used when the argument is not an std::string.  The specific value is
     479                 :   /// mangled into an intptr_t and the intepretation depends on exactly what
     480                 :   /// sort of argument kind it is.
     481                 :   intptr_t DiagArgumentsVal[MaxArguments];
     482                 : 
     483                 :   /// DiagRanges - The list of ranges added to this diagnostic.  It currently
     484                 :   /// only support 10 ranges, could easily be extended if needed.
     485                 :   SourceRange DiagRanges[10];
     486                 : 
     487                 :   enum { MaxCodeModificationHints = 3 };
     488                 : 
     489                 :   /// CodeModificationHints - If valid, provides a hint with some code
     490                 :   /// to insert, remove, or modify at a particular position.
     491                 :   CodeModificationHint CodeModificationHints[MaxCodeModificationHints];
     492                 : 
     493                 :   /// ProcessDiag - This is the method used to report a diagnostic that is
     494                 :   /// finally fully formed.
     495                 :   ///
     496                 :   /// \returns true if the diagnostic was emitted, false if it was
     497                 :   /// suppressed.
     498                 :   bool ProcessDiag();
     499                 : };
     500                 : 
     501                 : //===----------------------------------------------------------------------===//
     502                 : // DiagnosticBuilder
     503                 : //===----------------------------------------------------------------------===//
     504                 : 
     505                 : /// DiagnosticBuilder - This is a little helper class used to produce
     506                 : /// diagnostics.  This is constructed by the Diagnostic::Report method, and
     507                 : /// allows insertion of extra information (arguments and source ranges) into the
     508                 : /// currently "in flight" diagnostic.  When the temporary for the builder is
     509                 : /// destroyed, the diagnostic is issued.
     510                 : ///
     511                 : /// Note that many of these will be created as temporary objects (many call
     512                 : /// sites), so we want them to be small and we never want their address taken.
     513                 : /// This ensures that compilers with somewhat reasonable optimizers will promote
     514                 : /// the common fields to registers, eliminating increments of the NumArgs field,
     515                 : /// for example.
     516                 : class DiagnosticBuilder {
     517                 :   mutable Diagnostic *DiagObj;
     518                 :   mutable unsigned NumArgs, NumRanges, NumCodeModificationHints;
     519                 : 
     520                 :   void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT
     521                 :   friend class Diagnostic;
     522            18903:   explicit DiagnosticBuilder(Diagnostic *diagObj)
     523                 :     : DiagObj(diagObj), NumArgs(0), NumRanges(0),
     524            18903:       NumCodeModificationHints(0) {}
     525                 : 
     526                 : public:
     527                 :   /// Copy constructor.  When copied, this "takes" the diagnostic info from the
     528                 :   /// input and neuters it.
     529            15710:   DiagnosticBuilder(const DiagnosticBuilder &D) {
     530            15710:     DiagObj = D.DiagObj;
     531            15710:     D.DiagObj = 0;
     532            15710:     NumArgs = D.NumArgs;
     533            15710:     NumRanges = D.NumRanges;
     534            15710:     NumCodeModificationHints = D.NumCodeModificationHints;
     535            15710:   }
     536                 : 
     537                 :   /// \brief Simple enumeration value used to give a name to the
     538                 :   /// suppress-diagnostic constructor.
     539                 :   enum SuppressKind { Suppress };
     540                 : 
     541                 :   /// \brief Create an empty DiagnosticBuilder object that represents
     542                 :   /// no actual diagnostic.
     543               24:   explicit DiagnosticBuilder(SuppressKind)
     544               24:     : DiagObj(0), NumArgs(0), NumRanges(0), NumCodeModificationHints(0) { }
     545                 : 
     546                 :   /// \brief Force the diagnostic builder to emit the diagnostic now.
     547                 :   ///
     548                 :   /// Once this function has been called, the DiagnosticBuilder object
     549                 :   /// should not be used again before it is destroyed.
     550                 :   ///
     551                 :   /// \returns true if a diagnostic was emitted, false if the
     552                 :   /// diagnostic was suppressed.
     553            50317:   bool Emit() {
     554                 :     // If DiagObj is null, then its soul was stolen by the copy ctor
     555                 :     // or the user called Emit().
                    31433: branch 0 taken
                    18884: branch 1 taken
     556            50317:     if (DiagObj == 0) return false;
     557                 : 
     558                 :     // When emitting diagnostics, we set the final argument count into
     559                 :     // the Diagnostic object.
     560            18884:     DiagObj->NumDiagArgs = NumArgs;
     561            18884:     DiagObj->NumDiagRanges = NumRanges;
     562            18884:     DiagObj->NumCodeModificationHints = NumCodeModificationHints;
     563                 : 
     564                 :     // Process the diagnostic, sending the accumulated information to the
     565                 :     // DiagnosticClient.
     566            18884:     bool Emitted = DiagObj->ProcessDiag();
     567                 : 
     568                 :     // Clear out the current diagnostic object.
     569            18884:     DiagObj->Clear();
     570                 : 
     571                 :     // This diagnostic is dead.
     572            18884:     DiagObj = 0;
     573                 : 
     574            18884:     return Emitted;
     575                 :   }
     576                 : 
     577                 :   /// Destructor - The dtor emits the diagnostic if it hasn't already
     578                 :   /// been emitted.
     579            34637:   ~DiagnosticBuilder() { Emit(); }
     580                 : 
     581                 :   /// isActive - Determine whether this diagnostic is still active.
     582               73:   bool isActive() const { return DiagObj != 0; }
     583                 : 
     584                 :   /// Operator bool: conversion of DiagnosticBuilder to bool always returns
     585                 :   /// true.  This allows is to be used in boolean error contexts like:
     586                 :   /// return Diag(...);
     587              120:   operator bool() const { return true; }
     588                 : 
     589              770:   void AddString(llvm::StringRef S) const {
     590                 :     assert(NumArgs < Diagnostic::MaxArguments &&
                      770: branch 1 taken
                        0: branch 1 not taken
     591              770:            "Too many arguments to diagnostic!");
                      770: branch 0 taken
                        0: branch 1 not taken
     592              770:     if (DiagObj) {
     593              770:       DiagObj->DiagArgumentsKind[NumArgs] = Diagnostic::ak_std_string;
     594              770:       DiagObj->DiagArgumentsStr[NumArgs++] = S;
     595                 :     }
     596              770:   }
     597                 : 
     598            17626:   void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const {
     599                 :     assert(NumArgs < Diagnostic::MaxArguments &&
                        0: branch 1 not taken
                    17626: branch 1 taken
     600            17626:            "Too many arguments to diagnostic!");
                    17621: branch 0 taken
                        5: branch 1 taken
     601            17626:     if (DiagObj) {
     602            17621:       DiagObj->DiagArgumentsKind[NumArgs] = Kind;
     603            17621:       DiagObj->DiagArgumentsVal[NumArgs++] = V;
     604                 :     }
     605            17626:   }
     606                 : 
     607             4392:   void AddSourceRange(const SourceRange &R) const {
     608                 :     assert(NumRanges <
     609                 :            sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
                     4392: branch 1 taken
                        0: branch 1 not taken
     610             4392:            "Too many arguments to diagnostic!");
                     4371: branch 0 taken
                       21: branch 1 taken
     611             4392:     if (DiagObj)
     612             4371:       DiagObj->DiagRanges[NumRanges++] = R;
     613             4392:   }
     614                 : 
     615              883:   void AddCodeModificationHint(const CodeModificationHint &Hint) const {
                        0: branch 2 not taken
                        0: branch 2 not taken
     616              883:     if (Hint.isNull())
     617              298:       return;
     618                 :     
     619                 :     assert(NumCodeModificationHints < Diagnostic::MaxCodeModificationHints &&
                        0: branch 0 not taken
                      585: branch 1 taken
     620              585:            "Too many code modification hints!");
                      585: branch 0 taken
                        0: branch 1 not taken
     621              585:     if (DiagObj)
     622              585:       DiagObj->CodeModificationHints[NumCodeModificationHints++] = Hint;
     623                 :   }
     624                 : };
     625                 : 
     626                 : inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
     627              770:                                            llvm::StringRef S) {
     628              770:   DB.AddString(S);
     629              770:   return DB;
     630                 : }
     631                 : 
     632                 : inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
     633              727:                                            const char *Str) {
     634                 :   DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
     635              727:                   Diagnostic::ak_c_string);
     636              727:   return DB;
     637                 : }
     638                 : 
     639              786: inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
     640              786:   DB.AddTaggedVal(I, Diagnostic::ak_sint);
     641              786:   return DB;
     642                 : }
     643                 : 
     644              487: inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) {
     645              487:   DB.AddTaggedVal(I, Diagnostic::ak_sint);
     646              487:   return DB;
     647                 : }
     648                 : 
     649                 : inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
     650              881:                                            unsigned I) {
     651              881:   DB.AddTaggedVal(I, Diagnostic::ak_uint);
     652              881:   return DB;
     653                 : }
     654                 : 
     655                 : inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
     656              445:                                            const IdentifierInfo *II) {
     657                 :   DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
     658              445:                   Diagnostic::ak_identifierinfo);
     659              445:   return DB;
     660                 : }
     661                 : 
     662                 : // Adds a DeclContext to the diagnostic. The enable_if template magic is here
     663                 : // so that we only match those arguments that are (statically) DeclContexts;
     664                 : // other arguments that derive from DeclContext (e.g., RecordDecls) will not
     665                 : // match.
     666                 : template<typename T>
     667                 : inline
     668                 : typename llvm::enable_if<llvm::is_same<T, DeclContext>, 
     669                 :                          const DiagnosticBuilder &>::type
     670               89: operator<<(const DiagnosticBuilder &DB, T *DC) {
     671               89:   DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
     672                 :                   Diagnostic::ak_declcontext);
     673               89:   return DB;
     674                 : }
     675                 :   
     676                 : inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
     677             4270:                                            const SourceRange &R) {
     678             4270:   DB.AddSourceRange(R);
     679             4270:   return DB;
     680                 : }
     681                 : 
     682                 : inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
     683              871:                                            const CodeModificationHint &Hint) {
     684              871:   DB.AddCodeModificationHint(Hint);
     685              871:   return DB;
     686                 : }
     687                 : 
     688                 : /// Report - Issue the message to the client.  DiagID is a member of the
     689                 : /// diag::kind enum.  This actually returns a new instance of DiagnosticBuilder
     690                 : /// which emits the diagnostics (through ProcessDiag) when it is destroyed.
     691            18884: inline DiagnosticBuilder Diagnostic::Report(FullSourceLoc Loc, unsigned DiagID){
                    18884: branch 1 taken
                        0: branch 1 not taken
     692            18884:   assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
     693            18884:   CurDiagLoc = Loc;
     694            18884:   CurDiagID = DiagID;
     695            18884:   return DiagnosticBuilder(this);
     696                 : }
     697               61: inline DiagnosticBuilder Diagnostic::Report(unsigned DiagID) {
     698               61:   return Report(FullSourceLoc(), DiagID);
     699                 : }
     700                 : 
     701                 : //===----------------------------------------------------------------------===//
     702                 : // DiagnosticInfo
     703                 : //===----------------------------------------------------------------------===//
     704                 : 
     705                 : /// DiagnosticInfo - This is a little helper class (which is basically a smart
     706                 : /// pointer that forward info from Diagnostic) that allows clients to enquire
     707                 : /// about the currently in-flight diagnostic.
     708                 : class DiagnosticInfo {
     709                 :   const Diagnostic *DiagObj;
     710                 : public:
     711            18884:   explicit DiagnosticInfo(const Diagnostic *DO) : DiagObj(DO) {}
     712                 : 
     713            12595:   const Diagnostic *getDiags() const { return DiagObj; }
     714            26554:   unsigned getID() const { return DiagObj->CurDiagID; }
     715            20002:   const FullSourceLoc &getLocation() const { return DiagObj->CurDiagLoc; }
     716                 : 
     717            24725:   unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
     718                 : 
     719                 :   /// getArgKind - Return the kind of the specified index.  Based on the kind
     720                 :   /// of argument, the accessors below can be used to get the value.
     721            24725:   Diagnostic::ArgumentKind getArgKind(unsigned Idx) const {
     722            24725:     assert(Idx < getNumArgs() && "Argument index out of range!");
     723            24725:     return (Diagnostic::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
     724                 :   }
     725                 : 
     726                 :   /// getArgStdStr - Return the provided argument string specified by Idx.
     727             1336:   const std::string &getArgStdStr(unsigned Idx) const {
     728                 :     assert(getArgKind(Idx) == Diagnostic::ak_std_string &&
     729             1336:            "invalid argument accessor!");
     730             1336:     return DiagObj->DiagArgumentsStr[Idx];
     731                 :   }
     732                 : 
     733                 :   /// getArgCStr - Return the specified C string argument.
     734              445:   const char *getArgCStr(unsigned Idx) const {
     735                 :     assert(getArgKind(Idx) == Diagnostic::ak_c_string &&
     736              445:            "invalid argument accessor!");
     737              445:     return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
     738                 :   }
     739                 : 
     740                 :   /// getArgSInt - Return the specified signed integer argument.
     741             1176:   int getArgSInt(unsigned Idx) const {
     742                 :     assert(getArgKind(Idx) == Diagnostic::ak_sint &&
     743             1176:            "invalid argument accessor!");
     744             1176:     return (int)DiagObj->DiagArgumentsVal[Idx];
     745                 :   }
     746                 : 
     747                 :   /// getArgUInt - Return the specified unsigned integer argument.
     748              993:   unsigned getArgUInt(unsigned Idx) const {
     749                 :     assert(getArgKind(Idx) == Diagnostic::ak_uint &&
     750              993:            "invalid argument accessor!");
     751              993:     return (unsigned)DiagObj->DiagArgumentsVal[Idx];
     752                 :   }
     753                 : 
     754                 :   /// getArgIdentifier - Return the specified IdentifierInfo argument.
     755              383:   const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
     756                 :     assert(getArgKind(Idx) == Diagnostic::ak_identifierinfo &&
     757              383:            "invalid argument accessor!");
     758              383:     return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
     759                 :   }
     760                 : 
     761                 :   /// getRawArg - Return the specified non-string argument in an opaque form.
     762            12150:   intptr_t getRawArg(unsigned Idx) const {
     763                 :     assert(getArgKind(Idx) != Diagnostic::ak_std_string &&
     764            12150:            "invalid argument accessor!");
     765            12150:     return DiagObj->DiagArgumentsVal[Idx];
     766                 :   }
     767                 : 
     768                 : 
     769                 :   /// getNumRanges - Return the number of source ranges associated with this
     770                 :   /// diagnostic.
     771              884:   unsigned getNumRanges() const {
     772              884:     return DiagObj->NumDiagRanges;
     773                 :   }
     774                 : 
     775              240:   SourceRange getRange(unsigned Idx) const {
     776              240:     assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
     777              240:     return DiagObj->DiagRanges[Idx];
     778                 :   }
     779                 : 
     780             1691:   unsigned getNumCodeModificationHints() const {
     781             1691:     return DiagObj->NumCodeModificationHints;
     782                 :   }
     783                 : 
     784              241:   const CodeModificationHint &getCodeModificationHint(unsigned Idx) const {
     785              241:     return DiagObj->CodeModificationHints[Idx];
     786                 :   }
     787                 : 
     788              634:   const CodeModificationHint *getCodeModificationHints() const {
     789                 :     return DiagObj->NumCodeModificationHints?
     790              634:              &DiagObj->CodeModificationHints[0] : 0;
     791                 :   }
     792                 : 
     793                 :   /// FormatDiagnostic - Format this diagnostic into a string, substituting the
     794                 :   /// formal arguments into the %0 slots.  The result is appended onto the Str
     795                 :   /// array.
     796                 :   void FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const;
     797                 : 
     798                 :   /// FormatDiagnostic - Format the given format-string into the
     799                 :   /// output buffer using the arguments stored in this diagnostic.
     800                 :   void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
     801                 :                         llvm::SmallVectorImpl<char> &OutStr) const;
     802                 : 
     803                 :   /// Serialize - Serialize the given diagnostic (with its diagnostic
     804                 :   /// level) to the given stream. Serialization is a lossy operation,
     805                 :   /// since the specific diagnostic ID and any macro-instantiation
     806                 :   /// information is lost.
     807                 :   void Serialize(Diagnostic::Level DiagLevel, llvm::raw_ostream &OS) const;
     808                 : };
     809                 : 
     810                 : /// DiagnosticClient - This is an abstract interface implemented by clients of
     811                 : /// the front-end, which formats and prints fully processed diagnostics.
     812            11983: class DiagnosticClient {
     813                 : public:
     814                 :   virtual ~DiagnosticClient();
     815                 : 
     816                 :   /// BeginSourceFile - Callback to inform the diagnostic client that processing
     817                 :   /// of a source file is beginning.
     818                 :   ///
     819                 :   /// Note that diagnostics may be emitted outside the processing of a source
     820                 :   /// file, for example during the parsing of command line options. However,
     821                 :   /// diagnostics with source range information are required to only be emitted
     822                 :   /// in between BeginSourceFile() and EndSourceFile().
     823                 :   ///
     824                 :   /// \arg LO - The language options for the source file being processed.
     825                 :   /// \arg PP - The preprocessor object being used for the source; this optional
     826                 :   /// and may not be present, for example when processing AST source files.
     827                 :   virtual void BeginSourceFile(const LangOptions &LangOpts,
     828               52:                                const Preprocessor *PP = 0) {}
     829                 : 
     830                 :   /// EndSourceFile - Callback to inform the diagnostic client that processing
     831                 :   /// of a source file has ended. The diagnostic client should assume that any
     832                 :   /// objects made available via \see BeginSourceFile() are inaccessible.
     833               52:   virtual void EndSourceFile() {}
     834                 : 
     835                 :   /// IncludeInDiagnosticCounts - This method (whose default implementation
     836                 :   /// returns true) indicates whether the diagnostics handled by this
     837                 :   /// DiagnosticClient should be included in the number of diagnostics reported
     838                 :   /// by Diagnostic.
     839                 :   virtual bool IncludeInDiagnosticCounts() const;
     840                 : 
     841                 :   /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
     842                 :   /// capturing it to a log as needed.
     843                 :   virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
     844                 :                                 const DiagnosticInfo &Info) = 0;
     845                 : };
     846                 : 
     847                 : }  // end namespace clang
     848                 : 
     849                 : #endif

Generated: 2010-02-10 01:31 by zcov