Skip to content

Commit

Permalink
Parser: require integral types for fixed-type enums
Browse files Browse the repository at this point in the history
Closes #685
  • Loading branch information
ehaas committed Apr 17, 2024
1 parent 9aeacf0 commit c36fecb
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 2 deletions.
5 changes: 5 additions & 0 deletions src/aro/Diagnostics/messages.def
Original file line number Diff line number Diff line change
Expand Up @@ -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"
10 changes: 8 additions & 2 deletions src/aro/Parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down
33 changes: 33 additions & 0 deletions test/cases/enum fixed.c
Original file line number Diff line number Diff line change
Expand Up @@ -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" \
Expand All @@ -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]" \

0 comments on commit c36fecb

Please sign in to comment.