ClangDiagnosticsEmitter.cpp 59 KB

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