ClangDiagnosticsEmitter.cpp revision 1.1.1.3
1//=- ClangDiagnosticsEmitter.cpp - Generate Clang diagnostics tables -*- C++ -*-
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// These tablegen backends emit Clang diagnostics tables.
10//
11//===----------------------------------------------------------------------===//
12
13#include "TableGenBackends.h"
14#include "llvm/ADT/DenseSet.h"
15#include "llvm/ADT/Optional.h"
16#include "llvm/ADT/PointerUnion.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/SmallPtrSet.h"
19#include "llvm/ADT/SmallString.h"
20#include "llvm/ADT/SmallVector.h"
21#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringSwitch.h"
23#include "llvm/ADT/Twine.h"
24#include "llvm/Support/Casting.h"
25#include "llvm/TableGen/Error.h"
26#include "llvm/TableGen/Record.h"
27#include "llvm/TableGen/StringToOffsetTable.h"
28#include "llvm/TableGen/TableGenBackend.h"
29#include <algorithm>
30#include <cctype>
31#include <functional>
32#include <map>
33#include <set>
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    std::vector<const Record*> DiagsInGroup;
133    std::vector<std::string> SubGroups;
134    unsigned IDNo;
135
136    llvm::SmallVector<const Record *, 1> Defs;
137
138    GroupInfo() : IDNo(0) {}
139  };
140} // end anonymous namespace.
141
142static bool beforeThanCompare(const Record *LHS, const Record *RHS) {
143  assert(!LHS->getLoc().empty() && !RHS->getLoc().empty());
144  return
145    LHS->getLoc().front().getPointer() < RHS->getLoc().front().getPointer();
146}
147
148static bool diagGroupBeforeByName(const Record *LHS, const Record *RHS) {
149  return LHS->getValueAsString("GroupName") <
150         RHS->getValueAsString("GroupName");
151}
152
153/// Invert the 1-[0/1] mapping of diags to group into a one to many
154/// mapping of groups to diags in the group.
155static void groupDiagnostics(const std::vector<Record*> &Diags,
156                             const std::vector<Record*> &DiagGroups,
157                             std::map<std::string, GroupInfo> &DiagsInGroup) {
158
159  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
160    const Record *R = Diags[i];
161    DefInit *DI = dyn_cast<DefInit>(R->getValueInit("Group"));
162    if (!DI)
163      continue;
164    assert(R->getValueAsDef("Class")->getName() != "CLASS_NOTE" &&
165           "Note can't be in a DiagGroup");
166    std::string GroupName =
167        std::string(DI->getDef()->getValueAsString("GroupName"));
168    DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
169  }
170
171  // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
172  // groups (these are warnings that GCC supports that clang never produces).
173  for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
174    Record *Group = DiagGroups[i];
175    GroupInfo &GI =
176        DiagsInGroup[std::string(Group->getValueAsString("GroupName"))];
177    GI.Defs.push_back(Group);
178
179    std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
180    for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
181      GI.SubGroups.push_back(
182          std::string(SubGroups[j]->getValueAsString("GroupName")));
183  }
184
185  // Assign unique ID numbers to the groups.
186  unsigned IDNo = 0;
187  for (std::map<std::string, GroupInfo>::iterator
188       I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
189    I->second.IDNo = IDNo;
190
191  // Warn if the same group is defined more than once (including implicitly).
192  for (auto &Group : DiagsInGroup) {
193    if (Group.second.Defs.size() == 1 &&
194        (!Group.second.Defs.front()->isAnonymous() ||
195         Group.second.DiagsInGroup.size() <= 1))
196      continue;
197
198    bool First = true;
199    for (const Record *Def : Group.second.Defs) {
200      // Skip implicit definitions from diagnostics; we'll report those
201      // separately below.
202      bool IsImplicit = false;
203      for (const Record *Diag : Group.second.DiagsInGroup) {
204        if (cast<DefInit>(Diag->getValueInit("Group"))->getDef() == Def) {
205          IsImplicit = true;
206          break;
207        }
208      }
209      if (IsImplicit)
210        continue;
211
212      llvm::SMLoc Loc = Def->getLoc().front();
213      if (First) {
214        SrcMgr.PrintMessage(Loc, SourceMgr::DK_Error,
215                            Twine("group '") + Group.first +
216                                "' is defined more than once");
217        First = false;
218      } else {
219        SrcMgr.PrintMessage(Loc, SourceMgr::DK_Note, "also defined here");
220      }
221    }
222
223    for (const Record *Diag : Group.second.DiagsInGroup) {
224      if (!cast<DefInit>(Diag->getValueInit("Group"))->getDef()->isAnonymous())
225        continue;
226
227      llvm::SMLoc Loc = Diag->getLoc().front();
228      if (First) {
229        SrcMgr.PrintMessage(Loc, SourceMgr::DK_Error,
230                            Twine("group '") + Group.first +
231                                "' is implicitly defined more than once");
232        First = false;
233      } else {
234        SrcMgr.PrintMessage(Loc, SourceMgr::DK_Note,
235                            "also implicitly defined here");
236      }
237    }
238  }
239}
240
241//===----------------------------------------------------------------------===//
242// Infer members of -Wpedantic.
243//===----------------------------------------------------------------------===//
244
245typedef std::vector<const Record *> RecordVec;
246typedef llvm::DenseSet<const Record *> RecordSet;
247typedef llvm::PointerUnion<RecordVec*, RecordSet*> VecOrSet;
248
249namespace {
250class InferPedantic {
251  typedef llvm::DenseMap<const Record*,
252                         std::pair<unsigned, Optional<unsigned> > > GMap;
253
254  DiagGroupParentMap &DiagGroupParents;
255  const std::vector<Record*> &Diags;
256  const std::vector<Record*> DiagGroups;
257  std::map<std::string, GroupInfo> &DiagsInGroup;
258  llvm::DenseSet<const Record*> DiagsSet;
259  GMap GroupCount;
260public:
261  InferPedantic(DiagGroupParentMap &DiagGroupParents,
262                const std::vector<Record*> &Diags,
263                const std::vector<Record*> &DiagGroups,
264                std::map<std::string, GroupInfo> &DiagsInGroup)
265  : DiagGroupParents(DiagGroupParents),
266  Diags(Diags),
267  DiagGroups(DiagGroups),
268  DiagsInGroup(DiagsInGroup) {}
269
270  /// Compute the set of diagnostics and groups that are immediately
271  /// in -Wpedantic.
272  void compute(VecOrSet DiagsInPedantic,
273               VecOrSet GroupsInPedantic);
274
275private:
276  /// Determine whether a group is a subgroup of another group.
277  bool isSubGroupOfGroup(const Record *Group,
278                         llvm::StringRef RootGroupName);
279
280  /// Determine if the diagnostic is an extension.
281  bool isExtension(const Record *Diag);
282
283  /// Determine if the diagnostic is off by default.
284  bool isOffByDefault(const Record *Diag);
285
286  /// Increment the count for a group, and transitively marked
287  /// parent groups when appropriate.
288  void markGroup(const Record *Group);
289
290  /// Return true if the diagnostic is in a pedantic group.
291  bool groupInPedantic(const Record *Group, bool increment = false);
292};
293} // end anonymous namespace
294
295bool InferPedantic::isSubGroupOfGroup(const Record *Group,
296                                      llvm::StringRef GName) {
297  const std::string &GroupName =
298      std::string(Group->getValueAsString("GroupName"));
299  if (GName == GroupName)
300    return true;
301
302  const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
303  for (unsigned i = 0, e = Parents.size(); i != e; ++i)
304    if (isSubGroupOfGroup(Parents[i], GName))
305      return true;
306
307  return false;
308}
309
310/// Determine if the diagnostic is an extension.
311bool InferPedantic::isExtension(const Record *Diag) {
312  const std::string &ClsName =
313      std::string(Diag->getValueAsDef("Class")->getName());
314  return ClsName == "CLASS_EXTENSION";
315}
316
317bool InferPedantic::isOffByDefault(const Record *Diag) {
318  const std::string &DefSeverity = std::string(
319      Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name"));
320  return DefSeverity == "Ignored";
321}
322
323bool InferPedantic::groupInPedantic(const Record *Group, bool increment) {
324  GMap::mapped_type &V = GroupCount[Group];
325  // Lazily compute the threshold value for the group count.
326  if (!V.second.hasValue()) {
327    const GroupInfo &GI =
328        DiagsInGroup[std::string(Group->getValueAsString("GroupName"))];
329    V.second = GI.SubGroups.size() + GI.DiagsInGroup.size();
330  }
331
332  if (increment)
333    ++V.first;
334
335  // Consider a group in -Wpendatic IFF if has at least one diagnostic
336  // or subgroup AND all of those diagnostics and subgroups are covered
337  // by -Wpedantic via our computation.
338  return V.first != 0 && V.first == V.second.getValue();
339}
340
341void InferPedantic::markGroup(const Record *Group) {
342  // If all the diagnostics and subgroups have been marked as being
343  // covered by -Wpedantic, increment the count of parent groups.  Once the
344  // group's count is equal to the number of subgroups and diagnostics in
345  // that group, we can safely add this group to -Wpedantic.
346  if (groupInPedantic(Group, /* increment */ true)) {
347    const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
348    for (unsigned i = 0, e = Parents.size(); i != e; ++i)
349      markGroup(Parents[i]);
350  }
351}
352
353void InferPedantic::compute(VecOrSet DiagsInPedantic,
354                            VecOrSet GroupsInPedantic) {
355  // All extensions that are not on by default are implicitly in the
356  // "pedantic" group.  For those that aren't explicitly included in -Wpedantic,
357  // mark them for consideration to be included in -Wpedantic directly.
358  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
359    Record *R = Diags[i];
360    if (isExtension(R) && isOffByDefault(R)) {
361      DiagsSet.insert(R);
362      if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
363        const Record *GroupRec = Group->getDef();
364        if (!isSubGroupOfGroup(GroupRec, "pedantic")) {
365          markGroup(GroupRec);
366        }
367      }
368    }
369  }
370
371  // Compute the set of diagnostics that are directly in -Wpedantic.  We
372  // march through Diags a second time to ensure the results are emitted
373  // in deterministic order.
374  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
375    Record *R = Diags[i];
376    if (!DiagsSet.count(R))
377      continue;
378    // Check if the group is implicitly in -Wpedantic.  If so,
379    // the diagnostic should not be directly included in the -Wpedantic
380    // diagnostic group.
381    if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group")))
382      if (groupInPedantic(Group->getDef()))
383        continue;
384
385    // The diagnostic is not included in a group that is (transitively) in
386    // -Wpedantic.  Include it in -Wpedantic directly.
387    if (RecordVec *V = DiagsInPedantic.dyn_cast<RecordVec*>())
388      V->push_back(R);
389    else {
390      DiagsInPedantic.get<RecordSet*>()->insert(R);
391    }
392  }
393
394  if (!GroupsInPedantic)
395    return;
396
397  // Compute the set of groups that are directly in -Wpedantic.  We
398  // march through the groups to ensure the results are emitted
399  /// in a deterministc order.
400  for (unsigned i = 0, ei = DiagGroups.size(); i != ei; ++i) {
401    Record *Group = DiagGroups[i];
402    if (!groupInPedantic(Group))
403      continue;
404
405    unsigned ParentsInPedantic = 0;
406    const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
407    for (unsigned j = 0, ej = Parents.size(); j != ej; ++j) {
408      if (groupInPedantic(Parents[j]))
409        ++ParentsInPedantic;
410    }
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 && ParentsInPedantic == Parents.size())
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  LLVM_ATTRIBUTE_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 = 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    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("Text");
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("Text");
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 associated with the diagnostic. This is stored as an index into
1283    // the alphabetically sorted warning 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("Deferrable"))
1313      OS << ", true";
1314    else
1315      OS << ", false";
1316
1317    // Category number.
1318    OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
1319    OS << ")\n";
1320  }
1321}
1322
1323//===----------------------------------------------------------------------===//
1324// Warning Group Tables generation
1325//===----------------------------------------------------------------------===//
1326
1327static std::string getDiagCategoryEnum(llvm::StringRef name) {
1328  if (name.empty())
1329    return "DiagCat_None";
1330  SmallString<256> enumName = llvm::StringRef("DiagCat_");
1331  for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
1332    enumName += isalnum(*I) ? *I : '_';
1333  return std::string(enumName.str());
1334}
1335
1336/// Emit the array of diagnostic subgroups.
1337///
1338/// The array of diagnostic subgroups contains for each group a list of its
1339/// subgroups. The individual lists are separated by '-1'. Groups with no
1340/// subgroups are skipped.
1341///
1342/// \code
1343///   static const int16_t DiagSubGroups[] = {
1344///     /* Empty */ -1,
1345///     /* DiagSubGroup0 */ 142, -1,
1346///     /* DiagSubGroup13 */ 265, 322, 399, -1
1347///   }
1348/// \endcode
1349///
1350static void emitDiagSubGroups(std::map<std::string, GroupInfo> &DiagsInGroup,
1351                              RecordVec &GroupsInPedantic, raw_ostream &OS) {
1352  OS << "static const int16_t DiagSubGroups[] = {\n"
1353     << "  /* Empty */ -1,\n";
1354  for (auto const &I : DiagsInGroup) {
1355    const bool IsPedantic = I.first == "pedantic";
1356
1357    const std::vector<std::string> &SubGroups = I.second.SubGroups;
1358    if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty())) {
1359      OS << "  /* DiagSubGroup" << I.second.IDNo << " */ ";
1360      for (auto const &SubGroup : SubGroups) {
1361        std::map<std::string, GroupInfo>::const_iterator RI =
1362            DiagsInGroup.find(SubGroup);
1363        assert(RI != DiagsInGroup.end() && "Referenced without existing?");
1364        OS << RI->second.IDNo << ", ";
1365      }
1366      // Emit the groups implicitly in "pedantic".
1367      if (IsPedantic) {
1368        for (auto const &Group : GroupsInPedantic) {
1369          const std::string &GroupName =
1370              std::string(Group->getValueAsString("GroupName"));
1371          std::map<std::string, GroupInfo>::const_iterator RI =
1372              DiagsInGroup.find(GroupName);
1373          assert(RI != DiagsInGroup.end() && "Referenced without existing?");
1374          OS << RI->second.IDNo << ", ";
1375        }
1376      }
1377
1378      OS << "-1,\n";
1379    }
1380  }
1381  OS << "};\n\n";
1382}
1383
1384/// Emit the list of diagnostic arrays.
1385///
1386/// This data structure is a large array that contains itself arrays of varying
1387/// size. Each array represents a list of diagnostics. The different arrays are
1388/// separated by the value '-1'.
1389///
1390/// \code
1391///   static const int16_t DiagArrays[] = {
1392///     /* Empty */ -1,
1393///     /* DiagArray1 */ diag::warn_pragma_message,
1394///                      -1,
1395///     /* DiagArray2 */ diag::warn_abs_too_small,
1396///                      diag::warn_unsigned_abs,
1397///                      diag::warn_wrong_absolute_value_type,
1398///                      -1
1399///   };
1400/// \endcode
1401///
1402static void emitDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
1403                           RecordVec &DiagsInPedantic, raw_ostream &OS) {
1404  OS << "static const int16_t DiagArrays[] = {\n"
1405     << "  /* Empty */ -1,\n";
1406  for (auto const &I : DiagsInGroup) {
1407    const bool IsPedantic = I.first == "pedantic";
1408
1409    const std::vector<const Record *> &V = I.second.DiagsInGroup;
1410    if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) {
1411      OS << "  /* DiagArray" << I.second.IDNo << " */ ";
1412      for (auto *Record : V)
1413        OS << "diag::" << Record->getName() << ", ";
1414      // Emit the diagnostics implicitly in "pedantic".
1415      if (IsPedantic) {
1416        for (auto const &Diag : DiagsInPedantic)
1417          OS << "diag::" << Diag->getName() << ", ";
1418      }
1419      OS << "-1,\n";
1420    }
1421  }
1422  OS << "};\n\n";
1423}
1424
1425/// Emit a list of group names.
1426///
1427/// This creates a long string which by itself contains a list of pascal style
1428/// strings, which consist of a length byte directly followed by the string.
1429///
1430/// \code
1431///   static const char DiagGroupNames[] = {
1432///     \000\020#pragma-messages\t#warnings\020CFString-literal"
1433///   };
1434/// \endcode
1435static void emitDiagGroupNames(StringToOffsetTable &GroupNames,
1436                               raw_ostream &OS) {
1437  OS << "static const char DiagGroupNames[] = {\n";
1438  GroupNames.EmitString(OS);
1439  OS << "};\n\n";
1440}
1441
1442/// Emit diagnostic arrays and related data structures.
1443///
1444/// This creates the actual diagnostic array, an array of diagnostic subgroups
1445/// and an array of subgroup names.
1446///
1447/// \code
1448///  #ifdef GET_DIAG_ARRAYS
1449///     static const int16_t DiagArrays[];
1450///     static const int16_t DiagSubGroups[];
1451///     static const char DiagGroupNames[];
1452///  #endif
1453///  \endcode
1454static void emitAllDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
1455                              RecordVec &DiagsInPedantic,
1456                              RecordVec &GroupsInPedantic,
1457                              StringToOffsetTable &GroupNames,
1458                              raw_ostream &OS) {
1459  OS << "\n#ifdef GET_DIAG_ARRAYS\n";
1460  emitDiagArrays(DiagsInGroup, DiagsInPedantic, OS);
1461  emitDiagSubGroups(DiagsInGroup, GroupsInPedantic, OS);
1462  emitDiagGroupNames(GroupNames, OS);
1463  OS << "#endif // GET_DIAG_ARRAYS\n\n";
1464}
1465
1466/// Emit diagnostic table.
1467///
1468/// The table is sorted by the name of the diagnostic group. Each element
1469/// consists of the name of the diagnostic group (given as offset in the
1470/// group name table), a reference to a list of diagnostics (optional) and a
1471/// reference to a set of subgroups (optional).
1472///
1473/// \code
1474/// #ifdef GET_DIAG_TABLE
1475///  {/* abi */              159, /* DiagArray11 */ 19, /* Empty */          0},
1476///  {/* aggregate-return */ 180, /* Empty */        0, /* Empty */          0},
1477///  {/* all */              197, /* Empty */        0, /* DiagSubGroup13 */ 3},
1478///  {/* deprecated */       1981,/* DiagArray1 */ 348, /* DiagSubGroup3 */  9},
1479/// #endif
1480/// \endcode
1481static void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup,
1482                          RecordVec &DiagsInPedantic,
1483                          RecordVec &GroupsInPedantic,
1484                          StringToOffsetTable &GroupNames, raw_ostream &OS) {
1485  unsigned MaxLen = 0;
1486
1487  for (auto const &I: DiagsInGroup)
1488    MaxLen = std::max(MaxLen, (unsigned)I.first.size());
1489
1490  OS << "\n#ifdef GET_DIAG_TABLE\n";
1491  unsigned SubGroupIndex = 1, DiagArrayIndex = 1;
1492  for (auto const &I: DiagsInGroup) {
1493    // Group option string.
1494    OS << "  { /* ";
1495    if (I.first.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
1496                                   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1497                                   "0123456789!@#$%^*-+=:?") !=
1498        std::string::npos)
1499      PrintFatalError("Invalid character in diagnostic group '" + I.first +
1500                      "'");
1501    OS << I.first << " */ " << std::string(MaxLen - I.first.size(), ' ');
1502    // Store a pascal-style length byte at the beginning of the string.
1503    std::string Name = char(I.first.size()) + I.first;
1504    OS << GroupNames.GetOrAddStringOffset(Name, false) << ", ";
1505
1506    // Special handling for 'pedantic'.
1507    const bool IsPedantic = I.first == "pedantic";
1508
1509    // Diagnostics in the group.
1510    const std::vector<const Record *> &V = I.second.DiagsInGroup;
1511    const bool hasDiags =
1512        !V.empty() || (IsPedantic && !DiagsInPedantic.empty());
1513    if (hasDiags) {
1514      OS << "/* DiagArray" << I.second.IDNo << " */ " << DiagArrayIndex
1515         << ", ";
1516      if (IsPedantic)
1517        DiagArrayIndex += DiagsInPedantic.size();
1518      DiagArrayIndex += V.size() + 1;
1519    } else {
1520      OS << "/* Empty */     0, ";
1521    }
1522
1523    // Subgroups.
1524    const std::vector<std::string> &SubGroups = I.second.SubGroups;
1525    const bool hasSubGroups =
1526        !SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty());
1527    if (hasSubGroups) {
1528      OS << "/* DiagSubGroup" << I.second.IDNo << " */ " << SubGroupIndex;
1529      if (IsPedantic)
1530        SubGroupIndex += GroupsInPedantic.size();
1531      SubGroupIndex += SubGroups.size() + 1;
1532    } else {
1533      OS << "/* Empty */         0";
1534    }
1535
1536    OS << " },\n";
1537  }
1538  OS << "#endif // GET_DIAG_TABLE\n\n";
1539}
1540
1541/// Emit the table of diagnostic categories.
1542///
1543/// The table has the form of macro calls that have two parameters. The
1544/// category's name as well as an enum that represents the category. The
1545/// table can be used by defining the macro 'CATEGORY' and including this
1546/// table right after.
1547///
1548/// \code
1549/// #ifdef GET_CATEGORY_TABLE
1550///   CATEGORY("Semantic Issue", DiagCat_Semantic_Issue)
1551///   CATEGORY("Lambda Issue", DiagCat_Lambda_Issue)
1552/// #endif
1553/// \endcode
1554static void emitCategoryTable(RecordKeeper &Records, raw_ostream &OS) {
1555  DiagCategoryIDMap CategoriesByID(Records);
1556  OS << "\n#ifdef GET_CATEGORY_TABLE\n";
1557  for (auto const &C : CategoriesByID)
1558    OS << "CATEGORY(\"" << C << "\", " << getDiagCategoryEnum(C) << ")\n";
1559  OS << "#endif // GET_CATEGORY_TABLE\n\n";
1560}
1561
1562void clang::EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
1563  // Compute a mapping from a DiagGroup to all of its parents.
1564  DiagGroupParentMap DGParentMap(Records);
1565
1566  std::vector<Record *> Diags = Records.getAllDerivedDefinitions("Diagnostic");
1567
1568  std::vector<Record *> DiagGroups =
1569      Records.getAllDerivedDefinitions("DiagGroup");
1570
1571  std::map<std::string, GroupInfo> DiagsInGroup;
1572  groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
1573
1574  // All extensions are implicitly in the "pedantic" group.  Record the
1575  // implicit set of groups in the "pedantic" group, and use this information
1576  // later when emitting the group information for Pedantic.
1577  RecordVec DiagsInPedantic;
1578  RecordVec GroupsInPedantic;
1579  InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
1580  inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic);
1581
1582  StringToOffsetTable GroupNames;
1583  for (std::map<std::string, GroupInfo>::const_iterator
1584           I = DiagsInGroup.begin(),
1585           E = DiagsInGroup.end();
1586       I != E; ++I) {
1587    // Store a pascal-style length byte at the beginning of the string.
1588    std::string Name = char(I->first.size()) + I->first;
1589    GroupNames.GetOrAddStringOffset(Name, false);
1590  }
1591
1592  emitAllDiagArrays(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
1593                    OS);
1594  emitDiagTable(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
1595                OS);
1596  emitCategoryTable(Records, OS);
1597}
1598
1599//===----------------------------------------------------------------------===//
1600// Diagnostic name index generation
1601//===----------------------------------------------------------------------===//
1602
1603namespace {
1604struct RecordIndexElement
1605{
1606  RecordIndexElement() {}
1607  explicit RecordIndexElement(Record const &R)
1608      : Name(std::string(R.getName())) {}
1609
1610  std::string Name;
1611};
1612} // end anonymous namespace.
1613
1614void clang::EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
1615  const std::vector<Record*> &Diags =
1616    Records.getAllDerivedDefinitions("Diagnostic");
1617
1618  std::vector<RecordIndexElement> Index;
1619  Index.reserve(Diags.size());
1620  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
1621    const Record &R = *(Diags[i]);
1622    Index.push_back(RecordIndexElement(R));
1623  }
1624
1625  llvm::sort(Index,
1626             [](const RecordIndexElement &Lhs, const RecordIndexElement &Rhs) {
1627               return Lhs.Name < Rhs.Name;
1628             });
1629
1630  for (unsigned i = 0, e = Index.size(); i != e; ++i) {
1631    const RecordIndexElement &R = Index[i];
1632
1633    OS << "DIAG_NAME_INDEX(" << R.Name << ")\n";
1634  }
1635}
1636
1637//===----------------------------------------------------------------------===//
1638// Diagnostic documentation generation
1639//===----------------------------------------------------------------------===//
1640
1641namespace docs {
1642namespace {
1643
1644bool isRemarkGroup(const Record *DiagGroup,
1645                   const std::map<std::string, GroupInfo> &DiagsInGroup) {
1646  bool AnyRemarks = false, AnyNonRemarks = false;
1647
1648  std::function<void(StringRef)> Visit = [&](StringRef GroupName) {
1649    auto &GroupInfo = DiagsInGroup.find(std::string(GroupName))->second;
1650    for (const Record *Diag : GroupInfo.DiagsInGroup)
1651      (isRemark(*Diag) ? AnyRemarks : AnyNonRemarks) = true;
1652    for (const auto &Name : GroupInfo.SubGroups)
1653      Visit(Name);
1654  };
1655  Visit(DiagGroup->getValueAsString("GroupName"));
1656
1657  if (AnyRemarks && AnyNonRemarks)
1658    PrintFatalError(
1659        DiagGroup->getLoc(),
1660        "Diagnostic group contains both remark and non-remark diagnostics");
1661  return AnyRemarks;
1662}
1663
1664std::string getDefaultSeverity(const Record *Diag) {
1665  return std::string(
1666      Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name"));
1667}
1668
1669std::set<std::string>
1670getDefaultSeverities(const Record *DiagGroup,
1671                     const std::map<std::string, GroupInfo> &DiagsInGroup) {
1672  std::set<std::string> States;
1673
1674  std::function<void(StringRef)> Visit = [&](StringRef GroupName) {
1675    auto &GroupInfo = DiagsInGroup.find(std::string(GroupName))->second;
1676    for (const Record *Diag : GroupInfo.DiagsInGroup)
1677      States.insert(getDefaultSeverity(Diag));
1678    for (const auto &Name : GroupInfo.SubGroups)
1679      Visit(Name);
1680  };
1681  Visit(DiagGroup->getValueAsString("GroupName"));
1682  return States;
1683}
1684
1685void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') {
1686  OS << Str << "\n" << std::string(Str.size(), Kind) << "\n";
1687}
1688
1689void writeDiagnosticText(DiagnosticTextBuilder &Builder, const Record *R,
1690                         StringRef Role, raw_ostream &OS) {
1691  StringRef Text = R->getValueAsString("Text");
1692  if (Text == "%0")
1693    OS << "The text of this diagnostic is not controlled by Clang.\n\n";
1694  else {
1695    std::vector<std::string> Out = Builder.buildForDocumentation(Role, R);
1696    for (auto &Line : Out)
1697      OS << Line << "\n";
1698    OS << "\n";
1699  }
1700}
1701
1702}  // namespace
1703}  // namespace docs
1704
1705void clang::EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
1706  using namespace docs;
1707
1708  // Get the documentation introduction paragraph.
1709  const Record *Documentation = Records.getDef("GlobalDocumentation");
1710  if (!Documentation) {
1711    PrintFatalError("The Documentation top-level definition is missing, "
1712                    "no documentation will be generated.");
1713    return;
1714  }
1715
1716  OS << Documentation->getValueAsString("Intro") << "\n";
1717
1718  DiagnosticTextBuilder Builder(Records);
1719
1720  std::vector<Record*> Diags =
1721      Records.getAllDerivedDefinitions("Diagnostic");
1722
1723  std::vector<Record*> DiagGroups =
1724      Records.getAllDerivedDefinitions("DiagGroup");
1725  llvm::sort(DiagGroups, diagGroupBeforeByName);
1726
1727  DiagGroupParentMap DGParentMap(Records);
1728
1729  std::map<std::string, GroupInfo> DiagsInGroup;
1730  groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
1731
1732  // Compute the set of diagnostics that are in -Wpedantic.
1733  {
1734    RecordSet DiagsInPedanticSet;
1735    RecordSet GroupsInPedanticSet;
1736    InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
1737    inferPedantic.compute(&DiagsInPedanticSet, &GroupsInPedanticSet);
1738    auto &PedDiags = DiagsInGroup["pedantic"];
1739    // Put the diagnostics into a deterministic order.
1740    RecordVec DiagsInPedantic(DiagsInPedanticSet.begin(),
1741                              DiagsInPedanticSet.end());
1742    RecordVec GroupsInPedantic(GroupsInPedanticSet.begin(),
1743                               GroupsInPedanticSet.end());
1744    llvm::sort(DiagsInPedantic, beforeThanCompare);
1745    llvm::sort(GroupsInPedantic, beforeThanCompare);
1746    PedDiags.DiagsInGroup.insert(PedDiags.DiagsInGroup.end(),
1747                                 DiagsInPedantic.begin(),
1748                                 DiagsInPedantic.end());
1749    for (auto *Group : GroupsInPedantic)
1750      PedDiags.SubGroups.push_back(
1751          std::string(Group->getValueAsString("GroupName")));
1752  }
1753
1754  // FIXME: Write diagnostic categories and link to diagnostic groups in each.
1755
1756  // Write out the diagnostic groups.
1757  for (const Record *G : DiagGroups) {
1758    bool IsRemarkGroup = isRemarkGroup(G, DiagsInGroup);
1759    auto &GroupInfo =
1760        DiagsInGroup[std::string(G->getValueAsString("GroupName"))];
1761    bool IsSynonym = GroupInfo.DiagsInGroup.empty() &&
1762                     GroupInfo.SubGroups.size() == 1;
1763
1764    writeHeader(((IsRemarkGroup ? "-R" : "-W") +
1765                    G->getValueAsString("GroupName")).str(),
1766                OS);
1767
1768    if (!IsSynonym) {
1769      // FIXME: Ideally, all the diagnostics in a group should have the same
1770      // default state, but that is not currently the case.
1771      auto DefaultSeverities = getDefaultSeverities(G, DiagsInGroup);
1772      if (!DefaultSeverities.empty() && !DefaultSeverities.count("Ignored")) {
1773        bool AnyNonErrors = DefaultSeverities.count("Warning") ||
1774                            DefaultSeverities.count("Remark");
1775        if (!AnyNonErrors)
1776          OS << "This diagnostic is an error by default, but the flag ``-Wno-"
1777             << G->getValueAsString("GroupName") << "`` can be used to disable "
1778             << "the error.\n\n";
1779        else
1780          OS << "This diagnostic is enabled by default.\n\n";
1781      } else if (DefaultSeverities.size() > 1) {
1782        OS << "Some of the diagnostics controlled by this flag are enabled "
1783           << "by default.\n\n";
1784      }
1785    }
1786
1787    if (!GroupInfo.SubGroups.empty()) {
1788      if (IsSynonym)
1789        OS << "Synonym for ";
1790      else if (GroupInfo.DiagsInGroup.empty())
1791        OS << "Controls ";
1792      else
1793        OS << "Also controls ";
1794
1795      bool First = true;
1796      llvm::sort(GroupInfo.SubGroups);
1797      for (const auto &Name : GroupInfo.SubGroups) {
1798        if (!First) OS << ", ";
1799        OS << "`" << (IsRemarkGroup ? "-R" : "-W") << Name << "`_";
1800        First = false;
1801      }
1802      OS << ".\n\n";
1803    }
1804
1805    if (!GroupInfo.DiagsInGroup.empty()) {
1806      OS << "**Diagnostic text:**\n\n";
1807      for (const Record *D : GroupInfo.DiagsInGroup) {
1808        auto Severity = getDefaultSeverity(D);
1809        Severity[0] = tolower(Severity[0]);
1810        if (Severity == "ignored")
1811          Severity = IsRemarkGroup ? "remark" : "warning";
1812
1813        writeDiagnosticText(Builder, D, Severity, OS);
1814      }
1815    }
1816
1817    auto Doc = G->getValueAsString("Documentation");
1818    if (!Doc.empty())
1819      OS << Doc;
1820    else if (GroupInfo.SubGroups.empty() && GroupInfo.DiagsInGroup.empty())
1821      OS << "This diagnostic flag exists for GCC compatibility, and has no "
1822            "effect in Clang.\n";
1823    OS << "\n";
1824  }
1825}
1826