- 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();
- }
-end_error:
- return;
-}
-
-static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind)
-{
- entity_t *entity = allocate_entity_zero(kind);
- entity->base.source_position = *HERE;
- entity->base.symbol = symbol;
- if (is_declaration(entity)) {
- entity->declaration.type = type_error_type;
- entity->declaration.implicit = true;
- } else if (kind == ENTITY_TYPEDEF) {
- entity->typedefe.type = type_error_type;
- entity->typedefe.builtin = true;
- }
- if (kind != ENTITY_COMPOUND_MEMBER)
- record_entity(entity, false);
- return entity;
-}
-
-static variable_t *parse_microsoft_based(void)
-{
- if (token.type != T_IDENTIFIER) {
- parse_error_expected("while parsing __based", T_IDENTIFIER, NULL);
- return NULL;
- }
- symbol_t *symbol = token.v.symbol;
- entity_t *entity = get_entity(symbol, NAMESPACE_NORMAL);
-
- variable_t *variable;
- if (entity == NULL || entity->base.kind != ENTITY_VARIABLE) {
- errorf(HERE, "'%Y' is not a variable name.", symbol);
- variable = &create_error_entity(symbol, ENTITY_VARIABLE)->variable;
- } else {
- variable = &entity->variable;