@@ -150,8 +150,7 @@ c_convert (tree type, tree expr, bool init_const)
case BOOLEAN_TYPE:
convert_to_boolean:
- return fold_convert_loc
- (loc, type, c_objc_common_truthvalue_conversion (input_location, expr));
+ return c_objc_common_truthvalue_conversion (input_location, expr, type);
case POINTER_TYPE:
/* The type nullptr_t may be converted to a pointer type. The result is
@@ -755,7 +755,8 @@ bool c_type_variably_modified_p (tree t)
extern bool char_type_p (tree);
-extern tree c_objc_common_truthvalue_conversion (location_t, tree);
+extern tree c_objc_common_truthvalue_conversion (location_t, tree,
+ tree = integer_type_node);
extern tree require_complete_type (location_t, tree);
extern bool same_translation_unit_p (const_tree, const_tree);
extern int comptypes (tree, tree);
@@ -6363,6 +6363,22 @@ build_c_cast (location_t loc, tree type, tree expr)
" from %qT to %qT", otype, type);
ovalue = value;
+ /* If converting to boolean a value with integer operands that
+ is not itself represented as an INTEGER_CST, the call below
+ to note_integer_operands may insert a C_MAYBE_CONST_EXPR, but
+ build_binary_op as called by c_common_truthvalue_conversion
+ may also insert a C_MAYBE_CONST_EXPR to indicate that a
+ subexpression has been fully folded. To avoid nested
+ C_MAYBE_CONST_EXPR, ensure that
+ c_objc_common_truthvalue_conversion receives an argument
+ properly marked as having integer operands in that case. */
+ if (int_operands
+ && TREE_CODE (value) != INTEGER_CST
+ && (TREE_CODE (type) == BOOLEAN_TYPE
+ || (TREE_CODE (type) == ENUMERAL_TYPE
+ && ENUM_UNDERLYING_TYPE (type) != NULL_TREE
+ && TREE_CODE (ENUM_UNDERLYING_TYPE (type)) == BOOLEAN_TYPE)))
+ value = note_integer_operands (value);
value = convert (type, value);
/* Ignore any integer overflow caused by the cast. */
@@ -13509,11 +13525,11 @@ build_binary_op (location_t location, enum tree_code code,
}
-/* Convert EXPR to be a truth-value, validating its type for this
+/* Convert EXPR to be a truth-value (type TYPE), validating its type for this
purpose. LOCATION is the source location for the expression. */
tree
-c_objc_common_truthvalue_conversion (location_t location, tree expr)
+c_objc_common_truthvalue_conversion (location_t location, tree expr, tree type)
{
bool int_const, int_operands;
@@ -13556,14 +13572,17 @@ c_objc_common_truthvalue_conversion (location_t location, tree expr)
if (int_operands && TREE_CODE (expr) != INTEGER_CST)
{
expr = remove_c_maybe_const_expr (expr);
- expr = build2 (NE_EXPR, integer_type_node, expr,
+ expr = build2 (NE_EXPR, type, expr,
convert (TREE_TYPE (expr), integer_zero_node));
expr = note_integer_operands (expr);
}
else
- /* ??? Should we also give an error for vectors rather than leaving
- those to give errors later? */
- expr = c_common_truthvalue_conversion (location, expr);
+ {
+ /* ??? Should we also give an error for vectors rather than leaving
+ those to give errors later? */
+ expr = c_common_truthvalue_conversion (location, expr);
+ expr = fold_convert_loc (location, type, expr);
+ }
if (TREE_CODE (expr) == INTEGER_CST && int_operands && !int_const)
{
new file mode 100644
@@ -0,0 +1,5 @@
+void
+f ()
+{
+ (_Bool) (1 << -1);
+}
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-options "-std=gnu23 -Wno-div-by-zero" } */
+
+enum e : bool { X };
+
+enum e
+f ()
+{
+ return 0 / 0;
+}
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-options "-std=gnu23 -Wno-overflow" } */
+
+enum e : bool { X };
+
+void
+f ()
+{
+ (enum e) (__INT_MAX__ + 1);
+}
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-options "-std=gnu23 -Wno-overflow" } */
+
+enum e : bool { X };
+
+enum e
+f ()
+{
+ return __INT_MAX__ + 1;
+}
new file mode 100644
@@ -0,0 +1,5 @@
+void
+f ()
+{
+ (_Bool) (0 / 0);
+}
new file mode 100644
@@ -0,0 +1,5 @@
+_Bool
+f ()
+{
+ return 1 << -1;
+}
new file mode 100644
@@ -0,0 +1,5 @@
+_Bool
+f ()
+{
+ return 0 / 0;
+}
new file mode 100644
@@ -0,0 +1,5 @@
+void
+f ()
+{
+ (_Bool) (__INT_MAX__ + 1);
+}
new file mode 100644
@@ -0,0 +1,5 @@
+_Bool
+f ()
+{
+ return __INT_MAX__ + 1;
+}
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-options "-std=gnu23 -Wno-shift-count-negative" } */
+
+enum e : bool { X };
+
+void
+f ()
+{
+ (enum e) (1 << -1);
+}
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-options "-std=gnu23 -Wno-div-by-zero" } */
+
+enum e : bool { X };
+
+void
+f ()
+{
+ (enum e) (0 / 0);
+}
new file mode 100644
@@ -0,0 +1,9 @@
+/* { dg-options "-std=gnu23 -Wno-shift-count-negative" } */
+
+enum e : bool { X };
+
+enum e
+f ()
+{
+ return 1 << -1;
+}
new file mode 100644
@@ -0,0 +1,7 @@
+int
+main (void)
+{
+ if (!(_Bool)(__INT_MAX__ + 1) / !(_Bool)(__INT_MAX__ + 1))
+ ;
+ return 1;
+}
new file mode 100644
@@ -0,0 +1,11 @@
+/* { dg-options "-std=gnu23 -Wno-overflow -Wno-div-by-zero" } */
+
+enum e : bool { X };
+
+int
+main (void)
+{
+ if (!(enum e)(__INT_MAX__ + 1) / !(enum e)(__INT_MAX__ + 1))
+ ;
+ return 1;
+}