Coverage Report

Created: 2022-07-16 07:03

/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
37.2k
  unsigned getOptionGroupIndex() const {
126
37.2k
    return OptionGroupIndex;
127
37.2k
  }
128
129
416k
  StringRef getDescription() const {
130
416k
    size_t MyIndex = this - &StaticDiagInfo[0];
131
416k
    uint32_t StringOffset = StaticDiagInfoDescriptionOffsets[MyIndex];
132
416k
    const char* Table = reinterpret_cast<const char*>(&StaticDiagInfoDescriptions);
133
416k
    return StringRef(&Table[StringOffset], DescriptionLen);
134
416k
  }
135
136
5.61M
  diag::Flavor getFlavor() const {
137
5.61M
    return Class == CLASS_REMARK ? 
diag::Flavor::Remark2.71k
138
5.61M
                                 : 
diag::Flavor::WarningOrError5.61M
;
139
5.61M
  }
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
486M
static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
210
  // Out of bounds diag. Can't be in the table.
211
486M
  using namespace diag;
212
486M
  if (DiagID >= DIAG_UPPER_LIMIT || 
DiagID <= DIAG_START_COMMON486M
)
213
28.0k
    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
486M
  unsigned Offset = 0;
224
486M
  unsigned ID = DiagID - DIAG_START_COMMON - 1;
225
486M
#define CATEGORY(NAME, PREV) \
226
5.35G
  if (DiagID > DIAG_START_##NAME) { \
227
3.38G
    Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
228
3.38G
    ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
229
3.38G
  }
230
486M
CATEGORY(DRIVER, COMMON)
231
486M
CATEGORY(FRONTEND, DRIVER)
232
486M
CATEGORY(SERIALIZATION, FRONTEND)
233
486M
CATEGORY(LEX, SERIALIZATION)
234
486M
CATEGORY(PARSE, LEX)
235
486M
CATEGORY(AST, PARSE)
236
486M
CATEGORY(COMMENT, AST)
237
486M
CATEGORY(CROSSTU, COMMENT)
238
486M
CATEGORY(SEMA, CROSSTU)
239
486M
CATEGORY(ANALYSIS, SEMA)
240
486M
CATEGORY(REFACTORING, ANALYSIS)
241
486M
#undef CATEGORY
242
243
  // Avoid out of bounds reads.
244
486M
  if (ID + Offset >= StaticDiagInfoSize)
245
0
    return nullptr;
246
247
486M
  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
486M
  if (Found->DiagID != DiagID)
254
0
    return nullptr;
255
486M
  return Found;
256
486M
}
257
258
14.8M
static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID) {
259
14.8M
  DiagnosticMapping Info = DiagnosticMapping::Make(
260
14.8M
      diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false);
261
262
14.8M
  if (const StaticDiagInfoRec *
StaticInfo14.8M
= GetDiagInfo(DiagID)) {
263
14.8M
    Info.setSeverity((diag::Severity)StaticInfo->DefaultSeverity);
264
265
14.8M
    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
14.8M
  }
271
272
0
  return Info;
273
14.8M
}
274
275
/// getCategoryNumberForDiag - Return the category number that a specified
276
/// DiagID belongs to, or 0 if no category.
277
445k
unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
278
445k
  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
279
445k
    return Info->Category;
280
1
  return 0;
281
445k
}
282
283
namespace {
284
  // The diagnostic category names.
285
  struct StaticDiagCategoryRec {
286
    const char *NameStr;
287
    uint8_t NameLen;
288
289
443k
    StringRef getName() const {
290
443k
      return StringRef(NameStr, NameLen);
291
443k
    }
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
200M
DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) {
300
200M
  std::pair<iterator, bool> Result =
301
200M
      DiagMap.insert(std::make_pair(Diag, DiagnosticMapping()));
302
303
  // Initialize the entry if we added it.
304
200M
  if (Result.second)
305
10.8M
    Result.first->second = GetDefaultDiagMapping(Diag);
306
307
200M
  return Result.first->second;
308
200M
}
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
443k
unsigned DiagnosticIDs::getNumberOfCategories() {
320
443k
  return llvm::array_lengthof(CategoryNameTable) - 1;
321
443k
}
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
443k
StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
327
443k
  if (CategoryID >= getNumberOfCategories())
328
0
   return StringRef();
329
443k
  return CategoryNameTable[CategoryID].getName();
330
443k
}
331
332
333
334
DiagnosticIDs::SFINAEResponse
335
224k
DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
336
224k
  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
337
224k
    return static_cast<DiagnosticIDs::SFINAEResponse>(Info->SFINAE);
338
0
  return SFINAE_Report;
339
224k
}
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
403M
static unsigned getBuiltinDiagClass(unsigned DiagID) {
350
403M
  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
351
403M
    return Info->Class;
352
18.4E
  return ~0U;
353
403M
}
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
26.5k
      StringRef getDescription(unsigned DiagID) const {
370
26.5k
        assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
371
26.5k
               "Invalid diagnostic ID");
372
0
        return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
373
26.5k
      }
374
375
      /// getLevel - Return the level of the specified custom diagnostic.
376
26.9k
      DiagnosticIDs::Level getLevel(unsigned DiagID) const {
377
26.9k
        assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
378
26.9k
               "Invalid diagnostic ID");
379
0
        return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
380
26.9k
      }
381
382
      unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
383
4.59k
                                 DiagnosticIDs &Diags) {
384
4.59k
        DiagDesc D(L, std::string(Message));
385
        // Check to see if it already exists.
386
4.59k
        std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
387
4.59k
        if (I != DiagIDs.end() && 
I->first == D2.37k
)
388
408
          return I->second;
389
390
        // If not, assign a new ID.
391
4.19k
        unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
392
4.19k
        DiagIDs.insert(std::make_pair(D, ID));
393
4.19k
        DiagInfo.push_back(D);
394
4.19k
        return ID;
395
4.59k
      }
396
    };
397
398
  } // end diag namespace
399
} // end clang namespace
400
401
402
//===----------------------------------------------------------------------===//
403
// Common Diagnostic implementation
404
//===----------------------------------------------------------------------===//
405
406
412k
DiagnosticIDs::DiagnosticIDs() {}
407
408
405k
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.59k
unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) {
417
4.59k
  if (!CustomDiagInfo)
418
2.22k
    CustomDiagInfo.reset(new diag::CustomDiagInfo());
419
4.59k
  return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this);
420
4.59k
}
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
3.64M
bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
428
3.64M
  return DiagID < diag::DIAG_UPPER_LIMIT &&
429
3.64M
         
getBuiltinDiagClass(DiagID) != CLASS_ERROR3.64M
;
430
3.64M
}
431
432
/// Determine whether the given built-in diagnostic ID is a
433
/// Note.
434
372k
bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
435
372k
  return DiagID < diag::DIAG_UPPER_LIMIT &&
436
372k
    
getBuiltinDiagClass(DiagID) == CLASS_NOTE372k
;
437
372k
}
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
191M
                                        bool &EnabledByDefault) {
446
191M
  if (DiagID >= diag::DIAG_UPPER_LIMIT ||
447
191M
      getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
448
190M
    return false;
449
450
610k
  EnabledByDefault =
451
610k
      GetDefaultDiagMapping(DiagID).getSeverity() != diag::Severity::Ignored;
452
610k
  return true;
453
191M
}
454
455
3.46M
bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) {
456
3.46M
  if (DiagID >= diag::DIAG_UPPER_LIMIT)
457
204
    return false;
458
459
3.46M
  return GetDefaultDiagMapping(DiagID).getSeverity() >= diag::Severity::Error;
460
3.46M
}
461
462
/// getDescription - Given a diagnostic ID, return a description of the
463
/// issue.
464
443k
StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
465
443k
  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
466
416k
    return Info->getDescription();
467
26.5k
  assert(CustomDiagInfo && "Invalid CustomDiagInfo");
468
0
  return CustomDiagInfo->getDescription(DiagID);
469
443k
}
470
471
13.7M
static DiagnosticIDs::Level toLevel(diag::Severity SV) {
472
13.7M
  switch (SV) {
473
11.5M
  case diag::Severity::Ignored:
474
11.5M
    return DiagnosticIDs::Ignored;
475
1.03k
  case diag::Severity::Remark:
476
1.03k
    return DiagnosticIDs::Remark;
477
1.57M
  case diag::Severity::Warning:
478
1.57M
    return DiagnosticIDs::Warning;
479
572k
  case diag::Severity::Error:
480
572k
    return DiagnosticIDs::Error;
481
304
  case diag::Severity::Fatal:
482
304
    return DiagnosticIDs::Fatal;
483
13.7M
  }
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
16.1M
                                  const DiagnosticsEngine &Diag) const {
493
  // Handle custom diagnostics, which cannot be mapped.
494
16.1M
  if (DiagID >= diag::DIAG_UPPER_LIMIT) {
495
26.5k
    assert(CustomDiagInfo && "Invalid CustomDiagInfo");
496
0
    return CustomDiagInfo->getLevel(DiagID);
497
26.5k
  }
498
499
16.1M
  unsigned DiagClass = getBuiltinDiagClass(DiagID);
500
16.1M
  if (DiagClass == CLASS_NOTE) 
return DiagnosticIDs::Note2.41M
;
501
13.7M
  return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
502
16.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
191M
                                     const DiagnosticsEngine &Diag) const {
513
191M
  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
191M
  DiagnosticsEngine::DiagState *State = Diag.GetDiagStateForLoc(Loc);
521
191M
  DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID);
522
523
  // TODO: Can a null severity really get here?
524
191M
  if (Mapping.getSeverity() != diag::Severity())
525
191M
    Result = Mapping.getSeverity();
526
527
  // Upgrade ignored diagnostics if -Weverything is enabled.
528
191M
  if (State->EnableAllWarnings && 
Result == diag::Severity::Ignored12.2k
&&
529
191M
      
!Mapping.isUser()11.2k
&&
getBuiltinDiagClass(DiagID) != CLASS_REMARK11.2k
)
530
11.2k
    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
191M
  bool EnabledByDefault = false;
536
191M
  bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
537
191M
  if (Diag.AllExtensionsSilenced && 
IsExtensionDiag420k
&&
!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
191M
  if (IsExtensionDiag && 
!Mapping.isUser()594k
)
543
583k
    Result = std::max(Result, State->ExtBehavior);
544
545
  // At this point, ignored errors can no longer be upgraded.
546
191M
  if (Result == diag::Severity::Ignored)
547
173M
    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
18.1M
  if (State->IgnoreAllWarnings) {
555
343k
    if (Result == diag::Severity::Warning ||
556
343k
        
(2.53k
Result >= diag::Severity::Error2.53k
&&
557
2.53k
         
!isDefaultMappingAsError((diag::kind)DiagID)2.52k
))
558
341k
      return diag::Severity::Ignored;
559
343k
  }
560
561
  // If -Werror is enabled, map warnings to errors unless explicitly disabled.
562
17.8M
  if (Result == diag::Severity::Warning) {
563
17.2M
    if (State->WarningsAsErrors && 
!Mapping.hasNoWarningAsError()2.92M
)
564
2.92M
      Result = diag::Severity::Error;
565
17.2M
  }
566
567
  // If -Wfatal-errors is enabled, map errors to fatal unless explicitly
568
  // disabled.
569
17.8M
  if (Result == diag::Severity::Error) {
570
3.56M
    if (State->ErrorsAsFatal && 
!Mapping.hasNoErrorAsFatal()7
)
571
7
      Result = diag::Severity::Fatal;
572
3.56M
  }
573
574
  // If explicitly requested, map fatal errors to errors.
575
17.8M
  if (Result == diag::Severity::Fatal &&
576
17.8M
      
Diag.CurDiagID != diag::fatal_too_many_errors337
&&
Diag.FatalsAsError326
)
577
12
    Result = diag::Severity::Error;
578
579
  // Custom diagnostics always are emitted in system headers.
580
17.8M
  bool ShowInSystemHeader =
581
17.8M
      
!GetDiagInfo(DiagID)17.8M
|| 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
17.8M
  if (State->SuppressSystemWarnings && 
!ShowInSystemHeader16.3M
&&
Loc.isValid()15.7M
&&
587
17.8M
      Diag.getSourceManager().isInSystemHeader(
588
11.3M
          Diag.getSourceManager().getExpansionLoc(Loc)))
589
4.69M
    return diag::Severity::Ignored;
590
591
  // We also ignore warnings due to system macros
592
13.1M
  bool ShowInSystemMacro =
593
13.1M
      
!GetDiagInfo(DiagID)13.1M
|| GetDiagInfo(DiagID)->WarnShowInSystemMacro;
594
13.1M
  if (State->SuppressSystemWarnings && 
!ShowInSystemMacro11.6M
&&
Loc.isValid()553
&&
595
13.1M
      
Diag.getSourceManager().isInSystemMacro(Loc)553
)
596
5
    return diag::Severity::Ignored;
597
598
13.1M
  return Result;
599
13.1M
}
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
    StringRef Documentation;
611
612
    // String is stored with a pascal-style length byte.
613
5.79M
    StringRef getName() const {
614
5.79M
      return StringRef(DiagGroupNames + NameOffset + 1,
615
5.79M
                       DiagGroupNames[NameOffset]);
616
5.79M
    }
617
  };
618
}
619
620
// Second the table of options, sorted by name for fast binary lookup.
621
static const WarningOption OptionTable[] = {
622
#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs)        \
623
  {FlagNameOffset, Members, SubGroups, Docs},
624
#include "clang/Basic/DiagnosticGroups.inc"
625
#undef DIAG_ENTRY
626
};
627
628
/// Given a diagnostic group ID, return its documentation.
629
0
StringRef DiagnosticIDs::getWarningOptionDocumentation(diag::Group Group) {
630
0
  return OptionTable[static_cast<int>(Group)].Documentation;
631
0
}
632
633
37.2k
StringRef DiagnosticIDs::getWarningOptionForGroup(diag::Group Group) {
634
37.2k
  return OptionTable[static_cast<int>(Group)].getName();
635
37.2k
}
636
637
llvm::Optional<diag::Group>
638
533k
DiagnosticIDs::getGroupForWarningOption(StringRef Name) {
639
533k
  const auto *Found = llvm::partition_point(
640
5.21M
      OptionTable, [=](const WarningOption &O) { return O.getName() < Name; });
641
533k
  if (Found == std::end(OptionTable) || 
Found->getName() != Name533k
)
642
58
    return llvm::None;
643
533k
  return static_cast<diag::Group>(Found - OptionTable);
644
533k
}
645
646
38.7k
llvm::Optional<diag::Group> DiagnosticIDs::getGroupForDiag(unsigned DiagID) {
647
38.7k
  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
648
37.2k
    return static_cast<diag::Group>(Info->getOptionGroupIndex());
649
1.51k
  return llvm::None;
650
38.7k
}
651
652
/// getWarningOptionForDiag - Return the lowest-level warning option that
653
/// enables the specified diagnostic.  If there is no -Wfoo flag that controls
654
/// the diagnostic, this returns null.
655
38.7k
StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
656
38.7k
  if (auto G = getGroupForDiag(DiagID))
657
37.2k
    return getWarningOptionForGroup(*G);
658
1.51k
  return StringRef();
659
38.7k
}
660
661
13
std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() {
662
13
  std::vector<std::string> Res{"-W", "-Wno-"};
663
12.3k
  for (size_t I = 1; DiagGroupNames[I] != '\0';) {
664
12.2k
    std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]);
665
12.2k
    I += DiagGroupNames[I] + 1;
666
12.2k
    Res.push_back("-W" + Diag);
667
12.2k
    Res.push_back("-Wno-" + Diag);
668
12.2k
  }
669
670
13
  return Res;
671
13
}
672
673
/// Return \c true if any diagnostics were found in this group, even if they
674
/// were filtered out due to having the wrong flavor.
675
static bool getDiagnosticsInGroup(diag::Flavor Flavor,
676
                                  const WarningOption *Group,
677
1.65M
                                  SmallVectorImpl<diag::kind> &Diags) {
678
  // An empty group is considered to be a warning group: we have empty groups
679
  // for GCC compatibility, and GCC does not have remarks.
680
1.65M
  if (!Group->Members && 
!Group->SubGroups62.4k
)
681
19.2k
    return Flavor == diag::Flavor::Remark;
682
683
1.63M
  bool NotFound = true;
684
685
  // Add the members of the option diagnostic set.
686
1.63M
  const int16_t *Member = DiagArrays + Group->Members;
687
6.99M
  for (; *Member != -1; 
++Member5.35M
) {
688
5.35M
    if (GetDiagInfo(*Member)->getFlavor() == Flavor) {
689
5.35M
      NotFound = false;
690
5.35M
      Diags.push_back(*Member);
691
5.35M
    }
692
5.35M
  }
693
694
  // Add the members of the subgroups.
695
1.63M
  const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
696
2.75M
  for (; *SubGroups != (int16_t)-1; 
++SubGroups1.12M
)
697
1.12M
    NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
698
1.12M
                                      Diags);
699
700
1.63M
  return NotFound;
701
1.65M
}
702
703
bool
704
DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
705
533k
                                     SmallVectorImpl<diag::kind> &Diags) const {
706
533k
  if (llvm::Optional<diag::Group> G = getGroupForWarningOption(Group))
707
533k
    return ::getDiagnosticsInGroup(
708
533k
        Flavor, &OptionTable[static_cast<unsigned>(*G)], Diags);
709
56
  return true;
710
533k
}
711
712
void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor,
713
44
                                      std::vector<diag::kind> &Diags) {
714
262k
  for (unsigned i = 0; i != StaticDiagInfoSize; 
++i262k
)
715
262k
    if (StaticDiagInfo[i].getFlavor() == Flavor)
716
208k
      Diags.push_back(StaticDiagInfo[i].DiagID);
717
44
}
718
719
StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
720
17
                                          StringRef Group) {
721
17
  StringRef Best;
722
17
  unsigned BestDistance = Group.size() + 1; // Maximum threshold.
723
16.0k
  for (const WarningOption &O : OptionTable) {
724
    // Don't suggest ignored warning flags.
725
16.0k
    if (!O.Members && 
!O.SubGroups2.05k
)
726
663
      continue;
727
728
15.4k
    unsigned Distance = O.getName().edit_distance(Group, true, BestDistance);
729
15.4k
    if (Distance > BestDistance)
730
14.7k
      continue;
731
732
    // Don't suggest groups that are not of this kind.
733
715
    llvm::SmallVector<diag::kind, 8> Diags;
734
715
    if (::getDiagnosticsInGroup(Flavor, &O, Diags) || 
Diags.empty()191
)
735
524
      continue;
736
737
191
    if (Distance == BestDistance) {
738
      // Two matches with the same distance, don't prefer one over the other.
739
97
      Best = "";
740
97
    } else 
if (94
Distance < BestDistance94
) {
741
      // This is a better match.
742
94
      Best = O.getName();
743
94
      BestDistance = Distance;
744
94
    }
745
191
  }
746
747
17
  return Best;
748
17
}
749
750
/// ProcessDiag - This is the method used to report a diagnostic that is
751
/// finally fully formed.
752
12.7M
bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
753
12.7M
  Diagnostic Info(&Diag);
754
755
12.7M
  assert(Diag.getClient() && "DiagnosticClient not set!");
756
757
  // Figure out the diagnostic level of this message.
758
0
  unsigned DiagID = Info.getID();
759
12.7M
  DiagnosticIDs::Level DiagLevel
760
12.7M
    = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
761
762
  // Update counts for DiagnosticErrorTrap even if a fatal error occurred
763
  // or diagnostics are suppressed.
764
12.7M
  if (DiagLevel >= DiagnosticIDs::Error) {
765
226k
    ++Diag.TrapNumErrorsOccurred;
766
226k
    if (isUnrecoverable(DiagID))
767
222k
      ++Diag.TrapNumUnrecoverableErrorsOccurred;
768
226k
  }
769
770
12.7M
  if (Diag.SuppressAllDiagnostics)
771
4.76k
    return false;
772
773
12.7M
  if (DiagLevel != DiagnosticIDs::Note) {
774
    // Record that a fatal error occurred only when we see a second
775
    // non-note diagnostic. This allows notes to be attached to the
776
    // fatal error, but suppresses any diagnostics that follow those
777
    // notes.
778
10.7M
    if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
779
139
      Diag.FatalErrorOccurred = true;
780
781
10.7M
    Diag.LastDiagLevel = DiagLevel;
782
10.7M
  }
783
784
  // If a fatal error has already been emitted, silence all subsequent
785
  // diagnostics.
786
12.7M
  if (Diag.FatalErrorOccurred) {
787
14.5k
    if (DiagLevel >= DiagnosticIDs::Error &&
788
14.5k
        
Diag.Client->IncludeInDiagnosticCounts()3.31k
) {
789
3.31k
      ++Diag.NumErrors;
790
3.31k
    }
791
792
14.5k
    return false;
793
14.5k
  }
794
795
  // If the client doesn't care about this message, don't issue it.  If this is
796
  // a note and the last real diagnostic was ignored, ignore it too.
797
12.7M
  if (DiagLevel == DiagnosticIDs::Ignored ||
798
12.7M
      
(3.73M
DiagLevel == DiagnosticIDs::Note3.73M
&&
799
3.73M
       
Diag.LastDiagLevel == DiagnosticIDs::Ignored1.98M
))
800
9.36M
    return false;
801
802
3.34M
  if (DiagLevel >= DiagnosticIDs::Error) {
803
221k
    if (isUnrecoverable(DiagID))
804
217k
      Diag.UnrecoverableErrorOccurred = true;
805
806
    // Warnings which have been upgraded to errors do not prevent compilation.
807
221k
    if (isDefaultMappingAsError(DiagID))
808
219k
      Diag.UncompilableErrorOccurred = true;
809
810
221k
    Diag.ErrorOccurred = true;
811
221k
    if (Diag.Client->IncludeInDiagnosticCounts()) {
812
221k
      ++Diag.NumErrors;
813
221k
    }
814
815
    // If we've emitted a lot of errors, emit a fatal error instead of it to
816
    // stop a flood of bogus errors.
817
221k
    if (Diag.ErrorLimit && 
Diag.NumErrors > Diag.ErrorLimit64.8k
&&
818
221k
        
DiagLevel == DiagnosticIDs::Error22
) {
819
11
      Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
820
11
      return false;
821
11
    }
822
221k
  }
823
824
  // Make sure we set FatalErrorOccurred to ensure that the notes from the
825
  // diagnostic that caused `fatal_too_many_errors` won't be emitted.
826
3.34M
  if (Diag.CurDiagID == diag::fatal_too_many_errors)
827
11
    Diag.FatalErrorOccurred = true;
828
  // Finally, report it.
829
3.34M
  EmitDiag(Diag, DiagLevel);
830
3.34M
  return true;
831
3.34M
}
832
833
3.34M
void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const {
834
3.34M
  Diagnostic Info(&Diag);
835
3.34M
  assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
836
837
0
  Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
838
3.34M
  if (Diag.Client->IncludeInDiagnosticCounts()) {
839
3.34M
    if (DiagLevel == DiagnosticIDs::Warning)
840
1.53M
      ++Diag.NumWarnings;
841
3.34M
  }
842
843
3.34M
  Diag.CurDiagID = ~0U;
844
3.34M
}
845
846
447k
bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
847
447k
  if (DiagID >= diag::DIAG_UPPER_LIMIT) {
848
406
    assert(CustomDiagInfo && "Invalid CustomDiagInfo");
849
    // Custom diagnostics.
850
0
    return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
851
406
  }
852
853
  // Only errors may be unrecoverable.
854
446k
  if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
855
3.80k
    return false;
856
857
442k
  if (DiagID == diag::err_unavailable ||
858
442k
      
DiagID == diag::err_unavailable_message442k
)
859
792
    return false;
860
861
  // Currently we consider all ARC errors as recoverable.
862
442k
  if (isARCDiagnostic(DiagID))
863
2.15k
    return false;
864
865
439k
  return true;
866
442k
}
867
868
443k
bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) {
869
443k
  unsigned cat = getCategoryNumberForDiag(DiagID);
870
443k
  return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC ");
871
443k
}