- break;
-
- TYPENAME_START
- type = parse_typename();
- break;
-
- default:
- expression = parse_expression();
- type = expression->base.type;
- break;
- }
- in_type_prop = old_type_prop;
- in_gcc_extension = old_gcc_extension;
-
- rem_anchor_token(')');
- expect(')', end_error);
-
- type_t *typeof_type = allocate_type_zero(TYPE_TYPEOF);
- typeof_type->typeoft.expression = expression;
- typeof_type->typeoft.typeof_type = type;
-
- return typeof_type;
-end_error:
- return NULL;
-}
-
-typedef enum specifiers_t {
- SPECIFIER_SIGNED = 1 << 0,
- SPECIFIER_UNSIGNED = 1 << 1,
- SPECIFIER_LONG = 1 << 2,
- SPECIFIER_INT = 1 << 3,
- SPECIFIER_DOUBLE = 1 << 4,
- SPECIFIER_CHAR = 1 << 5,
- SPECIFIER_WCHAR_T = 1 << 6,
- SPECIFIER_SHORT = 1 << 7,
- SPECIFIER_LONG_LONG = 1 << 8,
- SPECIFIER_FLOAT = 1 << 9,
- SPECIFIER_BOOL = 1 << 10,
- SPECIFIER_VOID = 1 << 11,
- SPECIFIER_INT8 = 1 << 12,
- SPECIFIER_INT16 = 1 << 13,
- SPECIFIER_INT32 = 1 << 14,
- SPECIFIER_INT64 = 1 << 15,
- SPECIFIER_INT128 = 1 << 16,
- SPECIFIER_COMPLEX = 1 << 17,
- SPECIFIER_IMAGINARY = 1 << 18,
-} specifiers_t;
-
-static type_t *create_builtin_type(symbol_t *const symbol,
- type_t *const real_type)
-{
- type_t *type = allocate_type_zero(TYPE_BUILTIN);
- type->builtin.symbol = symbol;
- type->builtin.real_type = real_type;
- return identify_new_type(type);
-}
-
-static type_t *get_typedef_type(symbol_t *symbol)
-{
- entity_t *entity = get_entity(symbol, NAMESPACE_NORMAL);
- if (entity == NULL || entity->kind != ENTITY_TYPEDEF)
- return NULL;
-
- type_t *type = allocate_type_zero(TYPE_TYPEDEF);
- type->typedeft.typedefe = &entity->typedefe;
-
- return type;
-}
-
-/**
- * check for the allowed MS alignment values.
- */
-static bool check_alignment_value(long long intvalue)
-{
- if (intvalue < 1 || intvalue > 8192) {
- errorf(HERE, "illegal alignment value");
- return false;
- }
- unsigned v = (unsigned)intvalue;
- for (unsigned i = 1; i <= 8192; i += i) {
- if (i == v)
- return true;
- }
- errorf(HERE, "alignment must be power of two");
- return false;
-}
-
-#define DET_MOD(name, tag) do { \
- if (*modifiers & tag && warning.other) warningf(HERE, #name " used more than once"); \
- *modifiers |= tag; \
-} while (0)
-
-static void parse_microsoft_extended_decl_modifier(declaration_specifiers_t *specifiers)
-{
- decl_modifiers_t *modifiers = &specifiers->modifiers;
-
- while (true) {
- if (token.type == T_restrict) {
- next_token();
- DET_MOD(restrict, DM_RESTRICT);
- goto end_loop;
- } else if (token.type != T_IDENTIFIER)
- break;
- symbol_t *symbol = token.v.symbol;
- if (symbol == sym_align) {
- next_token();
- expect('(', end_error);
- if (token.type != T_INTEGER)
- goto end_error;
- if (check_alignment_value(token.v.intvalue)) {
- if (specifiers->alignment != 0 && warning.other)
- warningf(HERE, "align used more than once");
- specifiers->alignment = (unsigned char)token.v.intvalue;
- }
- next_token();
- expect(')', end_error);
- } else if (symbol == sym_allocate) {
- next_token();
- expect('(', end_error);
- if (token.type != T_IDENTIFIER)
- goto end_error;
- (void)token.v.symbol;
- expect(')', end_error);
- } else if (symbol == sym_dllimport) {
- next_token();
- DET_MOD(dllimport, DM_DLLIMPORT);
- } else if (symbol == sym_dllexport) {
- next_token();
- DET_MOD(dllexport, DM_DLLEXPORT);
- } else if (symbol == sym_thread) {
- next_token();
- DET_MOD(thread, DM_THREAD);
- } else if (symbol == sym_naked) {
- next_token();
- DET_MOD(naked, DM_NAKED);
- } else if (symbol == sym_noinline) {
- next_token();
- DET_MOD(noinline, DM_NOINLINE);
- } else if (symbol == sym_returns_twice) {
- next_token();
- DET_MOD(returns_twice, DM_RETURNS_TWICE);
- } else if (symbol == sym_noreturn) {
- next_token();
- DET_MOD(noreturn, DM_NORETURN);
- } else if (symbol == sym_nothrow) {
- next_token();
- DET_MOD(nothrow, DM_NOTHROW);
- } else if (symbol == sym_novtable) {
- next_token();
- DET_MOD(novtable, DM_NOVTABLE);
- } else if (symbol == sym_property) {
- next_token();
- expect('(', end_error);
- for (;;) {
- bool is_get = false;
- if (token.type != T_IDENTIFIER)
- goto end_error;
- if (token.v.symbol == sym_get) {
- is_get = true;
- } else if (token.v.symbol == sym_put) {
- } else {
- errorf(HERE, "Bad property name '%Y'", token.v.symbol);
- goto end_error;
- }
- next_token();
- expect('=', end_error);
- if (token.type != T_IDENTIFIER)
- goto end_error;
- if (is_get) {
- if (specifiers->get_property_sym != NULL) {
- errorf(HERE, "get property name already specified");
- } else {
- specifiers->get_property_sym = token.v.symbol;
- }
- } else {
- if (specifiers->put_property_sym != NULL) {
- errorf(HERE, "put property name already specified");
- } else {
- specifiers->put_property_sym = token.v.symbol;
- }
- }
- next_token();
- if (token.type == ',') {
- next_token();
- continue;
- }
- break;
- }
- expect(')', end_error);
- } else if (symbol == sym_selectany) {
- next_token();
- DET_MOD(selectany, DM_SELECTANY);
- } else if (symbol == sym_uuid) {
- next_token();
- expect('(', end_error);
- if (token.type != T_STRING_LITERAL)
- goto end_error;
- next_token();
- expect(')', end_error);
- } else if (symbol == sym_deprecated) {
- next_token();
- if (specifiers->deprecated != 0 && warning.other)
- warningf(HERE, "deprecated used more than once");
- specifiers->deprecated = true;
- if (token.type == '(') {
- next_token();
- if (token.type == T_STRING_LITERAL) {
- specifiers->deprecated_string = token.v.string.begin;
- next_token();
- } else {
- errorf(HERE, "string literal expected");
- }
- expect(')', end_error);
- }
- } else if (symbol == sym_noalias) {
- next_token();
- DET_MOD(noalias, DM_NOALIAS);
- } else {
- if (warning.other)
- warningf(HERE, "Unknown modifier '%Y' ignored", token.v.symbol);
- next_token();
- if (token.type == '(')
- skip_until(')');
- }
-end_loop:
- if (token.type == ',')
- next_token();