Implicitly cast unadorned floating point constants

Floating point constants without f or d adornments will automatically
cast, without warnings, to the type appropriate to the rest of the
expression.
This commit is contained in:
Bill Currie 2020-02-23 22:28:54 +09:00
parent 14cde99d6e
commit e23aa40994
5 changed files with 18 additions and 4 deletions

View file

@ -197,6 +197,7 @@ typedef struct expr_s {
int printid; ///< avoid duplicate output when printing int printid; ///< avoid duplicate output when printing
unsigned paren:1; ///< the expression is enclosed in () unsigned paren:1; ///< the expression is enclosed in ()
unsigned rvalue:1; ///< the expression is on the right side of = unsigned rvalue:1; ///< the expression is on the right side of =
unsigned implicit:1; ///< don't warn for implicit casts
union { union {
ex_label_t label; ///< label expression ex_label_t label; ///< label expression
ex_labelref_t labelref; ///< label reference expression (&) ex_labelref_t labelref; ///< label reference expression (&)

View file

@ -609,7 +609,8 @@ initialize_def (symbol_t *sym, expr_t *init, defspace_t *space,
reloc_def_field (init->e.value->v.pointer.def, sym->s.def); reloc_def_field (init->e.value->v.pointer.def, sym->s.def);
} else { } else {
ex_value_t *v = init->e.value; ex_value_t *v = init->e.value;
if (is_double (init_type) if (!init->implicit
&& is_double (init_type)
&& (is_integral (sym->type) || is_float (sym->type))) { && (is_integral (sym->type) || is_float (sym->type))) {
warning (init, "assigning double to %s in initializer " warning (init, "assigning double to %s in initializer "
"(use a cast)", sym->type->name); "(use a cast)", sym->type->name);

View file

@ -151,10 +151,12 @@ check_types_compatible (expr_t *dst, expr_t *src)
if (type_assignable (dst_type, src_type)) { if (type_assignable (dst_type, src_type)) {
if (is_scalar (dst_type) && is_scalar (src_type)) { if (is_scalar (dst_type) && is_scalar (src_type)) {
if (!src->implicit) {
if (is_double (src_type)) { if (is_double (src_type)) {
warning (dst, "assignment of double to %s (use a cast)\n", warning (dst, "assignment of double to %s (use a cast)\n",
dst_type->name); dst_type->name);
} }
}
// the types are different but cast-compatible // the types are different but cast-compatible
expr_t *new = cast_expr (dst_type, src); expr_t *new = cast_expr (dst_type, src);
// the cast was a no-op, so the types are compatible at the // the cast was a no-op, so the types are compatible at the

View file

@ -954,6 +954,15 @@ binary_expr (int op, expr_t *e1, expr_t *e2)
et1 = low_level_type (t1); et1 = low_level_type (t1);
et2 = low_level_type (t2); et2 = low_level_type (t2);
if (is_constant (e1) && is_double (t1) && e1->implicit && is_float (t2)) {
t1 = &type_float;
convert_double (e1);
}
if (is_constant (e2) && is_double (t2) && e2->implicit && is_float (t1)) {
t2 = &type_float;
convert_double (e2);
}
if (et1 >= ev_type_count || !binary_expr_types[et1]) if (et1 >= ev_type_count || !binary_expr_types[et1])
return invalid_binary_expr(op, e1, e2); return invalid_binary_expr(op, e1, e2);
if (et2 >= ev_type_count || !binary_expr_types[et1][et2]) if (et2 >= ev_type_count || !binary_expr_types[et1][et2])

View file

@ -143,6 +143,7 @@ STRING \"(\\.|[^"\\])*\"
if (options.traditional < 1) { if (options.traditional < 1) {
double d = strtod (yytext, 0); double d = strtod (yytext, 0);
qc_yylval.expr = new_double_expr (d); qc_yylval.expr = new_double_expr (d);
qc_yylval.expr->implicit = 1;
} else { } else {
float f = strtof (yytext, 0); float f = strtof (yytext, 0);
qc_yylval.expr = new_float_expr (f); qc_yylval.expr = new_float_expr (f);