update preprocessor tests
[cparser] / parser.c
index 67f83ea..d60a90d 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -89,7 +89,6 @@ 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_entity    = 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;
@@ -101,8 +100,6 @@ static label_statement_t   *label_first       = NULL;
 static label_statement_t  **label_anchor      = NULL;
 /** current translation unit. */
 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;
 /** true if we are in an __extension__ context. */
 static bool                 in_gcc_extension  = false;
 static struct obstack       temp_obst;
@@ -117,11 +114,27 @@ static elf_visibility_tag_t default_visibility = ELF_VISIBILITY_DEFAULT;
        ((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() \
+       (void)0; \
+       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;
 
 /** The token anchor set */
-static unsigned char token_anchor_set[T_LAST_TOKEN];
+static unsigned short token_anchor_set[T_LAST_TOKEN];
 
 /** The current source position. */
 #define HERE (&token.source_position)
@@ -874,23 +887,6 @@ static type_t *promote_integer(type_t *type)
        return type;
 }
 
-/**
- * Create a cast expression.
- *
- * @param expression  the expression to cast
- * @param dest_type   the destination type
- */
-static expression_t *create_cast_expression(expression_t *expression,
-                                            type_t *dest_type)
-{
-       expression_t *cast = allocate_expression_zero(EXPR_UNARY_CAST_IMPLICIT);
-
-       cast->unary.value = expression;
-       cast->base.type   = dest_type;
-
-       return cast;
-}
-
 /**
  * Check if a given expression represents a null pointer constant.
  *
@@ -899,8 +895,7 @@ static expression_t *create_cast_expression(expression_t *expression,
 static bool is_null_pointer_constant(const expression_t *expression)
 {
        /* skip void* cast */
-       if (expression->kind == EXPR_UNARY_CAST ||
-                       expression->kind == EXPR_UNARY_CAST_IMPLICIT) {
+       if (expression->kind == EXPR_UNARY_CAST) {
                type_t *const type = skip_typeref(expression->base.type);
                if (types_compatible(type, type_void_ptr))
                        expression = expression->unary.value;
@@ -930,7 +925,12 @@ static expression_t *create_implicit_cast(expression_t *expression,
        if (source_type == dest_type)
                return expression;
 
-       return create_cast_expression(expression, dest_type);
+       expression_t *cast = allocate_expression_zero(EXPR_UNARY_CAST);
+       cast->unary.value   = expression;
+       cast->base.type     = dest_type;
+       cast->base.implicit = true;
+
+       return cast;
 }
 
 typedef enum assign_error_t {
@@ -1493,7 +1493,6 @@ static void mark_vars_read(expression_t *const expr, entity_t *lhs_ent)
                case EXPR_UNARY_POSTFIX_DECREMENT:
                case EXPR_UNARY_PREFIX_INCREMENT:
                case EXPR_UNARY_PREFIX_DECREMENT:
-               case EXPR_UNARY_CAST_IMPLICIT:
                case EXPR_UNARY_ASSUME:
 unary:
                        mark_vars_read(expr->unary.value, lhs_ent);
@@ -2568,14 +2567,6 @@ static type_t *parse_typeof(void)
 
        expression_t *expression  = NULL;
 
-       bool old_type_prop     = in_type_prop;
-       bool old_gcc_extension = in_gcc_extension;
-       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)) {
@@ -2588,8 +2579,6 @@ static type_t *parse_typeof(void)
                }
                break;
        }
-       in_type_prop     = old_type_prop;
-       in_gcc_extension = old_gcc_extension;
 
        rem_anchor_token(')');
        expect(')', end_error);
@@ -2771,12 +2760,11 @@ static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind)
 
 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;
@@ -2848,11 +2836,6 @@ wrong_thread_storage_class:
                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:                                                     \
@@ -3003,8 +2986,6 @@ wrong_thread_storage_class:
 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;
 
@@ -3317,7 +3298,6 @@ static void parse_parameters(function_type_t *type, scope_t *scope)
                                goto parameters_finished;
 
                        case T_IDENTIFIER:
-                       case T___extension__:
                        DECLARATION_START
                        {
                                entity_t *entity = parse_parameter();
@@ -4350,10 +4330,8 @@ static void parse_init_declarator_rest(entity_t *entity)
        env.type             = orig_type;
        env.must_be_constant = must_be_constant;
        env.entity           = entity;
-       current_init_decl    = entity;
 
        initializer_t *initializer = parse_initializer(&env);
-       current_init_decl = NULL;
 
        if (entity->kind == ENTITY_VARIABLE) {
                /* §6.7.5:22  array initializers for arrays with unknown size
@@ -4529,9 +4507,7 @@ static void parse_kr_declaration_list(entity_t *entity)
 
        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) {
@@ -4544,7 +4520,6 @@ static void parse_kr_declaration_list(entity_t *entity)
        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. */
@@ -4557,10 +4532,7 @@ static void parse_kr_declaration_list(entity_t *entity)
        }
 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);
@@ -5463,9 +5435,7 @@ static void parse_external_declaration(void)
        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) {
@@ -5526,9 +5496,7 @@ static void parse_external_declaration(void)
                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,
@@ -5667,7 +5635,7 @@ static expression_t *find_create_select(const source_position_t *pos,
 
                        expression_t *sub_addr = create_select(pos, addr, qualifiers, iter);
                        sub_addr->base.source_position = *pos;
-                       sub_addr->select.implicit      = true;
+                       sub_addr->base.implicit        = true;
                        return find_create_select(pos, sub_addr, qualifiers, sub_compound,
                                                  symbol);
                }
@@ -5777,10 +5745,13 @@ static void parse_compound_type_entries(compound_t *compound)
        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;
                        }
 
@@ -6293,11 +6264,6 @@ static expression_t *parse_reference(void)
 
        check_deprecated(&pos, entity);
 
-       if (entity == current_init_decl && !in_type_prop && entity->kind == ENTITY_VARIABLE) {
-               current_init_decl = NULL;
-               warningf(WARN_INIT_SELF, &pos, "variable '%#N' is initialized by itself", entity);
-       }
-
        return expression;
 }
 
@@ -7047,10 +7013,6 @@ static expression_t *parse_typeprop(expression_kind_t const kind)
 
        eat(kind == EXPR_SIZEOF ? T_sizeof : T___alignof__);
 
-       /* we only refer to a type property, mark this case */
-       bool old     = in_type_prop;
-       in_type_prop = true;
-
        type_t       *orig_type;
        expression_t *expression;
        if (token.type == '(' && is_declaration_specifier(look_ahead(1))) {
@@ -7107,7 +7069,6 @@ typeprop_expression:
        }
 
 end_error:
-       in_type_prop = old;
        return tp_expression;
 }
 
@@ -7592,12 +7553,9 @@ types_incompatible:
  */
 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;
 }
 
@@ -8638,7 +8596,6 @@ static bool expression_has_effect(const expression_t *const expr)
                        return is_type_atomic(type, ATOMIC_TYPE_VOID);
                }
 
-               case EXPR_UNARY_CAST_IMPLICIT:        return true;
                case EXPR_UNARY_ASSUME:               return true;
                case EXPR_UNARY_DELETE:               return true;
                case EXPR_UNARY_DELETE_ARRAY:         return true;
@@ -9102,7 +9059,8 @@ static statement_t *parse_label_inner_statement(statement_t const *const label,
 
                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);
                        }
@@ -9259,6 +9217,10 @@ static statement_t *parse_label_statement(void)
 
        eat(':');
 
+       if (token.type == T___attribute__ && !(c_mode & _CXX)) {
+               parse_attributes(NULL); // TODO process attributes
+       }
+
        statement->label.statement = parse_label_inner_statement(statement, "label");
 
        /* remember the labels in a list for later checking */
@@ -9269,6 +9231,17 @@ static statement_t *parse_label_statement(void)
        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.
  */
@@ -9297,12 +9270,12 @@ end_error:
        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;
@@ -9388,7 +9361,7 @@ static statement_t *parse_switch(void)
 
        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) {
@@ -9408,7 +9381,7 @@ static statement_t *parse_loop_body(statement_t *const loop)
        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;
@@ -9493,14 +9466,9 @@ static statement_t *parse_for(void)
        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)) {
@@ -9516,7 +9484,8 @@ static statement_t *parse_for(void)
                rem_anchor_token(';');
                expect(';', end_error2);
        }
-       in_gcc_extension = old_gcc_extension;
+
+       POP_EXTENSION();
 
        if (token.type != ';') {
                add_anchor_token(';');
@@ -9541,19 +9510,14 @@ static statement_t *parse_for(void)
        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_SCOPE();
        POP_PARENT();
        return statement;
 
 end_error2:
        POP_PARENT();
        rem_anchor_token(')');
-       assert(current_scope == &statement->fors.scope);
-       scope_pop(old_scope);
-       environment_pop_to(top);
+       POP_SCOPE();
        /* fallthrough */
 
 end_error1:
@@ -9957,8 +9921,7 @@ static void parse_namespace_definition(void)
        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;
@@ -9968,11 +9931,9 @@ static void parse_namespace_definition(void)
        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();
 }
 
 /**
@@ -10015,15 +9976,14 @@ static statement_t *intern_parse_statement(void)
                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();
@@ -10097,6 +10057,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement)
        statement_t *statement = allocate_statement_zero(STATEMENT_COMPOUND);
 
        PUSH_PARENT(statement);
+       PUSH_SCOPE(&statement->compound.scope);
 
        eat('{');
        add_anchor_token('}');
@@ -10189,9 +10150,6 @@ static statement_t *parse_compound_statement(bool inside_expression_statement)
        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 != '}') {
@@ -10330,10 +10288,8 @@ end_error:
        rem_anchor_token('&');
        rem_anchor_token('!');
        rem_anchor_token('}');
-       assert(current_scope == &statement->compound.scope);
-       scope_pop(old_scope);
-       environment_pop_to(top);
 
+       POP_SCOPE();
        POP_PARENT();
        return statement;
 }
@@ -10427,22 +10383,21 @@ end_error:
 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;
 
@@ -10478,14 +10433,14 @@ static void parse_externals(void)
 
 #ifndef NDEBUG
        /* make a copy of the anchor set, so we can check if it is restored after parsing */
-       unsigned char token_anchor_copy[T_LAST_TOKEN];
+       unsigned short token_anchor_copy[T_LAST_TOKEN];
        memcpy(token_anchor_copy, token_anchor_set, sizeof(token_anchor_copy));
 #endif
 
        while (token.type != T_EOF && token.type != '}') {
 #ifndef NDEBUG
                for (int i = 0; i < T_LAST_TOKEN; ++i) {
-                       unsigned char count = token_anchor_set[i] - token_anchor_copy[i];
+                       unsigned short count = token_anchor_set[i] - token_anchor_copy[i];
                        if (count != 0) {
                                /* the anchor set and its copy differs */
                                internal_errorf(HERE, "Leaked anchor token %k %d times", i, count);