diff --git a/gcc/c/c-convert.cc b/gcc/c/c-convert.cc
index 3e52926f276..7c1064c6691 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 cf29534c091..1fba9c8dae7 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 66c6abc9f07..12d1a5a5fa1 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 00000000000..5788cb49eba
--- /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 00000000000..fdd9a29ecf5
--- /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 00000000000..81260345a2c
--- /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 00000000000..d11fcf654ce
--- /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 00000000000..785e291e1d8
--- /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 00000000000..21099bc09fb
--- /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 00000000000..95c68e55ce0
--- /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 00000000000..10473550d26
--- /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 00000000000..213f79bfe72
--- /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 00000000000..466f45f1270
--- /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 00000000000..67f339534e3
--- /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 00000000000..f88096d4b47
--- /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 00000000000..350f4ccd1fd
--- /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 00000000000..28b69c46bdb
--- /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;
+}
