Clang Project

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