static elf_visibility_tag_t default_visibility = ELF_VISIBILITY_DEFAULT;
-#define PUSH_PARENT(stmt) \
- statement_t *const prev_parent = current_parent; \
- ((void)(current_parent = (stmt)))
-#define POP_PARENT ((void)(current_parent = prev_parent))
+#define PUSH_PARENT(stmt) \
+ statement_t *const new_parent = (stmt); \
+ statement_t *const old_parent = current_parent; \
+ ((void)(current_parent = new_parent))
+#define POP_PARENT() (assert(current_parent == new_parent), (void)(current_parent = old_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))
+
+#define PUSH_EXTENSION() \
+ bool const old_gcc_extension = in_gcc_extension; \
+ while (next_if(T___extension__)) { \
+ in_gcc_extension = true; \
+ } \
+ do {} while (0)
+#define POP_EXTENSION() \
+ ((void)(in_gcc_extension = old_gcc_extension))
/** special symbol used for anonymous entities. */
static symbol_t *sym_anonymous = NULL;
expression_t *expression = NULL;
- bool old_type_prop = in_type_prop;
- bool old_gcc_extension = in_gcc_extension;
- in_type_prop = true;
+ bool old_type_prop = in_type_prop;
+ in_type_prop = true;
- while (next_if(T___extension__)) {
- /* This can be a prefix to a typename or an expression. */
- in_gcc_extension = true;
- }
switch (token.type) {
case T_IDENTIFIER:
if (is_typedef_symbol(token.symbol)) {
}
break;
}
- in_type_prop = old_type_prop;
- in_gcc_extension = old_gcc_extension;
+ in_type_prop = old_type_prop;
rem_anchor_token(')');
expect(')', end_error);
static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
{
- type_t *type = NULL;
- type_qualifiers_t qualifiers = TYPE_QUALIFIER_NONE;
- unsigned type_specifiers = 0;
- bool newtype = false;
- bool saw_error = false;
- bool old_gcc_extension = in_gcc_extension;
+ type_t *type = NULL;
+ type_qualifiers_t qualifiers = TYPE_QUALIFIER_NONE;
+ unsigned type_specifiers = 0;
+ bool newtype = false;
+ bool saw_error = false;
memset(specifiers, 0, sizeof(*specifiers));
specifiers->source_position = token.source_position;
MATCH_TYPE_QUALIFIER(T___uptr, TYPE_QUALIFIER_UPTR);
MATCH_TYPE_QUALIFIER(T___sptr, TYPE_QUALIFIER_SPTR);
- case T___extension__:
- next_token();
- in_gcc_extension = true;
- break;
-
/* type specifiers */
#define MATCH_SPECIFIER(token, specifier, name) \
case token: \
finish_specifiers:
specifiers->attributes = parse_attributes(specifiers->attributes);
- in_gcc_extension = old_gcc_extension;
-
if (type == NULL || (saw_error && type_specifiers != 0)) {
atomic_type_kind_t atomic_type;
goto parameters_finished;
case T_IDENTIFIER:
- case T___extension__:
DECLARATION_START
{
entity_t *entity = parse_parameter();
add_anchor_token('{');
- /* push function parameters */
- size_t const top = environment_top();
- scope_t *old_scope = scope_push(&entity->function.parameters);
+ PUSH_SCOPE(&entity->function.parameters);
entity_t *parameter = entity->function.parameters.entities;
for ( ; parameter != NULL; parameter = parameter->base.next) {
for (;;) {
switch (token.type) {
DECLARATION_START
- case T___extension__:
/* This covers symbols, which are no type, too, and results in
* better error messages. The typical cases are misspelled type
* names and missing includes. */
}
decl_list_end:
- /* pop function parameters */
- assert(current_scope == &entity->function.parameters);
- scope_pop(old_scope);
- environment_pop_to(top);
+ POP_SCOPE();
/* update function type */
type_t *new_type = duplicate_type(type);
assert(is_declaration(entity));
type = skip_typeref(entity->declaration.type);
- /* push function parameters and switch scope */
- size_t const top = environment_top();
- scope_t *old_scope = scope_push(&function->parameters);
+ PUSH_SCOPE(&function->parameters);
entity_t *parameter = function->parameters.entities;
for (; parameter != NULL; parameter = parameter->base.next) {
entity_t *old_current_entity = current_entity;
current_function = function;
current_entity = entity;
- current_parent = NULL;
+ PUSH_PARENT(NULL);
goto_first = NULL;
goto_anchor = &goto_first;
}
}
- assert(current_parent == NULL);
+ POP_PARENT();
assert(current_function == function);
assert(current_entity == entity);
current_entity = old_current_entity;
label_pop_to(label_stack_top);
}
- assert(current_scope == &function->parameters);
- scope_pop(old_scope);
- environment_pop_to(top);
+ POP_SCOPE();
}
static type_t *make_bitfield_type(type_t *base_type, expression_t *size,
for (;;) {
switch (token.type) {
DECLARATION_START
+ case T___extension__:
case T_IDENTIFIER: {
+ PUSH_EXTENSION();
declaration_specifiers_t specifiers;
parse_declaration_specifiers(&specifiers);
parse_compound_declarators(compound, &specifiers);
+ POP_EXTENSION();
break;
}
*/
static expression_t *parse_extension(void)
{
- eat(T___extension__);
-
- bool old_gcc_extension = in_gcc_extension;
- in_gcc_extension = true;
+ PUSH_EXTENSION();
expression_t *expression = parse_subexpression(PREC_UNARY);
- in_gcc_extension = old_gcc_extension;
+ POP_EXTENSION();
return expression;
}
default:
inner_stmt = parse_statement();
- /* ISO/IEC 14882:1998(E) §6:1/§6.7 Declarations are statements */
+ /* ISO/IEC 9899:1999(E) §6.8:1/6.8.2:1 Declarations are no statements */
+ /* ISO/IEC 14882:1998(E) §6:1/§6.7 Declarations are statements */
if (inner_stmt->kind == STATEMENT_DECLARATION && !(c_mode & _CXX)) {
errorf(&inner_stmt->base.source_position, "declaration after %s", label_kind);
}
statement->case_label.statement = parse_label_inner_statement(statement, "case label");
- POP_PARENT;
+ POP_PARENT();
return statement;
}
statement->case_label.statement = parse_label_inner_statement(statement, "default label");
- POP_PARENT;
+ POP_PARENT();
return statement;
}
*label_anchor = &statement->label;
label_anchor = &statement->label.next;
- POP_PARENT;
+ POP_PARENT();
return statement;
}
+static statement_t *parse_inner_statement(void)
+{
+ statement_t *const stmt = parse_statement();
+ /* ISO/IEC 9899:1999(E) §6.8:1/6.8.2:1 Declarations are no statements */
+ /* ISO/IEC 14882:1998(E) §6:1/§6.7 Declarations are statements */
+ if (stmt->kind == STATEMENT_DECLARATION && !(c_mode & _CXX)) {
+ errorf(&stmt->base.source_position, "declaration as inner statement, use {}");
+ }
+ return stmt;
+}
+
/**
* Parse an if statement.
*/
rem_anchor_token('{');
add_anchor_token(T_else);
- statement_t *const true_stmt = parse_statement();
+ statement_t *const true_stmt = parse_inner_statement();
statement->ifs.true_statement = true_stmt;
rem_anchor_token(T_else);
if (next_if(T_else)) {
- statement->ifs.false_statement = parse_statement();
+ statement->ifs.false_statement = parse_inner_statement();
} else if (true_stmt->kind == STATEMENT_IF &&
true_stmt->ifs.false_statement != NULL) {
source_position_t const *const pos = &true_stmt->base.source_position;
warningf(WARN_PARENTHESES, pos, "suggest explicit braces to avoid ambiguous 'else'");
}
- POP_PARENT;
+ POP_PARENT();
return statement;
}
switch_statement_t *rem = current_switch;
current_switch = &statement->switchs;
- statement->switchs.body = parse_statement();
+ statement->switchs.body = parse_inner_statement();
current_switch = rem;
if (statement->switchs.default_label == NULL) {
}
check_enum_cases(&statement->switchs);
- POP_PARENT;
+ POP_PARENT();
return statement;
end_error:
- POP_PARENT;
+ POP_PARENT();
return create_invalid_statement();
}
statement_t *const rem = current_loop;
current_loop = loop;
- statement_t *const body = parse_statement();
+ statement_t *const body = parse_inner_statement();
current_loop = rem;
return body;
statement->whiles.body = parse_loop_body(statement);
- POP_PARENT;
+ POP_PARENT();
return statement;
end_error:
- POP_PARENT;
+ POP_PARENT();
return create_invalid_statement();
}
expect(')', end_error);
expect(';', end_error);
- POP_PARENT;
+ POP_PARENT();
return statement;
end_error:
- POP_PARENT;
+ POP_PARENT();
return create_invalid_statement();
}
add_anchor_token(')');
PUSH_PARENT(statement);
+ PUSH_SCOPE(&statement->fors.scope);
- size_t const top = environment_top();
- scope_t *old_scope = scope_push(&statement->fors.scope);
-
- bool old_gcc_extension = in_gcc_extension;
- while (next_if(T___extension__)) {
- in_gcc_extension = true;
- }
+ PUSH_EXTENSION();
if (next_if(';')) {
} else if (is_declaration_specifier(&token)) {
rem_anchor_token(';');
expect(';', end_error2);
}
- in_gcc_extension = old_gcc_extension;
+
+ POP_EXTENSION();
if (token.type != ';') {
add_anchor_token(';');
rem_anchor_token(')');
statement->fors.body = parse_loop_body(statement);
- assert(current_scope == &statement->fors.scope);
- scope_pop(old_scope);
- environment_pop_to(top);
-
- POP_PARENT;
+ POP_SCOPE();
+ POP_PARENT();
return statement;
end_error2:
- POP_PARENT;
+ POP_PARENT();
rem_anchor_token(')');
- assert(current_scope == &statement->fors.scope);
- scope_pop(old_scope);
- environment_pop_to(top);
+ POP_SCOPE();
/* fallthrough */
end_error1:
statement->ms_try.try_statement = parse_compound_statement(false);
current_try = rem;
- POP_PARENT;
+ POP_PARENT();
if (next_if(T___except)) {
expect('(', end_error);
environment_push(entity);
append_entity(current_scope, entity);
- size_t const top = environment_top();
- scope_t *old_scope = scope_push(&entity->namespacee.members);
+ PUSH_SCOPE(&entity->namespacee.members);
entity_t *old_current_entity = current_entity;
current_entity = entity;
expect('}', end_error);
end_error:
- assert(current_scope == &entity->namespacee.members);
assert(current_entity == entity);
current_entity = old_current_entity;
- scope_pop(old_scope);
- environment_pop_to(top);
+ POP_SCOPE();
}
/**
break;
}
- case T___extension__:
+ case T___extension__: {
/* This can be a prefix to a declaration or an expression statement.
* We simply eat it now and parse the rest with tail recursion. */
- while (next_if(T___extension__)) {}
- bool old_gcc_extension = in_gcc_extension;
- in_gcc_extension = true;
+ PUSH_EXTENSION();
statement = intern_parse_statement();
- in_gcc_extension = old_gcc_extension;
+ POP_EXTENSION();
break;
+ }
DECLARATION_START
statement = parse_declaration_statement();
statement_t *statement = allocate_statement_zero(STATEMENT_COMPOUND);
PUSH_PARENT(statement);
+ PUSH_SCOPE(&statement->compound.scope);
eat('{');
add_anchor_token('}');
add_anchor_token(T_wchar_t);
add_anchor_token(T_while);
- size_t const top = environment_top();
- scope_t *old_scope = scope_push(&statement->compound.scope);
-
statement_t **anchor = &statement->compound.statements;
bool only_decls_so_far = true;
while (token.type != '}') {
rem_anchor_token('&');
rem_anchor_token('!');
rem_anchor_token('}');
- assert(current_scope == &statement->compound.scope);
- scope_pop(old_scope);
- environment_pop_to(top);
- POP_PARENT;
+ POP_SCOPE();
+ POP_PARENT();
return statement;
}
static void parse_external(void)
{
switch (token.type) {
- DECLARATION_START_NO_EXTERN
- case T_IDENTIFIER:
- case T___extension__:
- /* tokens below are for implicit int */
- case '&': /* & x; -> int& x; (and error later, because C++ has no
- implicit int) */
- case '*': /* * x; -> int* x; */
- case '(': /* (x); -> int (x); */
- parse_external_declaration();
- return;
-
case T_extern:
if (look_ahead(1)->type == T_STRING_LITERAL) {
parse_linkage_specification();
} else {
+ DECLARATION_START_NO_EXTERN
+ case T_IDENTIFIER:
+ case T___extension__:
+ /* tokens below are for implicit int */
+ case '&': /* & x; -> int& x; (and error later, because C++ has no
+ implicit int) */
+ case '*': /* * x; -> int* x; */
+ case '(':; /* (x); -> int (x); */
+ PUSH_EXTENSION();
parse_external_declaration();
+ POP_EXTENSION();
}
return;