Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parser: require integral types for fixed-type enums #688

Merged
merged 2 commits into from
Apr 17, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/aro/Diagnostics/messages.def
Original file line number Diff line number Diff line change
@@ -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
@@ -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;
}
ehaas marked this conversation as resolved.
Show resolved Hide resolved
break :fixed fixed;
} else null;

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