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> 21using namespace clang; 22 23//===----------------------------------------------------------------------===// 24// Builtin Diagnostic information 25//===----------------------------------------------------------------------===// 26 27namespace { 28 29struct 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. 34struct 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 55const 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 76extern const StaticDiagInfoRec StaticDiagInfo[]; 77 78// Stored separately from StaticDiagInfoRec to pack better. Otherwise, 79// StaticDiagInfoRec would have extra padding on 64-bit platforms. 80const 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. 102enum { 103 CLASS_NOTE = 0x01, 104 CLASS_REMARK = 0x02, 105 CLASS_WARNING = 0x03, 106 CLASS_EXTENSION = 0x04, 107 CLASS_ERROR = 0x05 108}; 109 110struct 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."); 155VALIDATE_DIAG_SIZE(COMMON) 156VALIDATE_DIAG_SIZE(DRIVER) 157VALIDATE_DIAG_SIZE(FRONTEND) 158VALIDATE_DIAG_SIZE(SERIALIZATION) 159VALIDATE_DIAG_SIZE(LEX) 160VALIDATE_DIAG_SIZE(PARSE) 161VALIDATE_DIAG_SIZE(AST) 162VALIDATE_DIAG_SIZE(COMMENT) 163VALIDATE_DIAG_SIZE(CROSSTU) 164VALIDATE_DIAG_SIZE(SEMA) 165VALIDATE_DIAG_SIZE(ANALYSIS) 166VALIDATE_DIAG_SIZE(REFACTORING) 167#undef VALIDATE_DIAG_SIZE 168#undef STRINGIFY_NAME 169 170const 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 203static 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. 207static 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 } 228CATEGORY(DRIVER, COMMON) 229CATEGORY(FRONTEND, DRIVER) 230CATEGORY(SERIALIZATION, FRONTEND) 231CATEGORY(LEX, SERIALIZATION) 232CATEGORY(PARSE, LEX) 233CATEGORY(AST, PARSE) 234CATEGORY(COMMENT, AST) 235CATEGORY(CROSSTU, COMMENT) 236CATEGORY(SEMA, CROSSTU) 237CATEGORY(ANALYSIS, SEMA) 238CATEGORY(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 256static 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. 275unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) { 276 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 277 return Info->Category; 278 return 0; 279} 280 281namespace { 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. 296DiagnosticMapping & 297DiagnosticsEngine::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 308static 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 317unsigned 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. 324StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) { 325 if (CategoryID >= getNumberOfCategories()) 326 return StringRef(); 327 return CategoryNameTable[CategoryID].getName(); 328} 329 330 331 332DiagnosticIDs::SFINAEResponse 333DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) { 334 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 335 return static_cast<DiagnosticIDs::SFINAEResponse>(Info->SFINAE); 336 return SFINAE_Report; 337} 338 339bool 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/// 347static 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 357namespace 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 404DiagnosticIDs::DiagnosticIDs() {} 405 406DiagnosticIDs::~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. 414unsigned 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. 425bool 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. 432bool 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/// 442bool 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 453bool 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. 462StringRef 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 469static 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. 488DiagnosticIDs::Level 489DiagnosticIDs::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. 508diag::Severity 509DiagnosticIDs::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 596namespace { 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. 611static 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. 620StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) { 621 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 622 return OptionTable[Info->getOptionGroupIndex()].getName(); 623 return StringRef(); 624} 625 626std::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. 640static 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 668bool 669DiagnosticIDs::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 679void 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 686StringRef 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. 719bool 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 800void 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 813bool 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 835bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) { 836 unsigned cat = getCategoryNumberForDiag(DiagID); 837 return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC "); 838} 839