Coverage Report

Created: 2022-01-25 06:29

/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
387k
  StringRef getDescription() const {
130
387k
    size_t MyIndex = this - &StaticDiagInfo[0];
131
387k
    uint32_t StringOffset = StaticDiagInfoDescriptionOffsets[MyIndex];
132
387k
    const char* Table = reinterpret_cast<const char*>(&StaticDiagInfoDescriptions);
133
387k
    return StringRef(&Table[StringOffset], DescriptionLen);
134
387k
  }
135
136
6.12M
  diag::Flavor getFlavor() const {
137
6.12M
    return Class == CLASS_REMARK ? 
diag::Flavor::Remark2.79k
138
6.12M
                                 : 
diag::Flavor::WarningOrError6.12M
;
139
6.12M
  }
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
462M
static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
210
  // Out of bounds diag. Can't be in the table.
211
462M
  using namespace diag;
212
462M
  if (DiagID >= DIAG_UPPER_LIMIT || 
DiagID <= DIAG_START_COMMON462M
)
213
26.1k
    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
462M
  unsigned Offset = 0;
224
462M
  unsigned ID = DiagID - DIAG_START_COMMON - 1;
225
462M
#define CATEGORY(NAME, PREV) \
226
5.08G
  if (DiagID > DIAG_START_##NAME) { \
227
3.23G
    Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
228
3.23G
    ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
229
3.23G
  }
230
462M
CATEGORY(DRIVER, COMMON)
231
462M
CATEGORY(FRONTEND, DRIVER)
232
462M
CATEGORY(SERIALIZATION, FRONTEND)
233
462M
CATEGORY(LEX, SERIALIZATION)
234
462M
CATEGORY(PARSE, LEX)
235
462M
CATEGORY(AST, PARSE)
236
462M
CATEGORY(COMMENT, AST)
237
462M
CATEGORY(CROSSTU, COMMENT)
238
462M
CATEGORY(SEMA, CROSSTU)
239
462M
CATEGORY(ANALYSIS, SEMA)
240
462M
CATEGORY(REFACTORING, ANALYSIS)
241
462M
#undef CATEGORY
242
243
  // Avoid out of bounds reads.
244
462M
  if (ID + Offset >= StaticDiagInfoSize)
245
0
    return nullptr;
246
247
462M
  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
462M
  if (Found->DiagID != DiagID)
254
0
    return nullptr;
255
462M
  return Found;
256
462M
}
257
258
15.8M
static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID) {
259
15.8M
  DiagnosticMapping Info = DiagnosticMapping::Make(
260
15.8M
      diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false);
261
262
15.8M
  if (const StaticDiagInfoRec *
StaticInfo15.8M
= GetDiagInfo(DiagID)) {
263
15.8M
    Info.setSeverity((diag::Severity)StaticInfo->DefaultSeverity);
264
265
15.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
15.8M
  }
271
272
0
  return Info;
273
15.8M
}
274
275
/// getCategoryNumberForDiag - Return the category number that a specified
276
/// DiagID belongs to, or 0 if no category.
277
404k
unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
278
404k
  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
279
404k
    return Info->Category;
280
0
  return 0;
281
404k
}
282
283
namespace {
284
  // The diagnostic category names.
285
  struct StaticDiagCategoryRec {
286
    const char *NameStr;
287
    uint8_t NameLen;
288
289
402k
    StringRef getName() const {
290
402k
      return StringRef(NameStr, NameLen);
291
402k
    }
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
195M
DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) {
300
195M
  std::pair<iterator, bool> Result =
301
195M
      DiagMap.insert(std::make_pair(Diag, DiagnosticMapping()));
302
303
  // Initialize the entry if we added it.
304
195M
  if (Result.second)
305
12.1M
    Result.first->second = GetDefaultDiagMapping(Diag);
306
307
195M
  return Result.first->second;
308
195M
}
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
402k
unsigned DiagnosticIDs::getNumberOfCategories() {
320
402k
  return llvm::array_lengthof(CategoryNameTable) - 1;
321
402k
}
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
402k
StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
327
402k
  if (CategoryID >= getNumberOfCategories())
328
0
   return StringRef();
329
402k
  return CategoryNameTable[CategoryID].getName();
330
402k
}
331
332
333
334
DiagnosticIDs::SFINAEResponse
335
164k
DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
336
164k
  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
337
164k
    return static_cast<DiagnosticIDs::SFINAEResponse>(Info->SFINAE);
338
0
  return SFINAE_Report;
339
164k
}
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
386M
static unsigned getBuiltinDiagClass(unsigned DiagID) {
350
386M
  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
351
386M
    return Info->Class;
352
18.4E
  return ~0U;
353
386M
}
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
24.6k
      StringRef getDescription(unsigned DiagID) const {
370
24.6k
        assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
371
24.6k
               "Invalid diagnostic ID");
372
0
        return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
373
24.6k
      }
374
375
      /// getLevel - Return the level of the specified custom diagnostic.
376
25.0k
      DiagnosticIDs::Level getLevel(unsigned DiagID) const {
377
25.0k
        assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
378
25.0k
               "Invalid diagnostic ID");
379
0
        return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
380
25.0k
      }
381
382
      unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
383
4.39k
                                 DiagnosticIDs &Diags) {
384
4.39k
        DiagDesc D(L, std::string(Message));
385
        // Check to see if it already exists.
386
4.39k
        std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
387
4.39k
        if (I != DiagIDs.end() && 
I->first == D2.27k
)
388
401
          return I->second;
389
390
        // If not, assign a new ID.
391
3.99k
        unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
392
3.99k
        DiagIDs.insert(std::make_pair(D, ID));
393
3.99k
        DiagInfo.push_back(D);
394
3.99k
        return ID;
395
4.39k
      }
396
    };
397
398
  } // end diag namespace
399
} // end clang namespace
400
401
402
//===----------------------------------------------------------------------===//
403
// Common Diagnostic implementation
404
//===----------------------------------------------------------------------===//
405
406
381k
DiagnosticIDs::DiagnosticIDs() {}
407
408
375k
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.39k
unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) {
417
4.39k
  if (!CustomDiagInfo)
418
2.11k
    CustomDiagInfo.reset(new diag::CustomDiagInfo());
419
4.39k
  return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this);
420
4.39k
}
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.15M
bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
428
4.15M
  return DiagID < diag::DIAG_UPPER_LIMIT &&
429
4.15M
         
getBuiltinDiagClass(DiagID) != CLASS_ERROR4.15M
;
430
4.15M
}
431
432
/// Determine whether the given built-in diagnostic ID is a
433
/// Note.
434
352k
bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
435
352k
  return DiagID < diag::DIAG_UPPER_LIMIT &&
436
352k
    
getBuiltinDiagClass(DiagID) == CLASS_NOTE352k
;
437
352k
}
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
184M
                                        bool &EnabledByDefault) {
446
184M
  if (DiagID >= diag::DIAG_UPPER_LIMIT ||
447
184M
      getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
448
184M
    return false;
449
450
515k
  EnabledByDefault =
451
515k
      GetDefaultDiagMapping(DiagID).getSeverity() != diag::Severity::Ignored;
452
515k
  return true;
453
184M
}
454
455
3.20M
bool DiagnosticIDs::isDefaultMappingAsError(unsigned DiagID) {
456
3.20M
  if (DiagID >= diag::DIAG_UPPER_LIMIT)
457
178
    return false;
458
459
3.20M
  return GetDefaultDiagMapping(DiagID).getSeverity() >= diag::Severity::Error;
460
3.20M
}
461
462
/// getDescription - Given a diagnostic ID, return a description of the
463
/// issue.
464
411k
StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
465
411k
  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
466
387k
    return Info->getDescription();
467
24.6k
  assert(CustomDiagInfo && "Invalid CustomDiagInfo");
468
0
  return CustomDiagInfo->getDescription(DiagID);
469
411k
}
470
471
11.0M
static DiagnosticIDs::Level toLevel(diag::Severity SV) {
472
11.0M
  switch (SV) {
473
9.81M
  case diag::Severity::Ignored:
474
9.81M
    return DiagnosticIDs::Ignored;
475
1.03k
  case diag::Severity::Remark:
476
1.03k
    return DiagnosticIDs::Remark;
477
715k
  case diag::Severity::Warning:
478
715k
    return DiagnosticIDs::Warning;
479
506k
  case diag::Severity::Error:
480
506k
    return DiagnosticIDs::Error;
481
299
  case diag::Severity::Fatal:
482
299
    return DiagnosticIDs::Fatal;
483
11.0M
  }
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
12.5M
                                  const DiagnosticsEngine &Diag) const {
493
  // Handle custom diagnostics, which cannot be mapped.
494
12.5M
  if (DiagID >= diag::DIAG_UPPER_LIMIT) {
495
24.6k
    assert(CustomDiagInfo && "Invalid CustomDiagInfo");
496
0
    return CustomDiagInfo->getLevel(DiagID);
497
24.6k
  }
498
499
12.5M
  unsigned DiagClass = getBuiltinDiagClass(DiagID);
500
12.5M
  if (DiagClass == CLASS_NOTE) 
return DiagnosticIDs::Note1.48M
;
501
11.0M
  return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
502
12.5M
}
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
184M
                                     const DiagnosticsEngine &Diag) const {
513
184M
  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
184M
  DiagnosticsEngine::DiagState *State = Diag.GetDiagStateForLoc(Loc);
521
184M
  DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID);
522
523
  // TODO: Can a null severity really get here?
524
184M
  if (Mapping.getSeverity() != diag::Severity())
525
184M
    Result = Mapping.getSeverity();
526
527
  // Upgrade ignored diagnostics if -Weverything is enabled.
528
184M
  if (State->EnableAllWarnings && 
Result == diag::Severity::Ignored11.8k
&&
529
184M
      
!Mapping.isUser()10.8k
&&
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
184M
  bool EnabledByDefault = false;
536
184M
  bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
537
184M
  if (Diag.AllExtensionsSilenced && 
IsExtensionDiag424k
&&
!EnabledByDefault16.1k
)
538
16.1k
    return diag::Severity::Ignored;
539
540
  // For extension diagnostics that haven't been explicitly mapped, check if we
541
  // should upgrade the diagnostic.
542
184M
  if (IsExtensionDiag && 
!Mapping.isUser()499k
)
543
493k
    Result = std::max(Result, State->ExtBehavior);
544
545
  // At this point, ignored errors can no longer be upgraded.
546
184M
  if (Result == diag::Severity::Ignored)
547
168M
    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
15.7M
  if (State->IgnoreAllWarnings) {
555
343k
    if (Result == diag::Severity::Warning ||
556
343k
        
(2.52k
Result >= diag::Severity::Error2.52k
&&
557
2.52k
         
!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
15.3M
  if (Result == diag::Severity::Warning) {
563
14.8M
    if (State->WarningsAsErrors && 
!Mapping.hasNoWarningAsError()2.63M
)
564
2.63M
      Result = diag::Severity::Error;
565
14.8M
  }
566
567
  // If -Wfatal-errors is enabled, map errors to fatal unless explicitly
568
  // disabled.
569
15.3M
  if (Result == diag::Severity::Error) {
570
3.20M
    if (State->ErrorsAsFatal && 
!Mapping.hasNoErrorAsFatal()7
)
571
7
      Result = diag::Severity::Fatal;
572
3.20M
  }
573
574
  // If explicitly requested, map fatal errors to errors.
575
15.3M
  if (Result == diag::Severity::Fatal &&
576
15.3M
      
Diag.CurDiagID != diag::fatal_too_many_errors332
&&
Diag.FatalsAsError322
)
577
12
    Result = diag::Severity::Error;
578
579
  // Custom diagnostics always are emitted in system headers.
580
15.3M
  bool ShowInSystemHeader =
581
15.3M
      
!GetDiagInfo(DiagID)15.3M
|| 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
15.3M
  if (State->SuppressSystemWarnings && 
!ShowInSystemHeader14.7M
&&
Loc.isValid()14.2M
&&
587
15.3M
      Diag.getSourceManager().isInSystemHeader(
588
10.0M
          Diag.getSourceManager().getExpansionLoc(Loc)))
589
4.32M
    return diag::Severity::Ignored;
590
591
  // We also ignore warnings due to system macros
592
11.0M
  bool ShowInSystemMacro =
593
11.0M
      
!GetDiagInfo(DiagID)11.0M
|| GetDiagInfo(DiagID)->WarnShowInSystemMacro;
594
11.0M
  if (State->SuppressSystemWarnings && 
!ShowInSystemMacro10.4M
&&
Loc.isValid()544
&&
595
11.0M
      
Diag.getSourceManager().isInSystemMacro(Loc)544
)
596
5
    return diag::Severity::Ignored;
597
598
11.0M
  return Result;
599
11.0M
}
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.51M
    StringRef getName() const {
613
5.51M
      return StringRef(DiagGroupNames + NameOffset + 1,
614
5.51M
                       DiagGroupNames[NameOffset]);
615
5.51M
    }
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
/// getWarningOptionForDiag - Return the lowest-level warning option that
632
/// enables the specified diagnostic.  If there is no -Wfoo flag that controls
633
/// the diagnostic, this returns null.
634
37.9k
StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
635
37.9k
  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
636
36.4k
    return getWarningOptionForGroup(
637
36.4k
        static_cast<diag::Group>(Info->getOptionGroupIndex()));
638
1.47k
  return StringRef();
639
37.9k
}
640
641
12
std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() {
642
12
  std::vector<std::string> Res;
643
11.1k
  for (size_t I = 1; DiagGroupNames[I] != '\0';) {
644
11.1k
    std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]);
645
11.1k
    I += DiagGroupNames[I] + 1;
646
11.1k
    Res.push_back("-W" + Diag);
647
11.1k
    Res.push_back("-Wno-" + Diag);
648
11.1k
  }
649
650
12
  return Res;
651
12
}
652
653
/// Return \c true if any diagnostics were found in this group, even if they
654
/// were filtered out due to having the wrong flavor.
655
static bool getDiagnosticsInGroup(diag::Flavor Flavor,
656
                                  const WarningOption *Group,
657
1.89M
                                  SmallVectorImpl<diag::kind> &Diags) {
658
  // An empty group is considered to be a warning group: we have empty groups
659
  // for GCC compatibility, and GCC does not have remarks.
660
1.89M
  if (!Group->Members && 
!Group->SubGroups75.7k
)
661
18.9k
    return Flavor == diag::Flavor::Remark;
662
663
1.87M
  bool NotFound = true;
664
665
  // Add the members of the option diagnostic set.
666
1.87M
  const int16_t *Member = DiagArrays + Group->Members;
667
7.74M
  for (; *Member != -1; 
++Member5.86M
) {
668
5.86M
    if (GetDiagInfo(*Member)->getFlavor() == Flavor) {
669
5.85M
      NotFound = false;
670
5.85M
      Diags.push_back(*Member);
671
5.85M
    }
672
5.86M
  }
673
674
  // Add the members of the subgroups.
675
1.87M
  const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
676
3.27M
  for (; *SubGroups != (int16_t)-1; 
++SubGroups1.39M
)
677
1.39M
    NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
678
1.39M
                                      Diags);
679
680
1.87M
  return NotFound;
681
1.89M
}
682
683
bool
684
DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
685
498k
                                     SmallVectorImpl<diag::kind> &Diags) const {
686
498k
  auto Found = llvm::partition_point(
687
4.96M
      OptionTable, [=](const WarningOption &O) { return O.getName() < Group; });
688
498k
  if (Found == std::end(OptionTable) || 
Found->getName() != Group498k
)
689
60
    return true; // Option not found.
690
691
498k
  return ::getDiagnosticsInGroup(Flavor, Found, Diags);
692
498k
}
693
694
void DiagnosticIDs::getAllDiagnostics(diag::Flavor Flavor,
695
44
                                      std::vector<diag::kind> &Diags) {
696
257k
  for (unsigned i = 0; i != StaticDiagInfoSize; 
++i257k
)
697
257k
    if (StaticDiagInfo[i].getFlavor() == Flavor)
698
204k
      Diags.push_back(StaticDiagInfo[i].DiagID);
699
44
}
700
701
StringRef DiagnosticIDs::getNearestOption(diag::Flavor Flavor,
702
18
                                          StringRef Group) {
703
18
  StringRef Best;
704
18
  unsigned BestDistance = Group.size() + 1; // Maximum threshold.
705
16.7k
  for (const WarningOption &O : OptionTable) {
706
    // Don't suggest ignored warning flags.
707
16.7k
    if (!O.Members && 
!O.SubGroups2.16k
)
708
684
      continue;
709
710
16.0k
    unsigned Distance = O.getName().edit_distance(Group, true, BestDistance);
711
16.0k
    if (Distance > BestDistance)
712
14.9k
      continue;
713
714
    // Don't suggest groups that are not of this kind.
715
1.05k
    llvm::SmallVector<diag::kind, 8> Diags;
716
1.05k
    if (::getDiagnosticsInGroup(Flavor, &O, Diags) || 
Diags.empty()198
)
717
860
      continue;
718
719
198
    if (Distance == BestDistance) {
720
      // Two matches with the same distance, don't prefer one over the other.
721
98
      Best = "";
722
100
    } else if (Distance < BestDistance) {
723
      // This is a better match.
724
100
      Best = O.getName();
725
100
      BestDistance = Distance;
726
100
    }
727
198
  }
728
729
18
  return Best;
730
18
}
731
732
/// ProcessDiag - This is the method used to report a diagnostic that is
733
/// finally fully formed.
734
9.37M
bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
735
9.37M
  Diagnostic Info(&Diag);
736
737
9.37M
  assert(Diag.getClient() && "DiagnosticClient not set!");
738
739
  // Figure out the diagnostic level of this message.
740
0
  unsigned DiagID = Info.getID();
741
9.37M
  DiagnosticIDs::Level DiagLevel
742
9.37M
    = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
743
744
  // Update counts for DiagnosticErrorTrap even if a fatal error occurred
745
  // or diagnostics are suppressed.
746
9.37M
  if (DiagLevel >= DiagnosticIDs::Error) {
747
205k
    ++Diag.TrapNumErrorsOccurred;
748
205k
    if (isUnrecoverable(DiagID))
749
202k
      ++Diag.TrapNumUnrecoverableErrorsOccurred;
750
205k
  }
751
752
9.37M
  if (Diag.SuppressAllDiagnostics)
753
4.85k
    return false;
754
755
9.37M
  if (DiagLevel != DiagnosticIDs::Note) {
756
    // Record that a fatal error occurred only when we see a second
757
    // non-note diagnostic. This allows notes to be attached to the
758
    // fatal error, but suppresses any diagnostics that follow those
759
    // notes.
760
8.28M
    if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
761
135
      Diag.FatalErrorOccurred = true;
762
763
8.28M
    Diag.LastDiagLevel = DiagLevel;
764
8.28M
  }
765
766
  // If a fatal error has already been emitted, silence all subsequent
767
  // diagnostics.
768
9.37M
  if (Diag.FatalErrorOccurred) {
769
13.3k
    if (DiagLevel >= DiagnosticIDs::Error &&
770
13.3k
        
Diag.Client->IncludeInDiagnosticCounts()3.51k
) {
771
3.51k
      ++Diag.NumErrors;
772
3.51k
    }
773
774
13.3k
    return false;
775
13.3k
  }
776
777
  // If the client doesn't care about this message, don't issue it.  If this is
778
  // a note and the last real diagnostic was ignored, ignore it too.
779
9.35M
  if (DiagLevel == DiagnosticIDs::Ignored ||
780
9.35M
      
(1.95M
DiagLevel == DiagnosticIDs::Note1.95M
&&
781
1.95M
       
Diag.LastDiagLevel == DiagnosticIDs::Ignored1.08M
))
782
7.77M
    return false;
783
784
1.57M
  if (DiagLevel >= DiagnosticIDs::Error) {
785
200k
    if (isUnrecoverable(DiagID))
786
197k
      Diag.UnrecoverableErrorOccurred = true;
787
788
    // Warnings which have been upgraded to errors do not prevent compilation.
789
200k
    if (isDefaultMappingAsError(DiagID))
790
199k
      Diag.UncompilableErrorOccurred = true;
791
792
200k
    Diag.ErrorOccurred = true;
793
200k
    if (Diag.Client->IncludeInDiagnosticCounts()) {
794
200k
      ++Diag.NumErrors;
795
200k
    }
796
797
    // If we've emitted a lot of errors, emit a fatal error instead of it to
798
    // stop a flood of bogus errors.
799
200k
    if (Diag.ErrorLimit && 
Diag.NumErrors > Diag.ErrorLimit55.3k
&&
800
200k
        
DiagLevel == DiagnosticIDs::Error20
) {
801
10
      Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
802
10
      return false;
803
10
    }
804
200k
  }
805
806
  // Make sure we set FatalErrorOccurred to ensure that the notes from the
807
  // diagnostic that caused `fatal_too_many_errors` won't be emitted.
808
1.57M
  if (Diag.CurDiagID == diag::fatal_too_many_errors)
809
10
    Diag.FatalErrorOccurred = true;
810
  // Finally, report it.
811
1.57M
  EmitDiag(Diag, DiagLevel);
812
1.57M
  return true;
813
1.57M
}
814
815
1.57M
void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const {
816
1.57M
  Diagnostic Info(&Diag);
817
1.57M
  assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
818
819
0
  Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
820
1.57M
  if (Diag.Client->IncludeInDiagnosticCounts()) {
821
1.57M
    if (DiagLevel == DiagnosticIDs::Warning)
822
666k
      ++Diag.NumWarnings;
823
1.57M
  }
824
825
1.57M
  Diag.CurDiagID = ~0U;
826
1.57M
}
827
828
406k
bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
829
406k
  if (DiagID >= diag::DIAG_UPPER_LIMIT) {
830
352
    assert(CustomDiagInfo && "Invalid CustomDiagInfo");
831
    // Custom diagnostics.
832
0
    return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
833
352
  }
834
835
  // Only errors may be unrecoverable.
836
405k
  if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
837
3.77k
    return false;
838
839
402k
  if (DiagID == diag::err_unavailable ||
840
402k
      
DiagID == diag::err_unavailable_message401k
)
841
790
    return false;
842
843
  // Currently we consider all ARC errors as recoverable.
844
401k
  if (isARCDiagnostic(DiagID))
845
2.15k
    return false;
846
847
399k
  return true;
848
401k
}
849
850
402k
bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) {
851
402k
  unsigned cat = getCategoryNumberForDiag(DiagID);
852
402k
  return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC ");
853
402k
}