Coverage Report

Created: 2021-09-21 08:58

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