Get unqualified types before doing anything in semantic_arithmetic().
[cparser] / parser.c
index b3ff091..1502d2e 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1030,7 +1030,7 @@ static void report_assign_error(assign_error_t error, type_t *orig_type_left,
 
        case ASSIGN_WARNING_POINTER_FROM_INT:
                warningf(source_position,
-                        "%s makes integer '%T' from pointer '%T' without a cast",
+                        "%s makes pointer '%T' from integer '%T' without a cast",
                                 context, orig_type_left, orig_type_right);
                return;
 
@@ -2148,8 +2148,6 @@ static void descend_into_subtype(type_path_t *path)
        type_t *orig_top_type = path->top_type;
        type_t *top_type      = skip_typeref(orig_top_type);
 
-       assert(is_type_compound(top_type) || is_type_array(top_type));
-
        type_path_entry_t *top = append_to_type_path(path);
        top->type              = top_type;
 
@@ -2163,11 +2161,11 @@ static void descend_into_subtype(type_path_t *path)
                } else {
                        path->top_type         = NULL;
                }
-       } else {
-               assert(is_type_array(top_type));
-
+       } else if (is_type_array(top_type)) {
                top->v.index   = 0;
                path->top_type = top_type->array.element_type;
+       } else {
+               assert(!is_type_valid(top_type));
        }
 }
 
@@ -6857,19 +6855,18 @@ static expression_t *parse_array_expression(unsigned precedence,
                                orig_type_left, orig_type_inside);
                }
                return_type             = type_error_type;
-               array_access->array_ref = create_invalid_expression();
+               array_access->array_ref = left;
+               array_access->index     = inside;
        }
 
+       expression->base.type = automatic_type_conversion(return_type);
+
        rem_anchor_token(']');
-       if (token.type != ']') {
+       if (token.type == ']') {
+               next_token();
+       } else {
                parse_error_expected("Problem while parsing array access", ']', NULL);
-               return expression;
        }
-       next_token();
-
-       return_type           = automatic_type_conversion(return_type);
-       expression->base.type = return_type;
-
        return expression;
 }
 
@@ -7071,26 +7068,15 @@ static void check_call_argument(const function_parameter_t *parameter,
                snprintf(buf, sizeof(buf), "call argument %u", pos);
                report_assign_error(error, expected_type, arg_expr,     buf,
                                                        &arg_expr->base.source_position);
-       } else if (warning.traditional | warning.conversion) {
-               if (
-                   /* passing as integer instead of float or complex */
-                   (is_type_integer(expected_type) &&
-                    (is_type_float(arg_type) || is_type_complex(arg_type))) ||
-                   /* passing as complex instead of integer or float */
-                   (is_type_complex(expected_type) &&
-                    (is_type_integer(arg_type) || is_type_float(arg_type))) ||
-                   /* passing as float instead of integer or complex */
-                   (is_type_float(expected_type) &&
-                    (is_type_integer(arg_type) || is_type_complex(arg_type))) ||
-                   /* passing as float instead of double */
-                   (is_type_float(expected_type) && expected_type != type_double &&
-                    is_type_float(arg_type))) {
+       } else if (warning.traditional || warning.conversion) {
+               type_t *const promoted_type = get_default_promoted_type(arg_type);
+               if (!types_compatible(expected_type_skip, promoted_type) &&
+                   !types_compatible(expected_type_skip, type_void_ptr) &&
+                   !types_compatible(type_void_ptr,      promoted_type)) {
+                       /* Deliberately show the skipped types in this warning */
                        warningf(&arg_expr->base.source_position,
                                "passing call argument %u as '%T' rather than '%T' due to prototype",
-                               pos, expected_type, arg_type);
-               }
-               if (is_type_integer(expected_type) && is_type_integer(arg_type)) {
-                       /* TODO check for size HERE */
+                               pos, expected_type_skip, promoted_type);
                }
        }
 }
@@ -7611,6 +7597,9 @@ static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right)
 {
        /* TODO: handle complex + imaginary types */
 
+       type_left  = get_unqualified_type(type_left);
+       type_right = get_unqualified_type(type_right);
+
        /* ยง 6.3.1.8 Usual arithmetic conversions */
        if (type_left == type_long_double || type_right == type_long_double) {
                return type_long_double;
@@ -7697,10 +7686,15 @@ static void semantic_binexpr_arithmetic(binary_expression_t *expression)
 
 static void warn_div_by_zero(binary_expression_t const *const expression)
 {
-       if (warning.div_by_zero                       &&
-           is_type_integer(expression->base.type)    &&
-           is_constant_expression(expression->right) &&
-           fold_constant(expression->right) == 0) {
+       if (!warning.div_by_zero ||
+           !is_type_integer(expression->base.type))
+               return;
+
+       expression_t const *const right = expression->right;
+       /* The type of the right operand can be different for /= */
+       if (is_type_integer(right->base.type) &&
+           is_constant_expression(right)     &&
+           fold_constant(right) == 0) {
                warningf(&expression->base.source_position, "division by zero");
        }
 }
@@ -8626,12 +8620,18 @@ static statement_t *parse_case_statement(void)
        source_position_t *const pos       = &statement->base.source_position;
 
        *pos                             = token.source_position;
-       statement->case_label.expression = parse_expression();
-       if (! is_constant_expression(statement->case_label.expression)) {
-               errorf(pos, "case label does not reduce to an integer constant");
+       expression_t *const expression   = parse_expression();
+       statement->case_label.expression = expression;
+       if (!is_constant_expression(expression)) {
+               /* This check does not prevent the error message in all cases of an
+                * prior error while parsing the expression.  At least it catches the
+                * common case of a mistyped enum entry. */
+               if (is_type_valid(expression->base.type)) {
+                       errorf(pos, "case label does not reduce to an integer constant");
+               }
                statement->case_label.is_bad = true;
        } else {
-               long const val = fold_constant(statement->case_label.expression);
+               long const val = fold_constant(expression);
                statement->case_label.first_case = val;
                statement->case_label.last_case  = val;
        }
@@ -8639,12 +8639,18 @@ static statement_t *parse_case_statement(void)
        if (c_mode & _GNUC) {
                if (token.type == T_DOTDOTDOT) {
                        next_token();
-                       statement->case_label.end_range = parse_expression();
-                       if (! is_constant_expression(statement->case_label.end_range)) {
-                               errorf(pos, "case range does not reduce to an integer constant");
+                       expression_t *const end_range   = parse_expression();
+                       statement->case_label.end_range = end_range;
+                       if (!is_constant_expression(end_range)) {
+                               /* This check does not prevent the error message in all cases of an
+                                * prior error while parsing the expression.  At least it catches the
+                                * common case of a mistyped enum entry. */
+                               if (is_type_valid(end_range->base.type)) {
+                                       errorf(pos, "case range does not reduce to an integer constant");
+                               }
                                statement->case_label.is_bad = true;
                        } else {
-                               long const val = fold_constant(statement->case_label.end_range);
+                               long const val = fold_constant(end_range);
                                statement->case_label.last_case = val;
 
                                if (val < statement->case_label.first_case) {
@@ -9476,13 +9482,18 @@ static statement_t *intern_parse_statement(void)
                } else if (is_typedef_symbol(token.v.symbol)) {
                        statement = parse_declaration_statement();
                } else switch (la1_type) {
+                       case '*':
+                               if (get_declaration(token.v.symbol, NAMESPACE_NORMAL) != NULL)
+                                       goto expression_statment;
+                               /* FALLTHROUGH */
+
                        DECLARATION_START
                        case T_IDENTIFIER:
-                       case '*':
                                statement = parse_declaration_statement();
                                break;
 
                        default:
+expression_statment:
                                statement = parse_expression_statement();
                                break;
                }