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 9f964b728151066dd37dd80269ed23ea4b4cdeab
parent 27e77f6ca6872c8d332c2e153773ca226d69fb64
Author: Michael Forney <mforney@mforney.org>
Date:   Mon, 18 Feb 2019 12:34:25 -0800

Fix compatible check for basic types

This check was only supposed to return true for enum types and their
corresponding integer type. However, it had the side effect of making
'int' compatible with 'unsigned'.

To fix this, introduce a new basic type kind for enums with the same
rank as 'int', that is only compatible with itself and the 'int' type
with the matching sign.

Thanks to Andrew Chambers for the bug report.

Diffstat:
Mdecl.c | 1+
Atests/common-real-int-sign.c | 4++++
Atests/common-real-int-sign.qbe | 14++++++++++++++
Mtype.c | 6+++++-
Mtype.h | 1+
5 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/decl.c b/decl.c @@ -185,6 +185,7 @@ tagspec(struct scope *s) t = mktype(kind, NULL); if (kind == TYPEBASIC) { *t = typeint; + t->basic.kind = BASICENUM; } else { t->repr = &i64; // XXX t->size = 0; diff --git a/tests/common-real-int-sign.c b/tests/common-real-int-sign.c @@ -0,0 +1,4 @@ +int main(void) { + unsigned x = -1; + return 0 > x; +} diff --git a/tests/common-real-int-sign.qbe b/tests/common-real-int-sign.qbe @@ -0,0 +1,14 @@ +export +function w $main() { +@start.1 + %.1 =l alloc4 4 +@body.2 + %.2 =l add %.1, 0 + %.3 =w sub 0, 1 + %.4 =w copy %.3 + storew %.4, %.2 + %.5 =w copy 0 + %.6 =w loaduw %.1 + %.7 =w cugtw %.5, %.6 + ret %.7 +} diff --git a/type.c b/type.c @@ -142,6 +142,7 @@ typerank(struct type *t) case BASICBOOL: return 1; case BASICCHAR: return 2; case BASICSHORT: return 3; + case BASICENUM: case BASICINT: return 4; case BASICLONG: return 5; case BASICLONGLONG: return 6; @@ -162,9 +163,12 @@ typecompatible(struct type *t1, struct type *t2) return false; switch (t1->kind) { case TYPEBASIC: + if (t1->basic.issigned != t2->basic.issigned) + return false; /* enum types are compatible with 'int', but not with each other (unless they are the same type) */ - return t1->basic.kind == t2->basic.kind && (t1 == &typeint || t2 == &typeint); + return t1->basic.kind == BASICENUM && t2->basic.kind == BASICINT || + t1->basic.kind == BASICINT && t2->basic.kind == BASICENUM; case TYPEQUALIFIED: if (t1->qualified.kind != t2->qualified.kind) return false; diff --git a/type.h b/type.h @@ -68,6 +68,7 @@ struct type { BASICCHAR, BASICSHORT, BASICINT, + BASICENUM, BASICLONG, BASICLONGLONG, BASICFLOAT,