Coverage Report

Created: 2020-09-19 12:23

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