@@ -108,15 +108,38 @@ struct Diagnostic {
108
108
std::vector<FixItHint> FixIts;
109
109
};
110
110
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
+
111
132
struct Diagnostics {
112
133
std::vector<SLocEntry> SLocEntries;
113
134
std::vector<Diagnostic> Diags;
135
+ std::vector<CustomDiagDesc> CustomDiags;
114
136
115
137
size_t getNumDiags () const { return Diags.size (); }
116
138
117
139
void clear () {
118
140
SLocEntries.clear ();
119
141
Diags.clear ();
142
+ CustomDiags.clear ();
120
143
}
121
144
};
122
145
@@ -198,6 +221,10 @@ struct CachedDiagnosticSerializer {
198
221
// / produced it.
199
222
std::optional<std::string> serializeEmittedDiagnostics ();
200
223
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);
201
228
};
202
229
203
230
} // anonymous namespace
@@ -456,6 +483,46 @@ template <> struct MappingTraits<cached_diagnostics::SLocEntry> {
456
483
}
457
484
};
458
485
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
+
459
526
template <> struct MappingTraits <cached_diagnostics::SLocEntry::FileInfo> {
460
527
static void mapping (IO &io, cached_diagnostics::SLocEntry::FileInfo &s) {
461
528
io.mapRequired (" filename" , s.Filename );
@@ -537,6 +604,7 @@ template <> struct MappingTraits<cached_diagnostics::Diagnostics> {
537
604
static void mapping (IO &io, cached_diagnostics::Diagnostics &s) {
538
605
io.mapRequired (" sloc_entries" , s.SLocEntries );
539
606
io.mapRequired (" diagnostics" , s.Diags );
607
+ io.mapRequired (" custom_diagnostics" , s.CustomDiags );
540
608
}
541
609
};
542
610
} // namespace llvm::yaml
@@ -545,6 +613,28 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(cached_diagnostics::SLocEntry)
545
613
LLVM_YAML_IS_SEQUENCE_VECTOR(cached_diagnostics::Diagnostic)
546
614
LLVM_YAML_IS_SEQUENCE_VECTOR(cached_diagnostics::Range)
547
615
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
+ }
548
638
549
639
std::optional<std::string>
550
640
CachedDiagnosticSerializer::serializeEmittedDiagnostics () {
@@ -613,6 +703,13 @@ Error CachedDiagnosticSerializer::deserializeCachedDiagnostics(
613
703
if (YIn.error ())
614
704
return createStringError (YIn.error (),
615
705
" 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
+
616
713
return Error::success ();
617
714
}
618
715
@@ -661,6 +758,10 @@ struct CachingDiagnosticsProcessor::DiagnosticsConsumer
661
758
if (shouldCacheDiagnostic (Level, Info)) {
662
759
unsigned DiagIdx = Serializer.addDiag (StoredDiagnostic (Level, Info));
663
760
StoredDiagnostic NewDiag = Serializer.getDiag (DiagIdx);
761
+
762
+ if (DiagnosticIDs::IsCustomDiag (NewDiag.getID ()))
763
+ Serializer.captureCustomDiags (*Info.getDiags ());
764
+
664
765
// Pass the converted diagnostic to the original consumer. We do this
665
766
// because:
666
767
// 1. It ensures that the rendered diagnostics will use the same
0 commit comments