aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/c-convert.c35
-rw-r--r--gcc/c/c-typeck.c27
2 files changed, 52 insertions, 10 deletions
diff --git a/gcc/c/c-convert.c b/gcc/c/c-convert.c
index d0035a3..905b26a 100644
--- a/gcc/c/c-convert.c
+++ b/gcc/c/c-convert.c
@@ -60,10 +60,13 @@ along with GCC; see the file COPYING3. If not see
converted to type TYPE. The TREE_TYPE of the value
is always TYPE. This function implements all reasonable
conversions; callers should filter out those that are
- not permitted by the language being compiled. */
+ not permitted by the language being compiled.
+ INIT_CONST is true if the conversion is for arithmetic types for a static
+ initializer and folding must apply accordingly (discarding floating-point
+ exceptions and assuming the default rounding mode is in effect). */
-tree
-convert (tree type, tree expr)
+static tree
+c_convert (tree type, tree expr, bool init_const)
{
tree e = expr;
enum tree_code code = TREE_CODE (type);
@@ -115,7 +118,7 @@ convert (tree type, tree expr)
&& COMPLETE_TYPE_P (type))
{
expr = save_expr (expr);
- expr = c_fully_fold (expr, false, NULL);
+ expr = c_fully_fold (expr, init_const, NULL);
tree check = ubsan_instrument_float_cast (loc, type, expr);
expr = fold_build1 (FIX_TRUNC_EXPR, type, expr);
if (check == NULL_TREE)
@@ -173,10 +176,32 @@ convert (tree type, tree expr)
maybe_fold:
if (TREE_CODE (ret) != C_MAYBE_CONST_EXPR)
- ret = fold (ret);
+ ret = init_const ? fold_init (ret) : fold (ret);
return ret;
}
error ("conversion to non-scalar type requested");
return error_mark_node;
}
+
+/* Create an expression whose value is that of EXPR, converted to type TYPE.
+ The TREE_TYPE of the value is always TYPE. This function implements all
+ reasonable conversions; callers should filter out those that are not
+ permitted by the language being compiled. */
+
+tree
+convert (tree type, tree expr)
+{
+ return c_convert (type, expr, false);
+}
+
+/* Create an expression whose value is that of EXPR, converted to type TYPE, in
+ a static initializer. The TREE_TYPE of the value is always TYPE. This
+ function implements all reasonable conversions; callers should filter out
+ those that are not permitted by the language being compiled. */
+
+tree
+convert_init (tree type, tree expr)
+{
+ return c_convert (type, expr, true);
+}
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 0aac978..782414f 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -53,12 +53,13 @@ along with GCC; see the file COPYING3. If not see
#include "attribs.h"
#include "asan.h"
-/* Possible cases of implicit bad conversions. Used to select
- diagnostic messages in convert_for_assignment. */
+/* Possible cases of implicit conversions. Used to select diagnostic messages
+ and control folding initializers in convert_for_assignment. */
enum impl_conv {
ic_argpass,
ic_assign,
ic_init,
+ ic_init_const,
ic_return
};
@@ -6802,6 +6803,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
pedwarn (LOCATION, OPT, AS); \
break; \
case ic_init: \
+ case ic_init_const: \
pedwarn_init (LOCATION, OPT, IN); \
break; \
case ic_return: \
@@ -6838,6 +6840,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
warning_at (LOCATION, OPT, AS, QUALS); \
break; \
case ic_init: \
+ case ic_init_const: \
if (PEDWARN) \
pedwarn (LOCATION, OPT, IN, QUALS); \
else \
@@ -6886,6 +6889,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
break;
case ic_init:
+ case ic_init_const:
parmno = -2;
break;
@@ -6919,6 +6923,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
"%qT in assignment is invalid in C++", rhstype, type);
break;
case ic_init:
+ case ic_init_const:
pedwarn_init (location, OPT_Wc___compat, "enum conversion from "
"%qT to %qT in initialization is invalid in C++",
rhstype, type);
@@ -7029,7 +7034,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
&& sanitize_flags_p (SANITIZE_FLOAT_CAST)))
in_late_binary_op = true;
tree ret = convert_and_check (expr_loc != UNKNOWN_LOCATION
- ? expr_loc : location, type, orig_rhs);
+ ? expr_loc : location, type, orig_rhs,
+ errtype == ic_init_const);
in_late_binary_op = save;
return ret;
}
@@ -7252,6 +7258,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
break;
}
case ic_init:
+ case ic_init_const:
{
const char msg[] = G_("initialization from pointer to "
"non-enclosed address space");
@@ -7296,6 +7303,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
"a candidate for a format attribute");
break;
case ic_init:
+ case ic_init_const:
warning_at (location, OPT_Wsuggest_attribute_format,
"initialization left-hand side might be "
"a candidate for a format attribute");
@@ -7339,6 +7347,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
"incompatible scalar storage order", type, rhstype);
break;
case ic_init:
+ case ic_init_const:
/* Likewise. */
if (TREE_CODE (rhs) != CALL_EXPR
|| (t = get_callee_fndecl (rhs)) == NULL_TREE
@@ -7465,6 +7474,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
"differ in signedness", rhstype, type);
break;
case ic_init:
+ case ic_init_const:
pedwarn_init (location, OPT_Wpointer_sign,
"pointer targets in initialization of %qT "
"from %qT differ in signedness", type,
@@ -7530,6 +7540,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
type, rhstype);
break;
case ic_init:
+ case ic_init_const:
if (bltin)
pedwarn_init (location, OPT_Wincompatible_pointer_types,
"initialization of %qT from pointer to "
@@ -7599,6 +7610,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
"without a cast", type, rhstype);
break;
case ic_init:
+ case ic_init_const:
pedwarn_init (location, OPT_Wint_conversion,
"initialization of %qT from %qT makes pointer from "
"integer without a cast", type, rhstype);
@@ -7635,6 +7647,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
"without a cast", type, rhstype);
break;
case ic_init:
+ case ic_init_const:
pedwarn_init (location, OPT_Wint_conversion,
"initialization of %qT from %qT makes integer from "
"pointer without a cast", type, rhstype);
@@ -7686,6 +7699,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
break;
}
case ic_init:
+ case ic_init_const:
{
const char msg[]
= G_("incompatible types when initializing type %qT using type %qT");
@@ -8195,7 +8209,9 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE)
inside_init = convert_for_assignment (init_loc, UNKNOWN_LOCATION,
type, inside_init, origtype,
- ic_init, null_pointer_constant,
+ (require_constant
+ ? ic_init_const
+ : ic_init), null_pointer_constant,
NULL_TREE, NULL_TREE, 0);
return inside_init;
}
@@ -8215,7 +8231,8 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype,
inside_init);
inside_init
= convert_for_assignment (init_loc, UNKNOWN_LOCATION, type,
- inside_init, origtype, ic_init,
+ inside_init, origtype,
+ require_constant ? ic_init_const : ic_init,
null_pointer_constant, NULL_TREE, NULL_TREE,
0);