aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-09-01 21:39:10 +0900
committernsfisis <nsfisis@gmail.com>2025-09-01 23:55:56 +0900
commitc5cf38fffec9b7e0a96cc3f016c3a01820498953 (patch)
treecfee0200dc16735af6e6e12c7fdedeca42249c4f /src
parentdfea2b35c962740c701ebc2151067ce6fb155e78 (diff)
downloadducc-c5cf38fffec9b7e0a96cc3f016c3a01820498953.tar.gz
ducc-c5cf38fffec9b7e0a96cc3f016c3a01820498953.tar.zst
ducc-c5cf38fffec9b7e0a96cc3f016c3a01820498953.zip
feat: support signed/unsigned specifier
Diffstat (limited to 'src')
-rw-r--r--src/ast.c72
-rw-r--r--src/ast.h15
-rw-r--r--src/parse.c312
3 files changed, 333 insertions, 66 deletions
diff --git a/src/ast.c b/src/ast.c
index ae11ed3..0d19d40 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -5,26 +5,40 @@
const char* type_kind_stringify(TypeKind k) {
if (k == TypeKind_unknown)
return "<unknown>";
+ else if (k == TypeKind_void)
+ return "void";
else if (k == TypeKind_char)
return "char";
+ else if (k == TypeKind_schar)
+ return "signed char";
+ else if (k == TypeKind_uchar)
+ return "unsigned char";
else if (k == TypeKind_short)
return "short";
+ else if (k == TypeKind_ushort)
+ return "unsigned short";
else if (k == TypeKind_int)
return "int";
+ else if (k == TypeKind_uint)
+ return "unsigned int";
else if (k == TypeKind_long)
return "long";
- else if (k == TypeKind_void)
- return "void";
- else if (k == TypeKind_ptr)
- return "<pointer>";
- else if (k == TypeKind_array)
- return "<array>";
- else if (k == TypeKind_enum)
- return "enum";
+ else if (k == TypeKind_ulong)
+ return "unsigned long";
+ else if (k == TypeKind_llong)
+ return "long long";
+ else if (k == TypeKind_ullong)
+ return "unsigned long long";
else if (k == TypeKind_struct)
return "struct";
else if (k == TypeKind_union)
return "union";
+ else if (k == TypeKind_enum)
+ return "enum";
+ else if (k == TypeKind_ptr)
+ return "<pointer>";
+ else if (k == TypeKind_array)
+ return "<array>";
else
unreachable();
}
@@ -71,24 +85,25 @@ int type_sizeof(Type* ty) {
fatal_error("type_sizeof: type size cannot be determined");
}
- if (ty->kind == TypeKind_ptr)
- return 8;
- else if (ty->kind == TypeKind_char)
+ if (ty->kind == TypeKind_char || ty->kind == TypeKind_schar || ty->kind == TypeKind_uchar)
return 1;
- else if (ty->kind == TypeKind_short)
+ else if (ty->kind == TypeKind_short || ty->kind == TypeKind_ushort)
return 2;
- else if (ty->kind == TypeKind_int)
+ else if (ty->kind == TypeKind_int || ty->kind == TypeKind_uint)
return 4;
- else if (ty->kind == TypeKind_long)
+ else if (ty->kind == TypeKind_long || ty->kind == TypeKind_ulong || ty->kind == TypeKind_llong ||
+ ty->kind == TypeKind_ullong)
return 8;
- else if (ty->kind == TypeKind_enum)
- return 4;
- else if (ty->kind == TypeKind_array)
- return type_sizeof(ty->base) * ty->array_size;
else if (ty->kind == TypeKind_struct)
return type_sizeof_struct(ty);
else if (ty->kind == TypeKind_union)
return type_sizeof_union(ty);
+ else if (ty->kind == TypeKind_enum)
+ return 4;
+ else if (ty->kind == TypeKind_ptr)
+ return 8;
+ else if (ty->kind == TypeKind_array)
+ return type_sizeof(ty->base) * ty->array_size;
else
unreachable();
}
@@ -98,24 +113,25 @@ int type_alignof(Type* ty) {
fatal_error("type_alignof: type size cannot be determined");
}
- if (ty->kind == TypeKind_ptr)
- return 8;
- else if (ty->kind == TypeKind_char)
+ if (ty->kind == TypeKind_char || ty->kind == TypeKind_schar || ty->kind == TypeKind_uchar)
return 1;
- else if (ty->kind == TypeKind_short)
+ else if (ty->kind == TypeKind_short || ty->kind == TypeKind_ushort)
return 2;
- else if (ty->kind == TypeKind_int)
+ else if (ty->kind == TypeKind_int || ty->kind == TypeKind_uint)
return 4;
- else if (ty->kind == TypeKind_long)
+ else if (ty->kind == TypeKind_long || ty->kind == TypeKind_ulong || ty->kind == TypeKind_llong ||
+ ty->kind == TypeKind_ullong)
return 8;
- else if (ty->kind == TypeKind_enum)
- return 4;
- else if (ty->kind == TypeKind_array)
- return type_alignof(ty->base);
else if (ty->kind == TypeKind_struct)
return type_alignof_struct(ty);
else if (ty->kind == TypeKind_union)
return type_alignof_union(ty);
+ else if (ty->kind == TypeKind_enum)
+ return 4;
+ else if (ty->kind == TypeKind_ptr)
+ return 8;
+ else if (ty->kind == TypeKind_array)
+ return type_alignof(ty->base);
else
unreachable();
}
diff --git a/src/ast.h b/src/ast.h
index 8e70260..13fbf55 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -18,16 +18,23 @@ typedef enum StorageClass StorageClass;
enum TypeKind {
TypeKind_unknown,
+ TypeKind_void,
TypeKind_char,
+ TypeKind_schar,
+ TypeKind_uchar,
TypeKind_short,
+ TypeKind_ushort,
TypeKind_int,
+ TypeKind_uint,
TypeKind_long,
- TypeKind_void,
- TypeKind_ptr,
- TypeKind_array,
- TypeKind_enum,
+ TypeKind_ulong,
+ TypeKind_llong,
+ TypeKind_ullong,
TypeKind_struct,
TypeKind_union,
+ TypeKind_enum,
+ TypeKind_ptr,
+ TypeKind_array,
};
typedef enum TypeKind TypeKind;
diff --git a/src/parse.c b/src/parse.c
index 422cc64..e2466ad 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -1377,7 +1377,6 @@ static Type* parse_struct_specifier(Parser* p) {
AstNode* members = parse_struct_members(p);
expect(p, TokenKind_brace_r);
- expect(p, TokenKind_semicolon);
p->structs->node_items[struct_idx].node_members = members;
Type* ty = type_new(TypeKind_struct);
@@ -1430,7 +1429,6 @@ static Type* parse_union_specifier(Parser* p) {
AstNode* members = parse_union_members(p);
expect(p, TokenKind_brace_r);
- expect(p, TokenKind_semicolon);
p->unions->node_items[union_idx].node_members = members;
Type* ty = type_new(TypeKind_union);
@@ -1491,6 +1489,90 @@ static Type* parse_enum_specifier(Parser* p) {
return ty;
}
+enum TypeSpecifierMask {
+ // TODO: define these constants with shift operators once ducc supports it.
+ TypeSpecifierMask_void = 1,
+ TypeSpecifierMask_char = 2,
+ TypeSpecifierMask_short = 4,
+ TypeSpecifierMask_int = 8,
+ TypeSpecifierMask_long = 16,
+ // 1 << 5 is used for second 'long'.
+ TypeSpecifierMask_float = 64,
+ TypeSpecifierMask_double = 128,
+ TypeSpecifierMask_signed = 256,
+ TypeSpecifierMask_unsigned = 512,
+ TypeSpecifierMask__BitInt = 1024,
+ TypeSpecifierMask_bool = 2048,
+ TypeSpecifierMask__Complex = 4096,
+ TypeSpecifierMask__Decimal32 = 8192,
+ TypeSpecifierMask__Decimal64 = 16384,
+ TypeSpecifierMask__Decimal128 = 32768,
+ TypeSpecifierMask__Atomic = 65536,
+ TypeSpecifierMask_struct = 131072,
+ TypeSpecifierMask_union = 262144,
+ TypeSpecifierMask_enum = 524288,
+ TypeSpecifierMask_typeof = 1048576,
+ TypeSpecifierMask_typeof_unqual = 2097152,
+ TypeSpecifierMask_typedef_name = 4194304,
+};
+typedef enum TypeSpecifierMask TypeSpecifierMask;
+
+static Type* distinguish_type_from_type_specifiers(int type_specifiers) {
+ if (type_specifiers == TypeSpecifierMask_void) {
+ return type_new(TypeKind_void);
+ } else if (type_specifiers == TypeSpecifierMask_char) {
+ return type_new(TypeKind_char);
+ } else if (type_specifiers == (TypeSpecifierMask_signed + TypeSpecifierMask_char)) {
+ return type_new(TypeKind_schar);
+ } else if (type_specifiers == (TypeSpecifierMask_unsigned + TypeSpecifierMask_char)) {
+ return type_new(TypeKind_uchar);
+ } else if (type_specifiers == TypeSpecifierMask_short ||
+ type_specifiers == (TypeSpecifierMask_signed + TypeSpecifierMask_short) ||
+ type_specifiers == (TypeSpecifierMask_short + TypeSpecifierMask_int) ||
+ type_specifiers == (TypeSpecifierMask_signed + TypeSpecifierMask_short + TypeSpecifierMask_int)) {
+ return type_new(TypeKind_short);
+ } else if (type_specifiers == (TypeSpecifierMask_unsigned + TypeSpecifierMask_short) ||
+ type_specifiers == (TypeSpecifierMask_unsigned + TypeSpecifierMask_short + TypeSpecifierMask_int)) {
+ return type_new(TypeKind_ushort);
+ } else if (type_specifiers == TypeSpecifierMask_int || type_specifiers == TypeSpecifierMask_signed ||
+ type_specifiers == (TypeSpecifierMask_signed + TypeSpecifierMask_int)) {
+ return type_new(TypeKind_int);
+ } else if (type_specifiers == TypeSpecifierMask_unsigned ||
+ type_specifiers == (TypeSpecifierMask_unsigned + TypeSpecifierMask_int)) {
+ return type_new(TypeKind_uint);
+ } else if (type_specifiers == TypeSpecifierMask_long ||
+ type_specifiers == (TypeSpecifierMask_signed + TypeSpecifierMask_long) ||
+ type_specifiers == (TypeSpecifierMask_long + TypeSpecifierMask_int) ||
+ type_specifiers == (TypeSpecifierMask_signed + TypeSpecifierMask_long + TypeSpecifierMask_int)) {
+ return type_new(TypeKind_long);
+ } else if (type_specifiers == (TypeSpecifierMask_unsigned + TypeSpecifierMask_long) ||
+ type_specifiers == (TypeSpecifierMask_unsigned + TypeSpecifierMask_long + TypeSpecifierMask_int)) {
+ return type_new(TypeKind_ulong);
+ } else if (type_specifiers == (TypeSpecifierMask_long + TypeSpecifierMask_long) ||
+ type_specifiers == (TypeSpecifierMask_signed + TypeSpecifierMask_long + TypeSpecifierMask_long) ||
+ type_specifiers == (TypeSpecifierMask_long + TypeSpecifierMask_long + TypeSpecifierMask_int) ||
+ type_specifiers == (TypeSpecifierMask_signed + TypeSpecifierMask_long + TypeSpecifierMask_long +
+ TypeSpecifierMask_int)) {
+ return type_new(TypeKind_llong);
+ } else if (type_specifiers == (TypeSpecifierMask_unsigned + TypeSpecifierMask_long + TypeSpecifierMask_long) ||
+ type_specifiers == (TypeSpecifierMask_unsigned + TypeSpecifierMask_long + TypeSpecifierMask_long +
+ TypeSpecifierMask_int)) {
+ return type_new(TypeKind_ullong);
+ } else if (type_specifiers == TypeSpecifierMask_struct) {
+ return NULL;
+ } else if (type_specifiers == TypeSpecifierMask_union) {
+ return NULL;
+ } else if (type_specifiers == TypeSpecifierMask_enum) {
+ return NULL;
+ } else if (type_specifiers == TypeSpecifierMask_typedef_name) {
+ return NULL;
+ } else if (type_specifiers == 0) {
+ fatal_error("no type specifiers");
+ } else {
+ unimplemented();
+ }
+}
+
// declaration-specifiers:
// { declaration-specifier }+ TODO attribute-specifier-sequence?
//
@@ -1567,6 +1649,7 @@ static Type* parse_enum_specifier(Parser* p) {
// identifier
static Type* parse_declaration_specifiers(Parser* p) {
StorageClass storage_class = StorageClass_unspecified;
+ int type_specifiers = 0;
Type* ty = NULL;
while (1) {
@@ -1593,56 +1676,131 @@ static Type* parse_declaration_specifiers(Parser* p) {
}
// type-specifier-qualifier > type-specifier
else if (tok->kind == TokenKind_keyword_void) {
+ if (type_specifiers & TypeSpecifierMask_void) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
next_token(p);
- ty = type_new(TypeKind_void);
+ type_specifiers += TypeSpecifierMask_void;
} else if (tok->kind == TokenKind_keyword_char) {
+ if (type_specifiers & TypeSpecifierMask_char) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
next_token(p);
- ty = type_new(TypeKind_char);
+ type_specifiers += TypeSpecifierMask_char;
} else if (tok->kind == TokenKind_keyword_short) {
+ if (type_specifiers & TypeSpecifierMask_short) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
next_token(p);
- ty = type_new(TypeKind_short);
+ type_specifiers += TypeSpecifierMask_short;
} else if (tok->kind == TokenKind_keyword_int) {
+ if (type_specifiers & TypeSpecifierMask_int) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
next_token(p);
- ty = type_new(TypeKind_int);
+ type_specifiers += TypeSpecifierMask_int;
} else if (tok->kind == TokenKind_keyword_long) {
+ if (type_specifiers & (TypeSpecifierMask_long + TypeSpecifierMask_long)) {
+ fatal_error("%s:%d: too looong!", tok->loc.filename, tok->loc.line);
+ }
next_token(p);
- ty = type_new(TypeKind_long);
+ type_specifiers += TypeSpecifierMask_long;
} else if (tok->kind == TokenKind_keyword_float) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask_float) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask_float;
} else if (tok->kind == TokenKind_keyword_double) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask_double) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask_double;
} else if (tok->kind == TokenKind_keyword_signed) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask_signed) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask_signed;
} else if (tok->kind == TokenKind_keyword_unsigned) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask_unsigned) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask_unsigned;
} else if (tok->kind == TokenKind_keyword__BitInt) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask__BitInt) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask__BitInt;
} else if (tok->kind == TokenKind_keyword_bool) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask_bool) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask_bool;
} else if (tok->kind == TokenKind_keyword__Complex) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask__Complex) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask__Complex;
} else if (tok->kind == TokenKind_keyword__Decimal32) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask__Decimal32) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask__Decimal32;
} else if (tok->kind == TokenKind_keyword__Decimal64) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask__Decimal64) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask__Decimal64;
} else if (tok->kind == TokenKind_keyword__Decimal128) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask__Decimal128) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask__Decimal128;
} else if (tok->kind == TokenKind_keyword__Atomic) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask__Atomic) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask__Atomic;
} else if (tok->kind == TokenKind_keyword_struct) {
+ if (type_specifiers & TypeSpecifierMask_struct) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
ty = parse_struct_specifier(p);
+ type_specifiers += TypeSpecifierMask_struct;
} else if (tok->kind == TokenKind_keyword_union) {
+ if (type_specifiers & TypeSpecifierMask_union) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
ty = parse_union_specifier(p);
+ type_specifiers += TypeSpecifierMask_union;
} else if (tok->kind == TokenKind_keyword_enum) {
+ if (type_specifiers & TypeSpecifierMask_enum) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
ty = parse_enum_specifier(p);
+ type_specifiers += TypeSpecifierMask_enum;
} else if (tok->kind == TokenKind_keyword_typeof) {
unimplemented();
} else if (tok->kind == TokenKind_keyword_typeof_unqual) {
unimplemented();
} else if (is_typedef_name(p, tok)) {
+ if (type_specifiers & TypeSpecifierMask_typedef_name) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
next_token(p);
int typedef_idx = find_typedef(p, tok->value.string);
ty = p->typedefs->node_items[typedef_idx].ty;
+ type_specifiers += TypeSpecifierMask_typedef_name;
}
// type-specifier-qualifier > type-qualifier
else if (tok->kind == TokenKind_keyword_const) {
@@ -1670,6 +1828,11 @@ static Type* parse_declaration_specifiers(Parser* p) {
}
}
+ Type* ty_ = distinguish_type_from_type_specifiers(type_specifiers);
+ if (ty_) {
+ ty = ty_;
+ }
+
ty->storage_class = storage_class;
return ty;
}
@@ -1677,6 +1840,7 @@ static Type* parse_declaration_specifiers(Parser* p) {
// specifier-qualifier-list:
// { type-specifier-qualifier }+ TODO attribute-specifier-sequence?
static Type* parse_specifier_qualifier_list(Parser* p) {
+ int type_specifiers = 0;
Type* ty = NULL;
while (1) {
@@ -1684,56 +1848,131 @@ static Type* parse_specifier_qualifier_list(Parser* p) {
// type-specifier-qualifier > type-specifier
if (tok->kind == TokenKind_keyword_void) {
+ if (type_specifiers & TypeSpecifierMask_void) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
next_token(p);
- ty = type_new(TypeKind_void);
+ type_specifiers += TypeSpecifierMask_void;
} else if (tok->kind == TokenKind_keyword_char) {
+ if (type_specifiers & TypeSpecifierMask_char) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
next_token(p);
- ty = type_new(TypeKind_char);
+ type_specifiers += TypeSpecifierMask_char;
} else if (tok->kind == TokenKind_keyword_short) {
+ if (type_specifiers & TypeSpecifierMask_short) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
next_token(p);
- ty = type_new(TypeKind_short);
+ type_specifiers += TypeSpecifierMask_short;
} else if (tok->kind == TokenKind_keyword_int) {
+ if (type_specifiers & TypeSpecifierMask_int) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
next_token(p);
- ty = type_new(TypeKind_int);
+ type_specifiers += TypeSpecifierMask_int;
} else if (tok->kind == TokenKind_keyword_long) {
+ if (type_specifiers & (TypeSpecifierMask_long + TypeSpecifierMask_long)) {
+ fatal_error("%s:%d: too looong!", tok->loc.filename, tok->loc.line);
+ }
next_token(p);
- ty = type_new(TypeKind_long);
+ type_specifiers += TypeSpecifierMask_long;
} else if (tok->kind == TokenKind_keyword_float) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask_float) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask_float;
} else if (tok->kind == TokenKind_keyword_double) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask_double) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask_double;
} else if (tok->kind == TokenKind_keyword_signed) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask_signed) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask_signed;
} else if (tok->kind == TokenKind_keyword_unsigned) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask_unsigned) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask_unsigned;
} else if (tok->kind == TokenKind_keyword__BitInt) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask__BitInt) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask__BitInt;
} else if (tok->kind == TokenKind_keyword_bool) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask_bool) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask_bool;
} else if (tok->kind == TokenKind_keyword__Complex) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask__Complex) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask__Complex;
} else if (tok->kind == TokenKind_keyword__Decimal32) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask__Decimal32) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask__Decimal32;
} else if (tok->kind == TokenKind_keyword__Decimal64) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask__Decimal64) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask__Decimal64;
} else if (tok->kind == TokenKind_keyword__Decimal128) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask__Decimal128) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask__Decimal128;
} else if (tok->kind == TokenKind_keyword__Atomic) {
- unimplemented();
+ if (type_specifiers & TypeSpecifierMask__Atomic) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
+ next_token(p);
+ type_specifiers += TypeSpecifierMask__Atomic;
} else if (tok->kind == TokenKind_keyword_struct) {
+ if (type_specifiers & TypeSpecifierMask_struct) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
ty = parse_struct_specifier(p);
+ type_specifiers += TypeSpecifierMask_struct;
} else if (tok->kind == TokenKind_keyword_union) {
+ if (type_specifiers & TypeSpecifierMask_union) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
ty = parse_union_specifier(p);
+ type_specifiers += TypeSpecifierMask_union;
} else if (tok->kind == TokenKind_keyword_enum) {
+ if (type_specifiers & TypeSpecifierMask_enum) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
ty = parse_enum_specifier(p);
+ type_specifiers += TypeSpecifierMask_enum;
} else if (tok->kind == TokenKind_keyword_typeof) {
unimplemented();
} else if (tok->kind == TokenKind_keyword_typeof_unqual) {
unimplemented();
} else if (is_typedef_name(p, tok)) {
+ if (type_specifiers & TypeSpecifierMask_typedef_name) {
+ fatal_error("%s:%d: duplicate '%s'", tok->loc.filename, tok->loc.line, token_stringify(tok));
+ }
next_token(p);
int typedef_idx = find_typedef(p, tok->value.string);
ty = p->typedefs->node_items[typedef_idx].ty;
+ type_specifiers += TypeSpecifierMask_typedef_name;
}
// type-specifier-qualifier > type-qualifier
else if (tok->kind == TokenKind_keyword_const) {
@@ -1754,6 +1993,11 @@ static Type* parse_specifier_qualifier_list(Parser* p) {
}
}
+ Type* ty_ = distinguish_type_from_type_specifiers(type_specifiers);
+ if (ty_) {
+ ty = ty_;
+ }
+
return ty;
}