Get unqualified types before doing anything in semantic_arithmetic().
[cparser] / parser.c
index d25c44f..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));
        }
 }
 
@@ -4032,8 +4030,10 @@ 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;
+               if (inner_types != NULL) {
+                       /* All later declarators only modify the return type, not declaration */
+                       declaration = NULL;
+               }
                rem_anchor_token(')');
                expect(')');
                break;
@@ -4450,8 +4450,9 @@ static declaration_t *record_declaration(
                        if (old_storage_class == STORAGE_CLASS_EXTERN &&
                                        new_storage_class == STORAGE_CLASS_EXTERN) {
 warn_redundant_declaration:
-                               if (!is_definition          &&
-                                   warning.redundant_decls &&
+                               if (!is_definition           &&
+                                   warning.redundant_decls  &&
+                                   is_type_valid(prev_type) &&
                                    strcmp(previous_declaration->source_position.input_name, "<builtin>") != 0) {
                                        warningf(&declaration->source_position,
                                                 "redundant declaration for '%Y' (declared %P)",
@@ -4469,14 +4470,16 @@ warn_redundant_declaration:
                                } else {
                                        goto warn_redundant_declaration;
                                }
-                       } else if (old_storage_class == new_storage_class) {
-                               errorf(&declaration->source_position,
-                                      "redeclaration of '%Y' (declared %P)",
-                                      symbol, &previous_declaration->source_position);
-                       } else {
-                               errorf(&declaration->source_position,
-                                      "redeclaration of '%Y' with different linkage (declared %P)",
-                                      symbol, &previous_declaration->source_position);
+                       } else if (is_type_valid(prev_type)) {
+                               if (old_storage_class == new_storage_class) {
+                                       errorf(&declaration->source_position,
+                                              "redeclaration of '%Y' (declared %P)",
+                                              symbol, &previous_declaration->source_position);
+                               } else {
+                                       errorf(&declaration->source_position,
+                                              "redeclaration of '%Y' with different linkage (declared %P)",
+                                              symbol, &previous_declaration->source_position);
+                               }
                        }
                }
 
@@ -6046,11 +6049,8 @@ static expression_t *parse_reference(void)
 
        declaration_t *declaration = get_declaration(symbol, NAMESPACE_NORMAL);
 
-       source_position_t source_position = token.source_position;
-       next_token();
-
        if (declaration == NULL) {
-               if (token.type == '(') {
+               if (look_ahead(1)->type == '(') {
                        /* an implicitly declared function */
                        if (strict_mode) {
                                errorf(HERE, "unknown symbol '%Y' found.", symbol);
@@ -6059,8 +6059,7 @@ static expression_t *parse_reference(void)
                                        symbol);
                        }
 
-                       declaration = create_implicit_function(symbol,
-                                                              &source_position);
+                       declaration = create_implicit_function(symbol, HERE);
                } else {
                        errorf(HERE, "unknown symbol '%Y' found.", symbol);
                        declaration = create_error_declaration(symbol, STORAGE_CLASS_NONE);
@@ -6086,23 +6085,21 @@ static expression_t *parse_reference(void)
                        "function" : "variable";
 
                if (declaration->deprecated_string != NULL) {
-                       warningf(&source_position,
-                               "%s '%Y' is deprecated (declared %P): \"%s\"", prefix,
-                               declaration->symbol, &declaration->source_position,
+                       warningf(HERE, "%s '%Y' is deprecated (declared %P): \"%s\"",
+                               prefix, declaration->symbol, &declaration->source_position,
                                declaration->deprecated_string);
                } else {
-                       warningf(&source_position,
-                               "%s '%Y' is deprecated (declared %P)", prefix,
+                       warningf(HERE, "%s '%Y' is deprecated (declared %P)", prefix,
                                declaration->symbol, &declaration->source_position);
                }
        }
        if (warning.init_self && declaration == current_init_decl) {
                current_init_decl = NULL;
-               warningf(&source_position,
-                       "variable '%#T' is initialized by itself",
+               warningf(HERE, "variable '%#T' is initialized by itself",
                        declaration->type, declaration->symbol);
        }
 
+       next_token();
        return expression;
 }
 
@@ -6858,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;
 }
 
@@ -6990,7 +6986,7 @@ static expression_t *parse_select_expression(unsigned precedence,
                if (!declaration->init.complete) {
                        errorf(HERE, "request for member '%Y' of incomplete type '%T'",
                               symbol, type_left);
-                       return create_invalid_expression();
+                       goto create_error_entry;
                }
 
                entry = find_compound_entry(declaration, symbol);
@@ -7072,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);
                }
        }
 }
@@ -7612,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;
@@ -7698,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");
        }
 }
@@ -8627,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;
        }
@@ -8640,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) {
@@ -9477,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;
                }