aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-22 15:33:02 +0000
committer_ov4 <ov4@ov4.org>2026-10-22 15:33:15 +0000
commit5e84edbe1a79c6a7752ee276ea6c1a4daef4fa8e (patch)
tree0d958458a13aea9183b92dfb8b4f767e6d98414b
parent0e8bc8c3e806796bf3b03e7da6c59ff24e58559f (diff)
fix(diagnostics): print each identical diagnostic once
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
-rw-r--r--include/cps/Diagnostics.h17
1 files changed, 14 insertions, 3 deletions
diff --git a/include/cps/Diagnostics.h b/include/cps/Diagnostics.h
index 4bcb877..9c9ea37 100644
--- a/include/cps/Diagnostics.h
+++ b/include/cps/Diagnostics.h
@@ -1,6 +1,7 @@
#pragma once
#include <cstdarg>
#include <cstdio>
+#include <set>
#include <string>
namespace cps {
@@ -30,14 +31,24 @@ inline std::string diagnosticPrefix(Severity S, const std::string &Locus = "cpsc
return (Locus.empty() ? "" : Span("01", Locus + ":") + " ") + Span(Color, Label);
}
+// Every diagnostic line printed so far, to suppress exact repeats.
+inline std::set<std::string> PrintedDiagnostics;
+
// Prints "<path>:<line>: <label>: <message>\n" (just "<path>:" when the line is
// unknown, "cpsc:" when no source is set).
inline void vsourceDiagnostic(Severity S, int Line, const char *Format, va_list Args) {
std::string Locus = DiagnosticSource.empty() ? "cpsc" : DiagnosticSource;
if (!DiagnosticSource.empty() && Line > 0) Locus += ":" + std::to_string(Line);
- std::fputs(diagnosticPrefix(S, Locus).c_str(), stderr);
- std::vfprintf(stderr, Format, Args);
- std::fputc('\n', stderr);
+ va_list Copy;
+ va_copy(Copy, Args);
+ int Length = std::vsnprintf(nullptr, 0, Format, Copy);
+ va_end(Copy);
+ std::string Message(Length > 0 ? Length : 0, '\0');
+ if (Length > 0) std::vsnprintf(Message.data(), Message.size() + 1, Format, Args);
+ std::string Text = diagnosticPrefix(S, Locus) + Message + '\n';
+ // The same node can be diagnosed more than once; print each line once.
+ if (!PrintedDiagnostics.insert(Text).second) return;
+ std::fputs(Text.c_str(), stderr);
}
__attribute__((format(printf, 2, 3)))