static stack_entry_t *label_stack = NULL;
static stack_entry_t *local_label_stack = NULL;
/** The global file scope. */
-static scope_t *global_scope = NULL;
+static scope_t *file_scope = NULL;
/** The current scope. */
static scope_t *scope = NULL;
static declaration_t *last_declaration = NULL;
*/
static void eat_until_anchor(void)
{
- if (token.type == T_EOF)
- return;
while (token_anchor_set[token.type] == 0) {
if (token.type == '(' || token.type == '{' || token.type == '[')
eat_until_matching_token(token.type);
- if (token.type == T_EOF)
- break;
next_token();
}
}
namespace_t namespc = (namespace_t) declaration->namespc;
/* replace/add declaration into declaration list of the symbol */
- declaration_t *iter = symbol->declaration;
- if (iter == NULL) {
- symbol->declaration = declaration;
- } else {
- declaration_t *iter_last = NULL;
- for( ; iter != NULL; iter_last = iter, iter = iter->symbol_next) {
- /* replace an entry? */
- if (iter->namespc == namespc) {
- if (iter_last == NULL) {
- symbol->declaration = declaration;
- } else {
- iter_last->symbol_next = declaration;
- }
- declaration->symbol_next = iter->symbol_next;
- break;
- }
- }
- if (iter == NULL) {
- assert(iter_last->symbol_next == NULL);
- iter_last->symbol_next = declaration;
+ declaration_t **anchor;
+ declaration_t *iter;
+ for (anchor = &symbol->declaration;; anchor = &iter->symbol_next) {
+ iter = *anchor;
+ if (iter == NULL)
+ break;
+
+ /* replace an entry? */
+ if (iter->namespc == namespc) {
+ declaration->symbol_next = iter->symbol_next;
+ break;
}
}
+ *anchor = declaration;
/* remember old declaration */
stack_entry_t entry;
namespace_t namespc = (namespace_t)entry->namespc;
/* replace/remove declaration */
- declaration_t *declaration = symbol->declaration;
- assert(declaration != NULL);
- if (declaration->namespc == namespc) {
- if (old_declaration == NULL) {
- symbol->declaration = declaration->symbol_next;
- } else {
- symbol->declaration = old_declaration;
- }
- } else {
- declaration_t *iter_last = declaration;
- declaration_t *iter = declaration->symbol_next;
- for( ; iter != NULL; iter_last = iter, iter = iter->symbol_next) {
- /* replace an entry? */
- if (iter->namespc == namespc) {
- assert(iter_last != NULL);
- iter_last->symbol_next = old_declaration;
- if (old_declaration != NULL) {
- old_declaration->symbol_next = iter->symbol_next;
- }
- break;
- }
- }
+ declaration_t **anchor;
+ declaration_t *iter;
+ for (anchor = &symbol->declaration;; anchor = &iter->symbol_next) {
+ iter = *anchor;
assert(iter != NULL);
+ /* replace an entry? */
+ if (iter->namespc == namespc)
+ break;
}
+
+ /* Because of scopes and appending other namespaces to the end of
+ * the list, this must hold. */
+ assert((old_declaration != NULL ? old_declaration->symbol_next : NULL) == iter->symbol_next);
+ *anchor = old_declaration;
}
ARR_SHRINKLEN(*stack_ptr, (int) new_top);
decl->source_position = *HERE;
decl->declared_storage_class = storage_class;
decl->storage_class =
- storage_class != STORAGE_CLASS_NONE || scope == global_scope ?
+ storage_class != STORAGE_CLASS_NONE || scope == file_scope ?
storage_class : STORAGE_CLASS_AUTO;
decl->symbol = symbol;
decl->implicit = true;
type->compound.declaration = parse_compound_type_specifier(false);
if (type->compound.declaration->modifiers & DM_TRANSPARENT_UNION)
modifiers |= TYPE_MODIFIER_TRANSPARENT_UNION;
- break;
finish_union_type(&type->compound);
+ break;
}
case T_enum:
type = parse_enum_specifier();
declaration->is_inline = specifiers->is_inline;
declaration->storage_class = specifiers->declared_storage_class;
- if (declaration->storage_class == STORAGE_CLASS_NONE
- && scope != global_scope) {
+ if (declaration->storage_class == STORAGE_CLASS_NONE &&
+ scope != file_scope) {
declaration->storage_class = STORAGE_CLASS_AUTO;
}
if (warning.nested_externs &&
declaration->storage_class == STORAGE_CLASS_EXTERN &&
- scope != global_scope) {
+ scope != file_scope) {
warningf(&declaration->source_position,
"nested extern declaration of '%#T'", declaration->type, symbol);
}
}
} else {
if (warning.missing_declarations &&
- scope == global_scope && (
+ scope == file_scope && (
declaration->storage_class == STORAGE_CLASS_NONE ||
declaration->storage_class == STORAGE_CLASS_THREAD
)) {
}
bool must_be_constant = false;
- if (declaration->storage_class == STORAGE_CLASS_STATIC
- || declaration->storage_class == STORAGE_CLASS_THREAD_STATIC
- || declaration->parent_scope == global_scope) {
+ if (declaration->storage_class == STORAGE_CLASS_STATIC ||
+ declaration->storage_class == STORAGE_CLASS_THREAD_STATIC ||
+ declaration->parent_scope == file_scope) {
must_be_constant = true;
}
add_anchor_token('{');
/* push function parameters */
- int top = environment_top();
+ size_t const top = environment_top();
scope_push(&declaration->scope);
declaration_t *parameter = declaration->scope.declarations;
type = skip_typeref(declaration->type);
/* push function parameters and switch scope */
- int top = environment_top();
+ size_t const top = environment_top();
scope_push(&declaration->scope);
declaration_t *parameter = declaration->scope.declarations;
eat('{');
add_anchor_token('}');
- while (token.type != '}' && token.type != T_EOF) {
+ while (token.type != '}') {
+ if (token.type == T_EOF) {
+ errorf(HERE, "EOF while parsing struct");
+ break;
+ }
declaration_specifiers_t specifiers;
memset(&specifiers, 0, sizeof(specifiers));
parse_declaration_specifiers(&specifiers);
parse_compound_declarators(compound_declaration, &specifiers);
}
rem_anchor_token('}');
-
- if (token.type == T_EOF) {
- errorf(HERE, "EOF while parsing struct");
- }
next_token();
}
/* this declaration is used */
declaration->used = true;
- if (declaration->parent_scope != global_scope &&
+ if (declaration->parent_scope != file_scope &&
declaration->parent_scope->depth < current_function->scope.depth &&
is_type_valid(orig_type) && !is_type_function(orig_type)) {
/* access of a variable from an outer function */
break;
default:
internal_errorf(HERE, "invalid compare builtin found");
- break;
}
expression->base.source_position = *HERE;
next_token();
PUSH_PARENT(statement);
- int top = environment_top();
+ size_t const top = environment_top();
scope_push(&statement->fors.scope);
expect('(');
eat('{');
add_anchor_token('}');
- int top = environment_top();
- int top_local = local_label_top();
+ size_t const top = environment_top();
+ size_t const top_local = local_label_top();
scope_push(&statement->compound.scope);
statement_t **anchor = &statement->compound.statements;
bool only_decls_so_far = true;
- while (token.type != '}' && token.type != T_EOF) {
+ while (token.type != '}') {
+ if (token.type == T_EOF) {
+ errorf(&statement->base.source_position,
+ "EOF while parsing compound statement");
+ break;
+ }
statement_t *sub_statement = intern_parse_statement();
if (is_invalid_statement(sub_statement)) {
/* an error occurred. if we are at an anchor, return */
anchor = &sub_statement->base.next;
}
-
- if (token.type == '}') {
- next_token();
- } else {
- errorf(&statement->base.source_position,
- "end of file while looking for closing '}'");
- }
+ next_token();
/* look over all statements again to produce no effect warnings */
if (warning.unused_value) {
if (!warning.unused_function && !warning.unused_variable)
return;
- for (const declaration_t *decl = global_scope->declarations; decl != NULL; decl = decl->next) {
+ for (const declaration_t *decl = file_scope->declarations; decl != NULL; decl = decl->next) {
if (decl->used ||
decl->modifiers & DM_UNUSED ||
decl->modifiers & DM_USED ||
*/
static void parse_translation_unit(void)
{
+ add_anchor_token(T_EOF);
+
+#ifndef NDEBUG
+ unsigned char token_anchor_copy[T_LAST_TOKEN];
+ memcpy(token_anchor_copy, token_anchor_set, sizeof(token_anchor_copy));
+#endif
for (;;) {
#ifndef NDEBUG
bool anchor_leak = false;
for (int i = 0; i != T_LAST_TOKEN; ++i) {
- unsigned char count = token_anchor_set[i];
+ unsigned char count = token_anchor_set[i] - token_anchor_copy[i];
if (count != 0) {
errorf(HERE, "Leaked anchor token %k %d times", i, count);
anchor_leak = true;
break;
case T_EOF:
+ rem_anchor_token(T_EOF);
return;
case ';':
assert(unit == NULL);
unit = allocate_ast_zero(sizeof(unit[0]));
- assert(global_scope == NULL);
- global_scope = &unit->scope;
+ assert(file_scope == NULL);
+ file_scope = &unit->scope;
assert(scope == NULL);
scope_push(&unit->scope);
scope = NULL;
last_declaration = NULL;
- assert(global_scope == &unit->scope);
+ assert(file_scope == &unit->scope);
check_unused_globals();
- global_scope = NULL;
+ file_scope = NULL;
DEL_ARR_F(environment_stack);
DEL_ARR_F(label_stack);