commit 78dd6876acf34875b49ae2aad972ddeb0a2b38e6
parent 5c3b6c310fe5a6c29007deca89a659d4a6f73438
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Tue, 19 May 2026 14:45:15 -0700
Support #warning directive
Diffstat:
5 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/lang/c/pp/pp.c b/lang/c/pp/pp.c
@@ -206,6 +206,7 @@ static void pp_intern_keywords(Pp* pp) {
pp->sym_pragma = pool_intern_cstr(p, "pragma");
pp->sym_pragma_kw = pp->sym_pragma;
pp->sym_error = pool_intern_cstr(p, "error");
+ pp->sym_warning = pool_intern_cstr(p, "warning");
pp->sym_embed = pool_intern_cstr(p, "embed");
pp->sym_defined = pool_intern_cstr(p, "defined");
pp->sym_va_args = pool_intern_cstr(p, "__VA_ARGS__");
diff --git a/lang/c/pp/pp_directive.c b/lang/c/pp/pp_directive.c
@@ -1014,24 +1014,44 @@ int try_expand_pragma_op(Pp* pp, const Tok* invoke) {
}
/* ============================================================
- * #error
+ * #error / #warning
* ============================================================ */
-static void do_error(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
- /* Concatenate token spellings into a single message. */
- CharBuf cb = {0};
+static void directive_message(Pp* pp, const Tok* line, u32 n, CharBuf* cb) {
u32 i;
for (i = 0; i < n; ++i) {
size_t sl = 0;
const char* s =
line[i].spelling ? pool_str(pp->pool, line[i].spelling, &sl) : NULL;
- if (i > 0) cb_putc(pp, &cb, ' ');
- if (s && sl) cb_append(pp, &cb, s, (u32)sl);
+ if (i > 0) cb_putc(pp, cb, ' ');
+ if (s && sl) cb_append(pp, cb, s, (u32)sl);
+ }
+ cb_putc(pp, cb, 0);
+}
+
+static void pp_warn(Pp* pp, SrcLoc loc, const char* fmt, ...) {
+ CfreeDiagSink* sink = cfree_compiler_diag_sink(pp->c);
+ va_list ap;
+ if (sink && sink->emit) {
+ va_start(ap, fmt);
+ sink->emit(sink, CFREE_DIAG_WARN, loc, fmt, ap);
+ va_end(ap);
}
- cb_putc(pp, &cb, 0);
+ if (sink) sink->warnings++;
+}
+
+static void do_error(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
+ CharBuf cb = {0};
+ directive_message(pp, line, n, &cb);
compiler_panic(pp->c, loc, "#error: %s", cb.data ? cb.data : "");
}
+static void do_warning(Pp* pp, const Tok* line, u32 n, SrcLoc loc) {
+ CharBuf cb = {0};
+ directive_message(pp, line, n, &cb);
+ pp_warn(pp, loc, "#warning: %s", cb.data ? cb.data : "");
+}
+
/* ============================================================
* #embed (C23, ยง6.10.* per N3033)
* ============================================================ */
@@ -1244,6 +1264,8 @@ void process_directive(Pp* pp, SrcLoc hash_loc) {
do_pragma(pp, line + 1, n - 1, hash_loc);
else if (name == pp->sym_error)
do_error(pp, line + 1, n - 1, hash_loc);
+ else if (name == pp->sym_warning)
+ do_warning(pp, line + 1, n - 1, hash_loc);
else if (name == pp->sym_embed)
do_embed(pp, line + 1, n - 1, hash_loc);
else {
diff --git a/lang/c/pp/pp_priv.h b/lang/c/pp/pp_priv.h
@@ -138,6 +138,7 @@ struct Pp {
Sym sym_line;
Sym sym_pragma;
Sym sym_error;
+ Sym sym_warning;
Sym sym_embed;
Sym sym_defined;
Sym sym_va_args;
diff --git a/test/pp/cases/b3_warning_directive.c b/test/pp/cases/b3_warning_directive.c
@@ -0,0 +1,2 @@
+#warning "non-fatal diagnostic"
+int after_warning;
diff --git a/test/pp/cases/b3_warning_directive.expected b/test/pp/cases/b3_warning_directive.expected
@@ -0,0 +1 @@
+int after_warning;