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