151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//=- ClangDiagnosticsEmitter.cpp - Generate Clang diagnostics tables -*- C++ -*-
251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//                     The LLVM Compiler Infrastructure
451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// This file is distributed under the University of Illinois Open Source
651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// License. See LICENSE.TXT for details.
751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
1051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// These tablegen backends emit Clang diagnostics tables.
1151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//
1251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
1351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
1451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/DenseSet.h"
1530bc63ffbab71522e5c5a9adc5054e462a0cbf65Chandler Carruth#include "llvm/ADT/Optional.h"
1630bc63ffbab71522e5c5a9adc5054e462a0cbf65Chandler Carruth#include "llvm/ADT/PointerUnion.h"
1798e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose#include "llvm/ADT/SetVector.h"
1898e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose#include "llvm/ADT/SmallPtrSet.h"
1951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/SmallString.h"
2098e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose#include "llvm/ADT/SmallVector.h"
213cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/ADT/StringMap.h"
2298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose#include "llvm/ADT/Twine.h"
233cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/Support/Compiler.h"
243cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/Support/Debug.h"
2538859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger#include "llvm/TableGen/Error.h"
263cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/Record.h"
27354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper#include "llvm/TableGen/StringToOffsetTable.h"
283cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/TableGenBackend.h"
2951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include <algorithm>
307094dee95f8c915d27097ac18b47d1ef31fd72edJoerg Sonnenberger#include <cctype>
3151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include <functional>
323cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include <map>
33d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer#include <set>
3451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourneusing namespace llvm;
3551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
3651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
3751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Diagnostic category computation code.
3851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
3951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
4051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournenamespace {
4151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourneclass DiagGroupParentMap {
4251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  RecordKeeper &Records;
4351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::map<const Record*, std::vector<Record*> > Mapping;
4451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournepublic:
4551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  DiagGroupParentMap(RecordKeeper &records) : Records(records) {
4651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::vector<Record*> DiagGroups
4751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      = Records.getAllDerivedDefinitions("DiagGroup");
4851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
4951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::vector<Record*> SubGroups =
5051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        DiagGroups[i]->getValueAsListOfDefs("SubGroups");
5151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
5251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        Mapping[SubGroups[j]].push_back(DiagGroups[i]);
5351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
5451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
55519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
5651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const std::vector<Record*> &getParents(const Record *Group) {
5751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return Mapping[Group];
5851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
5951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne};
6051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} // end anonymous namespace.
6151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
6251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string
6351d7777a21b9706d503496c650af06f80d278c1aPeter CollingbournegetCategoryFromDiagGroup(const Record *Group,
6451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                         DiagGroupParentMap &DiagGroupParents) {
6551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If the DiagGroup has a category, return it.
6651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string CatName = Group->getValueAsString("CategoryName");
6751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (!CatName.empty()) return CatName;
68519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
6951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // The diag group may the subgroup of one or more other diagnostic groups,
7051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // check these for a category as well.
7151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
7251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
7351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
7451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (!CatName.empty()) return CatName;
7551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
7651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return "";
7751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
7851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
7951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// getDiagnosticCategory - Return the category that the specified diagnostic
8051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// lives in.
8151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string getDiagnosticCategory(const Record *R,
8251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                         DiagGroupParentMap &DiagGroupParents) {
8351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If the diagnostic is in a group, and that group has a category, use it.
841ab46323089f9a836a510521aab55ff958b67150Sean Silva  if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
8551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Check the diagnostic's diag group for a category.
8651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string CatName = getCategoryFromDiagGroup(Group->getDef(),
8751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                                   DiagGroupParents);
8851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (!CatName.empty()) return CatName;
8951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
90e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
9151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If the diagnostic itself has a category, get it.
9251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return R->getValueAsString("CategoryName");
9351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
9451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
9551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournenamespace {
9651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  class DiagCategoryIDMap {
9751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    RecordKeeper &Records;
9851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringMap<unsigned> CategoryIDs;
9951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::vector<std::string> CategoryStrings;
10051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  public:
10151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    DiagCategoryIDMap(RecordKeeper &records) : Records(records) {
10251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      DiagGroupParentMap ParentInfo(Records);
103519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
10451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // The zero'th category is "".
10551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      CategoryStrings.push_back("");
10651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      CategoryIDs[""] = 0;
107519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
10851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::vector<Record*> Diags =
10951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Records.getAllDerivedDefinitions("Diagnostic");
11051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
11151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
11251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (Category.empty()) continue;  // Skip diags with no category.
113519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
11451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        unsigned &ID = CategoryIDs[Category];
11551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (ID != 0) continue;  // Already seen.
116519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
11751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ID = CategoryStrings.size();
11851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        CategoryStrings.push_back(Category);
11951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
12051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
121519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
12251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned getID(StringRef CategoryString) {
12351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return CategoryIDs[CategoryString];
12451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
125519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
12685c48510a6fbbdad61cae381b4d788d388d62458Craig Topper    typedef std::vector<std::string>::const_iterator const_iterator;
12785c48510a6fbbdad61cae381b4d788d388d62458Craig Topper    const_iterator begin() const { return CategoryStrings.begin(); }
12885c48510a6fbbdad61cae381b4d788d388d62458Craig Topper    const_iterator end() const { return CategoryStrings.end(); }
12951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  };
130d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis
131d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  struct GroupInfo {
132d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    std::vector<const Record*> DiagsInGroup;
133d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    std::vector<std::string> SubGroups;
134d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    unsigned IDNo;
13598e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
13698e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose    const Record *ExplicitDef;
13798e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
1386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    GroupInfo() : ExplicitDef(nullptr) {}
139d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  };
14051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} // end anonymous namespace.
14151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
14298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rosestatic bool beforeThanCompare(const Record *LHS, const Record *RHS) {
14398e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  assert(!LHS->getLoc().empty() && !RHS->getLoc().empty());
14498e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  return
14598e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose    LHS->getLoc().front().getPointer() < RHS->getLoc().front().getPointer();
14698e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose}
14798e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
14898e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rosestatic bool beforeThanCompareGroups(const GroupInfo *LHS, const GroupInfo *RHS){
14998e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  assert(!LHS->DiagsInGroup.empty() && !RHS->DiagsInGroup.empty());
15098e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  return beforeThanCompare(LHS->DiagsInGroup.front(),
15198e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                           RHS->DiagsInGroup.front());
15298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose}
15398e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
15498e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rosestatic SMRange findSuperClassRange(const Record *R, StringRef SuperName) {
15598e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  ArrayRef<Record *> Supers = R->getSuperClasses();
15698e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
15798e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  for (size_t i = 0, e = Supers.size(); i < e; ++i)
15898e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose    if (Supers[i]->getName() == SuperName)
15998e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      return R->getSuperClassRanges()[i];
16098e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
16198e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  return SMRange();
16298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose}
16398e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
164d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis/// \brief Invert the 1-[0/1] mapping of diags to group into a one to many
165d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis/// mapping of groups to diags in the group.
166d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidisstatic void groupDiagnostics(const std::vector<Record*> &Diags,
167d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis                             const std::vector<Record*> &DiagGroups,
168d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis                             std::map<std::string, GroupInfo> &DiagsInGroup) {
16998e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
170d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
171d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    const Record *R = Diags[i];
1721ab46323089f9a836a510521aab55ff958b67150Sean Silva    DefInit *DI = dyn_cast<DefInit>(R->getValueInit("Group"));
1736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (!DI)
1746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      continue;
17546484770fe264fba24f7a9f608a3b7c3342690aaRichard Smith    assert(R->getValueAsDef("Class")->getName() != "CLASS_NOTE" &&
17646484770fe264fba24f7a9f608a3b7c3342690aaRichard Smith           "Note can't be in a DiagGroup");
177d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    std::string GroupName = DI->getDef()->getValueAsString("GroupName");
178d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
179d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  }
18098e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
18198e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  typedef SmallPtrSet<GroupInfo *, 16> GroupSetTy;
18298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  GroupSetTy ImplicitGroups;
18398e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
184d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
185d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  // groups (these are warnings that GCC supports that clang never produces).
186d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
187d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    Record *Group = DiagGroups[i];
188d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
18998e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose    if (Group->isAnonymous()) {
19098e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      if (GI.DiagsInGroup.size() > 1)
19198e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        ImplicitGroups.insert(&GI);
19298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose    } else {
19398e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      if (GI.ExplicitDef)
19498e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        assert(GI.ExplicitDef == Group);
19598e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      else
19698e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        GI.ExplicitDef = Group;
19798e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose    }
19898e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
199d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
200d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
201d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis      GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
202d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  }
203519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
204d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  // Assign unique ID numbers to the groups.
205d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  unsigned IDNo = 0;
206d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  for (std::map<std::string, GroupInfo>::iterator
207d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis       I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
208d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    I->second.IDNo = IDNo;
20998e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
21098e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  // Sort the implicit groups, so we can warn about them deterministically.
21198e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  SmallVector<GroupInfo *, 16> SortedGroups(ImplicitGroups.begin(),
21298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                                            ImplicitGroups.end());
21398e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  for (SmallVectorImpl<GroupInfo *>::iterator I = SortedGroups.begin(),
21498e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                                              E = SortedGroups.end();
21598e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose       I != E; ++I) {
21698e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose    MutableArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup;
21798e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose    std::sort(GroupDiags.begin(), GroupDiags.end(), beforeThanCompare);
21898e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  }
21998e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  std::sort(SortedGroups.begin(), SortedGroups.end(), beforeThanCompareGroups);
22098e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
22198e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  // Warn about the same group being used anonymously in multiple places.
22298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  for (SmallVectorImpl<GroupInfo *>::const_iterator I = SortedGroups.begin(),
22398e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                                                    E = SortedGroups.end();
22498e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose       I != E; ++I) {
22598e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose    ArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup;
22698e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
22798e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose    if ((*I)->ExplicitDef) {
22898e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      std::string Name = (*I)->ExplicitDef->getValueAsString("GroupName");
22998e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      for (ArrayRef<const Record *>::const_iterator DI = GroupDiags.begin(),
23098e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                                                    DE = GroupDiags.end();
23198e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose           DI != DE; ++DI) {
23298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        const DefInit *GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
23398e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        const Record *NextDiagGroup = GroupInit->getDef();
23498e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        if (NextDiagGroup == (*I)->ExplicitDef)
23598e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose          continue;
23698e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
23798e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        SMRange InGroupRange = findSuperClassRange(*DI, "InGroup");
23898e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        SmallString<64> Replacement;
23998e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        if (InGroupRange.isValid()) {
24098e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose          Replacement += "InGroup<";
24198e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose          Replacement += (*I)->ExplicitDef->getName();
24298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose          Replacement += ">";
24398e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        }
24498e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        SMFixIt FixIt(InGroupRange, Replacement.str());
24598e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
24698e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        SrcMgr.PrintMessage(NextDiagGroup->getLoc().front(),
24798e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                            SourceMgr::DK_Error,
24898e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                            Twine("group '") + Name +
24998e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                              "' is referred to anonymously",
250566bf620e1b52860b641e0feae910d40ce883afcDmitri Gribenko                            None,
25198e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                            InGroupRange.isValid() ? FixIt
25298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                                                   : ArrayRef<SMFixIt>());
25398e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        SrcMgr.PrintMessage((*I)->ExplicitDef->getLoc().front(),
25498e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                            SourceMgr::DK_Note, "group defined here");
25598e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      }
25698e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose    } else {
25798e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      // If there's no existing named group, we should just warn once and use
25898e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      // notes to list all the other cases.
25998e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      ArrayRef<const Record *>::const_iterator DI = GroupDiags.begin(),
26098e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                                               DE = GroupDiags.end();
26198e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      assert(DI != DE && "We only care about groups with multiple uses!");
26298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
26398e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      const DefInit *GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
26498e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      const Record *NextDiagGroup = GroupInit->getDef();
26598e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      std::string Name = NextDiagGroup->getValueAsString("GroupName");
26698e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
26798e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      SMRange InGroupRange = findSuperClassRange(*DI, "InGroup");
26898e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      SrcMgr.PrintMessage(NextDiagGroup->getLoc().front(),
26998e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                          SourceMgr::DK_Error,
27098e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                          Twine("group '") + Name +
27198e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                            "' is referred to anonymously",
27298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                          InGroupRange);
27398e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose
27498e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      for (++DI; DI != DE; ++DI) {
27598e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
27698e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        InGroupRange = findSuperClassRange(*DI, "InGroup");
27798e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose        SrcMgr.PrintMessage(GroupInit->getDef()->getLoc().front(),
27898e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                            SourceMgr::DK_Note, "also referenced here",
27998e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose                            InGroupRange);
28098e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose      }
28198e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose    }
28298e7369d9ef5e53964cc8ae48ec2dfcf6c4633c0Jordan Rose  }
283d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis}
28451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
28551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
286e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek// Infer members of -Wpedantic.
287e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek//===----------------------------------------------------------------------===//
288e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
289e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenektypedef std::vector<const Record *> RecordVec;
290e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenektypedef llvm::DenseSet<const Record *> RecordSet;
291e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenektypedef llvm::PointerUnion<RecordVec*, RecordSet*> VecOrSet;
292e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
293e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremeneknamespace {
294e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekclass InferPedantic {
295e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  typedef llvm::DenseMap<const Record*,
296943f909ba72a1c9351dd421cac1413d303a719f1Ted Kremenek                         std::pair<unsigned, Optional<unsigned> > > GMap;
297e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
298e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  DiagGroupParentMap &DiagGroupParents;
299e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  const std::vector<Record*> &Diags;
300e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  const std::vector<Record*> DiagGroups;
301e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  std::map<std::string, GroupInfo> &DiagsInGroup;
302e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  llvm::DenseSet<const Record*> DiagsSet;
303e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  GMap GroupCount;
304e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekpublic:
305e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  InferPedantic(DiagGroupParentMap &DiagGroupParents,
306e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                const std::vector<Record*> &Diags,
307e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                const std::vector<Record*> &DiagGroups,
308e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                std::map<std::string, GroupInfo> &DiagsInGroup)
309e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  : DiagGroupParents(DiagGroupParents),
310e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  Diags(Diags),
311e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  DiagGroups(DiagGroups),
312e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  DiagsInGroup(DiagsInGroup) {}
313e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
314e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// Compute the set of diagnostics and groups that are immediately
315e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// in -Wpedantic.
316e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  void compute(VecOrSet DiagsInPedantic,
317e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek               VecOrSet GroupsInPedantic);
318e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
319e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekprivate:
320e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// Determine whether a group is a subgroup of another group.
321e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  bool isSubGroupOfGroup(const Record *Group,
322e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                         llvm::StringRef RootGroupName);
323e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
324e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// Determine if the diagnostic is an extension.
325e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  bool isExtension(const Record *Diag);
326e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
327bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek  /// Determine if the diagnostic is off by default.
328bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek  bool isOffByDefault(const Record *Diag);
329bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek
330e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// Increment the count for a group, and transitively marked
331e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// parent groups when appropriate.
332e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  void markGroup(const Record *Group);
333e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
334e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// Return true if the diagnostic is in a pedantic group.
335e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  bool groupInPedantic(const Record *Group, bool increment = false);
336e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek};
337e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek} // end anonymous namespace
338e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
339e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekbool InferPedantic::isSubGroupOfGroup(const Record *Group,
340e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                                      llvm::StringRef GName) {
341e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
342e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  const std::string &GroupName = Group->getValueAsString("GroupName");
343e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  if (GName == GroupName)
344e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    return true;
345e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
346e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
347e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  for (unsigned i = 0, e = Parents.size(); i != e; ++i)
348e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (isSubGroupOfGroup(Parents[i], GName))
349e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      return true;
350e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
351e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  return false;
352e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek}
353e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
354e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek/// Determine if the diagnostic is an extension.
355e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekbool InferPedantic::isExtension(const Record *Diag) {
356e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  const std::string &ClsName = Diag->getValueAsDef("Class")->getName();
357e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  return ClsName == "CLASS_EXTENSION";
358e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek}
359e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
360bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenekbool InferPedantic::isOffByDefault(const Record *Diag) {
361ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  const std::string &DefSeverity =
362ef8225444452a1486bd721f3285301fe84643b00Stephen Hines      Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name");
363ef8225444452a1486bd721f3285301fe84643b00Stephen Hines  return DefSeverity == "Ignored";
364bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek}
365bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek
366e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekbool InferPedantic::groupInPedantic(const Record *Group, bool increment) {
367e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  GMap::mapped_type &V = GroupCount[Group];
368e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // Lazily compute the threshold value for the group count.
369e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  if (!V.second.hasValue()) {
370e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    const GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
371e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    V.second = GI.SubGroups.size() + GI.DiagsInGroup.size();
372e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  }
373e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
374e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  if (increment)
375e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    ++V.first;
376e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
377e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // Consider a group in -Wpendatic IFF if has at least one diagnostic
378e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // or subgroup AND all of those diagnostics and subgroups are covered
379e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // by -Wpedantic via our computation.
380e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  return V.first != 0 && V.first == V.second.getValue();
381e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek}
382e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
383e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekvoid InferPedantic::markGroup(const Record *Group) {
384e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // If all the diagnostics and subgroups have been marked as being
385e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // covered by -Wpedantic, increment the count of parent groups.  Once the
386e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // group's count is equal to the number of subgroups and diagnostics in
387e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // that group, we can safely add this group to -Wpedantic.
388e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  if (groupInPedantic(Group, /* increment */ true)) {
389e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
390e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    for (unsigned i = 0, e = Parents.size(); i != e; ++i)
391e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      markGroup(Parents[i]);
392e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  }
393e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek}
394e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
395e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekvoid InferPedantic::compute(VecOrSet DiagsInPedantic,
396e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                            VecOrSet GroupsInPedantic) {
397bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek  // All extensions that are not on by default are implicitly in the
398bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek  // "pedantic" group.  For those that aren't explicitly included in -Wpedantic,
399bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek  // mark them for consideration to be included in -Wpedantic directly.
400e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
401e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    Record *R = Diags[i];
402bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek    if (isExtension(R) && isOffByDefault(R)) {
403e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      DiagsSet.insert(R);
4041ab46323089f9a836a510521aab55ff958b67150Sean Silva      if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
405e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        const Record *GroupRec = Group->getDef();
406e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        if (!isSubGroupOfGroup(GroupRec, "pedantic")) {
407e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek          markGroup(GroupRec);
408e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        }
409e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      }
410e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    }
411e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  }
412e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
413e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // Compute the set of diagnostics that are directly in -Wpedantic.  We
414e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // march through Diags a second time to ensure the results are emitted
415e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // in deterministic order.
416e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
417e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    Record *R = Diags[i];
418e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (!DiagsSet.count(R))
419e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      continue;
420e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // Check if the group is implicitly in -Wpedantic.  If so,
421e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // the diagnostic should not be directly included in the -Wpedantic
422e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // diagnostic group.
4231ab46323089f9a836a510521aab55ff958b67150Sean Silva    if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group")))
424e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      if (groupInPedantic(Group->getDef()))
425e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        continue;
426e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
427e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // The diagnostic is not included in a group that is (transitively) in
428e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // -Wpedantic.  Include it in -Wpedantic directly.
429e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (RecordVec *V = DiagsInPedantic.dyn_cast<RecordVec*>())
430e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      V->push_back(R);
431e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    else {
432e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      DiagsInPedantic.get<RecordSet*>()->insert(R);
433e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    }
434e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  }
435e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
436e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  if (!GroupsInPedantic)
437e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    return;
438e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
439e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // Compute the set of groups that are directly in -Wpedantic.  We
440e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // march through the groups to ensure the results are emitted
441e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// in a deterministc order.
442e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  for (unsigned i = 0, ei = DiagGroups.size(); i != ei; ++i) {
443e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    Record *Group = DiagGroups[i];
444e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (!groupInPedantic(Group))
445e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      continue;
446e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
447e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    unsigned ParentsInPedantic = 0;
448e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
449e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    for (unsigned j = 0, ej = Parents.size(); j != ej; ++j) {
450e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      if (groupInPedantic(Parents[j]))
451e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        ++ParentsInPedantic;
452e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    }
453e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // If all the parents are in -Wpedantic, this means that this diagnostic
454e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // group will be indirectly included by -Wpedantic already.  In that
455e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // case, do not add it directly to -Wpedantic.  If the group has no
456e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // parents, obviously it should go into -Wpedantic.
457e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (Parents.size() > 0 && ParentsInPedantic == Parents.size())
458e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      continue;
459e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
460e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (RecordVec *V = GroupsInPedantic.dyn_cast<RecordVec*>())
461e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      V->push_back(Group);
462e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    else {
463e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      GroupsInPedantic.get<RecordSet*>()->insert(Group);
464e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    }
465e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  }
466e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek}
467e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
468e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek//===----------------------------------------------------------------------===//
46951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Warning Tables (.inc file) generation.
47051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
47151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
4724a535368eb4fca10b05c442e04725747dbf76081Ted Kremenekstatic bool isError(const Record &Diag) {
4734a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek  const std::string &ClsName = Diag.getValueAsDef("Class")->getName();
4744a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek  return ClsName == "CLASS_ERROR";
4754a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek}
4764a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek
477651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool isRemark(const Record &Diag) {
478651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const std::string &ClsName = Diag.getValueAsDef("Class")->getName();
479651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return ClsName == "CLASS_REMARK";
480651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
481651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
4823cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// ClangDiagsDefsEmitter - The top-level class emits .def files containing
4833cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// declarations of Clang diagnostics.
4843cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang {
4853cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
4863cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen                        const std::string &Component) {
48751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Write the #if guard
48851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (!Component.empty()) {
48990c7892b699c5405a81bcc339432ba2f4b50e0d6Benjamin Kramer    std::string ComponentName = StringRef(Component).upper();
49051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "#ifdef " << ComponentName << "START\n";
49151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
49251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne       << ",\n";
49351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "#undef " << ComponentName << "START\n";
49451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "#endif\n\n";
49551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
49651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
49751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const std::vector<Record*> &Diags =
49851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Records.getAllDerivedDefinitions("Diagnostic");
499d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer
500d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer  std::vector<Record*> DiagGroups
501d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer    = Records.getAllDerivedDefinitions("DiagGroup");
502d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis
503d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  std::map<std::string, GroupInfo> DiagsInGroup;
504d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
505d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer
50651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  DiagCategoryIDMap CategoryIDs(Records);
50751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  DiagGroupParentMap DGParentMap(Records);
50851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
509e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // Compute the set of diagnostics that are in -Wpedantic.
510e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  RecordSet DiagsInPedantic;
511e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
5126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  inferPedantic.compute(&DiagsInPedantic, (RecordVec*)nullptr);
513e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
51451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
51551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    const Record &R = *Diags[i];
516519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
5174a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek    // Check if this is an error that is accidentally in a warning
5184a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek    // group.
5194a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek    if (isError(R)) {
5201ab46323089f9a836a510521aab55ff958b67150Sean Silva      if (DefInit *Group = dyn_cast<DefInit>(R.getValueInit("Group"))) {
5214a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek        const Record *GroupRec = Group->getDef();
5224a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek        const std::string &GroupName = GroupRec->getValueAsString("GroupName");
52338859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger        PrintFatalError(R.getLoc(), "Error " + R.getName() +
52438859ee4a3c1253d5a45ed3f6b52e77702bfd913Joerg Sonnenberger                      " cannot be in a warning group [" + GroupName + "]");
5254a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek      }
5264a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek    }
5274a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek
528651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // Check that all remarks have an associated diagnostic group.
529651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (isRemark(R)) {
530651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (!isa<DefInit>(R.getValueInit("Group"))) {
531651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        PrintFatalError(R.getLoc(), "Error " + R.getName() +
532651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                        " not in any diagnostic group");
533651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      }
534651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
535651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
53651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Filter by component.
53751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (!Component.empty() && Component != R.getValueAsString("Component"))
53851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
53951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
54051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "DIAG(" << R.getName() << ", ";
54151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << R.getValueAsDef("Class")->getName();
542ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    OS << ", (unsigned)diag::Severity::"
543ef8225444452a1486bd721f3285301fe84643b00Stephen Hines       << R.getValueAsDef("DefaultSeverity")->getValueAsString("Name");
544519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
54551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Description string.
54651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << ", \"";
54751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS.write_escaped(R.getValueAsString("Text")) << '"';
548519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
549d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer    // Warning associated with the diagnostic. This is stored as an index into
550d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer    // the alphabetically sorted warning table.
5511ab46323089f9a836a510521aab55ff958b67150Sean Silva    if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
552d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis      std::map<std::string, GroupInfo>::iterator I =
553d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis          DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName"));
554d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis      assert(I != DiagsInGroup.end());
555d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis      OS << ", " << I->second.IDNo;
556e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    } else if (DiagsInPedantic.count(&R)) {
557e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      std::map<std::string, GroupInfo>::iterator I =
558e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        DiagsInGroup.find("pedantic");
559e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      assert(I != DiagsInGroup.end() && "pedantic group not defined");
560e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      OS << ", " << I->second.IDNo;
56151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
562d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer      OS << ", 0";
56351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
56451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
5653347b497157d36cf280d1d9f52956faa6e702f34Richard Smith    // SFINAE response.
5663347b497157d36cf280d1d9f52956faa6e702f34Richard Smith    OS << ", " << R.getValueAsDef("SFINAE")->getName();
5673347b497157d36cf280d1d9f52956faa6e702f34Richard Smith
5683347b497157d36cf280d1d9f52956faa6e702f34Richard Smith    // Default warning has no Werror bit.
5693347b497157d36cf280d1d9f52956faa6e702f34Richard Smith    if (R.getValueAsBit("WarningNoWerror"))
57051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ", true";
57151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
57251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ", false";
57351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
574ef8225444452a1486bd721f3285301fe84643b00Stephen Hines    if (R.getValueAsBit("ShowInSystemHeader"))
57551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ", true";
57651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
57751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ", false";
57851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
57951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Category number.
58051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
58151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << ")\n";
58251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
58351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
5843cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end namespace clang
58551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
58651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
58751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Warning Group Tables generation
58851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
58951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
59051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string getDiagCategoryEnum(llvm::StringRef name) {
59151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (name.empty())
59251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "DiagCat_None";
59336d592718ff342f762e32cbde73d1113f88cb275Dylan Noblesmith  SmallString<256> enumName = llvm::StringRef("DiagCat_");
59451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
59551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    enumName += isalnum(*I) ? *I : '_';
59651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return enumName.str();
59751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
598519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
5996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \brief Emit the array of diagnostic subgroups.
6006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
6016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// The array of diagnostic subgroups contains for each group a list of its
6026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// subgroups. The individual lists are separated by '-1'. Groups with no
6036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// subgroups are skipped.
6046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
6056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \code
6066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///   static const int16_t DiagSubGroups[] = {
6076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///     /* Empty */ -1,
6086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///     /* DiagSubGroup0 */ 142, -1,
6096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///     /* DiagSubGroup13 */ 265, 322, 399, -1
6106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///   }
6116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \endcode
6126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
6136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic void emitDiagSubGroups(std::map<std::string, GroupInfo> &DiagsInGroup,
6146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                              RecordVec &GroupsInPedantic, raw_ostream &OS) {
615b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper  OS << "static const int16_t DiagSubGroups[] = {\n"
616b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper     << "  /* Empty */ -1,\n";
6176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (auto const &I : DiagsInGroup) {
6186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const bool IsPedantic = I.first == "pedantic";
619519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
6206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const std::vector<std::string> &SubGroups = I.second.SubGroups;
621e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty())) {
6226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      OS << "  /* DiagSubGroup" << I.second.IDNo << " */ ";
6236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      for (auto const &SubGroup : SubGroups) {
62485c48510a6fbbdad61cae381b4d788d388d62458Craig Topper        std::map<std::string, GroupInfo>::const_iterator RI =
6256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines            DiagsInGroup.find(SubGroup);
62651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        assert(RI != DiagsInGroup.end() && "Referenced without existing?");
62751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << RI->second.IDNo << ", ";
62851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
629e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      // Emit the groups implicitly in "pedantic".
630e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      if (IsPedantic) {
6316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        for (auto const &Group : GroupsInPedantic) {
6326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          const std::string &GroupName = Group->getValueAsString("GroupName");
63385c48510a6fbbdad61cae381b4d788d388d62458Craig Topper          std::map<std::string, GroupInfo>::const_iterator RI =
6346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines              DiagsInGroup.find(GroupName);
635e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek          assert(RI != DiagsInGroup.end() && "Referenced without existing?");
636e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek          OS << RI->second.IDNo << ", ";
637e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        }
638e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      }
639e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
640b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper      OS << "-1,\n";
64151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
64251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
643354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper  OS << "};\n\n";
6446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
645354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper
6466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \brief Emit the list of diagnostic arrays.
6476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
6486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// This data structure is a large array that contains itself arrays of varying
6496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// size. Each array represents a list of diagnostics. The different arrays are
6506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// separated by the value '-1'.
6516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
6526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \code
6536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///   static const int16_t DiagArrays[] = {
6546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///     /* Empty */ -1,
6556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///     /* DiagArray1 */ diag::warn_pragma_message,
6566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///                      -1,
6576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///     /* DiagArray2 */ diag::warn_abs_too_small,
6586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///                      diag::warn_unsigned_abs,
6596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///                      diag::warn_wrong_absolute_value_type,
6606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///                      -1
6616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///   };
6626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \endcode
6636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
6646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic void emitDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
6656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                           RecordVec &DiagsInPedantic, raw_ostream &OS) {
6666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  OS << "static const int16_t DiagArrays[] = {\n"
6676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines     << "  /* Empty */ -1,\n";
6686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (auto const &I : DiagsInGroup) {
6696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const bool IsPedantic = I.first == "pedantic";
6706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
6716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const std::vector<const Record *> &V = I.second.DiagsInGroup;
6726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) {
6736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      OS << "  /* DiagArray" << I.second.IDNo << " */ ";
6746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      for (auto *Record : V)
6756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        OS << "diag::" << Record->getName() << ", ";
6766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      // Emit the diagnostics implicitly in "pedantic".
6776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      if (IsPedantic) {
6786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        for (auto const &Diag : DiagsInPedantic)
6796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines          OS << "diag::" << Diag->getName() << ", ";
6806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      }
6816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      OS << "-1,\n";
6826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    }
683354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper  }
6846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  OS << "};\n\n";
6856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
686354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper
6876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \brief Emit a list of group names.
6886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
6896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// This creates a long string which by itself contains a list of pascal style
6906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// strings, which consist of a length byte directly followed by the string.
6916bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
6926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \code
6936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///   static const char DiagGroupNames[] = {
6946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///     \000\020#pragma-messages\t#warnings\020CFString-literal"
6956bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///   };
6966bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \endcode
6976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic void emitDiagGroupNames(StringToOffsetTable &GroupNames,
6986bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                               raw_ostream &OS) {
699354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper  OS << "static const char DiagGroupNames[] = {\n";
700354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper  GroupNames.EmitString(OS);
701354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper  OS << "};\n\n";
7026bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
703354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper
7046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \brief Emit diagnostic arrays and related data structures.
7056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
7066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// This creates the actual diagnostic array, an array of diagnostic subgroups
7076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// and an array of subgroup names.
7086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
7096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \code
7106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///  #ifdef GET_DIAG_ARRAYS
7116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///     static const int16_t DiagArrays[];
7126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///     static const int16_t DiagSubGroups[];
7136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///     static const char DiagGroupNames[];
7146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///  #endif
7156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///  \endcode
7166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic void emitAllDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
7176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                              RecordVec &DiagsInPedantic,
7186bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                              RecordVec &GroupsInPedantic,
7196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                              StringToOffsetTable &GroupNames,
7206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                              raw_ostream &OS) {
7216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  OS << "\n#ifdef GET_DIAG_ARRAYS\n";
7226bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  emitDiagArrays(DiagsInGroup, DiagsInPedantic, OS);
7236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  emitDiagSubGroups(DiagsInGroup, GroupsInPedantic, OS);
7246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  emitDiagGroupNames(GroupNames, OS);
72551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif // GET_DIAG_ARRAYS\n\n";
7266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
7276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \brief Emit diagnostic table.
7296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
7306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// The table is sorted by the name of the diagnostic group. Each element
7316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// consists of the name of the diagnostic group (given as offset in the
7326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// group name table), a reference to a list of diagnostics (optional) and a
7336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// reference to a set of subgroups (optional).
7346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
7356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \code
7366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// #ifdef GET_DIAG_TABLE
7376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///  {/* abi */              159, /* DiagArray11 */ 19, /* Empty */          0},
7386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///  {/* aggregate-return */ 180, /* Empty */        0, /* Empty */          0},
7396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///  {/* all */              197, /* Empty */        0, /* DiagSubGroup13 */ 3},
7406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///  {/* deprecated */       1981,/* DiagArray1 */ 348, /* DiagSubGroup3 */  9},
7416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// #endif
7426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \endcode
7436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup,
7446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                          RecordVec &DiagsInPedantic,
7456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                          RecordVec &GroupsInPedantic,
7466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                          StringToOffsetTable &GroupNames, raw_ostream &OS) {
7476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  unsigned MaxLen = 0;
7486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
7496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (auto const &I: DiagsInGroup)
7506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    MaxLen = std::max(MaxLen, (unsigned)I.first.size());
751519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
75251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n#ifdef GET_DIAG_TABLE\n";
753b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper  unsigned SubGroupIndex = 1, DiagArrayIndex = 1;
7546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (auto const &I: DiagsInGroup) {
75551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Group option string.
756354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper    OS << "  { /* ";
7576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    if (I.first.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
758037ad1b8f00b80aa76e73e3118133e9a59fd177eBenjamin Kramer                                   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
7596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                                   "0123456789!@#$%^*-+=:?") !=
7606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        std::string::npos)
7616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      PrintFatalError("Invalid character in diagnostic group '" + I.first +
7626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                      "'");
7636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    OS << I.first << " */ " << std::string(MaxLen - I.first.size(), ' ');
764354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper    // Store a pascal-style length byte at the beginning of the string.
7656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    std::string Name = char(I.first.size()) + I.first;
766354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper    OS << GroupNames.GetOrAddStringOffset(Name, false) << ", ";
767e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
768e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // Special handling for 'pedantic'.
7696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const bool IsPedantic = I.first == "pedantic";
770e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
77151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Diagnostics in the group.
7726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const std::vector<const Record *> &V = I.second.DiagsInGroup;
7736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const bool hasDiags =
7746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        !V.empty() || (IsPedantic && !DiagsInPedantic.empty());
775b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper    if (hasDiags) {
7766bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      OS << "/* DiagArray" << I.second.IDNo << " */ " << DiagArrayIndex
7776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines         << ", ";
778b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper      if (IsPedantic)
779b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper        DiagArrayIndex += DiagsInPedantic.size();
780b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper      DiagArrayIndex += V.size() + 1;
781b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper    } else {
782354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper      OS << "/* Empty */     0, ";
783b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper    }
784519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
78551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Subgroups.
7866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const std::vector<std::string> &SubGroups = I.second.SubGroups;
7876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    const bool hasSubGroups =
7886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines        !SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty());
789b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper    if (hasSubGroups) {
7906bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      OS << "/* DiagSubGroup" << I.second.IDNo << " */ " << SubGroupIndex;
791b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper      if (IsPedantic)
792b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper        SubGroupIndex += GroupsInPedantic.size();
793b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper      SubGroupIndex += SubGroups.size() + 1;
794b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper    } else {
795354f20a8720732aa1745d1ff9595382cee324ee2Craig Topper      OS << "/* Empty */         0";
796b1aa16a18563ebb6824fbe7267420942c802a8caCraig Topper    }
7976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
79851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << " },\n";
79951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
80051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif // GET_DIAG_TABLE\n\n";
8016bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
802519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
8036bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \brief Emit the table of diagnostic categories.
8046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
8056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// The table has the form of macro calls that have two parameters. The
8066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// category's name as well as an enum that represents the category. The
8076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// table can be used by defining the macro 'CATEGORY' and including this
8086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// table right after.
8096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///
8106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \code
8116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// #ifdef GET_CATEGORY_TABLE
8126bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///   CATEGORY("Semantic Issue", DiagCat_Semantic_Issue)
8136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines///   CATEGORY("Lambda Issue", DiagCat_Lambda_Issue)
8146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// #endif
8156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines/// \endcode
8166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic void emitCategoryTable(RecordKeeper &Records, raw_ostream &OS) {
81751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  DiagCategoryIDMap CategoriesByID(Records);
81851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n#ifdef GET_CATEGORY_TABLE\n";
8196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (auto const &C : CategoriesByID)
8206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    OS << "CATEGORY(\"" << C << "\", " << getDiagCategoryEnum(C) << ")\n";
82151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif // GET_CATEGORY_TABLE\n\n";
82251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
8236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8246bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesnamespace clang {
8256bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
8266bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // Compute a mapping from a DiagGroup to all of its parents.
8276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  DiagGroupParentMap DGParentMap(Records);
8286bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8296bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  std::vector<Record *> Diags = Records.getAllDerivedDefinitions("Diagnostic");
8306bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  std::vector<Record *> DiagGroups =
8326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines      Records.getAllDerivedDefinitions("DiagGroup");
8336bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8346bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  std::map<std::string, GroupInfo> DiagsInGroup;
8356bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
8366bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8376bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // All extensions are implicitly in the "pedantic" group.  Record the
8386bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // implicit set of groups in the "pedantic" group, and use this information
8396bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  // later when emitting the group information for Pedantic.
8406bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  RecordVec DiagsInPedantic;
8416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  RecordVec GroupsInPedantic;
8426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
8436bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic);
8446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  StringToOffsetTable GroupNames;
8466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  for (std::map<std::string, GroupInfo>::const_iterator
8476bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines           I = DiagsInGroup.begin(),
8486bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines           E = DiagsInGroup.end();
8496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines       I != E; ++I) {
8506bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    // Store a pascal-style length byte at the beginning of the string.
8516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    std::string Name = char(I->first.size()) + I->first;
8526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    GroupNames.GetOrAddStringOffset(Name, false);
8536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  }
8546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines
8556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  emitAllDiagArrays(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
8566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                    OS);
8576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  emitDiagTable(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
8586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                OS);
8596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  emitCategoryTable(Records, OS);
8606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}
8613cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end namespace clang
86251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
86351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
86451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Diagnostic name index generation
86551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
86651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
86751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournenamespace {
86851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestruct RecordIndexElement
86951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne{
87051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  RecordIndexElement() {}
87151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  explicit RecordIndexElement(Record const &R):
87251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Name(R.getName()) {}
873519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
87451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Name;
87551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne};
87651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} // end anonymous namespace.
87751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
8783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang {
8793cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
88051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const std::vector<Record*> &Diags =
88151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Records.getAllDerivedDefinitions("Diagnostic");
882519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
88351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<RecordIndexElement> Index;
88451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  Index.reserve(Diags.size());
88551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
886519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper    const Record &R = *(Diags[i]);
88751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Index.push_back(RecordIndexElement(R));
88851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
889519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
890651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  std::sort(Index.begin(), Index.end(),
891651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            [](const RecordIndexElement &Lhs,
892651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines               const RecordIndexElement &Rhs) { return Lhs.Name < Rhs.Name; });
893519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
89451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = Index.size(); i != e; ++i) {
89551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    const RecordIndexElement &R = Index[i];
896519f26bd78c4743bb56e6fb74d9c5163f73d859cCraig Topper
89751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "DIAG_NAME_INDEX(" << R.Name << ")\n";
89851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
89951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
9003cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end namespace clang
901