Home | History | Annotate | Download | only in TableGen
      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/DenseSet.h"
     15 #include "llvm/ADT/Optional.h"
     16 #include "llvm/ADT/PointerUnion.h"
     17 #include "llvm/ADT/SetVector.h"
     18 #include "llvm/ADT/SmallPtrSet.h"
     19 #include "llvm/ADT/SmallString.h"
     20 #include "llvm/ADT/SmallVector.h"
     21 #include "llvm/ADT/StringMap.h"
     22 #include "llvm/ADT/Twine.h"
     23 #include "llvm/Support/Compiler.h"
     24 #include "llvm/Support/Debug.h"
     25 #include "llvm/TableGen/Error.h"
     26 #include "llvm/TableGen/Record.h"
     27 #include "llvm/TableGen/StringToOffsetTable.h"
     28 #include "llvm/TableGen/TableGenBackend.h"
     29 #include <algorithm>
     30 #include <cctype>
     31 #include <functional>
     32 #include <map>
     33 #include <set>
     34 using namespace llvm;
     35 
     36 //===----------------------------------------------------------------------===//
     37 // Diagnostic category computation code.
     38 //===----------------------------------------------------------------------===//
     39 
     40 namespace {
     41 class DiagGroupParentMap {
     42   RecordKeeper &Records;
     43   std::map<const Record*, std::vector<Record*> > Mapping;
     44 public:
     45   DiagGroupParentMap(RecordKeeper &records) : Records(records) {
     46     std::vector<Record*> DiagGroups
     47       = Records.getAllDerivedDefinitions("DiagGroup");
     48     for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
     49       std::vector<Record*> SubGroups =
     50         DiagGroups[i]->getValueAsListOfDefs("SubGroups");
     51       for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
     52         Mapping[SubGroups[j]].push_back(DiagGroups[i]);
     53     }
     54   }
     55 
     56   const std::vector<Record*> &getParents(const Record *Group) {
     57     return Mapping[Group];
     58   }
     59 };
     60 } // end anonymous namespace.
     61 
     62 static std::string
     63 getCategoryFromDiagGroup(const Record *Group,
     64                          DiagGroupParentMap &DiagGroupParents) {
     65   // If the DiagGroup has a category, return it.
     66   std::string CatName = Group->getValueAsString("CategoryName");
     67   if (!CatName.empty()) return CatName;
     68 
     69   // The diag group may the subgroup of one or more other diagnostic groups,
     70   // check these for a category as well.
     71   const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
     72   for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
     73     CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
     74     if (!CatName.empty()) return CatName;
     75   }
     76   return "";
     77 }
     78 
     79 /// getDiagnosticCategory - Return the category that the specified diagnostic
     80 /// lives in.
     81 static std::string getDiagnosticCategory(const Record *R,
     82                                          DiagGroupParentMap &DiagGroupParents) {
     83   // If the diagnostic is in a group, and that group has a category, use it.
     84   if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
     85     // Check the diagnostic's diag group for a category.
     86     std::string CatName = getCategoryFromDiagGroup(Group->getDef(),
     87                                                    DiagGroupParents);
     88     if (!CatName.empty()) return CatName;
     89   }
     90 
     91   // If the diagnostic itself has a category, get it.
     92   return R->getValueAsString("CategoryName");
     93 }
     94 
     95 namespace {
     96   class DiagCategoryIDMap {
     97     RecordKeeper &Records;
     98     StringMap<unsigned> CategoryIDs;
     99     std::vector<std::string> CategoryStrings;
    100   public:
    101     DiagCategoryIDMap(RecordKeeper &records) : Records(records) {
    102       DiagGroupParentMap ParentInfo(Records);
    103 
    104       // The zero'th category is "".
    105       CategoryStrings.push_back("");
    106       CategoryIDs[""] = 0;
    107 
    108       std::vector<Record*> Diags =
    109       Records.getAllDerivedDefinitions("Diagnostic");
    110       for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
    111         std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
    112         if (Category.empty()) continue;  // Skip diags with no category.
    113 
    114         unsigned &ID = CategoryIDs[Category];
    115         if (ID != 0) continue;  // Already seen.
    116 
    117         ID = CategoryStrings.size();
    118         CategoryStrings.push_back(Category);
    119       }
    120     }
    121 
    122     unsigned getID(StringRef CategoryString) {
    123       return CategoryIDs[CategoryString];
    124     }
    125 
    126     typedef std::vector<std::string>::const_iterator const_iterator;
    127     const_iterator begin() const { return CategoryStrings.begin(); }
    128     const_iterator end() const { return CategoryStrings.end(); }
    129   };
    130 
    131   struct GroupInfo {
    132     std::vector<const Record*> DiagsInGroup;
    133     std::vector<std::string> SubGroups;
    134     unsigned IDNo;
    135 
    136     const Record *ExplicitDef;
    137 
    138     GroupInfo() : ExplicitDef(nullptr) {}
    139   };
    140 } // end anonymous namespace.
    141 
    142 static bool beforeThanCompare(const Record *LHS, const Record *RHS) {
    143   assert(!LHS->getLoc().empty() && !RHS->getLoc().empty());
    144   return
    145     LHS->getLoc().front().getPointer() < RHS->getLoc().front().getPointer();
    146 }
    147 
    148 static bool beforeThanCompareGroups(const GroupInfo *LHS, const GroupInfo *RHS){
    149   assert(!LHS->DiagsInGroup.empty() && !RHS->DiagsInGroup.empty());
    150   return beforeThanCompare(LHS->DiagsInGroup.front(),
    151                            RHS->DiagsInGroup.front());
    152 }
    153 
    154 static SMRange findSuperClassRange(const Record *R, StringRef SuperName) {
    155   ArrayRef<Record *> Supers = R->getSuperClasses();
    156 
    157   for (size_t i = 0, e = Supers.size(); i < e; ++i)
    158     if (Supers[i]->getName() == SuperName)
    159       return R->getSuperClassRanges()[i];
    160 
    161   return SMRange();
    162 }
    163 
    164 /// \brief Invert the 1-[0/1] mapping of diags to group into a one to many
    165 /// mapping of groups to diags in the group.
    166 static void groupDiagnostics(const std::vector<Record*> &Diags,
    167                              const std::vector<Record*> &DiagGroups,
    168                              std::map<std::string, GroupInfo> &DiagsInGroup) {
    169 
    170   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
    171     const Record *R = Diags[i];
    172     DefInit *DI = dyn_cast<DefInit>(R->getValueInit("Group"));
    173     if (!DI)
    174       continue;
    175     assert(R->getValueAsDef("Class")->getName() != "CLASS_NOTE" &&
    176            "Note can't be in a DiagGroup");
    177     std::string GroupName = DI->getDef()->getValueAsString("GroupName");
    178     DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
    179   }
    180 
    181   typedef SmallPtrSet<GroupInfo *, 16> GroupSetTy;
    182   GroupSetTy ImplicitGroups;
    183 
    184   // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
    185   // groups (these are warnings that GCC supports that clang never produces).
    186   for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
    187     Record *Group = DiagGroups[i];
    188     GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
    189     if (Group->isAnonymous()) {
    190       if (GI.DiagsInGroup.size() > 1)
    191         ImplicitGroups.insert(&GI);
    192     } else {
    193       if (GI.ExplicitDef)
    194         assert(GI.ExplicitDef == Group);
    195       else
    196         GI.ExplicitDef = Group;
    197     }
    198 
    199     std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
    200     for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
    201       GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
    202   }
    203 
    204   // Assign unique ID numbers to the groups.
    205   unsigned IDNo = 0;
    206   for (std::map<std::string, GroupInfo>::iterator
    207        I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
    208     I->second.IDNo = IDNo;
    209 
    210   // Sort the implicit groups, so we can warn about them deterministically.
    211   SmallVector<GroupInfo *, 16> SortedGroups(ImplicitGroups.begin(),
    212                                             ImplicitGroups.end());
    213   for (SmallVectorImpl<GroupInfo *>::iterator I = SortedGroups.begin(),
    214                                               E = SortedGroups.end();
    215        I != E; ++I) {
    216     MutableArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup;
    217     std::sort(GroupDiags.begin(), GroupDiags.end(), beforeThanCompare);
    218   }
    219   std::sort(SortedGroups.begin(), SortedGroups.end(), beforeThanCompareGroups);
    220 
    221   // Warn about the same group being used anonymously in multiple places.
    222   for (SmallVectorImpl<GroupInfo *>::const_iterator I = SortedGroups.begin(),
    223                                                     E = SortedGroups.end();
    224        I != E; ++I) {
    225     ArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup;
    226 
    227     if ((*I)->ExplicitDef) {
    228       std::string Name = (*I)->ExplicitDef->getValueAsString("GroupName");
    229       for (ArrayRef<const Record *>::const_iterator DI = GroupDiags.begin(),
    230                                                     DE = GroupDiags.end();
    231            DI != DE; ++DI) {
    232         const DefInit *GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
    233         const Record *NextDiagGroup = GroupInit->getDef();
    234         if (NextDiagGroup == (*I)->ExplicitDef)
    235           continue;
    236 
    237         SMRange InGroupRange = findSuperClassRange(*DI, "InGroup");
    238         SmallString<64> Replacement;
    239         if (InGroupRange.isValid()) {
    240           Replacement += "InGroup<";
    241           Replacement += (*I)->ExplicitDef->getName();
    242           Replacement += ">";
    243         }
    244         SMFixIt FixIt(InGroupRange, Replacement.str());
    245 
    246         SrcMgr.PrintMessage(NextDiagGroup->getLoc().front(),
    247                             SourceMgr::DK_Error,
    248                             Twine("group '") + Name +
    249                               "' is referred to anonymously",
    250                             None,
    251                             InGroupRange.isValid() ? FixIt
    252                                                    : ArrayRef<SMFixIt>());
    253         SrcMgr.PrintMessage((*I)->ExplicitDef->getLoc().front(),
    254                             SourceMgr::DK_Note, "group defined here");
    255       }
    256     } else {
    257       // If there's no existing named group, we should just warn once and use
    258       // notes to list all the other cases.
    259       ArrayRef<const Record *>::const_iterator DI = GroupDiags.begin(),
    260                                                DE = GroupDiags.end();
    261       assert(DI != DE && "We only care about groups with multiple uses!");
    262 
    263       const DefInit *GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
    264       const Record *NextDiagGroup = GroupInit->getDef();
    265       std::string Name = NextDiagGroup->getValueAsString("GroupName");
    266 
    267       SMRange InGroupRange = findSuperClassRange(*DI, "InGroup");
    268       SrcMgr.PrintMessage(NextDiagGroup->getLoc().front(),
    269                           SourceMgr::DK_Error,
    270                           Twine("group '") + Name +
    271                             "' is referred to anonymously",
    272                           InGroupRange);
    273 
    274       for (++DI; DI != DE; ++DI) {
    275         GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
    276         InGroupRange = findSuperClassRange(*DI, "InGroup");
    277         SrcMgr.PrintMessage(GroupInit->getDef()->getLoc().front(),
    278                             SourceMgr::DK_Note, "also referenced here",
    279                             InGroupRange);
    280       }
    281     }
    282   }
    283 }
    284 
    285 //===----------------------------------------------------------------------===//
    286 // Infer members of -Wpedantic.
    287 //===----------------------------------------------------------------------===//
    288 
    289 typedef std::vector<const Record *> RecordVec;
    290 typedef llvm::DenseSet<const Record *> RecordSet;
    291 typedef llvm::PointerUnion<RecordVec*, RecordSet*> VecOrSet;
    292 
    293 namespace {
    294 class InferPedantic {
    295   typedef llvm::DenseMap<const Record*,
    296                          std::pair<unsigned, Optional<unsigned> > > GMap;
    297 
    298   DiagGroupParentMap &DiagGroupParents;
    299   const std::vector<Record*> &Diags;
    300   const std::vector<Record*> DiagGroups;
    301   std::map<std::string, GroupInfo> &DiagsInGroup;
    302   llvm::DenseSet<const Record*> DiagsSet;
    303   GMap GroupCount;
    304 public:
    305   InferPedantic(DiagGroupParentMap &DiagGroupParents,
    306                 const std::vector<Record*> &Diags,
    307                 const std::vector<Record*> &DiagGroups,
    308                 std::map<std::string, GroupInfo> &DiagsInGroup)
    309   : DiagGroupParents(DiagGroupParents),
    310   Diags(Diags),
    311   DiagGroups(DiagGroups),
    312   DiagsInGroup(DiagsInGroup) {}
    313 
    314   /// Compute the set of diagnostics and groups that are immediately
    315   /// in -Wpedantic.
    316   void compute(VecOrSet DiagsInPedantic,
    317                VecOrSet GroupsInPedantic);
    318 
    319 private:
    320   /// Determine whether a group is a subgroup of another group.
    321   bool isSubGroupOfGroup(const Record *Group,
    322                          llvm::StringRef RootGroupName);
    323 
    324   /// Determine if the diagnostic is an extension.
    325   bool isExtension(const Record *Diag);
    326 
    327   /// Determine if the diagnostic is off by default.
    328   bool isOffByDefault(const Record *Diag);
    329 
    330   /// Increment the count for a group, and transitively marked
    331   /// parent groups when appropriate.
    332   void markGroup(const Record *Group);
    333 
    334   /// Return true if the diagnostic is in a pedantic group.
    335   bool groupInPedantic(const Record *Group, bool increment = false);
    336 };
    337 } // end anonymous namespace
    338 
    339 bool InferPedantic::isSubGroupOfGroup(const Record *Group,
    340                                       llvm::StringRef GName) {
    341 
    342   const std::string &GroupName = Group->getValueAsString("GroupName");
    343   if (GName == GroupName)
    344     return true;
    345 
    346   const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
    347   for (unsigned i = 0, e = Parents.size(); i != e; ++i)
    348     if (isSubGroupOfGroup(Parents[i], GName))
    349       return true;
    350 
    351   return false;
    352 }
    353 
    354 /// Determine if the diagnostic is an extension.
    355 bool InferPedantic::isExtension(const Record *Diag) {
    356   const std::string &ClsName = Diag->getValueAsDef("Class")->getName();
    357   return ClsName == "CLASS_EXTENSION";
    358 }
    359 
    360 bool InferPedantic::isOffByDefault(const Record *Diag) {
    361   const std::string &DefSeverity =
    362       Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name");
    363   return DefSeverity == "Ignored";
    364 }
    365 
    366 bool InferPedantic::groupInPedantic(const Record *Group, bool increment) {
    367   GMap::mapped_type &V = GroupCount[Group];
    368   // Lazily compute the threshold value for the group count.
    369   if (!V.second.hasValue()) {
    370     const GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
    371     V.second = GI.SubGroups.size() + GI.DiagsInGroup.size();
    372   }
    373 
    374   if (increment)
    375     ++V.first;
    376 
    377   // Consider a group in -Wpendatic IFF if has at least one diagnostic
    378   // or subgroup AND all of those diagnostics and subgroups are covered
    379   // by -Wpedantic via our computation.
    380   return V.first != 0 && V.first == V.second.getValue();
    381 }
    382 
    383 void InferPedantic::markGroup(const Record *Group) {
    384   // If all the diagnostics and subgroups have been marked as being
    385   // covered by -Wpedantic, increment the count of parent groups.  Once the
    386   // group's count is equal to the number of subgroups and diagnostics in
    387   // that group, we can safely add this group to -Wpedantic.
    388   if (groupInPedantic(Group, /* increment */ true)) {
    389     const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
    390     for (unsigned i = 0, e = Parents.size(); i != e; ++i)
    391       markGroup(Parents[i]);
    392   }
    393 }
    394 
    395 void InferPedantic::compute(VecOrSet DiagsInPedantic,
    396                             VecOrSet GroupsInPedantic) {
    397   // All extensions that are not on by default are implicitly in the
    398   // "pedantic" group.  For those that aren't explicitly included in -Wpedantic,
    399   // mark them for consideration to be included in -Wpedantic directly.
    400   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
    401     Record *R = Diags[i];
    402     if (isExtension(R) && isOffByDefault(R)) {
    403       DiagsSet.insert(R);
    404       if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
    405         const Record *GroupRec = Group->getDef();
    406         if (!isSubGroupOfGroup(GroupRec, "pedantic")) {
    407           markGroup(GroupRec);
    408         }
    409       }
    410     }
    411   }
    412 
    413   // Compute the set of diagnostics that are directly in -Wpedantic.  We
    414   // march through Diags a second time to ensure the results are emitted
    415   // in deterministic order.
    416   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
    417     Record *R = Diags[i];
    418     if (!DiagsSet.count(R))
    419       continue;
    420     // Check if the group is implicitly in -Wpedantic.  If so,
    421     // the diagnostic should not be directly included in the -Wpedantic
    422     // diagnostic group.
    423     if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group")))
    424       if (groupInPedantic(Group->getDef()))
    425         continue;
    426 
    427     // The diagnostic is not included in a group that is (transitively) in
    428     // -Wpedantic.  Include it in -Wpedantic directly.
    429     if (RecordVec *V = DiagsInPedantic.dyn_cast<RecordVec*>())
    430       V->push_back(R);
    431     else {
    432       DiagsInPedantic.get<RecordSet*>()->insert(R);
    433     }
    434   }
    435 
    436   if (!GroupsInPedantic)
    437     return;
    438 
    439   // Compute the set of groups that are directly in -Wpedantic.  We
    440   // march through the groups to ensure the results are emitted
    441   /// in a deterministc order.
    442   for (unsigned i = 0, ei = DiagGroups.size(); i != ei; ++i) {
    443     Record *Group = DiagGroups[i];
    444     if (!groupInPedantic(Group))
    445       continue;
    446 
    447     unsigned ParentsInPedantic = 0;
    448     const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
    449     for (unsigned j = 0, ej = Parents.size(); j != ej; ++j) {
    450       if (groupInPedantic(Parents[j]))
    451         ++ParentsInPedantic;
    452     }
    453     // If all the parents are in -Wpedantic, this means that this diagnostic
    454     // group will be indirectly included by -Wpedantic already.  In that
    455     // case, do not add it directly to -Wpedantic.  If the group has no
    456     // parents, obviously it should go into -Wpedantic.
    457     if (Parents.size() > 0 && ParentsInPedantic == Parents.size())
    458       continue;
    459 
    460     if (RecordVec *V = GroupsInPedantic.dyn_cast<RecordVec*>())
    461       V->push_back(Group);
    462     else {
    463       GroupsInPedantic.get<RecordSet*>()->insert(Group);
    464     }
    465   }
    466 }
    467 
    468 //===----------------------------------------------------------------------===//
    469 // Warning Tables (.inc file) generation.
    470 //===----------------------------------------------------------------------===//
    471 
    472 static bool isError(const Record &Diag) {
    473   const std::string &ClsName = Diag.getValueAsDef("Class")->getName();
    474   return ClsName == "CLASS_ERROR";
    475 }
    476 
    477 static bool isRemark(const Record &Diag) {
    478   const std::string &ClsName = Diag.getValueAsDef("Class")->getName();
    479   return ClsName == "CLASS_REMARK";
    480 }
    481 
    482 /// ClangDiagsDefsEmitter - The top-level class emits .def files containing
    483 /// declarations of Clang diagnostics.
    484 namespace clang {
    485 void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
    486                         const std::string &Component) {
    487   // Write the #if guard
    488   if (!Component.empty()) {
    489     std::string ComponentName = StringRef(Component).upper();
    490     OS << "#ifdef " << ComponentName << "START\n";
    491     OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
    492        << ",\n";
    493     OS << "#undef " << ComponentName << "START\n";
    494     OS << "#endif\n\n";
    495   }
    496 
    497   const std::vector<Record*> &Diags =
    498     Records.getAllDerivedDefinitions("Diagnostic");
    499 
    500   std::vector<Record*> DiagGroups
    501     = Records.getAllDerivedDefinitions("DiagGroup");
    502 
    503   std::map<std::string, GroupInfo> DiagsInGroup;
    504   groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
    505 
    506   DiagCategoryIDMap CategoryIDs(Records);
    507   DiagGroupParentMap DGParentMap(Records);
    508 
    509   // Compute the set of diagnostics that are in -Wpedantic.
    510   RecordSet DiagsInPedantic;
    511   InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
    512   inferPedantic.compute(&DiagsInPedantic, (RecordVec*)nullptr);
    513 
    514   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
    515     const Record &R = *Diags[i];
    516 
    517     // Check if this is an error that is accidentally in a warning
    518     // group.
    519     if (isError(R)) {
    520       if (DefInit *Group = dyn_cast<DefInit>(R.getValueInit("Group"))) {
    521         const Record *GroupRec = Group->getDef();
    522         const std::string &GroupName = GroupRec->getValueAsString("GroupName");
    523         PrintFatalError(R.getLoc(), "Error " + R.getName() +
    524                       " cannot be in a warning group [" + GroupName + "]");
    525       }
    526     }
    527 
    528     // Check that all remarks have an associated diagnostic group.
    529     if (isRemark(R)) {
    530       if (!isa<DefInit>(R.getValueInit("Group"))) {
    531         PrintFatalError(R.getLoc(), "Error " + R.getName() +
    532                                         " not in any diagnostic group");
    533       }
    534     }
    535 
    536     // Filter by component.
    537     if (!Component.empty() && Component != R.getValueAsString("Component"))
    538       continue;
    539 
    540     OS << "DIAG(" << R.getName() << ", ";
    541     OS << R.getValueAsDef("Class")->getName();
    542     OS << ", (unsigned)diag::Severity::"
    543        << R.getValueAsDef("DefaultSeverity")->getValueAsString("Name");
    544 
    545     // Description string.
    546     OS << ", \"";
    547     OS.write_escaped(R.getValueAsString("Text")) << '"';
    548 
    549     // Warning associated with the diagnostic. This is stored as an index into
    550     // the alphabetically sorted warning table.
    551     if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
    552       std::map<std::string, GroupInfo>::iterator I =
    553           DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName"));
    554       assert(I != DiagsInGroup.end());
    555       OS << ", " << I->second.IDNo;
    556     } else if (DiagsInPedantic.count(&R)) {
    557       std::map<std::string, GroupInfo>::iterator I =
    558         DiagsInGroup.find("pedantic");
    559       assert(I != DiagsInGroup.end() && "pedantic group not defined");
    560       OS << ", " << I->second.IDNo;
    561     } else {
    562       OS << ", 0";
    563     }
    564 
    565     // SFINAE response.
    566     OS << ", " << R.getValueAsDef("SFINAE")->getName();
    567 
    568     // Default warning has no Werror bit.
    569     if (R.getValueAsBit("WarningNoWerror"))
    570       OS << ", true";
    571     else
    572       OS << ", false";
    573 
    574     if (R.getValueAsBit("ShowInSystemHeader"))
    575       OS << ", true";
    576     else
    577       OS << ", false";
    578 
    579     // Category number.
    580     OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
    581     OS << ")\n";
    582   }
    583 }
    584 } // end namespace clang
    585 
    586 //===----------------------------------------------------------------------===//
    587 // Warning Group Tables generation
    588 //===----------------------------------------------------------------------===//
    589 
    590 static std::string getDiagCategoryEnum(llvm::StringRef name) {
    591   if (name.empty())
    592     return "DiagCat_None";
    593   SmallString<256> enumName = llvm::StringRef("DiagCat_");
    594   for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
    595     enumName += isalnum(*I) ? *I : '_';
    596   return enumName.str();
    597 }
    598 
    599 /// \brief Emit the array of diagnostic subgroups.
    600 ///
    601 /// The array of diagnostic subgroups contains for each group a list of its
    602 /// subgroups. The individual lists are separated by '-1'. Groups with no
    603 /// subgroups are skipped.
    604 ///
    605 /// \code
    606 ///   static const int16_t DiagSubGroups[] = {
    607 ///     /* Empty */ -1,
    608 ///     /* DiagSubGroup0 */ 142, -1,
    609 ///     /* DiagSubGroup13 */ 265, 322, 399, -1
    610 ///   }
    611 /// \endcode
    612 ///
    613 static void emitDiagSubGroups(std::map<std::string, GroupInfo> &DiagsInGroup,
    614                               RecordVec &GroupsInPedantic, raw_ostream &OS) {
    615   OS << "static const int16_t DiagSubGroups[] = {\n"
    616      << "  /* Empty */ -1,\n";
    617   for (auto const &I : DiagsInGroup) {
    618     const bool IsPedantic = I.first == "pedantic";
    619 
    620     const std::vector<std::string> &SubGroups = I.second.SubGroups;
    621     if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty())) {
    622       OS << "  /* DiagSubGroup" << I.second.IDNo << " */ ";
    623       for (auto const &SubGroup : SubGroups) {
    624         std::map<std::string, GroupInfo>::const_iterator RI =
    625             DiagsInGroup.find(SubGroup);
    626         assert(RI != DiagsInGroup.end() && "Referenced without existing?");
    627         OS << RI->second.IDNo << ", ";
    628       }
    629       // Emit the groups implicitly in "pedantic".
    630       if (IsPedantic) {
    631         for (auto const &Group : GroupsInPedantic) {
    632           const std::string &GroupName = Group->getValueAsString("GroupName");
    633           std::map<std::string, GroupInfo>::const_iterator RI =
    634               DiagsInGroup.find(GroupName);
    635           assert(RI != DiagsInGroup.end() && "Referenced without existing?");
    636           OS << RI->second.IDNo << ", ";
    637         }
    638       }
    639 
    640       OS << "-1,\n";
    641     }
    642   }
    643   OS << "};\n\n";
    644 }
    645 
    646 /// \brief Emit the list of diagnostic arrays.
    647 ///
    648 /// This data structure is a large array that contains itself arrays of varying
    649 /// size. Each array represents a list of diagnostics. The different arrays are
    650 /// separated by the value '-1'.
    651 ///
    652 /// \code
    653 ///   static const int16_t DiagArrays[] = {
    654 ///     /* Empty */ -1,
    655 ///     /* DiagArray1 */ diag::warn_pragma_message,
    656 ///                      -1,
    657 ///     /* DiagArray2 */ diag::warn_abs_too_small,
    658 ///                      diag::warn_unsigned_abs,
    659 ///                      diag::warn_wrong_absolute_value_type,
    660 ///                      -1
    661 ///   };
    662 /// \endcode
    663 ///
    664 static void emitDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
    665                            RecordVec &DiagsInPedantic, raw_ostream &OS) {
    666   OS << "static const int16_t DiagArrays[] = {\n"
    667      << "  /* Empty */ -1,\n";
    668   for (auto const &I : DiagsInGroup) {
    669     const bool IsPedantic = I.first == "pedantic";
    670 
    671     const std::vector<const Record *> &V = I.second.DiagsInGroup;
    672     if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) {
    673       OS << "  /* DiagArray" << I.second.IDNo << " */ ";
    674       for (auto *Record : V)
    675         OS << "diag::" << Record->getName() << ", ";
    676       // Emit the diagnostics implicitly in "pedantic".
    677       if (IsPedantic) {
    678         for (auto const &Diag : DiagsInPedantic)
    679           OS << "diag::" << Diag->getName() << ", ";
    680       }
    681       OS << "-1,\n";
    682     }
    683   }
    684   OS << "};\n\n";
    685 }
    686 
    687 /// \brief Emit a list of group names.
    688 ///
    689 /// This creates a long string which by itself contains a list of pascal style
    690 /// strings, which consist of a length byte directly followed by the string.
    691 ///
    692 /// \code
    693 ///   static const char DiagGroupNames[] = {
    694 ///     \000\020#pragma-messages\t#warnings\020CFString-literal"
    695 ///   };
    696 /// \endcode
    697 static void emitDiagGroupNames(StringToOffsetTable &GroupNames,
    698                                raw_ostream &OS) {
    699   OS << "static const char DiagGroupNames[] = {\n";
    700   GroupNames.EmitString(OS);
    701   OS << "};\n\n";
    702 }
    703 
    704 /// \brief Emit diagnostic arrays and related data structures.
    705 ///
    706 /// This creates the actual diagnostic array, an array of diagnostic subgroups
    707 /// and an array of subgroup names.
    708 ///
    709 /// \code
    710 ///  #ifdef GET_DIAG_ARRAYS
    711 ///     static const int16_t DiagArrays[];
    712 ///     static const int16_t DiagSubGroups[];
    713 ///     static const char DiagGroupNames[];
    714 ///  #endif
    715 ///  \endcode
    716 static void emitAllDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
    717                               RecordVec &DiagsInPedantic,
    718                               RecordVec &GroupsInPedantic,
    719                               StringToOffsetTable &GroupNames,
    720                               raw_ostream &OS) {
    721   OS << "\n#ifdef GET_DIAG_ARRAYS\n";
    722   emitDiagArrays(DiagsInGroup, DiagsInPedantic, OS);
    723   emitDiagSubGroups(DiagsInGroup, GroupsInPedantic, OS);
    724   emitDiagGroupNames(GroupNames, OS);
    725   OS << "#endif // GET_DIAG_ARRAYS\n\n";
    726 }
    727 
    728 /// \brief Emit diagnostic table.
    729 ///
    730 /// The table is sorted by the name of the diagnostic group. Each element
    731 /// consists of the name of the diagnostic group (given as offset in the
    732 /// group name table), a reference to a list of diagnostics (optional) and a
    733 /// reference to a set of subgroups (optional).
    734 ///
    735 /// \code
    736 /// #ifdef GET_DIAG_TABLE
    737 ///  {/* abi */              159, /* DiagArray11 */ 19, /* Empty */          0},
    738 ///  {/* aggregate-return */ 180, /* Empty */        0, /* Empty */          0},
    739 ///  {/* all */              197, /* Empty */        0, /* DiagSubGroup13 */ 3},
    740 ///  {/* deprecated */       1981,/* DiagArray1 */ 348, /* DiagSubGroup3 */  9},
    741 /// #endif
    742 /// \endcode
    743 static void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup,
    744                           RecordVec &DiagsInPedantic,
    745                           RecordVec &GroupsInPedantic,
    746                           StringToOffsetTable &GroupNames, raw_ostream &OS) {
    747   unsigned MaxLen = 0;
    748 
    749   for (auto const &I: DiagsInGroup)
    750     MaxLen = std::max(MaxLen, (unsigned)I.first.size());
    751 
    752   OS << "\n#ifdef GET_DIAG_TABLE\n";
    753   unsigned SubGroupIndex = 1, DiagArrayIndex = 1;
    754   for (auto const &I: DiagsInGroup) {
    755     // Group option string.
    756     OS << "  { /* ";
    757     if (I.first.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
    758                                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    759                                    "0123456789!@#$%^*-+=:?") !=
    760         std::string::npos)
    761       PrintFatalError("Invalid character in diagnostic group '" + I.first +
    762                       "'");
    763     OS << I.first << " */ " << std::string(MaxLen - I.first.size(), ' ');
    764     // Store a pascal-style length byte at the beginning of the string.
    765     std::string Name = char(I.first.size()) + I.first;
    766     OS << GroupNames.GetOrAddStringOffset(Name, false) << ", ";
    767 
    768     // Special handling for 'pedantic'.
    769     const bool IsPedantic = I.first == "pedantic";
    770 
    771     // Diagnostics in the group.
    772     const std::vector<const Record *> &V = I.second.DiagsInGroup;
    773     const bool hasDiags =
    774         !V.empty() || (IsPedantic && !DiagsInPedantic.empty());
    775     if (hasDiags) {
    776       OS << "/* DiagArray" << I.second.IDNo << " */ " << DiagArrayIndex
    777          << ", ";
    778       if (IsPedantic)
    779         DiagArrayIndex += DiagsInPedantic.size();
    780       DiagArrayIndex += V.size() + 1;
    781     } else {
    782       OS << "/* Empty */     0, ";
    783     }
    784 
    785     // Subgroups.
    786     const std::vector<std::string> &SubGroups = I.second.SubGroups;
    787     const bool hasSubGroups =
    788         !SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty());
    789     if (hasSubGroups) {
    790       OS << "/* DiagSubGroup" << I.second.IDNo << " */ " << SubGroupIndex;
    791       if (IsPedantic)
    792         SubGroupIndex += GroupsInPedantic.size();
    793       SubGroupIndex += SubGroups.size() + 1;
    794     } else {
    795       OS << "/* Empty */         0";
    796     }
    797 
    798     OS << " },\n";
    799   }
    800   OS << "#endif // GET_DIAG_TABLE\n\n";
    801 }
    802 
    803 /// \brief Emit the table of diagnostic categories.
    804 ///
    805 /// The table has the form of macro calls that have two parameters. The
    806 /// category's name as well as an enum that represents the category. The
    807 /// table can be used by defining the macro 'CATEGORY' and including this
    808 /// table right after.
    809 ///
    810 /// \code
    811 /// #ifdef GET_CATEGORY_TABLE
    812 ///   CATEGORY("Semantic Issue", DiagCat_Semantic_Issue)
    813 ///   CATEGORY("Lambda Issue", DiagCat_Lambda_Issue)
    814 /// #endif
    815 /// \endcode
    816 static void emitCategoryTable(RecordKeeper &Records, raw_ostream &OS) {
    817   DiagCategoryIDMap CategoriesByID(Records);
    818   OS << "\n#ifdef GET_CATEGORY_TABLE\n";
    819   for (auto const &C : CategoriesByID)
    820     OS << "CATEGORY(\"" << C << "\", " << getDiagCategoryEnum(C) << ")\n";
    821   OS << "#endif // GET_CATEGORY_TABLE\n\n";
    822 }
    823 
    824 namespace clang {
    825 void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
    826   // Compute a mapping from a DiagGroup to all of its parents.
    827   DiagGroupParentMap DGParentMap(Records);
    828 
    829   std::vector<Record *> Diags = Records.getAllDerivedDefinitions("Diagnostic");
    830 
    831   std::vector<Record *> DiagGroups =
    832       Records.getAllDerivedDefinitions("DiagGroup");
    833 
    834   std::map<std::string, GroupInfo> DiagsInGroup;
    835   groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
    836 
    837   // All extensions are implicitly in the "pedantic" group.  Record the
    838   // implicit set of groups in the "pedantic" group, and use this information
    839   // later when emitting the group information for Pedantic.
    840   RecordVec DiagsInPedantic;
    841   RecordVec GroupsInPedantic;
    842   InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
    843   inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic);
    844 
    845   StringToOffsetTable GroupNames;
    846   for (std::map<std::string, GroupInfo>::const_iterator
    847            I = DiagsInGroup.begin(),
    848            E = DiagsInGroup.end();
    849        I != E; ++I) {
    850     // Store a pascal-style length byte at the beginning of the string.
    851     std::string Name = char(I->first.size()) + I->first;
    852     GroupNames.GetOrAddStringOffset(Name, false);
    853   }
    854 
    855   emitAllDiagArrays(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
    856                     OS);
    857   emitDiagTable(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
    858                 OS);
    859   emitCategoryTable(Records, OS);
    860 }
    861 } // end namespace clang
    862 
    863 //===----------------------------------------------------------------------===//
    864 // Diagnostic name index generation
    865 //===----------------------------------------------------------------------===//
    866 
    867 namespace {
    868 struct RecordIndexElement
    869 {
    870   RecordIndexElement() {}
    871   explicit RecordIndexElement(Record const &R):
    872     Name(R.getName()) {}
    873 
    874   std::string Name;
    875 };
    876 } // end anonymous namespace.
    877 
    878 namespace clang {
    879 void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
    880   const std::vector<Record*> &Diags =
    881     Records.getAllDerivedDefinitions("Diagnostic");
    882 
    883   std::vector<RecordIndexElement> Index;
    884   Index.reserve(Diags.size());
    885   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
    886     const Record &R = *(Diags[i]);
    887     Index.push_back(RecordIndexElement(R));
    888   }
    889 
    890   std::sort(Index.begin(), Index.end(),
    891             [](const RecordIndexElement &Lhs,
    892                const RecordIndexElement &Rhs) { return Lhs.Name < Rhs.Name; });
    893 
    894   for (unsigned i = 0, e = Index.size(); i != e; ++i) {
    895     const RecordIndexElement &R = Index[i];
    896 
    897     OS << "DIAG_NAME_INDEX(" << R.Name << ")\n";
    898   }
    899 }
    900 } // end namespace clang
    901