Skip to content

Commit 6d5e70b

Browse files
authored
Merge pull request #10326 from DougGregor/serialized-diag-category-url-20240723
[Serialized diagnostics] Encode category documentation URL in existing record
2 parents 99830f3 + 8304ed7 commit 6d5e70b

File tree

10 files changed

+81
-7
lines changed

10 files changed

+81
-7
lines changed

clang/include/clang-c/CXDiagnostic.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,14 @@ clang_getDiagnosticCategoryName(unsigned Category);
338338
*/
339339
CINDEX_LINKAGE CXString clang_getDiagnosticCategoryText(CXDiagnostic);
340340

341+
/**
342+
* Retrieve the diagnostic category's URL for a given diagnostic.
343+
*
344+
* \returns The URL that provides additional documentation for the
345+
* category of this diagnostic.
346+
*/
347+
CINDEX_LINKAGE CXString clang_getDiagnosticCategoryURL(CXDiagnostic);
348+
341349
/**
342350
* Determine the number of source ranges associated with the given
343351
* diagnostic.

clang/include/clang/Frontend/SerializedDiagnosticReader.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,21 @@ class SerializedDiagnosticReader {
8989
virtual std::error_code visitEndOfDiagnostic() { return {}; }
9090

9191
/// Visit a category. This associates the category \c ID to a \c Name.
92+
///
93+
/// This entrypoint has been superseded by the overload that follows, which
94+
/// also takes a (possibly-empty) URL providing additional documentation for
95+
/// the category.
9296
virtual std::error_code visitCategoryRecord(unsigned ID, StringRef Name) {
9397
return {};
9498
}
9599

100+
/// Visit a category. This associates the category \c ID to a \c Name with
101+
/// a (possibly empty) URL.
102+
virtual std::error_code visitCategoryRecord(unsigned ID, StringRef Name,
103+
StringRef URL) {
104+
return visitCategoryRecord(ID, Name);
105+
}
106+
96107
/// Visit a flag. This associates the flag's \c ID to a \c Name.
97108
virtual std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) {
98109
return {};

clang/lib/Frontend/SerializedDiagnosticReader.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,13 +266,28 @@ SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
266266
continue;
267267

268268
switch ((RecordIDs)RecID) {
269-
case RECORD_CATEGORY:
269+
case RECORD_CATEGORY: {
270270
// A category has ID and name size.
271271
if (Record.size() != 2)
272272
return SDError::MalformedDiagnosticRecord;
273-
if ((EC = visitCategoryRecord(Record[0], Blob)))
273+
274+
// Make sure the name size makes sense.
275+
unsigned NameLen = Record[1];
276+
if (NameLen > Blob.size())
277+
return SDError::MalformedDiagnosticRecord;
278+
279+
StringRef Name = Blob.substr(0, NameLen);
280+
StringRef URL;
281+
282+
// If the name didn't take up the full blob, and the character that
283+
// follows it is an '@', the rest is the category URL.
284+
if (NameLen < Blob.size() && Blob[NameLen] == '@')
285+
URL = Blob.substr(NameLen + 1);
286+
287+
if ((EC = visitCategoryRecord(Record[0], Name, URL)))
274288
return EC;
275289
continue;
290+
}
276291
case RECORD_DIAG:
277292
// A diagnostic has severity, location (4), category, flag, and message
278293
// size.

clang/tools/c-index-test/c-index-test.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4803,9 +4803,10 @@ static void printDiagnosticSet(
48034803
CXSourceLocation DiagLoc;
48044804
CXDiagnostic D;
48054805
CXFile File;
4806-
CXString FileName, DiagSpelling, DiagOption, DiagCat;
4806+
CXString FileName, DiagSpelling, DiagOption, DiagCat, DiagCatURL;
48074807
unsigned line, column, offset;
4808-
const char *FileNameStr = 0, *DiagOptionStr = 0, *DiagCatStr = 0;
4808+
const char *FileNameStr = 0, *DiagOptionStr = 0, *DiagCatStr = 0,
4809+
*DiagCatURLStr = 0;
48094810
const char *FileContents = 0;
48104811

48114812
D = clang_getDiagnosticInSet(Diags, i);
@@ -4863,13 +4864,20 @@ static void printDiagnosticSet(
48634864
fprintf(stderr, "%s\nEND CONTENTS OF FILE\n", FileContents);
48644865
}
48654866

4867+
DiagCatURL = clang_getDiagnosticCategoryURL(D);
4868+
DiagCatURLStr = clang_getCString(DiagCatURL);
4869+
if (DiagCatURLStr && DiagCatStr && DiagCatURLStr[0]) {
4870+
fprintf(stderr, "[%s]: <%s>\n", DiagCatStr, DiagCatURLStr);
4871+
}
4872+
48664873
/* Print subdiagnostics. */
48674874
printDiagnosticSet(clang_getChildDiagnostics(D), indent+2, TopDiags);
48684875

48694876
clang_disposeString(FileName);
48704877
clang_disposeString(DiagSpelling);
48714878
clang_disposeString(DiagOption);
48724879
clang_disposeString(DiagCat);
4880+
clang_disposeString(DiagCatURL);
48734881
}
48744882
}
48754883

clang/tools/libclang/CIndexDiagnostic.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class CXDiagnosticCustomNoteImpl : public CXDiagnosticImpl {
7070

7171
unsigned getCategory() const override { return 0; }
7272
CXString getCategoryText() const override { return cxstring::createEmpty(); }
73+
CXString getCategoryURL() const override { return cxstring::createEmpty(); }
7374

7475
unsigned getNumRanges() const override { return 0; }
7576
CXSourceRange getRange(unsigned Range) const override {
@@ -430,7 +431,13 @@ CXString clang_getDiagnosticCategoryText(CXDiagnostic Diag) {
430431
return D->getCategoryText();
431432
return cxstring::createEmpty();
432433
}
433-
434+
435+
CXString clang_getDiagnosticCategoryURL(CXDiagnostic Diag) {
436+
if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
437+
return D->getCategoryURL();
438+
return cxstring::createEmpty();
439+
}
440+
434441
unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
435442
if (CXDiagnosticImpl *D = static_cast<CXDiagnosticImpl *>(Diag))
436443
return D->getNumRanges();

clang/tools/libclang/CIndexDiagnostic.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ class CXDiagnosticImpl {
9999
/// Return the category string of the diagnostic.
100100
virtual CXString getCategoryText() const = 0;
101101

102+
/// Return the category URL of the diagnostic.
103+
virtual CXString getCategoryURL() const = 0;
104+
102105
/// Return the number of source ranges for the diagnostic.
103106
virtual unsigned getNumRanges() const = 0;
104107

@@ -160,6 +163,9 @@ struct CXStoredDiagnostic : public CXDiagnosticImpl {
160163
/// Return the category string of the diagnostic.
161164
CXString getCategoryText() const override;
162165

166+
/// Return the category URL of the diagnostic.
167+
CXString getCategoryURL() const override;
168+
163169
/// Return the number of source ranges for the diagnostic.
164170
unsigned getNumRanges() const override;
165171

clang/tools/libclang/CXLoadedDiagnostic.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class CXLoadedDiagnosticSetImpl : public CXDiagnosticSetImpl {
4141

4242
llvm::BumpPtrAllocator Alloc;
4343
Strings Categories;
44+
Strings CategoryURLs;
4445
Strings WarningFlags;
4546
Strings FileNames;
4647

@@ -126,6 +127,10 @@ CXString CXLoadedDiagnostic::getCategoryText() const {
126127
return cxstring::createDup(CategoryText);
127128
}
128129

130+
CXString CXLoadedDiagnostic::getCategoryURL() const {
131+
return cxstring::createDup(CategoryURL);
132+
}
133+
129134
unsigned CXLoadedDiagnostic::getNumRanges() const {
130135
return Ranges.size();
131136
}
@@ -215,7 +220,8 @@ class DiagLoader : serialized_diags::SerializedDiagnosticReader {
215220
std::error_code visitStartOfDiagnostic() override;
216221
std::error_code visitEndOfDiagnostic() override;
217222

218-
std::error_code visitCategoryRecord(unsigned ID, StringRef Name) override;
223+
std::error_code visitCategoryRecord(unsigned ID, StringRef Name,
224+
StringRef URL) override;
219225

220226
std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) override;
221227

@@ -345,11 +351,13 @@ std::error_code DiagLoader::visitEndOfDiagnostic() {
345351
return std::error_code();
346352
}
347353

348-
std::error_code DiagLoader::visitCategoryRecord(unsigned ID, StringRef Name) {
354+
std::error_code DiagLoader::visitCategoryRecord(unsigned ID, StringRef Name,
355+
StringRef URL) {
349356
// FIXME: Why do we care about long strings?
350357
if (Name.size() > 65536)
351358
return reportInvalidFile("Out-of-bounds string in category");
352359
TopDiags->Categories[ID] = TopDiags->copyString(Name);
360+
TopDiags->CategoryURLs[ID] = TopDiags->copyString(URL);
353361
return std::error_code();
354362
}
355363

@@ -431,6 +439,7 @@ std::error_code DiagLoader::visitDiagnosticRecord(
431439
D.category = Category;
432440
D.DiagOption = Flag ? TopDiags->WarningFlags[Flag] : "";
433441
D.CategoryText = Category ? TopDiags->Categories[Category] : "";
442+
D.CategoryURL = Category ? TopDiags->CategoryURLs[Category] : "";
434443
D.Spelling = TopDiags->copyString(Message);
435444
return std::error_code();
436445
}

clang/tools/libclang/CXLoadedDiagnostic.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ class CXLoadedDiagnostic : public CXDiagnosticImpl {
4949
/// Return the category string of the diagnostic.
5050
CXString getCategoryText() const override;
5151

52+
/// Return the category URL of the diagnostic.
53+
CXString getCategoryURL() const override;
54+
5255
/// Return the number of source ranges for the diagnostic.
5356
unsigned getNumRanges() const override;
5457

@@ -89,6 +92,7 @@ class CXLoadedDiagnostic : public CXDiagnosticImpl {
8992
const char *Spelling;
9093
llvm::StringRef DiagOption;
9194
llvm::StringRef CategoryText;
95+
llvm::StringRef CategoryURL;
9296
unsigned severity;
9397
unsigned category;
9498
};

clang/tools/libclang/CXStoredDiagnostic.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ CXString CXStoredDiagnostic::getCategoryText() const {
7676
return cxstring::createRef(DiagnosticIDs::getCategoryNameFromID(catID));
7777
}
7878

79+
CXString CXStoredDiagnostic::getCategoryURL() const {
80+
// Clang does not currently provide URLs for its own diagnostics.
81+
return cxstring::createEmpty();
82+
}
83+
7984
unsigned CXStoredDiagnostic::getNumRanges() const {
8085
if (Diag.getLocation().isInvalid())
8186
return 0;

clang/tools/libclang/libclang.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ LLVM_13 {
344344
clang_getDiagnosticCategory;
345345
clang_getDiagnosticCategoryName;
346346
clang_getDiagnosticCategoryText;
347+
clang_getDiagnosticCategoryURL;
347348
clang_getDiagnosticFixIt;
348349
clang_getDiagnosticInSet;
349350
clang_getDiagnosticLocation;

0 commit comments

Comments
 (0)