Skip to content

Commit eae83fd

Browse files
committed
[rulesets] Allow rule severity to be controlled by pragma directives (#9)
* Allow rule severity to be controlled by pragma directives * Rename DiagnosticIDs.Unreal.cpp
1 parent d21768c commit eae83fd

File tree

7 files changed

+304
-139
lines changed

7 files changed

+304
-139
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
unsigned getCustomDiagID(Level L, StringRef FormatString, StringRef Name);
2+
bool getExistingCustomDiagIDs(StringRef Name,
3+
SmallVectorImpl<diag::kind> &Diags);
4+
std::optional<unsigned> getExistingCustomDiagID(StringRef Name,
5+
Level L);

clang/include/clang/Basic/DiagnosticIDs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
200200
// writing, nearly all callers of this function were invalid.
201201
unsigned getCustomDiagID(Level L, StringRef FormatString);
202202

203+
// @unreal: BEGIN
204+
#include "DiagnosticIDs.Unreal.h"
205+
// @unreal: END
206+
203207
//===--------------------------------------------------------------------===//
204208
// Diagnostic classification and reporting interfaces.
205209
//

clang/lib/Basic/Diagnostic.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,10 @@ void DiagnosticsEngine::PushDiagStatePoint(DiagState *State,
353353

354354
void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map,
355355
SourceLocation L) {
356-
assert(Diag < diag::DIAG_UPPER_LIMIT &&
357-
"Can only map builtin diagnostics");
356+
// @unreal: BEGIN
357+
// assert(Diag < diag::DIAG_UPPER_LIMIT &&
358+
// "Can only map builtin diagnostics");
359+
// @unreal: END
358360
assert((Diags->isBuiltinWarningOrExtension(Diag) ||
359361
(Map == diag::Severity::Fatal || Map == diag::Severity::Error)) &&
360362
"Cannot map errors into warnings!");
@@ -404,7 +406,10 @@ bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor,
404406
// Get the diagnostics in this group.
405407
SmallVector<diag::kind, 256> GroupDiags;
406408
if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
407-
return true;
409+
// @unreal: BEGIN
410+
if (Diags->getExistingCustomDiagIDs(Group, GroupDiags))
411+
// @unreal: END
412+
return true;
408413

409414
// Set the mapping.
410415
for (diag::kind Diag : GroupDiags)
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
namespace clang {
2+
namespace diag {
3+
class CustomDiagInfoEntry {
4+
public:
5+
DiagnosticIDs::Level Level;
6+
std::string Name;
7+
std::string Description;
8+
unsigned DiagID;
9+
10+
CustomDiagInfoEntry() {}
11+
CustomDiagInfoEntry(DiagnosticIDs::Level InLevel, std::string InName,
12+
std::string InDescription, unsigned InDiagID)
13+
: Level(InLevel), Name(InName), Description(InDescription),
14+
DiagID(InDiagID) {}
15+
};
16+
17+
class CustomDiagInfo {
18+
std::vector<CustomDiagInfoEntry> DiagInfo;
19+
llvm::StringMap<std::vector<CustomDiagInfoEntry>> DiagInfoByName;
20+
21+
public:
22+
/// getName - Return the name of the specified custom
23+
/// diagnostic.
24+
StringRef getName(unsigned DiagID) const {
25+
assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
26+
"Invalid diagnostic ID");
27+
return DiagInfo[DiagID - DIAG_UPPER_LIMIT].Name;
28+
}
29+
30+
/// getDescription - Return the description of the specified custom
31+
/// diagnostic.
32+
StringRef getDescription(unsigned DiagID) const {
33+
assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
34+
"Invalid diagnostic ID");
35+
return DiagInfo[DiagID - DIAG_UPPER_LIMIT].Description;
36+
}
37+
38+
/// getLevel - Return the level of the specified custom diagnostic.
39+
DiagnosticIDs::Level getLevel(unsigned DiagID) const {
40+
assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
41+
"Invalid diagnostic ID");
42+
return DiagInfo[DiagID - DIAG_UPPER_LIMIT].Level;
43+
}
44+
45+
std::optional<unsigned> tryGetDiagID(StringRef Name,
46+
DiagnosticIDs::Level L) const {
47+
auto It = this->DiagInfoByName.find(Name);
48+
if (It == this->DiagInfoByName.end()) {
49+
return std::optional<unsigned>();
50+
}
51+
for (const auto &E : It->getValue()) {
52+
if (E.Level == L) {
53+
return E.DiagID;
54+
}
55+
}
56+
return std::optional<unsigned>();
57+
}
58+
59+
bool tryGetDiagIDs(StringRef Name, SmallVectorImpl<diag::kind> &Diags) const {
60+
auto It = this->DiagInfoByName.find(Name);
61+
if (It == this->DiagInfoByName.end()) {
62+
return false;
63+
}
64+
for (const auto &E : It->getValue()) {
65+
Diags.push_back(E.DiagID);
66+
}
67+
return true;
68+
}
69+
70+
unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
71+
DiagnosticIDs &Diags, StringRef *Name = nullptr) {
72+
// Check to see if it already exists.
73+
StringRef NameResolved =
74+
Name == nullptr ? std::to_string(llvm::xxHash64(Message)) : *Name;
75+
auto It = this->DiagInfoByName.find(NameResolved);
76+
if (It != this->DiagInfoByName.end()) {
77+
for (const auto &E : It->getValue()) {
78+
if (E.Level == L) {
79+
return E.DiagID;
80+
}
81+
}
82+
}
83+
84+
// If not, assign a new ID.
85+
unsigned ID = this->DiagInfo.size() + DIAG_UPPER_LIMIT;
86+
auto Entry = CustomDiagInfoEntry(L, NameResolved.str(), Message.str(), ID);
87+
this->DiagInfo.push_back(Entry);
88+
this->DiagInfoByName[NameResolved].push_back(Entry);
89+
return ID;
90+
}
91+
};
92+
93+
} // namespace diag
94+
} // namespace clang
95+
96+
unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString,
97+
StringRef Name) {
98+
if (!CustomDiagInfo)
99+
CustomDiagInfo.reset(new diag::CustomDiagInfo());
100+
return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this, &Name);
101+
}
102+
103+
bool DiagnosticIDs::getExistingCustomDiagIDs(
104+
StringRef Name, SmallVectorImpl<diag::kind> &Diags) {
105+
if (!CustomDiagInfo) {
106+
CustomDiagInfo.reset(new diag::CustomDiagInfo());
107+
}
108+
return !CustomDiagInfo->tryGetDiagIDs(Name, Diags);
109+
}
110+
111+
std::optional<unsigned> DiagnosticIDs::getExistingCustomDiagID(StringRef Name,
112+
Level L) {
113+
if (!CustomDiagInfo) {
114+
CustomDiagInfo.reset(new diag::CustomDiagInfo());
115+
}
116+
return CustomDiagInfo->tryGetDiagID(Name, L);
117+
}

clang/lib/Basic/DiagnosticIDs.cpp

Lines changed: 15 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
#include "llvm/Support/ErrorHandling.h"
2020
#include <map>
2121
#include <optional>
22+
// @unreal: BEGIN
23+
#include "llvm/Support/xxhash.h"
24+
// @unreal: END
2225
using namespace clang;
2326

2427
//===----------------------------------------------------------------------===//
@@ -183,7 +186,7 @@ const StaticDiagInfoRec StaticDiagInfo[] = {
183186
SHOWINSYSHEADER, \
184187
SHOWINSYSMACRO, \
185188
GROUP, \
186-
DEFERRABLE, \
189+
DEFERRABLE, \
187190
STR_SIZE(DESC, uint16_t)},
188191
#include "clang/Basic/DiagnosticCommonKinds.inc"
189192
#include "clang/Basic/DiagnosticDriverKinds.inc"
@@ -342,48 +345,11 @@ static unsigned getBuiltinDiagClass(unsigned DiagID) {
342345
// Custom Diagnostic information
343346
//===----------------------------------------------------------------------===//
344347

345-
namespace clang {
346-
namespace diag {
347-
class CustomDiagInfo {
348-
typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
349-
std::vector<DiagDesc> DiagInfo;
350-
std::map<DiagDesc, unsigned> DiagIDs;
351-
public:
352-
353-
/// getDescription - Return the description of the specified custom
354-
/// diagnostic.
355-
StringRef getDescription(unsigned DiagID) const {
356-
assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
357-
"Invalid diagnostic ID");
358-
return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
359-
}
360-
361-
/// getLevel - Return the level of the specified custom diagnostic.
362-
DiagnosticIDs::Level getLevel(unsigned DiagID) const {
363-
assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
364-
"Invalid diagnostic ID");
365-
return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
366-
}
367-
368-
unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
369-
DiagnosticIDs &Diags) {
370-
DiagDesc D(L, std::string(Message));
371-
// Check to see if it already exists.
372-
std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
373-
if (I != DiagIDs.end() && I->first == D)
374-
return I->second;
375-
376-
// If not, assign a new ID.
377-
unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
378-
DiagIDs.insert(std::make_pair(D, ID));
379-
DiagInfo.push_back(D);
380-
return ID;
381-
}
382-
};
383-
384-
} // end diag namespace
385-
} // end clang namespace
386-
348+
// @unreal: BEGIN
349+
// @note: We've replaced custom diagnostic information entirely
350+
// so we can support silencing ruleset rules via pragmas.
351+
#include "DiagnosticIDs.UnrealImpl.h"
352+
// @unreal: END
387353

388354
//===----------------------------------------------------------------------===//
389355
// Common Diagnostic implementation
@@ -479,6 +445,12 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
479445
// Handle custom diagnostics, which cannot be mapped.
480446
if (DiagID >= diag::DIAG_UPPER_LIMIT) {
481447
assert(CustomDiagInfo && "Invalid CustomDiagInfo");
448+
// @unreal: BEGIN
449+
auto CustomSeverity = getDiagnosticSeverity(DiagID, Loc, Diag);
450+
if (CustomSeverity != diag::Severity::Fatal) {
451+
return toLevel(CustomSeverity);
452+
}
453+
// @unreal: END
482454
return CustomDiagInfo->getLevel(DiagID);
483455
}
484456

0 commit comments

Comments
 (0)