public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* PATCH for c++/87068, missing diagnostic with fallthrough statement
@ 2018-08-23 20:38 Marek Polacek
  2018-08-30 21:17 ` Marek Polacek
  0 siblings, 1 reply; 5+ messages in thread
From: Marek Polacek @ 2018-08-23 20:38 UTC (permalink / raw)
  To: GCC Patches

The C++ standard says that [[fallthrough]]; at the end of a switch statement
is ill-formed: <http://eel.is/c++draft/dcl.attr.fallthrough>

Currently we do check that the statement after a fallthrough statement is
a labeled statement, but we didn't warn if a fallthrough statement is at
the very end of a switch statement.  This patch adds this warning.

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

2018-08-23  Marek Polacek  <polacek@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;
+	    }
 
 	  bool found = false;
-	  location_t loc = gimple_location (stmt);
 
 	  gimple_stmt_iterator gsi2 = *gsi_p;
 	  stmt = gsi_stmt (gsi2);
@@ -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 "
+		  "a case label or default label");
+    }
 }
 
 \f
diff --git gcc/testsuite/c-c++-common/Wimplicit-fallthrough-37.c gcc/testsuite/c-c++-common/Wimplicit-fallthrough-37.c
index e69de29bb2d..644003af47d 100644
--- gcc/testsuite/c-c++-common/Wimplicit-fallthrough-37.c
+++ 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" } */
+    }
+}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH for c++/87068, missing diagnostic with fallthrough statement
  2018-08-23 20:38 PATCH for c++/87068, missing diagnostic with fallthrough statement Marek Polacek
@ 2018-08-30 21:17 ` Marek Polacek
  2018-08-30 21:25   ` Jakub Jelinek
  0 siblings, 1 reply; 5+ messages in thread
From: Marek Polacek @ 2018-08-30 21:17 UTC (permalink / raw)
  To: GCC Patches

Ping.

On Thu, Aug 23, 2018 at 04:38:03PM -0400, Marek Polacek wrote:
> The C++ standard says that [[fallthrough]]; at the end of a switch statement
> is ill-formed: <http://eel.is/c++draft/dcl.attr.fallthrough>
> 
> Currently we do check that the statement after a fallthrough statement is
> a labeled statement, but we didn't warn if a fallthrough statement is at
> the very end of a switch statement.  This patch adds this warning.
> 
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
> 
> 2018-08-23  Marek Polacek  <polacek@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;
> +	    }
>  
>  	  bool found = false;
> -	  location_t loc = gimple_location (stmt);
>  
>  	  gimple_stmt_iterator gsi2 = *gsi_p;
>  	  stmt = gsi_stmt (gsi2);
> @@ -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 "
> +		  "a case label or default label");
> +    }
>  }
>  
>  \f
> diff --git gcc/testsuite/c-c++-common/Wimplicit-fallthrough-37.c gcc/testsuite/c-c++-common/Wimplicit-fallthrough-37.c
> index e69de29bb2d..644003af47d 100644
> --- gcc/testsuite/c-c++-common/Wimplicit-fallthrough-37.c
> +++ 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" } */
> +    }
> +}

	Marek

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH for c++/87068, missing diagnostic with fallthrough statement
  2018-08-30 21:17 ` Marek Polacek
@ 2018-08-30 21:25   ` Jakub Jelinek
  2019-02-28 23:03     ` Marek Polacek
  0 siblings, 1 reply; 5+ messages in thread
From: Jakub Jelinek @ 2018-08-30 21:25 UTC (permalink / raw)
  To: Marek Polacek; +Cc: GCC Patches

On Thu, Aug 30, 2018 at 05:17:03PM -0400, Marek Polacek wrote:
> > 2018-08-23  Marek Polacek  <polacek@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);
?

	Jakub

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH for c++/87068, missing diagnostic with fallthrough statement
  2018-08-30 21:25   ` Jakub Jelinek
@ 2019-02-28 23:03     ` Marek Polacek
  2019-02-28 23:07       ` Jakub Jelinek
  0 siblings, 1 reply; 5+ messages in thread
From: Marek Polacek @ 2019-02-28 23:03 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: GCC Patches

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  <polacek@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  <polacek@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");
 }
 
 \f
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" } */
+    }
+}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH for c++/87068, missing diagnostic with fallthrough statement
  2019-02-28 23:03     ` Marek Polacek
@ 2019-02-28 23:07       ` Jakub Jelinek
  0 siblings, 0 replies; 5+ messages in thread
From: Jakub Jelinek @ 2019-02-28 23:07 UTC (permalink / raw)
  To: Marek Polacek; +Cc: GCC Patches

On Thu, Feb 28, 2019 at 05:16:14PM -0500, Marek Polacek wrote:
> 2019-02-28  Marek Polacek  <polacek@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.

Ok, thanks.

	Jakub

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-02-28 22:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-08-23 20:38 PATCH for c++/87068, missing diagnostic with fallthrough statement Marek Polacek
2018-08-30 21:17 ` Marek Polacek
2018-08-30 21:25   ` Jakub Jelinek
2019-02-28 23:03     ` Marek Polacek
2019-02-28 23:07       ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).