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