From 8a225f1e22052e6f80b9f39146ce555f8478fb95 Mon Sep 17 00:00:00 2001 From: Evan Haas Date: Mon, 15 Apr 2024 21:01:27 -0700 Subject: [PATCH 1/2] Type: Improve type comparison of fixed-type enums Enums types with fixed underlying type should compare equal to the underlying type, but not to other enums with the same fixed underlying type. Closes #683 --- src/aro/Type.zig | 4 ++++ test/cases/enum fixed.c | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/aro/Type.zig b/src/aro/Type.zig index 35f2d9ae..cc660c3b 100644 --- a/src/aro/Type.zig +++ b/src/aro/Type.zig @@ -1220,6 +1220,10 @@ pub fn eql(a_param: Type, b_param: Type, comp: *const Compilation, check_qualifi if (!b.isFunc()) return false; } else if (a.isArray()) { if (!b.isArray()) return false; + } else if (a.specifier == .@"enum" and a.data.@"enum".fixed and b.specifier != .@"enum") { + return a.data.@"enum".tag_ty.eql(b, comp, check_qualifiers); + } else if (b.specifier == .@"enum" and b.data.@"enum".fixed and a.specifier != .@"enum") { + return a.eql(b.data.@"enum".tag_ty, comp, check_qualifiers); } else if (a.specifier != b.specifier) return false; if (a.qual.atomic != b.qual.atomic) return false; diff --git a/test/cases/enum fixed.c b/test/cases/enum fixed.c index d02b7484..3bccbd6e 100644 --- a/test/cases/enum fixed.c +++ b/test/cases/enum fixed.c @@ -34,6 +34,30 @@ enum E e; enum E: int; void fn(enum E); +enum Signed: int { + S, +}; + +enum Signed2: int { + S2, +}; + +enum Unsigned: unsigned { + U, +}; + +enum Plain { + P, +}; + +_Static_assert(!__builtin_types_compatible_p(enum Signed, enum Signed2), ""); +_Static_assert(!__builtin_types_compatible_p(enum Signed, enum Unsigned), ""); +_Static_assert(__builtin_types_compatible_p(enum Signed, int), ""); +_Static_assert(__builtin_types_compatible_p(enum Unsigned, unsigned), ""); + +_Static_assert(!__builtin_types_compatible_p(enum Signed, enum Plain), ""); +_Static_assert(!__builtin_types_compatible_p(enum Unsigned, enum Plain), ""); + #define EXPECTED_ERRORS "enum fixed.c:2:7: warning: enumeration types with a fixed underlying type are a Clang extension [-Wfixed-enum-extension]" \ "enum fixed.c:4:6: error: enumeration previously declared with fixed underlying type" \ "enum fixed.c:2:6: note: previous definition is here" \ From 9ad7baafc2491089a20ee29610d33abc1e101267 Mon Sep 17 00:00:00 2001 From: Evan Haas Date: Mon, 15 Apr 2024 21:36:17 -0700 Subject: [PATCH 2/2] Type: fix integer rank comparison for incomplete enums Fixes #681 --- src/aro/Type.zig | 5 +++++ test/cases/enum fixed.c | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/aro/Type.zig b/src/aro/Type.zig index cc660c3b..2364adcb 100644 --- a/src/aro/Type.zig +++ b/src/aro/Type.zig @@ -1318,6 +1318,10 @@ pub fn integerRank(ty: Type, comp: *const Compilation) usize { .typeof_expr => ty.data.expr.ty.integerRank(comp), .attributed => ty.data.attributed.base.integerRank(comp), + .@"enum" => { + std.debug.assert(real.data.@"enum".fixed); + return real.data.@"enum".tag_ty.integerRank(comp); + }, else => unreachable, }); } @@ -1325,6 +1329,7 @@ pub fn integerRank(ty: Type, comp: *const Compilation) usize { /// Returns true if `a` and `b` are integer types that differ only in sign pub fn sameRankDifferentSign(a: Type, b: Type, comp: *const Compilation) bool { if (!a.isInt() or !b.isInt()) return false; + if (a.hasIncompleteSize() or b.hasIncompleteSize()) return false; if (a.integerRank(comp) != b.integerRank(comp)) return false; return a.isUnsignedInt(comp) != b.isUnsignedInt(comp); } diff --git a/test/cases/enum fixed.c b/test/cases/enum fixed.c index 3bccbd6e..5c9dd94e 100644 --- a/test/cases/enum fixed.c +++ b/test/cases/enum fixed.c @@ -58,6 +58,19 @@ _Static_assert(__builtin_types_compatible_p(enum Unsigned, unsigned), ""); _Static_assert(!__builtin_types_compatible_p(enum Signed, enum Plain), ""); _Static_assert(!__builtin_types_compatible_p(enum Unsigned, enum Plain), ""); +void pointers(void) { + int x; + unsigned y; + + enum Signed *e1 = &x; + enum Signed *e2 = &y; + enum Unsigned *e3 = &x; + enum Unsigned *e4 = &y; + + enum Incomplete *i1 = &x; + enum Incomplete *i2 = &y; +} + #define EXPECTED_ERRORS "enum fixed.c:2:7: warning: enumeration types with a fixed underlying type are a Clang extension [-Wfixed-enum-extension]" \ "enum fixed.c:4:6: error: enumeration previously declared with fixed underlying type" \ "enum fixed.c:2:6: note: previous definition is here" \ @@ -67,3 +80,8 @@ _Static_assert(!__builtin_types_compatible_p(enum Unsigned, enum Plain), ""); "enum fixed.c:9:6: note: previous definition is here" \ "enum fixed.c:14:5: error: enumerator value is not representable in the underlying type 'unsigned char'" \ "enum fixed.c:18:5: error: enumerator value is not representable in the underlying type 'char'" \ + "enum fixed.c:66:23: warning: incompatible pointer types initializing 'enum Signed: int *' from incompatible type 'unsigned int *' converts between pointers to integer types with different sign [-Wpointer-sign]" \ + "enum fixed.c:67:25: warning: incompatible pointer types initializing 'enum Unsigned: unsigned int *' from incompatible type 'int *' [-Wincompatible-pointer-types]" \ + "enum fixed.c:70:27: warning: incompatible pointer types initializing 'enum Incomplete *' from incompatible type 'int *' [-Wincompatible-pointer-types]" \ + "enum fixed.c:71:27: warning: incompatible pointer types initializing 'enum Incomplete *' from incompatible type 'unsigned int *' [-Wincompatible-pointer-types]" \ +