Only warn about reaching the end of a non-void function, if the return type is valid.
[cparser] / parser.c
index f6abed4..c9df2f3 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -3053,7 +3053,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
        type_qualifiers_t  qualifiers      = TYPE_QUALIFIER_NONE;
        type_modifiers_t   modifiers       = TYPE_MODIFIER_NONE;
        unsigned           type_specifiers = 0;
-       int                newtype         = 0;
+       bool               newtype         = false;
 
        specifiers->source_position = token.source_position;
 
@@ -3377,7 +3377,7 @@ warn_about_long_long:
                                }
                        } else if ((type_specifiers & SPECIFIER_SIGNED) &&
                                  (type_specifiers & SPECIFIER_UNSIGNED)) {
-                               errorf(HERE, "signed and unsigned specifiers gives");
+                               errorf(HERE, "signed and unsigned specifiers given");
                        } else if (type_specifiers & (SPECIFIER_SIGNED | SPECIFIER_UNSIGNED)) {
                                errorf(HERE, "only integer types can be signed or unsigned");
                        } else {
@@ -3398,11 +3398,9 @@ warn_about_long_long:
                        type               = allocate_type_zero(TYPE_ATOMIC, &builtin_source_position);
                        type->atomic.akind = atomic_type;
                }
-               newtype = 1;
-       } else {
-               if (type_specifiers != 0) {
-                       errorf(HERE, "multiple datatypes in declaration");
-               }
+               newtype = true;
+       } else if (type_specifiers != 0) {
+               errorf(HERE, "multiple datatypes in declaration");
        }
 
        /* FIXME: check type qualifiers here */
@@ -3715,7 +3713,7 @@ static construct_type_t *parse_function_declarator(declaration_t *declaration)
                                else if (second == NULL) second = "stdcall";
                        }
                        if (declaration->modifiers & DM_FASTCALL) {
-                               if (first == NULL)       first = "faslcall";
+                               if (first == NULL)       first = "fastcall";
                                else if (second == NULL) second = "fastcall";
                        }
                        if (declaration->modifiers & DM_THISCALL) {
@@ -3819,6 +3817,8 @@ static construct_type_t *parse_inner_declarator(declaration_t *declaration,
                next_token();
                add_anchor_token(')');
                inner_types = parse_inner_declarator(declaration, may_be_abstract);
+               /* All later declarators only modify the return type, not declaration */
+               declaration = NULL;
                rem_anchor_token(')');
                expect(')');
                break;
@@ -4008,6 +4008,7 @@ static declaration_t *parse_declarator(
                const declaration_specifiers_t *specifiers, bool may_be_abstract)
 {
        declaration_t *const declaration    = allocate_declaration_zero();
+       declaration->source_position        = specifiers->source_position;
        declaration->declared_storage_class = specifiers->declared_storage_class;
        declaration->modifiers              = specifiers->modifiers;
        declaration->deprecated_string      = specifiers->deprecated_string;
@@ -4897,6 +4898,7 @@ found_break_parent:
                        type_t *const ret  = skip_typeref(type->function.return_type);
                        if (warning.return_type                    &&
                            !is_type_atomic(ret, ATOMIC_TYPE_VOID) &&
+                           is_type_valid(ret)                     &&
                            !is_sym_main(current_function->symbol)) {
                                warningf(&stmt->base.source_position,
                                         "control reaches end of non-void function");
@@ -5199,7 +5201,7 @@ static void parse_external_declaration(void)
                                || parameter->parent_scope == scope);
                parameter->parent_scope = scope;
                if (parameter->symbol == NULL) {
-                       errorf(&ndeclaration->source_position, "parameter name omitted");
+                       errorf(&parameter->source_position, "parameter name omitted");
                        continue;
                }
                environment_push(parameter);
@@ -6789,13 +6791,14 @@ static bool same_compound_type(const type_t *type1, const type_t *type2)
 static expression_t *parse_conditional_expression(unsigned precedence,
                                                   expression_t *expression)
 {
-       eat('?');
-       add_anchor_token(':');
-
        expression_t *result = allocate_expression_zero(EXPR_CONDITIONAL);
 
        conditional_expression_t *conditional = &result->conditional;
-       conditional->condition = expression;
+       conditional->base.source_position = *HERE;
+       conditional->condition            = expression;
+
+       eat('?');
+       add_anchor_token(':');
 
        /* 6.5.15.2 */
        type_t *const condition_type_orig = expression->base.type;
@@ -6821,7 +6824,7 @@ static expression_t *parse_conditional_expression(unsigned precedence,
                is_type_atomic(false_type, ATOMIC_TYPE_VOID)) {
                if (!is_type_atomic(true_type, ATOMIC_TYPE_VOID)
                    || !is_type_atomic(false_type, ATOMIC_TYPE_VOID)) {
-                       warningf(&expression->base.source_position,
+                       warningf(&conditional->base.source_position,
                                        "ISO C forbids conditional expression with only one void side");
                }
                result_type = type_void;
@@ -6867,7 +6870,7 @@ static expression_t *parse_conditional_expression(unsigned precedence,
                                                    get_unqualified_type(to2))) {
                                to = to1;
                        } else {
-                               warningf(&expression->base.source_position,
+                               warningf(&conditional->base.source_position,
                                        "pointer types '%T' and '%T' in conditional expression are incompatible",
                                        true_type, false_type);
                                to = type_void;
@@ -6882,7 +6885,7 @@ static expression_t *parse_conditional_expression(unsigned precedence,
 
                        result_type = make_pointer_type(type, TYPE_QUALIFIER_NONE);
                } else if (is_type_integer(other_type)) {
-                       warningf(&expression->base.source_position,
+                       warningf(&conditional->base.source_position,
                                        "pointer/integer type mismatch in conditional expression ('%T' and '%T')", true_type, false_type);
                        result_type = pointer_type;
                } else {
@@ -6895,7 +6898,7 @@ static expression_t *parse_conditional_expression(unsigned precedence,
 
                if (is_type_valid(true_type) && is_type_valid(false_type)) {
                        type_error_incompatible("while parsing conditional",
-                                               &expression->base.source_position, true_type,
+                                               &conditional->base.source_position, true_type,
                                                false_type);
                }
                result_type = type_error_type;
@@ -6946,7 +6949,7 @@ end_error:
        return create_invalid_expression();
 }
 
-static void check_pointer_arithmetic(const source_position_t *source_position,
+static bool check_pointer_arithmetic(const source_position_t *source_position,
                                      type_t *pointer_type,
                                      type_t *orig_pointer_type)
 {
@@ -6959,11 +6962,14 @@ static void check_pointer_arithmetic(const source_position_t *source_position,
                errorf(source_position,
                           "arithmetic with pointer to incomplete type '%T' not allowed",
                           orig_pointer_type);
+               return false;
        } else if (is_type_function(points_to)) {
                errorf(source_position,
                           "arithmetic with pointer to function type '%T' not allowed",
                           orig_pointer_type);
+               return false;
        }
+       return true;
 }
 
 static void semantic_incdec(unary_expression_t *expression)
@@ -6971,12 +6977,15 @@ static void semantic_incdec(unary_expression_t *expression)
        type_t *const orig_type = expression->value->base.type;
        type_t *const type      = skip_typeref(orig_type);
        if (is_type_pointer(type)) {
-               check_pointer_arithmetic(&expression->base.source_position,
-                                        type, orig_type);
+               if (!check_pointer_arithmetic(&expression->base.source_position,
+                                             type, orig_type)) {
+                       return;
+               }
        } else if (!is_type_real(type) && is_type_valid(type)) {
                /* TODO: improve error message */
                errorf(&expression->base.source_position,
                       "operation needs an arithmetic or pointer type");
+               return;
        }
        expression->base.type = orig_type;
 }
@@ -7080,11 +7089,10 @@ static void semantic_take_addr(unary_expression_t *expression)
 #define CREATE_UNARY_EXPRESSION_PARSER(token_type, unexpression_type, sfunc)   \
 static expression_t *parse_##unexpression_type(unsigned precedence)            \
 {                                                                              \
-       eat(token_type);                                                           \
-                                                                                  \
        expression_t *unary_expression                                             \
                = allocate_expression_zero(unexpression_type);                         \
        unary_expression->base.source_position = *HERE;                            \
+       eat(token_type);                                                           \
        unary_expression->unary.value = parse_sub_expression(precedence);          \
                                                                                   \
        sfunc(&unary_expression->unary);                                           \
@@ -7115,11 +7123,12 @@ static expression_t *parse_##unexpression_type(unsigned precedence,           \
                                                expression_t *left)            \
 {                                                                             \
        (void) precedence;                                                        \
-       eat(token_type);                                                          \
                                                                               \
        expression_t *unary_expression                                            \
                = allocate_expression_zero(unexpression_type);                        \
-       unary_expression->unary.value = left;                                     \
+       unary_expression->base.source_position = *HERE;                           \
+       eat(token_type);                                                          \
+       unary_expression->unary.value          = left;                            \
                                                                                  \
        sfunc(&unary_expression->unary);                                          \
                                                                               \
@@ -7713,14 +7722,13 @@ static void semantic_comma(binary_expression_t *expression)
 static expression_t *parse_##binexpression_type(unsigned precedence,      \
                                                 expression_t *left)       \
 {                                                                         \
+       expression_t *binexpr = allocate_expression_zero(binexpression_type); \
+       binexpr->base.source_position = *HERE;                                \
+       binexpr->binary.left          = left;                                 \
        eat(token_type);                                                      \
-       source_position_t pos = *HERE;                                        \
                                                                           \
        expression_t *right = parse_sub_expression(precedence + lr);          \
                                                                           \
-       expression_t *binexpr = allocate_expression_zero(binexpression_type); \
-       binexpr->base.source_position = pos;                                  \
-       binexpr->binary.left  = left;                                         \
        binexpr->binary.right = right;                                        \
        sfunc(&binexpr->binary);                                              \
                                                                           \