typedef entity_t* (*parsed_declaration_func) (entity_t *declaration, bool is_definition);
/** The current token. */
-static token_t token;
+static token_t token;
/** The lookahead ring-buffer. */
-static token_t lookahead_buffer[MAX_LOOKAHEAD];
+static token_t lookahead_buffer[MAX_LOOKAHEAD];
/** Position of the next token in the lookahead buffer. */
-static int lookahead_bufpos;
-static stack_entry_t *environment_stack = NULL;
-static stack_entry_t *label_stack = NULL;
-static scope_t *file_scope = NULL;
-static scope_t *current_scope = NULL;
+static int lookahead_bufpos;
+static stack_entry_t *environment_stack = NULL;
+static stack_entry_t *label_stack = NULL;
+static scope_t *file_scope = NULL;
+static scope_t *current_scope = NULL;
/** Point to the current function declaration if inside a function. */
-static function_t *current_function = NULL;
-static entity_t *current_init_decl = NULL;
-static switch_statement_t *current_switch = NULL;
-static statement_t *current_loop = NULL;
-static statement_t *current_parent = NULL;
-static ms_try_statement_t *current_try = NULL;
-static linkage_kind_t current_linkage = LINKAGE_INVALID;
-static goto_statement_t *goto_first = NULL;
-static goto_statement_t *goto_last = NULL;
-static label_statement_t *label_first = NULL;
-static label_statement_t *label_last = NULL;
+static function_t *current_function = NULL;
+static entity_t *current_init_decl = NULL;
+static switch_statement_t *current_switch = NULL;
+static statement_t *current_loop = NULL;
+static statement_t *current_parent = NULL;
+static ms_try_statement_t *current_try = NULL;
+static linkage_kind_t current_linkage = LINKAGE_INVALID;
+static goto_statement_t *goto_first = NULL;
+static goto_statement_t **goto_anchor = NULL;
+static label_statement_t *label_first = NULL;
+static label_statement_t **label_anchor = NULL;
/** current translation unit. */
-static translation_unit_t *unit = NULL;
+static translation_unit_t *unit = NULL;
/** true if we are in a type property context (evaluation only for type. */
-static bool in_type_prop = false;
+static bool in_type_prop = false;
/** true in we are in a __extension__ context. */
-static bool in_gcc_extension = false;
-static struct obstack temp_obst;
+static bool in_gcc_extension = false;
+static struct obstack temp_obst;
#define PUSH_PARENT(stmt) \
return (construct_type_t*) array;
}
-static construct_type_t *parse_function_declarator(scope_t *scope)
+static construct_type_t *parse_function_declarator(scope_t *scope,
+ decl_modifiers_t modifiers)
{
- type_t *type = allocate_type_zero(TYPE_FUNCTION);
+ type_t *type = allocate_type_zero(TYPE_FUNCTION);
+ function_type_t *ftype = &type->function;
- type->function.linkage = current_linkage;
+ ftype->linkage = current_linkage;
- /* TODO: revive this... once we know exactly how to do it */
-#if 0
- decl_modifiers_t modifiers = entity->declaration.modifiers;
-
- unsigned mask = modifiers & (DM_CDECL|DM_STDCALL|DM_FASTCALL|DM_THISCALL);
+ switch (modifiers & (DM_CDECL | DM_STDCALL | DM_FASTCALL | DM_THISCALL)) {
+ case DM_NONE: break;
+ case DM_CDECL: ftype->calling_convention = CC_CDECL; break;
+ case DM_STDCALL: ftype->calling_convention = CC_STDCALL; break;
+ case DM_FASTCALL: ftype->calling_convention = CC_FASTCALL; break;
+ case DM_THISCALL: ftype->calling_convention = CC_THISCALL; break;
- if (mask & (mask-1)) {
- const char *first = NULL, *second = NULL;
-
- /* more than one calling convention set */
- if (modifiers & DM_CDECL) {
- if (first == NULL) first = "cdecl";
- else if (second == NULL) second = "cdecl";
- }
- if (modifiers & DM_STDCALL) {
- if (first == NULL) first = "stdcall";
- else if (second == NULL) second = "stdcall";
- }
- if (modifiers & DM_FASTCALL) {
- if (first == NULL) first = "fastcall";
- else if (second == NULL) second = "fastcall";
- }
- if (modifiers & DM_THISCALL) {
- if (first == NULL) first = "thiscall";
- else if (second == NULL) second = "thiscall";
- }
- errorf(&entity->base.source_position,
- "%s and %s attributes are not compatible", first, second);
+ default:
+ errorf(HERE, "multiple calling conventions in declaration");
+ break;
}
- if (modifiers & DM_CDECL)
- type->function.calling_convention = CC_CDECL;
- else if (modifiers & DM_STDCALL)
- type->function.calling_convention = CC_STDCALL;
- else if (modifiers & DM_FASTCALL)
- type->function.calling_convention = CC_FASTCALL;
- else if (modifiers & DM_THISCALL)
- type->function.calling_convention = CC_THISCALL;
-#endif
-
- parse_parameters(&type->function, scope);
+ parse_parameters(ftype, scope);
construct_function_type_t *construct_function_type =
obstack_alloc(&temp_obst, sizeof(construct_function_type[0]));
modifiers |= parse_attributes(&attributes);
}
- if (env != NULL)
- env->modifiers |= modifiers;
+ if (env != NULL) {
+ modifiers |= env->modifiers;
+ env->modifiers = modifiers;
+ }
construct_type_t *inner_types = NULL;
if (env != NULL)
scope = &env->parameters;
- type = parse_function_declarator(scope);
+ type = parse_function_declarator(scope, modifiers);
break;
}
case '[':
{
parse_declarator_env_t env;
memset(&env, 0, sizeof(env));
+ env.modifiers = specifiers->modifiers;
construct_type_t *construct_type
= parse_inner_declarator(&env, may_be_abstract);
}
}
- entity->base.source_position = env.source_position;
- entity->base.symbol = env.symbol;
- entity->base.namespc = NAMESPACE_NORMAL;
- entity->declaration.type = type;
- entity->declaration.modifiers = env.modifiers | specifiers->modifiers;
+ entity->base.source_position = env.source_position;
+ entity->base.symbol = env.symbol;
+ entity->base.namespc = NAMESPACE_NORMAL;
+ entity->declaration.type = type;
+ entity->declaration.modifiers = env.modifiers;
entity->declaration.deprecated_string = specifiers->deprecated_string;
storage_class_t storage_class = specifiers->storage_class;
"label '%Y' used but not defined", label->base.symbol);
}
}
- goto_first = NULL;
- goto_last = NULL;
if (warning.unused_label) {
for (const label_statement_t *label_statement = label_first;
}
}
}
- label_first = label_last = NULL;
}
static void warn_unused_decl(entity_t *entity, entity_t *end,
current_function = function;
current_parent = NULL;
- statement_t *const body = parse_compound_statement(false);
+ goto_first = NULL;
+ goto_anchor = &goto_first;
+ label_first = NULL;
+ label_anchor = &label_first;
+
+ statement_t *const body = parse_compound_statement(false);
function->statement = body;
first_err = true;
check_labels();
cnst->conste.v.character = token.v.string;
if (cnst->conste.v.character.size != 1) {
- if (warning.multichar && GNU_MODE) {
+ if (!GNU_MODE) {
+ errorf(HERE, "more than 1 character in character constant");
+ } else if (warning.multichar) {
warningf(HERE, "multi-character character constant");
- } else {
- errorf(HERE, "more than 1 characters in character constant");
}
}
next_token();
cnst->conste.v.wide_character = token.v.wide_string;
if (cnst->conste.v.wide_character.size != 1) {
- if (warning.multichar && GNU_MODE) {
+ if (!GNU_MODE) {
+ errorf(HERE, "more than 1 character in character constant");
+ } else if (warning.multichar) {
warningf(HERE, "multi-character character constant");
- } else {
- errorf(HERE, "more than 1 characters in character constant");
}
}
next_token();
eat(kind == EXPR_SIZEOF ? T_sizeof : T___alignof__);
- char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof";
-
/* we only refer to a type property, mark this case */
bool old = in_type_prop;
in_type_prop = true;
type->kind == TYPE_BITFIELD ? "bitfield" :
NULL;
if (wrong_type != NULL) {
+ char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof";
errorf(&tp_expression->base.source_position,
"operand of %s expression must not be of %s type '%T'",
what, wrong_type, orig_type);
*/
static asm_argument_t *parse_asm_arguments(bool is_out)
{
- asm_argument_t *result = NULL;
- asm_argument_t *last = NULL;
+ asm_argument_t *result = NULL;
+ asm_argument_t **anchor = &result;
while (token.type == T_STRING_LITERAL || token.type == '[') {
asm_argument_t *argument = allocate_ast_zero(sizeof(argument[0]));
set_address_taken(expression, true);
- if (last != NULL) {
- last->next = argument;
- } else {
- result = argument;
- }
- last = argument;
+ *anchor = argument;
+ anchor = &argument->next;
if (token.type != ',')
break;
}
/* remember the labels in a list for later checking */
- if (label_last == NULL) {
- label_first = &statement->label;
- } else {
- label_last->next = &statement->label;
- }
- label_last = &statement->label;
+ *label_anchor = &statement->label;
+ label_anchor = &statement->label.next;
POP_PARENT;
return statement;
expression_t *expression = parse_expression();
mark_vars_read(expression, NULL);
- /* Argh: although documentation say the expression must be of type void *,
- * gcc excepts anything that can be casted into void * without error */
+ /* Argh: although documentation says the expression must be of type void*,
+ * gcc accepts anything that can be casted into void* without error */
type_t *type = expression->base.type;
if (type != type_error_type) {
}
/* remember the goto's in a list for later checking */
- if (goto_last == NULL) {
- goto_first = &statement->gotos;
- } else {
- goto_last->next = &statement->gotos;
- }
- goto_last = &statement->gotos;
+ *goto_anchor = &statement->gotos;
+ goto_anchor = &statement->gotos.next;
expect(';');