Skip to content

Commit 9c3627d

Browse files
authored
Merge pull request #9299 from benlangmuir/cache-custom-diags
[cas] Fix caching of diagnostics using getCustomDiagID
2 parents f608c1a + 61d414a commit 9c3627d

File tree

5 files changed

+147
-0
lines changed

5 files changed

+147
-0
lines changed

clang/include/clang/Basic/Diagnostic.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,18 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
894894
StringRef(FormatString, N - 1));
895895
}
896896

897+
unsigned getCustomDiagID(DiagnosticIDs::CustomDiagDesc Desc) {
898+
return Diags->getCustomDiagID(std::move(Desc));
899+
}
900+
901+
std::optional<unsigned> getMaxCustomDiagID() const {
902+
return Diags->getMaxCustomDiagID();
903+
}
904+
const DiagnosticIDs::CustomDiagDesc &
905+
getCustomDiagDesc(unsigned DiagID) const {
906+
return Diags->getCustomDiagDesc(DiagID);
907+
}
908+
897909
/// Converts a diagnostic argument (as an intptr_t) into the string
898910
/// that represents it.
899911
void ConvertArgToString(ArgumentKind Kind, intptr_t Val,

clang/include/clang/Basic/DiagnosticIDs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
245245
Class GetClass() const { return static_cast<Class>(DiagClass); }
246246
std::string_view GetDescription() const { return Description; }
247247
bool ShouldShowInSystemHeader() const { return ShowInSystemHeader; }
248+
bool ShouldShowInSystemMacro() const { return ShowInSystemMacro; }
248249

249250
friend bool operator==(const CustomDiagDesc &lhs,
250251
const CustomDiagDesc &rhs) {
@@ -318,6 +319,9 @@ class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> {
318319
}());
319320
}
320321

322+
std::optional<unsigned> getMaxCustomDiagID() const;
323+
const CustomDiagDesc &getCustomDiagDesc(unsigned DiagID) const;
324+
321325
//===--------------------------------------------------------------------===//
322326
// Diagnostic classification and reporting interfaces.
323327
//

clang/lib/Basic/DiagnosticIDs.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,10 @@ class CustomDiagInfo {
315315
return Diags->second;
316316
return {};
317317
}
318+
319+
unsigned getMaxCustomDiagID() const {
320+
return DIAG_UPPER_LIMIT + DiagInfo.size();
321+
}
318322
};
319323

320324
} // namespace diag
@@ -429,6 +433,18 @@ unsigned DiagnosticIDs::getCustomDiagID(CustomDiagDesc Diag) {
429433
return CustomDiagInfo->getOrCreateDiagID(Diag);
430434
}
431435

436+
std::optional<unsigned> DiagnosticIDs::getMaxCustomDiagID() const {
437+
if (CustomDiagInfo)
438+
return CustomDiagInfo->getMaxCustomDiagID();
439+
return std::nullopt;
440+
}
441+
442+
const DiagnosticIDs::CustomDiagDesc &
443+
DiagnosticIDs::getCustomDiagDesc(unsigned DiagID) const {
444+
assert(IsCustomDiag(DiagID));
445+
return CustomDiagInfo->getDescription(DiagID);
446+
}
447+
432448
bool DiagnosticIDs::isWarningOrExtension(unsigned DiagID) const {
433449
return DiagID < diag::DIAG_UPPER_LIMIT
434450
? getDiagClass(DiagID) != CLASS_ERROR

clang/lib/Frontend/CachedDiagnostics.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,38 @@ struct Diagnostic {
108108
std::vector<FixItHint> FixIts;
109109
};
110110

111+
struct CustomDiagDesc {
112+
diag::Severity DefaultSeverity;
113+
DiagnosticIDs::Class DiagClass;
114+
bool ShowInSystemHeader;
115+
bool ShowInSystemMacro;
116+
std::string Description;
117+
std::optional<diag::Group> Group;
118+
CustomDiagDesc() = default;
119+
CustomDiagDesc(const DiagnosticIDs::CustomDiagDesc &Desc)
120+
: DefaultSeverity(Desc.GetDefaultSeverity()), DiagClass(Desc.GetClass()),
121+
ShowInSystemHeader(Desc.ShouldShowInSystemHeader()),
122+
ShowInSystemMacro(Desc.ShouldShowInSystemMacro()),
123+
Description(Desc.GetDescription()), Group(Desc.GetGroup()) {}
124+
125+
DiagnosticIDs::CustomDiagDesc getDesc() const {
126+
return DiagnosticIDs::CustomDiagDesc(DefaultSeverity, Description,
127+
DiagClass, ShowInSystemHeader,
128+
ShowInSystemMacro, Group);
129+
}
130+
};
131+
111132
struct Diagnostics {
112133
std::vector<SLocEntry> SLocEntries;
113134
std::vector<Diagnostic> Diags;
135+
std::vector<CustomDiagDesc> CustomDiags;
114136

115137
size_t getNumDiags() const { return Diags.size(); }
116138

117139
void clear() {
118140
SLocEntries.clear();
119141
Diags.clear();
142+
CustomDiags.clear();
120143
}
121144
};
122145

@@ -198,6 +221,10 @@ struct CachedDiagnosticSerializer {
198221
/// produced it.
199222
std::optional<std::string> serializeEmittedDiagnostics();
200223
Error deserializeCachedDiagnostics(StringRef Buffer);
224+
225+
/// Capture any custom diagnostics registerd by \p Diags so that they can be
226+
/// later serialized.
227+
void captureCustomDiags(const DiagnosticsEngine &Diags);
201228
};
202229

203230
} // anonymous namespace
@@ -456,6 +483,46 @@ template <> struct MappingTraits<cached_diagnostics::SLocEntry> {
456483
}
457484
};
458485

486+
template <> struct ScalarEnumerationTraits<diag::Severity> {
487+
static void enumeration(IO &io, diag::Severity &value) {
488+
io.enumCase(value, "ignored", diag::Severity::Ignored);
489+
io.enumCase(value, "remark", diag::Severity::Remark);
490+
io.enumCase(value, "warning", diag::Severity::Warning);
491+
io.enumCase(value, "error", diag::Severity::Error);
492+
io.enumCase(value, "fatal", diag::Severity::Fatal);
493+
}
494+
};
495+
template <> struct ScalarEnumerationTraits<DiagnosticIDs::Class> {
496+
static void enumeration(IO &io, DiagnosticIDs::Class &value) {
497+
io.enumCase(value, "invalid", DiagnosticIDs::CLASS_INVALID);
498+
io.enumCase(value, "note", DiagnosticIDs::CLASS_NOTE);
499+
io.enumCase(value, "remark", DiagnosticIDs::CLASS_REMARK);
500+
io.enumCase(value, "warning", DiagnosticIDs::CLASS_WARNING);
501+
io.enumCase(value, "extension", DiagnosticIDs::CLASS_EXTENSION);
502+
io.enumCase(value, "error", DiagnosticIDs::CLASS_ERROR);
503+
}
504+
};
505+
template <> struct ScalarEnumerationTraits<diag::Group> {
506+
static void enumeration(IO &io, diag::Group &value) {
507+
#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
508+
io.enumCase(value, #GroupName, diag::Group::GroupName);
509+
#include "clang/Basic/DiagnosticGroups.inc"
510+
#undef CATEGORY
511+
#undef DIAG_ENTRY
512+
}
513+
};
514+
515+
template <> struct MappingTraits<cached_diagnostics::CustomDiagDesc> {
516+
static void mapping(IO &io, cached_diagnostics::CustomDiagDesc &DiagDesc) {
517+
io.mapRequired("severity", DiagDesc.DefaultSeverity);
518+
io.mapRequired("class", DiagDesc.DiagClass);
519+
io.mapRequired("show_in_system_header", DiagDesc.ShowInSystemHeader);
520+
io.mapRequired("show_in_system_macro", DiagDesc.ShowInSystemMacro);
521+
io.mapRequired("description", DiagDesc.Description);
522+
io.mapOptional("group", DiagDesc.Group);
523+
}
524+
};
525+
459526
template <> struct MappingTraits<cached_diagnostics::SLocEntry::FileInfo> {
460527
static void mapping(IO &io, cached_diagnostics::SLocEntry::FileInfo &s) {
461528
io.mapRequired("filename", s.Filename);
@@ -537,6 +604,7 @@ template <> struct MappingTraits<cached_diagnostics::Diagnostics> {
537604
static void mapping(IO &io, cached_diagnostics::Diagnostics &s) {
538605
io.mapRequired("sloc_entries", s.SLocEntries);
539606
io.mapRequired("diagnostics", s.Diags);
607+
io.mapRequired("custom_diagnostics", s.CustomDiags);
540608
}
541609
};
542610
} // namespace llvm::yaml
@@ -545,6 +613,28 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(cached_diagnostics::SLocEntry)
545613
LLVM_YAML_IS_SEQUENCE_VECTOR(cached_diagnostics::Diagnostic)
546614
LLVM_YAML_IS_SEQUENCE_VECTOR(cached_diagnostics::Range)
547615
LLVM_YAML_IS_SEQUENCE_VECTOR(cached_diagnostics::FixItHint)
616+
LLVM_YAML_IS_SEQUENCE_VECTOR(cached_diagnostics::CustomDiagDesc)
617+
618+
void CachedDiagnosticSerializer::captureCustomDiags(
619+
const DiagnosticsEngine &Diags) {
620+
auto MaxCustomDiagID = Diags.getMaxCustomDiagID();
621+
if (!MaxCustomDiagID)
622+
return;
623+
624+
// Capture any custom diagnostics we have not already seen.
625+
unsigned FirstUnknownDiag =
626+
diag::DIAG_UPPER_LIMIT + CachedDiags.CustomDiags.size();
627+
for (unsigned DiagID = FirstUnknownDiag; DiagID < *MaxCustomDiagID;
628+
++DiagID) {
629+
auto Desc = Diags.getCustomDiagDesc(DiagID);
630+
CachedDiags.CustomDiags.push_back(Desc);
631+
632+
// Forward the custom diagnostic to the Serializer's diagnostic engine.
633+
auto SerializerDiagID = DiagEngine.getCustomDiagID(Desc);
634+
assert(SerializerDiagID == DiagID && "mismatched custom diags");
635+
(void)SerializerDiagID;
636+
}
637+
}
548638

549639
std::optional<std::string>
550640
CachedDiagnosticSerializer::serializeEmittedDiagnostics() {
@@ -613,6 +703,13 @@ Error CachedDiagnosticSerializer::deserializeCachedDiagnostics(
613703
if (YIn.error())
614704
return createStringError(YIn.error(),
615705
"failed deserializing cached diagnostics");
706+
707+
assert(DiagEngine.getMaxCustomDiagID() == std::nullopt &&
708+
"existing custom diagnostics will conflict");
709+
for (const auto &CustomDiag : CachedDiags.CustomDiags) {
710+
(void)DiagEngine.getCustomDiagID(CustomDiag.getDesc());
711+
}
712+
616713
return Error::success();
617714
}
618715

@@ -661,6 +758,10 @@ struct CachingDiagnosticsProcessor::DiagnosticsConsumer
661758
if (shouldCacheDiagnostic(Level, Info)) {
662759
unsigned DiagIdx = Serializer.addDiag(StoredDiagnostic(Level, Info));
663760
StoredDiagnostic NewDiag = Serializer.getDiag(DiagIdx);
761+
762+
if (DiagnosticIDs::IsCustomDiag(NewDiag.getID()))
763+
Serializer.captureCustomDiags(*Info.getDiags());
764+
664765
// Pass the converted diagnostic to the original consumer. We do this
665766
// because:
666767
// 1. It ensures that the rendered diagnostics will use the same

clang/test/CAS/custom-diags.m

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: rm -rf %t && mkdir -p %t
2+
3+
// RUN: not %clang_cc1 -triple arm64-apple-macosx12 -fsyntax-only %s 2> %t/diags-orig
4+
5+
// RUN: %clang -cc1depscan -fdepscan=inline -fdepscan-include-tree -o %t/t.rsp -cc1-args \
6+
// RUN: -cc1 -triple arm64-apple-macosx12 -fcas-path %t/cas -fsyntax-only %s
7+
// RUN: not %clang @%t/t.rsp 2> %t/diags-cached
8+
9+
// RUN: diff -u %t/diags-orig %t/diags-cached
10+
11+
// RUN: FileCheck %s -input-file %t/diags-cached
12+
13+
const char s8[] = @encode(__SVInt8_t);
14+
// CHECK: cannot yet @encode type __SVInt8_t

0 commit comments

Comments
 (0)