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