]> granicus.if.org Git - clang/commitdiff
Add 'remark' diagnostic type in 'clang'
authorTobias Grosser <tobias@grosser.es>
Fri, 28 Feb 2014 09:11:08 +0000 (09:11 +0000)
committerTobias Grosser <tobias@grosser.es>
Fri, 28 Feb 2014 09:11:08 +0000 (09:11 +0000)
A 'remark' is information that is not an error or a warning, but rather some
additional information provided to the user. In contrast to a 'note' a 'remark'
is an independent diagnostic, whereas a 'note' always depends on another
diagnostic.

A typical use case for remark nodes is information provided to the user, e.g.
information provided by the vectorizer about loops that have been vectorized.

This patch provides the initial implementation of 'remarks'. It includes the
actual definiton of the remark nodes, their printing as well as basic parameter
handling. We are reusing the existing diagnostic parameters which means a remark
can be enabled with normal '-Wdiagnostic-name' flags and can be upgraded to
an error using '-Werror=diagnostic-name'. '-Werror' alone does not upgrade
remarks.

This patch is by intention minimal in terms of parameter handling. More
experience and more discussions will most likely lead to further enhancements
in the parameter handling.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@202475 91177308-0d34-0410-b5e6-96231b3b80d8

18 files changed:
docs/InternalsManual.rst
docs/UsersManual.rst
include/clang-c/Index.h
include/clang/Basic/Diagnostic.h
include/clang/Basic/Diagnostic.td
include/clang/Basic/DiagnosticFrontendKinds.td
include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticIDs.h
lib/Basic/DiagnosticIDs.cpp
lib/CodeGen/CodeGenAction.cpp
lib/Frontend/LogDiagnosticPrinter.cpp
lib/Frontend/PrintPreprocessedOutput.cpp
lib/Frontend/TextDiagnostic.cpp
tools/c-index-test/c-index-test.c
tools/diagtool/ShowEnabledWarnings.cpp
tools/libclang/CIndexDiagnostic.cpp
tools/libclang/CXStoredDiagnostic.cpp
utils/TableGen/ClangDiagnosticsEmitter.cpp

index a34ba29c21a4005e8449846c35b372d11e747eeb..5830a7e506080f5e45125e067be4bcdd2de2db16 100644 (file)
@@ -87,7 +87,8 @@ start with ``err_``, ``warn_``, ``ext_`` to encode the severity into the name.
 Since the enum is referenced in the C++ code that produces the diagnostic, it
 is somewhat useful for it to be reasonably short.
 
-The severity of the diagnostic comes from the set {``NOTE``, ``WARNING``,
+The severity of the diagnostic comes from the set {``NOTE``, ``REMARK``,
+``WARNING``,
 ``EXTENSION``, ``EXTWARN``, ``ERROR``}.  The ``ERROR`` severity is used for
 diagnostics indicating the program is never acceptable under any circumstances.
 When an error is emitted, the AST for the input code may not be fully built.
@@ -97,11 +98,13 @@ represent them in the AST, but we produce diagnostics to tell the user their
 code is non-portable.  The difference is that the former are ignored by
 default, and the later warn by default.  The ``WARNING`` severity is used for
 constructs that are valid in the currently selected source language but that
-are dubious in some way.  The ``NOTE`` level is used to staple more information
-onto previous diagnostics.
+are dubious in some way.  The ``REMARK`` severity provides generic information
+about the compilation that is not necessarily related to any dubious code.  The
+``NOTE`` level is used to staple more information onto previous diagnostics.
 
 These *severities* are mapped into a smaller set (the ``Diagnostic::Level``
-enum, {``Ignored``, ``Note``, ``Warning``, ``Error``, ``Fatal``}) of output
+enum, {``Ignored``, ``Note``, ``Remark``, ``Warning``, ``Error``, ``Fatal``}) of
+output
 *levels* by the diagnostics subsystem based on various configuration options.
 Clang internally supports a fully fine grained mapping mechanism that allows
 you to map almost any diagnostic to the output level that you want.  The only
index 4ca8435c368ccb11d51392840b2410b04ea57fef..ba915018230366a062a1687f046c27b3707776e3 100644 (file)
@@ -112,11 +112,11 @@ Options to Control Error and Warning Messages
 
 .. option:: -w
 
-  Disable all warnings.
+  Disable all diagnostics.
 
 .. option:: -Weverything
 
-  :ref:`Enable all warnings. <diagnostics_enable_everything>`
+  :ref:`Enable all diagnostics. <diagnostics_enable_everything>`
 
 .. option:: -pedantic
 
@@ -582,6 +582,7 @@ All diagnostics are mapped into one of these 5 classes:
 
 -  Ignored
 -  Note
+-  Remark
 -  Warning
 -  Error
 -  Fatal
@@ -722,11 +723,12 @@ is treated as a system header.
 
 .. _diagnostics_enable_everything:
 
-Enabling All Warnings
-^^^^^^^^^^^^^^^^^^^^^
+Enabling All Diagnostics
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 In addition to the traditional ``-W`` flags, one can enable **all**
-warnings by passing :option:`-Weverything`. This works as expected with
+diagnostics by passing :option:`-Weverything`. This works as expected
+with
 :option:`-Werror`, and also includes the warnings from :option:`-pedantic`.
 
 Note that when combined with :option:`-w` (which disables all warnings), that
index b77ddcb6c0579b91c9994fdc24a8380a770d0649..7eff0a4216a7d96135621448ea81ae5edb5c41a7 100644 (file)
@@ -652,6 +652,12 @@ enum CXDiagnosticSeverity {
    */
   CXDiagnostic_Note    = 1,
 
+  /**
+   * \brief This diagnostic is a remark that provides additional information
+   * for the user.
+   */
+  CXDiagnostic_Remark = 5,
+
   /**
    * \brief This diagnostic indicates suspicious code that may not be
    * wrong.
index 6782964df6682bd28b8046e926df89556a98b268..d83c4c0b9b4084a649cf9a9426218329152e5110 100644 (file)
@@ -142,6 +142,7 @@ public:
   enum Level {
     Ignored = DiagnosticIDs::Ignored,
     Note = DiagnosticIDs::Note,
+    Remark = DiagnosticIDs::Remark,
     Warning = DiagnosticIDs::Warning,
     Error = DiagnosticIDs::Error,
     Fatal = DiagnosticIDs::Fatal
index 2616548bc00943a70399c7f2419d0f3582b80714..61a4508615e16d49a2fc40fc4af003e06d899a27 100644 (file)
@@ -15,6 +15,7 @@
 // Define the diagnostic mappings.
 class DiagMapping;
 def MAP_IGNORE  : DiagMapping;
+def MAP_REMARK  : DiagMapping;
 def MAP_WARNING : DiagMapping;
 def MAP_ERROR   : DiagMapping;
 def MAP_FATAL   : DiagMapping;
@@ -22,6 +23,7 @@ def MAP_FATAL   : DiagMapping;
 // Define the diagnostic classes.
 class DiagClass;
 def CLASS_NOTE      : DiagClass;
+def CLASS_REMARK    : DiagClass;
 def CLASS_WARNING   : DiagClass;
 def CLASS_EXTENSION : DiagClass;
 def CLASS_ERROR     : DiagClass;
@@ -84,6 +86,7 @@ class AccessControl {
 // FIXME: ExtWarn and Extension should also be SFINAEFailure by default.
 class Error<string str>     : Diagnostic<str, CLASS_ERROR, MAP_ERROR>, SFINAEFailure;
 class Warning<string str>   : Diagnostic<str, CLASS_WARNING, MAP_WARNING>;
+class Remark<string str>    : Diagnostic<str, CLASS_REMARK, MAP_IGNORE>;
 class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, MAP_IGNORE>;
 class ExtWarn<string str>   : Diagnostic<str, CLASS_EXTENSION, MAP_WARNING>;
 class Note<string str>      : Diagnostic<str, CLASS_NOTE, MAP_FATAL/*ignored*/>;
index 2b36d38a3f1bb5360476df2c3733b6f7c43248c1..41a83a0b8ed3595a373618671b1bdbeca422bffc 100644 (file)
@@ -29,6 +29,7 @@ def note_fe_backend_frame_larger_than: Note<"%0">, CatBackend;
 
 def warn_fe_backend_plugin: Warning<"%0">, CatBackend, InGroup<BackendPlugin>;
 def err_fe_backend_plugin: Error<"%0">, CatBackend;
+def remark_fe_backend_plugin: Remark<"%0">, CatBackend, InGroup<RemarkBackendPlugin>;
 def note_fe_backend_plugin: Note<"%0">, CatBackend;
 
 def err_fe_invalid_code_complete_file : Error<
index 428363bcfc5dd824adb86637b0f7d0ab3b63d238..9ec2f421cda34a2afd75d9e5a0830931bd2fba85 100644 (file)
@@ -637,3 +637,4 @@ def SourceUsesOpenMP : DiagGroup<"source-uses-openmp">;
 def BackendInlineAsm : DiagGroup<"inline-asm">;
 def BackendFrameLargerThan : DiagGroup<"frame-larger-than">;
 def BackendPlugin : DiagGroup<"backend-plugin">;
+def RemarkBackendPlugin : DiagGroup<"remark-backend-plugin">;
index 0152f25fa669c4e6e5c0741e36c18deaee5f364b..f9b845606bc681bb14b9c178cf76bd8779486306 100644 (file)
@@ -56,16 +56,17 @@ namespace clang {
     };
 
     /// 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).
+    /// to either MAP_IGNORE (nothing), MAP_REMARK (emit a remark), 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_REMARK  = 2,     ///< Map this diagnostic to a remark.
+      MAP_WARNING = 3,     ///< Map this diagnostic to a warning.
+      MAP_ERROR   = 4,     ///< Map this diagnostic to an error.
+      MAP_FATAL   = 5      ///< Map this diagnostic to a fatal error.
     };
   }
 
@@ -113,7 +114,7 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
 public:
   /// \brief The level of the diagnostic, after it has been through mapping.
   enum Level {
-    Ignored, Note, Warning, Error, Fatal
+    Ignored, Note, Remark, Warning, Error, Fatal
   };
 
 private:
index c8cd03e030983ce899740c1f29e0c99388085fea..cf6933aeb1c2f6bf2a61aa3b93da77af21cabeeb 100644 (file)
@@ -30,9 +30,10 @@ namespace {
 // Diagnostic classes.
 enum {
   CLASS_NOTE       = 0x01,
-  CLASS_WARNING    = 0x02,
-  CLASS_EXTENSION  = 0x03,
-  CLASS_ERROR      = 0x04
+  CLASS_REMARK     = 0x02,
+  CLASS_WARNING    = 0x03,
+  CLASS_EXTENSION  = 0x04,
+  CLASS_ERROR      = 0x05
 };
 
 struct StaticDiagInfoRec {
@@ -409,6 +410,9 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
   case diag::MAP_IGNORE:
     Result = DiagnosticIDs::Ignored;
     break;
+  case diag::MAP_REMARK:
+    Result = DiagnosticIDs::Remark;
+    break;
   case diag::MAP_WARNING:
     Result = DiagnosticIDs::Warning;
     break;
@@ -425,6 +429,11 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
       !MappingInfo.isUser())
     Result = DiagnosticIDs::Warning;
 
+  // Diagnostics of class REMARK are either printed as remarks or in case they
+  // have been added to -Werror they are printed as errors.
+  if (DiagClass == CLASS_REMARK && Result == DiagnosticIDs::Warning)
+    Result = DiagnosticIDs::Remark;
+
   // Ignore -pedantic diagnostics inside __extension__ blocks.
   // (The diagnostics controlled by -pedantic are the extension diagnostics
   // that are not enabled by default.)
index d7c03e8820ae1c230d92b4a1e6467e0deab46a30..2dab64072df9a3ecacdfb68cbe2f2687f8985dc2 100644 (file)
@@ -307,6 +307,27 @@ void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
     case llvm::DS_Warning:                                                     \
       DiagID = diag::warn_fe_##GroupName;                                      \
       break;                                                                   \
+    case llvm::DS_Remark:                                                      \
+      llvm_unreachable("'remark' severity not expected");                      \
+      break;                                                                   \
+    case llvm::DS_Note:                                                        \
+      DiagID = diag::note_fe_##GroupName;                                      \
+      break;                                                                   \
+    }                                                                          \
+  } while (false)
+
+#define ComputeDiagRemarkID(Severity, GroupName, DiagID)                       \
+  do {                                                                         \
+    switch (Severity) {                                                        \
+    case llvm::DS_Error:                                                       \
+      DiagID = diag::err_fe_##GroupName;                                       \
+      break;                                                                   \
+    case llvm::DS_Warning:                                                     \
+      DiagID = diag::warn_fe_##GroupName;                                      \
+      break;                                                                   \
+    case llvm::DS_Remark:                                                      \
+      DiagID = diag::remark_fe_##GroupName;                                    \
+      break;                                                                   \
     case llvm::DS_Note:                                                        \
       DiagID = diag::note_fe_##GroupName;                                      \
       break;                                                                   \
@@ -372,7 +393,7 @@ void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
     break;
   default:
     // Plugin IDs are not bound to any value as they are set dynamically.
-    ComputeDiagID(Severity, backend_plugin, DiagID);
+    ComputeDiagRemarkID(Severity, backend_plugin, DiagID);
     break;
   }
   std::string MsgStorage;
index 6e09a8180c9ef74c8fdb648afa148f5a45fb49d8..53b13fc6f978758d791d9a75a433dbfb65a3764b 100644 (file)
@@ -31,6 +31,7 @@ LogDiagnosticPrinter::~LogDiagnosticPrinter() {
 static StringRef getLevelName(DiagnosticsEngine::Level Level) {
   switch (Level) {
   case DiagnosticsEngine::Ignored: return "ignored";
+  case DiagnosticsEngine::Remark:  return "remark";
   case DiagnosticsEngine::Note:    return "note";
   case DiagnosticsEngine::Warning: return "warning";
   case DiagnosticsEngine::Error:   return "error";
index 489227d9d7ed1bff35fe10e41105824a875020d4..20d7cd3a8c011cda1f57865fb7515beca8626d0b 100644 (file)
@@ -459,6 +459,9 @@ PragmaDiagnostic(SourceLocation Loc, StringRef Namespace,
   MoveToLine(Loc);
   OS << "#pragma " << Namespace << " diagnostic ";
   switch (Map) {
+  case diag::MAP_REMARK:
+    OS << "remark";
+    break;
   case diag::MAP_WARNING:
     OS << "warning";
     break;
index 79f05c6ecd5d9c32e88f2d29cb32cbad4c22f151..d95b925355b48827d744f0e42734e8058b77a0ae 100644 (file)
@@ -26,6 +26,8 @@ using namespace clang;
 
 static const enum raw_ostream::Colors noteColor =
   raw_ostream::BLACK;
+static const enum raw_ostream::Colors remarkColor =
+  raw_ostream::BLUE;
 static const enum raw_ostream::Colors fixitColor =
   raw_ostream::GREEN;
 static const enum raw_ostream::Colors caretColor =
@@ -711,6 +713,7 @@ TextDiagnostic::printDiagnosticLevel(raw_ostream &OS,
     case DiagnosticsEngine::Ignored:
       llvm_unreachable("Invalid diagnostic type");
     case DiagnosticsEngine::Note:    OS.changeColor(noteColor, true); break;
+    case DiagnosticsEngine::Remark:  OS.changeColor(remarkColor, true); break;
     case DiagnosticsEngine::Warning: OS.changeColor(warningColor, true); break;
     case DiagnosticsEngine::Error:   OS.changeColor(errorColor, true); break;
     case DiagnosticsEngine::Fatal:   OS.changeColor(fatalColor, true); break;
@@ -721,6 +724,7 @@ TextDiagnostic::printDiagnosticLevel(raw_ostream &OS,
   case DiagnosticsEngine::Ignored:
     llvm_unreachable("Invalid diagnostic type");
   case DiagnosticsEngine::Note:    OS << "note"; break;
+  case DiagnosticsEngine::Remark:  OS << "remark"; break;
   case DiagnosticsEngine::Warning: OS << "warning"; break;
   case DiagnosticsEngine::Error:   OS << "error"; break;
   case DiagnosticsEngine::Fatal:   OS << "fatal error"; break;
index defc9168193d3d94777307fe92af34e9dc56b0e8..22c0d976234c40eb552f29d5ef161570fa11575a 100644 (file)
@@ -3736,6 +3736,7 @@ static const char *getDiagnosticCodeStr(enum CXLoadDiag_Error error) {
 static const char *getSeverityString(enum CXDiagnosticSeverity severity) {
   switch (severity) {
     case CXDiagnostic_Note: return "note";
+    case CXDiagnostic_Remark: return "remark";
     case CXDiagnostic_Error: return "error";
     case CXDiagnostic_Fatal: return "fatal";
     case CXDiagnostic_Ignored: return "ignored";
index bcc7520c1bd7b5a5623c3015f745b660ffbf87b1..51213a41fc59f780e117883c10822919b4b204c1 100644 (file)
@@ -44,6 +44,7 @@ static char getCharForLevel(DiagnosticsEngine::Level Level) {
   switch (Level) {
   case DiagnosticsEngine::Ignored: return ' ';
   case DiagnosticsEngine::Note:    return '-';
+  case DiagnosticsEngine::Remark:  return 'R';
   case DiagnosticsEngine::Warning: return 'W';
   case DiagnosticsEngine::Error:   return 'E';
   case DiagnosticsEngine::Fatal:   return 'F';
index d3450d5dece7c1f237c78fdf563231c166d1c64c..a5440b4dfb65ca9d77a6280b8deb4f036527b572 100644 (file)
@@ -305,6 +305,7 @@ CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
   switch (Severity) {
   case CXDiagnostic_Ignored: llvm_unreachable("impossible");
   case CXDiagnostic_Note: Out << "note: "; break;
+  case CXDiagnostic_Remark: Out << "remark: "; break;
   case CXDiagnostic_Warning: Out << "warning: "; break;
   case CXDiagnostic_Error: Out << "error: "; break;
   case CXDiagnostic_Fatal: Out << "fatal error: "; break;
index 9731616c6b5d05996bd28908cb8bb12f33d87343..45ce39b60d02dc301b88db766afc156631837c8f 100644 (file)
@@ -31,6 +31,7 @@ CXDiagnosticSeverity CXStoredDiagnostic::getSeverity() const {
   switch (Diag.getLevel()) {
     case DiagnosticsEngine::Ignored: return CXDiagnostic_Ignored;
     case DiagnosticsEngine::Note:    return CXDiagnostic_Note;
+    case DiagnosticsEngine::Remark:  return CXDiagnostic_Remark;
     case DiagnosticsEngine::Warning: return CXDiagnostic_Warning;
     case DiagnosticsEngine::Error:   return CXDiagnostic_Error;
     case DiagnosticsEngine::Fatal:   return CXDiagnostic_Fatal;
index db159d102cd825c12cbdd1d3737a5c8ed1c99a61..2c265aff62c7a24e624982e8442bf2a9a70e981b 100644 (file)
@@ -472,6 +472,11 @@ static bool isError(const Record &Diag) {
   return ClsName == "CLASS_ERROR";
 }
 
+static bool isRemark(const Record &Diag) {
+  const std::string &ClsName = Diag.getValueAsDef("Class")->getName();
+  return ClsName == "CLASS_REMARK";
+}
+
 /// ClangDiagsDefsEmitter - The top-level class emits .def files containing
 /// declarations of Clang diagnostics.
 namespace clang {
@@ -518,6 +523,14 @@ void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
       }
     }
 
+    // Check that all remarks have an associated diagnostic group.
+    if (isRemark(R)) {
+      if (!isa<DefInit>(R.getValueInit("Group"))) {
+        PrintFatalError(R.getLoc(), "Error " + R.getName() +
+                                        " not in any diagnostic group");
+      }
+    }
+
     // Filter by component.
     if (!Component.empty() && Component != R.getValueAsString("Component"))
       continue;