diff options
-rw-r--r-- | gcc/c/c-convert.cc | 3 | ||||
-rw-r--r-- | gcc/c/c-tree.h | 3 | ||||
-rw-r--r-- | gcc/c/c-typeck.cc | 31 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111059-1.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111059-10.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111059-11.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111059-12.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111059-2.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111059-3.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111059-4.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111059-5.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111059-6.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111059-7.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111059-8.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111059-9.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111911-1.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr111911-2.c | 11 |
17 files changed, 130 insertions, 9 deletions
diff --git a/gcc/c/c-convert.cc b/gcc/c/c-convert.cc index 3e52926..7c1064c 100644 --- a/gcc/c/c-convert.cc +++ b/gcc/c/c-convert.cc @@ -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 diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index cf29534..1fba9c8 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -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); diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 66c6abc..12d1a5a 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -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) { diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111059-1.c b/gcc/testsuite/gcc.c-torture/compile/pr111059-1.c new file mode 100644 index 0000000..5788cb4 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111059-1.c @@ -0,0 +1,5 @@ +void +f () +{ + (_Bool) (1 << -1); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111059-10.c b/gcc/testsuite/gcc.c-torture/compile/pr111059-10.c new file mode 100644 index 0000000..fdd9a29 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111059-10.c @@ -0,0 +1,9 @@ +/* { dg-options "-std=gnu23 -Wno-div-by-zero" } */ + +enum e : bool { X }; + +enum e +f () +{ + return 0 / 0; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111059-11.c b/gcc/testsuite/gcc.c-torture/compile/pr111059-11.c new file mode 100644 index 0000000..8126034 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111059-11.c @@ -0,0 +1,9 @@ +/* { dg-options "-std=gnu23 -Wno-overflow" } */ + +enum e : bool { X }; + +void +f () +{ + (enum e) (__INT_MAX__ + 1); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111059-12.c b/gcc/testsuite/gcc.c-torture/compile/pr111059-12.c new file mode 100644 index 0000000..d11fcf6 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111059-12.c @@ -0,0 +1,9 @@ +/* { dg-options "-std=gnu23 -Wno-overflow" } */ + +enum e : bool { X }; + +enum e +f () +{ + return __INT_MAX__ + 1; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111059-2.c b/gcc/testsuite/gcc.c-torture/compile/pr111059-2.c new file mode 100644 index 0000000..785e291 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111059-2.c @@ -0,0 +1,5 @@ +void +f () +{ + (_Bool) (0 / 0); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111059-3.c b/gcc/testsuite/gcc.c-torture/compile/pr111059-3.c new file mode 100644 index 0000000..21099bc --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111059-3.c @@ -0,0 +1,5 @@ +_Bool +f () +{ + return 1 << -1; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111059-4.c b/gcc/testsuite/gcc.c-torture/compile/pr111059-4.c new file mode 100644 index 0000000..95c68e5 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111059-4.c @@ -0,0 +1,5 @@ +_Bool +f () +{ + return 0 / 0; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111059-5.c b/gcc/testsuite/gcc.c-torture/compile/pr111059-5.c new file mode 100644 index 0000000..1047355 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111059-5.c @@ -0,0 +1,5 @@ +void +f () +{ + (_Bool) (__INT_MAX__ + 1); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111059-6.c b/gcc/testsuite/gcc.c-torture/compile/pr111059-6.c new file mode 100644 index 0000000..213f79b --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111059-6.c @@ -0,0 +1,5 @@ +_Bool +f () +{ + return __INT_MAX__ + 1; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111059-7.c b/gcc/testsuite/gcc.c-torture/compile/pr111059-7.c new file mode 100644 index 0000000..466f45f --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111059-7.c @@ -0,0 +1,9 @@ +/* { dg-options "-std=gnu23 -Wno-shift-count-negative" } */ + +enum e : bool { X }; + +void +f () +{ + (enum e) (1 << -1); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111059-8.c b/gcc/testsuite/gcc.c-torture/compile/pr111059-8.c new file mode 100644 index 0000000..67f3395 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111059-8.c @@ -0,0 +1,9 @@ +/* { dg-options "-std=gnu23 -Wno-div-by-zero" } */ + +enum e : bool { X }; + +void +f () +{ + (enum e) (0 / 0); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111059-9.c b/gcc/testsuite/gcc.c-torture/compile/pr111059-9.c new file mode 100644 index 0000000..f88096d --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111059-9.c @@ -0,0 +1,9 @@ +/* { dg-options "-std=gnu23 -Wno-shift-count-negative" } */ + +enum e : bool { X }; + +enum e +f () +{ + return 1 << -1; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111911-1.c b/gcc/testsuite/gcc.c-torture/compile/pr111911-1.c new file mode 100644 index 0000000..350f4cc --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111911-1.c @@ -0,0 +1,7 @@ +int +main (void) +{ + if (!(_Bool)(__INT_MAX__ + 1) / !(_Bool)(__INT_MAX__ + 1)) + ; + return 1; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr111911-2.c b/gcc/testsuite/gcc.c-torture/compile/pr111911-2.c new file mode 100644 index 0000000..28b69c4 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr111911-2.c @@ -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; +} |