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