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