Coverage Report

Created: 2022-05-14 11:35

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