add support for gcc nested functions
[cparser] / parser.c
index 119677c..77c5884 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -643,16 +643,6 @@ static void eat_block(void)
                next_token();
 }
 
-/**
- * eat all token until a ';' is reached or a stop token is found.
- */
-static void eat_statement(void)
-{
-       eat_until_matching_token(';');
-       if (token.type == ';')
-               next_token();
-}
-
 #define eat(token_type)  do { assert(token.type == token_type); next_token(); } while (0)
 
 /**
@@ -3914,9 +3904,8 @@ static construct_type_t *parse_array_declarator(void)
        rem_anchor_token(']');
        expect(']');
 
-       return (construct_type_t*) array;
 end_error:
-       return NULL;
+       return (construct_type_t*) array;
 }
 
 static construct_type_t *parse_function_declarator(declaration_t *declaration)
@@ -4055,13 +4044,7 @@ static construct_type_t *parse_inner_declarator(declaration_t *declaration,
                if (may_be_abstract)
                        break;
                parse_error_expected("while parsing declarator", T_IDENTIFIER, '(', NULL);
-               /* avoid a loop in the outermost scope, because eat_statement doesn't
-                * eat '}' */
-               if (token.type == '}' && current_function == NULL) {
-                       next_token();
-               } else {
-                       eat_statement();
-               }
+               eat_until_anchor();
                return NULL;
        }
 
@@ -4160,19 +4143,19 @@ static type_t *construct_declarator_type(construct_type_t *construct_list,
                        function_type->function.return_type = type;
 
                        type_t *skipped_return_type = skip_typeref(type);
+                       /* §6.7.5.3(1) */
                        if (is_type_function(skipped_return_type)) {
                                errorf(HERE, "function returning function is not allowed");
-                               type = type_error_type;
                        } else if (is_type_array(skipped_return_type)) {
                                errorf(HERE, "function returning array is not allowed");
-                               type = type_error_type;
                        } else {
                                if (skipped_return_type->base.qualifiers != 0) {
                                        warningf(HERE,
                                                "type qualifiers in return type of function type are meaningless");
                                }
-                               type = function_type;
                        }
+
+                       type = function_type;
                        break;
                }
 
@@ -4213,12 +4196,13 @@ static type_t *construct_declarator_type(construct_type_t *construct_list,
                        }
 
                        type_t *skipped_type = skip_typeref(type);
-                       if (is_type_atomic(skipped_type, ATOMIC_TYPE_VOID)) {
-                               errorf(HERE, "array of void is not allowed");
-                               type = type_error_type;
-                       } else {
-                               type = array_type;
+                       /* §6.7.5.2(1) */
+                       if (is_type_incomplete(skipped_type)) {
+                               errorf(HERE, "array of incomplete type '%T' is not allowed", type);
+                       } else if (is_type_function(skipped_type)) {
+                               errorf(HERE, "array of functions is not allowed");
                        }
+                       type = array_type;
                        break;
                }
                }
@@ -4378,7 +4362,7 @@ static declaration_t *record_declaration(
                        previous_declaration == NULL) {
                warningf(&declaration->source_position,
                         "function declaration '%#T' is not a prototype",
-                        orig_type, declaration->symbol);
+                        orig_type, symbol);
        }
 
        if (warning.main && is_type_function(type) && is_sym_main(symbol)) {
@@ -4609,24 +4593,17 @@ static void parse_anonymous_declaration_rest(
 {
        eat(';');
 
-       declaration_t *const declaration    = allocate_declaration_zero();
-       declaration->type                   = specifiers->type;
-       declaration->declared_storage_class = specifiers->declared_storage_class;
-       declaration->source_position        = specifiers->source_position;
-       declaration->modifiers              = specifiers->modifiers;
-
-       if (declaration->declared_storage_class != STORAGE_CLASS_NONE) {
-               warningf(&declaration->source_position,
+       if (specifiers->declared_storage_class != STORAGE_CLASS_NONE) {
+               warningf(&specifiers->source_position,
                         "useless storage class in empty declaration");
        }
-       declaration->storage_class = STORAGE_CLASS_NONE;
 
-       type_t *type = declaration->type;
+       type_t *type = specifiers->type;
        switch (type->kind) {
                case TYPE_COMPOUND_STRUCT:
                case TYPE_COMPOUND_UNION: {
                        if (type->compound.declaration->symbol == NULL) {
-                               warningf(&declaration->source_position,
+                               warningf(&specifiers->source_position,
                                         "unnamed struct/union that defines no instances");
                        }
                        break;
@@ -4636,11 +4613,20 @@ static void parse_anonymous_declaration_rest(
                        break;
 
                default:
-                       warningf(&declaration->source_position, "empty declaration");
+                       warningf(&specifiers->source_position, "empty declaration");
                        break;
        }
 
+#ifdef RECORD_EMPTY_DECLARATIONS
+       declaration_t *const declaration    = allocate_declaration_zero();
+       declaration->type                   = specifiers->type;
+       declaration->declared_storage_class = specifiers->declared_storage_class;
+       declaration->source_position        = specifiers->source_position;
+       declaration->modifiers              = specifiers->modifiers;
+       declaration->storage_class          = STORAGE_CLASS_NONE;
+
        append_declaration(declaration);
+#endif
 }
 
 static void parse_declaration_rest(declaration_t *ndeclaration,
@@ -4721,7 +4707,10 @@ static void parse_declaration(parsed_declaration_func finished_declaration)
 {
        declaration_specifiers_t specifiers;
        memset(&specifiers, 0, sizeof(specifiers));
+
+       add_anchor_token(';');
        parse_declaration_specifiers(&specifiers);
+       rem_anchor_token(';');
 
        if (token.type == ';') {
                parse_anonymous_declaration_rest(&specifiers);
@@ -6910,12 +6899,16 @@ static expression_t *parse_typeprop(expression_kind_t const kind,
                                     source_position_t const pos,
                                     unsigned const precedence)
 {
-       expression_t *tp_expression = allocate_expression_zero(kind);
+       expression_t  *tp_expression = allocate_expression_zero(kind);
        tp_expression->base.type            = type_size_t;
        tp_expression->base.source_position = pos;
 
        char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof";
 
+       /* we only refer to a type property, not the value, so do not warn
+        * when using current_init_decl */
+       declaration_t *old = current_init_decl;
+       current_init_decl  = NULL;
        if (token.type == '(' && is_declaration_specifier(look_ahead(1), true)) {
                next_token();
                add_anchor_token(')');
@@ -6956,6 +6949,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind,
        }
 
 end_error:
+       current_init_decl  = old;
        return tp_expression;
 }
 
@@ -9154,7 +9148,7 @@ static statement_t *parse_goto(void)
                                parse_error_expected("while parsing goto", T_IDENTIFIER, '*', NULL);
                        else
                                parse_error_expected("while parsing goto", T_IDENTIFIER, NULL);
-                       eat_statement();
+                       eat_until_anchor();
                        goto end_error;
                }
                symbol_t *symbol = token.v.symbol;
@@ -9362,7 +9356,10 @@ static statement_t *parse_declaration_statement(void)
        statement->base.source_position = token.source_position;
 
        declaration_t *before = last_declaration;
-       parse_declaration(record_declaration);
+       if (c_mode & _GNUC)
+               parse_external_declaration();
+       else
+               parse_declaration(record_declaration);
 
        if (before == NULL) {
                statement->declaration.declarations_begin = scope->declarations;