void f(int a, int *b) { *b = a; } void g(void) { int a = 5; f(++a, &a); } with -Wall reports t.c:1: warning: operation on `a' may be undefined. This is with the following gcc versions: [I realize they are all Red Hat versions, not official releases, but I think that this happening on three different release branches provides sufficient argument that this is very likely an upstream bug.] Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.3.3/specs Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --disable-libunwind-exceptions --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux Thread model: posix gcc version 3.3.3 20040412 (Red Hat Linux 3.3.3-7) and Reading specs from /usr/lib/gcc/i386-redhat-linux/3.4.1/specs Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=i386-redhat-linux Thread model: posix gcc version 3.4.1 20040831 (Red Hat 3.4.1-10) and Reading specs from /usr/lib/gcc/i386-redhat-linux/3.5.0/specs Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --with-gxx-include-dir=/usr/include/c++/3.4.1 --enable-languages=c,c++,f99 --disable-libgcj --host=i386-redhat-linux Thread model: posix gcc version 3.5.0 20040818 (Red Hat 3.5.0-0.9)
No the warning is correct. ++a could come before or after taking the address of a which is why this is undefined.
Uh? How can an increment operation change the address of a variable?
Oh, you are right I need to look at the test more closely.
We cannot just ignore ADDR_EXPR outright though (this is undefined): struct x { int i; }; void g(struct x*, int *); void f(struct x *y) { g(y++, &y->i); } I think I have a fix will test the fix.
Actually the patch will not work when we start warning about full expression, here is the patch just to give an example of what the final patch would look like: Index: c-common.c =============================================================== ==== RCS file: /cvs/gcc/gcc/gcc/c-common.c,v retrieving revision 1.578 diff -u -p -r1.578 c-common.c --- c-common.c 16 Oct 2004 22:58:45 -0000 1.578 +++ c-common.c 18 Oct 2004 22:42:30 -0000 @@ -1358,6 +1358,16 @@ verify_tree (tree x, struct tlist **pbef add_tlist (pno_sp, t->cache_after_sp, NULL_TREE, 1); return; } + + case ADDR_EXPR: + { + x = TREE_OPERAND (x, 0); + if (DECL_P (x)) + return; + writer = 0; + goto restart; + } + return; default: /* For other expressions, simply recurse on their operands. Here is the test which I was taking about: struct x { int i; }; void g(int, int *); void f(struct x *y) { g(y->i++, &y->i); /* {dg-bogus "undefined" } */ } Here is another where we should warn: struct x { int i; }; void g(int, int *); void f(struct x *y) { g((y++)->i, &y->i); /* { dg-warning "undefined" } */ }
Another one: int foo(int i) { i = ++i; return i; } I think the point is we should not warn for pre-increment, only post-increment. Or can someone come up with a testcase that has undefined evaluation order just by using pre-increment? One with two pre-increments: int foo(void) { int i = 1; i = (++i == 2) + ++i; return i; } This is certainly undefined. But with one pre-increment only?
Subject: Re: -Wsequence-point reports false positives On Wed, 22 Mar 2006, rguenth at gcc dot gnu dot org wrote: > i = ++i; Modified twice between sequence points, so undefined behavior. > I think the point is we should not warn for pre-increment, only post-increment. > Or can someone come up with a testcase that has undefined evaluation order just > by using pre-increment? One with two pre-increments: It's undefined behavior, not undefined evaluation order. Pre-increment returns the new value, but that doesn't mean the new value is stored until the following sequence point.
Sure - but this doesn't matter in this case. And 6.5.3.1 tells you "The expression ++E is equivalent to (E+=1)." 6.5.16 says "The side effect of updating the stored value of the left operand shall occur between the previous and the next sequence point." For i = ++i; this means we have i = (i += 1); where for i += 1 the next sequence point is the i = ... assigment? Of course for the particular testcase the ordering of the two stores does not matter. Would int i=0; i = ++i + 1; be able to result in i == 1? I don't think so as per 6.5.16.
(In reply to comment #8) > i = (i += 1); > > where for i += 1 the next sequence point is the i = ... assigment? The next sequence point is the semicolon. > Of course for the particular testcase the ordering of the two stores > does not matter. Would int i=0; i = ++i + 1; be able to result in > i == 1? Yes, the side effects of = and ++ can be performed in either order.
*** Bug 37259 has been marked as a duplicate of this bug. ***
Andrew, your patch seems to work, so what is the problem?
(In reply to comment #11) > Andrew, your patch seems to work, so what is the problem? I think we are still warning in too many places but I can't remember now, it was almost 4 years ago and many stuff has changed.
(In reply to comment #12) > > I think we are still warning in too many places but I can't remember now, it > was almost 4 years ago and many stuff has changed. Do you mind if I test it and try to make it work? For the tests in this PR it seems to work correctly. If you can think of other tests, please post them here.
Subject: Bug 18050 Author: manu Date: Fri Aug 29 00:06:19 2008 New Revision: 139742 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=139742 Log: 2008-08-28 Manuel Lopez-Ibanez <manu@gcc.gnu.org> Andrew Pinski <pinskia@gcc.gnu.org> PR 18050 * c-common.c (verify_tree): Fix handling of ADDR_EXPR. testsuite/ * gcc.dg/Wsequence-point-pr18050.c: New. * g++.dg/warn/Wsequence-point-pr18050.C: New. Added: trunk/gcc/testsuite/g++.dg/warn/Wsequence-point-pr18050.C trunk/gcc/testsuite/gcc.dg/Wsequence-point-pr18050.c Modified: trunk/gcc/ChangeLog trunk/gcc/c-common.c trunk/gcc/testsuite/ChangeLog
Fixed in GCC 4.4 Thanks for the report.