* common.opt (Wswitch-unreachable): New option.
* doc/invoke.texi: Document -Wswitch-unreachable.
* gimplify.c (gimplify_switch_expr): Implement the -Wswitch-unreachable warning.
* c-c++-common/Wswitch-unreachable-1.c: New test.
* gcc.dg/Wswitch-unreachable-1.c: New test.
* c-c++-common/goacc/sb-2.c (void foo): Add dg-warning.
* g++.dg/cpp0x/lambda/lambda-switch.C (main): Likewise.
* g++.dg/gomp/block-10.C: Likewise.
* gcc.dg/gomp/block-10.c: Likewise.
* g++.dg/gomp/block-9.C: Likewise.
* gcc.dg/gomp/block-9.c: Likewise.
* g++.dg/gomp/target-1.C: Likewise.
* g++.dg/gomp/target-2.C: Likewise.
* gcc.dg/gomp/target-1.c: Likewise.
* gcc.dg/gomp/target-2.c: Likewise.
* g++.dg/gomp/taskgroup-1.C: Likewise.
* gcc.dg/gomp/taskgroup-1.c: Likewise.
* gcc.dg/gomp/teams-1.c: Likewise.
* g++.dg/gomp/teams-1.C: Likewise.
* g++.dg/overload/error3.C: Likewise.
* g++.dg/tm/jump1.C: Likewise.
* g++.dg/torture/pr40335.C: Likewise.
* gcc.dg/c99-vla-jump-5.c: Likewise.
* gcc.dg/switch-warn-1.c: Likewise.
* gcc.dg/Wjump-misses-init-1.c: Use -Wno-switch-unreachable.
* gcc.dg/nested-func-1.c: Likewise.
* gcc.dg/pr67784-4.c: Likewise.
upstream hash:
1398da0f786e120bb0b407e84f412aa9fc6d80ee
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@236597
138bc75d-0d04-0410-961f-
82ee72b054a4
Change-Id: I8f3be300f4bbb9695c6a4257cf47851241c19fe7
Common Var(warn_suggest_final_methods) Warning
Warn about C++ virtual methods where adding final keyword would improve code quality.
+Wswitch-unreachable
+Common Var(warn_switch_unreachable) Warning Init(1)
+Warn about statements between switch's controlling expression and the first
+case.
+
Wsystem-headers
Common Var(warn_system_headers) Warning
Do not suppress warnings from system headers.
-Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{]} @gol
-Wsuggest-final-types @gol -Wsuggest-final-methods -Wsuggest-override @gol
-Wmissing-format-attribute -Wsubobject-linkage @gol
--Wswitch -Wswitch-default -Wswitch-enum -Wswitch-bool -Wsync-nand @gol
+-Wswitch -Wswitch-bool -Wswitch-default -Wswitch-enum @gol
+-Wswitch-unreachable -Wsync-nand @gol
-Wsystem-headers -Wtautological-compare -Wtrampolines -Wtrigraphs @gol
-Wtype-limits -Wundef @gol
-Wuninitialized -Wunknown-pragmas -Wunsafe-loop-optimizations @gol
@end smallexample
This warning is enabled by default for C and C++ programs.
+@item -Wswitch-unreachable
+@opindex Wswitch-unreachable
+@opindex Wno-switch-unreachable
+Warn whenever a @code{switch} statement contains statements between the
+controlling expression and the first case label, which will never be
+executed. For example:
+@smallexample
+@group
+switch (cond)
+ @{
+ i = 15;
+ @dots{}
+ case 5:
+ @dots{}
+ @}
+@end group
+@end smallexample
+@option{-Wswitch-unreachable} does not warn if the statement between the
+controlling expression and the first case label is just a declaration:
+@smallexample
+@group
+switch (cond)
+ @{
+ int i;
+ @dots{}
+ case 5:
+ i = 5;
+ @dots{}
+ @}
+@end group
+@end smallexample
+This warning is enabled by default for C and C++ programs.
+
@item -Wsync-nand @r{(C and C++ only)}
@opindex Wsync-nand
@opindex Wno-sync-nand
gimplify_ctxp->case_labels.create (8);
gimplify_stmt (&SWITCH_BODY (switch_expr), &switch_body_seq);
+
+ /* Possibly warn about unreachable statements between switch's
+ controlling expression and the first case. */
+ if (warn_switch_unreachable
+ /* This warning doesn't play well with Fortran when optimizations
+ are on. */
+ && !lang_GNU_Fortran ()
+ && switch_body_seq != NULL)
+ {
+ gimple_seq seq = switch_body_seq;
+ if (gimple_code (switch_body_seq) == GIMPLE_BIND)
+ seq = gimple_bind_body (as_a <gbind *> (switch_body_seq));
+ gimple *stmt = gimple_seq_first_stmt (seq);
+ enum gimple_code code = gimple_code (stmt);
+ if (code != GIMPLE_LABEL && code != GIMPLE_TRY)
+ {
+ if (code == GIMPLE_GOTO
+ && TREE_CODE (gimple_goto_dest (stmt)) == LABEL_DECL
+ && DECL_ARTIFICIAL (gimple_goto_dest (stmt)))
+ /* Don't warn for compiler-generated gotos. These occur
+ in Duff's devices, for example. */;
+ else
+ warning_at (gimple_location (stmt), OPT_Wswitch_unreachable,
+ "statement will never be executed");
+ }
+ }
labels = gimplify_ctxp->case_labels;
gimplify_ctxp->case_labels = saved_labels;
--- /dev/null
+/* PR c/49859 */
+/* { dg-do compile } */
+
+extern void foo (int);
+extern int j;
+
+void
+fn0 (int i)
+{
+ switch (i)
+ {
+ int k;
+ case 1:
+ k = 11;
+ foo (k);
+ }
+
+ switch (i)
+ j = 10; /* { dg-warning "statement will never be executed" } */
+
+ switch (i)
+ ;
+
+ switch (i)
+ {
+ j = 12; /* { dg-warning "statement will never be executed" } */
+ default:
+ foo (j);
+ }
+
+ int o;
+ switch (i)
+ {
+ o = 333; /* { dg-warning "statement will never be executed" } */
+ case 4: break;
+ default:
+ foo (o);
+ }
+
+ switch (i)
+ switch (j) /* { dg-warning "statement will never be executed" } */
+ {
+ o = 42; /* { dg-warning "statement will never be executed" } */
+ case 8:;
+ }
+
+ switch (i)
+ {
+ int l = 3; /* { dg-warning "statement will never be executed" } */
+ o = 5;
+ j = 7;
+ ++l;
+ }
+
+ switch (i)
+ {
+ int x;
+ int l = 3; /* { dg-warning "statement will never be executed" } */
+ ++l, ++x;
+ }
+
+ switch (i)
+ if (j != 3) /* { dg-warning "statement will never be executed" } */
+ foo (j);
+
+ switch (i)
+ while (1)
+ foo (0);
+
+ switch (i)
+ while (i > 5) { }
+
+ switch (i)
+ goto X; /* { dg-warning "statement will never be executed" } */
+X:
+
+ switch (i)
+ do
+ foo (1);
+ while (1);
+
+ switch (i)
+ for (;;)
+ foo (-1);
+
+ switch (i)
+ default:
+ j = 6;
+
+ switch (i)
+ {
+ typedef int T;
+ case 3:
+ {
+ T x = 5;
+ foo (x);
+ }
+ }
+
+ switch (i)
+ {
+ static int g;
+ default:
+ foo (g);
+ }
+
+ switch (i)
+ {
+L:
+ j = 16;
+ default:
+ if (j < 5)
+ goto L;
+ break;
+ }
+}
{
switch (i) // { dg-error "invalid entry to OpenACC structured block" }
{
- #pragma acc parallel
+ #pragma acc parallel // { dg-warning "statement will never be executed" }
{ case 0:; }
}
switch (i) // { dg-error "invalid entry to OpenACC structured block" }
{
- #pragma acc kernels
+ #pragma acc kernels // { dg-warning "statement will never be executed" }
{ case 0:; }
}
switch (i) // { dg-error "invalid entry to OpenACC structured block" }
{
- #pragma acc data
+ #pragma acc data // { dg-warning "statement will never be executed" }
{ case 0:; }
}
}
{
case 3: // { dg-error "case" }
break; // { dg-error "break" }
- };
+ }; // { dg-warning "statement will never be executed" }
}
}
}
int j;
switch (i)
{
- #pragma omp parallel
+ #pragma omp parallel // { dg-warning "statement will never be executed" }
{ case 0:; } // { dg-error "jump|enters" }
}
switch (i)
{
- #pragma omp for
+ #pragma omp for // { dg-warning "statement will never be executed" }
for (j = 0; j < 10; ++ j)
{ case 1:; } // { dg-error "jump|enters" }
}
switch (i)
{
- #pragma omp critical
+ #pragma omp critical // { dg-warning "statement will never be executed" }
{ case 2:; } // { dg-error "jump|enters" }
}
switch (i)
{
- #pragma omp master
+ #pragma omp master // { dg-warning "statement will never be executed" }
{ case 3:; } // { dg-error "jump|enters" }
}
switch (i)
{
- #pragma omp sections
+ #pragma omp sections // { dg-warning "statement will never be executed" }
{ case 4:; // { dg-error "jump|enters" }
#pragma omp section
{ case 5:; } // { dg-error "jump|enters" }
}
switch (i)
{
- #pragma omp ordered
+ #pragma omp ordered // { dg-warning "statement will never be executed" }
{ default:; } // { dg-error "jump|enters" }
}
}
int j;
switch (i)
{
- #pragma omp parallel
+ #pragma omp parallel // { dg-warning "statement will never be executed" }
{ case 0:; } // { dg-error "jump|enters" }
#pragma omp for
for (j = 0; j < 10; ++ j)
switch (x)
{
- #pragma omp target
+ #pragma omp target // { dg-warning "statement will never be executed" }
{ case 0:; } // { dg-error "jump" }
// { dg-message "enters" "" { target *-*-* } 28 }
}
switch (x)
{
- #pragma omp target data map(tofrom: y)
+ #pragma omp target data map(tofrom: y) // { dg-warning "statement will never be executed" }
{ case 0:; } // { dg-error "jump" }
// { dg-message "enters" "" { target *-*-* } 28 }
}
switch (x)
{
- #pragma omp taskgroup
+ #pragma omp taskgroup // { dg-warning "statement will never be executed" }
{ case 0:; } // { dg-error "jump" }
// { dg-message "enters" "" { target *-*-* } 28 }
}
{
#pragma omp target teams
{ case 0:; } // { dg-error "jump" }
+ // { dg-warning "statement will never be executed" "" { target *-*-* } 28 }
// { dg-message "enters" "" { target *-*-* } 28 }
}
}
#pragma omp teams
{
bad2: ; // { dg-error "jump to label" }
- // { dg-message "enters OpenMP" "" { target *-*-* } 45 }
+ // { dg-message "enters OpenMP" "" { target *-*-* } 46 }
}
#pragma omp target
switch (x)
{
- #pragma omp target
+ #pragma omp target // { dg-warning "statement will never be executed" }
#pragma omp teams
{ case 0:; } // { dg-error "jump" }
- // { dg-message "enters" "" { target *-*-* } 62 }
+ // { dg-message "enters" "" { target *-*-* } 63 }
}
}
// { dg-error "invalid branch to/from OpenMP structured block" "" { target *-*-* } 8 }
// { dg-error "invalid entry to OpenMP structured block" "" { target *-*-* } 10 }
-// { dg-error "invalid branch to/from OpenMP structured block" "" { target *-*-* } 39 }
-// { dg-error "invalid entry to OpenMP structured block" "" { target *-*-* } 41 }
+// { dg-error "invalid branch to/from OpenMP structured block" "" { target *-*-* } 40 }
+// { dg-error "invalid entry to OpenMP structured block" "" { target *-*-* } 42 }
void MainWindow::update_status(Result result) {
switch (result) {
status_frame.modify_bg(Gtk::STATE_NORMAL,Gdk::Color::Color("green")); // { dg-error "" }
+ // { dg-warning "statement will never be executed" "" { target *-*-* } 37 }
status_frame.modify_bg(Gtk::STATE_NORMAL,Gdk::Color::Color("red")); // { dg-error "" }
status_label.set_text("Out of memory");
}
switch (i)
{
- synchronized {
+ synchronized { // { dg-warning "statement will never be executed" }
++i;
case 42: // { dg-error "" }
++i;
switch ((signed char) i)
{
case 255: /* { dg-bogus "exceeds maximum value" "" { xfail *-*-* } } */
- abort ();
+ abort (); /* { dg-warning "statement will never be executed" } */
default:
break;
}
/* { dg-do compile } */
-/* { dg-options "-Wjump-misses-init" } */
+/* { dg-options "-Wjump-misses-init -Wno-switch-unreachable" } */
int
f1 (int a)
{
--- /dev/null
+/* PR c/49859 */
+/* { dg-do compile } */
+/* { dg-options "-Wswitch-unreachable" } */
+
+extern void foo (int);
+extern int j;
+
+void
+fn0 (int i)
+{
+ switch (i)
+ {
+ int t = 10; /* { dg-warning "statement will never be executed" } */
+ default:
+ foo (t);
+ }
+
+ switch (i)
+ { /* { dg-warning "statement will never be executed" } */
+ int A[i];
+ default: /* { dg-error "switch jumps into scope" } */
+ break;
+ }
+
+ switch (i)
+ default:
+ j = sizeof (struct { int i; });
+
+ switch (i)
+ {
+ int A[3];
+ default:
+ break;
+ }
+}
void
f (int a, int b)
{
- switch (a) {
+ switch (a) { /* { dg-warning "statement will never be executed" } */
int v[b];
case 2: /* { dg-error "switch jumps into scope of identifier with variably modified type" } */
default: /* { dg-error "switch jumps into scope of identifier with variably modified type" } */
int j;
switch (i) // { dg-error "invalid entry to OpenMP structured block" }
{
- #pragma omp parallel
+ #pragma omp parallel // { dg-warning "statement will never be executed" }
{ case 0:; }
}
switch (i) // { dg-error "invalid entry to OpenMP structured block" }
{
- #pragma omp for
+ #pragma omp for // { dg-warning "statement will never be executed" }
for (j = 0; j < 10; ++ j)
{ case 1:; }
}
switch (i) // { dg-error "invalid entry to OpenMP structured block" }
{
- #pragma omp critical
+ #pragma omp critical // { dg-warning "statement will never be executed" }
{ case 2:; }
}
switch (i) // { dg-error "invalid entry to OpenMP structured block" }
{
- #pragma omp master
+ #pragma omp master // { dg-warning "statement will never be executed" }
{ case 3:; }
}
switch (i) // { dg-error "invalid entry to OpenMP structured block" }
{
- #pragma omp sections
+ #pragma omp sections // { dg-warning "statement will never be executed" }
{ case 4:;
#pragma omp section
{ case 5:; }
}
switch (i) // { dg-error "invalid entry to OpenMP structured block" }
{
- #pragma omp ordered
+ #pragma omp ordered // { dg-warning "statement will never be executed" }
{ default:; }
}
}
int j;
switch (i) // { dg-error "invalid entry to OpenMP structured block" }
{
- #pragma omp parallel
+ #pragma omp parallel // { dg-warning "statement will never be executed" }
{ case 0:; }
#pragma omp for
for (j = 0; j < 10; ++ j)
switch (x) // { dg-error "invalid entry to OpenMP structured block" }
{
- #pragma omp target
+ #pragma omp target // { dg-warning "statement will never be executed" }
{ case 0:; }
}
}
switch (x) // { dg-error "invalid entry to OpenMP structured block" }
{
- #pragma omp target data map(tofrom: y)
+ #pragma omp target data map(tofrom: y) // { dg-warning "statement will never be executed" }
{ case 0:; }
}
}
switch (x) // { dg-error "invalid entry to OpenMP structured block" }
{
- #pragma omp taskgroup
+ #pragma omp taskgroup // { dg-warning "statement will never be executed" }
{ case 0:; }
}
}
switch (x) // { dg-error "invalid entry to OpenMP structured block" }
{
#pragma omp target teams
- { case 0:; }
+ { case 0:; } // { dg-warning "statement will never be executed" }
}
}
switch (x) // { dg-error "invalid entry to OpenMP structured block" }
{
- #pragma omp target
+ #pragma omp target // { dg-warning "statement will never be executed" }
#pragma omp teams
{ case 0:; }
}
/* Test for proper errors for break and continue in nested functions. */
/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
/* { dg-do compile } */
-/* { dg-options "" } */
+/* { dg-options "-Wno-switch-unreachable" } */
void
foo (int a)
/* PR c/67784 */
/* { dg-do compile } */
-/* { dg-options "" } */
+/* { dg-options "-Wno-switch-unreachable" } */
typedef int T;
{
switch (i)
{
- case -1: /* { dg-warning "case label value is less than minimum value for type" } */
+ case -1: /* { dg-warning "case label value is less than minimum value for type|statement will never be executed" } */
return 1;
case 256: /* { dg-warning "case label value exceeds maximum value for type" } */
return 2;