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