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;
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;
} 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));
}
}
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);
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);
"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;
}
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;
}
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);
}
}
}
{
/* 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;
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");
}
}
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;
}
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) {
} 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;
}