From 3f67cc35c7659a3c6921caaabac8b6a4399e72cb Mon Sep 17 00:00:00 2001 From: lemon Date: Mon, 22 Dec 2025 20:07:17 +0100 Subject: c: add _Generic --- c/c.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ todo.txt | 2 +- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/c/c.c b/c/c.c index a93dcc6..e070924 100644 --- a/c/c.c +++ b/c/c.c @@ -926,6 +926,55 @@ vaargexpr(struct comp *cm, struct span *span) return ex; } +static struct expr +genericexpr(struct comp *cm, struct span *span) +{ + struct token tk; + if (expect(cm, '(', "after _Generic")) { + struct expr control = expr(cm), dfault = {0}, ex = {0}; + expect(cm, ',', NULL); + for (;;) { + if (match(cm, &tk, TKWdefault)) { + expect(cm, ':', NULL); + if (dfault.t) { + error(&tk.span, "duplicate 'default' specifier in generic selection expression"); + (void)expr(cm); + } else { + dfault = expr(cm); + } + } else { + struct decl decl = pdecl(&(struct declstate){DCASTEXPR}, cm); + union type ty = decl.ty; + expect(cm, ':', NULL); + if (!ex.t && + (typedecay(ty).bits == typedecay(control.ty).bits + || ((ty.t == TYENUM || control.ty.t == TYENUM) && scalartypet(ty) == scalartypet(control.ty)))) + ex = expr(cm); + else + (void)expr(cm); + } + if (match(cm, &tk, ')')) break; + else if (!expect(cm, ',', "or `)'")) { + if (!isdecltok(cm)) { + peek(cm, &tk); /* want the span */ + break; + } + } + } + if (!ex.t) ex = dfault; + if (!ex.t) { + error(&control.span, + "controlling type '%ty' not compatible with any generic association type", + control.ty); + ex.ty.t = TYINT; + } + ex.span = *span; + joinspan(&ex.span.ex, tk.span.ex); + return ex; + } + return mkexpr(ENUMLIT,*span,mktype(TYINT),); +} + static inline int tkprec(int tt) { @@ -1086,6 +1135,10 @@ Unary: span = tk.span; ex = vaargexpr(cm, &span); break; + case TKW_Generic: + span = tk.span; + ex = genericexpr(cm, &span); + break; default: fatal(&tk.span, "expected %s (near %'tk)", ctx == EFROMSTMT ? "statement" : "expression", &tk); } diff --git a/todo.txt b/todo.txt index 94308d0..746d5c4 100644 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,5 @@ - aarch64 backend -- STDC: thread local, VLAs, complex, long double, _Generic, atomics +- STDC: thread local, VLAs, complex, long double, atomics - test on non-GNU and non-linux POSIX systems (alpine, various BSDs). Maybe we'll need a configure script after all - DWARF debug information - implement GNU extensions: __attribute__, __builtin_*, ... -- cgit v1.2.3