The standard calls it "file scope", so rename global_scope to file_scope.
[cparser] / parser.c
index 833a213..14a84c4 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -115,7 +115,7 @@ static stack_entry_t      *environment_stack = NULL;
 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;
@@ -640,13 +640,9 @@ check_stop:
  */
 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();
        }
 }
@@ -761,28 +757,20 @@ static void stack_push(stack_entry_t **stack_ptr, declaration_t *declaration)
        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;
@@ -847,30 +835,20 @@ static void stack_pop_to(stack_entry_t **stack_ptr, size_t new_top)
                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);
@@ -3134,7 +3112,7 @@ static declaration_t *create_error_declaration(symbol_t *symbol, storage_class_t
        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;
@@ -3386,8 +3364,8 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                        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();
@@ -4281,8 +4259,8 @@ static declaration_t *parse_declarator(
        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;
        }
 
@@ -4418,7 +4396,7 @@ static declaration_t *record_declaration(
 
        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);
        }
@@ -4558,7 +4536,7 @@ warn_redundant_declaration:
                }
        } else {
                if (warning.missing_declarations &&
-                   scope == global_scope && (
+                   scope == file_scope && (
                      declaration->storage_class == STORAGE_CLASS_NONE ||
                      declaration->storage_class == STORAGE_CLASS_THREAD
                    )) {
@@ -4614,9 +4592,9 @@ static void parse_init_declarator_rest(declaration_t *declaration)
        }
 
        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;
        }
 
@@ -4802,7 +4780,7 @@ static void parse_kr_declaration_list(declaration_t *declaration)
        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;
@@ -5517,7 +5495,7 @@ static void parse_external_declaration(void)
        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;
@@ -5738,7 +5716,11 @@ static void parse_compound_type_entries(declaration_t *compound_declaration)
        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);
@@ -5746,10 +5728,6 @@ static void parse_compound_type_entries(declaration_t *compound_declaration)
                parse_compound_declarators(compound_declaration, &specifiers);
        }
        rem_anchor_token('}');
-
-       if (token.type == T_EOF) {
-               errorf(HERE, "EOF while parsing struct");
-       }
        next_token();
 }
 
@@ -6161,7 +6139,7 @@ static expression_t *parse_reference(void)
        /* 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 */
@@ -6661,7 +6639,6 @@ static expression_t *parse_compare_builtin(void)
                break;
        default:
                internal_errorf(HERE, "invalid compare builtin found");
-               break;
        }
        expression->base.source_position = *HERE;
        next_token();
@@ -9202,7 +9179,7 @@ static statement_t *parse_for(void)
 
        PUSH_PARENT(statement);
 
-       int top = environment_top();
+       size_t const top = environment_top();
        scope_push(&statement->fors.scope);
 
        expect('(');
@@ -9815,13 +9792,18 @@ static statement_t *parse_compound_statement(bool inside_expression_statement)
        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 */
@@ -9846,13 +9828,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement)
 
                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) {
@@ -9919,7 +9895,7 @@ static void check_unused_globals(void)
        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   ||
@@ -9967,11 +9943,17 @@ end_error:;
  */
 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;
@@ -9998,6 +9980,7 @@ static void parse_translation_unit(void)
                                break;
 
                        case T_EOF:
+                               rem_anchor_token(T_EOF);
                                return;
 
                        case ';':
@@ -10036,8 +10019,8 @@ void start_parsing(void)
        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);
@@ -10052,9 +10035,9 @@ translation_unit_t *finish_parsing(void)
        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);