[cfe-commits] r64746 - in /cfe/trunk: include/clang/Basic/Diagnostic.h lib/Basic/Diagnostic.cpp

Chris Lattner sabre at nondot.org
Mon Feb 16 22:49:55 PST 2009


Author: lattner
Date: Tue Feb 17 00:49:55 2009
New Revision: 64746

URL: http://llvm.org/viewvc/llvm-project?rev=64746&view=rev
Log:
fix notes so that they are always filtered with the same logic 
as the last non-note diagnostic that preceeded them.  This ensures
that diagnostics in main files which have notes with locations in 
system headers get all the bits and pieces emitted or not in a 
unit.  This fixes PR3215.

Modified:
    cfe/trunk/include/clang/Basic/Diagnostic.h
    cfe/trunk/lib/Basic/Diagnostic.cpp

Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=64746&r1=64745&r2=64746&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Tue Feb 17 00:49:55 2009
@@ -106,6 +106,11 @@
   /// fatal error is emitted, and is sticky.
   bool ErrorOccurred;
   bool FatalErrorOccurred;
+  
+  /// 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;
 
   unsigned NumDiagnostics;    // Number of diagnostics reported
   unsigned NumErrors;         // Number of diagnostics that are errors
@@ -161,11 +166,11 @@
   bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
 
   /// setDiagnosticMapping - This allows the client to specify that certain
-  /// warnings are ignored.  Only NOTEs, WARNINGs, and EXTENSIONs can be mapped.
+  /// warnings are ignored.  Only WARNINGs and EXTENSIONs can be mapped.
   void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map) {
     assert(Diag < diag::DIAG_UPPER_LIMIT &&
            "Can only map builtin diagnostics");
-    assert((isBuiltinNoteWarningOrExtension(Diag) || Map == diag::MAP_FATAL) &&
+    assert((isBuiltinWarningOrExtension(Diag) || Map == diag::MAP_FATAL) &&
            "Cannot map errors!");
     unsigned char &Slot = DiagMappings[Diag/2];
     unsigned Bits = (Diag & 1)*4;
@@ -212,16 +217,16 @@
   /// issue.
   const char *getDescription(unsigned DiagID) const;
   
-  /// isBuiltinNoteWarningOrExtension - Return true if the unmapped diagnostic
-  /// level of the specified diagnostic ID is a Note, Warning, or Extension.
-  /// Note that this only works on builtin diagnostics, not custom ones.
-  static bool isBuiltinNoteWarningOrExtension(unsigned DiagID);
+  /// 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);
 
   /// 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;  
   
   /// Report - Issue the message to the client.  @c DiagID is a member of the
   /// @c diag::kind enum.  This actually returns aninstance of DiagnosticBuilder
@@ -231,6 +236,10 @@
   inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID);
   
 private:
+  /// 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

Modified: cfe/trunk/lib/Basic/Diagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=64746&r1=64745&r2=64746&view=diff

==============================================================================
--- cfe/trunk/lib/Basic/Diagnostic.cpp (original)
+++ cfe/trunk/lib/Basic/Diagnostic.cpp Tue Feb 17 00:49:55 2009
@@ -196,6 +196,7 @@
   NumErrors = 0;
   CustomDiagInfo = 0;
   CurDiagID = ~0U;
+  LastDiagLevel = Fatal;
   
   ArgToStringFn = DummyArgToStringFn;
 }
@@ -214,10 +215,11 @@
 }
 
 
-/// isBuiltinNoteWarningOrExtension - Return true if the unmapped diagnostic
-/// level of the specified diagnostic ID is a Note, Warning, or Extension.
-/// Note that this only works on builtin diagnostics, not custom ones.
-bool Diagnostic::isBuiltinNoteWarningOrExtension(unsigned DiagID) {
+/// 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) < ERROR;
 }
 
@@ -225,21 +227,18 @@
 /// getDescription - Given a diagnostic ID, return a description of the
 /// issue.
 const char *Diagnostic::getDescription(unsigned DiagID) const {
-  if (DiagID < diag::DIAG_UPPER_LIMIT) {
-    if (DiagID < diag::DIAG_START_LEX)
-      return DiagnosticTextCommon[DiagID];
-    else if (DiagID < diag::DIAG_START_PARSE)
-      return DiagnosticTextLex[DiagID - diag::DIAG_START_LEX - 1];
-    else if (DiagID < diag::DIAG_START_AST)
-      return DiagnosticTextParse[DiagID - diag::DIAG_START_PARSE - 1];
-    else if (DiagID < diag::DIAG_START_SEMA)
-      return DiagnosticTextAST[DiagID - diag::DIAG_START_AST - 1];
-    else if (DiagID < diag::DIAG_START_ANALYSIS)
-      return DiagnosticTextSema[DiagID - diag::DIAG_START_SEMA - 1];
-    else if (DiagID < diag::DIAG_UPPER_LIMIT)
-      return DiagnosticTextAnalysis[DiagID - diag::DIAG_START_ANALYSIS - 1];
-  }
-   
+  if (DiagID < diag::DIAG_START_LEX)
+    return DiagnosticTextCommon[DiagID];
+  else if (DiagID < diag::DIAG_START_PARSE)
+    return DiagnosticTextLex[DiagID - diag::DIAG_START_LEX - 1];
+  else if (DiagID < diag::DIAG_START_AST)
+    return DiagnosticTextParse[DiagID - diag::DIAG_START_PARSE - 1];
+  else if (DiagID < diag::DIAG_START_SEMA)
+    return DiagnosticTextAST[DiagID - diag::DIAG_START_AST - 1];
+  else if (DiagID < diag::DIAG_START_ANALYSIS)
+    return DiagnosticTextSema[DiagID - diag::DIAG_START_SEMA - 1];
+  else if (DiagID < diag::DIAG_UPPER_LIMIT)
+    return DiagnosticTextAnalysis[DiagID - diag::DIAG_START_ANALYSIS - 1];
   return CustomDiagInfo->getDescription(DiagID);
 }
 
@@ -252,19 +251,23 @@
     return CustomDiagInfo->getLevel(DiagID);
   
   unsigned DiagClass = getBuiltinDiagClass(DiagID);
-  
+  assert(DiagClass != NOTE && "Cannot get the 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.
-  if (DiagClass < ERROR) {
-    switch (getDiagnosticMapping((diag::kind)DiagID)) {
-    case diag::MAP_DEFAULT: break;
-    case diag::MAP_IGNORE:  return Diagnostic::Ignored;
-    case diag::MAP_WARNING: DiagClass = WARNING; break;
-    case diag::MAP_ERROR:   DiagClass = ERROR; break;
-    case diag::MAP_FATAL:   DiagClass = FATAL; break;
-    }
-  } else if (getDiagnosticMapping((diag::kind)DiagID) == diag::MAP_FATAL) {
-    DiagClass = FATAL;
+  // to error.  Errors can only be mapped to fatal.
+  switch (getDiagnosticMapping((diag::kind)DiagID)) {
+  case diag::MAP_DEFAULT: break;
+  case diag::MAP_IGNORE:  return Diagnostic::Ignored;
+  case diag::MAP_WARNING: DiagClass = WARNING; break;
+  case diag::MAP_ERROR:   DiagClass = ERROR; break;
+  case diag::MAP_FATAL:   DiagClass = FATAL; break;
   }
   
   // Map diagnostic classes based on command line argument settings.
@@ -289,7 +292,6 @@
   
   switch (DiagClass) {
   default: assert(0 && "Unknown diagnostic class!");
-  case NOTE:        return Diagnostic::Note;
   case WARNING:     return Diagnostic::Warning;
   case ERROR:       return Diagnostic::Error;
   case FATAL:       return Diagnostic::Fatal;
@@ -307,23 +309,55 @@
     return;
   
   // Figure out the diagnostic level of this message.
-  Diagnostic::Level DiagLevel = getDiagnosticLevel(Info.getID());
+  Diagnostic::Level DiagLevel;
+  unsigned DiagID = Info.getID();
   
-  // If the client doesn't care about this message, don't issue it.
-  if (DiagLevel == Diagnostic::Ignored)
+  // 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 == 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 == ERROR;
+      
+      DiagLevel = getDiagnosticLevel(DiagID, DiagClass);
+    }
+  }
+
+  if (DiagLevel != Diagnostic::Note)
+    LastDiagLevel = DiagLevel;
+  
+  // 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;
 
-  // If this is not an error and we are in a system header, ignore it.  We
-  // have to check on 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.
-  if (SuppressSystemWarnings &&
-      Info.getID() < diag::DIAG_UPPER_LIMIT &&
-      getBuiltinDiagClass(Info.getID()) != ERROR &&
+  // If this diagnostic is in a system header and is not a clang error, suppress
+  // it.
+  if (SuppressSystemWarnings && !ShouldEmitInSystemHeader &&
       Info.getLocation().isValid() &&
-      Info.getLocation().getSpellingLoc().isInSystemHeader())
+      Info.getLocation().getSpellingLoc().isInSystemHeader() &&
+      (DiagLevel != Diagnostic::Note || LastDiagLevel == Diagnostic::Ignored))
     return;
-  
+
   if (DiagLevel >= Diagnostic::Error) {
     ErrorOccurred = true;
     ++NumErrors;
@@ -331,7 +365,7 @@
     if (DiagLevel == Diagnostic::Fatal)
       FatalErrorOccurred = true;
   }
-
+  
   // Finally, report it.
   Client->HandleDiagnostic(DiagLevel, Info);
   if (Client->IncludeInDiagnosticCounts()) ++NumDiagnostics;





More information about the cfe-commits mailing list