On Thu, Aug 30, 2018 at 11:24:50PM +0200, Jakub Jelinek wrote:
> On Thu, Aug 30, 2018 at 05:17:03PM -0400, Marek Polacek wrote:
> > > 2018-08-23  Marek Polacek  <pola...@redhat.com>
> > > 
> > >   PR c++/87068
> > >   * gimplify.c (expand_FALLTHROUGH_r): If IFN_FALLTHROUGH was found
> > >   at the end of a seq, save its location to walk_stmt_info.
> > >   (expand_FALLTHROUGH): Warn if IFN_FALLTHROUGH is at the end of
> > >   a switch.
> > > 
> > >   * c-c++-common/Wimplicit-fallthrough-37.c: New test.
> > > 
> > > diff --git gcc/gimplify.c gcc/gimplify.c
> > > index e35137aec2c..04c15016f18 100644
> > > --- gcc/gimplify.c
> > > +++ gcc/gimplify.c
> > > @@ -2231,7 +2231,7 @@ maybe_warn_implicit_fallthrough (gimple_seq seq)
> > >  
> > >  static tree
> > >  expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
> > > -               struct walk_stmt_info *)
> > > +               struct walk_stmt_info *wi)
> > >  {
> > >    gimple *stmt = gsi_stmt (*gsi_p);
> > >  
> > > @@ -2250,11 +2250,14 @@ expand_FALLTHROUGH_r (gimple_stmt_iterator 
> > > *gsi_p, bool *handled_ops_p,
> > >        if (gimple_call_internal_p (stmt, IFN_FALLTHROUGH))
> > >   {
> > >     gsi_remove (gsi_p, true);
> > > +   location_t loc = gimple_location (stmt);
> > >     if (gsi_end_p (*gsi_p))
> > > -     return integer_zero_node;
> > > +     {
> > > +       wi->info = &loc;
> > > +       return integer_zero_node;
> 
> This looks incorrect.  loc is an automatic variable in
> expand_FALLTHROUGH_r, you set wi->info to the address of that variable,
> then immediately return and then:
> 
> > > @@ -2317,6 +2320,14 @@ expand_FALLTHROUGH (gimple_seq *seq_p)
> > >    struct walk_stmt_info wi;
> > >    memset (&wi, 0, sizeof (wi));
> > >    walk_gimple_seq_mod (seq_p, expand_FALLTHROUGH_r, NULL, &wi);
> > > +  if (wi.callback_result == integer_zero_node)
> > > +    {
> > > +      /* We've found [[fallthrough]]; at the end of a switch, which the 
> > > C++
> > > +  standard says is ill-formed; see [dcl.attr.fallthrough].  */
> > > +      location_t *loc = static_cast<location_t *>(wi.info);
> > > +      warning_at (*loc, 0, "attribute %<fallthrough%> not preceding "
> 
> dereference it here, when the loc variable is no longer in scope.
> -fsanitize-use-after-scope should complain here...
> 
> > > +           "a case label or default label");
> > > +    }
> 
> If the only spot that ises wi->info is in these two new spots, can't you
> e.g. set in the expand_FALLTHROUGH function:
>   location_t loc;
>   wi.info = (void *) &loc;
> and then in expand_FALLTHROUGH_r do:
>   *static_cast<location_t *>(wi.info) = gimple_location (stmt);
> ?

Sorry for the ridiculous delay and an embarassing thinko :(.

Here's an updated patch.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2019-02-28  Marek Polacek  <pola...@redhat.com>

        PR c++/87068 - missing diagnostic with fallthrough statement.
        * gimplify.c (expand_FALLTHROUGH_r): If IFN_FALLTHROUGH was found
        at the end of a seq, save its location to walk_stmt_info.
        (expand_FALLTHROUGH): Warn if IFN_FALLTHROUGH is at the end of
        a switch.

        * c-c++-common/Wimplicit-fallthrough-37.c: New test.

diff --git gcc/gimplify.c gcc/gimplify.c
index 7e37e500d81..983635ba21f 100644
--- gcc/gimplify.c
+++ gcc/gimplify.c
@@ -2263,7 +2263,7 @@ maybe_warn_implicit_fallthrough (gimple_seq seq)
 
 static tree
 expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
-                     struct walk_stmt_info *)
+                     struct walk_stmt_info *wi)
 {
   gimple *stmt = gsi_stmt (*gsi_p);
 
@@ -2283,7 +2283,10 @@ expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool 
*handled_ops_p,
        {
          gsi_remove (gsi_p, true);
          if (gsi_end_p (*gsi_p))
-           return integer_zero_node;
+           {
+             *static_cast<location_t *>(wi->info) = gimple_location (stmt);
+             return integer_zero_node;
+           }
 
          bool found = false;
          location_t loc = gimple_location (stmt);
@@ -2347,8 +2350,15 @@ static void
 expand_FALLTHROUGH (gimple_seq *seq_p)
 {
   struct walk_stmt_info wi;
+  location_t loc;
   memset (&wi, 0, sizeof (wi));
+  wi.info = (void *) &loc;
   walk_gimple_seq_mod (seq_p, expand_FALLTHROUGH_r, NULL, &wi);
+  if (wi.callback_result == integer_zero_node)
+    /* We've found [[fallthrough]]; at the end of a switch, which the C++
+       standard says is ill-formed; see [dcl.attr.fallthrough].  */
+    warning_at (loc, 0, "attribute %<fallthrough%> not preceding "
+               "a case label or default label");
 }
 
 
diff --git gcc/testsuite/c-c++-common/Wimplicit-fallthrough-37.c 
gcc/testsuite/c-c++-common/Wimplicit-fallthrough-37.c
new file mode 100644
index 00000000000..644003af47d
--- /dev/null
+++ gcc/testsuite/c-c++-common/Wimplicit-fallthrough-37.c
@@ -0,0 +1,13 @@
+/* PR c++/87068 */
+/* { dg-do compile } */
+
+void
+f (int n)
+{
+  switch (n)
+    {
+    case 4:
+      ++n;
+      __attribute__((fallthrough)); /* { dg-warning "not preceding" } */
+    }
+}

Reply via email to