Home | History | Annotate | Line # | Download | only in TableGen
ClangDiagnosticsEmitter.cpp revision 1.1.1.1
      1 //=- ClangDiagnosticsEmitter.cpp - Generate Clang diagnostics tables -*- C++ -*-
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // These tablegen backends emit Clang diagnostics tables.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include "TableGenBackends.h"
     14 #include "llvm/ADT/DenseSet.h"
     15 #include "llvm/ADT/Optional.h"
     16 #include "llvm/ADT/PointerUnion.h"
     17 #include "llvm/ADT/STLExtras.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/Casting.h"
     24 #include "llvm/TableGen/Error.h"
     25 #include "llvm/TableGen/Record.h"
     26 #include "llvm/TableGen/StringToOffsetTable.h"
     27 #include "llvm/TableGen/TableGenBackend.h"
     28 #include <algorithm>
     29 #include <cctype>
     30 #include <functional>
     31 #include <map>
     32 #include <set>
     33 using namespace llvm;
     34 
     35 //===----------------------------------------------------------------------===//
     36 // Diagnostic category computation code.
     37 //===----------------------------------------------------------------------===//
     38 
     39 namespace {
     40 class DiagGroupParentMap {
     41   RecordKeeper &Records;
     42   std::map<const Record*, std::vector<Record*> > Mapping;
     43 public:
     44   DiagGroupParentMap(RecordKeeper &records) : Records(records) {
     45     std::vector<Record*> DiagGroups
     46       = Records.getAllDerivedDefinitions("DiagGroup");
     47     for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
     48       std::vector<Record*> SubGroups =
     49         DiagGroups[i]->getValueAsListOfDefs("SubGroups");
     50       for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
     51         Mapping[SubGroups[j]].push_back(DiagGroups[i]);
     52     }
     53   }
     54 
     55   const std::vector<Record*> &getParents(const Record *Group) {
     56     return Mapping[Group];
     57   }
     58 };
     59 } // end anonymous namespace.
     60 
     61 static std::string
     62 getCategoryFromDiagGroup(const Record *Group,
     63                          DiagGroupParentMap &DiagGroupParents) {
     64   // If the DiagGroup has a category, return it.
     65   std::string CatName = Group->getValueAsString("CategoryName");
     66   if (!CatName.empty()) return CatName;
     67 
     68   // The diag group may the subgroup of one or more other diagnostic groups,
     69   // check these for a category as well.
     70   const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
     71   for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
     72     CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
     73     if (!CatName.empty()) return CatName;
     74   }
     75   return "";
     76 }
     77 
     78 /// getDiagnosticCategory - Return the category that the specified diagnostic
     79 /// lives in.
     80 static std::string getDiagnosticCategory(const Record *R,
     81                                          DiagGroupParentMap &DiagGroupParents) {
     82   // If the diagnostic is in a group, and that group has a category, use it.
     83   if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
     84     // Check the diagnostic's diag group for a category.
     85     std::string CatName = getCategoryFromDiagGroup(Group->getDef(),
     86                                                    DiagGroupParents);
     87     if (!CatName.empty()) return CatName;
     88   }
     89 
     90   // If the diagnostic itself has a category, get it.
     91   return R->getValueAsString("CategoryName");
     92 }
     93 
     94 namespace {
     95   class DiagCategoryIDMap {
     96     RecordKeeper &Records;
     97     StringMap<unsigned> CategoryIDs;
     98     std::vector<std::string> CategoryStrings;
     99   public:
    100     DiagCategoryIDMap(RecordKeeper &records) : Records(records) {
    101       DiagGroupParentMap ParentInfo(Records);
    102 
    103       // The zero'th category is "".
    104       CategoryStrings.push_back("");
    105       CategoryIDs[""] = 0;
    106 
    107       std::vector<Record*> Diags =
    108       Records.getAllDerivedDefinitions("Diagnostic");
    109       for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
    110         std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
    111         if (Category.empty()) continue;  // Skip diags with no category.
    112 
    113         unsigned &ID = CategoryIDs[Category];
    114         if (ID != 0) continue;  // Already seen.
    115 
    116         ID = CategoryStrings.size();
    117         CategoryStrings.push_back(Category);
    118       }
    119     }
    120 
    121     unsigned getID(StringRef CategoryString) {
    122       return CategoryIDs[CategoryString];
    123     }
    124 
    125     typedef std::vector<std::string>::const_iterator const_iterator;
    126     const_iterator begin() const { return CategoryStrings.begin(); }
    127     const_iterator end() const { return CategoryStrings.end(); }
    128   };
    129 
    130   struct GroupInfo {
    131     std::vector<const Record*> DiagsInGroup;
    132     std::vector<std::string> SubGroups;
    133     unsigned IDNo;
    134 
    135     const Record *ExplicitDef;
    136 
    137     GroupInfo() : ExplicitDef(nullptr) {}
    138   };
    139 } // end anonymous namespace.
    140 
    141 static bool beforeThanCompare(const Record *LHS, const Record *RHS) {
    142   assert(!LHS->getLoc().empty() && !RHS->getLoc().empty());
    143   return
    144     LHS->getLoc().front().getPointer() < RHS->getLoc().front().getPointer();
    145 }
    146 
    147 static bool diagGroupBeforeByName(const Record *LHS, const Record *RHS) {
    148   return LHS->getValueAsString("GroupName") <
    149          RHS->getValueAsString("GroupName");
    150 }
    151 
    152 static bool beforeThanCompareGroups(const GroupInfo *LHS, const GroupInfo *RHS){
    153   assert(!LHS->DiagsInGroup.empty() && !RHS->DiagsInGroup.empty());
    154   return beforeThanCompare(LHS->DiagsInGroup.front(),
    155                            RHS->DiagsInGroup.front());
    156 }
    157 
    158 /// Invert the 1-[0/1] mapping of diags to group into a one to many
    159 /// mapping of groups to diags in the group.
    160 static void groupDiagnostics(const std::vector<Record*> &Diags,
    161                              const std::vector<Record*> &DiagGroups,
    162                              std::map<std::string, GroupInfo> &DiagsInGroup) {
    163 
    164   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
    165     const Record *R = Diags[i];
    166     DefInit *DI = dyn_cast<DefInit>(R->getValueInit("Group"));
    167     if (!DI)
    168       continue;
    169     assert(R->getValueAsDef("Class")->getName() != "CLASS_NOTE" &&
    170            "Note can't be in a DiagGroup");
    171     std::string GroupName = DI->getDef()->getValueAsString("GroupName");
    172     DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
    173   }
    174 
    175   typedef SmallPtrSet<GroupInfo *, 16> GroupSetTy;
    176   GroupSetTy ImplicitGroups;
    177 
    178   // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
    179   // groups (these are warnings that GCC supports that clang never produces).
    180   for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
    181     Record *Group = DiagGroups[i];
    182     GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
    183     if (Group->isAnonymous()) {
    184       if (GI.DiagsInGroup.size() > 1)
    185         ImplicitGroups.insert(&GI);
    186     } else {
    187       if (GI.ExplicitDef)
    188         assert(GI.ExplicitDef == Group);
    189       else
    190         GI.ExplicitDef = Group;
    191     }
    192 
    193     std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
    194     for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
    195       GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
    196   }
    197 
    198   // Assign unique ID numbers to the groups.
    199   unsigned IDNo = 0;
    200   for (std::map<std::string, GroupInfo>::iterator
    201        I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
    202     I->second.IDNo = IDNo;
    203 
    204   // Sort the implicit groups, so we can warn about them deterministically.
    205   SmallVector<GroupInfo *, 16> SortedGroups(ImplicitGroups.begin(),
    206                                             ImplicitGroups.end());
    207   for (SmallVectorImpl<GroupInfo *>::iterator I = SortedGroups.begin(),
    208                                               E = SortedGroups.end();
    209        I != E; ++I) {
    210     MutableArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup;
    211     llvm::sort(GroupDiags, beforeThanCompare);
    212   }
    213   llvm::sort(SortedGroups, beforeThanCompareGroups);
    214 
    215   // Warn about the same group being used anonymously in multiple places.
    216   for (SmallVectorImpl<GroupInfo *>::const_iterator I = SortedGroups.begin(),
    217                                                     E = SortedGroups.end();
    218        I != E; ++I) {
    219     ArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup;
    220 
    221     if ((*I)->ExplicitDef) {
    222       std::string Name = (*I)->ExplicitDef->getValueAsString("GroupName");
    223       for (ArrayRef<const Record *>::const_iterator DI = GroupDiags.begin(),
    224                                                     DE = GroupDiags.end();
    225            DI != DE; ++DI) {
    226         const DefInit *GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
    227         const Record *NextDiagGroup = GroupInit->getDef();
    228         if (NextDiagGroup == (*I)->ExplicitDef)
    229           continue;
    230 
    231         SrcMgr.PrintMessage((*DI)->getLoc().front(),
    232                             SourceMgr::DK_Error,
    233                             Twine("group '") + Name +
    234                               "' is referred to anonymously");
    235         SrcMgr.PrintMessage((*I)->ExplicitDef->getLoc().front(),
    236                             SourceMgr::DK_Note, "group defined here");
    237       }
    238     } else {
    239       // If there's no existing named group, we should just warn once and use
    240       // notes to list all the other cases.
    241       ArrayRef<const Record *>::const_iterator DI = GroupDiags.begin(),
    242                                                DE = GroupDiags.end();
    243       assert(DI != DE && "We only care about groups with multiple uses!");
    244 
    245       const DefInit *GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
    246       const Record *NextDiagGroup = GroupInit->getDef();
    247       std::string Name = NextDiagGroup->getValueAsString("GroupName");
    248 
    249       SrcMgr.PrintMessage((*DI)->getLoc().front(),
    250                           SourceMgr::DK_Error,
    251                           Twine("group '") + Name +
    252                             "' is referred to anonymously");
    253 
    254       for (++DI; DI != DE; ++DI) {
    255         SrcMgr.PrintMessage((*DI)->getLoc().front(),
    256                             SourceMgr::DK_Note, "also referenced here");
    257       }
    258     }
    259   }
    260 }
    261 
    262 //===----------------------------------------------------------------------===//
    263 // Infer members of -Wpedantic.
    264 //===----------------------------------------------------------------------===//
    265 
    266 typedef std::vector<const Record *> RecordVec;
    267 typedef llvm::DenseSet<const Record *> RecordSet;
    268 typedef llvm::PointerUnion<RecordVec*, RecordSet*> VecOrSet;
    269 
    270 namespace {
    271 class InferPedantic {
    272   typedef llvm::DenseMap<const Record*,
    273                          std::pair<unsigned, Optional<unsigned> > > GMap;
    274 
    275   DiagGroupParentMap &DiagGroupParents;
    276   const std::vector<Record*> &Diags;
    277   const std::vector<Record*> DiagGroups;
    278   std::map<std::string, GroupInfo> &DiagsInGroup;
    279   llvm::DenseSet<const Record*> DiagsSet;
    280   GMap GroupCount;
    281 public:
    282   InferPedantic(DiagGroupParentMap &DiagGroupParents,
    283                 const std::vector<Record*> &Diags,
    284                 const std::vector<Record*> &DiagGroups,
    285                 std::map<std::string, GroupInfo> &DiagsInGroup)
    286   : DiagGroupParents(DiagGroupParents),
    287   Diags(Diags),
    288   DiagGroups(DiagGroups),
    289   DiagsInGroup(DiagsInGroup) {}
    290 
    291   /// Compute the set of diagnostics and groups that are immediately
    292   /// in -Wpedantic.
    293   void compute(VecOrSet DiagsInPedantic,
    294                VecOrSet GroupsInPedantic);
    295 
    296 private:
    297   /// Determine whether a group is a subgroup of another group.
    298   bool isSubGroupOfGroup(const Record *Group,
    299                          llvm::StringRef RootGroupName);
    300 
    301   /// Determine if the diagnostic is an extension.
    302   bool isExtension(const Record *Diag);
    303 
    304   /// Determine if the diagnostic is off by default.
    305   bool isOffByDefault(const Record *Diag);
    306 
    307   /// Increment the count for a group, and transitively marked
    308   /// parent groups when appropriate.
    309   void markGroup(const Record *Group);
    310 
    311   /// Return true if the diagnostic is in a pedantic group.
    312   bool groupInPedantic(const Record *Group, bool increment = false);
    313 };
    314 } // end anonymous namespace
    315 
    316 bool InferPedantic::isSubGroupOfGroup(const Record *Group,
    317                                       llvm::StringRef GName) {
    318 
    319   const std::string &GroupName = Group->getValueAsString("GroupName");
    320   if (GName == GroupName)
    321     return true;
    322 
    323   const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
    324   for (unsigned i = 0, e = Parents.size(); i != e; ++i)
    325     if (isSubGroupOfGroup(Parents[i], GName))
    326       return true;
    327 
    328   return false;
    329 }
    330 
    331 /// Determine if the diagnostic is an extension.
    332 bool InferPedantic::isExtension(const Record *Diag) {
    333   const std::string &ClsName = Diag->getValueAsDef("Class")->getName();
    334   return ClsName == "CLASS_EXTENSION";
    335 }
    336 
    337 bool InferPedantic::isOffByDefault(const Record *Diag) {
    338   const std::string &DefSeverity =
    339       Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name");
    340   return DefSeverity == "Ignored";
    341 }
    342 
    343 bool InferPedantic::groupInPedantic(const Record *Group, bool increment) {
    344   GMap::mapped_type &V = GroupCount[Group];
    345   // Lazily compute the threshold value for the group count.
    346   if (!V.second.hasValue()) {
    347     const GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
    348     V.second = GI.SubGroups.size() + GI.DiagsInGroup.size();
    349   }
    350 
    351   if (increment)
    352     ++V.first;
    353 
    354   // Consider a group in -Wpendatic IFF if has at least one diagnostic
    355   // or subgroup AND all of those diagnostics and subgroups are covered
    356   // by -Wpedantic via our computation.
    357   return V.first != 0 && V.first == V.second.getValue();
    358 }
    359 
    360 void InferPedantic::markGroup(const Record *Group) {
    361   // If all the diagnostics and subgroups have been marked as being
    362   // covered by -Wpedantic, increment the count of parent groups.  Once the
    363   // group's count is equal to the number of subgroups and diagnostics in
    364   // that group, we can safely add this group to -Wpedantic.
    365   if (groupInPedantic(Group, /* increment */ true)) {
    366     const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
    367     for (unsigned i = 0, e = Parents.size(); i != e; ++i)
    368       markGroup(Parents[i]);
    369   }
    370 }
    371 
    372 void InferPedantic::compute(VecOrSet DiagsInPedantic,
    373                             VecOrSet GroupsInPedantic) {
    374   // All extensions that are not on by default are implicitly in the
    375   // "pedantic" group.  For those that aren't explicitly included in -Wpedantic,
    376   // mark them for consideration to be included in -Wpedantic directly.
    377   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
    378     Record *R = Diags[i];
    379     if (isExtension(R) && isOffByDefault(R)) {
    380       DiagsSet.insert(R);
    381       if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
    382         const Record *GroupRec = Group->getDef();
    383         if (!isSubGroupOfGroup(GroupRec, "pedantic")) {
    384           markGroup(GroupRec);
    385         }
    386       }
    387     }
    388   }
    389 
    390   // Compute the set of diagnostics that are directly in -Wpedantic.  We
    391   // march through Diags a second time to ensure the results are emitted
    392   // in deterministic order.
    393   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
    394     Record *R = Diags[i];
    395     if (!DiagsSet.count(R))
    396       continue;
    397     // Check if the group is implicitly in -Wpedantic.  If so,
    398     // the diagnostic should not be directly included in the -Wpedantic
    399     // diagnostic group.
    400     if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group")))
    401       if (groupInPedantic(Group->getDef()))
    402         continue;
    403 
    404     // The diagnostic is not included in a group that is (transitively) in
    405     // -Wpedantic.  Include it in -Wpedantic directly.
    406     if (RecordVec *V = DiagsInPedantic.dyn_cast<RecordVec*>())
    407       V->push_back(R);
    408     else {
    409       DiagsInPedantic.get<RecordSet*>()->insert(R);
    410     }
    411   }
    412 
    413   if (!GroupsInPedantic)
    414     return;
    415 
    416   // Compute the set of groups that are directly in -Wpedantic.  We
    417   // march through the groups to ensure the results are emitted
    418   /// in a deterministc order.
    419   for (unsigned i = 0, ei = DiagGroups.size(); i != ei; ++i) {
    420     Record *Group = DiagGroups[i];
    421     if (!groupInPedantic(Group))
    422       continue;
    423 
    424     unsigned ParentsInPedantic = 0;
    425     const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
    426     for (unsigned j = 0, ej = Parents.size(); j != ej; ++j) {
    427       if (groupInPedantic(Parents[j]))
    428         ++ParentsInPedantic;
    429     }
    430     // If all the parents are in -Wpedantic, this means that this diagnostic
    431     // group will be indirectly included by -Wpedantic already.  In that
    432     // case, do not add it directly to -Wpedantic.  If the group has no
    433     // parents, obviously it should go into -Wpedantic.
    434     if (Parents.size() > 0 && ParentsInPedantic == Parents.size())
    435       continue;
    436 
    437     if (RecordVec *V = GroupsInPedantic.dyn_cast<RecordVec*>())
    438       V->push_back(Group);
    439     else {
    440       GroupsInPedantic.get<RecordSet*>()->insert(Group);
    441     }
    442   }
    443 }
    444 
    445 namespace {
    446 enum PieceKind {
    447   MultiPieceClass,
    448   TextPieceClass,
    449   PlaceholderPieceClass,
    450   SelectPieceClass,
    451   PluralPieceClass,
    452   DiffPieceClass,
    453   SubstitutionPieceClass,
    454 };
    455 
    456 enum ModifierType {
    457   MT_Unknown,
    458   MT_Placeholder,
    459   MT_Select,
    460   MT_Sub,
    461   MT_Plural,
    462   MT_Diff,
    463   MT_Ordinal,
    464   MT_S,
    465   MT_Q,
    466   MT_ObjCClass,
    467   MT_ObjCInstance,
    468 };
    469 
    470 static StringRef getModifierName(ModifierType MT) {
    471   switch (MT) {
    472   case MT_Select:
    473     return "select";
    474   case MT_Sub:
    475     return "sub";
    476   case MT_Diff:
    477     return "diff";
    478   case MT_Plural:
    479     return "plural";
    480   case MT_Ordinal:
    481     return "ordinal";
    482   case MT_S:
    483     return "s";
    484   case MT_Q:
    485     return "q";
    486   case MT_Placeholder:
    487     return "";
    488   case MT_ObjCClass:
    489     return "objcclass";
    490   case MT_ObjCInstance:
    491     return "objcinstance";
    492   case MT_Unknown:
    493     llvm_unreachable("invalid modifier type");
    494   }
    495   // Unhandled case
    496   llvm_unreachable("invalid modifier type");
    497 }
    498 
    499 struct Piece {
    500   // This type and its derived classes are move-only.
    501   Piece(PieceKind Kind) : ClassKind(Kind) {}
    502   Piece(Piece const &O) = delete;
    503   Piece &operator=(Piece const &) = delete;
    504   virtual ~Piece() {}
    505 
    506   PieceKind getPieceClass() const { return ClassKind; }
    507   static bool classof(const Piece *) { return true; }
    508 
    509 private:
    510   PieceKind ClassKind;
    511 };
    512 
    513 struct MultiPiece : Piece {
    514   MultiPiece() : Piece(MultiPieceClass) {}
    515   MultiPiece(std::vector<Piece *> Pieces)
    516       : Piece(MultiPieceClass), Pieces(std::move(Pieces)) {}
    517 
    518   std::vector<Piece *> Pieces;
    519 
    520   static bool classof(const Piece *P) {
    521     return P->getPieceClass() == MultiPieceClass;
    522   }
    523 };
    524 
    525 struct TextPiece : Piece {
    526   StringRef Role;
    527   std::string Text;
    528   TextPiece(StringRef Text, StringRef Role = "")
    529       : Piece(TextPieceClass), Role(Role), Text(Text.str()) {}
    530 
    531   static bool classof(const Piece *P) {
    532     return P->getPieceClass() == TextPieceClass;
    533   }
    534 };
    535 
    536 struct PlaceholderPiece : Piece {
    537   ModifierType Kind;
    538   int Index;
    539   PlaceholderPiece(ModifierType Kind, int Index)
    540       : Piece(PlaceholderPieceClass), Kind(Kind), Index(Index) {}
    541 
    542   static bool classof(const Piece *P) {
    543     return P->getPieceClass() == PlaceholderPieceClass;
    544   }
    545 };
    546 
    547 struct SelectPiece : Piece {
    548 protected:
    549   SelectPiece(PieceKind Kind, ModifierType ModKind)
    550       : Piece(Kind), ModKind(ModKind) {}
    551 
    552 public:
    553   SelectPiece(ModifierType ModKind) : SelectPiece(SelectPieceClass, ModKind) {}
    554 
    555   ModifierType ModKind;
    556   std::vector<Piece *> Options;
    557   int Index;
    558 
    559   static bool classof(const Piece *P) {
    560     return P->getPieceClass() == SelectPieceClass ||
    561            P->getPieceClass() == PluralPieceClass;
    562   }
    563 };
    564 
    565 struct PluralPiece : SelectPiece {
    566   PluralPiece() : SelectPiece(PluralPieceClass, MT_Plural) {}
    567 
    568   std::vector<Piece *> OptionPrefixes;
    569   int Index;
    570 
    571   static bool classof(const Piece *P) {
    572     return P->getPieceClass() == PluralPieceClass;
    573   }
    574 };
    575 
    576 struct DiffPiece : Piece {
    577   DiffPiece() : Piece(DiffPieceClass) {}
    578 
    579   Piece *Options[2] = {};
    580   int Indexes[2] = {};
    581 
    582   static bool classof(const Piece *P) {
    583     return P->getPieceClass() == DiffPieceClass;
    584   }
    585 };
    586 
    587 struct SubstitutionPiece : Piece {
    588   SubstitutionPiece() : Piece(SubstitutionPieceClass) {}
    589 
    590   std::string Name;
    591   std::vector<int> Modifiers;
    592 
    593   static bool classof(const Piece *P) {
    594     return P->getPieceClass() == SubstitutionPieceClass;
    595   }
    596 };
    597 
    598 /// Diagnostic text, parsed into pieces.
    599 
    600 
    601 struct DiagnosticTextBuilder {
    602   DiagnosticTextBuilder(DiagnosticTextBuilder const &) = delete;
    603   DiagnosticTextBuilder &operator=(DiagnosticTextBuilder const &) = delete;
    604 
    605   DiagnosticTextBuilder(RecordKeeper &Records) {
    606     // Build up the list of substitution records.
    607     for (auto *S : Records.getAllDerivedDefinitions("TextSubstitution")) {
    608       EvaluatingRecordGuard Guard(&EvaluatingRecord, S);
    609       Substitutions.try_emplace(
    610           S->getName(), DiagText(*this, S->getValueAsString("Substitution")));
    611     }
    612 
    613     // Check that no diagnostic definitions have the same name as a
    614     // substitution.
    615     for (Record *Diag : Records.getAllDerivedDefinitions("Diagnostic")) {
    616       StringRef Name = Diag->getName();
    617       if (Substitutions.count(Name))
    618         llvm::PrintFatalError(
    619             Diag->getLoc(),
    620             "Diagnostic '" + Name +
    621                 "' has same name as TextSubstitution definition");
    622     }
    623   }
    624 
    625   std::vector<std::string> buildForDocumentation(StringRef Role,
    626                                                  const Record *R);
    627   std::string buildForDefinition(const Record *R);
    628 
    629   Piece *getSubstitution(SubstitutionPiece *S) const {
    630     auto It = Substitutions.find(S->Name);
    631     if (It == Substitutions.end())
    632       PrintFatalError("Failed to find substitution with name: " + S->Name);
    633     return It->second.Root;
    634   }
    635 
    636   LLVM_ATTRIBUTE_NORETURN void PrintFatalError(llvm::Twine const &Msg) const {
    637     assert(EvaluatingRecord && "not evaluating a record?");
    638     llvm::PrintFatalError(EvaluatingRecord->getLoc(), Msg);
    639   }
    640 
    641 private:
    642   struct DiagText {
    643     DiagnosticTextBuilder &Builder;
    644     std::vector<Piece *> AllocatedPieces;
    645     Piece *Root = nullptr;
    646 
    647     template <class T, class... Args> T *New(Args &&... args) {
    648       static_assert(std::is_base_of<Piece, T>::value, "must be piece");
    649       T *Mem = new T(std::forward<Args>(args)...);
    650       AllocatedPieces.push_back(Mem);
    651       return Mem;
    652     }
    653 
    654     DiagText(DiagnosticTextBuilder &Builder, StringRef Text)
    655         : Builder(Builder), Root(parseDiagText(Text)) {}
    656 
    657     Piece *parseDiagText(StringRef &Text, bool Nested = false);
    658     int parseModifier(StringRef &) const;
    659 
    660   public:
    661     DiagText(DiagText &&O) noexcept
    662         : Builder(O.Builder), AllocatedPieces(std::move(O.AllocatedPieces)),
    663           Root(O.Root) {
    664       O.Root = nullptr;
    665     }
    666 
    667     ~DiagText() {
    668       for (Piece *P : AllocatedPieces)
    669         delete P;
    670     }
    671   };
    672 
    673 private:
    674   const Record *EvaluatingRecord = nullptr;
    675   struct EvaluatingRecordGuard {
    676     EvaluatingRecordGuard(const Record **Dest, const Record *New)
    677         : Dest(Dest), Old(*Dest) {
    678       *Dest = New;
    679     }
    680     ~EvaluatingRecordGuard() { *Dest = Old; }
    681     const Record **Dest;
    682     const Record *Old;
    683   };
    684 
    685   StringMap<DiagText> Substitutions;
    686 };
    687 
    688 template <class Derived> struct DiagTextVisitor {
    689   using ModifierMappingsType = Optional<std::vector<int>>;
    690 
    691 private:
    692   Derived &getDerived() { return static_cast<Derived &>(*this); }
    693 
    694 public:
    695   std::vector<int>
    696   getSubstitutionMappings(SubstitutionPiece *P,
    697                           const ModifierMappingsType &Mappings) const {
    698     std::vector<int> NewMappings;
    699     for (int Idx : P->Modifiers)
    700       NewMappings.push_back(mapIndex(Idx, Mappings));
    701     return NewMappings;
    702   }
    703 
    704   struct SubstitutionContext {
    705     SubstitutionContext(DiagTextVisitor &Visitor, SubstitutionPiece *P)
    706         : Visitor(Visitor) {
    707       Substitution = Visitor.Builder.getSubstitution(P);
    708       OldMappings = std::move(Visitor.ModifierMappings);
    709       std::vector<int> NewMappings =
    710           Visitor.getSubstitutionMappings(P, OldMappings);
    711       Visitor.ModifierMappings = std::move(NewMappings);
    712     }
    713 
    714     ~SubstitutionContext() {
    715       Visitor.ModifierMappings = std::move(OldMappings);
    716     }
    717 
    718   private:
    719     DiagTextVisitor &Visitor;
    720     Optional<std::vector<int>> OldMappings;
    721 
    722   public:
    723     Piece *Substitution;
    724   };
    725 
    726 public:
    727   DiagTextVisitor(DiagnosticTextBuilder &Builder) : Builder(Builder) {}
    728 
    729   void Visit(Piece *P) {
    730     switch (P->getPieceClass()) {
    731 #define CASE(T)                                                                \
    732   case T##PieceClass:                                                          \
    733     return getDerived().Visit##T(static_cast<T##Piece *>(P))
    734       CASE(Multi);
    735       CASE(Text);
    736       CASE(Placeholder);
    737       CASE(Select);
    738       CASE(Plural);
    739       CASE(Diff);
    740       CASE(Substitution);
    741 #undef CASE
    742     }
    743   }
    744 
    745   void VisitSubstitution(SubstitutionPiece *P) {
    746     SubstitutionContext Guard(*this, P);
    747     Visit(Guard.Substitution);
    748   }
    749 
    750   int mapIndex(int Idx,
    751                     ModifierMappingsType const &ModifierMappings) const {
    752     if (!ModifierMappings)
    753       return Idx;
    754     if (ModifierMappings->size() <= static_cast<unsigned>(Idx))
    755       Builder.PrintFatalError("Modifier value '" + std::to_string(Idx) +
    756                               "' is not valid for this mapping (has " +
    757                               std::to_string(ModifierMappings->size()) +
    758                               " mappings)");
    759     return (*ModifierMappings)[Idx];
    760   }
    761 
    762   int mapIndex(int Idx) const {
    763     return mapIndex(Idx, ModifierMappings);
    764   }
    765 
    766 protected:
    767   DiagnosticTextBuilder &Builder;
    768   ModifierMappingsType ModifierMappings;
    769 };
    770 
    771 void escapeRST(StringRef Str, std::string &Out) {
    772   for (auto K : Str) {
    773     if (StringRef("`*|_[]\\").count(K))
    774       Out.push_back('\\');
    775     Out.push_back(K);
    776   }
    777 }
    778 
    779 template <typename It> void padToSameLength(It Begin, It End) {
    780   size_t Width = 0;
    781   for (It I = Begin; I != End; ++I)
    782     Width = std::max(Width, I->size());
    783   for (It I = Begin; I != End; ++I)
    784     (*I) += std::string(Width - I->size(), ' ');
    785 }
    786 
    787 template <typename It> void makeTableRows(It Begin, It End) {
    788   if (Begin == End)
    789     return;
    790   padToSameLength(Begin, End);
    791   for (It I = Begin; I != End; ++I)
    792     *I = "|" + *I + "|";
    793 }
    794 
    795 void makeRowSeparator(std::string &Str) {
    796   for (char &K : Str)
    797     K = (K == '|' ? '+' : '-');
    798 }
    799 
    800 struct DiagTextDocPrinter : DiagTextVisitor<DiagTextDocPrinter> {
    801   using BaseTy = DiagTextVisitor<DiagTextDocPrinter>;
    802   DiagTextDocPrinter(DiagnosticTextBuilder &Builder,
    803                      std::vector<std::string> &RST)
    804       : BaseTy(Builder), RST(RST) {}
    805 
    806   void gatherNodes(
    807       Piece *OrigP, const ModifierMappingsType &CurrentMappings,
    808       std::vector<std::pair<Piece *, ModifierMappingsType>> &Pieces) const {
    809     if (auto *Sub = dyn_cast<SubstitutionPiece>(OrigP)) {
    810       ModifierMappingsType NewMappings =
    811           getSubstitutionMappings(Sub, CurrentMappings);
    812       return gatherNodes(Builder.getSubstitution(Sub), NewMappings, Pieces);
    813     }
    814     if (auto *MD = dyn_cast<MultiPiece>(OrigP)) {
    815       for (Piece *Node : MD->Pieces)
    816         gatherNodes(Node, CurrentMappings, Pieces);
    817       return;
    818     }
    819     Pieces.push_back(std::make_pair(OrigP, CurrentMappings));
    820   }
    821 
    822   void VisitMulti(MultiPiece *P) {
    823     if (P->Pieces.empty()) {
    824       RST.push_back("");
    825       return;
    826     }
    827 
    828     if (P->Pieces.size() == 1)
    829       return Visit(P->Pieces[0]);
    830 
    831     // Flatten the list of nodes, replacing any substitution pieces with the
    832     // recursively flattened substituted node.
    833     std::vector<std::pair<Piece *, ModifierMappingsType>> Pieces;
    834     gatherNodes(P, ModifierMappings, Pieces);
    835 
    836     std::string EmptyLinePrefix;
    837     size_t Start = RST.size();
    838     bool HasMultipleLines = true;
    839     for (const std::pair<Piece *, ModifierMappingsType> &NodePair : Pieces) {
    840       std::vector<std::string> Lines;
    841       DiagTextDocPrinter Visitor{Builder, Lines};
    842       Visitor.ModifierMappings = NodePair.second;
    843       Visitor.Visit(NodePair.first);
    844 
    845       if (Lines.empty())
    846         continue;
    847 
    848       // We need a vertical separator if either this or the previous piece is a
    849       // multi-line piece, or this is the last piece.
    850       const char *Separator = (Lines.size() > 1 || HasMultipleLines) ? "|" : "";
    851       HasMultipleLines = Lines.size() > 1;
    852 
    853       if (Start + Lines.size() > RST.size())
    854         RST.resize(Start + Lines.size(), EmptyLinePrefix);
    855 
    856       padToSameLength(Lines.begin(), Lines.end());
    857       for (size_t I = 0; I != Lines.size(); ++I)
    858         RST[Start + I] += Separator + Lines[I];
    859       std::string Empty(Lines[0].size(), ' ');
    860       for (size_t I = Start + Lines.size(); I != RST.size(); ++I)
    861         RST[I] += Separator + Empty;
    862       EmptyLinePrefix += Separator + Empty;
    863     }
    864     for (size_t I = Start; I != RST.size(); ++I)
    865       RST[I] += "|";
    866     EmptyLinePrefix += "|";
    867 
    868     makeRowSeparator(EmptyLinePrefix);
    869     RST.insert(RST.begin() + Start, EmptyLinePrefix);
    870     RST.insert(RST.end(), EmptyLinePrefix);
    871   }
    872 
    873   void VisitText(TextPiece *P) {
    874     RST.push_back("");
    875     auto &S = RST.back();
    876 
    877     StringRef T = P->Text;
    878     while (!T.empty() && T.front() == ' ') {
    879       RST.back() += " |nbsp| ";
    880       T = T.drop_front();
    881     }
    882 
    883     std::string Suffix;
    884     while (!T.empty() && T.back() == ' ') {
    885       Suffix += " |nbsp| ";
    886       T = T.drop_back();
    887     }
    888 
    889     if (!T.empty()) {
    890       S += ':';
    891       S += P->Role;
    892       S += ":`";
    893       escapeRST(T, S);
    894       S += '`';
    895     }
    896 
    897     S += Suffix;
    898   }
    899 
    900   void VisitPlaceholder(PlaceholderPiece *P) {
    901     RST.push_back(std::string(":placeholder:`") +
    902                   char('A' + mapIndex(P->Index)) + "`");
    903   }
    904 
    905   void VisitSelect(SelectPiece *P) {
    906     std::vector<size_t> SeparatorIndexes;
    907     SeparatorIndexes.push_back(RST.size());
    908     RST.emplace_back();
    909     for (auto *O : P->Options) {
    910       Visit(O);
    911       SeparatorIndexes.push_back(RST.size());
    912       RST.emplace_back();
    913     }
    914 
    915     makeTableRows(RST.begin() + SeparatorIndexes.front(),
    916                   RST.begin() + SeparatorIndexes.back() + 1);
    917     for (size_t I : SeparatorIndexes)
    918       makeRowSeparator(RST[I]);
    919   }
    920 
    921   void VisitPlural(PluralPiece *P) { VisitSelect(P); }
    922 
    923   void VisitDiff(DiffPiece *P) { Visit(P->Options[1]); }
    924 
    925   std::vector<std::string> &RST;
    926 };
    927 
    928 struct DiagTextPrinter : DiagTextVisitor<DiagTextPrinter> {
    929 public:
    930   using BaseTy = DiagTextVisitor<DiagTextPrinter>;
    931   DiagTextPrinter(DiagnosticTextBuilder &Builder, std::string &Result)
    932       : BaseTy(Builder), Result(Result) {}
    933 
    934   void VisitMulti(MultiPiece *P) {
    935     for (auto *Child : P->Pieces)
    936       Visit(Child);
    937   }
    938   void VisitText(TextPiece *P) { Result += P->Text; }
    939   void VisitPlaceholder(PlaceholderPiece *P) {
    940     Result += "%";
    941     Result += getModifierName(P->Kind);
    942     addInt(mapIndex(P->Index));
    943   }
    944   void VisitSelect(SelectPiece *P) {
    945     Result += "%";
    946     Result += getModifierName(P->ModKind);
    947     if (P->ModKind == MT_Select) {
    948       Result += "{";
    949       for (auto *D : P->Options) {
    950         Visit(D);
    951         Result += '|';
    952       }
    953       if (!P->Options.empty())
    954         Result.erase(--Result.end());
    955       Result += '}';
    956     }
    957     addInt(mapIndex(P->Index));
    958   }
    959 
    960   void VisitPlural(PluralPiece *P) {
    961     Result += "%plural{";
    962     assert(P->Options.size() == P->OptionPrefixes.size());
    963     for (unsigned I = 0, End = P->Options.size(); I < End; ++I) {
    964       if (P->OptionPrefixes[I])
    965         Visit(P->OptionPrefixes[I]);
    966       Visit(P->Options[I]);
    967       Result += "|";
    968     }
    969     if (!P->Options.empty())
    970       Result.erase(--Result.end());
    971     Result += '}';
    972     addInt(mapIndex(P->Index));
    973   }
    974 
    975   void VisitDiff(DiffPiece *P) {
    976     Result += "%diff{";
    977     Visit(P->Options[0]);
    978     Result += "|";
    979     Visit(P->Options[1]);
    980     Result += "}";
    981     addInt(mapIndex(P->Indexes[0]));
    982     Result += ",";
    983     addInt(mapIndex(P->Indexes[1]));
    984   }
    985 
    986   void addInt(int Val) { Result += std::to_string(Val); }
    987 
    988   std::string &Result;
    989 };
    990 
    991 int DiagnosticTextBuilder::DiagText::parseModifier(StringRef &Text) const {
    992   if (Text.empty() || !isdigit(Text[0]))
    993     Builder.PrintFatalError("expected modifier in diagnostic");
    994   int Val = 0;
    995   do {
    996     Val *= 10;
    997     Val += Text[0] - '0';
    998     Text = Text.drop_front();
    999   } while (!Text.empty() && isdigit(Text[0]));
   1000   return Val;
   1001 }
   1002 
   1003 Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text,
   1004                                                       bool Nested) {
   1005   std::vector<Piece *> Parsed;
   1006 
   1007   while (!Text.empty()) {
   1008     size_t End = (size_t)-2;
   1009     do
   1010       End = Nested ? Text.find_first_of("%|}", End + 2)
   1011                    : Text.find_first_of('%', End + 2);
   1012     while (End < Text.size() - 1 && Text[End] == '%' &&
   1013            (Text[End + 1] == '%' || Text[End + 1] == '|'));
   1014 
   1015     if (End) {
   1016       Parsed.push_back(New<TextPiece>(Text.slice(0, End), "diagtext"));
   1017       Text = Text.slice(End, StringRef::npos);
   1018       if (Text.empty())
   1019         break;
   1020     }
   1021 
   1022     if (Text[0] == '|' || Text[0] == '}')
   1023       break;
   1024 
   1025     // Drop the '%'.
   1026     Text = Text.drop_front();
   1027 
   1028     // Extract the (optional) modifier.
   1029     size_t ModLength = Text.find_first_of("0123456789{");
   1030     StringRef Modifier = Text.slice(0, ModLength);
   1031     Text = Text.slice(ModLength, StringRef::npos);
   1032     ModifierType ModType = llvm::StringSwitch<ModifierType>{Modifier}
   1033                                .Case("select", MT_Select)
   1034                                .Case("sub", MT_Sub)
   1035                                .Case("diff", MT_Diff)
   1036                                .Case("plural", MT_Plural)
   1037                                .Case("s", MT_S)
   1038                                .Case("ordinal", MT_Ordinal)
   1039                                .Case("q", MT_Q)
   1040                                .Case("objcclass", MT_ObjCClass)
   1041                                .Case("objcinstance", MT_ObjCInstance)
   1042                                .Case("", MT_Placeholder)
   1043                                .Default(MT_Unknown);
   1044 
   1045     switch (ModType) {
   1046     case MT_Unknown:
   1047       Builder.PrintFatalError("Unknown modifier type: " + Modifier);
   1048     case MT_Select: {
   1049       SelectPiece *Select = New<SelectPiece>(MT_Select);
   1050       do {
   1051         Text = Text.drop_front(); // '{' or '|'
   1052         Select->Options.push_back(parseDiagText(Text, true));
   1053         assert(!Text.empty() && "malformed %select");
   1054       } while (Text.front() == '|');
   1055       // Drop the trailing '}'.
   1056       Text = Text.drop_front(1);
   1057       Select->Index = parseModifier(Text);
   1058       Parsed.push_back(Select);
   1059       continue;
   1060     }
   1061     case MT_Plural: {
   1062       PluralPiece *Plural = New<PluralPiece>();
   1063       do {
   1064         Text = Text.drop_front(); // '{' or '|'
   1065         size_t End = Text.find_first_of(":");
   1066         if (End == StringRef::npos)
   1067           Builder.PrintFatalError("expected ':' while parsing %plural");
   1068         ++End;
   1069         assert(!Text.empty());
   1070         Plural->OptionPrefixes.push_back(
   1071             New<TextPiece>(Text.slice(0, End), "diagtext"));
   1072         Text = Text.slice(End, StringRef::npos);
   1073         Plural->Options.push_back(parseDiagText(Text, true));
   1074         assert(!Text.empty() && "malformed %select");
   1075       } while (Text.front() == '|');
   1076       // Drop the trailing '}'.
   1077       Text = Text.drop_front(1);
   1078       Plural->Index = parseModifier(Text);
   1079       Parsed.push_back(Plural);
   1080       continue;
   1081     }
   1082     case MT_Sub: {
   1083       SubstitutionPiece *Sub = New<SubstitutionPiece>();
   1084       Text = Text.drop_front(); // '{'
   1085       size_t NameSize = Text.find_first_of('}');
   1086       assert(NameSize != size_t(-1) && "failed to find the end of the name");
   1087       assert(NameSize != 0 && "empty name?");
   1088       Sub->Name = Text.substr(0, NameSize).str();
   1089       Text = Text.drop_front(NameSize);
   1090       Text = Text.drop_front(); // '}'
   1091       if (!Text.empty()) {
   1092         while (true) {
   1093           if (!isdigit(Text[0]))
   1094             break;
   1095           Sub->Modifiers.push_back(parseModifier(Text));
   1096           if (Text.empty() || Text[0] != ',')
   1097             break;
   1098           Text = Text.drop_front(); // ','
   1099           assert(!Text.empty() && isdigit(Text[0]) &&
   1100                  "expected another modifier");
   1101         }
   1102       }
   1103       Parsed.push_back(Sub);
   1104       continue;
   1105     }
   1106     case MT_Diff: {
   1107       DiffPiece *Diff = New<DiffPiece>();
   1108       Text = Text.drop_front(); // '{'
   1109       Diff->Options[0] = parseDiagText(Text, true);
   1110       Text = Text.drop_front(); // '|'
   1111       Diff->Options[1] = parseDiagText(Text, true);
   1112 
   1113       Text = Text.drop_front(); // '}'
   1114       Diff->Indexes[0] = parseModifier(Text);
   1115       Text = Text.drop_front(); // ','
   1116       Diff->Indexes[1] = parseModifier(Text);
   1117       Parsed.push_back(Diff);
   1118       continue;
   1119     }
   1120     case MT_S: {
   1121       SelectPiece *Select = New<SelectPiece>(ModType);
   1122       Select->Options.push_back(New<TextPiece>(""));
   1123       Select->Options.push_back(New<TextPiece>("s", "diagtext"));
   1124       Select->Index = parseModifier(Text);
   1125       Parsed.push_back(Select);
   1126       continue;
   1127     }
   1128     case MT_Q:
   1129     case MT_Placeholder:
   1130     case MT_ObjCClass:
   1131     case MT_ObjCInstance:
   1132     case MT_Ordinal: {
   1133       Parsed.push_back(New<PlaceholderPiece>(ModType, parseModifier(Text)));
   1134       continue;
   1135     }
   1136     }
   1137   }
   1138 
   1139   return New<MultiPiece>(Parsed);
   1140 }
   1141 
   1142 std::vector<std::string>
   1143 DiagnosticTextBuilder::buildForDocumentation(StringRef Severity,
   1144                                              const Record *R) {
   1145   EvaluatingRecordGuard Guard(&EvaluatingRecord, R);
   1146   StringRef Text = R->getValueAsString("Text");
   1147 
   1148   DiagText D(*this, Text);
   1149   TextPiece *Prefix = D.New<TextPiece>(Severity, Severity);
   1150   Prefix->Text += ": ";
   1151   auto *MP = dyn_cast<MultiPiece>(D.Root);
   1152   if (!MP) {
   1153     MP = D.New<MultiPiece>();
   1154     MP->Pieces.push_back(D.Root);
   1155     D.Root = MP;
   1156   }
   1157   MP->Pieces.insert(MP->Pieces.begin(), Prefix);
   1158   std::vector<std::string> Result;
   1159   DiagTextDocPrinter{*this, Result}.Visit(D.Root);
   1160   return Result;
   1161 }
   1162 
   1163 std::string DiagnosticTextBuilder::buildForDefinition(const Record *R) {
   1164   EvaluatingRecordGuard Guard(&EvaluatingRecord, R);
   1165   StringRef Text = R->getValueAsString("Text");
   1166   DiagText D(*this, Text);
   1167   std::string Result;
   1168   DiagTextPrinter{*this, Result}.Visit(D.Root);
   1169   return Result;
   1170 }
   1171 
   1172 } // namespace
   1173 
   1174 //===----------------------------------------------------------------------===//
   1175 // Warning Tables (.inc file) generation.
   1176 //===----------------------------------------------------------------------===//
   1177 
   1178 static bool isError(const Record &Diag) {
   1179   const std::string &ClsName = Diag.getValueAsDef("Class")->getName();
   1180   return ClsName == "CLASS_ERROR";
   1181 }
   1182 
   1183 static bool isRemark(const Record &Diag) {
   1184   const std::string &ClsName = Diag.getValueAsDef("Class")->getName();
   1185   return ClsName == "CLASS_REMARK";
   1186 }
   1187 
   1188 
   1189 /// ClangDiagsDefsEmitter - The top-level class emits .def files containing
   1190 /// declarations of Clang diagnostics.
   1191 void clang::EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
   1192                                const std::string &Component) {
   1193   // Write the #if guard
   1194   if (!Component.empty()) {
   1195     std::string ComponentName = StringRef(Component).upper();
   1196     OS << "#ifdef " << ComponentName << "START\n";
   1197     OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
   1198        << ",\n";
   1199     OS << "#undef " << ComponentName << "START\n";
   1200     OS << "#endif\n\n";
   1201   }
   1202 
   1203   DiagnosticTextBuilder DiagTextBuilder(Records);
   1204 
   1205   std::vector<Record *> Diags = Records.getAllDerivedDefinitions("Diagnostic");
   1206 
   1207   std::vector<Record*> DiagGroups
   1208     = Records.getAllDerivedDefinitions("DiagGroup");
   1209 
   1210   std::map<std::string, GroupInfo> DiagsInGroup;
   1211   groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
   1212 
   1213   DiagCategoryIDMap CategoryIDs(Records);
   1214   DiagGroupParentMap DGParentMap(Records);
   1215 
   1216   // Compute the set of diagnostics that are in -Wpedantic.
   1217   RecordSet DiagsInPedantic;
   1218   InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
   1219   inferPedantic.compute(&DiagsInPedantic, (RecordVec*)nullptr);
   1220 
   1221   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
   1222     const Record &R = *Diags[i];
   1223 
   1224     // Check if this is an error that is accidentally in a warning
   1225     // group.
   1226     if (isError(R)) {
   1227       if (DefInit *Group = dyn_cast<DefInit>(R.getValueInit("Group"))) {
   1228         const Record *GroupRec = Group->getDef();
   1229         const std::string &GroupName = GroupRec->getValueAsString("GroupName");
   1230         PrintFatalError(R.getLoc(), "Error " + R.getName() +
   1231                       " cannot be in a warning group [" + GroupName + "]");
   1232       }
   1233     }
   1234 
   1235     // Check that all remarks have an associated diagnostic group.
   1236     if (isRemark(R)) {
   1237       if (!isa<DefInit>(R.getValueInit("Group"))) {
   1238         PrintFatalError(R.getLoc(), "Error " + R.getName() +
   1239                                         " not in any diagnostic group");
   1240       }
   1241     }
   1242 
   1243     // Filter by component.
   1244     if (!Component.empty() && Component != R.getValueAsString("Component"))
   1245       continue;
   1246 
   1247     OS << "DIAG(" << R.getName() << ", ";
   1248     OS << R.getValueAsDef("Class")->getName();
   1249     OS << ", (unsigned)diag::Severity::"
   1250        << R.getValueAsDef("DefaultSeverity")->getValueAsString("Name");
   1251 
   1252     // Description string.
   1253     OS << ", \"";
   1254     OS.write_escaped(DiagTextBuilder.buildForDefinition(&R)) << '"';
   1255 
   1256     // Warning associated with the diagnostic. This is stored as an index into
   1257     // the alphabetically sorted warning table.
   1258     if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
   1259       std::map<std::string, GroupInfo>::iterator I =
   1260           DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName"));
   1261       assert(I != DiagsInGroup.end());
   1262       OS << ", " << I->second.IDNo;
   1263     } else if (DiagsInPedantic.count(&R)) {
   1264       std::map<std::string, GroupInfo>::iterator I =
   1265         DiagsInGroup.find("pedantic");
   1266       assert(I != DiagsInGroup.end() && "pedantic group not defined");
   1267       OS << ", " << I->second.IDNo;
   1268     } else {
   1269       OS << ", 0";
   1270     }
   1271 
   1272     // SFINAE response.
   1273     OS << ", " << R.getValueAsDef("SFINAE")->getName();
   1274 
   1275     // Default warning has no Werror bit.
   1276     if (R.getValueAsBit("WarningNoWerror"))
   1277       OS << ", true";
   1278     else
   1279       OS << ", false";
   1280 
   1281     if (R.getValueAsBit("ShowInSystemHeader"))
   1282       OS << ", true";
   1283     else
   1284       OS << ", false";
   1285 
   1286     // Category number.
   1287     OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
   1288     OS << ")\n";
   1289   }
   1290 }
   1291 
   1292 //===----------------------------------------------------------------------===//
   1293 // Warning Group Tables generation
   1294 //===----------------------------------------------------------------------===//
   1295 
   1296 static std::string getDiagCategoryEnum(llvm::StringRef name) {
   1297   if (name.empty())
   1298     return "DiagCat_None";
   1299   SmallString<256> enumName = llvm::StringRef("DiagCat_");
   1300   for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
   1301     enumName += isalnum(*I) ? *I : '_';
   1302   return enumName.str();
   1303 }
   1304 
   1305 /// Emit the array of diagnostic subgroups.
   1306 ///
   1307 /// The array of diagnostic subgroups contains for each group a list of its
   1308 /// subgroups. The individual lists are separated by '-1'. Groups with no
   1309 /// subgroups are skipped.
   1310 ///
   1311 /// \code
   1312 ///   static const int16_t DiagSubGroups[] = {
   1313 ///     /* Empty */ -1,
   1314 ///     /* DiagSubGroup0 */ 142, -1,
   1315 ///     /* DiagSubGroup13 */ 265, 322, 399, -1
   1316 ///   }
   1317 /// \endcode
   1318 ///
   1319 static void emitDiagSubGroups(std::map<std::string, GroupInfo> &DiagsInGroup,
   1320                               RecordVec &GroupsInPedantic, raw_ostream &OS) {
   1321   OS << "static const int16_t DiagSubGroups[] = {\n"
   1322      << "  /* Empty */ -1,\n";
   1323   for (auto const &I : DiagsInGroup) {
   1324     const bool IsPedantic = I.first == "pedantic";
   1325 
   1326     const std::vector<std::string> &SubGroups = I.second.SubGroups;
   1327     if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty())) {
   1328       OS << "  /* DiagSubGroup" << I.second.IDNo << " */ ";
   1329       for (auto const &SubGroup : SubGroups) {
   1330         std::map<std::string, GroupInfo>::const_iterator RI =
   1331             DiagsInGroup.find(SubGroup);
   1332         assert(RI != DiagsInGroup.end() && "Referenced without existing?");
   1333         OS << RI->second.IDNo << ", ";
   1334       }
   1335       // Emit the groups implicitly in "pedantic".
   1336       if (IsPedantic) {
   1337         for (auto const &Group : GroupsInPedantic) {
   1338           const std::string &GroupName = Group->getValueAsString("GroupName");
   1339           std::map<std::string, GroupInfo>::const_iterator RI =
   1340               DiagsInGroup.find(GroupName);
   1341           assert(RI != DiagsInGroup.end() && "Referenced without existing?");
   1342           OS << RI->second.IDNo << ", ";
   1343         }
   1344       }
   1345 
   1346       OS << "-1,\n";
   1347     }
   1348   }
   1349   OS << "};\n\n";
   1350 }
   1351 
   1352 /// Emit the list of diagnostic arrays.
   1353 ///
   1354 /// This data structure is a large array that contains itself arrays of varying
   1355 /// size. Each array represents a list of diagnostics. The different arrays are
   1356 /// separated by the value '-1'.
   1357 ///
   1358 /// \code
   1359 ///   static const int16_t DiagArrays[] = {
   1360 ///     /* Empty */ -1,
   1361 ///     /* DiagArray1 */ diag::warn_pragma_message,
   1362 ///                      -1,
   1363 ///     /* DiagArray2 */ diag::warn_abs_too_small,
   1364 ///                      diag::warn_unsigned_abs,
   1365 ///                      diag::warn_wrong_absolute_value_type,
   1366 ///                      -1
   1367 ///   };
   1368 /// \endcode
   1369 ///
   1370 static void emitDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
   1371                            RecordVec &DiagsInPedantic, raw_ostream &OS) {
   1372   OS << "static const int16_t DiagArrays[] = {\n"
   1373      << "  /* Empty */ -1,\n";
   1374   for (auto const &I : DiagsInGroup) {
   1375     const bool IsPedantic = I.first == "pedantic";
   1376 
   1377     const std::vector<const Record *> &V = I.second.DiagsInGroup;
   1378     if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) {
   1379       OS << "  /* DiagArray" << I.second.IDNo << " */ ";
   1380       for (auto *Record : V)
   1381         OS << "diag::" << Record->getName() << ", ";
   1382       // Emit the diagnostics implicitly in "pedantic".
   1383       if (IsPedantic) {
   1384         for (auto const &Diag : DiagsInPedantic)
   1385           OS << "diag::" << Diag->getName() << ", ";
   1386       }
   1387       OS << "-1,\n";
   1388     }
   1389   }
   1390   OS << "};\n\n";
   1391 }
   1392 
   1393 /// Emit a list of group names.
   1394 ///
   1395 /// This creates a long string which by itself contains a list of pascal style
   1396 /// strings, which consist of a length byte directly followed by the string.
   1397 ///
   1398 /// \code
   1399 ///   static const char DiagGroupNames[] = {
   1400 ///     \000\020#pragma-messages\t#warnings\020CFString-literal"
   1401 ///   };
   1402 /// \endcode
   1403 static void emitDiagGroupNames(StringToOffsetTable &GroupNames,
   1404                                raw_ostream &OS) {
   1405   OS << "static const char DiagGroupNames[] = {\n";
   1406   GroupNames.EmitString(OS);
   1407   OS << "};\n\n";
   1408 }
   1409 
   1410 /// Emit diagnostic arrays and related data structures.
   1411 ///
   1412 /// This creates the actual diagnostic array, an array of diagnostic subgroups
   1413 /// and an array of subgroup names.
   1414 ///
   1415 /// \code
   1416 ///  #ifdef GET_DIAG_ARRAYS
   1417 ///     static const int16_t DiagArrays[];
   1418 ///     static const int16_t DiagSubGroups[];
   1419 ///     static const char DiagGroupNames[];
   1420 ///  #endif
   1421 ///  \endcode
   1422 static void emitAllDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
   1423                               RecordVec &DiagsInPedantic,
   1424                               RecordVec &GroupsInPedantic,
   1425                               StringToOffsetTable &GroupNames,
   1426                               raw_ostream &OS) {
   1427   OS << "\n#ifdef GET_DIAG_ARRAYS\n";
   1428   emitDiagArrays(DiagsInGroup, DiagsInPedantic, OS);
   1429   emitDiagSubGroups(DiagsInGroup, GroupsInPedantic, OS);
   1430   emitDiagGroupNames(GroupNames, OS);
   1431   OS << "#endif // GET_DIAG_ARRAYS\n\n";
   1432 }
   1433 
   1434 /// Emit diagnostic table.
   1435 ///
   1436 /// The table is sorted by the name of the diagnostic group. Each element
   1437 /// consists of the name of the diagnostic group (given as offset in the
   1438 /// group name table), a reference to a list of diagnostics (optional) and a
   1439 /// reference to a set of subgroups (optional).
   1440 ///
   1441 /// \code
   1442 /// #ifdef GET_DIAG_TABLE
   1443 ///  {/* abi */              159, /* DiagArray11 */ 19, /* Empty */          0},
   1444 ///  {/* aggregate-return */ 180, /* Empty */        0, /* Empty */          0},
   1445 ///  {/* all */              197, /* Empty */        0, /* DiagSubGroup13 */ 3},
   1446 ///  {/* deprecated */       1981,/* DiagArray1 */ 348, /* DiagSubGroup3 */  9},
   1447 /// #endif
   1448 /// \endcode
   1449 static void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup,
   1450                           RecordVec &DiagsInPedantic,
   1451                           RecordVec &GroupsInPedantic,
   1452                           StringToOffsetTable &GroupNames, raw_ostream &OS) {
   1453   unsigned MaxLen = 0;
   1454 
   1455   for (auto const &I: DiagsInGroup)
   1456     MaxLen = std::max(MaxLen, (unsigned)I.first.size());
   1457 
   1458   OS << "\n#ifdef GET_DIAG_TABLE\n";
   1459   unsigned SubGroupIndex = 1, DiagArrayIndex = 1;
   1460   for (auto const &I: DiagsInGroup) {
   1461     // Group option string.
   1462     OS << "  { /* ";
   1463     if (I.first.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
   1464                                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   1465                                    "0123456789!@#$%^*-+=:?") !=
   1466         std::string::npos)
   1467       PrintFatalError("Invalid character in diagnostic group '" + I.first +
   1468                       "'");
   1469     OS << I.first << " */ " << std::string(MaxLen - I.first.size(), ' ');
   1470     // Store a pascal-style length byte at the beginning of the string.
   1471     std::string Name = char(I.first.size()) + I.first;
   1472     OS << GroupNames.GetOrAddStringOffset(Name, false) << ", ";
   1473 
   1474     // Special handling for 'pedantic'.
   1475     const bool IsPedantic = I.first == "pedantic";
   1476 
   1477     // Diagnostics in the group.
   1478     const std::vector<const Record *> &V = I.second.DiagsInGroup;
   1479     const bool hasDiags =
   1480         !V.empty() || (IsPedantic && !DiagsInPedantic.empty());
   1481     if (hasDiags) {
   1482       OS << "/* DiagArray" << I.second.IDNo << " */ " << DiagArrayIndex
   1483          << ", ";
   1484       if (IsPedantic)
   1485         DiagArrayIndex += DiagsInPedantic.size();
   1486       DiagArrayIndex += V.size() + 1;
   1487     } else {
   1488       OS << "/* Empty */     0, ";
   1489     }
   1490 
   1491     // Subgroups.
   1492     const std::vector<std::string> &SubGroups = I.second.SubGroups;
   1493     const bool hasSubGroups =
   1494         !SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty());
   1495     if (hasSubGroups) {
   1496       OS << "/* DiagSubGroup" << I.second.IDNo << " */ " << SubGroupIndex;
   1497       if (IsPedantic)
   1498         SubGroupIndex += GroupsInPedantic.size();
   1499       SubGroupIndex += SubGroups.size() + 1;
   1500     } else {
   1501       OS << "/* Empty */         0";
   1502     }
   1503 
   1504     OS << " },\n";
   1505   }
   1506   OS << "#endif // GET_DIAG_TABLE\n\n";
   1507 }
   1508 
   1509 /// Emit the table of diagnostic categories.
   1510 ///
   1511 /// The table has the form of macro calls that have two parameters. The
   1512 /// category's name as well as an enum that represents the category. The
   1513 /// table can be used by defining the macro 'CATEGORY' and including this
   1514 /// table right after.
   1515 ///
   1516 /// \code
   1517 /// #ifdef GET_CATEGORY_TABLE
   1518 ///   CATEGORY("Semantic Issue", DiagCat_Semantic_Issue)
   1519 ///   CATEGORY("Lambda Issue", DiagCat_Lambda_Issue)
   1520 /// #endif
   1521 /// \endcode
   1522 static void emitCategoryTable(RecordKeeper &Records, raw_ostream &OS) {
   1523   DiagCategoryIDMap CategoriesByID(Records);
   1524   OS << "\n#ifdef GET_CATEGORY_TABLE\n";
   1525   for (auto const &C : CategoriesByID)
   1526     OS << "CATEGORY(\"" << C << "\", " << getDiagCategoryEnum(C) << ")\n";
   1527   OS << "#endif // GET_CATEGORY_TABLE\n\n";
   1528 }
   1529 
   1530 void clang::EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
   1531   // Compute a mapping from a DiagGroup to all of its parents.
   1532   DiagGroupParentMap DGParentMap(Records);
   1533 
   1534   std::vector<Record *> Diags = Records.getAllDerivedDefinitions("Diagnostic");
   1535 
   1536   std::vector<Record *> DiagGroups =
   1537       Records.getAllDerivedDefinitions("DiagGroup");
   1538 
   1539   std::map<std::string, GroupInfo> DiagsInGroup;
   1540   groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
   1541 
   1542   // All extensions are implicitly in the "pedantic" group.  Record the
   1543   // implicit set of groups in the "pedantic" group, and use this information
   1544   // later when emitting the group information for Pedantic.
   1545   RecordVec DiagsInPedantic;
   1546   RecordVec GroupsInPedantic;
   1547   InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
   1548   inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic);
   1549 
   1550   StringToOffsetTable GroupNames;
   1551   for (std::map<std::string, GroupInfo>::const_iterator
   1552            I = DiagsInGroup.begin(),
   1553            E = DiagsInGroup.end();
   1554        I != E; ++I) {
   1555     // Store a pascal-style length byte at the beginning of the string.
   1556     std::string Name = char(I->first.size()) + I->first;
   1557     GroupNames.GetOrAddStringOffset(Name, false);
   1558   }
   1559 
   1560   emitAllDiagArrays(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
   1561                     OS);
   1562   emitDiagTable(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
   1563                 OS);
   1564   emitCategoryTable(Records, OS);
   1565 }
   1566 
   1567 //===----------------------------------------------------------------------===//
   1568 // Diagnostic name index generation
   1569 //===----------------------------------------------------------------------===//
   1570 
   1571 namespace {
   1572 struct RecordIndexElement
   1573 {
   1574   RecordIndexElement() {}
   1575   explicit RecordIndexElement(Record const &R):
   1576     Name(R.getName()) {}
   1577 
   1578   std::string Name;
   1579 };
   1580 } // end anonymous namespace.
   1581 
   1582 void clang::EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
   1583   const std::vector<Record*> &Diags =
   1584     Records.getAllDerivedDefinitions("Diagnostic");
   1585 
   1586   std::vector<RecordIndexElement> Index;
   1587   Index.reserve(Diags.size());
   1588   for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
   1589     const Record &R = *(Diags[i]);
   1590     Index.push_back(RecordIndexElement(R));
   1591   }
   1592 
   1593   llvm::sort(Index,
   1594              [](const RecordIndexElement &Lhs, const RecordIndexElement &Rhs) {
   1595                return Lhs.Name < Rhs.Name;
   1596              });
   1597 
   1598   for (unsigned i = 0, e = Index.size(); i != e; ++i) {
   1599     const RecordIndexElement &R = Index[i];
   1600 
   1601     OS << "DIAG_NAME_INDEX(" << R.Name << ")\n";
   1602   }
   1603 }
   1604 
   1605 //===----------------------------------------------------------------------===//
   1606 // Diagnostic documentation generation
   1607 //===----------------------------------------------------------------------===//
   1608 
   1609 namespace docs {
   1610 namespace {
   1611 
   1612 bool isRemarkGroup(const Record *DiagGroup,
   1613                    const std::map<std::string, GroupInfo> &DiagsInGroup) {
   1614   bool AnyRemarks = false, AnyNonRemarks = false;
   1615 
   1616   std::function<void(StringRef)> Visit = [&](StringRef GroupName) {
   1617     auto &GroupInfo = DiagsInGroup.find(GroupName)->second;
   1618     for (const Record *Diag : GroupInfo.DiagsInGroup)
   1619       (isRemark(*Diag) ? AnyRemarks : AnyNonRemarks) = true;
   1620     for (const auto &Name : GroupInfo.SubGroups)
   1621       Visit(Name);
   1622   };
   1623   Visit(DiagGroup->getValueAsString("GroupName"));
   1624 
   1625   if (AnyRemarks && AnyNonRemarks)
   1626     PrintFatalError(
   1627         DiagGroup->getLoc(),
   1628         "Diagnostic group contains both remark and non-remark diagnostics");
   1629   return AnyRemarks;
   1630 }
   1631 
   1632 std::string getDefaultSeverity(const Record *Diag) {
   1633   return Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name");
   1634 }
   1635 
   1636 std::set<std::string>
   1637 getDefaultSeverities(const Record *DiagGroup,
   1638                      const std::map<std::string, GroupInfo> &DiagsInGroup) {
   1639   std::set<std::string> States;
   1640 
   1641   std::function<void(StringRef)> Visit = [&](StringRef GroupName) {
   1642     auto &GroupInfo = DiagsInGroup.find(GroupName)->second;
   1643     for (const Record *Diag : GroupInfo.DiagsInGroup)
   1644       States.insert(getDefaultSeverity(Diag));
   1645     for (const auto &Name : GroupInfo.SubGroups)
   1646       Visit(Name);
   1647   };
   1648   Visit(DiagGroup->getValueAsString("GroupName"));
   1649   return States;
   1650 }
   1651 
   1652 void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') {
   1653   OS << Str << "\n" << std::string(Str.size(), Kind) << "\n";
   1654 }
   1655 
   1656 void writeDiagnosticText(DiagnosticTextBuilder &Builder, const Record *R,
   1657                          StringRef Role, raw_ostream &OS) {
   1658   StringRef Text = R->getValueAsString("Text");
   1659   if (Text == "%0")
   1660     OS << "The text of this diagnostic is not controlled by Clang.\n\n";
   1661   else {
   1662     std::vector<std::string> Out = Builder.buildForDocumentation(Role, R);
   1663     for (auto &Line : Out)
   1664       OS << Line << "\n";
   1665     OS << "\n";
   1666   }
   1667 }
   1668 
   1669 }  // namespace
   1670 }  // namespace docs
   1671 
   1672 void clang::EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
   1673   using namespace docs;
   1674 
   1675   // Get the documentation introduction paragraph.
   1676   const Record *Documentation = Records.getDef("GlobalDocumentation");
   1677   if (!Documentation) {
   1678     PrintFatalError("The Documentation top-level definition is missing, "
   1679                     "no documentation will be generated.");
   1680     return;
   1681   }
   1682 
   1683   OS << Documentation->getValueAsString("Intro") << "\n";
   1684 
   1685   DiagnosticTextBuilder Builder(Records);
   1686 
   1687   std::vector<Record*> Diags =
   1688       Records.getAllDerivedDefinitions("Diagnostic");
   1689 
   1690   std::vector<Record*> DiagGroups =
   1691       Records.getAllDerivedDefinitions("DiagGroup");
   1692   llvm::sort(DiagGroups, diagGroupBeforeByName);
   1693 
   1694   DiagGroupParentMap DGParentMap(Records);
   1695 
   1696   std::map<std::string, GroupInfo> DiagsInGroup;
   1697   groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
   1698 
   1699   // Compute the set of diagnostics that are in -Wpedantic.
   1700   {
   1701     RecordSet DiagsInPedanticSet;
   1702     RecordSet GroupsInPedanticSet;
   1703     InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
   1704     inferPedantic.compute(&DiagsInPedanticSet, &GroupsInPedanticSet);
   1705     auto &PedDiags = DiagsInGroup["pedantic"];
   1706     // Put the diagnostics into a deterministic order.
   1707     RecordVec DiagsInPedantic(DiagsInPedanticSet.begin(),
   1708                               DiagsInPedanticSet.end());
   1709     RecordVec GroupsInPedantic(GroupsInPedanticSet.begin(),
   1710                                GroupsInPedanticSet.end());
   1711     llvm::sort(DiagsInPedantic, beforeThanCompare);
   1712     llvm::sort(GroupsInPedantic, beforeThanCompare);
   1713     PedDiags.DiagsInGroup.insert(PedDiags.DiagsInGroup.end(),
   1714                                  DiagsInPedantic.begin(),
   1715                                  DiagsInPedantic.end());
   1716     for (auto *Group : GroupsInPedantic)
   1717       PedDiags.SubGroups.push_back(Group->getValueAsString("GroupName"));
   1718   }
   1719 
   1720   // FIXME: Write diagnostic categories and link to diagnostic groups in each.
   1721 
   1722   // Write out the diagnostic groups.
   1723   for (const Record *G : DiagGroups) {
   1724     bool IsRemarkGroup = isRemarkGroup(G, DiagsInGroup);
   1725     auto &GroupInfo = DiagsInGroup[G->getValueAsString("GroupName")];
   1726     bool IsSynonym = GroupInfo.DiagsInGroup.empty() &&
   1727                      GroupInfo.SubGroups.size() == 1;
   1728 
   1729     writeHeader(((IsRemarkGroup ? "-R" : "-W") +
   1730                     G->getValueAsString("GroupName")).str(),
   1731                 OS);
   1732 
   1733     if (!IsSynonym) {
   1734       // FIXME: Ideally, all the diagnostics in a group should have the same
   1735       // default state, but that is not currently the case.
   1736       auto DefaultSeverities = getDefaultSeverities(G, DiagsInGroup);
   1737       if (!DefaultSeverities.empty() && !DefaultSeverities.count("Ignored")) {
   1738         bool AnyNonErrors = DefaultSeverities.count("Warning") ||
   1739                             DefaultSeverities.count("Remark");
   1740         if (!AnyNonErrors)
   1741           OS << "This diagnostic is an error by default, but the flag ``-Wno-"
   1742              << G->getValueAsString("GroupName") << "`` can be used to disable "
   1743              << "the error.\n\n";
   1744         else
   1745           OS << "This diagnostic is enabled by default.\n\n";
   1746       } else if (DefaultSeverities.size() > 1) {
   1747         OS << "Some of the diagnostics controlled by this flag are enabled "
   1748            << "by default.\n\n";
   1749       }
   1750     }
   1751 
   1752     if (!GroupInfo.SubGroups.empty()) {
   1753       if (IsSynonym)
   1754         OS << "Synonym for ";
   1755       else if (GroupInfo.DiagsInGroup.empty())
   1756         OS << "Controls ";
   1757       else
   1758         OS << "Also controls ";
   1759 
   1760       bool First = true;
   1761       llvm::sort(GroupInfo.SubGroups);
   1762       for (const auto &Name : GroupInfo.SubGroups) {
   1763         if (!First) OS << ", ";
   1764         OS << "`" << (IsRemarkGroup ? "-R" : "-W") << Name << "`_";
   1765         First = false;
   1766       }
   1767       OS << ".\n\n";
   1768     }
   1769 
   1770     if (!GroupInfo.DiagsInGroup.empty()) {
   1771       OS << "**Diagnostic text:**\n\n";
   1772       for (const Record *D : GroupInfo.DiagsInGroup) {
   1773         auto Severity = getDefaultSeverity(D);
   1774         Severity[0] = tolower(Severity[0]);
   1775         if (Severity == "ignored")
   1776           Severity = IsRemarkGroup ? "remark" : "warning";
   1777 
   1778         writeDiagnosticText(Builder, D, Severity, OS);
   1779       }
   1780     }
   1781 
   1782     auto Doc = G->getValueAsString("Documentation");
   1783     if (!Doc.empty())
   1784       OS << Doc;
   1785     else if (GroupInfo.SubGroups.empty() && GroupInfo.DiagsInGroup.empty())
   1786       OS << "This diagnostic flag exists for GCC compatibility, and has no "
   1787             "effect in Clang.\n";
   1788     OS << "\n";
   1789   }
   1790 }
   1791