Summary: | Temporary rvalue (result of cast) can be illegally bound to non-const reference | ||
---|---|---|---|
Product: | gcc | Reporter: | peteb |
Component: | c++ | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED DUPLICATE | ||
Severity: | normal | CC: | aoliva, bangerth, bangerth, bangerth, gcc-bugs, gdr, giovannibajo, mike, nigels |
Priority: | P3 | Keywords: | rejects-valid |
Version: | 2.95.2 | ||
Target Milestone: | 3.4.0 | ||
Host: | Target: | ||
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | 2003-05-03 00:00:00 |
Description
peteb
2001-02-01 11:26:00 UTC
State-Changed-From-To: open->analyzed State-Changed-Why: There is indeed a bug. The problem is that the result of the cast is an rvalue, because the cast-to type is not a reference type. Therefore, a temporary should be created. However, a temporary cannot be bound to a non-const reference, but g++ happily binds it to frob2's argument, even with -ansi -pedantic. Even if the binding-to-non-const were to be done as an extension, it still shouldn't modify variable s; it should modify the temporary, then discard it. WRT the difference between the inline and the non-inline functions, the problem is likely to be in the tree level, because the initial RTL dump is already significantly different for the two functions. From: aoliva@gcc.gnu.org To: gcc-gnats@gcc.gnu.org, nobody@gcc.gnu.org, peteb@sitera.com Cc: Subject: Re: c++/1833 Date: 2 Mar 2001 10:26:28 -0000 Synopsis: inlining sometimes causes incorrect behavior State-Changed-From-To: open->analyzed State-Changed-By: aoliva State-Changed-When: Fri Mar 2 02:26:28 2001 State-Changed-Why: There is indeed a bug. The problem is that the result of the cast is an rvalue, because the cast-to type is not a reference type. Therefore, a temporary should be created. However, a temporary cannot be bound to a non-const reference, but g++ happily binds it to frob2's argument, even with -ansi -pedantic. Even if the binding-to-non-const were to be done as an extension, it still shouldn't modify variable s; it should modify the temporary, then discard it. WRT the difference between the inline and the non-inline functions, the problem is likely to be in the tree level, because the initial RTL dump is already significantly different for the two functions. http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view&pr=1833&database=gcc From: Wolfgang Bangerth <bangerth@ticam.utexas.edu> To: gcc-bugs@gcc.gnu.org, <gcc-gnats@gcc.gnu.org> Cc: Subject: Re: c++/1833: inlining sometimes causes incorrect behavior Date: Wed, 30 Oct 2002 19:27:24 -0600 (CST) I can confirm this also with newer gcc's, and this indeed very surprising. Here's the thing: ----------------------------------- #include <iostream> using namespace std; typedef char *pchar; void advance_by_3 (pchar &s) { s += 3; } inline void frob_fail (char *s) { advance_by_3((pchar)s); cerr << "should be 34567: " << s << endl; } void frob_pass (char *s) { advance_by_3((pchar)s); cerr << "should be 34567: " << s << endl; } int main () { char *x = "01234567"; frob_fail(x); char *y = "01234567"; frob_pass(y); } ----------------------------------- and I get: tmp/g> /home/bangerth/bin/gcc-3.2.1-pre/bin/c++ -O2 x.cc tmp/g> ./a.out should be 34567: 01234567 should be 34567: 01234567 tmp/g> /home/bangerth/bin/gcc-3.2.1-pre/bin/c++ x.cc tmp/g> ./a.out should be 34567: 34567 should be 34567: 34567 With present CVS I get the first results also for -O0. For 2.95, I get the wrong result only for the _inlined_ function, where I now get it uniformly. The problem is rather surreal, since touching it somewhere makes it go away. For example, removing the (pchar) casts in the call to advance_by_3 make a difference, although the variable is already a char*. Regards Wolfgang ------------------------------------------------------------------------- Wolfgang Bangerth email: bangerth@ticam.utexas.edu www: http://www.ticam.utexas.edu/~bangerth From: Wolfgang Bangerth <bangerth@apex68.ticam.utexas.edu> To: gcc-gnats@gcc.gnu.org Cc: Subject: c++/1833: inlining sometimes causes incorrect behavior Date: Thu, 14 Nov 2002 14:35:19 -0600 Re-confirmed with 3.3 CVS from 2002-11-10 and 3.2.1 pre from the same date. From: Wolfgang Bangerth <bangerth@ices.utexas.edu> To: gcc-gnats@gcc.gnu.org, <nigels@nigels.com> Cc: Subject: Re: c++/1833 Date: Thu, 3 Apr 2003 11:31:58 -0600 (CST) Nigel, the problem you sent has nothing to do with the problem described in PR 1833. You are violating aliasing rules. The code in the report is legal, yours is not. W. ------------------------------------------------------------------------- Wolfgang Bangerth email: bangerth@ices.utexas.edu www: http://www.ices.utexas.edu/~bangerth/ From: Nigel Stewart <nigels@nigels.com> To: gcc-gnats@gcc.gnu.org, gcc-bugs@gcc.gnu.org, nobody@gcc.gnu.org, gcc-prs@gcc.gnu.org, peteb@sitera.com Cc: Subject: Re: c++/1833: [2003-01-01] inlining sometimes causes incorrect behavior Date: Fri, 04 Apr 2003 03:24:48 +1000 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=1833 Perhaps the bug/problem/issue I've found in gcc is related to this one already in the database: Problem Report 1833 ------- #include <iostream> using namespace std; float foo() { assert(sizeof(unsigned int)==sizeof(float)); float tmp = 0.0; *((unsigned int *) &tmp) = (127<<23) | (1<<22); return tmp; } int main(int argc,char *argv[]) { cout << "Output should be 1.5: " << foo() << endl; } ------- $ gcc -v Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/3.2/specs Configured with: /netrel/src/gcc-3.2-3/configure --enable-languages=c,c++,f77,java --enable-libgcj --enable-threads=posix --with-system-zlib --enable-nls --without-included-gettext --enable-interpreter --disable-sjlj-exceptions --disable-version-specific-runtime-libs --enable-shared --build=i686-pc-linux --host=i686-pc-cygwin --target=i686-pc-cygwin --enable-haifa --prefix=/usr --exec-prefix=/usr --sysconfdir=/etc --libdir=/usr/lib --includedir=/nonexistent/include --libexecdir=/usr/sbin Thread model: posix gcc version 3.2 20020927 (prerelease) $ g++ test.cpp -o test && ./test Output should be 1.5: 1.5 $ g++ -O2 test.cpp -o test && ./test Output should be 1.5: 0 -------- The following version of foo does not exhibit the same problem: float foo() { assert(sizeof(unsigned int)==sizeof(float)); unsigned int tmp = (127<<23) | (1<<22); return *((float *) &tmp); } Regards, Nigel Stewart nigels@nigels.com From: Nigel Stewart <nigels@nigels.com> To: Wolfgang Bangerth <bangerth@ices.utexas.edu> Cc: gcc-gnats@gcc.gnu.org Subject: Re: c++/1833 Date: Fri, 04 Apr 2003 12:58:54 +1000 Wolfgang, Heeding your advice about aliasing rules, I've replaced the cast with a union. Problem is solved. However, I would suggest that gcc should provide warnings or errors in the case of being fed illegal code. float foo() { assert(sizeof(unsigned int)==sizeof(float)); union { float f; unsigned int i; } tmp; tmp.i = (127<<23) | (1<<22); return tmp.f; } Thanks for your response, and my apologies for cluttering the bug database... N Stewart > Nigel, > the problem you sent has nothing to do with the problem described in PR > 1833. You are violating aliasing rules. The code in the report is legal, > yours is not. > > W. From: Wolfgang Bangerth <bangerth@ices.utexas.edu> To: gcc-gnats@gcc.gnu.org, Giovanni Bajo <giovannibajo@libero.it> Cc: Subject: Re: c++/1833 Date: Thu, 8 May 2003 18:38:11 -0500 (CDT) This is a gcc extension: cast-as-lvalue. I personally think it's an evil one. Binding it to a reference yields all sorts of problems. I closed several duplicates of some such bug recently. Giovanni, check 1920 and 7884, possibly also 7503. W. ------------------------------------------------------------------------- Wolfgang Bangerth email: bangerth@ices.utexas.edu www: http://www.ices.utexas.edu/~bangerth/ From: "Giovanni Bajo" <giovannibajo@libero.it> To: <gcc-gnats@gcc.gnu.org>, <gcc-bugs@gcc.gnu.org>, <nobody@gcc.gnu.org>, <gcc-prs@gcc.gnu.org>, <peteb@sitera.com> Cc: Subject: Re: c++/1833: [2003-01-01] inlining sometimes causes incorrect behavior Date: Fri, 9 May 2003 01:17:04 +0200 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=1833 Given Alexander's analysys, which I confirm, this PR boils down to the following code: -------------------------------- typedef char *pchar; void func(pchar &s) {} int main () { char *s = "123"; func((pchar)s); } -------------------------------- which is illegal, because the cast creates a temporary rvalue which cannot be bound to a non-const reference. But GCC compiles it happily even with -ansi -pedantic. So it's an accept-illegal. Giovanni Bajo From: Gabriel Dos Reis <gdr@integrable-solutions.net> To: Wolfgang Bangerth <bangerth@ices.utexas.edu> Cc: gcc-gnats@gcc.gnu.org Subject: Re: c++/1833 Date: 09 May 2003 09:05:35 +0200 Wolfgang Bangerth <bangerth@ices.utexas.edu> writes: | The following reply was made to PR c++/1833; it has been noted by GNATS. | | From: Wolfgang Bangerth <bangerth@ices.utexas.edu> | To: gcc-gnats@gcc.gnu.org, Giovanni Bajo <giovannibajo@libero.it> | Cc: | Subject: Re: c++/1833 | Date: Thu, 8 May 2003 18:38:11 -0500 (CDT) | | This is a gcc extension: cast-as-lvalue. I personally think it's an evil | one. It should be removed. -- Gaby *** Bug 11374 has been marked as a duplicate of this bug. *** |