Bug 44715 - Break in increment expression of "for" statement inconsistent with g++
Summary: Break in increment expression of "for" statement inconsistent with g++
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 49779 90617 (view as bug list)
Depends on:
Blocks:
 
Reported: 2010-06-29 16:20 UTC by Doug Gregor
Modified: 2019-05-27 17:33 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Doug Gregor 2010-06-29 16:20:00 UTC
The following program exhibits different behavior with gcc vs. g++:

dgregor$ cat t.c
#include <stdio.h>

int main()
{
  int i;
  for( i = 0; i < 3; )
    for( ; ; ({ i++; break; }) )
      printf( "%d\n", i );
}

With gcc, the break in the statement expression applies to the outer "for" loop, so we get just "0" as output:

dgregor$ gcc t.c && ./a.out
0

with g++, the break in the statement expression applies to the inner "for" loop, so we get "0" "1" and "2" as the output:

dgregor$ g++ t.c && ./a.out
0
1
2

g++ seems to have the right behavior here, and in any case g++ can't really be changed now: Qt's foreach macro depends on having "break" bind to the inner for loop.
Comment 1 jsm-csl@polyomino.org.uk 2010-06-29 16:36:43 UTC
Subject: Re:   New: Break in increment expression of "for"
 statement inconsistent with g++

On Tue, 29 Jun 2010, doug dot gregor at gmail dot com wrote:

> g++ seems to have the right behavior here, and in any case g++ can't really be
> changed now: Qt's foreach macro depends on having "break" bind to the inner for
> loop.

Yes, the inconsistency should be fixed, but for both C and C++ I get 
"error: break statement not within loop or switch" if I only have one loop 
rather than nested loops, and break binding to the inner loop seems 
inconsistent with that error.  The C standard specifically says that 
continue and break statements must appear in a loop body (or switch body, 
in the case of break); if you make break bind to the inner loop, you 
should also not have that error in the single loop case (the rule should 
change to allow additional positions in the loop outside its body).

Whatever is done needs clearly defining and documenting (with testcases) 
for both break and continue, and including all relevant places in for, 
while, do-while and switch statements (I do not make a claim here as to 
exactly which places should allow break and so bind to the inner 
construct, and which should not and so bind to the outer construct if 
any).

Comment 2 pinskia@gmail.com 2010-06-29 16:40:15 UTC
Subject: Re:   New: Break in increment expression of "for" statement inconsistent with g++

What does a break with a statement expression do for each frontend? Is  
it even valid to have a break there(without a statement expression)?
If it is valid, what does each standard say about the break there? If  
they say the same thing then I say both frontends should behave the  
same but if the c standard says a break should apply to the outer one  
then we should follow that for statement expressions also.

On Jun 29, 2010, at 9:20 AM, "doug dot gregor at gmail dot com" <gcc-bugzilla@gcc.gnu.org 
 > wrote:

> The following program exhibits different behavior with gcc vs. g++:
>
> dgregor$ cat t.c
> #include <stdio.h>
>
> int main()
> {
>  int i;
>  for( i = 0; i < 3; )
>    for( ; ; ({ i++; break; }) )
>      printf( "%d\n", i );
> }
>
> With gcc, the break in the statement expression applies to the outer  
> "for"
> loop, so we get just "0" as output:
>
> dgregor$ gcc t.c && ./a.out
> 0
>
> with g++, the break in the statement expression applies to the inner  
> "for"
> loop, so we get "0" "1" and "2" as the output:
>
> dgregor$ g++ t.c && ./a.out
> 0
> 1
> 2
>
> g++ seems to have the right behavior here, and in any case g++ can't  
> really be
> changed now: Qt's foreach macro depends on having "break" bind to  
> the inner for
> loop.
>
>
> -- 
>           Summary: Break in increment expression of "for" statement
>                    inconsistent with g++
>           Product: gcc
>           Version: 4.2.0
>            Status: UNCONFIRMED
>          Severity: normal
>          Priority: P3
>         Component: c
>        AssignedTo: unassigned at gcc dot gnu dot org
>        ReportedBy: doug dot gregor at gmail dot com
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44715
>
Comment 3 jsm-csl@polyomino.org.uk 2010-06-29 16:46:57 UTC
Subject: Re:  Break in increment expression of "for" statement
 inconsistent with g++

On Tue, 29 Jun 2010, pinskia at gmail dot com wrote:

> What does a break with a statement expression do for each frontend? Is  
> it even valid to have a break there(without a statement expression)?

The relevant contexts have expressions, so without statement expressions 
it's not possible to have break there.  The C standard (I haven't checked 
C++) requires break (and continue, which probably has much the same issue) 
to be in a loop or switch body - but being elsewhere in the loop than its 
body isn't possible in standard C anyway.  When I was fixing statement 
expression issues with jumps, and defining exactly what was permitted (bug 
772), I didn't think of this particular issue.

Comment 4 ecyrbe 2010-07-06 05:28:04 UTC
(In reply to comment #3)
> Subject: Re:  Break in increment expression of "for" statement
>  inconsistent with g++
> 
> On Tue, 29 Jun 2010, pinskia at gmail dot com wrote:
> 
> > What does a break with a statement expression do for each frontend? Is  
> > it even valid to have a break there(without a statement expression)?
> 
> The relevant contexts have expressions, so without statement expressions 
> it's not possible to have break there.  The C standard (I haven't checked 
> C++) requires break (and continue, which probably has much the same issue) 
> to be in a loop or switch body - but being elsewhere in the loop than its 
> body isn't possible in standard C anyway.  When I was fixing statement 
> expression issues with jumps, and defining exactly what was permitted (bug 
> 772), I didn't think of this particular issue.
> 

As i said in the clang bug tracker who triggered this issue initially :
Here is what the c++ standard says :

"The break statement shall occur only in an iteration-statement or a switch
statement and causes termination of the smallest enclosing iteration-statement
or switch statement; control passes to the statement following the terminated
statement, if any."

So the break (if the expression statement extension is activated) is considered
in the inner loop with this extension.

And now here is what the c99 standard says :

"A break statement shall appear only in or as a switch body or loop body"

But in C, the loop body does not contain the expression statement. So the break
applie only to the outer loop in C.

The result is that gcc is correct in this behavior. C++ and C should differ in
this matter.
Comment 5 Martin Sebor 2017-03-17 22:55:48 UTC
*** Bug 49779 has been marked as a duplicate of this bug. ***
Comment 6 Jakub Jelinek 2019-01-23 14:41:47 UTC
Author: jakub
Date: Wed Jan 23 14:41:16 2019
New Revision: 268188

URL: https://gcc.gnu.org/viewcvs?rev=268188&root=gcc&view=rev
Log:
	PR c/44715
	* cp-gimplify.c (genericize_cp_loop): Call begin_bc_block only
	after genericizing cond and incr expressions.

	* doc/extend.texi: Document break and continue behavior in
	statement expressions.

	* c-c++-common/pr44715.c: New test.

Added:
    trunk/gcc/testsuite/c-c++-common/pr44715.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/cp-gimplify.c
    trunk/gcc/doc/extend.texi
    trunk/gcc/testsuite/ChangeLog
Comment 7 Jakub Jelinek 2019-01-24 17:18:01 UTC
Should be fixed for GCC 9+.
Comment 8 Andrew Pinski 2019-05-27 17:33:42 UTC
*** Bug 90617 has been marked as a duplicate of this bug. ***