Skip to content

Commit

Permalink
[rulesets] Allow rule severity to be controlled by pragma directives (#9
Browse files Browse the repository at this point in the history
)

* Allow rule severity to be controlled by pragma directives

* Rename DiagnosticIDs.Unreal.cpp
  • Loading branch information
hach-que committed Oct 5, 2024
1 parent d21768c commit eae83fd
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 139 deletions.
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/DiagnosticIDs.Unreal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
unsigned getCustomDiagID(Level L, StringRef FormatString, StringRef Name);
bool getExistingCustomDiagIDs(StringRef Name,
SmallVectorImpl<diag::kind> &Diags);
std::optional<unsigned> getExistingCustomDiagID(StringRef Name,
Level L);
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticIDs.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
// writing, nearly all callers of this function were invalid.
unsigned getCustomDiagID(Level L, StringRef FormatString);

// @unreal: BEGIN
#include "DiagnosticIDs.Unreal.h"
// @unreal: END

//===--------------------------------------------------------------------===//
// Diagnostic classification and reporting interfaces.
//
Expand Down
11 changes: 8 additions & 3 deletions clang/lib/Basic/Diagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,10 @@ void DiagnosticsEngine::PushDiagStatePoint(DiagState *State,

void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map,
SourceLocation L) {
assert(Diag < diag::DIAG_UPPER_LIMIT &&
"Can only map builtin diagnostics");
// @unreal: BEGIN
// assert(Diag < diag::DIAG_UPPER_LIMIT &&
// "Can only map builtin diagnostics");
// @unreal: END
assert((Diags->isBuiltinWarningOrExtension(Diag) ||
(Map == diag::Severity::Fatal || Map == diag::Severity::Error)) &&
"Cannot map errors into warnings!");
Expand Down Expand Up @@ -404,7 +406,10 @@ bool DiagnosticsEngine::setSeverityForGroup(diag::Flavor Flavor,
// Get the diagnostics in this group.
SmallVector<diag::kind, 256> GroupDiags;
if (Diags->getDiagnosticsInGroup(Flavor, Group, GroupDiags))
return true;
// @unreal: BEGIN
if (Diags->getExistingCustomDiagIDs(Group, GroupDiags))
// @unreal: END
return true;

// Set the mapping.
for (diag::kind Diag : GroupDiags)
Expand Down
117 changes: 117 additions & 0 deletions clang/lib/Basic/DiagnosticIDs.UnrealImpl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
namespace clang {
namespace diag {
class CustomDiagInfoEntry {
public:
DiagnosticIDs::Level Level;
std::string Name;
std::string Description;
unsigned DiagID;

CustomDiagInfoEntry() {}
CustomDiagInfoEntry(DiagnosticIDs::Level InLevel, std::string InName,
std::string InDescription, unsigned InDiagID)
: Level(InLevel), Name(InName), Description(InDescription),
DiagID(InDiagID) {}
};

class CustomDiagInfo {
std::vector<CustomDiagInfoEntry> DiagInfo;
llvm::StringMap<std::vector<CustomDiagInfoEntry>> DiagInfoByName;

public:
/// getName - Return the name of the specified custom
/// diagnostic.
StringRef getName(unsigned DiagID) const {
assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
"Invalid diagnostic ID");
return DiagInfo[DiagID - DIAG_UPPER_LIMIT].Name;
}

/// getDescription - Return the description of the specified custom
/// diagnostic.
StringRef getDescription(unsigned DiagID) const {
assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
"Invalid diagnostic ID");
return DiagInfo[DiagID - DIAG_UPPER_LIMIT].Description;
}

/// getLevel - Return the level of the specified custom diagnostic.
DiagnosticIDs::Level getLevel(unsigned DiagID) const {
assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
"Invalid diagnostic ID");
return DiagInfo[DiagID - DIAG_UPPER_LIMIT].Level;
}

std::optional<unsigned> tryGetDiagID(StringRef Name,
DiagnosticIDs::Level L) const {
auto It = this->DiagInfoByName.find(Name);
if (It == this->DiagInfoByName.end()) {
return std::optional<unsigned>();
}
for (const auto &E : It->getValue()) {
if (E.Level == L) {
return E.DiagID;
}
}
return std::optional<unsigned>();
}

bool tryGetDiagIDs(StringRef Name, SmallVectorImpl<diag::kind> &Diags) const {
auto It = this->DiagInfoByName.find(Name);
if (It == this->DiagInfoByName.end()) {
return false;
}
for (const auto &E : It->getValue()) {
Diags.push_back(E.DiagID);
}
return true;
}

unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
DiagnosticIDs &Diags, StringRef *Name = nullptr) {
// Check to see if it already exists.
StringRef NameResolved =
Name == nullptr ? std::to_string(llvm::xxHash64(Message)) : *Name;
auto It = this->DiagInfoByName.find(NameResolved);
if (It != this->DiagInfoByName.end()) {
for (const auto &E : It->getValue()) {
if (E.Level == L) {
return E.DiagID;
}
}
}

// If not, assign a new ID.
unsigned ID = this->DiagInfo.size() + DIAG_UPPER_LIMIT;
auto Entry = CustomDiagInfoEntry(L, NameResolved.str(), Message.str(), ID);
this->DiagInfo.push_back(Entry);
this->DiagInfoByName[NameResolved].push_back(Entry);
return ID;
}
};

} // namespace diag
} // namespace clang

unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString,
StringRef Name) {
if (!CustomDiagInfo)
CustomDiagInfo.reset(new diag::CustomDiagInfo());
return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this, &Name);
}

bool DiagnosticIDs::getExistingCustomDiagIDs(
StringRef Name, SmallVectorImpl<diag::kind> &Diags) {
if (!CustomDiagInfo) {
CustomDiagInfo.reset(new diag::CustomDiagInfo());
}
return !CustomDiagInfo->tryGetDiagIDs(Name, Diags);
}

std::optional<unsigned> DiagnosticIDs::getExistingCustomDiagID(StringRef Name,
Level L) {
if (!CustomDiagInfo) {
CustomDiagInfo.reset(new diag::CustomDiagInfo());
}
return CustomDiagInfo->tryGetDiagID(Name, L);
}
58 changes: 15 additions & 43 deletions clang/lib/Basic/DiagnosticIDs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
#include "llvm/Support/ErrorHandling.h"
#include <map>
#include <optional>
// @unreal: BEGIN
#include "llvm/Support/xxhash.h"
// @unreal: END
using namespace clang;

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -183,7 +186,7 @@ const StaticDiagInfoRec StaticDiagInfo[] = {
SHOWINSYSHEADER, \
SHOWINSYSMACRO, \
GROUP, \
DEFERRABLE, \
DEFERRABLE, \
STR_SIZE(DESC, uint16_t)},
#include "clang/Basic/DiagnosticCommonKinds.inc"
#include "clang/Basic/DiagnosticDriverKinds.inc"
Expand Down Expand Up @@ -342,48 +345,11 @@ static unsigned getBuiltinDiagClass(unsigned DiagID) {
// Custom Diagnostic information
//===----------------------------------------------------------------------===//

namespace clang {
namespace diag {
class CustomDiagInfo {
typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
std::vector<DiagDesc> DiagInfo;
std::map<DiagDesc, unsigned> DiagIDs;
public:

/// getDescription - Return the description of the specified custom
/// diagnostic.
StringRef getDescription(unsigned DiagID) const {
assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
"Invalid diagnostic ID");
return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
}

/// getLevel - Return the level of the specified custom diagnostic.
DiagnosticIDs::Level getLevel(unsigned DiagID) const {
assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
"Invalid diagnostic ID");
return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
}

unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
DiagnosticIDs &Diags) {
DiagDesc D(L, std::string(Message));
// Check to see if it already exists.
std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
if (I != DiagIDs.end() && I->first == D)
return I->second;

// If not, assign a new ID.
unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
DiagIDs.insert(std::make_pair(D, ID));
DiagInfo.push_back(D);
return ID;
}
};

} // end diag namespace
} // end clang namespace

// @unreal: BEGIN
// @note: We've replaced custom diagnostic information entirely
// so we can support silencing ruleset rules via pragmas.
#include "DiagnosticIDs.UnrealImpl.h"
// @unreal: END

//===----------------------------------------------------------------------===//
// Common Diagnostic implementation
Expand Down Expand Up @@ -479,6 +445,12 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
// Handle custom diagnostics, which cannot be mapped.
if (DiagID >= diag::DIAG_UPPER_LIMIT) {
assert(CustomDiagInfo && "Invalid CustomDiagInfo");
// @unreal: BEGIN
auto CustomSeverity = getDiagnosticSeverity(DiagID, Loc, Diag);
if (CustomSeverity != diag::Severity::Fatal) {
return toLevel(CustomSeverity);
}
// @unreal: END
return CustomDiagInfo->getLevel(DiagID);
}

Expand Down
Loading

0 comments on commit eae83fd

Please sign in to comment.