From 70f6d5e19bb7c0eed9f3fc028632405b5c166676 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 12 Oct 2016 01:19:06 +0200 Subject: [PATCH] gcc/ * common.opt (Wimplicit-fallthrough) Turn into alias to -Wimplicit-fallthrough=3. Remove EnabledBy. (Wimplicit-fallthrough=): New option. * gimplify.c (warn_implicit_fallthrough_r): Use OPT_Wimplicit_fallthrough_ instead of OPT_Wimplicit_fallthrough. * doc/invoke.texi (-Wimplicit-fallthrough): Document as alias to -Wimplicit-fallthrough=3. (-Wimplicit-fallthrough=): Document. gcc/c-family/ * c.opt (Wextra): Add as C/C++/ObjC/ObjC++ option. (Wimplicit-fallthrough=): Enable for these languages by -Wextra. * c-opts.c (sanitize_cpp_opts): Initialize cpp_opts->cpp_warn_implicit_fallthrough. gcc/testsuite/ * c-c++-common/Wimplicit-fallthrough-25.c: New test. * c-c++-common/Wimplicit-fallthrough-26.c: New test. * c-c++-common/Wimplicit-fallthrough-27.c: New test. * c-c++-common/Wimplicit-fallthrough-28.c: New test. * c-c++-common/Wimplicit-fallthrough-29.c: New test. * c-c++-common/Wimplicit-fallthrough-30.c: New test. * c-c++-common/Wimplicit-fallthrough-31.c: New test. * c-c++-common/Wimplicit-fallthrough-32.c: New test. * c-c++-common/Wimplicit-fallthrough-33.c: New test. libcpp/ * include/cpplib.h (struct cpp_options): Add cpp_warn_implicit_fallthrough. * init.c (cpp_create_reader): Initialize it to 0. * lex.c (fallthrough_comment_p): Handle different cpp_warn_implicit_fallthrough levels. Whitespace fixes. From-SVN: r241013 --- gcc/ChangeLog | 11 ++ gcc/c-family/ChangeLog | 7 ++ gcc/c-family/c-opts.c | 5 + gcc/c-family/c.opt | 8 ++ gcc/common.opt | 5 +- gcc/doc/invoke.texi | 64 +++++++++-- gcc/gimplify.c | 4 +- gcc/testsuite/ChangeLog | 12 ++ .../c-c++-common/Wimplicit-fallthrough-25.c | 33 ++++++ .../c-c++-common/Wimplicit-fallthrough-26.c | 33 ++++++ .../c-c++-common/Wimplicit-fallthrough-27.c | 33 ++++++ .../c-c++-common/Wimplicit-fallthrough-28.c | 33 ++++++ .../c-c++-common/Wimplicit-fallthrough-29.c | 33 ++++++ .../c-c++-common/Wimplicit-fallthrough-30.c | 33 ++++++ .../c-c++-common/Wimplicit-fallthrough-31.c | 33 ++++++ .../c-c++-common/Wimplicit-fallthrough-32.c | 33 ++++++ .../c-c++-common/Wimplicit-fallthrough-33.c | 33 ++++++ libcpp/ChangeLog | 8 ++ libcpp/include/cpplib.h | 3 + libcpp/init.c | 1 + libcpp/lex.c | 103 ++++++++++++++++-- 21 files changed, 502 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/Wimplicit-fallthrough-25.c create mode 100644 gcc/testsuite/c-c++-common/Wimplicit-fallthrough-26.c create mode 100644 gcc/testsuite/c-c++-common/Wimplicit-fallthrough-27.c create mode 100644 gcc/testsuite/c-c++-common/Wimplicit-fallthrough-28.c create mode 100644 gcc/testsuite/c-c++-common/Wimplicit-fallthrough-29.c create mode 100644 gcc/testsuite/c-c++-common/Wimplicit-fallthrough-30.c create mode 100644 gcc/testsuite/c-c++-common/Wimplicit-fallthrough-31.c create mode 100644 gcc/testsuite/c-c++-common/Wimplicit-fallthrough-32.c create mode 100644 gcc/testsuite/c-c++-common/Wimplicit-fallthrough-33.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 110c2f3adf5..6facb484ff8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2016-10-12 Jakub Jelinek + + * common.opt (Wimplicit-fallthrough) Turn into alias to + -Wimplicit-fallthrough=3. Remove EnabledBy. + (Wimplicit-fallthrough=): New option. + * gimplify.c (warn_implicit_fallthrough_r): Use + OPT_Wimplicit_fallthrough_ instead of OPT_Wimplicit_fallthrough. + * doc/invoke.texi (-Wimplicit-fallthrough): Document as alias + to -Wimplicit-fallthrough=3. + (-Wimplicit-fallthrough=): Document. + 2016-10-11 Eric Botcazou * config/sparc/sparc.c (emit_scc_insn): Remove direct support for EQ diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 78a494722cb..64619fc6082 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2016-10-12 Jakub Jelinek + + * c.opt (Wextra): Add as C/C++/ObjC/ObjC++ option. + (Wimplicit-fallthrough=): Enable for these languages by -Wextra. + * c-opts.c (sanitize_cpp_opts): Initialize + cpp_opts->cpp_warn_implicit_fallthrough. + 2016-10-11 Marek Polacek * c-common.c (warning_candidate_p): Change the return type to bool diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index c5a699d67cf..da62b55fea3 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -1279,6 +1279,11 @@ sanitize_cpp_opts (void) if (flag_working_directory == -1) flag_working_directory = (debug_info_level != DINFO_LEVEL_NONE); + if (warn_implicit_fallthrough < 5) + cpp_opts->cpp_warn_implicit_fallthrough = warn_implicit_fallthrough; + else + cpp_opts->cpp_warn_implicit_fallthrough = 0; + if (cpp_opts->directives_only) { if (cpp_warn_unused_macros) diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index e14678103cd..82c992c1f5a 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -462,6 +462,10 @@ Werror-implicit-function-declaration C ObjC RejectNegative Warning Alias(Werror=, implicit-function-declaration) This switch is deprecated; use -Werror=implicit-function-declaration instead. +Wextra +C ObjC C++ ObjC++ Warning +; in common.opt + Wfloat-conversion C ObjC C++ ObjC++ Var(warn_float_conversion) Warning LangEnabledBy(C ObjC C++ ObjC++,Wconversion) Warn for implicit type conversions that cause loss of floating point precision. @@ -536,6 +540,10 @@ Wimplicit C ObjC Var(warn_implicit) Warning LangEnabledBy(C ObjC,Wall) Warn about implicit declarations. +Wimplicit-fallthrough= +LangEnabledBy(C ObjC C++ ObjC++,Wextra,3,0) +; in common.opt + Wdouble-promotion C ObjC C++ ObjC++ Var(warn_double_promotion) Warning Warn about implicit conversions from \"float\" to \"double\". diff --git a/gcc/common.opt b/gcc/common.opt index 3425c19e514..15679c5d392 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -602,7 +602,10 @@ Common Var(warn_hsa) Init(1) Warning Warn when a function cannot be expanded to HSAIL. Wimplicit-fallthrough -Common Var(warn_implicit_fallthrough) Warning EnabledBy(Wextra) +Common Alias(Wimplicit-fallthrough=,3,0) Warning + +Wimplicit-fallthrough= +Common Var(warn_implicit_fallthrough) RejectNegative Joined UInteger Warning Warn when a switch case falls through. Winline diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index fa693bae4f7..c11f1d572e9 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -273,8 +273,8 @@ Objective-C and Objective-C++ Dialects}. -Wformat-security -Wformat-signedness -Wformat-y2k -Wframe-address @gol -Wframe-larger-than=@var{len} -Wno-free-nonheap-object -Wjump-misses-init @gol -Wignored-qualifiers -Wignored-attributes -Wincompatible-pointer-types @gol --Wimplicit -Wimplicit-fallthrough -Wimplicit-function-declaration @gol --Wimplicit-int @gol +-Wimplicit -Wimplicit-fallthrough -Wimplicit-fallthrough=@var{n} @gol +-Wimplicit-function-declaration -Wimplicit-int @gol -Winit-self -Winline -Wno-int-conversion -Wint-in-bool-context @gol -Wno-int-to-pointer-cast -Winvalid-memory-model -Wno-invalid-offsetof @gol -Winvalid-pch -Wlarger-than=@var{len} @gol @@ -3734,7 +3734,7 @@ name is still supported, but the newer name is more descriptive.) @gccoptlist{-Wclobbered @gol -Wempty-body @gol -Wignored-qualifiers @gol --Wimplicit-fallthrough @gol +-Wimplicit-fallthrough=3 @gol -Wmissing-field-initializers @gol -Wmissing-parameter-type @r{(C only)} @gol -Wold-style-declaration @r{(C only)} @gol @@ -4106,6 +4106,12 @@ This warning is enabled by @option{-Wall}. @item -Wimplicit-fallthrough @opindex Wimplicit-fallthrough @opindex Wno-implicit-fallthrough +@option{-Wimplicit-fallthrough} is the same as @option{-Wimplicit-fallthrough=3} +and @option{-Wno-implicit-fallthrough} is the same as +@option{-Wimplicit-fallthrough=0}. + +@item -Wimplicit-fallthrough=@var{n} +@opindex Wimplicit-fallthrough= Warn when a switch case falls through. For example: @smallexample @@ -4126,7 +4132,7 @@ switch (cond) This warning does not warn when the last statement of a case cannot fall through, e.g. when there is a return statement or a call to function -declared with the noreturn attribute. @option{-Wimplicit-fallthrough} +declared with the noreturn attribute. @option{-Wimplicit-fallthrough=} also takes into account control flow statements, such as ifs, and only warns when appropriate. E.g.@: @@ -4169,9 +4175,23 @@ switch (cond) C++17 provides a standard way to suppress the @option{-Wimplicit-fallthrough} warning using @code{[[fallthrough]];} instead of the GNU attribute. In C++11 or C++14 users can use @code{[[gnu::fallthrough]];}, which is a GNU extension. -Instead of the these attributes, it is also possible to add a "falls through" +Instead of the these attributes, it is also possible to add a fallthrough comment to silence the warning. The whole body of the C or C++ style comment -should match one of the following regular expressions: +should match the given regular expressions listed below. The option argument +@var{n} specifies what kind of comments are accepted: + +@itemize @bullet + +@item @option{-Wimplicit-fallthrough=0} disables the warning altogether. + +@item @option{-Wimplicit-fallthrough=1} matches @code{.*} regular +expression, any comment is used as fallthrough comment. + +@item @option{-Wimplicit-fallthrough=2} case insensitively matches +@code{.*falls?[ \t-]*thr(ough|u).*} regular expression. + +@item @option{-Wimplicit-fallthrough=3} case sensitively matches one of the +following regular expressions: @itemize @bullet @@ -4179,17 +4199,37 @@ should match one of the following regular expressions: @item @code{@@fallthrough@@} -@item @code{lint -fallthrough ?} +@item @code{lint -fallthrough[ \t]*} + +@item @code{[ \t.!]*(ELSE,? |INTENTIONAL(LY)? )?@*FALL(S | |-)?THR(OUGH|U)[ \t.!]*(-[^\n\r]*)?} + +@item @code{[ \t.!]*(Else,? |Intentional(ly)? )?@*Fall((s | |-)[Tt]|t)hr(ough|u)[ \t.!]*(-[^\n\r]*)?} -@item @code{[ \t.!]*(ELSE,? |INTENTIONAL(LY)? )?FALL(S | |-)?THR(OUGH|U)[ \t.!]*(-[^\n\r]*)?} +@item @code{[ \t.!]*([Ee]lse,? |[Ii]ntentional(ly)? )?@*fall(s | |-)?thr(ough|u)[ \t.!]*(-[^\n\r]*)?} + +@end itemize -@item @code{[ \t.!]*(Else,? |Intentional(ly)? )?Fall((s | |-)[Tt]|t)hr(ough|u)[ \t.!]*(-[^\n\r]*)?} +@item @option{-Wimplicit-fallthrough=4} case sensitively matches one of the +following regular expressions: + +@itemize @bullet + +@item @code{-fallthrough} + +@item @code{@@fallthrough@@} + +@item @code{lint -fallthrough[ \t]*} + +@item @code{[ \t]*FALLTHR(OUGH|U)[ \t]*} + +@end itemize -@item @code{[ \t.!]*([Ee]lse,? |[Ii]ntentional(ly)? )?fall(s | |-)?thr(ough|u)[ \t.!]*(-[^\n\r]*)?} +@item @option{-Wimplicit-fallthrough=5} doesn't recognize any comments as +fallthrough comments, only attributes disable the warning. @end itemize -and the comment needs to be followed after optional whitespace and other comments +The comment needs to be followed after optional whitespace and other comments by @code{case} or @code{default} keywords or by a user label that preceeds some @code{case} or @code{default} label. @@ -4206,7 +4246,7 @@ switch (cond) @end group @end smallexample -This warning is enabled by @option{-Wextra}. +The @option{-Wimplicit-fallthrough=3} warning is enabled by @option{-Wextra}. @item -Wignored-qualifiers @r{(C and C++ only)} @opindex Wignored-qualifiers diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 0b1a0beccf5..2f074f9532c 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1918,7 +1918,7 @@ warn_implicit_fallthrough_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, else if (gimple_code (prev) == GIMPLE_LABEL && (label = gimple_label_label (as_a (prev))) && (l = find_label_entry (&labels, label))) - warned_p = warning_at (l->loc, OPT_Wimplicit_fallthrough, + warned_p = warning_at (l->loc, OPT_Wimplicit_fallthrough_, "this statement may fall through"); else if (!gimple_call_internal_p (prev, IFN_FALLTHROUGH) /* Try to be clever and don't warn when the statement @@ -1926,7 +1926,7 @@ warn_implicit_fallthrough_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, && gimple_stmt_may_fallthru (prev) && gimple_has_location (prev)) warned_p = warning_at (gimple_location (prev), - OPT_Wimplicit_fallthrough, + OPT_Wimplicit_fallthrough_, "this statement may fall through"); if (warned_p) inform (gimple_location (next), "here"); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c0f20cd1166..4423684948a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2016-10-12 Jakub Jelinek + + * c-c++-common/Wimplicit-fallthrough-25.c: New test. + * c-c++-common/Wimplicit-fallthrough-26.c: New test. + * c-c++-common/Wimplicit-fallthrough-27.c: New test. + * c-c++-common/Wimplicit-fallthrough-28.c: New test. + * c-c++-common/Wimplicit-fallthrough-29.c: New test. + * c-c++-common/Wimplicit-fallthrough-30.c: New test. + * c-c++-common/Wimplicit-fallthrough-31.c: New test. + * c-c++-common/Wimplicit-fallthrough-32.c: New test. + * c-c++-common/Wimplicit-fallthrough-33.c: New test. + 2016-10-11 Eric Botcazou * gcc.target/sparc/setcc-4.c: Adjust. diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-25.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-25.c new file mode 100644 index 00000000000..f62287885ee --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-25.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-Wextra" } */ + +void bar (int); + +void +foo (int i) +{ + switch (i) + { + case 1: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (1); + case 2: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (2); + /* Some comment. */ + case 3: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (3); + /* Here we really do want to fALl tHRoUgh and we mean it! */ + case 4: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (4); + /* Intentionally fall through. */ + case 5: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (5); + /* FALLTHROUGH */ + case 6: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (6); + __attribute__((fallthrough)); + case 7: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (7); + default: + break; + } +} diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-26.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-26.c new file mode 100644 index 00000000000..3c62de1ff6c --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-26.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-Wimplicit-fallthrough" } */ + +void bar (int); + +void +foo (int i) +{ + switch (i) + { + case 1: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (1); + case 2: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (2); + /* Some comment. */ + case 3: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (3); + /* Here we really do want to fALl tHRoUgh and we mean it! */ + case 4: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (4); + /* Intentionally fall through. */ + case 5: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (5); + /* FALLTHROUGH */ + case 6: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (6); + __attribute__((fallthrough)); + case 7: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (7); + default: + break; + } +} diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-27.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-27.c new file mode 100644 index 00000000000..7ea0815f50b --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-27.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-Wimplicit-fallthrough=1" } */ + +void bar (int); + +void +foo (int i) +{ + switch (i) + { + case 1: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (1); + case 2: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (2); + /* Some comment. */ + case 3: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (3); + /* Here we really do want to fALl tHRoUgh and we mean it! */ + case 4: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (4); + /* Intentionally fall through. */ + case 5: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (5); + /* FALLTHROUGH */ + case 6: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (6); + __attribute__((fallthrough)); + case 7: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (7); + default: + break; + } +} diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-28.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-28.c new file mode 100644 index 00000000000..7c685f64d5f --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-28.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-Wimplicit-fallthrough=2" } */ + +void bar (int); + +void +foo (int i) +{ + switch (i) + { + case 1: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (1); + case 2: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (2); + /* Some comment. */ + case 3: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (3); + /* Here we really do want to fALl tHRoUgh and we mean it! */ + case 4: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (4); + /* Intentionally fall through. */ + case 5: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (5); + /* FALLTHROUGH */ + case 6: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (6); + __attribute__((fallthrough)); + case 7: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (7); + default: + break; + } +} diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-29.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-29.c new file mode 100644 index 00000000000..9863e9d140a --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-29.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-Wimplicit-fallthrough=3" } */ + +void bar (int); + +void +foo (int i) +{ + switch (i) + { + case 1: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (1); + case 2: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (2); + /* Some comment. */ + case 3: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (3); + /* Here we really do want to fALl tHRoUgh and we mean it! */ + case 4: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (4); + /* Intentionally fall through. */ + case 5: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (5); + /* FALLTHROUGH */ + case 6: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (6); + __attribute__((fallthrough)); + case 7: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (7); + default: + break; + } +} diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-30.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-30.c new file mode 100644 index 00000000000..54d22dff6b4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-30.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-Wimplicit-fallthrough=4" } */ + +void bar (int); + +void +foo (int i) +{ + switch (i) + { + case 1: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (1); + case 2: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (2); + /* Some comment. */ + case 3: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (3); + /* Here we really do want to fALl tHRoUgh and we mean it! */ + case 4: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (4); + /* Intentionally fall through. */ + case 5: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (5); + /* FALLTHROUGH */ + case 6: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (6); + __attribute__((fallthrough)); + case 7: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (7); + default: + break; + } +} diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-31.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-31.c new file mode 100644 index 00000000000..de20d92e20a --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-31.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-Wimplicit-fallthrough=5" } */ + +void bar (int); + +void +foo (int i) +{ + switch (i) + { + case 1: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (1); + case 2: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (2); + /* Some comment. */ + case 3: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (3); + /* Here we really do want to fALl tHRoUgh and we mean it! */ + case 4: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (4); + /* Intentionally fall through. */ + case 5: /* { dg-warning "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (5); + /* FALLTHROUGH */ + case 6: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (6); + __attribute__((fallthrough)); + case 7: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (7); + default: + break; + } +} diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-32.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-32.c new file mode 100644 index 00000000000..cd0b8ce9363 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-32.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-Wimplicit-fallthrough=0" } */ + +void bar (int); + +void +foo (int i) +{ + switch (i) + { + case 1: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (1); + case 2: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (2); + /* Some comment. */ + case 3: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (3); + /* Here we really do want to fALl tHRoUgh and we mean it! */ + case 4: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (4); + /* Intentionally fall through. */ + case 5: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (5); + /* FALLTHROUGH */ + case 6: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (6); + __attribute__((fallthrough)); + case 7: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (7); + default: + break; + } +} diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-33.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-33.c new file mode 100644 index 00000000000..336cc447e21 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-33.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-Wno-implicit-fallthrough" } */ + +void bar (int); + +void +foo (int i) +{ + switch (i) + { + case 1: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (1); + case 2: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (2); + /* Some comment. */ + case 3: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (3); + /* Here we really do want to fALl tHRoUgh and we mean it! */ + case 4: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (4); + /* Intentionally fall through. */ + case 5: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (5); + /* FALLTHROUGH */ + case 6: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (6); + __attribute__((fallthrough)); + case 7: /* { dg-bogus "this statement may \[fla\]* through" "" { target *-*-* } .+1 } */ + bar (7); + default: + break; + } +} diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 1f4db497dd1..40bd5cdc02e 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,11 @@ +2016-10-12 Jakub Jelinek + + * include/cpplib.h (struct cpp_options): Add + cpp_warn_implicit_fallthrough. + * init.c (cpp_create_reader): Initialize it to 0. + * lex.c (fallthrough_comment_p): Handle different + cpp_warn_implicit_fallthrough levels. Whitespace fixes. + 2016-10-08 Jakub Jelinek * lex.c (fallthrough_comment_p): Accept Else, fallthrough. diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 6352ac586d4..0781c095156 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -395,6 +395,9 @@ struct cpp_options explicitly undefined. */ unsigned char warn_builtin_macro_redefined; + /* Different -Wimplicit-fallthrough= levels. */ + unsigned char cpp_warn_implicit_fallthrough; + /* Nonzero means we should look for header.gcc files that remap file names. */ unsigned char remap; diff --git a/libcpp/init.c b/libcpp/init.c index 2df8cfb73c3..5e352806100 100644 --- a/libcpp/init.c +++ b/libcpp/init.c @@ -189,6 +189,7 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table, CPP_OPTION (pfile, warn_dollars) = 1; CPP_OPTION (pfile, warn_variadic_macros) = 1; CPP_OPTION (pfile, warn_builtin_macro_redefined) = 1; + CPP_OPTION (pfile, cpp_warn_implicit_fallthrough) = 0; /* By default, track locations of tokens resulting from macro expansion. The '2' means, track the locations with the highest accuracy. Read the comments for struct diff --git a/libcpp/lex.c b/libcpp/lex.c index 4d8e5e70326..6f65fa152fc 100644 --- a/libcpp/lex.c +++ b/libcpp/lex.c @@ -2040,6 +2040,64 @@ static bool fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start) { const unsigned char *from = comment_start + 1; + + switch (CPP_OPTION (pfile, cpp_warn_implicit_fallthrough)) + { + /* For both -Wimplicit-fallthrough=0 and -Wimplicit-fallthrough=5 we + don't recognize any comments. The latter only checks attributes, + the former doesn't warn. */ + case 0: + default: + return false; + /* -Wimplicit-fallthrough=1 considers any comment, no matter what + content it has. */ + case 1: + return true; + case 2: + /* -Wimplicit-fallthrough=2 looks for (case insensitive) + .*falls?[ \t-]*thr(u|ough).* regex. */ + for (; (size_t) (pfile->buffer->cur - from) >= sizeof "fallthru" - 1; + from++) + { + /* Is there anything like strpbrk with upper boundary, or + memchr looking for 2 characters rather than just one? */ + if (from[0] != 'f' && from[0] != 'F') + continue; + if (from[1] != 'a' && from[1] != 'A') + continue; + if (from[2] != 'l' && from[2] != 'L') + continue; + if (from[3] != 'l' && from[3] != 'L') + continue; + from += sizeof "fall" - 1; + if (from[0] == 's' || from[0] == 'S') + from++; + while (*from == ' ' || *from == '\t' || *from == '-') + from++; + if (from[0] != 't' && from[0] != 'T') + continue; + if (from[1] != 'h' && from[1] != 'H') + continue; + if (from[2] != 'r' && from[2] != 'R') + continue; + if (from[3] == 'u' || from[3] == 'U') + return true; + if (from[3] != 'o' && from[3] != 'O') + continue; + if (from[4] != 'u' && from[4] != 'U') + continue; + if (from[5] != 'g' && from[5] != 'G') + continue; + if (from[6] != 'h' && from[6] != 'H') + continue; + return true; + } + return false; + case 3: + case 4: + break; + } + /* Whole comment contents: -fallthrough @fallthrough@ @@ -2060,7 +2118,7 @@ fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start) from += 1 + len; } /* Whole comment contents (regex): - lint -fallthrough ? + lint -fallthrough[ \t]* */ else if (*from == 'l') { @@ -2068,10 +2126,33 @@ fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start) if ((size_t) (pfile->buffer->cur - from - 1) < len) return false; if (memcmp (from + 1, "int -fallthrough", len)) - return false; + return false; from += 1 + len; - if (*from == ' ') - from++; + while (*from == ' ' || *from == '\t') + from++; + } + /* Whole comment contents (regex): + [ \t]*FALLTHR(U|OUGH)[ \t]* + */ + else if (CPP_OPTION (pfile, cpp_warn_implicit_fallthrough) == 4) + { + while (*from == ' ' || *from == '\t') + from++; + if ((size_t) (pfile->buffer->cur - from) < sizeof "FALLTHRU" - 1) + return false; + if (memcmp (from, "FALLTHR", sizeof "FALLTHR" - 1)) + return false; + from += sizeof "FALLTHR" - 1; + if (*from == 'U') + from++; + else if ((size_t) (pfile->buffer->cur - from) < sizeof "OUGH" - 1) + return false; + else if (memcmp (from, "OUGH", sizeof "OUGH" - 1)) + return false; + else + from += sizeof "OUGH" - 1; + while (*from == ' ' || *from == '\t') + from++; } /* Whole comment contents (regex): [ \t.!]*(ELSE,? |INTENTIONAL(LY)? )?FALL(S | |-)?THR(OUGH|U)[ \t.!]*(-[^\n\r]*)? @@ -2085,8 +2166,8 @@ fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start) unsigned char f = *from; bool all_upper = false; if (f == 'E' || f == 'e') - { - if ((size_t) (pfile->buffer->cur - from) + { + if ((size_t) (pfile->buffer->cur - from) < sizeof "else fallthru" - 1) return false; if (f == 'E' && memcmp (from + 1, "LSE", sizeof "LSE" - 1) == 0) @@ -2096,7 +2177,7 @@ fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start) from += sizeof "else" - 1; if (*from == ',') from++; - if (*from != ' ') + if (*from != ' ') return false; from++; if (all_upper && *from == 'f') @@ -2104,10 +2185,10 @@ fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start) if (f == 'e' && *from == 'F') return false; f = *from; - } + } else if (f == 'I' || f == 'i') - { - if ((size_t) (pfile->buffer->cur - from) + { + if ((size_t) (pfile->buffer->cur - from) < sizeof "intentional fallthru" - 1) return false; if (f == 'I' && memcmp (from + 1, "NTENTIONAL", @@ -2138,7 +2219,7 @@ fallthrough_comment_p (cpp_reader *pfile, const unsigned char *comment_start) if (f == 'i' && *from == 'F') return false; f = *from; - } + } if (f != 'F' && f != 'f') return false; if ((size_t) (pfile->buffer->cur - from) < sizeof "fallthru" - 1) -- 2.30.2