xref: /llvm-project/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp (revision f4de28a63c81c909df28b6b065fad19e2189c54e)
1 //===-- ClangDiagnosticsEmitter.cpp - Generate Clang diagnostics tables ---===//
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/PointerUnion.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/ADT/StringSwitch.h"
21 #include "llvm/ADT/Twine.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/TableGen/Error.h"
24 #include "llvm/TableGen/Record.h"
25 #include "llvm/TableGen/StringToOffsetTable.h"
26 #include "llvm/TableGen/TableGenBackend.h"
27 #include <algorithm>
28 #include <cctype>
29 #include <functional>
30 #include <map>
31 #include <optional>
32 #include <set>
33 using namespace llvm;
34 
35 //===----------------------------------------------------------------------===//
36 // Diagnostic category computation code.
37 //===----------------------------------------------------------------------===//
38 
39 namespace {
40 class DiagGroupParentMap {
41   const RecordKeeper &Records;
42   std::map<const Record *, std::vector<const Record *>> Mapping;
43 
44 public:
45   DiagGroupParentMap(const RecordKeeper &records) : Records(records) {
46     for (const Record *Group : Records.getAllDerivedDefinitions("DiagGroup"))
47       for (const Record *SubGroup : Group->getValueAsListOfDefs("SubGroups"))
48         Mapping[SubGroup].push_back(Group);
49   }
50 
51   ArrayRef<const Record *> getParents(const Record *Group) {
52     return Mapping[Group];
53   }
54 };
55 } // end anonymous namespace.
56 
57 static StringRef
58 getCategoryFromDiagGroup(const Record *Group,
59                          DiagGroupParentMap &DiagGroupParents) {
60   // If the DiagGroup has a category, return it.
61   StringRef CatName = Group->getValueAsString("CategoryName");
62   if (!CatName.empty()) return CatName;
63 
64   // The diag group may the subgroup of one or more other diagnostic groups,
65   // check these for a category as well.
66   for (const Record *Parent : DiagGroupParents.getParents(Group)) {
67     CatName = getCategoryFromDiagGroup(Parent, DiagGroupParents);
68     if (!CatName.empty()) return CatName;
69   }
70   return "";
71 }
72 
73 /// getDiagnosticCategory - Return the category that the specified diagnostic
74 /// lives in.
75 static StringRef getDiagnosticCategory(const Record *R,
76                                        DiagGroupParentMap &DiagGroupParents) {
77   // If the diagnostic is in a group, and that group has a category, use it.
78   if (const auto *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
79     // Check the diagnostic's diag group for a category.
80     StringRef CatName =
81         getCategoryFromDiagGroup(Group->getDef(), DiagGroupParents);
82     if (!CatName.empty()) return CatName;
83   }
84 
85   // If the diagnostic itself has a category, get it.
86   return R->getValueAsString("CategoryName");
87 }
88 
89 namespace {
90   class DiagCategoryIDMap {
91     const RecordKeeper &Records;
92     StringMap<unsigned> CategoryIDs;
93     std::vector<StringRef> CategoryStrings;
94 
95   public:
96     DiagCategoryIDMap(const RecordKeeper &records) : Records(records) {
97       DiagGroupParentMap ParentInfo(Records);
98 
99       // The zero'th category is "".
100       CategoryStrings.push_back("");
101       CategoryIDs[""] = 0;
102 
103       for (const Record *Diag :
104            Records.getAllDerivedDefinitions("Diagnostic")) {
105         StringRef Category = getDiagnosticCategory(Diag, ParentInfo);
106         if (Category.empty()) continue;  // Skip diags with no category.
107 
108         unsigned &ID = CategoryIDs[Category];
109         if (ID != 0) continue;  // Already seen.
110 
111         ID = CategoryStrings.size();
112         CategoryStrings.push_back(Category);
113       }
114     }
115 
116     unsigned getID(StringRef CategoryString) {
117       return CategoryIDs[CategoryString];
118     }
119 
120     typedef std::vector<StringRef>::const_iterator const_iterator;
121     const_iterator begin() const { return CategoryStrings.begin(); }
122     const_iterator end() const { return CategoryStrings.end(); }
123   };
124 
125   struct GroupInfo {
126     StringRef GroupName;
127     std::vector<const Record*> DiagsInGroup;
128     std::vector<StringRef> SubGroups;
129     unsigned IDNo = 0;
130 
131     SmallVector<const Record *, 1> Defs;
132 
133     GroupInfo() = default;
134   };
135 } // end anonymous namespace.
136 
137 static bool beforeThanCompare(const Record *LHS, const Record *RHS) {
138   assert(!LHS->getLoc().empty() && !RHS->getLoc().empty());
139   return
140     LHS->getLoc().front().getPointer() < RHS->getLoc().front().getPointer();
141 }
142 
143 static bool diagGroupBeforeByName(const Record *LHS, const Record *RHS) {
144   return LHS->getValueAsString("GroupName") <
145          RHS->getValueAsString("GroupName");
146 }
147 
148 using DiagsInGroupTy = std::map<StringRef, GroupInfo>;
149 
150 /// Invert the 1-[0/1] mapping of diags to group into a one to many
151 /// mapping of groups to diags in the group.
152 static void groupDiagnostics(ArrayRef<const Record *> Diags,
153                              ArrayRef<const Record *> DiagGroups,
154                              DiagsInGroupTy &DiagsInGroup) {
155   for (const Record *R : Diags) {
156     const auto *DI = dyn_cast<DefInit>(R->getValueInit("Group"));
157     if (!DI)
158       continue;
159     assert(R->getValueAsDef("Class")->getName() != "CLASS_NOTE" &&
160            "Note can't be in a DiagGroup");
161     StringRef GroupName = DI->getDef()->getValueAsString("GroupName");
162     DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
163   }
164 
165   // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
166   // groups (these are warnings that GCC supports that clang never produces).
167   for (const Record *Group : DiagGroups) {
168     GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
169     GI.GroupName = Group->getName();
170     GI.Defs.push_back(Group);
171 
172     for (const Record *SubGroup : Group->getValueAsListOfDefs("SubGroups"))
173       GI.SubGroups.push_back(SubGroup->getValueAsString("GroupName"));
174   }
175 
176   // Assign unique ID numbers to the groups.
177   for (auto [IdNo, Iter] : enumerate(DiagsInGroup))
178     Iter.second.IDNo = IdNo;
179 
180   // Warn if the same group is defined more than once (including implicitly).
181   for (auto &Group : DiagsInGroup) {
182     if (Group.second.Defs.size() == 1 &&
183         (!Group.second.Defs.front()->isAnonymous() ||
184          Group.second.DiagsInGroup.size() <= 1))
185       continue;
186 
187     bool First = true;
188     for (const Record *Def : Group.second.Defs) {
189       // Skip implicit definitions from diagnostics; we'll report those
190       // separately below.
191       bool IsImplicit = false;
192       for (const Record *Diag : Group.second.DiagsInGroup) {
193         if (cast<DefInit>(Diag->getValueInit("Group"))->getDef() == Def) {
194           IsImplicit = true;
195           break;
196         }
197       }
198       if (IsImplicit)
199         continue;
200 
201       SMLoc Loc = Def->getLoc().front();
202       if (First) {
203         SrcMgr.PrintMessage(Loc, SourceMgr::DK_Error,
204                             Twine("group '") + Group.first +
205                                 "' is defined more than once");
206         First = false;
207       } else {
208         SrcMgr.PrintMessage(Loc, SourceMgr::DK_Note, "also defined here");
209       }
210     }
211 
212     for (const Record *Diag : Group.second.DiagsInGroup) {
213       if (!cast<DefInit>(Diag->getValueInit("Group"))->getDef()->isAnonymous())
214         continue;
215 
216       SMLoc Loc = Diag->getLoc().front();
217       if (First) {
218         SrcMgr.PrintMessage(Loc, SourceMgr::DK_Error,
219                             Twine("group '") + Group.first +
220                                 "' is implicitly defined more than once");
221         First = false;
222       } else {
223         SrcMgr.PrintMessage(Loc, SourceMgr::DK_Note,
224                             "also implicitly defined here");
225       }
226     }
227   }
228 }
229 
230 //===----------------------------------------------------------------------===//
231 // Infer members of -Wpedantic.
232 //===----------------------------------------------------------------------===//
233 
234 typedef std::vector<const Record *> RecordVec;
235 typedef DenseSet<const Record *> RecordSet;
236 typedef PointerUnion<RecordVec *, RecordSet *> VecOrSet;
237 
238 namespace {
239 class InferPedantic {
240   typedef DenseMap<const Record *, std::pair<unsigned, std::optional<unsigned>>>
241       GMap;
242 
243   DiagGroupParentMap &DiagGroupParents;
244   ArrayRef<const Record *> Diags;
245   const std::vector<const Record *> DiagGroups;
246   DiagsInGroupTy &DiagsInGroup;
247   DenseSet<const Record *> DiagsSet;
248   GMap GroupCount;
249 public:
250   InferPedantic(DiagGroupParentMap &DiagGroupParents,
251                 ArrayRef<const Record *> Diags,
252                 ArrayRef<const Record *> DiagGroups,
253                 DiagsInGroupTy &DiagsInGroup)
254       : DiagGroupParents(DiagGroupParents), Diags(Diags),
255         DiagGroups(DiagGroups), DiagsInGroup(DiagsInGroup) {}
256 
257   /// Compute the set of diagnostics and groups that are immediately
258   /// in -Wpedantic.
259   void compute(VecOrSet DiagsInPedantic,
260                VecOrSet GroupsInPedantic);
261 
262 private:
263   /// Determine whether a group is a subgroup of another group.
264   bool isSubGroupOfGroup(const Record *Group, StringRef RootGroupName);
265 
266   /// Determine if the diagnostic is an extension.
267   bool isExtension(const Record *Diag);
268 
269   /// Determine if the diagnostic is off by default.
270   bool isOffByDefault(const Record *Diag);
271 
272   /// Increment the count for a group, and transitively marked
273   /// parent groups when appropriate.
274   void markGroup(const Record *Group);
275 
276   /// Return true if the diagnostic is in a pedantic group.
277   bool groupInPedantic(const Record *Group, bool increment = false);
278 };
279 } // end anonymous namespace
280 
281 bool InferPedantic::isSubGroupOfGroup(const Record *Group, StringRef GName) {
282   StringRef GroupName = Group->getValueAsString("GroupName");
283   if (GName == GroupName)
284     return true;
285 
286   for (const Record *Parent : DiagGroupParents.getParents(Group))
287     if (isSubGroupOfGroup(Parent, GName))
288       return true;
289 
290   return false;
291 }
292 
293 /// Determine if the diagnostic is an extension.
294 bool InferPedantic::isExtension(const Record *Diag) {
295   return Diag->getValueAsDef("Class")->getName() == "CLASS_EXTENSION";
296 }
297 
298 bool InferPedantic::isOffByDefault(const Record *Diag) {
299   return Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name") ==
300          "Ignored";
301 }
302 
303 bool InferPedantic::groupInPedantic(const Record *Group, bool increment) {
304   GMap::mapped_type &V = GroupCount[Group];
305   // Lazily compute the threshold value for the group count.
306   if (!V.second) {
307     const GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
308     V.second = GI.SubGroups.size() + GI.DiagsInGroup.size();
309   }
310 
311   if (increment)
312     ++V.first;
313 
314   // Consider a group in -Wpendatic IFF if has at least one diagnostic
315   // or subgroup AND all of those diagnostics and subgroups are covered
316   // by -Wpedantic via our computation.
317   return V.first != 0 && V.first == *V.second;
318 }
319 
320 void InferPedantic::markGroup(const Record *Group) {
321   // If all the diagnostics and subgroups have been marked as being
322   // covered by -Wpedantic, increment the count of parent groups.  Once the
323   // group's count is equal to the number of subgroups and diagnostics in
324   // that group, we can safely add this group to -Wpedantic.
325   if (groupInPedantic(Group, /* increment */ true))
326     for (const Record *Parent : DiagGroupParents.getParents(Group))
327       markGroup(Parent);
328 }
329 
330 void InferPedantic::compute(VecOrSet DiagsInPedantic,
331                             VecOrSet GroupsInPedantic) {
332   // All extensions that are not on by default are implicitly in the
333   // "pedantic" group.  For those that aren't explicitly included in -Wpedantic,
334   // mark them for consideration to be included in -Wpedantic directly.
335   for (const Record *R : Diags) {
336     if (!isExtension(R) || !isOffByDefault(R))
337       continue;
338     DiagsSet.insert(R);
339     if (const auto *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
340       const Record *GroupRec = Group->getDef();
341       if (!isSubGroupOfGroup(GroupRec, "pedantic")) {
342         markGroup(GroupRec);
343       }
344     }
345   }
346 
347   // Compute the set of diagnostics that are directly in -Wpedantic.  We
348   // march through Diags a second time to ensure the results are emitted
349   // in deterministic order.
350   for (const Record *R : Diags) {
351     if (!DiagsSet.count(R))
352       continue;
353     // Check if the group is implicitly in -Wpedantic.  If so,
354     // the diagnostic should not be directly included in the -Wpedantic
355     // diagnostic group.
356     if (const auto *Group = dyn_cast<DefInit>(R->getValueInit("Group")))
357       if (groupInPedantic(Group->getDef()))
358         continue;
359 
360     // The diagnostic is not included in a group that is (transitively) in
361     // -Wpedantic.  Include it in -Wpedantic directly.
362     if (auto *V = DiagsInPedantic.dyn_cast<RecordVec *>())
363       V->push_back(R);
364     else
365       cast<RecordSet *>(DiagsInPedantic)->insert(R);
366   }
367 
368   if (!GroupsInPedantic)
369     return;
370 
371   // Compute the set of groups that are directly in -Wpedantic.  We
372   // march through the groups to ensure the results are emitted
373   /// in a deterministc order.
374   for (const Record *Group : DiagGroups) {
375     if (!groupInPedantic(Group))
376       continue;
377 
378     const std::vector<const Record *> &Parents =
379         DiagGroupParents.getParents(Group);
380     bool AllParentsInPedantic =
381         all_of(Parents, [&](const Record *R) { return groupInPedantic(R); });
382     // If all the parents are in -Wpedantic, this means that this diagnostic
383     // group will be indirectly included by -Wpedantic already.  In that
384     // case, do not add it directly to -Wpedantic.  If the group has no
385     // parents, obviously it should go into -Wpedantic.
386     if (Parents.size() > 0 && AllParentsInPedantic)
387       continue;
388 
389     if (auto *V = GroupsInPedantic.dyn_cast<RecordVec *>())
390       V->push_back(Group);
391     else
392       cast<RecordSet *>(GroupsInPedantic)->insert(Group);
393   }
394 }
395 
396 namespace {
397 enum PieceKind {
398   MultiPieceClass,
399   TextPieceClass,
400   PlaceholderPieceClass,
401   SelectPieceClass,
402   EnumSelectPieceClass,
403   PluralPieceClass,
404   DiffPieceClass,
405   SubstitutionPieceClass,
406 };
407 
408 enum ModifierType {
409   MT_Unknown,
410   MT_Placeholder,
411   MT_Select,
412   MT_EnumSelect,
413   MT_Sub,
414   MT_Plural,
415   MT_Diff,
416   MT_Ordinal,
417   MT_Human,
418   MT_S,
419   MT_Q,
420   MT_ObjCClass,
421   MT_ObjCInstance,
422 };
423 
424 static StringRef getModifierName(ModifierType MT) {
425   switch (MT) {
426   case MT_EnumSelect:
427   case MT_Select:
428     return "select";
429   case MT_Sub:
430     return "sub";
431   case MT_Diff:
432     return "diff";
433   case MT_Plural:
434     return "plural";
435   case MT_Ordinal:
436     return "ordinal";
437   case MT_Human:
438     return "human";
439   case MT_S:
440     return "s";
441   case MT_Q:
442     return "q";
443   case MT_Placeholder:
444     return "";
445   case MT_ObjCClass:
446     return "objcclass";
447   case MT_ObjCInstance:
448     return "objcinstance";
449   case MT_Unknown:
450     llvm_unreachable("invalid modifier type");
451   }
452   // Unhandled case
453   llvm_unreachable("invalid modifier type");
454 }
455 
456 struct Piece {
457   // This type and its derived classes are move-only.
458   Piece(PieceKind Kind) : ClassKind(Kind) {}
459   Piece(Piece const &O) = delete;
460   Piece &operator=(Piece const &) = delete;
461   virtual ~Piece() {}
462 
463   PieceKind getPieceClass() const { return ClassKind; }
464   static bool classof(const Piece *) { return true; }
465 
466 private:
467   PieceKind ClassKind;
468 };
469 
470 struct MultiPiece : Piece {
471   MultiPiece() : Piece(MultiPieceClass) {}
472   MultiPiece(std::vector<Piece *> Pieces)
473       : Piece(MultiPieceClass), Pieces(std::move(Pieces)) {}
474 
475   std::vector<Piece *> Pieces;
476 
477   static bool classof(const Piece *P) {
478     return P->getPieceClass() == MultiPieceClass;
479   }
480 };
481 
482 struct TextPiece : Piece {
483   StringRef Role;
484   std::string Text;
485   TextPiece(StringRef Text, StringRef Role = "")
486       : Piece(TextPieceClass), Role(Role), Text(Text.str()) {}
487 
488   static bool classof(const Piece *P) {
489     return P->getPieceClass() == TextPieceClass;
490   }
491 };
492 
493 struct PlaceholderPiece : Piece {
494   ModifierType Kind;
495   int Index;
496   PlaceholderPiece(ModifierType Kind, int Index)
497       : Piece(PlaceholderPieceClass), Kind(Kind), Index(Index) {}
498 
499   static bool classof(const Piece *P) {
500     return P->getPieceClass() == PlaceholderPieceClass;
501   }
502 };
503 
504 struct SelectPiece : Piece {
505 protected:
506   SelectPiece(PieceKind Kind, ModifierType ModKind)
507       : Piece(Kind), ModKind(ModKind) {}
508 
509 public:
510   SelectPiece(ModifierType ModKind) : SelectPiece(SelectPieceClass, ModKind) {}
511 
512   ModifierType ModKind;
513   std::vector<Piece *> Options;
514   int Index = 0;
515 
516   static bool classof(const Piece *P) {
517     return P->getPieceClass() == SelectPieceClass ||
518            P->getPieceClass() == EnumSelectPieceClass ||
519            P->getPieceClass() == PluralPieceClass;
520   }
521 };
522 
523 struct EnumSelectPiece : SelectPiece {
524   EnumSelectPiece() : SelectPiece(EnumSelectPieceClass, MT_EnumSelect) {}
525 
526   StringRef EnumName;
527   std::vector<StringRef> OptionEnumNames;
528 
529   static bool classof(const Piece *P) {
530     return P->getPieceClass() == EnumSelectPieceClass;
531   }
532 };
533 
534 struct EnumValuePiece : Piece {
535   ModifierType Kind;
536 };
537 
538 struct PluralPiece : SelectPiece {
539   PluralPiece() : SelectPiece(PluralPieceClass, MT_Plural) {}
540 
541   std::vector<Piece *> OptionPrefixes;
542   int Index = 0;
543 
544   static bool classof(const Piece *P) {
545     return P->getPieceClass() == PluralPieceClass;
546   }
547 };
548 
549 struct DiffPiece : Piece {
550   DiffPiece() : Piece(DiffPieceClass) {}
551 
552   Piece *Parts[4] = {};
553   int Indexes[2] = {};
554 
555   static bool classof(const Piece *P) {
556     return P->getPieceClass() == DiffPieceClass;
557   }
558 };
559 
560 struct SubstitutionPiece : Piece {
561   SubstitutionPiece() : Piece(SubstitutionPieceClass) {}
562 
563   std::string Name;
564   std::vector<int> Modifiers;
565 
566   static bool classof(const Piece *P) {
567     return P->getPieceClass() == SubstitutionPieceClass;
568   }
569 };
570 
571 /// Diagnostic text, parsed into pieces.
572 
573 
574 struct DiagnosticTextBuilder {
575   DiagnosticTextBuilder(DiagnosticTextBuilder const &) = delete;
576   DiagnosticTextBuilder &operator=(DiagnosticTextBuilder const &) = delete;
577 
578   DiagnosticTextBuilder(const RecordKeeper &Records) {
579     // Build up the list of substitution records.
580     for (auto *S : Records.getAllDerivedDefinitions("TextSubstitution")) {
581       EvaluatingRecordGuard Guard(&EvaluatingRecord, S);
582       Substitutions.try_emplace(
583           S->getName(), DiagText(*this, S->getValueAsString("Substitution")));
584     }
585 
586     // Check that no diagnostic definitions have the same name as a
587     // substitution.
588     for (const Record *Diag : Records.getAllDerivedDefinitions("Diagnostic")) {
589       StringRef Name = Diag->getName();
590       if (Substitutions.count(Name))
591         llvm::PrintFatalError(
592             Diag->getLoc(),
593             "Diagnostic '" + Name +
594                 "' has same name as TextSubstitution definition");
595     }
596   }
597 
598   std::vector<std::string> buildForDocumentation(StringRef Role,
599                                                  const Record *R);
600   std::string buildForDefinition(const Record *R);
601   llvm::SmallVector<std::pair<
602       std::string, llvm::SmallVector<std::pair<unsigned, std::string>>>>
603   buildForEnum(const Record *R);
604 
605   Piece *getSubstitution(SubstitutionPiece *S) const {
606     auto It = Substitutions.find(S->Name);
607     if (It == Substitutions.end())
608       llvm::PrintFatalError("Failed to find substitution with name: " +
609                             S->Name);
610     return It->second.Root;
611   }
612 
613   [[noreturn]] void PrintFatalError(Twine const &Msg) const {
614     assert(EvaluatingRecord && "not evaluating a record?");
615     llvm::PrintFatalError(EvaluatingRecord->getLoc(), Msg);
616   }
617 
618 private:
619   struct DiagText {
620     DiagnosticTextBuilder &Builder;
621     std::vector<Piece *> AllocatedPieces;
622     Piece *Root = nullptr;
623 
624     template <class T, class... Args> T *New(Args &&... args) {
625       static_assert(std::is_base_of<Piece, T>::value, "must be piece");
626       T *Mem = new T(std::forward<Args>(args)...);
627       AllocatedPieces.push_back(Mem);
628       return Mem;
629     }
630 
631     DiagText(DiagnosticTextBuilder &Builder, StringRef Text)
632         : Builder(Builder), Root(parseDiagText(Text, StopAt::End)) {}
633 
634     enum class StopAt {
635       // Parse until the end of the string.
636       End,
637       // Additionally stop if we hit a non-nested '|' or '}'.
638       PipeOrCloseBrace,
639       // Additionally stop if we hit a non-nested '$'.
640       Dollar,
641     };
642 
643     Piece *parseDiagText(StringRef &Text, StopAt Stop);
644     int parseModifier(StringRef &) const;
645 
646   public:
647     DiagText(DiagText &&O) noexcept
648         : Builder(O.Builder), AllocatedPieces(std::move(O.AllocatedPieces)),
649           Root(O.Root) {
650       O.Root = nullptr;
651     }
652     // The move assignment operator is defined as deleted pending further
653     // motivation.
654     DiagText &operator=(DiagText &&) = delete;
655 
656     // The copy constrcutor and copy assignment operator is defined as deleted
657     // pending further motivation.
658     DiagText(const DiagText &) = delete;
659     DiagText &operator=(const DiagText &) = delete;
660 
661     ~DiagText() {
662       for (Piece *P : AllocatedPieces)
663         delete P;
664     }
665   };
666 
667 private:
668   const Record *EvaluatingRecord = nullptr;
669   struct EvaluatingRecordGuard {
670     EvaluatingRecordGuard(const Record **Dest, const Record *New)
671         : Dest(Dest), Old(*Dest) {
672       *Dest = New;
673     }
674     ~EvaluatingRecordGuard() { *Dest = Old; }
675     const Record **Dest;
676     const Record *Old;
677   };
678 
679   StringMap<DiagText> Substitutions;
680 };
681 
682 template <class Derived> struct DiagTextVisitor {
683   using ModifierMappingsType = std::optional<std::vector<int>>;
684 
685 private:
686   Derived &getDerived() { return static_cast<Derived &>(*this); }
687 
688 public:
689   std::vector<int>
690   getSubstitutionMappings(SubstitutionPiece *P,
691                           const ModifierMappingsType &Mappings) const {
692     std::vector<int> NewMappings;
693     for (int Idx : P->Modifiers)
694       NewMappings.push_back(mapIndex(Idx, Mappings));
695     return NewMappings;
696   }
697 
698   struct SubstitutionContext {
699     SubstitutionContext(DiagTextVisitor &Visitor, SubstitutionPiece *P)
700         : Visitor(Visitor) {
701       Substitution = Visitor.Builder.getSubstitution(P);
702       OldMappings = std::move(Visitor.ModifierMappings);
703       std::vector<int> NewMappings =
704           Visitor.getSubstitutionMappings(P, OldMappings);
705       Visitor.ModifierMappings = std::move(NewMappings);
706     }
707 
708     ~SubstitutionContext() {
709       Visitor.ModifierMappings = std::move(OldMappings);
710     }
711 
712   private:
713     DiagTextVisitor &Visitor;
714     std::optional<std::vector<int>> OldMappings;
715 
716   public:
717     Piece *Substitution;
718   };
719 
720 public:
721   DiagTextVisitor(DiagnosticTextBuilder &Builder) : Builder(Builder) {}
722 
723   void Visit(Piece *P) {
724     switch (P->getPieceClass()) {
725 #define CASE(T)                                                                \
726   case T##PieceClass:                                                          \
727     return getDerived().Visit##T(static_cast<T##Piece *>(P))
728       CASE(Multi);
729       CASE(Text);
730       CASE(Placeholder);
731       CASE(Select);
732       CASE(EnumSelect);
733       CASE(Plural);
734       CASE(Diff);
735       CASE(Substitution);
736 #undef CASE
737     }
738   }
739 
740   void VisitSubstitution(SubstitutionPiece *P) {
741     SubstitutionContext Guard(*this, P);
742     Visit(Guard.Substitution);
743   }
744 
745   int mapIndex(int Idx,
746                     ModifierMappingsType const &ModifierMappings) const {
747     if (!ModifierMappings)
748       return Idx;
749     if (ModifierMappings->size() <= static_cast<unsigned>(Idx))
750       Builder.PrintFatalError("Modifier value '" + std::to_string(Idx) +
751                               "' is not valid for this mapping (has " +
752                               std::to_string(ModifierMappings->size()) +
753                               " mappings)");
754     return (*ModifierMappings)[Idx];
755   }
756 
757   int mapIndex(int Idx) const {
758     return mapIndex(Idx, ModifierMappings);
759   }
760 
761 protected:
762   DiagnosticTextBuilder &Builder;
763   ModifierMappingsType ModifierMappings;
764 };
765 
766 void escapeRST(StringRef Str, std::string &Out) {
767   for (auto K : Str) {
768     if (StringRef("`*|_[]\\").count(K))
769       Out.push_back('\\');
770     Out.push_back(K);
771   }
772 }
773 
774 template <typename It> void padToSameLength(It Begin, It End) {
775   size_t Width = 0;
776   for (It I = Begin; I != End; ++I)
777     Width = std::max(Width, I->size());
778   for (It I = Begin; I != End; ++I)
779     (*I) += std::string(Width - I->size(), ' ');
780 }
781 
782 template <typename It> void makeTableRows(It Begin, It End) {
783   if (Begin == End)
784     return;
785   padToSameLength(Begin, End);
786   for (It I = Begin; I != End; ++I)
787     *I = "|" + *I + "|";
788 }
789 
790 void makeRowSeparator(std::string &Str) {
791   for (char &K : Str)
792     K = (K == '|' ? '+' : '-');
793 }
794 
795 struct DiagTextDocPrinter : DiagTextVisitor<DiagTextDocPrinter> {
796   using BaseTy = DiagTextVisitor<DiagTextDocPrinter>;
797   DiagTextDocPrinter(DiagnosticTextBuilder &Builder,
798                      std::vector<std::string> &RST)
799       : BaseTy(Builder), RST(RST) {}
800 
801   void gatherNodes(
802       Piece *OrigP, const ModifierMappingsType &CurrentMappings,
803       std::vector<std::pair<Piece *, ModifierMappingsType>> &Pieces) const {
804     if (auto *Sub = dyn_cast<SubstitutionPiece>(OrigP)) {
805       ModifierMappingsType NewMappings =
806           getSubstitutionMappings(Sub, CurrentMappings);
807       return gatherNodes(Builder.getSubstitution(Sub), NewMappings, Pieces);
808     }
809     if (auto *MD = dyn_cast<MultiPiece>(OrigP)) {
810       for (Piece *Node : MD->Pieces)
811         gatherNodes(Node, CurrentMappings, Pieces);
812       return;
813     }
814     Pieces.push_back(std::make_pair(OrigP, CurrentMappings));
815   }
816 
817   void VisitMulti(MultiPiece *P) {
818     if (P->Pieces.empty()) {
819       RST.push_back("");
820       return;
821     }
822 
823     if (P->Pieces.size() == 1)
824       return Visit(P->Pieces[0]);
825 
826     // Flatten the list of nodes, replacing any substitution pieces with the
827     // recursively flattened substituted node.
828     std::vector<std::pair<Piece *, ModifierMappingsType>> Pieces;
829     gatherNodes(P, ModifierMappings, Pieces);
830 
831     std::string EmptyLinePrefix;
832     size_t Start = RST.size();
833     bool HasMultipleLines = true;
834     for (const std::pair<Piece *, ModifierMappingsType> &NodePair : Pieces) {
835       std::vector<std::string> Lines;
836       DiagTextDocPrinter Visitor{Builder, Lines};
837       Visitor.ModifierMappings = NodePair.second;
838       Visitor.Visit(NodePair.first);
839 
840       if (Lines.empty())
841         continue;
842 
843       // We need a vertical separator if either this or the previous piece is a
844       // multi-line piece, or this is the last piece.
845       const char *Separator = (Lines.size() > 1 || HasMultipleLines) ? "|" : "";
846       HasMultipleLines = Lines.size() > 1;
847 
848       if (Start + Lines.size() > RST.size())
849         RST.resize(Start + Lines.size(), EmptyLinePrefix);
850 
851       padToSameLength(Lines.begin(), Lines.end());
852       for (size_t I = 0; I != Lines.size(); ++I)
853         RST[Start + I] += Separator + Lines[I];
854       std::string Empty(Lines[0].size(), ' ');
855       for (size_t I = Start + Lines.size(); I != RST.size(); ++I)
856         RST[I] += Separator + Empty;
857       EmptyLinePrefix += Separator + Empty;
858     }
859     for (size_t I = Start; I != RST.size(); ++I)
860       RST[I] += "|";
861     EmptyLinePrefix += "|";
862 
863     makeRowSeparator(EmptyLinePrefix);
864     RST.insert(RST.begin() + Start, EmptyLinePrefix);
865     RST.insert(RST.end(), EmptyLinePrefix);
866   }
867 
868   void VisitText(TextPiece *P) {
869     RST.push_back("");
870     auto &S = RST.back();
871 
872     StringRef T = P->Text;
873     while (T.consume_front(" "))
874       RST.back() += " |nbsp| ";
875 
876     std::string Suffix;
877     while (T.consume_back(" "))
878       Suffix += " |nbsp| ";
879 
880     if (!T.empty()) {
881       S += ':';
882       S += P->Role;
883       S += ":`";
884       escapeRST(T, S);
885       S += '`';
886     }
887 
888     S += Suffix;
889   }
890 
891   void VisitPlaceholder(PlaceholderPiece *P) {
892     RST.push_back(std::string(":placeholder:`") +
893                   char('A' + mapIndex(P->Index)) + "`");
894   }
895 
896   void VisitSelect(SelectPiece *P) {
897     std::vector<size_t> SeparatorIndexes;
898     SeparatorIndexes.push_back(RST.size());
899     RST.emplace_back();
900     for (auto *O : P->Options) {
901       Visit(O);
902       SeparatorIndexes.push_back(RST.size());
903       RST.emplace_back();
904     }
905 
906     makeTableRows(RST.begin() + SeparatorIndexes.front(),
907                   RST.begin() + SeparatorIndexes.back() + 1);
908     for (size_t I : SeparatorIndexes)
909       makeRowSeparator(RST[I]);
910   }
911 
912   void VisitEnumSelect(EnumSelectPiece *P) {
913     // Document this as if it were a 'select', which properly prints all of the
914     // options correctly in a readable/reasonable manner. There isn't really
915     // anything valuable we could add to readers here.
916     VisitSelect(P);
917   }
918 
919   void VisitPlural(PluralPiece *P) { VisitSelect(P); }
920 
921   void VisitDiff(DiffPiece *P) {
922     // Render %diff{a $ b $ c|d}e,f as %select{a %e b %f c|d}.
923     PlaceholderPiece E(MT_Placeholder, P->Indexes[0]);
924     PlaceholderPiece F(MT_Placeholder, P->Indexes[1]);
925 
926     MultiPiece FirstOption;
927     FirstOption.Pieces.push_back(P->Parts[0]);
928     FirstOption.Pieces.push_back(&E);
929     FirstOption.Pieces.push_back(P->Parts[1]);
930     FirstOption.Pieces.push_back(&F);
931     FirstOption.Pieces.push_back(P->Parts[2]);
932 
933     SelectPiece Select(MT_Diff);
934     Select.Options.push_back(&FirstOption);
935     Select.Options.push_back(P->Parts[3]);
936 
937     VisitSelect(&Select);
938   }
939 
940   std::vector<std::string> &RST;
941 };
942 
943 struct DiagEnumPrinter : DiagTextVisitor<DiagEnumPrinter> {
944 public:
945   using BaseTy = DiagTextVisitor<DiagEnumPrinter>;
946   using EnumeratorItem = std::pair<unsigned, std::string>;
947   using EnumeratorList = llvm::SmallVector<EnumeratorItem>;
948   using ResultTy = llvm::SmallVector<std::pair<std::string, EnumeratorList>>;
949 
950   DiagEnumPrinter(DiagnosticTextBuilder &Builder, ResultTy &Result)
951       : BaseTy(Builder), Result(Result) {}
952 
953   ResultTy &Result;
954 
955   void VisitMulti(MultiPiece *P) {
956     for (auto *Child : P->Pieces)
957       Visit(Child);
958   }
959   void VisitText(TextPiece *P) {}
960   void VisitPlaceholder(PlaceholderPiece *P) {}
961   void VisitDiff(DiffPiece *P) {}
962   void VisitSelect(SelectPiece *P) {
963     for (auto *D : P->Options)
964       Visit(D);
965   }
966   void VisitPlural(PluralPiece *P) { VisitSelect(P); }
967   void VisitEnumSelect(EnumSelectPiece *P) {
968     assert(P->Options.size() == P->OptionEnumNames.size());
969 
970     if (!P->EnumName.empty()) {
971       EnumeratorList List;
972 
973       for (const auto &Tup : llvm::enumerate(P->OptionEnumNames))
974         if (!Tup.value().empty())
975           List.emplace_back(Tup.index(), Tup.value());
976 
977       Result.emplace_back(P->EnumName, List);
978     }
979 
980     VisitSelect(P);
981   }
982 };
983 
984 struct DiagTextPrinter : DiagTextVisitor<DiagTextPrinter> {
985 public:
986   using BaseTy = DiagTextVisitor<DiagTextPrinter>;
987   DiagTextPrinter(DiagnosticTextBuilder &Builder, std::string &Result)
988       : BaseTy(Builder), Result(Result) {}
989 
990   void VisitMulti(MultiPiece *P) {
991     for (auto *Child : P->Pieces)
992       Visit(Child);
993   }
994   void VisitText(TextPiece *P) { Result += P->Text; }
995   void VisitPlaceholder(PlaceholderPiece *P) {
996     Result += "%";
997     Result += getModifierName(P->Kind);
998     addInt(mapIndex(P->Index));
999   }
1000   void VisitSelect(SelectPiece *P) {
1001     Result += "%";
1002     Result += getModifierName(P->ModKind);
1003     if (P->ModKind == MT_Select || P->ModKind == MT_EnumSelect) {
1004       Result += "{";
1005       for (auto *D : P->Options) {
1006         Visit(D);
1007         Result += '|';
1008       }
1009       if (!P->Options.empty())
1010         Result.erase(--Result.end());
1011       Result += '}';
1012     }
1013     addInt(mapIndex(P->Index));
1014   }
1015 
1016   void VisitPlural(PluralPiece *P) {
1017     Result += "%plural{";
1018     assert(P->Options.size() == P->OptionPrefixes.size());
1019     for (const auto [Prefix, Option] :
1020          zip_equal(P->OptionPrefixes, P->Options)) {
1021       if (Prefix)
1022         Visit(Prefix);
1023       Visit(Option);
1024       Result += "|";
1025     }
1026     if (!P->Options.empty())
1027       Result.erase(--Result.end());
1028     Result += '}';
1029     addInt(mapIndex(P->Index));
1030   }
1031 
1032   void VisitEnumSelect(EnumSelectPiece *P) {
1033     // Print as if we are a 'select', which will result in the compiler just
1034     // treating this like a normal select.  This way we don't have to do any
1035     // special work for the compiler to consume these.
1036     VisitSelect(P);
1037   }
1038 
1039   void VisitDiff(DiffPiece *P) {
1040     Result += "%diff{";
1041     Visit(P->Parts[0]);
1042     Result += "$";
1043     Visit(P->Parts[1]);
1044     Result += "$";
1045     Visit(P->Parts[2]);
1046     Result += "|";
1047     Visit(P->Parts[3]);
1048     Result += "}";
1049     addInt(mapIndex(P->Indexes[0]));
1050     Result += ",";
1051     addInt(mapIndex(P->Indexes[1]));
1052   }
1053 
1054   void addInt(int Val) { Result += std::to_string(Val); }
1055 
1056   std::string &Result;
1057 };
1058 
1059 int DiagnosticTextBuilder::DiagText::parseModifier(StringRef &Text) const {
1060   if (Text.empty() || !isdigit(Text[0]))
1061     Builder.PrintFatalError("expected modifier in diagnostic");
1062   int Val = 0;
1063   do {
1064     Val *= 10;
1065     Val += Text[0] - '0';
1066     Text = Text.drop_front();
1067   } while (!Text.empty() && isdigit(Text[0]));
1068   return Val;
1069 }
1070 
1071 Piece *DiagnosticTextBuilder::DiagText::parseDiagText(StringRef &Text,
1072                                                       StopAt Stop) {
1073   std::vector<Piece *> Parsed;
1074 
1075   constexpr StringLiteral StopSets[] = {"%", "%|}", "%|}$"};
1076   StringRef StopSet = StopSets[static_cast<int>(Stop)];
1077 
1078   while (!Text.empty()) {
1079     size_t End = (size_t)-2;
1080     do
1081       End = Text.find_first_of(StopSet, End + 2);
1082     while (
1083         End < Text.size() - 1 && Text[End] == '%' &&
1084         (Text[End + 1] == '%' || Text[End + 1] == '|' || Text[End + 1] == '$'));
1085 
1086     if (End) {
1087       Parsed.push_back(New<TextPiece>(Text.slice(0, End), "diagtext"));
1088       Text = Text.slice(End, StringRef::npos);
1089       if (Text.empty())
1090         break;
1091     }
1092 
1093     if (Text[0] == '|' || Text[0] == '}' || Text[0] == '$')
1094       break;
1095 
1096     // Drop the '%'.
1097     Text = Text.drop_front();
1098 
1099     // Extract the (optional) modifier.
1100     size_t ModLength = Text.find_first_of("0123456789<{");
1101     StringRef Modifier = Text.slice(0, ModLength);
1102     Text = Text.slice(ModLength, StringRef::npos);
1103     ModifierType ModType = StringSwitch<ModifierType>{Modifier}
1104                                .Case("select", MT_Select)
1105                                .Case("enum_select", MT_EnumSelect)
1106                                .Case("sub", MT_Sub)
1107                                .Case("diff", MT_Diff)
1108                                .Case("plural", MT_Plural)
1109                                .Case("s", MT_S)
1110                                .Case("ordinal", MT_Ordinal)
1111                                .Case("human", MT_Human)
1112                                .Case("q", MT_Q)
1113                                .Case("objcclass", MT_ObjCClass)
1114                                .Case("objcinstance", MT_ObjCInstance)
1115                                .Case("", MT_Placeholder)
1116                                .Default(MT_Unknown);
1117 
1118     auto ExpectAndConsume = [&](StringRef Prefix) {
1119       if (!Text.consume_front(Prefix))
1120         Builder.PrintFatalError("expected '" + Prefix + "' while parsing %" +
1121                                 Modifier);
1122     };
1123 
1124     if (ModType != MT_EnumSelect && Text[0] == '<')
1125       Builder.PrintFatalError("modifier '<' syntax not valid with %" +
1126                               Modifier);
1127 
1128     switch (ModType) {
1129     case MT_Unknown:
1130       Builder.PrintFatalError("Unknown modifier type: " + Modifier);
1131     case MT_Select: {
1132       SelectPiece *Select = New<SelectPiece>(MT_Select);
1133       do {
1134         Text = Text.drop_front(); // '{' or '|'
1135         Select->Options.push_back(
1136             parseDiagText(Text, StopAt::PipeOrCloseBrace));
1137         assert(!Text.empty() && "malformed %select");
1138       } while (Text.front() == '|');
1139       ExpectAndConsume("}");
1140       Select->Index = parseModifier(Text);
1141       Parsed.push_back(Select);
1142       continue;
1143     }
1144     case MT_EnumSelect: {
1145       EnumSelectPiece *EnumSelect = New<EnumSelectPiece>();
1146       if (Text[0] != '<')
1147         Builder.PrintFatalError("expected '<' after " + Modifier);
1148 
1149       Text = Text.drop_front(); // Drop '<'
1150       size_t EnumNameLen = Text.find_first_of('>');
1151       EnumSelect->EnumName = Text.slice(0, EnumNameLen);
1152       Text = Text.slice(EnumNameLen, StringRef::npos);
1153       ExpectAndConsume(">");
1154 
1155       if (Text[0] != '{')
1156         Builder.PrintFatalError("expected '{' after " + Modifier);
1157 
1158       do {
1159         Text = Text.drop_front(); // '{' or '|'
1160 
1161         bool BracketsRequired = false;
1162         if (Text[0] == '%') {
1163           BracketsRequired = true;
1164           Text = Text.drop_front(); // '%'
1165           size_t OptionNameLen = Text.find_first_of("{");
1166           EnumSelect->OptionEnumNames.push_back(Text.slice(0, OptionNameLen));
1167           Text = Text.slice(OptionNameLen, StringRef::npos);
1168         } else {
1169           EnumSelect->OptionEnumNames.push_back({});
1170         }
1171 
1172         if (BracketsRequired)
1173           ExpectAndConsume("{");
1174         else if (Text.front() == '{') {
1175           Text = Text.drop_front();
1176           BracketsRequired = true;
1177         }
1178 
1179         EnumSelect->Options.push_back(
1180             parseDiagText(Text, StopAt::PipeOrCloseBrace));
1181 
1182         if (BracketsRequired)
1183           ExpectAndConsume("}");
1184 
1185         assert(!Text.empty() && "malformed %select");
1186       } while (Text.front() == '|');
1187 
1188       ExpectAndConsume("}");
1189       EnumSelect->Index = parseModifier(Text);
1190       Parsed.push_back(EnumSelect);
1191       continue;
1192     }
1193     case MT_Plural: {
1194       PluralPiece *Plural = New<PluralPiece>();
1195       do {
1196         Text = Text.drop_front(); // '{' or '|'
1197         size_t End = Text.find_first_of(':');
1198         if (End == StringRef::npos)
1199           Builder.PrintFatalError("expected ':' while parsing %plural");
1200         ++End;
1201         assert(!Text.empty());
1202         Plural->OptionPrefixes.push_back(
1203             New<TextPiece>(Text.slice(0, End), "diagtext"));
1204         Text = Text.slice(End, StringRef::npos);
1205         Plural->Options.push_back(
1206             parseDiagText(Text, StopAt::PipeOrCloseBrace));
1207         assert(!Text.empty() && "malformed %plural");
1208       } while (Text.front() == '|');
1209       ExpectAndConsume("}");
1210       Plural->Index = parseModifier(Text);
1211       Parsed.push_back(Plural);
1212       continue;
1213     }
1214     case MT_Sub: {
1215       SubstitutionPiece *Sub = New<SubstitutionPiece>();
1216       ExpectAndConsume("{");
1217       size_t NameSize = Text.find_first_of('}');
1218       assert(NameSize != size_t(-1) && "failed to find the end of the name");
1219       assert(NameSize != 0 && "empty name?");
1220       Sub->Name = Text.substr(0, NameSize).str();
1221       Text = Text.drop_front(NameSize);
1222       ExpectAndConsume("}");
1223       if (!Text.empty()) {
1224         while (true) {
1225           if (!isdigit(Text[0]))
1226             break;
1227           Sub->Modifiers.push_back(parseModifier(Text));
1228           if (!Text.consume_front(","))
1229             break;
1230           assert(!Text.empty() && isdigit(Text[0]) &&
1231                  "expected another modifier");
1232         }
1233       }
1234       Parsed.push_back(Sub);
1235       continue;
1236     }
1237     case MT_Diff: {
1238       DiffPiece *Diff = New<DiffPiece>();
1239       ExpectAndConsume("{");
1240       Diff->Parts[0] = parseDiagText(Text, StopAt::Dollar);
1241       ExpectAndConsume("$");
1242       Diff->Parts[1] = parseDiagText(Text, StopAt::Dollar);
1243       ExpectAndConsume("$");
1244       Diff->Parts[2] = parseDiagText(Text, StopAt::PipeOrCloseBrace);
1245       ExpectAndConsume("|");
1246       Diff->Parts[3] = parseDiagText(Text, StopAt::PipeOrCloseBrace);
1247       ExpectAndConsume("}");
1248       Diff->Indexes[0] = parseModifier(Text);
1249       ExpectAndConsume(",");
1250       Diff->Indexes[1] = parseModifier(Text);
1251       Parsed.push_back(Diff);
1252       continue;
1253     }
1254     case MT_S: {
1255       SelectPiece *Select = New<SelectPiece>(ModType);
1256       Select->Options.push_back(New<TextPiece>(""));
1257       Select->Options.push_back(New<TextPiece>("s", "diagtext"));
1258       Select->Index = parseModifier(Text);
1259       Parsed.push_back(Select);
1260       continue;
1261     }
1262     case MT_Q:
1263     case MT_Placeholder:
1264     case MT_ObjCClass:
1265     case MT_ObjCInstance:
1266     case MT_Ordinal:
1267     case MT_Human: {
1268       Parsed.push_back(New<PlaceholderPiece>(ModType, parseModifier(Text)));
1269       continue;
1270     }
1271     }
1272   }
1273 
1274   return New<MultiPiece>(Parsed);
1275 }
1276 
1277 std::vector<std::string>
1278 DiagnosticTextBuilder::buildForDocumentation(StringRef Severity,
1279                                              const Record *R) {
1280   EvaluatingRecordGuard Guard(&EvaluatingRecord, R);
1281   StringRef Text = R->getValueAsString("Summary");
1282 
1283   DiagText D(*this, Text);
1284   TextPiece *Prefix = D.New<TextPiece>(Severity, Severity);
1285   Prefix->Text += ": ";
1286   auto *MP = dyn_cast<MultiPiece>(D.Root);
1287   if (!MP) {
1288     MP = D.New<MultiPiece>();
1289     MP->Pieces.push_back(D.Root);
1290     D.Root = MP;
1291   }
1292   MP->Pieces.insert(MP->Pieces.begin(), Prefix);
1293   std::vector<std::string> Result;
1294   DiagTextDocPrinter{*this, Result}.Visit(D.Root);
1295   return Result;
1296 }
1297 
1298 DiagEnumPrinter::ResultTy DiagnosticTextBuilder::buildForEnum(const Record *R) {
1299   EvaluatingRecordGuard Guard(&EvaluatingRecord, R);
1300   StringRef Text = R->getValueAsString("Summary");
1301   DiagText D(*this, Text);
1302   DiagEnumPrinter::ResultTy Result;
1303   DiagEnumPrinter{*this, Result}.Visit(D.Root);
1304   return Result;
1305 }
1306 
1307 std::string DiagnosticTextBuilder::buildForDefinition(const Record *R) {
1308   EvaluatingRecordGuard Guard(&EvaluatingRecord, R);
1309   StringRef Text = R->getValueAsString("Summary");
1310   DiagText D(*this, Text);
1311   std::string Result;
1312   DiagTextPrinter{*this, Result}.Visit(D.Root);
1313   return Result;
1314 }
1315 
1316 } // namespace
1317 
1318 //===----------------------------------------------------------------------===//
1319 // Warning Tables (.inc file) generation.
1320 //===----------------------------------------------------------------------===//
1321 
1322 static bool isError(const Record &Diag) {
1323   return Diag.getValueAsDef("Class")->getName() == "CLASS_ERROR";
1324 }
1325 
1326 static bool isRemark(const Record &Diag) {
1327   return Diag.getValueAsDef("Class")->getName() == "CLASS_REMARK";
1328 }
1329 
1330 // Presumes the text has been split at the first whitespace or hyphen.
1331 static bool isExemptAtStart(StringRef Text) {
1332   // Fast path, the first character is lowercase or not alphanumeric.
1333   if (Text.empty() || isLower(Text[0]) || !isAlnum(Text[0]))
1334     return true;
1335 
1336   // If the text is all uppercase (or numbers, +, or _), then we assume it's an
1337   // acronym and that's allowed. This covers cases like ISO, C23, C++14, and
1338   // OBJECT_MODE. However, if there's only a single letter other than "C", we
1339   // do not exempt it so that we catch a case like "A really bad idea" while
1340   // still allowing a case like "C does not allow...".
1341   if (all_of(Text, [](char C) {
1342         return isUpper(C) || isDigit(C) || C == '+' || C == '_';
1343       }))
1344     return Text.size() > 1 || Text[0] == 'C';
1345 
1346   // Otherwise, there are a few other exemptions.
1347   return StringSwitch<bool>(Text)
1348       .Case("AddressSanitizer", true)
1349       .Case("CFString", true)
1350       .Case("Clang", true)
1351       .Case("Fuchsia", true)
1352       .Case("GNUstep", true)
1353       .Case("IBOutletCollection", true)
1354       .Case("Microsoft", true)
1355       .Case("Neon", true)
1356       .StartsWith("NSInvocation", true) // NSInvocation, NSInvocation's
1357       .Case("Objective", true) // Objective-C (hyphen is a word boundary)
1358       .Case("OpenACC", true)
1359       .Case("OpenCL", true)
1360       .Case("OpenMP", true)
1361       .Case("Pascal", true)
1362       .Case("Swift", true)
1363       .Case("Unicode", true)
1364       .Case("Vulkan", true)
1365       .Case("WebAssembly", true)
1366       .Default(false);
1367 }
1368 
1369 // Does not presume the text has been split at all.
1370 static bool isExemptAtEnd(StringRef Text) {
1371   // Rather than come up with a list of characters that are allowed, we go the
1372   // other way and look only for characters that are not allowed.
1373   switch (Text.back()) {
1374   default:
1375     return true;
1376   case '?':
1377     // Explicitly allowed to support "; did you mean?".
1378     return true;
1379   case '.':
1380   case '!':
1381     return false;
1382   }
1383 }
1384 
1385 static void verifyDiagnosticWording(const Record &Diag) {
1386   StringRef FullDiagText = Diag.getValueAsString("Summary");
1387 
1388   auto DiagnoseStart = [&](StringRef Text) {
1389     // Verify that the text does not start with a capital letter, except for
1390     // special cases that are exempt like ISO and C++. Find the first word
1391     // by looking for a word breaking character.
1392     char Separators[] = {' ', '-', ',', '}'};
1393     auto Iter = std::find_first_of(
1394         Text.begin(), Text.end(), std::begin(Separators), std::end(Separators));
1395 
1396     StringRef First = Text.substr(0, Iter - Text.begin());
1397     if (!isExemptAtStart(First)) {
1398       PrintError(&Diag,
1399                  "Diagnostics should not start with a capital letter; '" +
1400                      First + "' is invalid");
1401     }
1402   };
1403 
1404   auto DiagnoseEnd = [&](StringRef Text) {
1405     // Verify that the text does not end with punctuation like '.' or '!'.
1406     if (!isExemptAtEnd(Text)) {
1407       PrintError(&Diag, "Diagnostics should not end with punctuation; '" +
1408                             Text.substr(Text.size() - 1, 1) + "' is invalid");
1409     }
1410   };
1411 
1412   // If the diagnostic starts with %select, look through it to see whether any
1413   // of the options will cause a problem.
1414   if (FullDiagText.starts_with("%select{")) {
1415     // Do a balanced delimiter scan from the start of the text to find the
1416     // closing '}', skipping intermediary {} pairs.
1417 
1418     size_t BraceCount = 1;
1419     constexpr size_t PercentSelectBraceLen = sizeof("%select{") - 1;
1420     auto Iter = FullDiagText.begin() + PercentSelectBraceLen;
1421     for (auto End = FullDiagText.end(); Iter != End; ++Iter) {
1422       char Ch = *Iter;
1423       if (Ch == '{')
1424         ++BraceCount;
1425       else if (Ch == '}')
1426         --BraceCount;
1427       if (!BraceCount)
1428         break;
1429     }
1430     // Defending against a malformed diagnostic string.
1431     if (BraceCount != 0)
1432       return;
1433 
1434     StringRef SelectText =
1435         FullDiagText.substr(PercentSelectBraceLen, Iter - FullDiagText.begin() -
1436                                                        PercentSelectBraceLen);
1437     SmallVector<StringRef, 4> SelectPieces;
1438     SelectText.split(SelectPieces, '|');
1439 
1440     // Walk over all of the individual pieces of select text to see if any of
1441     // them start with an invalid character. If any of the select pieces is
1442     // empty, we need to look at the first word after the %select to see
1443     // whether that is invalid or not. If all of the pieces are fine, then we
1444     // don't need to check anything else about the start of the diagnostic.
1445     bool CheckSecondWord = false;
1446     for (StringRef Piece : SelectPieces) {
1447       if (Piece.empty())
1448         CheckSecondWord = true;
1449       else
1450         DiagnoseStart(Piece);
1451     }
1452 
1453     if (CheckSecondWord) {
1454       // There was an empty select piece, so we need to check the second
1455       // word. This catches situations like '%select{|fine}0 Not okay'. Add
1456       // two to account for the closing curly brace and the number after it.
1457       StringRef AfterSelect =
1458           FullDiagText.substr(Iter - FullDiagText.begin() + 2).ltrim();
1459       DiagnoseStart(AfterSelect);
1460     }
1461   } else {
1462     // If the start of the diagnostic is not %select, we can check the first
1463     // word and be done with it.
1464     DiagnoseStart(FullDiagText);
1465   }
1466 
1467   // If the last character in the diagnostic is a number preceded by a }, scan
1468   // backwards to see if this is for a %select{...}0. If it is, we need to look
1469   // at each piece to see whether it ends in punctuation or not.
1470   bool StillNeedToDiagEnd = true;
1471   if (isDigit(FullDiagText.back()) && *(FullDiagText.end() - 2) == '}') {
1472     // Scan backwards to find the opening curly brace.
1473     size_t BraceCount = 1;
1474     auto Iter = FullDiagText.end() - sizeof("}0");
1475     for (auto End = FullDiagText.begin(); Iter != End; --Iter) {
1476       char Ch = *Iter;
1477       if (Ch == '}')
1478         ++BraceCount;
1479       else if (Ch == '{')
1480         --BraceCount;
1481       if (!BraceCount)
1482         break;
1483     }
1484     // Defending against a malformed diagnostic string.
1485     if (BraceCount != 0)
1486       return;
1487 
1488     // Continue the backwards scan to find the word before the '{' to see if it
1489     // is 'select'.
1490     constexpr size_t SelectLen = sizeof("select") - 1;
1491     bool IsSelect =
1492         (FullDiagText.substr(Iter - SelectLen - FullDiagText.begin(),
1493                              SelectLen) == "select");
1494     if (IsSelect) {
1495       // Gather the content between the {} for the select in question so we can
1496       // split it into pieces.
1497       StillNeedToDiagEnd = false; // No longer need to handle the end.
1498       StringRef SelectText =
1499           FullDiagText.substr(Iter - FullDiagText.begin() + /*{*/ 1,
1500                               FullDiagText.end() - Iter - /*pos before }0*/ 3);
1501       SmallVector<StringRef, 4> SelectPieces;
1502       SelectText.split(SelectPieces, '|');
1503       for (StringRef Piece : SelectPieces) {
1504         // Not worrying about a situation like: "this is bar. %select{foo|}0".
1505         if (!Piece.empty())
1506           DiagnoseEnd(Piece);
1507       }
1508     }
1509   }
1510 
1511   // If we didn't already cover the diagnostic because of a %select, handle it
1512   // now.
1513   if (StillNeedToDiagEnd)
1514     DiagnoseEnd(FullDiagText);
1515 
1516   // FIXME: This could also be improved by looking for instances of clang or
1517   // gcc in the diagnostic and recommend Clang or GCC instead. However, this
1518   // runs into odd situations like [[clang::warn_unused_result]],
1519   // #pragma clang, or --unwindlib=libgcc.
1520 }
1521 /// ClangDiagsEnumsEmitter - The top-level class emits .def files containing
1522 /// declarations of Clang diagnostic enums for selects.
1523 void clang::EmitClangDiagsEnums(const RecordKeeper &Records, raw_ostream &OS,
1524                                 const std::string &Component) {
1525   DiagnosticTextBuilder DiagTextBuilder(Records);
1526   ArrayRef<const Record *> Diags =
1527       Records.getAllDerivedDefinitions("Diagnostic");
1528 
1529   llvm::SmallVector<std::pair<const Record *, std::string>> EnumerationNames;
1530 
1531   for (const Record &R : make_pointee_range(Diags)) {
1532     DiagEnumPrinter::ResultTy Enums = DiagTextBuilder.buildForEnum(&R);
1533 
1534     for (auto &Enumeration : Enums) {
1535       bool ShouldPrint =
1536           Component.empty() || Component == R.getValueAsString("Component");
1537 
1538       auto PreviousByName = llvm::find_if(EnumerationNames, [&](auto &Prev) {
1539         return Prev.second == Enumeration.first;
1540       });
1541 
1542       if (PreviousByName != EnumerationNames.end()) {
1543         PrintError(&R,
1544                    "Duplicate enumeration name '" + Enumeration.first + "'");
1545         PrintNote(PreviousByName->first->getLoc(),
1546                   "Previous diagnostic is here");
1547       }
1548 
1549       EnumerationNames.emplace_back(&R, Enumeration.first);
1550 
1551       if (ShouldPrint)
1552         OS << "DIAG_ENUM(" << Enumeration.first << ")\n";
1553 
1554       llvm::SmallVector<std::string> EnumeratorNames;
1555       for (auto &Enumerator : Enumeration.second) {
1556         if (llvm::find(EnumeratorNames, Enumerator.second) !=
1557             EnumeratorNames.end())
1558           PrintError(&R,
1559                      "Duplicate enumerator name '" + Enumerator.second + "'");
1560         EnumeratorNames.push_back(Enumerator.second);
1561 
1562         if (ShouldPrint)
1563           OS << "DIAG_ENUM_ITEM(" << Enumerator.first << ", "
1564              << Enumerator.second << ")\n";
1565       }
1566       if (ShouldPrint)
1567         OS << "DIAG_ENUM_END()\n";
1568     }
1569   }
1570 }
1571 
1572 /// ClangDiagsDefsEmitter - The top-level class emits .def files containing
1573 /// declarations of Clang diagnostics.
1574 void clang::EmitClangDiagsDefs(const RecordKeeper &Records, raw_ostream &OS,
1575                                const std::string &Component) {
1576   // Write the #if guard
1577   if (!Component.empty()) {
1578     std::string ComponentName = StringRef(Component).upper();
1579     OS << "#ifdef " << ComponentName << "START\n";
1580     OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
1581        << ",\n";
1582     OS << "#undef " << ComponentName << "START\n";
1583     OS << "#endif\n\n";
1584   }
1585 
1586   DiagnosticTextBuilder DiagTextBuilder(Records);
1587 
1588   ArrayRef<const Record *> Diags =
1589       Records.getAllDerivedDefinitions("Diagnostic");
1590 
1591   ArrayRef<const Record *> DiagGroups =
1592       Records.getAllDerivedDefinitions("DiagGroup");
1593 
1594   DiagsInGroupTy DiagsInGroup;
1595   groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
1596 
1597   DiagCategoryIDMap CategoryIDs(Records);
1598   DiagGroupParentMap DGParentMap(Records);
1599 
1600   // Compute the set of diagnostics that are in -Wpedantic.
1601   RecordSet DiagsInPedantic;
1602   InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
1603   inferPedantic.compute(&DiagsInPedantic, (RecordVec*)nullptr);
1604 
1605   for (const Record &R : make_pointee_range(Diags)) {
1606     // Check if this is an error that is accidentally in a warning
1607     // group.
1608     if (isError(R)) {
1609       if (const auto *Group = dyn_cast<DefInit>(R.getValueInit("Group"))) {
1610         const Record *GroupRec = Group->getDef();
1611         StringRef GroupName = GroupRec->getValueAsString("GroupName");
1612         PrintFatalError(R.getLoc(), "Error " + R.getName() +
1613                       " cannot be in a warning group [" + GroupName + "]");
1614       }
1615     }
1616 
1617     // Check that all remarks have an associated diagnostic group.
1618     if (isRemark(R)) {
1619       if (!isa<DefInit>(R.getValueInit("Group"))) {
1620         PrintFatalError(R.getLoc(), "Error " + R.getName() +
1621                                         " not in any diagnostic group");
1622       }
1623     }
1624 
1625     // Filter by component.
1626     if (!Component.empty() && Component != R.getValueAsString("Component"))
1627       continue;
1628 
1629     // Validate diagnostic wording for common issues.
1630     verifyDiagnosticWording(R);
1631 
1632     OS << "DIAG(" << R.getName() << ", ";
1633     OS << R.getValueAsDef("Class")->getName();
1634     OS << ", (unsigned)diag::Severity::"
1635        << R.getValueAsDef("DefaultSeverity")->getValueAsString("Name");
1636 
1637     // Description string.
1638     OS << ", \"";
1639     OS.write_escaped(DiagTextBuilder.buildForDefinition(&R)) << '"';
1640 
1641     // Warning group associated with the diagnostic. This is stored as an index
1642     // into the alphabetically sorted warning group table.
1643     if (const auto *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
1644       auto I = DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName"));
1645       assert(I != DiagsInGroup.end());
1646       OS << ", " << I->second.IDNo;
1647     } else if (DiagsInPedantic.count(&R)) {
1648       auto I = DiagsInGroup.find("pedantic");
1649       assert(I != DiagsInGroup.end() && "pedantic group not defined");
1650       OS << ", " << I->second.IDNo;
1651     } else {
1652       OS << ", 0";
1653     }
1654 
1655     // SFINAE response.
1656     OS << ", " << R.getValueAsDef("SFINAE")->getName();
1657 
1658     // Default warning has no Werror bit.
1659     if (R.getValueAsBit("WarningNoWerror"))
1660       OS << ", true";
1661     else
1662       OS << ", false";
1663 
1664     if (R.getValueAsBit("ShowInSystemHeader"))
1665       OS << ", true";
1666     else
1667       OS << ", false";
1668 
1669     if (R.getValueAsBit("ShowInSystemMacro"))
1670       OS << ", true";
1671     else
1672       OS << ", false";
1673 
1674     if (R.getValueAsBit("Deferrable"))
1675       OS << ", true";
1676     else
1677       OS << ", false";
1678 
1679     // Category number.
1680     OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
1681     OS << ")\n";
1682   }
1683 }
1684 
1685 //===----------------------------------------------------------------------===//
1686 // Warning Group Tables generation
1687 //===----------------------------------------------------------------------===//
1688 
1689 static std::string getDiagCategoryEnum(StringRef name) {
1690   if (name.empty())
1691     return "DiagCat_None";
1692   SmallString<256> enumName = StringRef("DiagCat_");
1693   for (StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
1694     enumName += isalnum(*I) ? *I : '_';
1695   return std::string(enumName);
1696 }
1697 
1698 /// Emit the array of diagnostic subgroups.
1699 ///
1700 /// The array of diagnostic subgroups contains for each group a list of its
1701 /// subgroups. The individual lists are separated by '-1'. Groups with no
1702 /// subgroups are skipped.
1703 ///
1704 /// \code
1705 ///   static const int16_t DiagSubGroups[] = {
1706 ///     /* Empty */ -1,
1707 ///     /* DiagSubGroup0 */ 142, -1,
1708 ///     /* DiagSubGroup13 */ 265, 322, 399, -1
1709 ///   }
1710 /// \endcode
1711 ///
1712 static void emitDiagSubGroups(DiagsInGroupTy &DiagsInGroup,
1713                               RecordVec &GroupsInPedantic, raw_ostream &OS) {
1714   OS << "static const int16_t DiagSubGroups[] = {\n"
1715      << "  /* Empty */ -1,\n";
1716   for (auto const &[Name, Group] : DiagsInGroup) {
1717     const bool IsPedantic = Name == "pedantic";
1718     const std::vector<StringRef> &SubGroups = Group.SubGroups;
1719     if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty())) {
1720       OS << "  /* DiagSubGroup" << Group.IDNo << " */ ";
1721       for (StringRef SubGroup : SubGroups) {
1722         auto RI = DiagsInGroup.find(SubGroup);
1723         assert(RI != DiagsInGroup.end() && "Referenced without existing?");
1724         OS << RI->second.IDNo << ", ";
1725       }
1726       // Emit the groups implicitly in "pedantic".
1727       if (IsPedantic) {
1728         for (auto const &Group : GroupsInPedantic) {
1729           StringRef GroupName = Group->getValueAsString("GroupName");
1730           auto RI = DiagsInGroup.find(GroupName);
1731           assert(RI != DiagsInGroup.end() && "Referenced without existing?");
1732           OS << RI->second.IDNo << ", ";
1733         }
1734       }
1735 
1736       OS << "-1,\n";
1737     }
1738   }
1739   OS << "};\n\n";
1740 }
1741 
1742 /// Emit the list of diagnostic arrays.
1743 ///
1744 /// This data structure is a large array that contains itself arrays of varying
1745 /// size. Each array represents a list of diagnostics. The different arrays are
1746 /// separated by the value '-1'.
1747 ///
1748 /// \code
1749 ///   static const int16_t DiagArrays[] = {
1750 ///     /* Empty */ -1,
1751 ///     /* DiagArray1 */ diag::warn_pragma_message,
1752 ///                      -1,
1753 ///     /* DiagArray2 */ diag::warn_abs_too_small,
1754 ///                      diag::warn_unsigned_abs,
1755 ///                      diag::warn_wrong_absolute_value_type,
1756 ///                      -1
1757 ///   };
1758 /// \endcode
1759 ///
1760 static void emitDiagArrays(DiagsInGroupTy &DiagsInGroup,
1761                            RecordVec &DiagsInPedantic, raw_ostream &OS) {
1762   OS << "static const int16_t DiagArrays[] = {\n"
1763      << "  /* Empty */ -1,\n";
1764   for (const auto &[Name, Group] : DiagsInGroup) {
1765     const bool IsPedantic = Name == "pedantic";
1766 
1767     const std::vector<const Record *> &V = Group.DiagsInGroup;
1768     if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) {
1769       OS << "  /* DiagArray" << Group.IDNo << " */ ";
1770       for (auto *Record : V)
1771         OS << "diag::" << Record->getName() << ", ";
1772       // Emit the diagnostics implicitly in "pedantic".
1773       if (IsPedantic) {
1774         for (auto const &Diag : DiagsInPedantic)
1775           OS << "diag::" << Diag->getName() << ", ";
1776       }
1777       OS << "-1,\n";
1778     }
1779   }
1780   OS << "};\n\n";
1781 }
1782 
1783 /// Emit a list of group names.
1784 ///
1785 /// This creates an `llvm::StringTable` of all the diagnostic group names.
1786 static void emitDiagGroupNames(const StringToOffsetTable &GroupNames,
1787                                raw_ostream &OS) {
1788   GroupNames.EmitStringTableDef(OS, "DiagGroupNames");
1789   OS << "\n";
1790 }
1791 
1792 /// Emit diagnostic arrays and related data structures.
1793 ///
1794 /// This creates the actual diagnostic array, an array of diagnostic subgroups
1795 /// and an array of subgroup names.
1796 ///
1797 /// \code
1798 ///  #ifdef GET_DIAG_ARRAYS
1799 ///     static const int16_t DiagArrays[];
1800 ///     static const int16_t DiagSubGroups[];
1801 ///     static constexpr llvm::StringTable DiagGroupNames;
1802 ///  #endif
1803 ///  \endcode
1804 static void emitAllDiagArrays(DiagsInGroupTy &DiagsInGroup,
1805                               RecordVec &DiagsInPedantic,
1806                               RecordVec &GroupsInPedantic,
1807                               const StringToOffsetTable &GroupNames,
1808                               raw_ostream &OS) {
1809   OS << "\n#ifdef GET_DIAG_ARRAYS\n";
1810   emitDiagArrays(DiagsInGroup, DiagsInPedantic, OS);
1811   emitDiagSubGroups(DiagsInGroup, GroupsInPedantic, OS);
1812   emitDiagGroupNames(GroupNames, OS);
1813   OS << "#endif // GET_DIAG_ARRAYS\n\n";
1814 }
1815 
1816 /// Emit diagnostic table.
1817 ///
1818 /// The table is sorted by the name of the diagnostic group. Each element
1819 /// consists of the name of the diagnostic group (given as offset in the
1820 /// group name table), a reference to a list of diagnostics (optional) and a
1821 /// reference to a set of subgroups (optional).
1822 ///
1823 /// \code
1824 /// #ifdef GET_DIAG_TABLE
1825 ///  {/* abi */              159, /* DiagArray11 */ 19, /* Empty */          0},
1826 ///  {/* aggregate-return */ 180, /* Empty */        0, /* Empty */          0},
1827 ///  {/* all */              197, /* Empty */        0, /* DiagSubGroup13 */ 3},
1828 ///  {/* deprecated */       1981,/* DiagArray1 */ 348, /* DiagSubGroup3 */  9},
1829 /// #endif
1830 /// \endcode
1831 static void emitDiagTable(DiagsInGroupTy &DiagsInGroup,
1832                           RecordVec &DiagsInPedantic,
1833                           RecordVec &GroupsInPedantic,
1834                           const StringToOffsetTable &GroupNames,
1835                           raw_ostream &OS) {
1836   unsigned MaxLen = 0;
1837 
1838   for (auto const &I: DiagsInGroup)
1839     MaxLen = std::max(MaxLen, (unsigned)I.first.size());
1840 
1841   OS << "\n#ifdef DIAG_ENTRY\n";
1842   unsigned SubGroupIndex = 1, DiagArrayIndex = 1;
1843   for (auto const &[Name, GroupInfo] : DiagsInGroup) {
1844     // Group option string.
1845     OS << "DIAG_ENTRY(";
1846     OS << GroupInfo.GroupName << " /* ";
1847 
1848     if (Name.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
1849                                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1850                                "0123456789!@#$%^*-+=:?") != std::string::npos)
1851       PrintFatalError("Invalid character in diagnostic group '" + Name + "'");
1852     OS << Name << " */, ";
1853     OS << *GroupNames.GetStringOffset(Name) << ", ";
1854 
1855     // Special handling for 'pedantic'.
1856     const bool IsPedantic = Name == "pedantic";
1857 
1858     // Diagnostics in the group.
1859     const std::vector<const Record *> &V = GroupInfo.DiagsInGroup;
1860     const bool hasDiags =
1861         !V.empty() || (IsPedantic && !DiagsInPedantic.empty());
1862     if (hasDiags) {
1863       OS << "/* DiagArray" << GroupInfo.IDNo << " */ " << DiagArrayIndex
1864          << ", ";
1865       if (IsPedantic)
1866         DiagArrayIndex += DiagsInPedantic.size();
1867       DiagArrayIndex += V.size() + 1;
1868     } else {
1869       OS << "0, ";
1870     }
1871 
1872     // Subgroups.
1873     const std::vector<StringRef> &SubGroups = GroupInfo.SubGroups;
1874     const bool hasSubGroups =
1875         !SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty());
1876     if (hasSubGroups) {
1877       OS << "/* DiagSubGroup" << GroupInfo.IDNo << " */ " << SubGroupIndex
1878          << ", ";
1879       if (IsPedantic)
1880         SubGroupIndex += GroupsInPedantic.size();
1881       SubGroupIndex += SubGroups.size() + 1;
1882     } else {
1883       OS << "0, ";
1884     }
1885 
1886     std::string Documentation = GroupInfo.Defs.back()
1887                                     ->getValue("Documentation")
1888                                     ->getValue()
1889                                     ->getAsUnquotedString();
1890 
1891     OS << "R\"(" << StringRef(Documentation).trim() << ")\"";
1892 
1893     OS << ")\n";
1894   }
1895   OS << "#endif // DIAG_ENTRY\n\n";
1896 }
1897 
1898 /// Emit the table of diagnostic categories.
1899 ///
1900 /// The table has the form of macro calls that have two parameters. The
1901 /// category's name as well as an enum that represents the category. The
1902 /// table can be used by defining the macro 'CATEGORY' and including this
1903 /// table right after.
1904 ///
1905 /// \code
1906 /// #ifdef GET_CATEGORY_TABLE
1907 ///   CATEGORY("Semantic Issue", DiagCat_Semantic_Issue)
1908 ///   CATEGORY("Lambda Issue", DiagCat_Lambda_Issue)
1909 /// #endif
1910 /// \endcode
1911 static void emitCategoryTable(const RecordKeeper &Records, raw_ostream &OS) {
1912   DiagCategoryIDMap CategoriesByID(Records);
1913   OS << "\n#ifdef GET_CATEGORY_TABLE\n";
1914   for (auto const &C : CategoriesByID)
1915     OS << "CATEGORY(\"" << C << "\", " << getDiagCategoryEnum(C) << ")\n";
1916   OS << "#endif // GET_CATEGORY_TABLE\n\n";
1917 }
1918 
1919 void clang::EmitClangDiagGroups(const RecordKeeper &Records, raw_ostream &OS) {
1920   // Compute a mapping from a DiagGroup to all of its parents.
1921   DiagGroupParentMap DGParentMap(Records);
1922 
1923   ArrayRef<const Record *> Diags =
1924       Records.getAllDerivedDefinitions("Diagnostic");
1925 
1926   ArrayRef<const Record *> DiagGroups =
1927       Records.getAllDerivedDefinitions("DiagGroup");
1928 
1929   DiagsInGroupTy DiagsInGroup;
1930   groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
1931 
1932   // All extensions are implicitly in the "pedantic" group.  Record the
1933   // implicit set of groups in the "pedantic" group, and use this information
1934   // later when emitting the group information for Pedantic.
1935   RecordVec DiagsInPedantic;
1936   RecordVec GroupsInPedantic;
1937   InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
1938   inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic);
1939 
1940   StringToOffsetTable GroupNames;
1941   for (const auto &[Name, Group] : DiagsInGroup) {
1942     GroupNames.GetOrAddStringOffset(Name);
1943   }
1944 
1945   emitAllDiagArrays(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
1946                     OS);
1947   emitDiagTable(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
1948                 OS);
1949   emitCategoryTable(Records, OS);
1950 }
1951 
1952 //===----------------------------------------------------------------------===//
1953 // Diagnostic name index generation
1954 //===----------------------------------------------------------------------===//
1955 
1956 void clang::EmitClangDiagsIndexName(const RecordKeeper &Records,
1957                                     raw_ostream &OS) {
1958   std::vector<const Record *> Diags =
1959       Records.getAllDerivedDefinitions("Diagnostic");
1960 
1961   sort(Diags, [](const Record *LHS, const Record *RHS) {
1962     return LHS->getName() < RHS->getName();
1963   });
1964 
1965   for (const Record *Elem : Diags)
1966     OS << "DIAG_NAME_INDEX(" << Elem->getName() << ")\n";
1967 }
1968 
1969 //===----------------------------------------------------------------------===//
1970 // Diagnostic documentation generation
1971 //===----------------------------------------------------------------------===//
1972 
1973 namespace docs {
1974 namespace {
1975 
1976 bool isRemarkGroup(const Record *DiagGroup,
1977                    const DiagsInGroupTy &DiagsInGroup) {
1978   bool AnyRemarks = false, AnyNonRemarks = false;
1979 
1980   std::function<void(StringRef)> Visit = [&](StringRef GroupName) {
1981     auto &GroupInfo = DiagsInGroup.find(GroupName)->second;
1982     for (const Record *Diag : GroupInfo.DiagsInGroup)
1983       (isRemark(*Diag) ? AnyRemarks : AnyNonRemarks) = true;
1984     for (StringRef Name : GroupInfo.SubGroups)
1985       Visit(Name);
1986   };
1987   Visit(DiagGroup->getValueAsString("GroupName"));
1988 
1989   if (AnyRemarks && AnyNonRemarks)
1990     PrintFatalError(
1991         DiagGroup->getLoc(),
1992         "Diagnostic group contains both remark and non-remark diagnostics");
1993   return AnyRemarks;
1994 }
1995 
1996 std::string getDefaultSeverity(const Record *Diag) {
1997   return std::string(
1998       Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name"));
1999 }
2000 
2001 std::set<std::string> getDefaultSeverities(const Record *DiagGroup,
2002                                            const DiagsInGroupTy &DiagsInGroup) {
2003   std::set<std::string> States;
2004 
2005   std::function<void(StringRef)> Visit = [&](StringRef GroupName) {
2006     auto &GroupInfo = DiagsInGroup.find(GroupName)->second;
2007     for (const Record *Diag : GroupInfo.DiagsInGroup)
2008       States.insert(getDefaultSeverity(Diag));
2009     for (const auto &Name : GroupInfo.SubGroups)
2010       Visit(Name);
2011   };
2012   Visit(DiagGroup->getValueAsString("GroupName"));
2013   return States;
2014 }
2015 
2016 void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') {
2017   OS << Str << "\n" << std::string(Str.size(), Kind) << "\n";
2018 }
2019 
2020 void writeDiagnosticText(DiagnosticTextBuilder &Builder, const Record *R,
2021                          StringRef Role, raw_ostream &OS) {
2022   StringRef Text = R->getValueAsString("Summary");
2023   if (Text == "%0")
2024     OS << "The text of this diagnostic is not controlled by Clang.\n\n";
2025   else {
2026     std::vector<std::string> Out = Builder.buildForDocumentation(Role, R);
2027     for (auto &Line : Out)
2028       OS << Line << "\n";
2029     OS << "\n";
2030   }
2031 }
2032 
2033 }  // namespace
2034 }  // namespace docs
2035 
2036 void clang::EmitClangDiagDocs(const RecordKeeper &Records, raw_ostream &OS) {
2037   using namespace docs;
2038 
2039   // Get the documentation introduction paragraph.
2040   const Record *Documentation = Records.getDef("GlobalDocumentation");
2041   if (!Documentation) {
2042     PrintFatalError("The Documentation top-level definition is missing, "
2043                     "no documentation will be generated.");
2044     return;
2045   }
2046 
2047   OS << Documentation->getValueAsString("Intro") << "\n";
2048 
2049   DiagnosticTextBuilder Builder(Records);
2050 
2051   ArrayRef<const Record *> Diags =
2052       Records.getAllDerivedDefinitions("Diagnostic");
2053 
2054   std::vector<const Record *> DiagGroups =
2055       Records.getAllDerivedDefinitions("DiagGroup");
2056   sort(DiagGroups, diagGroupBeforeByName);
2057 
2058   DiagGroupParentMap DGParentMap(Records);
2059 
2060   DiagsInGroupTy DiagsInGroup;
2061   groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
2062 
2063   // Compute the set of diagnostics that are in -Wpedantic.
2064   {
2065     RecordSet DiagsInPedanticSet;
2066     RecordSet GroupsInPedanticSet;
2067     InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
2068     inferPedantic.compute(&DiagsInPedanticSet, &GroupsInPedanticSet);
2069     auto &PedDiags = DiagsInGroup["pedantic"];
2070     // Put the diagnostics into a deterministic order.
2071     RecordVec DiagsInPedantic(DiagsInPedanticSet.begin(),
2072                               DiagsInPedanticSet.end());
2073     RecordVec GroupsInPedantic(GroupsInPedanticSet.begin(),
2074                                GroupsInPedanticSet.end());
2075     sort(DiagsInPedantic, beforeThanCompare);
2076     sort(GroupsInPedantic, beforeThanCompare);
2077     PedDiags.DiagsInGroup.insert(PedDiags.DiagsInGroup.end(),
2078                                  DiagsInPedantic.begin(),
2079                                  DiagsInPedantic.end());
2080     for (auto *Group : GroupsInPedantic)
2081       PedDiags.SubGroups.push_back(Group->getValueAsString("GroupName"));
2082   }
2083 
2084   // FIXME: Write diagnostic categories and link to diagnostic groups in each.
2085 
2086   // Write out the diagnostic groups.
2087   for (const Record *G : DiagGroups) {
2088     bool IsRemarkGroup = isRemarkGroup(G, DiagsInGroup);
2089     auto &GroupInfo = DiagsInGroup[G->getValueAsString("GroupName")];
2090     bool IsSynonym = GroupInfo.DiagsInGroup.empty() &&
2091                      GroupInfo.SubGroups.size() == 1;
2092 
2093     writeHeader(((IsRemarkGroup ? "-R" : "-W") +
2094                     G->getValueAsString("GroupName")).str(),
2095                 OS);
2096 
2097     if (!IsSynonym) {
2098       // FIXME: Ideally, all the diagnostics in a group should have the same
2099       // default state, but that is not currently the case.
2100       auto DefaultSeverities = getDefaultSeverities(G, DiagsInGroup);
2101       if (!DefaultSeverities.empty() && !DefaultSeverities.count("Ignored")) {
2102         bool AnyNonErrors = DefaultSeverities.count("Warning") ||
2103                             DefaultSeverities.count("Remark");
2104         if (!AnyNonErrors)
2105           OS << "This diagnostic is an error by default, but the flag ``-Wno-"
2106              << G->getValueAsString("GroupName") << "`` can be used to disable "
2107              << "the error.\n\n";
2108         else
2109           OS << "This diagnostic is enabled by default.\n\n";
2110       } else if (DefaultSeverities.size() > 1) {
2111         OS << "Some of the diagnostics controlled by this flag are enabled "
2112            << "by default.\n\n";
2113       }
2114     }
2115 
2116     if (!GroupInfo.SubGroups.empty()) {
2117       if (IsSynonym)
2118         OS << "Synonym for ";
2119       else if (GroupInfo.DiagsInGroup.empty())
2120         OS << "Controls ";
2121       else
2122         OS << "Also controls ";
2123 
2124       bool First = true;
2125       sort(GroupInfo.SubGroups);
2126       for (StringRef Name : GroupInfo.SubGroups) {
2127         if (!First) OS << ", ";
2128         OS << "`" << (IsRemarkGroup ? "-R" : "-W") << Name << "`_";
2129         First = false;
2130       }
2131       OS << ".\n\n";
2132     }
2133 
2134     if (!GroupInfo.DiagsInGroup.empty()) {
2135       OS << "**Diagnostic text:**\n\n";
2136       for (const Record *D : GroupInfo.DiagsInGroup) {
2137         auto Severity = getDefaultSeverity(D);
2138         Severity[0] = tolower(Severity[0]);
2139         if (Severity == "ignored")
2140           Severity = IsRemarkGroup ? "remark" : "warning";
2141 
2142         writeDiagnosticText(Builder, D, Severity, OS);
2143       }
2144     }
2145 
2146     auto Doc = G->getValueAsString("Documentation");
2147     if (!Doc.empty())
2148       OS << Doc;
2149     else if (GroupInfo.SubGroups.empty() && GroupInfo.DiagsInGroup.empty())
2150       OS << "This diagnostic flag exists for GCC compatibility, and has no "
2151             "effect in Clang.\n";
2152     OS << "\n";
2153   }
2154 }
2155