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