[PATCH] Store warning option for custom diagnostic messages.

Alexander Kornienko alexfh at google.com
Thu Jan 30 09:32:03 PST 2014


Hi jordan_rose,

This patch extends DiagnosticIDs::getCustomDiagID to accept an optional
WarningOption argument, which can then be retrieved by diagnostic ID using the
new getWarningOption method. This can be used, e.g. by the static analyzer and
clang-tidy to report the name of specific module/checker producing the
diagnostic.

http://llvm-reviews.chandlerc.com/D2660

Files:
  include/clang/Basic/DiagnosticIDs.h
  lib/Basic/DiagnosticIDs.cpp

Index: include/clang/Basic/DiagnosticIDs.h
===================================================================
--- include/clang/Basic/DiagnosticIDs.h
+++ include/clang/Basic/DiagnosticIDs.h
@@ -124,24 +124,35 @@
   DiagnosticIDs();
   ~DiagnosticIDs();
 
-  /// \brief Return an ID for a diagnostic with the specified format string and
-  /// level.
+  /// \brief Return an ID for a diagnostic with the specified format string,
+  /// level and warning option.
   ///
   /// If this is the first request for this diagnostic, it is registered and
   /// created, otherwise the existing ID is returned.
 
   // FIXME: Replace this function with a create-only facilty like
   // createCustomDiagIDFromFormatString() to enforce safe usage. At the time of
   // writing, nearly all callers of this function were invalid.
-  unsigned getCustomDiagID(Level L, StringRef FormatString);
+  unsigned getCustomDiagID(Level L, StringRef FormatString,
+                           StringRef WarningOption = "");
 
   //===--------------------------------------------------------------------===//
   // Diagnostic classification and reporting interfaces.
   //
 
   /// \brief Given a diagnostic ID, return a description of the issue.
   StringRef getDescription(unsigned DiagID) const;
 
+  /// \brief Return the lowest-level warning option that enables the specified
+  /// diagnostic.
+  ///
+  /// This method is similar to getWarningOptionForDiag, but it also handles
+  /// custom diagnostic DiagIDs.
+  ///
+  /// If there is no -Wfoo flag that controls the diagnostic, this returns an
+  /// empty string.
+  StringRef getWarningOption(unsigned DiagID) const;
+
   /// \brief Return true if the unmapped diagnostic levelof the specified
   /// diagnostic ID is a Warning or Extension.
   ///
Index: lib/Basic/DiagnosticIDs.cpp
===================================================================
--- lib/Basic/DiagnosticIDs.cpp
+++ lib/Basic/DiagnosticIDs.cpp
@@ -256,7 +256,25 @@
 namespace clang {
   namespace diag {
     class CustomDiagInfo {
-      typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
+      struct DiagDesc {
+        DiagnosticIDs::Level Level;
+        std::string Description;
+        std::string WarningOption;
+        DiagDesc(DiagnosticIDs::Level Level, std::string Description,
+                 std::string WarningOption)
+            : Level(Level), Description(Description),
+              WarningOption(WarningOption) {}
+        bool operator==(const DiagDesc &RHS) const {
+          return Level == RHS.Level && Description == RHS.Description &&
+                 WarningOption == RHS.WarningOption;
+        }
+        bool operator<(const DiagDesc &RHS) const {
+          return Level < RHS.Level ||
+                 (Level == RHS.Level && Description < RHS.Description) ||
+                 (Level == RHS.Level && Description == RHS.Description &&
+                  WarningOption < RHS.WarningOption);
+        }
+      };
       std::vector<DiagDesc> DiagInfo;
       std::map<DiagDesc, unsigned> DiagIDs;
     public:
@@ -266,19 +284,27 @@
       StringRef getDescription(unsigned DiagID) const {
         assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
                "Invalid diagnostic ID");
-        return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
+        return DiagInfo[DiagID-DIAG_UPPER_LIMIT].Description;
       }
 
       /// getLevel - Return the level of the specified custom diagnostic.
       DiagnosticIDs::Level getLevel(unsigned DiagID) const {
         assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
                "Invalid diagnostic ID");
-        return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
+        return DiagInfo[DiagID-DIAG_UPPER_LIMIT].Level;
       }
 
+      /// getLevel - Return the warning option of the specified custom
+      /// diagnostic.
+      StringRef getWarningOption(unsigned DiagID) const {
+        assert(this);
+        assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
+               "Invalid diagnostic ID");
+        return DiagInfo[DiagID-DIAG_UPPER_LIMIT].WarningOption;
+      }
       unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
-                                 DiagnosticIDs &Diags) {
-        DiagDesc D(L, Message);
+                                 StringRef WarningOption) {
+        DiagDesc D(L, Message, WarningOption);
         // Check to see if it already exists.
         std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
         if (I != DiagIDs.end() && I->first == D)
@@ -314,12 +340,19 @@
 ///
 /// \param FormatString A fixed diagnostic format string that will be hashed and
 /// mapped to a unique DiagID.
-unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) {
+unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString,
+                                        StringRef WarningOption /*= ""*/) {
   if (CustomDiagInfo == 0)
     CustomDiagInfo = new diag::CustomDiagInfo();
-  return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this);
+  return CustomDiagInfo->getOrCreateDiagID(L, FormatString, WarningOption);
 }
 
+StringRef DiagnosticIDs::getWarningOption(unsigned DiagID) const {
+  if (DiagID >= diag::DIAG_UPPER_LIMIT)
+    return CustomDiagInfo->getWarningOption(DiagID);
+
+  return getWarningOptionForDiag(DiagID);
+}
 
 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
 /// level of the specified diagnostic ID is a Warning or Extension.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2660.1.patch
Type: text/x-patch
Size: 5523 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140130/1277bc39/attachment.bin>


More information about the cfe-commits mailing list