static elf_visibility_tag_t default_visibility = ELF_VISIBILITY_DEFAULT;
+#define PUSH_CURRENT_ENTITY(entity) \
+ entity_t *const new_current_entity = (entity); \
+ entity_t *const old_current_entity = current_entity; \
+ ((void)(current_entity = new_current_entity))
+#define POP_CURRENT_ENTITY() (assert(current_entity == new_current_entity), (void)(current_entity = old_current_entity))
+
#define PUSH_PARENT(stmt) \
statement_t *const new_parent = (stmt); \
statement_t *const old_parent = current_parent; \
#define PUSH_SCOPE(scope) \
size_t const top = environment_top(); \
scope_t *const new_scope = (scope); \
- scope_t *const old_scope = scope_push(new_scope)
-#define POP_SCOPE() (assert(current_scope == new_scope), scope_pop(old_scope), environment_pop_to(top))
+ scope_t *const old_scope = (new_scope ? scope_push(new_scope) : NULL)
+#define PUSH_SCOPE_STATEMENT(scope) PUSH_SCOPE(c_mode & (_C99 | _CXX) ? (scope) : NULL)
+#define POP_SCOPE() (new_scope ? assert(current_scope == new_scope), scope_pop(old_scope), environment_pop_to(top) : (void)0)
#define PUSH_EXTENSION() \
(void)0; \
case T_ANDAND: \
case T_CHARACTER_CONSTANT: \
case T_FLOATINGPOINT: \
- case T_FLOATINGPOINT_HEXADECIMAL: \
case T_INTEGER: \
- case T_INTEGER_HEXADECIMAL: \
- case T_INTEGER_OCTAL: \
case T_MINUSMINUS: \
case T_PLUSPLUS: \
case T_STRING_LITERAL: \
[EXPR_ENUM_CONSTANT] = sizeof(reference_expression_t),
[EXPR_LITERAL_BOOLEAN] = sizeof(literal_expression_t),
[EXPR_LITERAL_INTEGER] = sizeof(literal_expression_t),
- [EXPR_LITERAL_INTEGER_OCTAL] = sizeof(literal_expression_t),
- [EXPR_LITERAL_INTEGER_HEXADECIMAL]= sizeof(literal_expression_t),
[EXPR_LITERAL_FLOATINGPOINT] = sizeof(literal_expression_t),
- [EXPR_LITERAL_FLOATINGPOINT_HEXADECIMAL] = sizeof(literal_expression_t),
[EXPR_LITERAL_CHARACTER] = sizeof(literal_expression_t),
[EXPR_LITERAL_WIDE_CHARACTER] = sizeof(literal_expression_t),
[EXPR_STRING_LITERAL] = sizeof(string_literal_expression_t),
#endif
}
-static inline bool next_if(int const type)
+static inline bool next_if(token_kind_t const type)
{
if (token.kind == type) {
next_token();
/**
* Adds a token type to the token type anchor set (a multi-set).
*/
-static void add_anchor_token(int token_kind)
+static void add_anchor_token(token_kind_t const token_kind)
{
- assert(0 <= token_kind && token_kind < T_LAST_TOKEN);
+ assert(token_kind < T_LAST_TOKEN);
++token_anchor_set[token_kind];
}
-/**
- * Set the number of tokens types of the given type
- * to zero and return the old count.
- */
-static int save_and_reset_anchor_state(int token_kind)
-{
- assert(0 <= token_kind && token_kind < T_LAST_TOKEN);
- int count = token_anchor_set[token_kind];
- token_anchor_set[token_kind] = 0;
- return count;
-}
-
-/**
- * Restore the number of token types to the given count.
- */
-static void restore_anchor_state(int token_kind, int count)
-{
- assert(0 <= token_kind && token_kind < T_LAST_TOKEN);
- token_anchor_set[token_kind] = count;
-}
-
/**
* Remove a token type from the token type anchor set (a multi-set).
*/
-static void rem_anchor_token(int token_kind)
+static void rem_anchor_token(token_kind_t const token_kind)
{
- assert(0 <= token_kind && token_kind < T_LAST_TOKEN);
+ assert(token_kind < T_LAST_TOKEN);
assert(token_anchor_set[token_kind] != 0);
--token_anchor_set[token_kind];
}
/**
* Eat tokens until a matching token type is found.
*/
-static void eat_until_matching_token(int type)
+static void eat_until_matching_token(token_kind_t const type)
{
- int end_token;
+ token_kind_t end_token;
switch (type) {
case '(': end_token = ')'; break;
case '{': end_token = '}'; break;
if (token.kind != T_IDENTIFIER)
return NULL;
}
- symbol_t *const sym = token.identifier.symbol;
+ symbol_t *const sym = token.base.symbol;
if (pos)
*pos = *HERE;
eat(T_IDENTIFIER);
/* is it an identifier */
if (token.kind == T_IDENTIFIER
&& (look_ahead(1)->kind == ',' || look_ahead(1)->kind == ')')) {
- symbol_t *symbol = token.identifier.symbol;
argument->kind = ATTRIBUTE_ARGUMENT_SYMBOL;
- argument->v.symbol = symbol;
+ argument->v.symbol = token.base.symbol;
next_token();
} else {
/* must be an expression */
return attribute;
}
-static symbol_t *get_symbol_from_token(void)
-{
- switch(token.kind) {
- case T_IDENTIFIER:
- return token.identifier.symbol;
- case T_auto:
- case T_char:
- case T_double:
- case T_enum:
- case T_extern:
- case T_float:
- case T_int:
- case T_long:
- case T_register:
- case T_short:
- case T_static:
- case T_struct:
- case T_union:
- case T_unsigned:
- case T_void:
- case T_bool:
- case T__Bool:
- case T_class:
- case T_explicit:
- case T_export:
- case T_wchar_t:
- case T_const:
- case T_signed:
- case T___real__:
- case T___imag__:
- case T_restrict:
- case T_volatile:
- case T_inline:
- /* maybe we need more tokens ... add them on demand */
- return get_token_kind_symbol(token.kind);
- default:
- return NULL;
- }
-}
-
static attribute_t *parse_attribute_gnu_single(void)
{
/* parse "any-word" */
- symbol_t *symbol = get_symbol_from_token();
+ symbol_t *const symbol = token.base.symbol;
if (symbol == NULL) {
parse_error_expected("while parsing attribute((", T_IDENTIFIER, NULL);
return NULL;
/* GNU-style designator ("identifier: value") */
designator = allocate_ast_zero(sizeof(designator[0]));
designator->source_position = token.base.source_position;
- designator->symbol = token.identifier.symbol;
+ designator->symbol = token.base.symbol;
eat(T_IDENTIFIER);
eat(':');
} else {
if (type == NULL) {
if (env->entity != NULL) {
- errorf(HERE,
- "extra brace group at end of initializer for '%Y'",
- env->entity->base.symbol);
+ errorf(HERE, "extra brace group at end of initializer for '%N'", env->entity);
} else {
errorf(HERE, "extra brace group at end of initializer");
}
source_position_t const* const pos = &expression->base.source_position;
if (env->entity != NULL) {
- warningf(WARN_OTHER, pos, "excess elements in initializer for '%Y'", env->entity->base.symbol);
+ warningf(WARN_OTHER, pos, "excess elements in initializer for '%N'", env->entity);
} else {
warningf(WARN_OTHER, pos, "excess elements in initializer");
}
entity_kind_tag_t const kind = is_struct ? ENTITY_STRUCT : ENTITY_UNION;
if (token.kind == T_IDENTIFIER) {
/* the compound has a name, check if we have seen it already */
- symbol = token.identifier.symbol;
+ symbol = token.base.symbol;
entity = get_tag(symbol, kind);
next_token();
eat(T_enum);
switch (token.kind) {
case T_IDENTIFIER:
- symbol = token.identifier.symbol;
+ symbol = token.base.symbol;
entity = get_tag(symbol, ENTITY_ENUM);
next_token();
switch (token.kind) {
case T_IDENTIFIER:
- if (is_typedef_symbol(token.identifier.symbol)) {
+ if (is_typedef_symbol(token.base.symbol)) {
DECLARATION_START
type = parse_typename();
} else {
if (next_if(T_restrict)) {
kind = ATTRIBUTE_MS_RESTRICT;
} else if (token.kind == T_IDENTIFIER) {
- const char *name = token.identifier.symbol->string;
+ char const *const name = token.base.symbol->string;
for (attribute_kind_t k = ATTRIBUTE_MS_FIRST; k <= ATTRIBUTE_MS_LAST;
++k) {
const char *attribute_name = get_attribute_name(k);
}
}
- type_t *const typedef_type = get_typedef_type(token.identifier.symbol);
+ type_t *const typedef_type = get_typedef_type(token.base.symbol);
if (typedef_type == NULL) {
/* Be somewhat resilient to typos like 'vodi f()' at the beginning of a
* declaration, so it doesn't generate 'implicit int' followed by more
case '*': {
errorf(HERE, "%K does not name a type", &token);
- symbol_t *symbol = token.identifier.symbol;
- entity_t *entity
- = create_error_entity(symbol, ENTITY_TYPEDEF);
+ entity_t *const entity = create_error_entity(token.base.symbol, ENTITY_TYPEDEF);
type = allocate_type_zero(TYPE_TYPEDEF);
type->typedeft.typedefe = &entity->typedefe;
{
assert(token.kind == T_IDENTIFIER);
do {
- entity_t *const entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, token.identifier.symbol, HERE);
+ entity_t *const entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, token.base.symbol, HERE);
/* a K&R parameter has no type, yet */
next_token();
if (look_ahead(1)->kind != ')')
return true;
if (token.kind == T_IDENTIFIER) {
- entity_t const *const entity
- = get_entity(token.identifier.symbol, NAMESPACE_NORMAL);
+ entity_t const *const entity = get_entity(token.base.symbol, NAMESPACE_NORMAL);
if (entity == NULL)
return true;
if (entity->kind != ENTITY_TYPEDEF)
{
eat('(');
add_anchor_token(')');
- int saved_comma_state = save_and_reset_anchor_state(',');
- if (token.kind == T_IDENTIFIER
- && !is_typedef_symbol(token.identifier.symbol)) {
- token_kind_t la1_type = (token_kind_t)look_ahead(1)->kind;
- if (la1_type == ',' || la1_type == ')') {
- type->kr_style_parameters = true;
- parse_identifier_list(scope);
- goto parameters_finished;
- }
- }
-
- if (token.kind == ')') {
+ if (token.kind == T_IDENTIFIER &&
+ !is_typedef_symbol(token.base.symbol) &&
+ (look_ahead(1)->kind == ',' || look_ahead(1)->kind == ')')) {
+ type->kr_style_parameters = true;
+ parse_identifier_list(scope);
+ } else if (token.kind == ')') {
/* ISO/IEC 14882:1998(E) §C.1.6:1 */
if (!(c_mode & _CXX))
type->unspecified_parameters = true;
} else if (has_parameters()) {
function_parameter_t **anchor = &type->parameters;
+ add_anchor_token(',');
do {
switch (token.kind) {
case T_DOTDOTDOT:
goto parameters_finished;
}
} while (next_if(','));
+parameters_finished:
+ rem_anchor_token(',');
}
-parameters_finished:
rem_anchor_token(')');
expect(')');
-
- restore_anchor_state(',', saved_comma_state);
}
typedef enum construct_type_kind_t {
if (env->must_be_abstract) {
errorf(HERE, "no identifier expected in typename");
} else {
- env->symbol = token.identifier.symbol;
+ env->symbol = token.base.symbol;
env->source_position = token.base.source_position;
}
next_token();
token_t const *const la1 = look_ahead(1);
switch (la1->kind) {
case T_IDENTIFIER:
- if (is_typedef_symbol(la1->identifier.symbol)) {
+ if (is_typedef_symbol(la1->base.symbol)) {
case ')':
/* §6.7.6:2 footnote 126: Empty parentheses in a type name are
* interpreted as ``function with no parameter specification'', rather
if (env.symbol != NULL) {
if (specifiers->is_inline && is_type_valid(type)) {
- errorf(&env.source_position,
- "compound member '%Y' declared 'inline'", env.symbol);
+ errorf(&env.source_position, "'%N' declared 'inline'", entity);
}
if (specifiers->thread_local ||
specifiers->storage_class != STORAGE_CLASS_NONE) {
- errorf(&env.source_position,
- "compound member '%Y' must have no storage class",
- env.symbol);
+ errorf(&env.source_position, "'%N' must have no storage class", entity);
}
}
} else if (flags & DECL_IS_PARAMETER) {
}
}
if (invalid_storage_class) {
- errorf(&env.source_position, "invalid storage class for variable '%N'", entity);
+ errorf(&env.source_position, "invalid storage class for '%N'", entity);
}
}
}
}
}
-/**
- * Check if a symbol is the equal to "main".
- */
-static bool is_sym_main(const symbol_t *const sym)
-{
- return streq(sym->string, "main");
-}
-
static void error_redefined_as_different_kind(const source_position_t *pos,
const entity_t *old, entity_kind_t new_kind)
{
}
}
+static bool is_main(entity_t*);
+
/**
* record entities for the NAMESPACE_NORMAL, and produce error messages/warnings
* for various problems that occur for multiple definitions
if (symbol == NULL)
return entity;
+ assert(!entity->base.parent_scope);
+ assert(current_scope);
+ entity->base.parent_scope = current_scope;
+
entity_t *const previous_entity = get_entity(symbol, namespc);
/* pushing the same entity twice will break the stack structure */
assert(previous_entity != entity);
warningf(WARN_STRICT_PROTOTYPES, pos, "function declaration '%#N' is not a prototype", entity);
}
- if (current_scope == file_scope && is_sym_main(symbol)) {
+ if (is_main(entity)) {
check_main(entity);
}
}
case STORAGE_CLASS_EXTERN:
if (is_definition) {
- if (prev_type->function.unspecified_parameters && !is_sym_main(symbol)) {
+ if (prev_type->function.unspecified_parameters && !is_main(entity)) {
warningf(WARN_MISSING_PROTOTYPES, pos, "no previous prototype for '%#N'", entity);
}
} else if (new_storage_class == STORAGE_CLASS_NONE) {
} else if (!is_definition &&
is_type_valid(prev_type) &&
!pos->is_system_header) {
- warningf(WARN_REDUNDANT_DECLS, pos, "redundant declaration for '%Y' (declared %P)", symbol, ppos);
+ warningf(WARN_REDUNDANT_DECLS, pos, "redundant declaration for '%N' (declared %P)", entity, ppos);
}
} else if (current_function == NULL) {
if (old_storage_class != STORAGE_CLASS_STATIC &&
new_storage_class == STORAGE_CLASS_STATIC) {
- errorf(pos, "static declaration of '%Y' follows non-static declaration (declared %P)", symbol, ppos);
+ errorf(pos, "static declaration of '%N' follows non-static declaration (declared %P)", entity, ppos);
} else if (old_storage_class == STORAGE_CLASS_EXTERN) {
prev_decl->storage_class = STORAGE_CLASS_NONE;
prev_decl->declared_storage_class = STORAGE_CLASS_NONE;
} else if (is_type_valid(prev_type)) {
if (old_storage_class == new_storage_class) {
error_redeclaration:
- errorf(pos, "redeclaration of '%Y' (declared %P)", symbol, ppos);
+ errorf(pos, "redeclaration of '%N' (declared %P)", entity, ppos);
} else {
- errorf(pos, "redeclaration of '%Y' with different linkage (declared %P)", symbol, ppos);
+ errorf(pos, "redeclaration of '%N' with different linkage (declared %P)", entity, ppos);
}
}
}
if (entity->kind == ENTITY_FUNCTION) {
if (is_definition &&
entity->declaration.storage_class != STORAGE_CLASS_STATIC &&
- !is_sym_main(symbol)) {
+ !is_main(entity)) {
if (is_warn_on(WARN_MISSING_PROTOTYPES)) {
warningf(WARN_MISSING_PROTOTYPES, pos, "no previous prototype for '%#N'", entity);
} else {
}
finish:
- assert(entity->base.parent_scope == NULL);
- assert(current_scope != NULL);
-
- entity->base.parent_scope = current_scope;
environment_push(entity);
append_entity(current_scope, entity);
static void parser_error_multiple_definition(entity_t *entity,
const source_position_t *source_position)
{
- errorf(source_position, "multiple definition of '%Y' (declared %P)",
- entity->base.symbol, &entity->base.source_position);
+ errorf(source_position, "redefinition of '%N' (declared %P)", entity, &entity->base.source_position);
}
static bool is_declaration_specifier(const token_t *token)
DECLARATION_START
return true;
case T_IDENTIFIER:
- return is_typedef_symbol(token->identifier.symbol);
+ return is_typedef_symbol(token->base.symbol);
default:
return false;
{
if (is_warn_on(WARN_UNUSED_PARAMETER)) {
const scope_t *scope = ¤t_function->parameters;
-
- /* do not issue unused warnings for main */
- if (!is_sym_main(current_function->base.base.symbol)) {
- warn_unused_entity(WARN_UNUSED_PARAMETER, scope->entities, NULL);
- }
+ warn_unused_entity(WARN_UNUSED_PARAMETER, scope->entities, NULL);
}
if (is_warn_on(WARN_UNUSED_VARIABLE)) {
walk_statements(current_function->statement, check_unused_variables,
type_t *const ret = skip_typeref(type->function.return_type);
if (!is_type_void(ret) &&
is_type_valid(ret) &&
- !is_sym_main(current_function->base.base.symbol)) {
+ !is_main(current_entity)) {
source_position_t const *const pos = &stmt->base.source_position;
warningf(WARN_RETURN_TYPE, pos, "control reaches end of non-void function");
}
return true;
}
+static void prepare_main_collect2(entity_t*);
+
static void parse_external_declaration(void)
{
/* function-definitions and declarations both start with declaration
if (ndeclaration != entity) {
function->parameters = ndeclaration->function.parameters;
}
- assert(is_declaration(entity));
- type = skip_typeref(entity->declaration.type);
PUSH_SCOPE(&function->parameters);
/* parse function body */
int label_stack_top = label_top();
function_t *old_current_function = current_function;
- entity_t *old_current_entity = current_entity;
current_function = function;
- current_entity = entity;
+ PUSH_CURRENT_ENTITY(entity);
PUSH_PARENT(NULL);
goto_first = NULL;
}
}
- if (is_main(entity) && enable_main_collect2_hack)
- prepare_main_collect2(entity);
+ if (is_main(entity)) {
+ /* Force main to C linkage. */
+ type_t *const type = entity->declaration.type;
+ assert(is_type_function(type));
+ if (type->function.linkage != LINKAGE_C) {
+ type_t *new_type = duplicate_type(type);
+ new_type->function.linkage = LINKAGE_C;
+ entity->declaration.type = identify_new_type(new_type);
+ }
+ if (enable_main_collect2_hack)
+ prepare_main_collect2(entity);
+ }
+
+ POP_CURRENT_ENTITY();
POP_PARENT();
assert(current_function == function);
- assert(current_entity == entity);
- current_entity = old_current_entity;
current_function = old_current_function;
label_pop_to(label_stack_top);
}
entity_t *prev = find_compound_entry(compound, symbol);
if (prev != NULL) {
source_position_t const *const ppos = &prev->base.source_position;
- errorf(pos, "multiple declarations of symbol '%Y' (declared %P)", symbol, ppos);
+ errorf(pos, "multiple declarations of '%N' (declared %P)", entity, ppos);
}
}
static expression_parser_function_t expression_parsers[T_LAST_TOKEN];
-/**
- * Prints an error message if an expression was expected but not read
- */
-static expression_t *expected_expression_error(void)
-{
- /* skip the error message if the error token was read */
- if (token.kind != T_ERROR) {
- errorf(HERE, "expected expression, got token %K", &token);
- }
- next_token();
-
- return create_error_expression();
-}
-
static type_t *get_string_type(void)
{
return is_warn_on(WARN_WRITE_STRINGS) ? type_const_char_ptr : type_char_ptr;
check_integer_suffix();
type = type_int;
break;
- case T_INTEGER_OCTAL:
- kind = EXPR_LITERAL_INTEGER_OCTAL;
- check_integer_suffix();
- type = type_int;
- break;
- case T_INTEGER_HEXADECIMAL:
- kind = EXPR_LITERAL_INTEGER_HEXADECIMAL;
- check_integer_suffix();
- type = type_int;
- break;
+
case T_FLOATINGPOINT:
kind = EXPR_LITERAL_FLOATINGPOINT;
type = check_floatingpoint_suffix();
break;
- case T_FLOATINGPOINT_HEXADECIMAL:
- kind = EXPR_LITERAL_FLOATINGPOINT_HEXADECIMAL;
- type = check_floatingpoint_suffix();
- break;
+
default:
panic("unexpected token type in parse_number_literal");
}
if (entity == NULL) {
if (!strict_mode && token.kind == '(') {
/* an implicitly declared function */
- warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos,
- "implicit declaration of function '%Y'", symbol);
entity = create_implicit_function(symbol, &pos);
+ warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos, "implicit declaration of '%N'", entity);
} else {
errorf(&pos, "unknown identifier '%Y' found.", symbol);
entity = create_error_entity(symbol, ENTITY_VARIABLE);
return parse_statement_expression();
case T_IDENTIFIER:
- if (is_typedef_symbol(la1->identifier.symbol)) {
+ if (is_typedef_symbol(la1->base.symbol)) {
DECLARATION_START
return parse_cast();
}
assert(token.kind == T_IDENTIFIER);
assert(current_function != NULL);
- entity_t *label = get_entity(token.identifier.symbol, NAMESPACE_LABEL);
+ entity_t *label = get_entity(token.base.symbol, NAMESPACE_LABEL);
/* If we find a local label, we already created the declaration. */
if (label != NULL && label->kind == ENTITY_LOCAL_LABEL) {
if (label->base.parent_scope != current_scope) {
} else if (label == NULL || label->base.parent_scope != ¤t_function->parameters) {
/* There is no matching label in the same function, so create a new one. */
source_position_t const nowhere = { NULL, 0, 0, false };
- label = allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, token.identifier.symbol, &nowhere);
+ label = allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, token.base.symbol, &nowhere);
label_push(label);
}
case T_false: return parse_boolean_literal(false);
case T_true: return parse_boolean_literal(true);
case T_INTEGER:
- case T_INTEGER_OCTAL:
- case T_INTEGER_HEXADECIMAL:
- case T_FLOATINGPOINT:
- case T_FLOATINGPOINT_HEXADECIMAL: return parse_number_literal();
+ case T_FLOATINGPOINT: return parse_number_literal();
case T_CHARACTER_CONSTANT: return parse_character_constant();
case T_WIDE_CHARACTER_CONSTANT: return parse_wide_character_constant();
case T_STRING_LITERAL:
case T_COLONCOLON:
return parse_reference();
case T_IDENTIFIER:
- if (!is_typedef_symbol(token.identifier.symbol)) {
+ if (!is_typedef_symbol(token.base.symbol)) {
return parse_reference();
}
/* FALLTHROUGH */
case EXPR_LITERAL_CHARACTER:
case EXPR_LITERAL_WIDE_CHARACTER:
case EXPR_LITERAL_INTEGER:
- case EXPR_LITERAL_INTEGER_OCTAL:
- case EXPR_LITERAL_INTEGER_HEXADECIMAL:
case EXPR_LITERAL_FLOATINGPOINT:
- case EXPR_LITERAL_FLOATINGPOINT_HEXADECIMAL: return false;
case EXPR_STRING_LITERAL: return false;
case EXPR_WIDE_STRING_LITERAL: return false;
static expression_t *parse_subexpression(precedence_t precedence)
{
- if (token.kind < 0) {
- return expected_expression_error();
- }
-
expression_parser_function_t *parser
= &expression_parsers[token.kind];
expression_t *left;
assert(left != NULL);
while (true) {
- if (token.kind < 0) {
- return expected_expression_error();
- }
-
parser = &expression_parsers[token.kind];
if (parser->infix_parser == NULL)
break;
eat(T_if);
PUSH_PARENT(statement);
+ PUSH_SCOPE_STATEMENT(&statement->ifs.scope);
add_anchor_token(T_else);
warningf(WARN_PARENTHESES, pos, "suggest explicit braces to avoid ambiguous 'else'");
}
+ POP_SCOPE();
POP_PARENT();
return statement;
}
eat(T_switch);
PUSH_PARENT(statement);
+ PUSH_SCOPE_STATEMENT(&statement->switchs.scope);
expression_t *const expr = parse_condition();
type_t * type = skip_typeref(expr->base.type);
}
check_enum_cases(&statement->switchs);
+ POP_SCOPE();
POP_PARENT();
return statement;
}
eat(T_while);
PUSH_PARENT(statement);
+ PUSH_SCOPE_STATEMENT(&statement->whiles.scope);
expression_t *const cond = parse_condition();
statement->whiles.condition = cond;
statement->whiles.body = parse_loop_body(statement);
+ POP_SCOPE();
POP_PARENT();
return statement;
}
eat(T_do);
PUSH_PARENT(statement);
+ PUSH_SCOPE_STATEMENT(&statement->do_while.scope);
add_anchor_token(T_while);
statement->do_while.body = parse_loop_body(statement);
semantic_condition(cond, "condition of 'do-while'-statement");
expect(';');
+ POP_SCOPE();
POP_PARENT();
return statement;
}
eat(T_for);
PUSH_PARENT(statement);
- PUSH_SCOPE(&statement->fors.scope);
+ PUSH_SCOPE_STATEMENT(&statement->fors.scope);
expect('(');
add_anchor_token(')');
symbol_t *symbol = NULL;
if (token.kind == T_IDENTIFIER) {
- symbol = token.identifier.symbol;
+ symbol = token.base.symbol;
next_token();
entity = get_entity(symbol, NAMESPACE_NORMAL);
append_entity(current_scope, entity);
PUSH_SCOPE(&entity->namespacee.members);
-
- entity_t *old_current_entity = current_entity;
- current_entity = entity;
+ PUSH_CURRENT_ENTITY(entity);
add_anchor_token('}');
expect('{');
rem_anchor_token('}');
expect('}');
- assert(current_entity == entity);
- current_entity = old_current_entity;
+ POP_CURRENT_ENTITY();
POP_SCOPE();
}
token_kind_t la1_type = (token_kind_t)look_ahead(1)->kind;
if (la1_type == ':') {
statement = parse_label_statement();
- } else if (is_typedef_symbol(token.identifier.symbol)) {
+ } else if (is_typedef_symbol(token.base.symbol)) {
statement = parse_declaration_statement();
} else {
/* it's an identifier, the grammar says this must be an
switch (la1_type) {
case '&':
case '*':
- if (get_entity(token.identifier.symbol, NAMESPACE_NORMAL) != NULL) {
+ if (get_entity(token.base.symbol, NAMESPACE_NORMAL) != NULL) {
default:
statement = parse_expression_statement();
} else {
}
}
-void prepare_main_collect2(entity_t *entity)
+static void prepare_main_collect2(entity_t *const entity)
{
PUSH_SCOPE(&entity->function.statement->compound.scope);