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