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
14e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek#include "llvm/ADT/PointerUnion.h"
1551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/DenseSet.h"
1651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include "llvm/ADT/SmallString.h"
173cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/ADT/StringMap.h"
18e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek#include "llvm/ADT/Optional.h"
193cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/Support/Compiler.h"
203cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/Support/Debug.h"
213cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/Record.h"
223cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include "llvm/TableGen/TableGenBackend.h"
2351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include <algorithm>
247094dee95f8c915d27097ac18b47d1ef31fd72edJoerg Sonnenberger#include <cctype>
2551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne#include <functional>
263cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen#include <map>
27d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer#include <set>
2851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourneusing namespace llvm;
2951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
3051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
3151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Diagnostic category computation code.
3251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
3351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
3451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournenamespace {
3551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourneclass DiagGroupParentMap {
3651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  RecordKeeper &Records;
3751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::map<const Record*, std::vector<Record*> > Mapping;
3851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournepublic:
3951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  DiagGroupParentMap(RecordKeeper &records) : Records(records) {
4051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::vector<Record*> DiagGroups
4151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      = Records.getAllDerivedDefinitions("DiagGroup");
4251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
4351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::vector<Record*> SubGroups =
4451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        DiagGroups[i]->getValueAsListOfDefs("SubGroups");
4551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
4651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        Mapping[SubGroups[j]].push_back(DiagGroups[i]);
4751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
4851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
4951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
5051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const std::vector<Record*> &getParents(const Record *Group) {
5151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return Mapping[Group];
5251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
5351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne};
5451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} // end anonymous namespace.
5551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
5651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string
5751d7777a21b9706d503496c650af06f80d278c1aPeter CollingbournegetCategoryFromDiagGroup(const Record *Group,
5851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                         DiagGroupParentMap &DiagGroupParents) {
5951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If the DiagGroup has a category, return it.
6051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string CatName = Group->getValueAsString("CategoryName");
6151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (!CatName.empty()) return CatName;
6251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
6351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // The diag group may the subgroup of one or more other diagnostic groups,
6451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // check these for a category as well.
6551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
6651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
6751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
6851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (!CatName.empty()) return CatName;
6951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
7051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return "";
7151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
7251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
7351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// getDiagnosticCategory - Return the category that the specified diagnostic
7451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne/// lives in.
7551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string getDiagnosticCategory(const Record *R,
7651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                         DiagGroupParentMap &DiagGroupParents) {
7751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If the diagnostic is in a group, and that group has a category, use it.
7851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group"))) {
7951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Check the diagnostic's diag group for a category.
8051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::string CatName = getCategoryFromDiagGroup(Group->getDef(),
8151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                                                   DiagGroupParents);
8251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (!CatName.empty()) return CatName;
8351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
84e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
8551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // If the diagnostic itself has a category, get it.
8651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return R->getValueAsString("CategoryName");
8751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
8851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
8951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournenamespace {
9051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  class DiagCategoryIDMap {
9151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    RecordKeeper &Records;
9251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    StringMap<unsigned> CategoryIDs;
9351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::vector<std::string> CategoryStrings;
9451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  public:
9551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    DiagCategoryIDMap(RecordKeeper &records) : Records(records) {
9651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      DiagGroupParentMap ParentInfo(Records);
9751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
9851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // The zero'th category is "".
9951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      CategoryStrings.push_back("");
10051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      CategoryIDs[""] = 0;
10151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
10251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      std::vector<Record*> Diags =
10351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      Records.getAllDerivedDefinitions("Diagnostic");
10451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
10551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
10651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (Category.empty()) continue;  // Skip diags with no category.
10751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
10851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        unsigned &ID = CategoryIDs[Category];
10951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        if (ID != 0) continue;  // Already seen.
11051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
11151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        ID = CategoryStrings.size();
11251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        CategoryStrings.push_back(Category);
11351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
11451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
11551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
11651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    unsigned getID(StringRef CategoryString) {
11751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      return CategoryIDs[CategoryString];
11851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
11951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
12051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    typedef std::vector<std::string>::iterator iterator;
12151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    iterator begin() { return CategoryStrings.begin(); }
12251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    iterator end() { return CategoryStrings.end(); }
12351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  };
124d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis
125d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  struct GroupInfo {
126d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    std::vector<const Record*> DiagsInGroup;
127d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    std::vector<std::string> SubGroups;
128d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    unsigned IDNo;
129d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  };
13051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} // end anonymous namespace.
13151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
132d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis/// \brief Invert the 1-[0/1] mapping of diags to group into a one to many
133d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis/// mapping of groups to diags in the group.
134d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidisstatic void groupDiagnostics(const std::vector<Record*> &Diags,
135d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis                             const std::vector<Record*> &DiagGroups,
136d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis                             std::map<std::string, GroupInfo> &DiagsInGroup) {
137d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
138d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    const Record *R = Diags[i];
139d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group"));
140d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    if (DI == 0) continue;
14146484770fe264fba24f7a9f608a3b7c3342690aaRichard Smith    assert(R->getValueAsDef("Class")->getName() != "CLASS_NOTE" &&
14246484770fe264fba24f7a9f608a3b7c3342690aaRichard Smith           "Note can't be in a DiagGroup");
143d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    std::string GroupName = DI->getDef()->getValueAsString("GroupName");
144d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
145d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  }
146d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis
147d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
148d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  // groups (these are warnings that GCC supports that clang never produces).
149d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
150d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    Record *Group = DiagGroups[i];
151d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
152d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis
153d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
154d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
155d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis      GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
156d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  }
157d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis
158d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  // Assign unique ID numbers to the groups.
159d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  unsigned IDNo = 0;
160d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  for (std::map<std::string, GroupInfo>::iterator
161d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis       I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
162d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis    I->second.IDNo = IDNo;
163d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis}
16451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
16551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
166e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek// Infer members of -Wpedantic.
167e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek//===----------------------------------------------------------------------===//
168e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
169e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenektypedef std::vector<const Record *> RecordVec;
170e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenektypedef llvm::DenseSet<const Record *> RecordSet;
171e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenektypedef llvm::PointerUnion<RecordVec*, RecordSet*> VecOrSet;
172e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
173e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremeneknamespace {
174e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekclass InferPedantic {
175e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  typedef llvm::DenseMap<const Record*,
176e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                         std::pair<unsigned, llvm::Optional<unsigned> > > GMap;
177e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
178e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  DiagGroupParentMap &DiagGroupParents;
179e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  const std::vector<Record*> &Diags;
180e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  const std::vector<Record*> DiagGroups;
181e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  std::map<std::string, GroupInfo> &DiagsInGroup;
182e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  llvm::DenseSet<const Record*> DiagsSet;
183e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  GMap GroupCount;
184e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekpublic:
185e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  InferPedantic(DiagGroupParentMap &DiagGroupParents,
186e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                const std::vector<Record*> &Diags,
187e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                const std::vector<Record*> &DiagGroups,
188e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                std::map<std::string, GroupInfo> &DiagsInGroup)
189e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  : DiagGroupParents(DiagGroupParents),
190e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  Diags(Diags),
191e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  DiagGroups(DiagGroups),
192e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  DiagsInGroup(DiagsInGroup) {}
193e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
194e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// Compute the set of diagnostics and groups that are immediately
195e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// in -Wpedantic.
196e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  void compute(VecOrSet DiagsInPedantic,
197e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek               VecOrSet GroupsInPedantic);
198e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
199e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekprivate:
200e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// Determine whether a group is a subgroup of another group.
201e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  bool isSubGroupOfGroup(const Record *Group,
202e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                         llvm::StringRef RootGroupName);
203e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
204e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// Determine if the diagnostic is an extension.
205e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  bool isExtension(const Record *Diag);
206e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
207bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek  /// Determine if the diagnostic is off by default.
208bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek  bool isOffByDefault(const Record *Diag);
209bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek
210e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// Increment the count for a group, and transitively marked
211e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// parent groups when appropriate.
212e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  void markGroup(const Record *Group);
213e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
214e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// Return true if the diagnostic is in a pedantic group.
215e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  bool groupInPedantic(const Record *Group, bool increment = false);
216e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek};
217e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek} // end anonymous namespace
218e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
219e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekbool InferPedantic::isSubGroupOfGroup(const Record *Group,
220e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                                      llvm::StringRef GName) {
221e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
222e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  const std::string &GroupName = Group->getValueAsString("GroupName");
223e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  if (GName == GroupName)
224e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    return true;
225e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
226e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
227e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  for (unsigned i = 0, e = Parents.size(); i != e; ++i)
228e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (isSubGroupOfGroup(Parents[i], GName))
229e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      return true;
230e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
231e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  return false;
232e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek}
233e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
234e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek/// Determine if the diagnostic is an extension.
235e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekbool InferPedantic::isExtension(const Record *Diag) {
236e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  const std::string &ClsName = Diag->getValueAsDef("Class")->getName();
237e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  return ClsName == "CLASS_EXTENSION";
238e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek}
239e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
240bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenekbool InferPedantic::isOffByDefault(const Record *Diag) {
241bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek  const std::string &DefMap = Diag->getValueAsDef("DefaultMapping")->getName();
242bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek  return DefMap == "MAP_IGNORE";
243bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek}
244bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek
245e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekbool InferPedantic::groupInPedantic(const Record *Group, bool increment) {
246e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  GMap::mapped_type &V = GroupCount[Group];
247e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // Lazily compute the threshold value for the group count.
248e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  if (!V.second.hasValue()) {
249e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    const GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
250e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    V.second = GI.SubGroups.size() + GI.DiagsInGroup.size();
251e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  }
252e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
253e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  if (increment)
254e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    ++V.first;
255e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
256e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // Consider a group in -Wpendatic IFF if has at least one diagnostic
257e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // or subgroup AND all of those diagnostics and subgroups are covered
258e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // by -Wpedantic via our computation.
259e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  return V.first != 0 && V.first == V.second.getValue();
260e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek}
261e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
262e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekvoid InferPedantic::markGroup(const Record *Group) {
263e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // If all the diagnostics and subgroups have been marked as being
264e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // covered by -Wpedantic, increment the count of parent groups.  Once the
265e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // group's count is equal to the number of subgroups and diagnostics in
266e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // that group, we can safely add this group to -Wpedantic.
267e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  if (groupInPedantic(Group, /* increment */ true)) {
268e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
269e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    for (unsigned i = 0, e = Parents.size(); i != e; ++i)
270e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      markGroup(Parents[i]);
271e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  }
272e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek}
273e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
274e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenekvoid InferPedantic::compute(VecOrSet DiagsInPedantic,
275e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                            VecOrSet GroupsInPedantic) {
276bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek  // All extensions that are not on by default are implicitly in the
277bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek  // "pedantic" group.  For those that aren't explicitly included in -Wpedantic,
278bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek  // mark them for consideration to be included in -Wpedantic directly.
279e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
280e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    Record *R = Diags[i];
281bb5185c0ca3de4e7d91d011a83c902d7b02a2a1aTed Kremenek    if (isExtension(R) && isOffByDefault(R)) {
282e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      DiagsSet.insert(R);
283e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      if (DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group"))) {
284e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        const Record *GroupRec = Group->getDef();
285e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        if (!isSubGroupOfGroup(GroupRec, "pedantic")) {
286e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek          markGroup(GroupRec);
287e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        }
288e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      }
289e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    }
290e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  }
291e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
292e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // Compute the set of diagnostics that are directly in -Wpedantic.  We
293e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // march through Diags a second time to ensure the results are emitted
294e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // in deterministic order.
295e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
296e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    Record *R = Diags[i];
297e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (!DiagsSet.count(R))
298e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      continue;
299e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // Check if the group is implicitly in -Wpedantic.  If so,
300e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // the diagnostic should not be directly included in the -Wpedantic
301e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // diagnostic group.
302e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group")))
303e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      if (groupInPedantic(Group->getDef()))
304e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        continue;
305e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
306e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // The diagnostic is not included in a group that is (transitively) in
307e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // -Wpedantic.  Include it in -Wpedantic directly.
308e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (RecordVec *V = DiagsInPedantic.dyn_cast<RecordVec*>())
309e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      V->push_back(R);
310e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    else {
311e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      DiagsInPedantic.get<RecordSet*>()->insert(R);
312e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    }
313e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  }
314e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
315e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  if (!GroupsInPedantic)
316e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    return;
317e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
318e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // Compute the set of groups that are directly in -Wpedantic.  We
319e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // march through the groups to ensure the results are emitted
320e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  /// in a deterministc order.
321e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  for (unsigned i = 0, ei = DiagGroups.size(); i != ei; ++i) {
322e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    Record *Group = DiagGroups[i];
323e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (!groupInPedantic(Group))
324e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      continue;
325e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
326e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    unsigned ParentsInPedantic = 0;
327e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
328e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    for (unsigned j = 0, ej = Parents.size(); j != ej; ++j) {
329e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      if (groupInPedantic(Parents[j]))
330e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        ++ParentsInPedantic;
331e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    }
332e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // If all the parents are in -Wpedantic, this means that this diagnostic
333e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // group will be indirectly included by -Wpedantic already.  In that
334e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // case, do not add it directly to -Wpedantic.  If the group has no
335e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // parents, obviously it should go into -Wpedantic.
336e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (Parents.size() > 0 && ParentsInPedantic == Parents.size())
337e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      continue;
338e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
339e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (RecordVec *V = GroupsInPedantic.dyn_cast<RecordVec*>())
340e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      V->push_back(Group);
341e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    else {
342e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      GroupsInPedantic.get<RecordSet*>()->insert(Group);
343e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    }
344e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  }
345e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek}
346e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
347e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek//===----------------------------------------------------------------------===//
34851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Warning Tables (.inc file) generation.
34951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
35051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
3514a535368eb4fca10b05c442e04725747dbf76081Ted Kremenekstatic bool isError(const Record &Diag) {
3524a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek  const std::string &ClsName = Diag.getValueAsDef("Class")->getName();
3534a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek  return ClsName == "CLASS_ERROR";
3544a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek}
3554a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek
3563cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// ClangDiagsDefsEmitter - The top-level class emits .def files containing
3573cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen/// declarations of Clang diagnostics.
3583cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang {
3593cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
3603cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen                        const std::string &Component) {
36151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Write the #if guard
36251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (!Component.empty()) {
36390c7892b699c5405a81bcc339432ba2f4b50e0d6Benjamin Kramer    std::string ComponentName = StringRef(Component).upper();
36451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "#ifdef " << ComponentName << "START\n";
36551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
36651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne       << ",\n";
36751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "#undef " << ComponentName << "START\n";
36851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "#endif\n\n";
36951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
37051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
37151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const std::vector<Record*> &Diags =
37251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Records.getAllDerivedDefinitions("Diagnostic");
373d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer
374d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer  std::vector<Record*> DiagGroups
375d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer    = Records.getAllDerivedDefinitions("DiagGroup");
376d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis
377d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  std::map<std::string, GroupInfo> DiagsInGroup;
378d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
379d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer
38051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  DiagCategoryIDMap CategoryIDs(Records);
38151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  DiagGroupParentMap DGParentMap(Records);
38251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
383e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // Compute the set of diagnostics that are in -Wpedantic.
384e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  RecordSet DiagsInPedantic;
385e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
386e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  inferPedantic.compute(&DiagsInPedantic, (RecordVec*)0);
387e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
38851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
38951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    const Record &R = *Diags[i];
3904a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek
3914a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek    // Check if this is an error that is accidentally in a warning
3924a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek    // group.
3934a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek    if (isError(R)) {
3944a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek      if (DefInit *Group = dynamic_cast<DefInit*>(R.getValueInit("Group"))) {
3954a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek        const Record *GroupRec = Group->getDef();
3964a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek        const std::string &GroupName = GroupRec->getValueAsString("GroupName");
3974a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek        throw "Error " + R.getName() + " cannot be in a warning group [" +
3984a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek              GroupName + "]";
3994a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek      }
4004a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek    }
4014a535368eb4fca10b05c442e04725747dbf76081Ted Kremenek
40251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Filter by component.
40351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (!Component.empty() && Component != R.getValueAsString("Component"))
40451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      continue;
40551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
40651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "DIAG(" << R.getName() << ", ";
40751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << R.getValueAsDef("Class")->getName();
40851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << ", diag::" << R.getValueAsDef("DefaultMapping")->getName();
40951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
41051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Description string.
41151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << ", \"";
41251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS.write_escaped(R.getValueAsString("Text")) << '"';
41351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
414d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer    // Warning associated with the diagnostic. This is stored as an index into
415d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer    // the alphabetically sorted warning table.
41651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("Group"))) {
417d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis      std::map<std::string, GroupInfo>::iterator I =
418d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis          DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName"));
419d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis      assert(I != DiagsInGroup.end());
420d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis      OS << ", " << I->second.IDNo;
421e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    } else if (DiagsInPedantic.count(&R)) {
422e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      std::map<std::string, GroupInfo>::iterator I =
423e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        DiagsInGroup.find("pedantic");
424e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      assert(I != DiagsInGroup.end() && "pedantic group not defined");
425e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      OS << ", " << I->second.IDNo;
42651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    } else {
427d49cb20288b2dbc222aaf5673c1a4738c151b7bfBenjamin Kramer      OS << ", 0";
42851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
42951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
43051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // SFINAE bit
43151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R.getValueAsBit("SFINAE"))
43251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ", true";
43351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
43451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ", false";
43551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
43651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Access control bit
43751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R.getValueAsBit("AccessControl"))
43851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ", true";
43951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
44051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << ", false";
44151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
44251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // FIXME: This condition is just to avoid temporary revlock, it can be
44351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // removed.
44451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    if (R.getValue("WarningNoWerror")) {
44551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Default warning has no Werror bit.
44651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (R.getValueAsBit("WarningNoWerror"))
44751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << ", true";
44851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
44951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << ", false";
45051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
45151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      // Default warning show in system header bit.
45251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      if (R.getValueAsBit("WarningShowInSystemHeader"))
45351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << ", true";
45451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      else
45551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << ", false";
45651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
45751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
45851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Category number.
45951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
46051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << ")\n";
46151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
46251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
4633cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end namespace clang
46451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
46551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
46651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Warning Group Tables generation
46751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
46851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
46951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestatic std::string getDiagCategoryEnum(llvm::StringRef name) {
47051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  if (name.empty())
47151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return "DiagCat_None";
47236d592718ff342f762e32cbde73d1113f88cb275Dylan Noblesmith  SmallString<256> enumName = llvm::StringRef("DiagCat_");
47351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
47451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    enumName += isalnum(*I) ? *I : '_';
47551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  return enumName.str();
47651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
477e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
4783cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang {
4793cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
48051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Compute a mapping from a DiagGroup to all of its parents.
48151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  DiagGroupParentMap DGParentMap(Records);
482e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
48351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> Diags =
48451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Records.getAllDerivedDefinitions("Diagnostic");
48551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
48651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<Record*> DiagGroups
48751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    = Records.getAllDerivedDefinitions("DiagGroup");
488d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis
489d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  std::map<std::string, GroupInfo> DiagsInGroup;
490d42236e9d5aa8881bee103d923475daffc791f38Argyrios Kyrtzidis  groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
491e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
492e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // All extensions are implicitly in the "pedantic" group.  Record the
493e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // implicit set of groups in the "pedantic" group, and use this information
494e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  // later when emitting the group information for Pedantic.
495e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  RecordVec DiagsInPedantic;
496e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  RecordVec GroupsInPedantic;
497e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
498e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek  inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic);
499e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
50051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Walk through the groups emitting an array for each diagnostic of the diags
50151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // that are mapped to.
50251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n#ifdef GET_DIAG_ARRAYS\n";
50351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  unsigned MaxLen = 0;
50451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (std::map<std::string, GroupInfo>::iterator
50551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne       I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
50651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    MaxLen = std::max(MaxLen, (unsigned)I->first.size());
507e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    const bool IsPedantic = I->first == "pedantic";
508e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
50951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    std::vector<const Record*> &V = I->second.DiagsInGroup;
510e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) {
51151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "static const short DiagArray" << I->second.IDNo << "[] = { ";
51251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned i = 0, e = V.size(); i != e; ++i)
51351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << "diag::" << V[i]->getName() << ", ";
514e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      // Emit the diagnostics implicitly in "pedantic".
515e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      if (IsPedantic) {
516e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        for (unsigned i = 0, e = DiagsInPedantic.size(); i != e; ++i)
517e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek          OS << "diag::" << DiagsInPedantic[i]->getName() << ", ";
518e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      }
51951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "-1 };\n";
52051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
52151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
52251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    const std::vector<std::string> &SubGroups = I->second.SubGroups;
523e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty())) {
52451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "static const short DiagSubGroup" << I->second.IDNo << "[] = { ";
52551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      for (unsigned i = 0, e = SubGroups.size(); i != e; ++i) {
52651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        std::map<std::string, GroupInfo>::iterator RI =
52751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne          DiagsInGroup.find(SubGroups[i]);
52851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        assert(RI != DiagsInGroup.end() && "Referenced without existing?");
52951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne        OS << RI->second.IDNo << ", ";
53051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      }
531e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      // Emit the groups implicitly in "pedantic".
532e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      if (IsPedantic) {
533e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        for (unsigned i = 0, e = GroupsInPedantic.size(); i != e; ++i) {
534e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek          const std::string &GroupName =
535e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek            GroupsInPedantic[i]->getValueAsString("GroupName");
536e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek          std::map<std::string, GroupInfo>::iterator RI =
537e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek            DiagsInGroup.find(GroupName);
538e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek          assert(RI != DiagsInGroup.end() && "Referenced without existing?");
539e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek          OS << RI->second.IDNo << ", ";
540e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek        }
541e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek      }
542e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
54351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "-1 };\n";
54451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    }
54551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
54651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif // GET_DIAG_ARRAYS\n\n";
54751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
54851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the table now.
54951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n#ifdef GET_DIAG_TABLE\n";
55051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (std::map<std::string, GroupInfo>::iterator
55151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne       I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) {
55251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Group option string.
55351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "  { ";
55451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << I->first.size() << ", ";
55551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "\"";
556037ad1b8f00b80aa76e73e3118133e9a59fd177eBenjamin Kramer    if (I->first.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
557037ad1b8f00b80aa76e73e3118133e9a59fd177eBenjamin Kramer                                   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
558037ad1b8f00b80aa76e73e3118133e9a59fd177eBenjamin Kramer                                   "0123456789!@#$%^*-+=:?")!=std::string::npos)
559037ad1b8f00b80aa76e73e3118133e9a59fd177eBenjamin Kramer      throw "Invalid character in diagnostic group '" + I->first + "'";
56051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS.write_escaped(I->first) << "\","
56151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                               << std::string(MaxLen-I->first.size()+1, ' ');
562e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
563e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    // Special handling for 'pedantic'.
564e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    const bool IsPedantic = I->first == "pedantic";
565e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek
56651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Diagnostics in the group.
567e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    const bool hasDiags = !I->second.DiagsInGroup.empty() ||
568e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                          (IsPedantic && !DiagsInPedantic.empty());
569e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (!hasDiags)
57051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "0, ";
57151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
57251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "DiagArray" << I->second.IDNo << ", ";
57351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
57451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    // Subgroups.
575e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    const bool hasSubGroups = !I->second.SubGroups.empty() ||
576e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek                              (IsPedantic && !GroupsInPedantic.empty());
577e8cf7d143446c45568bb7c9a6fbd8f32ca6ae93eTed Kremenek    if (!hasSubGroups)
57851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << 0;
57951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    else
58051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne      OS << "DiagSubGroup" << I->second.IDNo;
58151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << " },\n";
58251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
58351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif // GET_DIAG_TABLE\n\n";
58451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
58551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  // Emit the category table next.
58651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  DiagCategoryIDMap CategoriesByID(Records);
58751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "\n#ifdef GET_CATEGORY_TABLE\n";
58851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(),
58951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne       E = CategoriesByID.end(); I != E; ++I)
59051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "CATEGORY(\"" << *I << "\", " << getDiagCategoryEnum(*I) << ")\n";
59151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  OS << "#endif // GET_CATEGORY_TABLE\n\n";
59251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
5933cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end namespace clang
59451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
59551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
59651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne// Diagnostic name index generation
59751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne//===----------------------------------------------------------------------===//
59851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
59951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournenamespace {
60051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestruct RecordIndexElement
60151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne{
60251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  RecordIndexElement() {}
60351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  explicit RecordIndexElement(Record const &R):
60451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Name(R.getName()) {}
60551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
60651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::string Name;
60751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne};
60851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
60951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbournestruct RecordIndexElementSorter :
61051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  public std::binary_function<RecordIndexElement, RecordIndexElement, bool> {
61151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
61251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  bool operator()(RecordIndexElement const &Lhs,
61351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne                  RecordIndexElement const &Rhs) const {
61451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    return Lhs.Name < Rhs.Name;
61551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
61651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
61751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne};
61851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
61951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne} // end anonymous namespace.
62051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
6213cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesennamespace clang {
6223cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesenvoid EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
62351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  const std::vector<Record*> &Diags =
62451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Records.getAllDerivedDefinitions("Diagnostic");
62551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
62651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::vector<RecordIndexElement> Index;
62751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  Index.reserve(Diags.size());
62851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
62951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    const Record &R = *(Diags[i]);
63051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    Index.push_back(RecordIndexElement(R));
63151d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
63251d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
63351d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  std::sort(Index.begin(), Index.end(), RecordIndexElementSorter());
63451d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
63551d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  for (unsigned i = 0, e = Index.size(); i != e; ++i) {
63651d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    const RecordIndexElement &R = Index[i];
63751d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne
63851d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne    OS << "DIAG_NAME_INDEX(" << R.Name << ")\n";
63951d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne  }
64051d7777a21b9706d503496c650af06f80d278c1aPeter Collingbourne}
6413cc509b5ac0e99ef44c1bf8b57cd403b546abc3dJakob Stoklund Olesen} // end namespace clang
642