When -fdiagnostics-print-source-range-info is specified,
print the diagnostic category number in the [] at the end
of the line.  For example:

$ cat t.c 
#include <stdio.h>
void foo() {
 printf("%s", 4);
}
$  clang t.c -fsyntax-only -fdiagnostics-print-source-range-info
t.c:3:11:{3:10-3:12}{3:15-3:16}: warning: conversion specifies type 'char *' but the argument has type 'int' [-Wformat,1]
  printf("%s", 4);
          ~^   ~
1 warning generated.

Clients that want category information can now pick the number 
out of the output, rdar://7928231.

More coming.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103053 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h
index 6b2912e..62f06ed 100644
--- a/include/clang/Basic/Diagnostic.h
+++ b/include/clang/Basic/Diagnostic.h
@@ -423,6 +423,14 @@
   /// the diagnostic, this returns null.
   static const char *getWarningOptionForDiag(unsigned DiagID);
 
+  /// getWarningOptionForDiag - Return the category number that a specified
+  /// DiagID belongs to, or 0 if no category.
+  static unsigned getCategoryNumberForDiag(unsigned DiagID);
+
+  /// getCategoryNameFromID - Given a category ID, return the name of the
+  /// category.
+  static const char *getCategoryNameFromID(unsigned CategoryID);
+  
   /// \brief Enumeration describing how the the emission of a diagnostic should
   /// be treated when it occurs during C++ template argument deduction.
   enum SFINAEResponse {
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp
index 9e6f168..f48758b 100644
--- a/lib/Basic/Diagnostic.cpp
+++ b/lib/Basic/Diagnostic.cpp
@@ -127,6 +127,35 @@
   return 0;
 }
 
+/// getWarningOptionForDiag - Return the category number that a specified
+/// DiagID belongs to, or 0 if no category.
+unsigned Diagnostic::getCategoryNumberForDiag(unsigned DiagID) {
+  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+    return Info->Category;
+  return 0;
+}
+
+/// getCategoryNameFromID - Given a category ID, return the name of the
+/// category, an empty string if CategoryID is zero, or null if CategoryID is
+/// invalid.
+const char *Diagnostic::getCategoryNameFromID(unsigned CategoryID) {
+  // Second the table of options, sorted by name for fast binary lookup.
+  static const char *CategoryNameTable[] = {
+#define GET_CATEGORY_TABLE
+#define CATEGORY(X) X,
+#include "clang/Basic/DiagnosticGroups.inc"
+#undef GET_CATEGORY_TABLE
+    "<<END>>"
+  };
+  static const size_t CategoryNameTableSize =
+    sizeof(CategoryNameTable) / sizeof(CategoryNameTable[0])-1;
+  
+  if (CategoryID >= CategoryNameTableSize) return 0;
+  return CategoryNameTable[CategoryID];
+}
+
+
+
 Diagnostic::SFINAEResponse 
 Diagnostic::getDiagnosticSFINAEResponse(unsigned DiagID) {
   if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) {
diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp
index 66ed956..46bdd75 100644
--- a/lib/Frontend/TextDiagnosticPrinter.cpp
+++ b/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -18,6 +18,7 @@
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
 #include <algorithm>
 using namespace clang;
 
@@ -819,21 +820,45 @@
   llvm::SmallString<100> OutStr;
   Info.FormatDiagnostic(OutStr);
 
+  std::string OptionName;
   if (DiagOpts->ShowOptionNames) {
     if (const char *Opt = Diagnostic::getWarningOptionForDiag(Info.getID())) {
-      OutStr += " [-W";
-      OutStr += Opt;
-      OutStr += ']';
+      OptionName = "-W";
+      OptionName += Opt;
     } else {
       // If the diagnostic is an extension diagnostic and not enabled by default
       // then it must have been turned on with -pedantic.
       bool EnabledByDefault;
       if (Diagnostic::isBuiltinExtensionDiag(Info.getID(), EnabledByDefault) &&
           !EnabledByDefault)
-        OutStr += " [-pedantic]";
+        OptionName = "-pedantic";
     }
   }
+  
+  // If the user wants to see category information, include it too.
+  unsigned DiagCategory = 0;
+  if (DiagOpts->ShowSourceRanges)
+    DiagCategory = Diagnostic::getCategoryNumberForDiag(Info.getID());
 
+  // If there is any categorization information, include it.
+  if (!OptionName.empty() || DiagCategory != 0) {
+    bool NeedsComma = false;
+    OutStr += " [";
+    
+    if (!OptionName.empty()) {
+      OutStr += OptionName;
+      NeedsComma = true;
+    }
+    
+    if (DiagCategory) {
+      if (NeedsComma) OutStr += ',';
+      OutStr += llvm::utostr(DiagCategory);
+    }
+    
+    OutStr += "]";
+  }
+
+  
   if (DiagOpts->ShowColors) {
     // Print warnings, errors and fatal errors in bold, no color
     switch (Level) {