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