aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2024-03-16 14:22:43 -0700
committerMichael Forney <mforney@mforney.org>2024-03-16 14:41:19 -0700
commit8bed97beaea3839369a947ea741aa083e76ca014 (patch)
treeaac7e8be8be1a05ff9ee2bc9a5ecefc224221669
parent773bae1fe954fd578a8360c01ca83675bba9e6b4 (diff)
Store enum underlying type in base field
This will facilitate supporting underlying types other than int or unsigned, possible in C23. References: https://todo.sr.ht/~mcf/cproc/64
-rw-r--r--decl.c11
-rw-r--r--type.c15
2 files changed, 15 insertions, 11 deletions
diff --git a/decl.c b/decl.c
index 111c0e3..37498d8 100644
--- a/decl.c
+++ b/decl.c
@@ -177,9 +177,8 @@ tagspec(struct scope *s)
error(&tok.loc, "redeclaration of tag '%s' with different kind", tag);
} else {
if (kind == TYPEENUM) {
- t = xmalloc(sizeof(*t));
- *t = typeuint;
- t->kind = kind;
+ t = mktype(kind, PROPSCALAR|PROPARITH|PROPREAL|PROPINT);
+ t->base = &typeuint;
} else {
t = mktype(kind, 0);
t->size = 0;
@@ -223,7 +222,7 @@ tagspec(struct scope *s)
if (e->type->u.basic.issigned && i >= 1ull << 63) {
if (i < -1ull << 31)
goto invalid;
- t->u.basic.issigned = true;
+ t->base = &typeint;
} else if (i >= 1ull << 32) {
goto invalid;
}
@@ -237,13 +236,15 @@ tagspec(struct scope *s)
large = true;
d->type = &typeuint;
}
- if (large && t->u.basic.issigned)
+ if (large && t->base->u.basic.issigned)
error(&tok.loc, "neither 'int' nor 'unsigned' can represent all enumerator values");
scopeputdecl(s, name, d);
if (!consume(TCOMMA))
break;
}
expect(TRBRACE, "to close enum specifier");
+ t->size = t->base->size;
+ t->align = t->base->align;
t->incomplete = false;
}
diff --git a/type.c b/type.c
index 563b3bf..ea9e56e 100644
--- a/type.c
+++ b/type.c
@@ -91,12 +91,13 @@ mkarraytype(struct type *base, enum typequal qual, unsigned long long len)
static int
typerank(struct type *t)
{
+ if (t->kind == TYPEENUM)
+ t = t->base;
assert(t->prop & PROPINT);
switch (t->kind) {
case TYPEBOOL: return 1;
case TYPECHAR: return 2;
case TYPESHORT: return 3;
- case TYPEENUM:
case TYPEINT: return 4;
case TYPELONG: return 5;
case TYPELLONG: return 6;
@@ -114,11 +115,13 @@ typecompatible(struct type *t1, struct type *t2)
if (t1 == t2)
return true;
if (t1->kind != t2->kind) {
- /* enum types are compatible with 'int', but not with
- each other (unless they are the same type) */
- return (t1->kind == TYPEENUM && t2->kind == TYPEINT ||
- t1->kind == TYPEINT && t2->kind == TYPEENUM) &&
- t1->u.basic.issigned == t2->u.basic.issigned;
+ /*
+ enum types are compatible with their underlying
+ type, but not with each other (unless they are the
+ same type)
+ */
+ return t1->kind == TYPEENUM && t2 == t1->base ||
+ t2->kind == TYPEENUM && t1 == t2->base;
}
switch (t1->kind) {
case TYPEPOINTER: