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