Warn about type qualifiers in the return type of function types.
[cparser] / parser.c
index e3edd0d..119677c 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1501,12 +1501,12 @@ static void parse_gnu_attribute_format_args(gnu_attribute_t *attribute)
        add_anchor_token(',');
        parse_constant_expression();
        rem_anchor_token(',');
-       rem_anchor_token('(');
+       rem_anchor_token(')');
 
        expect(',');
        add_anchor_token(')');
        parse_constant_expression();
-       rem_anchor_token('(');
+       rem_anchor_token(')');
        expect(')');
        return;
 end_error:
@@ -2475,6 +2475,10 @@ finish_designator:
 
                        if (type == NULL) {
                                /* we are already outside, ... */
+                               if (is_type_compound(outer_type) &&
+                                   !outer_type->compound.declaration->init.complete) {
+                                       goto error_parse_next;
+                               }
                                goto error_excess;
                        }
 
@@ -3584,10 +3588,8 @@ warn_about_long_long:
                default:
                        /* invalid specifier combination, give an error message */
                        if (type_specifiers == 0) {
-                               if (saw_error) {
-                                       specifiers->type = type_error_type;
-                                       return;
-                               }
+                               if (saw_error)
+                                       goto end_error;
 
                                if (!strict_mode) {
                                        if (warning.implicit_int) {
@@ -3606,15 +3608,13 @@ warn_about_long_long:
                        } else {
                                errorf(HERE, "multiple datatypes in declaration");
                        }
-                       atomic_type = ATOMIC_TYPE_INVALID;
+                       goto end_error;
                }
 
-               if (type_specifiers & SPECIFIER_COMPLEX &&
-                  atomic_type != ATOMIC_TYPE_INVALID) {
+               if (type_specifiers & SPECIFIER_COMPLEX) {
                        type                = allocate_type_zero(TYPE_COMPLEX, &builtin_source_position);
                        type->complex.akind = atomic_type;
-               } else if (type_specifiers & SPECIFIER_IMAGINARY &&
-                         atomic_type != ATOMIC_TYPE_INVALID) {
+               } else if (type_specifiers & SPECIFIER_IMAGINARY) {
                        type                  = allocate_type_zero(TYPE_IMAGINARY, &builtin_source_position);
                        type->imaginary.akind = atomic_type;
                } else {
@@ -3637,7 +3637,10 @@ warn_about_long_long:
        }
 
        specifiers->type = result;
+       return;
+
 end_error:
+       specifiers->type = type_error_type;
        return;
 }
 
@@ -4164,6 +4167,10 @@ static type_t *construct_declarator_type(construct_type_t *construct_list,
                                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;
                        }
                        break;
@@ -4308,7 +4315,7 @@ static void check_type_of_main(const declaration_t *const decl, const function_t
                warningf(&decl->source_position,
                         "'main' is normally a non-static function");
        }
-       if (skip_typeref(func_type->return_type) != type_int) {
+       if (!types_compatible(skip_typeref(func_type->return_type), type_int)) {
                warningf(&decl->source_position,
                         "return type of 'main' should be 'int', but is '%T'",
                         func_type->return_type);
@@ -5384,7 +5391,7 @@ static void parse_external_declaration(void)
 
        add_anchor_token(',');
        add_anchor_token('=');
-       rem_anchor_token(';');
+       add_anchor_token(';');
 
        /* declarator is common to both function-definitions and declarations */
        declaration_t *ndeclaration = parse_declarator(&specifiers, /*may_be_abstract=*/false);
@@ -6203,11 +6210,12 @@ static expression_t *parse_compound_literal(type_t *type)
  */
 static expression_t *parse_cast(void)
 {
+       add_anchor_token(')');
+
        source_position_t source_position = token.source_position;
 
        type_t *type  = parse_typename();
 
-       /* matching add_anchor_token() is at call site */
        rem_anchor_token(')');
        expect(')');
 
@@ -6236,6 +6244,8 @@ end_error:
  */
 static expression_t *parse_statement_expression(void)
 {
+       add_anchor_token(')');
+
        expression_t *expression = allocate_expression_zero(EXPR_STATEMENT);
 
        statement_t *statement           = parse_compound_statement(true);
@@ -6257,6 +6267,7 @@ static expression_t *parse_statement_expression(void)
        }
        expression->base.type = type;
 
+       rem_anchor_token(')');
        expect(')');
 
 end_error:
@@ -6269,7 +6280,6 @@ end_error:
 static expression_t *parse_parenthesized_expression(void)
 {
        eat('(');
-       add_anchor_token(')');
 
        switch(token.type) {
        case '{':
@@ -6285,6 +6295,7 @@ static expression_t *parse_parenthesized_expression(void)
                }
        }
 
+       add_anchor_token(')');
        expression_t *result = parse_expression();
        rem_anchor_token(')');
        expect(')');
@@ -6467,17 +6478,15 @@ static expression_t *parse_va_start(void)
        expression_t *const expr = parse_assignment_expression();
        if (expr->kind == EXPR_REFERENCE) {
                declaration_t *const decl = expr->reference.declaration;
-               if (decl == NULL)
-                       return create_invalid_expression();
-               if (decl->parent_scope == &current_function->scope &&
-                   decl->next == NULL) {
-                       expression->va_starte.parameter = decl;
-                       expect(')');
-                       return expression;
+               if (decl->parent_scope != &current_function->scope || decl->next != NULL) {
+                       errorf(&expr->base.source_position,
+                              "second argument of 'va_start' must be last parameter of the current function");
                }
+               expression->va_starte.parameter = decl;
+               expect(')');
+               return expression;
        }
-       errorf(&expr->base.source_position,
-              "second argument of 'va_start' must be last parameter of the current function");
+       expect(')');
 end_error:
        return create_invalid_expression();
 }
@@ -9544,7 +9553,7 @@ expression_statment:
 
        case ';':        statement = parse_empty_statement();         break;
        case '{':        statement = parse_compound_statement(false); break;
-       case T___leave:  statement = parse_leave_statement();                   break;
+       case T___leave:  statement = parse_leave_statement();         break;
        case T___try:    statement = parse_ms_try_statment();         break;
        case T_asm:      statement = parse_asm_statement();           break;
        case T_break:    statement = parse_break();                   break;
@@ -9558,7 +9567,58 @@ expression_statment:
        case T_return:   statement = parse_return();                  break;
        case T_switch:   statement = parse_switch();                  break;
        case T_while:    statement = parse_while();                   break;
-       default:         statement = parse_expression_statement();    break;
+
+       case '!':
+       case '&':
+       case '(':
+       case '*':
+       case '+':
+       case '-':
+       case '~':
+       case T_ANDAND:
+       case T_CHARACTER_CONSTANT:
+       case T_FLOATINGPOINT:
+       case T_INTEGER:
+       case T_MINUSMINUS:
+       case T_PLUSPLUS:
+       case T_STRING_LITERAL:
+       case T_WIDE_CHARACTER_CONSTANT:
+       case T_WIDE_STRING_LITERAL:
+       case T___FUNCDNAME__:
+       case T___FUNCSIG__:
+       case T___FUNCTION__:
+       case T___PRETTY_FUNCTION__:
+       case T___builtin_alloca:
+       case T___builtin_classify_type:
+       case T___builtin_constant_p:
+       case T___builtin_expect:
+       case T___builtin_huge_val:
+       case T___builtin_isgreater:
+       case T___builtin_isgreaterequal:
+       case T___builtin_isless:
+       case T___builtin_islessequal:
+       case T___builtin_islessgreater:
+       case T___builtin_isunordered:
+       case T___builtin_nan:
+       case T___builtin_nand:
+       case T___builtin_nanf:
+       case T___builtin_offsetof:
+       case T___builtin_prefetch:
+       case T___builtin_va_arg:
+       case T___builtin_va_end:
+       case T___builtin_va_start:
+       case T___func__:
+       case T___noop:
+       case T__assume:
+               statement = parse_expression_statement();
+               break;
+
+       default:
+               errorf(HERE, "unexpected token %K while parsing statement", &token);
+               statement = create_invalid_statement();
+               if (!at_anchor())
+                       next_token();
+               break;
        }
        rem_anchor_token(';');
 
@@ -9766,7 +9826,7 @@ static void parse_translation_unit(void)
                        }
                }
                if (anchor_leak)
-                       exit(1);
+                       abort();
 #endif
 
                switch (token.type) {