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