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 DiagnosticMapping DiagnosticIDs::getDefaultMapping(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 static const StaticDiagCategoryRec CategoryNameTable[] = { 297 #define GET_CATEGORY_TABLE 298 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) }, 299 #include "clang/Basic/DiagnosticGroups.inc" 300 #undef GET_CATEGORY_TABLE 301 { nullptr, 0 } 302 }; 303 304 /// getNumberOfCategories - Return the number of categories 305 unsigned DiagnosticIDs::getNumberOfCategories() { 306 return std::size(CategoryNameTable) - 1; 307 } 308 309 /// getCategoryNameFromID - Given a category ID, return the name of the 310 /// category, an empty string if CategoryID is zero, or null if CategoryID is 311 /// invalid. 312 StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) { 313 if (CategoryID >= getNumberOfCategories()) 314 return StringRef(); 315 return CategoryNameTable[CategoryID].getName(); 316 } 317 318 319 320 DiagnosticIDs::SFINAEResponse 321 DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) { 322 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 323 return static_cast<DiagnosticIDs::SFINAEResponse>(Info->SFINAE); 324 return SFINAE_Report; 325 } 326 327 bool DiagnosticIDs::isDeferrable(unsigned DiagID) { 328 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 329 return Info->Deferrable; 330 return false; 331 } 332 333 /// getBuiltinDiagClass - Return the class field of the diagnostic. 334 /// 335 static unsigned getBuiltinDiagClass(unsigned DiagID) { 336 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 337 return Info->Class; 338 return ~0U; 339 } 340 341 //===----------------------------------------------------------------------===// 342 // Custom Diagnostic information 343 //===----------------------------------------------------------------------===// 344 345 namespace clang { 346 namespace diag { 347 class CustomDiagInfo { 348 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc; 349 std::vector<DiagDesc> DiagInfo; 350 std::map<DiagDesc, unsigned> DiagIDs; 351 public: 352 353 /// getDescription - Return the description of the specified custom 354 /// diagnostic. 355 StringRef getDescription(unsigned DiagID) const { 356 assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() && 357 "Invalid diagnostic ID"); 358 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second; 359 } 360 361 /// getLevel - Return the level of the specified custom diagnostic. 362 DiagnosticIDs::Level getLevel(unsigned DiagID) const { 363 assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() && 364 "Invalid diagnostic ID"); 365 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first; 366 } 367 368 unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message, 369 DiagnosticIDs &Diags) { 370 DiagDesc D(L, std::string(Message)); 371 // Check to see if it already exists. 372 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D); 373 if (I != DiagIDs.end() && I->first == D) 374 return I->second; 375 376 // If not, assign a new ID. 377 unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT; 378 DiagIDs.insert(std::make_pair(D, ID)); 379 DiagInfo.push_back(D); 380 return ID; 381 } 382 }; 383 384 } // end diag namespace 385 } // end clang namespace 386 387 388 //===----------------------------------------------------------------------===// 389 // Common Diagnostic implementation 390 //===----------------------------------------------------------------------===// 391 392 DiagnosticIDs::DiagnosticIDs() {} 393 394 DiagnosticIDs::~DiagnosticIDs() {} 395 396 /// getCustomDiagID - Return an ID for a diagnostic with the specified message 397 /// and level. If this is the first request for this diagnostic, it is 398 /// registered and created, otherwise the existing ID is returned. 399 /// 400 /// \param FormatString A fixed diagnostic format string that will be hashed and 401 /// mapped to a unique DiagID. 402 unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) { 403 if (!CustomDiagInfo) 404 CustomDiagInfo.reset(new diag::CustomDiagInfo()); 405 return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this); 406 } 407 408 409 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic 410 /// level of the specified diagnostic ID is a Warning or Extension. 411 /// This only works on builtin diagnostics, not custom ones, and is not legal to 412 /// call on NOTEs. 413 bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) { 414 return DiagID < diag::DIAG_UPPER_LIMIT && 415 getBuiltinDiagClass(DiagID) != CLASS_ERROR; 416 } 417 418 /// Determine whether the given built-in diagnostic ID is a 419 /// Note. 420 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) { 421 return DiagID < diag::DIAG_UPPER_LIMIT && 422 getBuiltinDiagClass(DiagID) == CLASS_NOTE; 423 } 424 425 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic 426 /// ID is for an extension of some sort. This also returns EnabledByDefault, 427 /// which is set to indicate whether the diagnostic is ignored by default (in 428 /// which case -pedantic enables it) or treated as a warning/error by default. 429 /// 430 bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID, 431 bool &EnabledByDefault) { 432 if (DiagID >= diag::DIAG_UPPER_LIMIT || 433 getBuiltinDiagClass(DiagID) != CLASS_EXTENSION) 434 return false; 435 436 EnabledByDefault = 437 getDefaultMapping(DiagID).getSeverity() != diag::Severity::Ignored; 438 return true; 439 } 440 441 bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) { 442 if (DiagID >= diag::DIAG_UPPER_LIMIT) 443 return false; 444 445 return getDefaultMapping(DiagID).getSeverity() >= diag::Severity::Error; 446 } 447 448 /// getDescription - Given a diagnostic ID, return a description of the 449 /// issue. 450 StringRef DiagnosticIDs::getDescription(unsigned DiagID) const { 451 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 452 return Info->getDescription(); 453 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 454 return CustomDiagInfo->getDescription(DiagID); 455 } 456 457 static DiagnosticIDs::Level toLevel(diag::Severity SV) { 458 switch (SV) { 459 case diag::Severity::Ignored: 460 return DiagnosticIDs::Ignored; 461 case diag::Severity::Remark: 462 return DiagnosticIDs::Remark; 463 case diag::Severity::Warning: 464 return DiagnosticIDs::Warning; 465 case diag::Severity::Error: 466 return DiagnosticIDs::Error; 467 case diag::Severity::Fatal: 468 return DiagnosticIDs::Fatal; 469 } 470 llvm_unreachable("unexpected severity"); 471 } 472 473 /// getDiagnosticLevel - Based on the way the client configured the 474 /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level, 475 /// by consumable the DiagnosticClient. 476 DiagnosticIDs::Level 477 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, 478 const DiagnosticsEngine &Diag) const { 479 // Handle custom diagnostics, which cannot be mapped. 480 if (DiagID >= diag::DIAG_UPPER_LIMIT) { 481 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 482 return CustomDiagInfo->getLevel(DiagID); 483 } 484 485 unsigned DiagClass = getBuiltinDiagClass(DiagID); 486 if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note; 487 return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag)); 488 } 489 490 /// Based on the way the client configured the Diagnostic 491 /// object, classify the specified diagnostic ID into a Level, consumable by 492 /// the DiagnosticClient. 493 /// 494 /// \param Loc The source location we are interested in finding out the 495 /// diagnostic state. Can be null in order to query the latest state. 496 diag::Severity 497 DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, 498 const DiagnosticsEngine &Diag) const { 499 assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE); 500 501 // Specific non-error diagnostics may be mapped to various levels from ignored 502 // to error. Errors can only be mapped to fatal. 503 diag::Severity Result = diag::Severity::Fatal; 504 505 // Get the mapping information, or compute it lazily. 506 DiagnosticsEngine::DiagState *State = Diag.GetDiagStateForLoc(Loc); 507 DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID); 508 509 // TODO: Can a null severity really get here? 510 if (Mapping.getSeverity() != diag::Severity()) 511 Result = Mapping.getSeverity(); 512 513 // Upgrade ignored diagnostics if -Weverything is enabled. 514 if (State->EnableAllWarnings && Result == diag::Severity::Ignored && 515 !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK) 516 Result = diag::Severity::Warning; 517 518 // Ignore -pedantic diagnostics inside __extension__ blocks. 519 // (The diagnostics controlled by -pedantic are the extension diagnostics 520 // that are not enabled by default.) 521 bool EnabledByDefault = false; 522 bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault); 523 if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault) 524 return diag::Severity::Ignored; 525 526 // For extension diagnostics that haven't been explicitly mapped, check if we 527 // should upgrade the diagnostic. 528 if (IsExtensionDiag && !Mapping.isUser()) 529 Result = std::max(Result, State->ExtBehavior); 530 531 // At this point, ignored errors can no longer be upgraded. 532 if (Result == diag::Severity::Ignored) 533 return Result; 534 535 // Honor -w: this disables all messages which are not Error/Fatal by 536 // default (disregarding attempts to upgrade severity from Warning to Error), 537 // as well as disabling all messages which are currently mapped to Warning 538 // (whether by default or downgraded from Error via e.g. -Wno-error or #pragma 539 // diagnostic.) 540 if (State->IgnoreAllWarnings) { 541 if (Result == diag::Severity::Warning || 542 (Result >= diag::Severity::Error && 543 !isDefaultMappingAsError((diag::kind)DiagID))) 544 return diag::Severity::Ignored; 545 } 546 547 // If -Werror is enabled, map warnings to errors unless explicitly disabled. 548 if (Result == diag::Severity::Warning) { 549 if (State->WarningsAsErrors && !Mapping.hasNoWarningAsError()) 550 Result = diag::Severity::Error; 551 } 552 553 // If -Wfatal-errors is enabled, map errors to fatal unless explicitly 554 // disabled. 555 if (Result == diag::Severity::Error) { 556 if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal()) 557 Result = diag::Severity::Fatal; 558 } 559 560 // If explicitly requested, map fatal errors to errors. 561 if (Result == diag::Severity::Fatal && 562 Diag.CurDiagID != diag::fatal_too_many_errors && Diag.FatalsAsError) 563 Result = diag::Severity::Error; 564 565 // Custom diagnostics always are emitted in system headers. 566 bool ShowInSystemHeader = 567 !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader; 568 569 // If we are in a system header, we ignore it. We look at the diagnostic class 570 // because we also want to ignore extensions and warnings in -Werror and 571 // -pedantic-errors modes, which *map* warnings/extensions to errors. 572 if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() && 573 Diag.getSourceManager().isInSystemHeader( 574 Diag.getSourceManager().getExpansionLoc(Loc))) 575 return diag::Severity::Ignored; 576 577 // We also ignore warnings due to system macros 578 bool ShowInSystemMacro = 579 !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemMacro; 580 if (State->SuppressSystemWarnings && !ShowInSystemMacro && Loc.isValid() && 581 Diag.getSourceManager().isInSystemMacro(Loc)) 582 return diag::Severity::Ignored; 583 584 return Result; 585 } 586 587 #define GET_DIAG_ARRAYS 588 #include "clang/Basic/DiagnosticGroups.inc" 589 #undef GET_DIAG_ARRAYS 590 591 namespace { 592 struct WarningOption { 593 uint16_t NameOffset; 594 uint16_t Members; 595 uint16_t SubGroups; 596 StringRef Documentation; 597 598 // String is stored with a pascal-style length byte. 599 StringRef getName() const { 600 return StringRef(DiagGroupNames + NameOffset + 1, 601 DiagGroupNames[NameOffset]); 602 } 603 }; 604 } 605 606 // Second the table of options, sorted by name for fast binary lookup. 607 static const WarningOption OptionTable[] = { 608 #define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \ 609 {FlagNameOffset, Members, SubGroups, Docs}, 610 #include "clang/Basic/DiagnosticGroups.inc" 611 #undef DIAG_ENTRY 612 }; 613 614 /// Given a diagnostic group ID, return its documentation. 615 StringRef DiagnosticIDs::getWarningOptionDocumentation(diag::Group Group) { 616 return OptionTable[static_cast<int>(Group)].Documentation; 617 } 618 619 StringRef DiagnosticIDs::getWarningOptionForGroup(diag::Group Group) { 620 return OptionTable[static_cast<int>(Group)].getName(); 621 } 622 623 std::optional<diag::Group> 624 DiagnosticIDs::getGroupForWarningOption(StringRef Name) { 625 const auto *Found = llvm::partition_point( 626 OptionTable, [=](const WarningOption &O) { return O.getName() < Name; }); 627 if (Found == std::end(OptionTable) || Found->getName() != Name) 628 return std::nullopt; 629 return static_cast<diag::Group>(Found - OptionTable); 630 } 631 632 std::optional<diag::Group> DiagnosticIDs::getGroupForDiag(unsigned DiagID) { 633 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 634 return static_cast<diag::Group>(Info->getOptionGroupIndex()); 635 return std::nullopt; 636 } 637 638 /// getWarningOptionForDiag - Return the lowest-level warning option that 639 /// enables the specified diagnostic. If there is no -Wfoo flag that controls 640 /// the diagnostic, this returns null. 641 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { 642 if (auto G = getGroupForDiag(DiagID)) 643 return getWarningOptionForGroup(*G); 644 return StringRef(); 645 } 646 647 std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() { 648 std::vector<std::string> Res{"-W", "-Wno-"}; 649 for (size_t I = 1; DiagGroupNames[I] != '\0';) { 650 std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]); 651 I += DiagGroupNames[I] + 1; 652 Res.push_back("-W" + Diag); 653 Res.push_back("-Wno-" + Diag); 654 } 655 656 return Res; 657 } 658 659 /// Return \c true if any diagnostics were found in this group, even if they 660 /// were filtered out due to having the wrong flavor. 661 static bool getDiagnosticsInGroup(diag::Flavor Flavor, 662 const WarningOption *Group, 663 SmallVectorImpl<diag::kind> &Diags) { 664 // An empty group is considered to be a warning group: we have empty groups 665 // for GCC compatibility, and GCC does not have remarks. 666 if (!Group->Members && !Group->SubGroups) 667 return Flavor == diag::Flavor::Remark; 668 669 bool NotFound = true; 670 671 // Add the members of the option diagnostic set. 672 const int16_t *Member = DiagArrays + Group->Members; 673 for (; *Member != -1; ++Member) { 674 if (GetDiagInfo(*Member)->getFlavor() == Flavor) { 675 NotFound = false; 676 Diags.push_back(*Member); 677 } 678 } 679 680 // Add the members of the subgroups. 681 const int16_t *SubGroups = DiagSubGroups + Group->SubGroups; 682 for (; *SubGroups != (int16_t)-1; ++SubGroups) 683 NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups], 684 Diags); 685 686 return NotFound; 687 } 688 689 bool 690 DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group, 691 SmallVectorImpl<diag::kind> &Diags) const { 692 if (std::optional<diag::Group> G = getGroupForWarningOption(Group)) 693 return ::getDiagnosticsInGroup( 694 Flavor, &OptionTable[static_cast<unsigned>(*G)], Diags); 695 return true; 696 } 697 698 void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor, 699 std::vector<diag::kind> &Diags) { 700 for (unsigned i = 0; i != StaticDiagInfoSize; ++i) 701 if (StaticDiagInfo[i].getFlavor() == Flavor) 702 Diags.push_back(StaticDiagInfo[i].DiagID); 703 } 704 705 StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor, 706 StringRef Group) { 707 StringRef Best; 708 unsigned BestDistance = Group.size() + 1; // Maximum threshold. 709 for (const WarningOption &O : OptionTable) { 710 // Don't suggest ignored warning flags. 711 if (!O.Members && !O.SubGroups) 712 continue; 713 714 unsigned Distance = O.getName().edit_distance(Group, true, BestDistance); 715 if (Distance > BestDistance) 716 continue; 717 718 // Don't suggest groups that are not of this kind. 719 llvm::SmallVector<diag::kind, 8> Diags; 720 if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty()) 721 continue; 722 723 if (Distance == BestDistance) { 724 // Two matches with the same distance, don't prefer one over the other. 725 Best = ""; 726 } else if (Distance < BestDistance) { 727 // This is a better match. 728 Best = O.getName(); 729 BestDistance = Distance; 730 } 731 } 732 733 return Best; 734 } 735 736 /// ProcessDiag - This is the method used to report a diagnostic that is 737 /// finally fully formed. 738 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const { 739 Diagnostic Info(&Diag); 740 741 assert(Diag.getClient() && "DiagnosticClient not set!"); 742 743 // Figure out the diagnostic level of this message. 744 unsigned DiagID = Info.getID(); 745 DiagnosticIDs::Level DiagLevel 746 = getDiagnosticLevel(DiagID, Info.getLocation(), Diag); 747 748 // Update counts for DiagnosticErrorTrap even if a fatal error occurred 749 // or diagnostics are suppressed. 750 if (DiagLevel >= DiagnosticIDs::Error) { 751 ++Diag.TrapNumErrorsOccurred; 752 if (isUnrecoverable(DiagID)) 753 ++Diag.TrapNumUnrecoverableErrorsOccurred; 754 } 755 756 if (Diag.SuppressAllDiagnostics) 757 return false; 758 759 if (DiagLevel != DiagnosticIDs::Note) { 760 // Record that a fatal error occurred only when we see a second 761 // non-note diagnostic. This allows notes to be attached to the 762 // fatal error, but suppresses any diagnostics that follow those 763 // notes. 764 if (Diag.LastDiagLevel == DiagnosticIDs::Fatal) 765 Diag.FatalErrorOccurred = true; 766 767 Diag.LastDiagLevel = DiagLevel; 768 } 769 770 // If a fatal error has already been emitted, silence all subsequent 771 // diagnostics. 772 if (Diag.FatalErrorOccurred) { 773 if (DiagLevel >= DiagnosticIDs::Error && 774 Diag.Client->IncludeInDiagnosticCounts()) { 775 ++Diag.NumErrors; 776 } 777 778 return false; 779 } 780 781 // If the client doesn't care about this message, don't issue it. If this is 782 // a note and the last real diagnostic was ignored, ignore it too. 783 if (DiagLevel == DiagnosticIDs::Ignored || 784 (DiagLevel == DiagnosticIDs::Note && 785 Diag.LastDiagLevel == DiagnosticIDs::Ignored)) 786 return false; 787 788 if (DiagLevel >= DiagnosticIDs::Error) { 789 if (isUnrecoverable(DiagID)) 790 Diag.UnrecoverableErrorOccurred = true; 791 792 // Warnings which have been upgraded to errors do not prevent compilation. 793 if (isDefaultMappingAsError(DiagID)) 794 Diag.UncompilableErrorOccurred = true; 795 796 Diag.ErrorOccurred = true; 797 if (Diag.Client->IncludeInDiagnosticCounts()) { 798 ++Diag.NumErrors; 799 } 800 801 // If we've emitted a lot of errors, emit a fatal error instead of it to 802 // stop a flood of bogus errors. 803 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit && 804 DiagLevel == DiagnosticIDs::Error) { 805 Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors); 806 return false; 807 } 808 } 809 810 // Make sure we set FatalErrorOccurred to ensure that the notes from the 811 // diagnostic that caused `fatal_too_many_errors` won't be emitted. 812 if (Diag.CurDiagID == diag::fatal_too_many_errors) 813 Diag.FatalErrorOccurred = true; 814 // Finally, report it. 815 EmitDiag(Diag, DiagLevel); 816 return true; 817 } 818 819 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const { 820 Diagnostic Info(&Diag); 821 assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!"); 822 823 Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info); 824 if (Diag.Client->IncludeInDiagnosticCounts()) { 825 if (DiagLevel == DiagnosticIDs::Warning) 826 ++Diag.NumWarnings; 827 } 828 829 Diag.CurDiagID = ~0U; 830 } 831 832 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const { 833 if (DiagID >= diag::DIAG_UPPER_LIMIT) { 834 assert(CustomDiagInfo && "Invalid CustomDiagInfo"); 835 // Custom diagnostics. 836 return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error; 837 } 838 839 // Only errors may be unrecoverable. 840 if (getBuiltinDiagClass(DiagID) < CLASS_ERROR) 841 return false; 842 843 if (DiagID == diag::err_unavailable || 844 DiagID == diag::err_unavailable_message) 845 return false; 846 847 // Currently we consider all ARC errors as recoverable. 848 if (isARCDiagnostic(DiagID)) 849 return false; 850 851 return true; 852 } 853 854 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) { 855 unsigned cat = getCategoryNumberForDiag(DiagID); 856 return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC "); 857 } 858