@@ -529,6 +529,10 @@ Wswitch-enum
C ObjC C++ ObjC++ Var(warn_switch_enum) Warning
Warn about all enumerated switches missing a specific case
+Wswitch-bool
+C ObjC Warning Init(1)
+Warn about switches with boolean controlling expression
+
Wmissing-format-attribute
C ObjC C++ ObjC++ Alias(Wsuggest-attribute=format)
;
@@ -9344,6 +9344,15 @@ c_start_case (location_t switch_loc,
else
{
tree type = TYPE_MAIN_VARIANT (orig_type);
+ tree e = exp;
+
+ while (TREE_CODE (e) == COMPOUND_EXPR)
+ e = TREE_OPERAND (e, 1);
+
+ if (TREE_CODE (type) == BOOLEAN_TYPE
+ || truth_value_p (TREE_CODE (e)))
+ warning_at (switch_cond_loc, OPT_Wswitch_bool,
+ "switch condition has boolean value");
if (!in_system_header_at (input_location)
&& (type == long_integer_type_node
@@ -268,7 +268,7 @@ Objective-C and Objective-C++ Dialects}.
-Wstrict-aliasing=n @gol -Wstrict-overflow -Wstrict-overflow=@var{n} @gol
-Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{]} @gol
-Wmissing-format-attribute @gol
--Wswitch -Wswitch-default -Wswitch-enum -Wsync-nand @gol
+-Wswitch -Wswitch-default -Wswitch-enum -Wswitch-bool -Wsync-nand @gol
-Wsystem-headers -Wtrampolines -Wtrigraphs -Wtype-limits -Wundef @gol
-Wuninitialized -Wunknown-pragmas -Wno-pragmas @gol
-Wunsuffixed-float-constants -Wunused -Wunused-function @gol
@@ -3822,6 +3822,12 @@ between @option{-Wswitch} and this option is that this option gives a
warning about an omitted enumeration code even if there is a
@code{default} label.
+@item -Wswitch-bool
+@opindex Wswitch-bool
+@opindex Wno-switch-bool
+Warn whenever a @code{switch} statement has an index of boolean type.
+This warning is enabled by default for C programs.
+
@item -Wsync-nand @r{(C and C++ only)}
@opindex Wsync-nand
@opindex Wno-sync-nand
@@ -0,0 +1,112 @@
+/* PR c/60439 */
+/* { dg-do compile } */
+
+typedef _Bool bool;
+extern _Bool foo (void);
+
+void
+f1 (const _Bool b)
+{
+ switch (b) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+}
+
+void
+f2 (int a, int b)
+{
+ switch (a && b) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+ switch ((bool) (a && b)) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+ switch ((a && b) || a) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+}
+
+void
+f3 (int a)
+{
+ switch (!!a) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+ switch (!a) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+}
+
+void
+f4 (void)
+{
+ switch (foo ()) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+}
+
+void
+f5 (int a)
+{
+ switch (a == 3) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+ switch (a != 3) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+ switch (a > 3) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+ switch (a < 3) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+ switch (a <= 3) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+ switch (a >= 3) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+ switch (foo (), foo (), a >= 42) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+ switch (a == 3, a & 4, a ^ 5, a)
+ case 1:
+ break;
+}
+
+void
+f6 (bool b)
+{
+ switch (b) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+ switch (!b) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+ switch (b++) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+}
+
+void
+f7 (void)
+{
+ bool b;
+ switch (b = 1) /* { dg-warning "switch condition has boolean value" } */
+ case 1:
+ break;
+}
+
+void
+f8 (int i)
+{
+ switch (i)
+ case 0:
+ break;
+ switch ((unsigned int) i)
+ case 0:
+ break;
+ switch ((bool) i) /* { dg-warning "switch condition has boolean value" } */
+ case 0:
+ break;
+}