From c36fecb56648e7bc9197d1e78f1706207113b1af Mon Sep 17 00:00:00 2001 From: Evan Haas Date: Wed, 17 Apr 2024 00:50:05 -0700 Subject: [PATCH 1/2] Parser: require integral types for fixed-type enums Closes #685 --- src/aro/Diagnostics/messages.def | 5 +++++ src/aro/Parser.zig | 10 ++++++++-- test/cases/enum fixed.c | 33 ++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/aro/Diagnostics/messages.def b/src/aro/Diagnostics/messages.def index 89faf02e..5d242d32 100644 --- a/src/aro/Diagnostics/messages.def +++ b/src/aro/Diagnostics/messages.def @@ -2482,3 +2482,8 @@ attribute_todo .msg = "TODO: implement '{s}' attribute for {s}" .extra = .attribute_todo .kind = .@"error" + +invalid_type_underlying_enum + .msg = "non-integral type '{s}' is an invalid underlying type" + .extra = .str + .kind = .@"error" diff --git a/src/aro/Parser.zig b/src/aro/Parser.zig index c395ee2a..4dc4f3ce 100644 --- a/src/aro/Parser.zig +++ b/src/aro/Parser.zig @@ -2478,7 +2478,8 @@ fn enumSpec(p: *Parser) Error!Type { const maybe_ident = try p.eatIdentifier(); const fixed_ty = if (p.eatToken(.colon)) |colon| fixed: { - const fixed = (try p.typeName()) orelse { + const ty_start = p.tok_i; + const fixed = (try p.specQual()) orelse { if (p.record.kind != .invalid) { // This is a bit field. p.tok_i -= 1; @@ -2488,7 +2489,12 @@ fn enumSpec(p: *Parser) Error!Type { try p.errTok(.enum_fixed, colon); break :fixed null; }; - try p.errTok(.enum_fixed, colon); + if (fixed.isInt() and !fixed.is(.@"enum")) { + try p.errTok(.enum_fixed, colon); + } else { + try p.errStr(.invalid_type_underlying_enum, ty_start, try p.typeStr(fixed)); + break :fixed Type.int; + } break :fixed fixed; } else null; diff --git a/test/cases/enum fixed.c b/test/cases/enum fixed.c index 5c9dd94e..6fa58d4e 100644 --- a/test/cases/enum fixed.c +++ b/test/cases/enum fixed.c @@ -71,6 +71,34 @@ void pointers(void) { enum Incomplete *i2 = &y; } +typedef struct BackingStruct { + int x; +} BackingStruct; + +typedef enum BackingEnum : int { + B0, +} BackingEnum; + +enum Bad1: BackingStruct { + B1, +}; + +enum Bad2: BackingEnum { + B2, +}; + +enum Bad3: unsigned * { + B3, +}; + +void more_pointers(void) { + unsigned y; + + enum SignedEnum: int *p = &y; + enum UnsignedEnum: unsigned *p2 = &y; + enum CharEnum: char signed *p3 = &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" \ @@ -84,4 +112,9 @@ void pointers(void) { "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]" \ + "enum fixed.c:82:12: error: non-integral type 'struct BackingStruct' is an invalid underlying type" \ + "enum fixed.c:86:12: error: non-integral type 'enum BackingEnum: int' is an invalid underlying type" \ + "enum fixed.c:90:23: error: expected identifier or '('" \ + "enum fixed.c:97:31: warning: incompatible pointer types initializing 'enum SignedEnum: int *' from incompatible type 'unsigned int *' converts between pointers to integer types with different sign [-Wpointer-sign]" \ + "enum fixed.c:99:38: warning: incompatible pointer types initializing 'enum CharEnum: signed char *' from incompatible type 'unsigned int *' [-Wincompatible-pointer-types]" \ From 46b692f1f6c98015215e4a9245afb38874188b7e Mon Sep 17 00:00:00 2001 From: Evan Haas Date: Wed, 17 Apr 2024 08:22:01 -0700 Subject: [PATCH 2/2] Update src/aro/Parser.zig Co-authored-by: Veikka Tuominen --- src/aro/Parser.zig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/aro/Parser.zig b/src/aro/Parser.zig index 4dc4f3ce..ef39f075 100644 --- a/src/aro/Parser.zig +++ b/src/aro/Parser.zig @@ -2489,12 +2489,13 @@ fn enumSpec(p: *Parser) Error!Type { try p.errTok(.enum_fixed, colon); break :fixed null; }; - if (fixed.isInt() and !fixed.is(.@"enum")) { - try p.errTok(.enum_fixed, colon); - } else { + + if (!fixed.isInt() or fixed.is(.@"enum")) { try p.errStr(.invalid_type_underlying_enum, ty_start, try p.typeStr(fixed)); break :fixed Type.int; } + + try p.errTok(.enum_fixed, colon); break :fixed fixed; } else null;