1 //===--- DiagnosticIDs.cpp - Diagnostic IDs Handling ----------------------===// 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 // This file implements the Diagnostic IDs-related interfaces. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/Basic/DiagnosticIDs.h" 14 #include "clang/Basic/AllDiagnostics.h" 15 #include "clang/Basic/DiagnosticCategories.h" 16 #include "clang/Basic/SourceManager.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/Support/ErrorHandling.h" 20 #include <map> 21 #include <optional> 22 using namespace clang; 23 24 //===----------------------------------------------------------------------===// 25 // Builtin Diagnostic information 26 //===----------------------------------------------------------------------===// 27 28 namespace { 29 30 struct StaticDiagInfoRec; 31 32 // Store the descriptions in a separate table to avoid pointers that need to 33 // be relocated, and also decrease the amount of data needed on 64-bit 34 // platforms. See "How To Write Shared Libraries" by Ulrich Drepper. 35 struct StaticDiagInfoDescriptionStringTable { 36 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ 37 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \ 38 char ENUM##_desc[sizeof(DESC)]; 39 // clang-format off 40 #include "clang/Basic/DiagnosticCommonKinds.inc" 41 #include "clang/Basic/DiagnosticDriverKinds.inc" 42 #include "clang/Basic/DiagnosticFrontendKinds.inc" 43 #include "clang/Basic/DiagnosticSerializationKinds.inc" 44 #include "clang/Basic/DiagnosticLexKinds.inc" 45 #include "clang/Basic/DiagnosticParseKinds.inc" 46 #include "clang/Basic/DiagnosticASTKinds.inc" 47 #include "clang/Basic/DiagnosticCommentKinds.inc" 48 #include "clang/Basic/DiagnosticCrossTUKinds.inc" 49 #include "clang/Basic/DiagnosticSemaKinds.inc" 50 #include "clang/Basic/DiagnosticAnalysisKinds.inc" 51 #include "clang/Basic/DiagnosticRefactoringKinds.inc" 52 // clang-format on 53 #undef DIAG 54 }; 55 56 const StaticDiagInfoDescriptionStringTable StaticDiagInfoDescriptions = { 57 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ 58 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \ 59 DESC, 60 // clang-format off 61 #include "clang/Basic/DiagnosticCommonKinds.inc" 62 #include "clang/Basic/DiagnosticDriverKinds.inc" 63 #include "clang/Basic/DiagnosticFrontendKinds.inc" 64 #include "clang/Basic/DiagnosticSerializationKinds.inc" 65 #include "clang/Basic/DiagnosticLexKinds.inc" 66 #include "clang/Basic/DiagnosticParseKinds.inc" 67 #include "clang/Basic/DiagnosticASTKinds.inc" 68 #include "clang/Basic/DiagnosticCommentKinds.inc" 69 #include "clang/Basic/DiagnosticCrossTUKinds.inc" 70 #include "clang/Basic/DiagnosticSemaKinds.inc" 71 #include "clang/Basic/DiagnosticAnalysisKinds.inc" 72 #include "clang/Basic/DiagnosticRefactoringKinds.inc" 73 // clang-format on 74 #undef DIAG 75 }; 76 77 extern const StaticDiagInfoRec StaticDiagInfo[]; 78 79 // Stored separately from StaticDiagInfoRec to pack better. Otherwise, 80 // StaticDiagInfoRec would have extra padding on 64-bit platforms. 81 const uint32_t StaticDiagInfoDescriptionOffsets[] = { 82 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ 83 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \ 84 offsetof(StaticDiagInfoDescriptionStringTable, ENUM##_desc), 85 // clang-format off 86 #include "clang/Basic/DiagnosticCommonKinds.inc" 87 #include "clang/Basic/DiagnosticDriverKinds.inc" 88 #include "clang/Basic/DiagnosticFrontendKinds.inc" 89 #include "clang/Basic/DiagnosticSerializationKinds.inc" 90 #include "clang/Basic/DiagnosticLexKinds.inc" 91 #include "clang/Basic/DiagnosticParseKinds.inc" 92 #include "clang/Basic/DiagnosticASTKinds.inc" 93 #include "clang/Basic/DiagnosticCommentKinds.inc" 94 #include "clang/Basic/DiagnosticCrossTUKinds.inc" 95 #include "clang/Basic/DiagnosticSemaKinds.inc" 96 #include "clang/Basic/DiagnosticAnalysisKinds.inc" 97 #include "clang/Basic/DiagnosticRefactoringKinds.inc" 98 // clang-format on 99 #undef DIAG 100 }; 101 102 // Diagnostic classes. 103 enum { 104 CLASS_NOTE = 0x01, 105 CLASS_REMARK = 0x02, 106 CLASS_WARNING = 0x03, 107 CLASS_EXTENSION = 0x04, 108 CLASS_ERROR = 0x05 109 }; 110 111 struct StaticDiagInfoRec { 112 uint16_t DiagID; 113 uint8_t DefaultSeverity : 3; 114 uint8_t Class : 3; 115 uint8_t SFINAE : 2; 116 uint8_t Category : 6; 117 uint8_t WarnNoWerror : 1; 118 uint8_t WarnShowInSystemHeader : 1; 119 uint8_t WarnShowInSystemMacro : 1; 120 121 uint16_t OptionGroupIndex : 15; 122 uint16_t Deferrable : 1; 123 124 uint16_t DescriptionLen; 125 126 unsigned getOptionGroupIndex() const { 127 return OptionGroupIndex; 128 } 129 130 StringRef getDescription() const { 131 size_t MyIndex = this - &StaticDiagInfo[0]; 132 uint32_t StringOffset = StaticDiagInfoDescriptionOffsets[MyIndex]; 133 const char* Table = reinterpret_cast<const char*>(&StaticDiagInfoDescriptions); 134 return StringRef(&Table[StringOffset], DescriptionLen); 135 } 136 137 diag::Flavor getFlavor() const { 138 return Class == CLASS_REMARK ? diag::Flavor::Remark 139 : diag::Flavor::WarningOrError; 140 } 141 142 bool operator<(const StaticDiagInfoRec &RHS) const { 143 return DiagID < RHS.DiagID; 144 } 145 }; 146 147 #define STRINGIFY_NAME(NAME) #NAME 148 #define VALIDATE_DIAG_SIZE(NAME) \ 149 static_assert( \ 150 static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \ 151 static_cast<unsigned>(diag::DIAG_START_##NAME) + \ 152 static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \ 153 STRINGIFY_NAME( \ 154 DIAG_SIZE_##NAME) " is insufficient to contain all " \ 155 "diagnostics, it may need to be made larger in " \ 156 "DiagnosticIDs.h."); 157 VALIDATE_DIAG_SIZE(COMMON) 158 VALIDATE_DIAG_SIZE(DRIVER) 159 VALIDATE_DIAG_SIZE(FRONTEND) 160 VALIDATE_DIAG_SIZE(SERIALIZATION) 161 VALIDATE_DIAG_SIZE(LEX) 162 VALIDATE_DIAG_SIZE(PARSE) 163 VALIDATE_DIAG_SIZE(AST) 164 VALIDATE_DIAG_SIZE(COMMENT) 165 VALIDATE_DIAG_SIZE(CROSSTU) 166 VALIDATE_DIAG_SIZE(SEMA) 167 VALIDATE_DIAG_SIZE(ANALYSIS) 168 VALIDATE_DIAG_SIZE(REFACTORING) 169 #undef VALIDATE_DIAG_SIZE 170 #undef STRINGIFY_NAME 171 172 const StaticDiagInfoRec StaticDiagInfo[] = { 173 // clang-format off 174 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \ 175 SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \ 176 { \ 177 diag::ENUM, \ 178 DEFAULT_SEVERITY, \ 179 CLASS, \ 180 DiagnosticIDs::SFINAE, \ 181 CATEGORY, \ 182 NOWERROR, \ 183 SHOWINSYSHEADER, \ 184 SHOWINSYSMACRO, \ 185 GROUP, \ 186 DEFERRABLE, \ 187 STR_SIZE(DESC, uint16_t)}, 188 #include "clang/Basic/DiagnosticCommonKinds.inc" 189 #include "clang/Basic/DiagnosticDriverKinds.inc" 190 #include "clang/Basic/DiagnosticFrontendKinds.inc" 191 #include "clang/Basic/DiagnosticSerializationKinds.inc" 192 #include "clang/Basic/DiagnosticLexKinds.inc" 193 #include "clang/Basic/DiagnosticParseKinds.inc" 194 #include "clang/Basic/DiagnosticASTKinds.inc" 195 #include "clang/Basic/DiagnosticCommentKinds.inc" 196 #include "clang/Basic/DiagnosticCrossTUKinds.inc" 197 #include "clang/Basic/DiagnosticSemaKinds.inc" 198 #include "clang/Basic/DiagnosticAnalysisKinds.inc" 199 #include "clang/Basic/DiagnosticRefactoringKinds.inc" 200 // clang-format on 201 #undef DIAG 202 }; 203 204 } // namespace 205 206 static const unsigned StaticDiagInfoSize = std::size(StaticDiagInfo); 207 208 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, 209 /// or null if the ID is invalid. 210 static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { 211 // Out of bounds diag. Can't be in the table. 212 using namespace diag; 213 if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON) 214 return nullptr; 215 216 // Compute the index of the requested diagnostic in the static table. 217 // 1. Add the number of diagnostics in each category preceding the 218 // diagnostic and of the category the diagnostic is in. This gives us 219 // the offset of the category in the table. 220 // 2. Subtract the number of IDs in each category from our ID. This gives us 221 // the offset of the diagnostic in the category. 222 // This is cheaper than a binary search on the table as it doesn't touch 223 // memory at all. 224 unsigned Offset = 0; 225 unsigned ID = DiagID - DIAG_START_COMMON - 1; 226 #define CATEGORY(NAME, PREV) \ 227 if (DiagID > DIAG_START_##NAME) { \ 228 Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \ 229 ID -= DIAG_START_##NAME - DIAG_START_##PREV; \ 230 } 231 CATEGORY(DRIVER, COMMON) 232 CATEGORY(FRONTEND, DRIVER) 233 CATEGORY(SERIALIZATION, FRONTEND) 234 CATEGORY(LEX, SERIALIZATION) 235 CATEGORY(PARSE, LEX) 236 CATEGORY(AST, PARSE) 237 CATEGORY(COMMENT, AST) 238 CATEGORY(CROSSTU, COMMENT) 239 CATEGORY(SEMA, CROSSTU) 240 CATEGORY(ANALYSIS, SEMA) 241 CATEGORY(REFACTORING, ANALYSIS) 242 #undef CATEGORY 243 244 // Avoid out of bounds reads. 245 if (ID + Offset >= StaticDiagInfoSize) 246 return nullptr; 247 248 assert(ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize); 249 250 const StaticDiagInfoRec *Found = &StaticDiagInfo[ID + Offset]; 251 // If the diag id doesn't match we found a different diag, abort. This can 252 // happen when this function is called with an ID that points into a hole in 253 // the diagID space. 254 if (Found->DiagID != DiagID) 255 return nullptr; 256 return Found; 257 } 258 259 static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID) { 260 DiagnosticMapping Info = DiagnosticMapping::Make( 261 diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false); 262 263 if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) { 264 Info.setSeverity((diag::Severity)StaticInfo->DefaultSeverity); 265 266 if (StaticInfo->WarnNoWerror) { 267 assert(Info.getSeverity() == diag::Severity::Warning && 268 "Unexpected mapping with no-Werror bit!"); 269 Info.setNoWarningAsError(true); 270 } 271 } 272 273 return Info; 274 } 275 276 /// getCategoryNumberForDiag - Return the category number that a specified 277 /// DiagID belongs to, or 0 if no category. 278 unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) { 279 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 280 return Info->Category; 281 return 0; 282 } 283 284 namespace { 285 // The diagnostic category names. 286 struct StaticDiagCategoryRec { 287 const char *NameStr; 288 uint8_t NameLen; 289 290 StringRef getName() const { 291 return StringRef(NameStr, NameLen); 292 } 293 }; 294 } 295 296 // Unfortunately, the split between DiagnosticIDs and Diagnostic is not 297 // particularly clean, but for now we just implement this method here so we can 298 // access GetDefaultDiagMapping. 299 DiagnosticMapping & 300 DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) { 301 std::pair<iterator, bool> Result = 302 DiagMap.insert(std::make_pair(Diag, DiagnosticMapping())); 303 304 // Initialize the entry if we added it. 305 if (Result.second) 306 Result.first->second = GetDefaultDiagMapping(Diag); 307 308 return Result.first->second; 309 } 310 311 static const StaticDiagCategoryRec CategoryNameTable[] = { 312 #define GET_CATEGORY_TABLE 313 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) }, 314 #include "clang/Basic/DiagnosticGroups.inc" 315 #undef GET_CATEGORY_TABLE 316 { nullptr, 0 } 317 }; 318 319 /// getNumberOfCategories - Return the number of categories 320 unsigned DiagnosticIDs::getNumberOfCategories() { 321 return std::size(CategoryNameTable) - 1; 322 } 323 324 /// getCategoryNameFromID - Given a category ID, return the name of the 325 /// category, an empty string if CategoryID is zero, or null if CategoryID is 326 /// invalid. 327 StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) { 328 if (CategoryID >= getNumberOfCategories()) 329 return StringRef(); 330 return CategoryNameTable[CategoryID].getName(); 331 } 332 333 334 335 DiagnosticIDs::SFINAEResponse 336 DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) { 337 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 338 return static_cast<DiagnosticIDs::SFINAEResponse>(Info->SFINAE); 339 return SFINAE_Report; 340 } 341 342 bool DiagnosticIDs::isDeferrable(unsigned DiagID) { 343 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 344 return Info->Deferrable; 345 return false; 346 } 347 348 /// getBuiltinDiagClass - Return the class field of the diagnostic. 349 /// 350 static unsigned getBuiltinDiagClass(unsigned DiagID) { 351 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 352 return Info->Class; 353 return ~0U; 354 } 355 356 //===----------------------------------------------------------------------===// 357 // Custom Diagnostic information 358 //===----------------------------------------------------------------------===// 359 360 namespace clang { 361 namespace diag { 362 class CustomDiagInfo { 363 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc; 364 std::vector<DiagDesc> DiagInfo; 365 std::map<DiagDesc, unsigned> DiagIDs; 366 public: 367 368 /// getDescription - Return the description of the specified custom 369 /// diagnostic. 370 StringRef getDescription(unsigned DiagID) const { 371 assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() && 372 "Invalid diagnostic ID"); 373 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second; 374 } 375 376 /// getLevel - Return the level of the specified custom diagnostic. 377 DiagnosticIDs::Level getLevel(unsigned DiagID) const { 378 assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() && 379 "Invalid diagnostic ID"); 380 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first; 381 } 382 383 unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message, 384 DiagnosticIDs &Diags) { 385 DiagDesc D(L, std::string(Message)); 386 // Check to see if it already exists. 387 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D); 388 if (I != DiagIDs.end() && I->first == D) 389 return I->second; 390 391 // If not, assign a new ID. 392 unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT; 393 DiagIDs.insert(std::make_pair(D, ID)); 394 DiagInfo.push_back(D); 395 return ID; 396 } 397 }; 398 399 } // end diag namespace 400 } // end clang namespace 401 402 403 //===----------------------------------------------------------------------===// 404 // Common Diagnostic implementation 405 //===----------------------------------------------------------------------===// 406 407 DiagnosticIDs::DiagnosticIDs() {} 408 409 DiagnosticIDs::~DiagnosticIDs() {} 410 411 /// getCustomDiagID - Return an ID for a diagnostic with the specified message 412 /// and level. If this is the first request for this diagnostic, it is 413 /// registered and created, otherwise the existing ID is returned. 414 /// 415 /// \param FormatString A fixed diagnostic format string that will be hashed and 416 /// mapped to a unique DiagID. 417 unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) { 418 if (!CustomDiagInfo) 419 CustomDiagInfo.reset(new diag::CustomDiagInfo()); 420 return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this); 421 } 422 423 424 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic 425 /// level of the specified diagnostic ID is a Warning or Extension. 426 /// This only works on builtin diagnostics, not custom ones, and is not legal to 427 /// call on NOTEs. 428 bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) { 429 return DiagID < diag::DIAG_UPPER_LIMIT && 430 getBuiltinDiagClass(DiagID) != CLASS_ERROR; 431 } 432 433 /// Determine whether the given built-in diagnostic ID is a 434 /// Note. 435 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) { 436 return DiagID < diag::DIAG_UPPER_LIMIT && 437 getBuiltinDiagClass(DiagID) == CLASS_NOTE; 438 } 439 440 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic 441 /// ID is for an extension of some sort. This also returns EnabledByDefault, 442 /// which is set to indicate whether the diagnostic is ignored by default (in 443 /// which case -pedantic enables it) or treated as a warning/error by default. 444 /// 445 bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID, 446 bool &EnabledByDefault) { 447 if (DiagID >= diag::DIAG_UPPER_LIMIT || 448 getBuiltinDiagClass(DiagID) != CLASS_EXTENSION) 449 return false; 450 451 EnabledByDefault = 452 GetDefaultDiagMapping(DiagID).getSeverity() != diag::Severity::Ignored; 453 return true; 454 } 455 456 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) { 457 if (DiagID >= diag::DIAG_UPPER_LIMIT) 458 return false; 459 460 return GetDefaultDiagMapping(DiagID).getSeverity() >= diag::Severity::Error; 461 } 462 463 /// getDescription - Given a diagnostic ID, return a description of the 464 /// issue. 465 StringRef DiagnosticIDs::getDescription(unsigned DiagID) const { 466 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 467 return Info->getDescription(); 468 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 469 return CustomDiagInfo->getDescription(DiagID); 470 } 471 472 static DiagnosticIDs::Level toLevel(diag::Severity SV) { 473 switch (SV) { 474 case diag::Severity::Ignored: 475 return DiagnosticIDs::Ignored; 476 case diag::Severity::Remark: 477 return DiagnosticIDs::Remark; 478 case diag::Severity::Warning: 479 return DiagnosticIDs::Warning; 480 case diag::Severity::Error: 481 return DiagnosticIDs::Error; 482 case diag::Severity::Fatal: 483 return DiagnosticIDs::Fatal; 484 } 485 llvm_unreachable("unexpected severity"); 486 } 487 488 /// getDiagnosticLevel - Based on the way the client configured the 489 /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level, 490 /// by consumable the DiagnosticClient. 491 DiagnosticIDs::Level 492 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, 493 const DiagnosticsEngine &Diag) const { 494 // Handle custom diagnostics, which cannot be mapped. 495 if (DiagID >= diag::DIAG_UPPER_LIMIT) { 496 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 497 return CustomDiagInfo->getLevel(DiagID); 498 } 499 500 unsigned DiagClass = getBuiltinDiagClass(DiagID); 501 if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note; 502 return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag)); 503 } 504 505 /// Based on the way the client configured the Diagnostic 506 /// object, classify the specified diagnostic ID into a Level, consumable by 507 /// the DiagnosticClient. 508 /// 509 /// \param Loc The source location we are interested in finding out the 510 /// diagnostic state. Can be null in order to query the latest state. 511 diag::Severity 512 DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, 513 const DiagnosticsEngine &Diag) const { 514 assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE); 515 516 // Specific non-error diagnostics may be mapped to various levels from ignored 517 // to error. Errors can only be mapped to fatal. 518 diag::Severity Result = diag::Severity::Fatal; 519 520 // Get the mapping information, or compute it lazily. 521 DiagnosticsEngine::DiagState *State = Diag.GetDiagStateForLoc(Loc); 522 DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID); 523 524 // TODO: Can a null severity really get here? 525 if (Mapping.getSeverity() != diag::Severity()) 526 Result = Mapping.getSeverity(); 527 528 // Upgrade ignored diagnostics if -Weverything is enabled. 529 if (State->EnableAllWarnings && Result == diag::Severity::Ignored && 530 !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK) 531 Result = diag::Severity::Warning; 532 533 // Ignore -pedantic diagnostics inside __extension__ blocks. 534 // (The diagnostics controlled by -pedantic are the extension diagnostics 535 // that are not enabled by default.) 536 bool EnabledByDefault = false; 537 bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault); 538 if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault) 539 return diag::Severity::Ignored; 540 541 // For extension diagnostics that haven't been explicitly mapped, check if we 542 // should upgrade the diagnostic. 543 if (IsExtensionDiag && !Mapping.isUser()) 544 Result = std::max(Result, State->ExtBehavior); 545 546 // At this point, ignored errors can no longer be upgraded. 547 if (Result == diag::Severity::Ignored) 548 return Result; 549 550 // Honor -w: this disables all messages which are not Error/Fatal by 551 // default (disregarding attempts to upgrade severity from Warning to Error), 552 // as well as disabling all messages which are currently mapped to Warning 553 // (whether by default or downgraded from Error via e.g. -Wno-error or #pragma 554 // diagnostic.) 555 if (State->IgnoreAllWarnings) { 556 if (Result == diag::Severity::Warning || 557 (Result >= diag::Severity::Error && 558 !isDefaultMappingAsError((diag::kind)DiagID))) 559 return diag::Severity::Ignored; 560 } 561 562 // If -Werror is enabled, map warnings to errors unless explicitly disabled. 563 if (Result == diag::Severity::Warning) { 564 if (State->WarningsAsErrors && !Mapping.hasNoWarningAsError()) 565 Result = diag::Severity::Error; 566 } 567 568 // If -Wfatal-errors is enabled, map errors to fatal unless explicitly 569 // disabled. 570 if (Result == diag::Severity::Error) { 571 if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal()) 572 Result = diag::Severity::Fatal; 573 } 574 575 // If explicitly requested, map fatal errors to errors. 576 if (Result == diag::Severity::Fatal && 577 Diag.CurDiagID != diag::fatal_too_many_errors && Diag.FatalsAsError) 578 Result = diag::Severity::Error; 579 580 // Custom diagnostics always are emitted in system headers. 581 bool ShowInSystemHeader = 582 !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader; 583 584 // If we are in a system header, we ignore it. We look at the diagnostic class 585 // because we also want to ignore extensions and warnings in -Werror and 586 // -pedantic-errors modes, which *map* warnings/extensions to errors. 587 if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() && 588 Diag.getSourceManager().isInSystemHeader( 589 Diag.getSourceManager().getExpansionLoc(Loc))) 590 return diag::Severity::Ignored; 591 592 // We also ignore warnings due to system macros 593 bool ShowInSystemMacro = 594 !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemMacro; 595 if (State->SuppressSystemWarnings && !ShowInSystemMacro && Loc.isValid() && 596 Diag.getSourceManager().isInSystemMacro(Loc)) 597 return diag::Severity::Ignored; 598 599 return Result; 600 } 601 602 #define GET_DIAG_ARRAYS 603 #include "clang/Basic/DiagnosticGroups.inc" 604 #undef GET_DIAG_ARRAYS 605 606 namespace { 607 struct WarningOption { 608 uint16_t NameOffset; 609 uint16_t Members; 610 uint16_t SubGroups; 611 StringRef Documentation; 612 613 // String is stored with a pascal-style length byte. 614 StringRef getName() const { 615 return StringRef(DiagGroupNames + NameOffset + 1, 616 DiagGroupNames[NameOffset]); 617 } 618 }; 619 } 620 621 // Second the table of options, sorted by name for fast binary lookup. 622 static const WarningOption OptionTable[] = { 623 #define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \ 624 {FlagNameOffset, Members, SubGroups, Docs}, 625 #include "clang/Basic/DiagnosticGroups.inc" 626 #undef DIAG_ENTRY 627 }; 628 629 /// Given a diagnostic group ID, return its documentation. 630 StringRef DiagnosticIDs::getWarningOptionDocumentation(diag::Group Group) { 631 return OptionTable[static_cast<int>(Group)].Documentation; 632 } 633 634 StringRef DiagnosticIDs::getWarningOptionForGroup(diag::Group Group) { 635 return OptionTable[static_cast<int>(Group)].getName(); 636 } 637 638 std::optional<diag::Group> 639 DiagnosticIDs::getGroupForWarningOption(StringRef Name) { 640 const auto *Found = llvm::partition_point( 641 OptionTable, [=](const WarningOption &O) { return O.getName() < Name; }); 642 if (Found == std::end(OptionTable) || Found->getName() != Name) 643 return std::nullopt; 644 return static_cast<diag::Group>(Found - OptionTable); 645 } 646 647 std::optional<diag::Group> DiagnosticIDs::getGroupForDiag(unsigned DiagID) { 648 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 649 return static_cast<diag::Group>(Info->getOptionGroupIndex()); 650 return std::nullopt; 651 } 652 653 /// getWarningOptionForDiag - Return the lowest-level warning option that 654 /// enables the specified diagnostic. If there is no -Wfoo flag that controls 655 /// the diagnostic, this returns null. 656 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { 657 if (auto G = getGroupForDiag(DiagID)) 658 return getWarningOptionForGroup(*G); 659 return StringRef(); 660 } 661 662 std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() { 663 std::vector<std::string> Res{"-W", "-Wno-"}; 664 for (size_t I = 1; DiagGroupNames[I] != '\0';) { 665 std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]); 666 I += DiagGroupNames[I] + 1; 667 Res.push_back("-W" + Diag); 668 Res.push_back("-Wno-" + Diag); 669 } 670 671 return Res; 672 } 673 674 /// Return \c true if any diagnostics were found in this group, even if they 675 /// were filtered out due to having the wrong flavor. 676 static bool getDiagnosticsInGroup(diag::Flavor Flavor, 677 const WarningOption *Group, 678 SmallVectorImpl<diag::kind> &Diags) { 679 // An empty group is considered to be a warning group: we have empty groups 680 // for GCC compatibility, and GCC does not have remarks. 681 if (!Group->Members && !Group->SubGroups) 682 return Flavor == diag::Flavor::Remark; 683 684 bool NotFound = true; 685 686 // Add the members of the option diagnostic set. 687 const int16_t *Member = DiagArrays + Group->Members; 688 for (; *Member != -1; ++Member) { 689 if (GetDiagInfo(*Member)->getFlavor() == Flavor) { 690 NotFound = false; 691 Diags.push_back(*Member); 692 } 693 } 694 695 // Add the members of the subgroups. 696 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups; 697 for (; *SubGroups != (int16_t)-1; ++SubGroups) 698 NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups], 699 Diags); 700 701 return NotFound; 702 } 703 704 bool 705 DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group, 706 SmallVectorImpl<diag::kind> &Diags) const { 707 if (std::optional<diag::Group> G = getGroupForWarningOption(Group)) 708 return ::getDiagnosticsInGroup( 709 Flavor, &OptionTable[static_cast<unsigned>(*G)], Diags); 710 return true; 711 } 712 713 void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor, 714 std::vector<diag::kind> &Diags) { 715 for (unsigned i = 0; i != StaticDiagInfoSize; ++i) 716 if (StaticDiagInfo[i].getFlavor() == Flavor) 717 Diags.push_back(StaticDiagInfo[i].DiagID); 718 } 719 720 StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor, 721 StringRef Group) { 722 StringRef Best; 723 unsigned BestDistance = Group.size() + 1; // Maximum threshold. 724 for (const WarningOption &O : OptionTable) { 725 // Don't suggest ignored warning flags. 726 if (!O.Members && !O.SubGroups) 727 continue; 728 729 unsigned Distance = O.getName().edit_distance(Group, true, BestDistance); 730 if (Distance > BestDistance) 731 continue; 732 733 // Don't suggest groups that are not of this kind. 734 llvm::SmallVector<diag::kind, 8> Diags; 735 if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty()) 736 continue; 737 738 if (Distance == BestDistance) { 739 // Two matches with the same distance, don't prefer one over the other. 740 Best = ""; 741 } else if (Distance < BestDistance) { 742 // This is a better match. 743 Best = O.getName(); 744 BestDistance = Distance; 745 } 746 } 747 748 return Best; 749 } 750 751 /// ProcessDiag - This is the method used to report a diagnostic that is 752 /// finally fully formed. 753 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { 754 Diagnostic Info(&Diag); 755 756 assert(Diag.getClient() && "DiagnosticClient not set!"); 757 758 // Figure out the diagnostic level of this message. 759 unsigned DiagID = Info.getID(); 760 DiagnosticIDs::Level DiagLevel 761 = getDiagnosticLevel(DiagID, Info.getLocation(), Diag); 762 763 // Update counts for DiagnosticErrorTrap even if a fatal error occurred 764 // or diagnostics are suppressed. 765 if (DiagLevel >= DiagnosticIDs::Error) { 766 ++Diag.TrapNumErrorsOccurred; 767 if (isUnrecoverable(DiagID)) 768 ++Diag.TrapNumUnrecoverableErrorsOccurred; 769 } 770 771 if (Diag.SuppressAllDiagnostics) 772 return false; 773 774 if (DiagLevel != DiagnosticIDs::Note) { 775 // Record that a fatal error occurred only when we see a second 776 // non-note diagnostic. This allows notes to be attached to the 777 // fatal error, but suppresses any diagnostics that follow those 778 // notes. 779 if (Diag.LastDiagLevel == DiagnosticIDs::Fatal) 780 Diag.FatalErrorOccurred = true; 781 782 Diag.LastDiagLevel = DiagLevel; 783 } 784 785 // If a fatal error has already been emitted, silence all subsequent 786 // diagnostics. 787 if (Diag.FatalErrorOccurred) { 788 if (DiagLevel >= DiagnosticIDs::Error && 789 Diag.Client->IncludeInDiagnosticCounts()) { 790 ++Diag.NumErrors; 791 } 792 793 return false; 794 } 795 796 // If the client doesn't care about this message, don't issue it. If this is 797 // a note and the last real diagnostic was ignored, ignore it too. 798 if (DiagLevel == DiagnosticIDs::Ignored || 799 (DiagLevel == DiagnosticIDs::Note && 800 Diag.LastDiagLevel == DiagnosticIDs::Ignored)) 801 return false; 802 803 if (DiagLevel >= DiagnosticIDs::Error) { 804 if (isUnrecoverable(DiagID)) 805 Diag.UnrecoverableErrorOccurred = true; 806 807 // Warnings which have been upgraded to errors do not prevent compilation. 808 if (isDefaultMappingAsError(DiagID)) 809 Diag.UncompilableErrorOccurred = true; 810 811 Diag.ErrorOccurred = true; 812 if (Diag.Client->IncludeInDiagnosticCounts()) { 813 ++Diag.NumErrors; 814 } 815 816 // If we've emitted a lot of errors, emit a fatal error instead of it to 817 // stop a flood of bogus errors. 818 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit && 819 DiagLevel == DiagnosticIDs::Error) { 820 Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors); 821 return false; 822 } 823 } 824 825 // Make sure we set FatalErrorOccurred to ensure that the notes from the 826 // diagnostic that caused `fatal_too_many_errors` won't be emitted. 827 if (Diag.CurDiagID == diag::fatal_too_many_errors) 828 Diag.FatalErrorOccurred = true; 829 // Finally, report it. 830 EmitDiag(Diag, DiagLevel); 831 return true; 832 } 833 834 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const { 835 Diagnostic Info(&Diag); 836 assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!"); 837 838 Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info); 839 if (Diag.Client->IncludeInDiagnosticCounts()) { 840 if (DiagLevel == DiagnosticIDs::Warning) 841 ++Diag.NumWarnings; 842 } 843 844 Diag.CurDiagID = ~0U; 845 } 846 847 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const { 848 if (DiagID >= diag::DIAG_UPPER_LIMIT) { 849 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 850 // Custom diagnostics. 851 return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error; 852 } 853 854 // Only errors may be unrecoverable. 855 if (getBuiltinDiagClass(DiagID) < CLASS_ERROR) 856 return false; 857 858 if (DiagID == diag::err_unavailable || 859 DiagID == diag::err_unavailable_message) 860 return false; 861 862 // Currently we consider all ARC errors as recoverable. 863 if (isARCDiagnostic(DiagID)) 864 return false; 865 866 return true; 867 } 868 869 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) { 870 unsigned cat = getCategoryNumberForDiag(DiagID); 871 return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC "); 872 } 873