Bug 11633 - [DR 430] g++ does not initialize structures when auto-increment variables are used
Summary: [DR 430] g++ does not initialize structures when auto-increment variables are...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.3
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2003-07-22 20:53 UTC by Mike Simons
Modified: 2021-11-05 23:23 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work: 3.4.6, 4.0.4, 4.4.1, 4.5.0
Known to fail:
Last reconfirmed: 2009-03-03 21:46:06


Attachments
Sample program for structure initialization bug (151 bytes, text/plain)
2003-07-22 20:55 UTC, Mike Simons
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Mike Simons 2003-07-22 20:53:41 UTC
int count = 23;
int foo[] = { count++, count++, count++ };

results:
  foo == { 23, 23, 23 }, count == 26;

expected:
  foo == { 23, 24, 25 }, count == 26;

===
  Tested only on intel platform with g++.  on debian stable version 2.95.4 and a
on Redhat AS 2.1 with a self compiled version 3.3.

  With g++ 2.96 from Redhat AS 2.1, if foo is a global variable (not inside any
function scope), then foo is initialized correctly to different values.

  Attached to the bug is a simple test program... beta.cc

g++ -Wall -g -o beta beta.cc

gdb -q ./beta
===
(gdb) b main
Breakpoint 1 at 0x8048674: file beta.cc, line 21.
(gdb) r
Starting program: ./beta

Breakpoint 1, main () at beta.cc:21
21        static_func();
(gdb) p foo
$1 = {23, 24, 25}
(gdb) p zap
$2 = {26, 26, 26}
(gdb) s
static_func() () at beta.cc:8
8         static int bar[] = { value(), value(), value() };
(gdb) n
9         static int baz[] = { count++, count++, count++ };
(gdb) n
11        return bar[0] + baz[0];
(gdb) p bar
$3 = {29, 30, 31}
(gdb) p baz
$4 = {32, 32, 32}
===

  Notice that the function calls are handled correctly, but the count++ is not.

  I do not know the c++ standard, it is *possible* that the code above is
"undefined" by the standard and what g++ is doing is correct.  However, the same
code compiled with at least 5 commercial compilers on various platforms all
resulted in what I say is the "expected" result with different values.
Comment 1 Mike Simons 2003-07-22 20:55:00 UTC
Created attachment 4452 [details]
Sample program for structure initialization bug
Comment 2 Wolfgang Bangerth 2003-07-22 21:41:17 UTC
The question is whether commas in initializers are sequence points. I don't
know whether they are, though.

W.
Comment 3 Wolfgang Bangerth 2003-07-22 21:55:34 UTC
Hm, 8.5.1 is the normative part of the standard, but it doesn't say anything
about the order of evaluation. Nathan, language lawyers to the front?

W.
Comment 4 Mike Simons 2003-07-22 22:10:55 UTC
static int zap[] = { ++count-1, ++count-1, ++count-1 };

  static int baz[] = { ++count-1, ++count-1, ++count-1 };
===

Changing the code to the above... works around this problem in this sample.
Comment 5 Mike Simons 2003-07-22 23:19:57 UTC
  A friend pointed out language in the gcc.info file which appears to cover
the 'comma' ordering case:
===
   * Making side effects happen in the same order as in some other
     compiler.

     It is never safe to depend on the order of evaluation of side
     effects.  For example, a function call like this may very well
     behave differently from one compiler to another:

          void func (int, int);
          
          int i = 2;
          func (i++, i++);

     There is no guarantee (in either the C or the C++ standard language
     definitions) that the increments will be evaluated in any
     particular order.  Either increment might happen first.  `func'
     might get the arguments `2, 3', or it might get `3, 2', or even
     `2, 2'.
===

  I'm not sure if this applies here... and if it *does* apply it seems
inconsistant that things like: ++foo-1, ++foo-1 ... foo++ + 0, foo++ + 0 ...
and value(), value()... all get evaluated left to right, but foo++, foo++ value
gets looked up once, and gets somehow the increment happens N times.

  I am very interested in what the c++ language lawyers have to say about this 
sample.  If it is truely undefined I am *amazed* that practically all of the
remaining commercial unix, c++ compilers do it the same way.
Comment 6 Wolfgang Bangerth 2003-07-22 23:36:49 UTC
Commas separating function call arguments are not sequence points, so
  foo(x++, x++)
can really be evaluated in different ways. On the other hand, commas in
comma expressions as in 
  while (x++, x++)
_are_ sequence points, so the order of evaluation is defined. The only question
which I can't answer from the standard is whether commas in initializer expressions
are sequence points.

If the order of evaluation is undefined, then the fact that some compilers implement
one way of doing things is not a reason to rely on a feature. Likewise,
random changes to the code _may_ make the code do what you expect, but
the code still triggers undefined behavior and may break again with
the next compiler version. The only way around this is to make the code
use only well defined semantics.

W.
Comment 7 Mike Simons 2003-07-23 01:09:30 UTC
For the C language, in a draft of the C99 spec around section 6.7.8
"Initialization", it talks about initialization lists.
===
       [#23]  The  order  in which any side effects occur among the
       initialization list expressions is unspecified. (121)

    121 - In particular, the evaluation order need not be the  same
          as the order of subobject initialization.
===

  Perhaps someone with the c++ standard handy can find "initialization lists".

If the same holds true for the c++ standard, then I agree this is a code bug
not a compiler bug.  :(
Comment 8 Nathan Sidwell 2003-07-23 09:04:08 UTC
I beleive the code to be ill formed. Looking at 8.5.1 of the std does not
help. brace enclosed initializer lists can only be used for aggregates. 1.9
talks about sequence points and full-expression. The initializers in an
initializer list are not full-expressions, because they'r part of the initializer.

AFAICT, The comma symbol is only a sequence point when it is the comma-operator
(and does not resolve to an overloaded function!)

I suspect when designtated initializers are used in different C99 compilers,
you'll find the behaviour is not the same across all compilers.

The Defect list does not talk about this case, I will ask the committee.
I would be surprised if the intent is to be anything different from
C90/C99.

nathan
Comment 9 Andrew Pinski 2003-11-21 16:55:28 UTC
Lets confirm this and then ...
Comment 10 Andrew Pinski 2003-11-21 16:57:08 UTC
To suspend it while the issue is going in c++ standards committee.
Comment 11 Andrew Pinski 2004-04-30 01:13:37 UTC
The DR report is 430: <http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#430>.
Comment 12 Andrew Pinski 2004-04-30 17:25:13 UTC
Adding what I got in my email:
	From: 	  msimons@moria.simons-clan.com
	Subject: 	Re: [Bug c++/11633] [DR 430] g++ does not initialize structures when auto-increment 
variables are used
	Date: 	April 30, 2004 13:19:11 EDT
	To: 	  jsa@edg.com
	Cc: 	  msimons@simons-clan.com, pinskia@gcc.gnu.org

Steve Adamczyk wrote: 
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#430
I believe the standard is clear that each initializer expression in the
above is a full-expression (1.9 intro.execution/12-13; see also issue
392) and therefore there is a sequence point after each expression
(1.9  intro.execution/16). I agree that the standard does not seem to
dictate the order in which the expressions are evaluated, and perhaps
it should.

Does anyone know of a compiler that would not evaluate the expressions
left to right?

Steve,

  Actually there is one, that does not do left to right: gcc/C++.

  None of the post increment operations take effect until after the 
statement finishes.  So in the sample code gcc stores 23 into all 
positions in the array.

  The commercial vendor C++ compilers for AIX, Solaris, Tru64, HPUX
(parisc and ia64), and Windows, all do sequence points at each ','
in the initializer list.

  So I opened a bug report against gcc (#11633, link to bug below).

  Unfortunately if the C++ standard does not say one way or the other 
then gcc/C++ is unlikely to change.

On Fri, Apr 30, 2004 at 01:13:38AM -0000, pinskia at gcc dot gnu dot org wrote:
------- Additional Comments From pinskia at gcc dot gnu dot org  2004-04-30 01:13 -------
The DR report is 430: <http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#430>.

-- 
           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|g++ does not initialize     |[DR 430] g++ does not
                   |structures when auto-       |initialize structures when
                   |increment variables are used|auto-increment variables are
                   |                            |used


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11633

------- You are receiving this mail because: -------
You reported the bug, or are watching the reporter.
Comment 13 Jason Merrill 2009-03-03 21:46:06 UTC
DR 430 is resolved; this is a bug.
Comment 14 Jason Merrill 2010-01-09 12:29:47 UTC
I can reproduce this bug with 2.95, but not with 3.4 or later.  Closing as fixed.
Comment 15 Jackie Rosen 2014-02-16 10:01:43 UTC Comment hidden (spam)
Comment 16 Tim Turner 2021-11-05 23:18:20 UTC Comment hidden (spam)