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+ }
0 commit comments