]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
MFC r244628:
[FreeBSD/stable/9.git] / contrib / llvm / tools / clang / utils / TableGen / ClangDiagnosticsEmitter.cpp
1 //=- ClangDiagnosticsEmitter.cpp - Generate Clang diagnostics tables -*- 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 // These tablegen backends emit Clang diagnostics tables.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ADT/PointerUnion.h"
15 #include "llvm/ADT/DenseSet.h"
16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ADT/Optional.h"
19 #include "llvm/Support/Compiler.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/TableGen/Error.h"
22 #include "llvm/TableGen/Record.h"
23 #include "llvm/TableGen/TableGenBackend.h"
24 #include <algorithm>
25 #include <cctype>
26 #include <functional>
27 #include <map>
28 #include <set>
29 using namespace llvm;
30
31 //===----------------------------------------------------------------------===//
32 // Diagnostic category computation code.
33 //===----------------------------------------------------------------------===//
34
35 namespace {
36 class DiagGroupParentMap {
37   RecordKeeper &Records;
38   std::map<const Record*, std::vector<Record*> > Mapping;
39 public:
40   DiagGroupParentMap(RecordKeeper &records) : Records(records) {
41     std::vector<Record*> DiagGroups
42       = Records.getAllDerivedDefinitions("DiagGroup");
43     for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
44       std::vector<Record*> SubGroups =
45         DiagGroups[i]->getValueAsListOfDefs("SubGroups");
46       for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
47         Mapping[SubGroups[j]].push_back(DiagGroups[i]);
48     }
49   }
50   
51   const std::vector<Record*> &getParents(const Record *Group) {
52     return Mapping[Group];
53   }
54 };
55 } // end anonymous namespace.
56
57 static std::string
58 getCategoryFromDiagGroup(const Record *Group,
59                          DiagGroupParentMap &DiagGroupParents) {
60   // If the DiagGroup has a category, return it.
61   std::string CatName = Group->getValueAsString("CategoryName");
62   if (!CatName.empty()) return CatName;
63   
64   // The diag group may the subgroup of one or more other diagnostic groups,
65   // check these for a category as well.
66   const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
67   for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
68     CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
69     if (!CatName.empty()) return CatName;
70   }
71   return "";
72 }
73
74 /// getDiagnosticCategory - Return the category that the specified diagnostic
75 /// lives in.
76 static std::string getDiagnosticCategory(const Record *R,
77                                          DiagGroupParentMap &DiagGroupParents) {
78   // If the diagnostic is in a group, and that group has a category, use it.
79   if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
80     // Check the diagnostic's diag group for a category.
81     std::string CatName = getCategoryFromDiagGroup(Group->getDef(),
82                                                    DiagGroupParents);
83     if (!CatName.empty()) return CatName;
84   }
85
86   // If the diagnostic itself has a category, get it.
87   return R->getValueAsString("CategoryName");
88 }
89
90 namespace {
91   class DiagCategoryIDMap {
92     RecordKeeper &Records;
93     StringMap<unsigned> CategoryIDs;
94     std::vector<std::string> CategoryStrings;
95   public:
96     DiagCategoryIDMap(RecordKeeper &records) : Records(records) {
97       DiagGroupParentMap ParentInfo(Records);
98       
99       // The zero'th category is "".
100       CategoryStrings.push_back("");
101       CategoryIDs[""] = 0;
102       
103       std::vector<Record*> Diags =
104       Records.getAllDerivedDefinitions("Diagnostic");
105       for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
106         std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
107         if (Category.empty()) continue;  // Skip diags with no category.
108         
109         unsigned &ID = CategoryIDs[Category];
110         if (ID != 0) continue;  // Already seen.
111         
112         ID = CategoryStrings.size();
113         CategoryStrings.push_back(Category);
114       }
115     }
116     
117     unsigned getID(StringRef CategoryString) {
118       return CategoryIDs[CategoryString];
119     }
120     
121     typedef std::vector<std::string>::iterator iterator;
122     iterator begin() { return CategoryStrings.begin(); }
123     iterator end() { return CategoryStrings.end(); }
124   };
125
126   struct GroupInfo {
127     std::vector<const Record*> DiagsInGroup;
128     std::vector<std::string> SubGroups;
129     unsigned IDNo;
130   };
131 } // end anonymous namespace.
132
133 /// \brief Invert the 1-[0/1] mapping of diags to group into a one to many
134 /// mapping of groups to diags in the group.
135 static void groupDiagnostics(const std::vector<Record*> &Diags,
136                              const std::vector<Record*> &DiagGroups,
137                              std::map<std::string, GroupInfo> &DiagsInGroup) {
138   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
139     const Record *R = Diags[i];
140     DefInit *DI = dyn_cast<DefInit>(R->getValueInit("Group"));
141     if (DI == 0) continue;
142     assert(R->getValueAsDef("Class")->getName() != "CLASS_NOTE" &&
143            "Note can't be in a DiagGroup");
144     std::string GroupName = DI->getDef()->getValueAsString("GroupName");
145     DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
146   }
147   
148   // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
149   // groups (these are warnings that GCC supports that clang never produces).
150   for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
151     Record *Group = DiagGroups[i];
152     GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
153     
154     std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
155     for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
156       GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
157   }
158   
159   // Assign unique ID numbers to the groups.
160   unsigned IDNo = 0;
161   for (std::map<std::string, GroupInfo>::iterator
162        I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
163     I->second.IDNo = IDNo;
164 }
165
166 //===----------------------------------------------------------------------===//
167 // Infer members of -Wpedantic.
168 //===----------------------------------------------------------------------===//
169
170 typedef std::vector<const Record *> RecordVec;
171 typedef llvm::DenseSet<const Record *> RecordSet;
172 typedef llvm::PointerUnion<RecordVec*, RecordSet*> VecOrSet;
173
174 namespace {
175 class InferPedantic {
176   typedef llvm::DenseMap<const Record*,
177                          std::pair<unsigned, llvm::Optional<unsigned> > > GMap;
178
179   DiagGroupParentMap &DiagGroupParents;
180   const std::vector<Record*> &Diags;
181   const std::vector<Record*> DiagGroups;
182   std::map<std::string, GroupInfo> &DiagsInGroup;
183   llvm::DenseSet<const Record*> DiagsSet;
184   GMap GroupCount;
185 public:
186   InferPedantic(DiagGroupParentMap &DiagGroupParents,
187                 const std::vector<Record*> &Diags,
188                 const std::vector<Record*> &DiagGroups,
189                 std::map<std::string, GroupInfo> &DiagsInGroup)
190   : DiagGroupParents(DiagGroupParents),
191   Diags(Diags),
192   DiagGroups(DiagGroups),
193   DiagsInGroup(DiagsInGroup) {}
194
195   /// Compute the set of diagnostics and groups that are immediately
196   /// in -Wpedantic.
197   void compute(VecOrSet DiagsInPedantic,
198                VecOrSet GroupsInPedantic);
199
200 private:
201   /// Determine whether a group is a subgroup of another group.
202   bool isSubGroupOfGroup(const Record *Group,
203                          llvm::StringRef RootGroupName);
204
205   /// Determine if the diagnostic is an extension.
206   bool isExtension(const Record *Diag);
207
208   /// Determine if the diagnostic is off by default.
209   bool isOffByDefault(const Record *Diag);
210
211   /// Increment the count for a group, and transitively marked
212   /// parent groups when appropriate.
213   void markGroup(const Record *Group);
214
215   /// Return true if the diagnostic is in a pedantic group.
216   bool groupInPedantic(const Record *Group, bool increment = false);
217 };
218 } // end anonymous namespace
219
220 bool InferPedantic::isSubGroupOfGroup(const Record *Group,
221                                       llvm::StringRef GName) {
222
223   const std::string &GroupName = Group->getValueAsString("GroupName");
224   if (GName == GroupName)
225     return true;
226
227   const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
228   for (unsigned i = 0, e = Parents.size(); i != e; ++i)
229     if (isSubGroupOfGroup(Parents[i], GName))
230       return true;
231
232   return false;
233 }
234
235 /// Determine if the diagnostic is an extension.
236 bool InferPedantic::isExtension(const Record *Diag) {
237   const std::string &ClsName = Diag->getValueAsDef("Class")->getName();
238   return ClsName == "CLASS_EXTENSION";
239 }
240
241 bool InferPedantic::isOffByDefault(const Record *Diag) {
242   const std::string &DefMap = Diag->getValueAsDef("DefaultMapping")->getName();
243   return DefMap == "MAP_IGNORE";
244 }
245
246 bool InferPedantic::groupInPedantic(const Record *Group, bool increment) {
247   GMap::mapped_type &V = GroupCount[Group];
248   // Lazily compute the threshold value for the group count.
249   if (!V.second.hasValue()) {
250     const GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
251     V.second = GI.SubGroups.size() + GI.DiagsInGroup.size();
252   }
253
254   if (increment)
255     ++V.first;
256
257   // Consider a group in -Wpendatic IFF if has at least one diagnostic
258   // or subgroup AND all of those diagnostics and subgroups are covered
259   // by -Wpedantic via our computation.
260   return V.first != 0 && V.first == V.second.getValue();
261 }
262
263 void InferPedantic::markGroup(const Record *Group) {
264   // If all the diagnostics and subgroups have been marked as being
265   // covered by -Wpedantic, increment the count of parent groups.  Once the
266   // group's count is equal to the number of subgroups and diagnostics in
267   // that group, we can safely add this group to -Wpedantic.
268   if (groupInPedantic(Group, /* increment */ true)) {
269     const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
270     for (unsigned i = 0, e = Parents.size(); i != e; ++i)
271       markGroup(Parents[i]);
272   }
273 }
274
275 void InferPedantic::compute(VecOrSet DiagsInPedantic,
276                             VecOrSet GroupsInPedantic) {
277   // All extensions that are not on by default are implicitly in the
278   // "pedantic" group.  For those that aren't explicitly included in -Wpedantic,
279   // mark them for consideration to be included in -Wpedantic directly.
280   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
281     Record *R = Diags[i];
282     if (isExtension(R) && isOffByDefault(R)) {
283       DiagsSet.insert(R);
284       if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
285         const Record *GroupRec = Group->getDef();
286         if (!isSubGroupOfGroup(GroupRec, "pedantic")) {
287           markGroup(GroupRec);
288         }
289       }
290     }
291   }
292
293   // Compute the set of diagnostics that are directly in -Wpedantic.  We
294   // march through Diags a second time to ensure the results are emitted
295   // in deterministic order.
296   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
297     Record *R = Diags[i];
298     if (!DiagsSet.count(R))
299       continue;
300     // Check if the group is implicitly in -Wpedantic.  If so,
301     // the diagnostic should not be directly included in the -Wpedantic
302     // diagnostic group.
303     if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group")))
304       if (groupInPedantic(Group->getDef()))
305         continue;
306
307     // The diagnostic is not included in a group that is (transitively) in
308     // -Wpedantic.  Include it in -Wpedantic directly.
309     if (RecordVec *V = DiagsInPedantic.dyn_cast<RecordVec*>())
310       V->push_back(R);
311     else {
312       DiagsInPedantic.get<RecordSet*>()->insert(R);
313     }
314   }
315
316   if (!GroupsInPedantic)
317     return;
318
319   // Compute the set of groups that are directly in -Wpedantic.  We
320   // march through the groups to ensure the results are emitted
321   /// in a deterministc order.
322   for (unsigned i = 0, ei = DiagGroups.size(); i != ei; ++i) {
323     Record *Group = DiagGroups[i];
324     if (!groupInPedantic(Group))
325       continue;
326
327     unsigned ParentsInPedantic = 0;
328     const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
329     for (unsigned j = 0, ej = Parents.size(); j != ej; ++j) {
330       if (groupInPedantic(Parents[j]))
331         ++ParentsInPedantic;
332     }
333     // If all the parents are in -Wpedantic, this means that this diagnostic
334     // group will be indirectly included by -Wpedantic already.  In that
335     // case, do not add it directly to -Wpedantic.  If the group has no
336     // parents, obviously it should go into -Wpedantic.
337     if (Parents.size() > 0 && ParentsInPedantic == Parents.size())
338       continue;
339
340     if (RecordVec *V = GroupsInPedantic.dyn_cast<RecordVec*>())
341       V->push_back(Group);
342     else {
343       GroupsInPedantic.get<RecordSet*>()->insert(Group);
344     }
345   }
346 }
347
348 //===----------------------------------------------------------------------===//
349 // Warning Tables (.inc file) generation.
350 //===----------------------------------------------------------------------===//
351
352 static bool isError(const Record &Diag) {
353   const std::string &ClsName = Diag.getValueAsDef("Class")->getName();
354   return ClsName == "CLASS_ERROR";
355 }
356
357 /// ClangDiagsDefsEmitter - The top-level class emits .def files containing
358 /// declarations of Clang diagnostics.
359 namespace clang {
360 void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
361                         const std::string &Component) {
362   // Write the #if guard
363   if (!Component.empty()) {
364     std::string ComponentName = StringRef(Component).upper();
365     OS << "#ifdef " << ComponentName << "START\n";
366     OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
367        << ",\n";
368     OS << "#undef " << ComponentName << "START\n";
369     OS << "#endif\n\n";
370   }
371
372   const std::vector<Record*> &Diags =
373     Records.getAllDerivedDefinitions("Diagnostic");
374
375   std::vector<Record*> DiagGroups
376     = Records.getAllDerivedDefinitions("DiagGroup");
377
378   std::map<std::string, GroupInfo> DiagsInGroup;
379   groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
380
381   DiagCategoryIDMap CategoryIDs(Records);
382   DiagGroupParentMap DGParentMap(Records);
383
384   // Compute the set of diagnostics that are in -Wpedantic.
385   RecordSet DiagsInPedantic;
386   InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
387   inferPedantic.compute(&DiagsInPedantic, (RecordVec*)0);
388
389   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
390     const Record &R = *Diags[i];
391     
392     // Check if this is an error that is accidentally in a warning
393     // group.
394     if (isError(R)) {
395       if (DefInit *Group = dyn_cast<DefInit>(R.getValueInit("Group"))) {
396         const Record *GroupRec = Group->getDef();
397         const std::string &GroupName = GroupRec->getValueAsString("GroupName");
398         PrintFatalError(R.getLoc(), "Error " + R.getName() +
399                       " cannot be in a warning group [" + GroupName + "]");
400       }
401     }
402
403     // Filter by component.
404     if (!Component.empty() && Component != R.getValueAsString("Component"))
405       continue;
406
407     OS << "DIAG(" << R.getName() << ", ";
408     OS << R.getValueAsDef("Class")->getName();
409     OS << ", diag::" << R.getValueAsDef("DefaultMapping")->getName();
410     
411     // Description string.
412     OS << ", \"";
413     OS.write_escaped(R.getValueAsString("Text")) << '"';
414     
415     // Warning associated with the diagnostic. This is stored as an index into
416     // the alphabetically sorted warning table.
417     if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
418       std::map<std::string, GroupInfo>::iterator I =
419           DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName"));
420       assert(I != DiagsInGroup.end());
421       OS << ", " << I->second.IDNo;
422     } else if (DiagsInPedantic.count(&R)) {
423       std::map<std::string, GroupInfo>::iterator I =
424         DiagsInGroup.find("pedantic");
425       assert(I != DiagsInGroup.end() && "pedantic group not defined");
426       OS << ", " << I->second.IDNo;
427     } else {
428       OS << ", 0";
429     }
430
431     // SFINAE bit
432     if (R.getValueAsBit("SFINAE"))
433       OS << ", true";
434     else
435       OS << ", false";
436
437     // Access control bit
438     if (R.getValueAsBit("AccessControl"))
439       OS << ", true";
440     else
441       OS << ", false";
442
443     // FIXME: This condition is just to avoid temporary revlock, it can be
444     // removed.
445     if (R.getValue("WarningNoWerror")) {
446       // Default warning has no Werror bit.
447       if (R.getValueAsBit("WarningNoWerror"))
448         OS << ", true";
449       else
450         OS << ", false";
451   
452       // Default warning show in system header bit.
453       if (R.getValueAsBit("WarningShowInSystemHeader"))
454         OS << ", true";
455       else
456         OS << ", false";
457     }
458   
459     // Category number.
460     OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
461     OS << ")\n";
462   }
463 }
464 } // end namespace clang
465
466 //===----------------------------------------------------------------------===//
467 // Warning Group Tables generation
468 //===----------------------------------------------------------------------===//
469
470 static std::string getDiagCategoryEnum(llvm::StringRef name) {
471   if (name.empty())
472     return "DiagCat_None";
473   SmallString<256> enumName = llvm::StringRef("DiagCat_");
474   for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
475     enumName += isalnum(*I) ? *I : '_';
476   return enumName.str();
477 }
478   
479 namespace clang {
480 void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
481   // Compute a mapping from a DiagGroup to all of its parents.
482   DiagGroupParentMap DGParentMap(Records);
483
484   std::vector<Record*> Diags =
485     Records.getAllDerivedDefinitions("Diagnostic");
486   
487   std::vector<Record*> DiagGroups
488     = Records.getAllDerivedDefinitions("DiagGroup");
489
490   std::map<std::string, GroupInfo> DiagsInGroup;
491   groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
492
493   // All extensions are implicitly in the "pedantic" group.  Record the
494   // implicit set of groups in the "pedantic" group, and use this information
495   // later when emitting the group information for Pedantic.
496   RecordVec DiagsInPedantic;
497   RecordVec GroupsInPedantic;
498   InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
499   inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic);
500
501   // Walk through the groups emitting an array for each diagnostic of the diags
502   // that are mapped to.
503   OS << "\n#ifdef GET_DIAG_ARRAYS\n";
504   unsigned MaxLen = 0;
505   for (std::map<std::string, GroupInfo>::iterator
506        I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
507     MaxLen = std::max(MaxLen, (unsigned)I->first.size());
508     const bool IsPedantic = I->first == "pedantic";
509
510     std::vector<const Record*> &V = I->second.DiagsInGroup;
511     if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) {
512       OS << "static const short DiagArray" << I->second.IDNo << "[] = { ";
513       for (unsigned i = 0, e = V.size(); i != e; ++i)
514         OS << "diag::" << V[i]->getName() << ", ";
515       // Emit the diagnostics implicitly in "pedantic".
516       if (IsPedantic) {
517         for (unsigned i = 0, e = DiagsInPedantic.size(); i != e; ++i)
518           OS << "diag::" << DiagsInPedantic[i]->getName() << ", ";
519       }
520       OS << "-1 };\n";
521     }
522     
523     const std::vector<std::string> &SubGroups = I->second.SubGroups;
524     if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty())) {
525       OS << "static const short DiagSubGroup" << I->second.IDNo << "[] = { ";
526       for (unsigned i = 0, e = SubGroups.size(); i != e; ++i) {
527         std::map<std::string, GroupInfo>::iterator RI =
528           DiagsInGroup.find(SubGroups[i]);
529         assert(RI != DiagsInGroup.end() && "Referenced without existing?");
530         OS << RI->second.IDNo << ", ";
531       }
532       // Emit the groups implicitly in "pedantic".
533       if (IsPedantic) {
534         for (unsigned i = 0, e = GroupsInPedantic.size(); i != e; ++i) {
535           const std::string &GroupName =
536             GroupsInPedantic[i]->getValueAsString("GroupName");
537           std::map<std::string, GroupInfo>::iterator RI =
538             DiagsInGroup.find(GroupName);
539           assert(RI != DiagsInGroup.end() && "Referenced without existing?");
540           OS << RI->second.IDNo << ", ";
541         }
542       }
543
544       OS << "-1 };\n";
545     }
546   }
547   OS << "#endif // GET_DIAG_ARRAYS\n\n";
548   
549   // Emit the table now.
550   OS << "\n#ifdef GET_DIAG_TABLE\n";
551   for (std::map<std::string, GroupInfo>::iterator
552        I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
553     // Group option string.
554     OS << "  { ";
555     OS << I->first.size() << ", ";
556     OS << "\"";
557     if (I->first.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
558                                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
559                                    "0123456789!@#$%^*-+=:?")!=std::string::npos)
560       PrintFatalError("Invalid character in diagnostic group '" +
561                       I->first + "'");
562     OS.write_escaped(I->first) << "\","
563                                << std::string(MaxLen-I->first.size()+1, ' ');
564
565     // Special handling for 'pedantic'.
566     const bool IsPedantic = I->first == "pedantic";
567
568     // Diagnostics in the group.
569     const bool hasDiags = !I->second.DiagsInGroup.empty() ||
570                           (IsPedantic && !DiagsInPedantic.empty());
571     if (!hasDiags)
572       OS << "0, ";
573     else
574       OS << "DiagArray" << I->second.IDNo << ", ";
575     
576     // Subgroups.
577     const bool hasSubGroups = !I->second.SubGroups.empty() ||
578                               (IsPedantic && !GroupsInPedantic.empty());
579     if (!hasSubGroups)
580       OS << 0;
581     else
582       OS << "DiagSubGroup" << I->second.IDNo;
583     OS << " },\n";
584   }
585   OS << "#endif // GET_DIAG_TABLE\n\n";
586   
587   // Emit the category table next.
588   DiagCategoryIDMap CategoriesByID(Records);
589   OS << "\n#ifdef GET_CATEGORY_TABLE\n";
590   for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(),
591        E = CategoriesByID.end(); I != E; ++I)
592     OS << "CATEGORY(\"" << *I << "\", " << getDiagCategoryEnum(*I) << ")\n";
593   OS << "#endif // GET_CATEGORY_TABLE\n\n";
594 }
595 } // end namespace clang
596
597 //===----------------------------------------------------------------------===//
598 // Diagnostic name index generation
599 //===----------------------------------------------------------------------===//
600
601 namespace {
602 struct RecordIndexElement
603 {
604   RecordIndexElement() {}
605   explicit RecordIndexElement(Record const &R):
606     Name(R.getName()) {}
607   
608   std::string Name;
609 };
610
611 struct RecordIndexElementSorter :
612   public std::binary_function<RecordIndexElement, RecordIndexElement, bool> {
613   
614   bool operator()(RecordIndexElement const &Lhs,
615                   RecordIndexElement const &Rhs) const {
616     return Lhs.Name < Rhs.Name;
617   }
618   
619 };
620
621 } // end anonymous namespace.
622
623 namespace clang {
624 void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
625   const std::vector<Record*> &Diags =
626     Records.getAllDerivedDefinitions("Diagnostic");
627   
628   std::vector<RecordIndexElement> Index;
629   Index.reserve(Diags.size());
630   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
631     const Record &R = *(Diags[i]);    
632     Index.push_back(RecordIndexElement(R));
633   }
634   
635   std::sort(Index.begin(), Index.end(), RecordIndexElementSorter());
636   
637   for (unsigned i = 0, e = Index.size(); i != e; ++i) {
638     const RecordIndexElement &R = Index[i];
639     
640     OS << "DIAG_NAME_INDEX(" << R.Name << ")\n";
641   }
642 }
643 } // end namespace clang