cproc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/cproc
Log | Files | Refs | Submodules | README | LICENSE

commit 67c96568772bc0686e9a73e1d6490d9d982b53dd
parent 11ba42eccc2bd0ce6d893b583a37dc0b46d09adf
Author: Michael Forney <mforney@mforney.org>
Date:   Wed, 24 Apr 2019 19:28:07 -0700

Implement _Generic selection

Diffstat:
MREADME.md | 1-
Mexpr.c | 49++++++++++++++++++++++++++++++++++++++++++++++++-
Atest/generic.c | 6++++++
Atest/generic.qbe | 1+
4 files changed, 55 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md @@ -63,7 +63,6 @@ specified in `config.h`. - Preprocessor ([#6]). - Generation of position independent code (i.e. shared libraries, modules, PIEs). -- `_Generic` selection ([#44]). - Currently only `x86_64` is supported and tested, though QBE also supports `aarch64`, so it is possible that it works as well. diff --git a/expr.c b/expr.c @@ -322,6 +322,52 @@ unescape(char **p) return c; } +static struct expr * +generic(struct scope *s) +{ + struct expr *e, *match = NULL, *def = NULL; + struct type *t, *want; + enum typequal qual; + + next(); + expect(TLPAREN, "after '_Generic'"); + e = assignexpr(s); + expect(TCOMMA, "after generic selector expression"); + want = e->type; + delexpr(e); + do { + if (consume(TDEFAULT)) { + if (def) + error(&tok.loc, "multiple default expressions in generic association list"); + expect(TCOLON, "after 'default'"); + def = assignexpr(s); + } else { + qual = QUALNONE; + t = typename(s, &qual); + if (!t) + error(&tok.loc, "expected typename for generic association"); + expect(TCOLON, "after type name"); + e = assignexpr(s); + if (typecompatible(t, want) && qual == QUALNONE) { + if (match) + error(&tok.loc, "generic selector matches multiple associations"); + match = e; + } else { + delexpr(e); + } + } + } while (consume(TCOMMA)); + expect(TRPAREN, "after generic assocation list"); + if (!match) { + if (!def) + error(&tok.loc, "generic selector matches no associations and no default was specified"); + match = def; + } else if (def) { + delexpr(def); + } + return match; +} + /* 6.5 Expressions */ static struct expr * primaryexpr(struct scope *s) @@ -407,7 +453,8 @@ primaryexpr(struct scope *s) expect(TRPAREN, "after expression"); break; case T_GENERIC: - error(&tok.loc, "generic selection is not yet supported"); + e = generic(s); + break; default: error(&tok.loc, "expected primary expression"); } diff --git a/test/generic.c b/test/generic.c @@ -0,0 +1,6 @@ +int x = _Generic(123, + const int: 1, + unsigned: 2, + int: 3, + int *: 4 +); diff --git a/test/generic.qbe b/test/generic.qbe @@ -0,0 +1 @@ +export data $x = align 4 { w 3, }