Bug 7135 - Faulty Operator Precedence
Summary: Faulty Operator Precedence
Status: RESOLVED DUPLICATE of bug 11751
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 2.95.3
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-06-26 16:36 UTC by lindahlb
Modified: 2004-08-13 16:03 UTC (History)
4 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 lindahlb 2002-06-26 16:36:00 UTC
The source code depicting the problem is attatched as a file.

Lines which show existance of the bug:
cout << a.set(5).get() << a.set(30).get();
cout << a.get();

The output of the compiled program:
5305

The machine code appears to be executeing 'set(5)' first, and then 'set(30)', as it should. However, as indicated by the last output, it executed 'set(5)' last as well as first. It appears to be executing 'set(5)' twice.

The generated code should be of the following:
operator<<(operator<<(cout, a.set(5).get()), a.set(30).get());

I ran over the output and code several times to figure out what order the operations are actually taking place, but I was unable to come up with a logical order that would produce the output, unless 'set(5)' was being executed twice.

Release:
2.95.3

Environment:
FreeBSD

How-To-Repeat:
The file attatched shows how to repeat.
Comment 1 lindahlb 2002-06-26 16:36:00 UTC
Fix:
There are two fixes:
1) Adjust the problem lines as so:
cout << a.set(5).get();
cout << a.set(30).get();
cout << a.get();
2) Inline the methods 'set(int)' and 'get()'

Apply either fix and the output of the compiled program is as expected:
53030
Comment 2 Nathan Sidwell 2002-06-27 04:14:43 UTC
State-Changed-From-To: open->feedback
State-Changed-Why: I beleive the code is ill-formed. I agree the code is
    equivalent to
    operator<<(operator<<(cout, a.set(5).get()), a.set(30).get());
    which I'll rewrite as
    	Foo (Baz (cout a.Wibble (5)), a.Wobble (30)))
    There are 4 sequence points in that, each between
    evaluating the parameters to a call, and the call itself.
    These sequence points are partially ordered, but not
    completely ordered. In particular there is no ordering
    between the a.Wobble (30) call and the a.Wibble (5) call.
    i.e. in evaluating the argyments to Foo, I could
    	a.Wobble (30)
    	a.Wibble (5)
    	cout
    	call Baz
    	call Foo
    I cout reorder the a.Wibble and a.Wobble calls. your example
    had a.Wobble (5).Fetch1 () and a.Wibble (30).Fetch2 (),
    those fetch calls are similarly unorderd. Provided the
    appropriate Fetch occurs after the Wibble/Wobble call,
    C++ semantics are maintained.
    
    Let me know if you disagree with my analysis
Comment 3 lindahlb 2002-06-27 11:47:27 UTC
From: "Brian Lindahl" <lindahlb@hotmail.com>
To: nathan@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-prs@gcc.gnu.org, lindahlb@hotmail.com, nobody@gcc.gnu.org, unifex@yuidesigns.net, gcc-gnats@gcc.gnu.org
Cc:  
Subject: Re: c++/7135: Faulty Operator Precedence
Date: Thu, 27 Jun 2002 11:47:27 -0700

 First of all, I disagree with your analysis. One fact alone should 
 contradict the analysis:
 Inlining the methods changes the compiler output, and thus, the output 
 displayed on the screen.
 
 I believe that, according to C++ semantics, inlining a function should not 
 change compiler output.
 
 I think the problem in my example was the naive expansion of the code from:
 cout << a.set(5).get() << a.set(30).get();
 To:
 operator<<(operator<<(cout, a.set(5).get()), a.set(30).get());
 
 In fact, I should have stated that the code should be equivalent to:
 operator<<(
    operator<<(
       cout,
       A::get(
          &A::set(5, &a)
       )
    ),
    A::get(
       &A::set(30, &a)
    )
 );
 
 (Note the method, set, returns '*this' as a 'const A &')
 
 >     There are 4 sequence points in that, each between
 >     evaluating the parameters to a call, and the call itself.
 >     These sequence points are partially ordered, but not
 >     completely ordered. In particular there is no ordering
 
 As shown above, there are more than 4 sequence points, in evaluating the 
 parameters of the parameters of the call. Furthermore, the existance of 
 parenthesis creates a need, I believe, for complete ordering, not the 
 partial ordering you suggest.
 
 >     completely ordered. In particular there is no ordering
 >     between the a.Wobble (30) call and the a.Wibble (5) call.
 
 Correct, in particular. But because they are contained in different layers 
 of parenthesis, there is a complete ordering in the code.
 
 I hope I understood what you meant correctly,
 -Brian Lindahl
 
 _________________________________________________________________
 Chat with friends online, try MSN Messenger: http://messenger.msn.com
 
Comment 4 Nathan Sidwell 2002-06-30 02:52:19 UTC
State-Changed-From-To: feedback->closed
State-Changed-Why: not a bug
Comment 5 Nathan Sidwell 2002-06-30 10:47:40 UTC
From: Nathan Sidwell <nathan@codesourcery.com>
To: Brian Lindahl <lindahlb@hotmail.com>
Cc: nathan@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-prs@gcc.gnu.org,
   nobody@gcc.gnu.org, unifex@yuidesigns.net, gcc-gnats@gcc.gnu.org
Subject: Re: c++/7135: Faulty Operator Precedence
Date: Sun, 30 Jun 2002 10:47:40 +0100

 Brian Lindahl wrote:
 > 
 > First of all, I disagree with your analysis. One fact alone should
 > contradict the analysis:
 > Inlining the methods changes the compiler output, and thus, the output
 > displayed on the screen.
 > 
 > I believe that, according to C++ semantics, inlining a function should not
 > change compiler output.
 all compiler optimizations are invariant on the abstract machined described
 by the std for well formed programs. But, I contend that your program
 is not well-formed, so a compiler assumption is broken, and hence optimizations
 may do anything.
 
 
 
 > In fact, I should have stated that the code should be equivalent to:
 > operator<<(
 >    operator<<(
 >       cout,
 >       A::get(
 >          &A::set(5, &a)
 >       )
 >    ),
 >    A::get(
 >       &A::set(30, &a)
 >    )
 > );
 > 
 > (Note the method, set, returns '*this' as a 'const A &')
 > 
 > >     There are 4 sequence points in that, each between
 > >     evaluating the parameters to a call, and the call itself.
 > >     These sequence points are partially ordered, but not
 > >     completely ordered. In particular there is no ordering
 > 
 > As shown above, there are more than 4 sequence points, in evaluating the
 > parameters of the parameters of the call. Furthermore, the existance of
 > parenthesis creates a need, I believe, for complete ordering, not the
 > partial ordering you suggest.
 no it does not. function parameters may be evaluated in any order. 
 the inner operator << call may be performed before or after the second
 a::get (a::set (30)) call. Hence the a::get (a::set ()) sequences
 are unordered wrt eachother.
 
 > Correct, in particular. But because they are contained in different layers
 > of parenthesis, there is a complete ordering in the code.
 no, you are incorrect. You cannot enforce evaluation ordering by
 adding parentheses. Anyway these parentheses are part of the function
 call syntax, and not the same as expression grouping parenthsese (and,
 more importantly), neither are those ','s comma operators.
 
 I am closing the PR.
 
 nathan
 
 -- 
 Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
          'But that's a lie.' - 'Yes it is. What's your point?'
 nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
Comment 6 Wolfgang Bangerth 2004-08-13 16:01:24 UTC
Reopening to mark as a duplicate of... 
Comment 7 Wolfgang Bangerth 2004-08-13 16:03:56 UTC
...PR 11751. 

*** This bug has been marked as a duplicate of 11751 ***