By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
428,742 Members | 1,570 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 428,742 IT Pros & Developers. It's quick & easy.

Bug in gcc4 initialisers suspected

P: n/a
Dear all,

I would like to confirm my suspicion of a compiler
bug in gcc4 for MacOSX. The code example below expects
that the initializer of 'v' sets all elements in
v.u.bytes[] to zero, as specified by the C99 standard:

"""21 If there are fewer initializers in a brace-enclosed
list than there are elements or members of an
aggregate, [...] the remainder of the aggregate shall
be initialized implicitly the same as objects that
have static storage duration."""
(ref: ANSI+ISO+IEC+8999-1999, 6.7.8 Initialization, p.127)

However, the code only works as expected on some platforms:

system cpu compiler result
------ --- -------- ------
SunOS-5.8 UltraSPARC-IIe gcc-2.95.3 returns OK
FreeBSD-4.11 Pentium2 gcc-2.95.4 returns OK
SunOS-5.8 UltraSPARC-IIi gcc-3.1.1 returns OK
Darwin-7.9.0 PowerPC-G4 gcc-3.3 returns OK
Linux-2.4.29 Celeron gcc-3.3.5 returns OK
FreeBSD-5.4 Pentium4 gcc-3.4.2 returns OK
Darwin-8.0.0 PowerPC-G4 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'
Darwin-8.0.0 PowerPC-G5 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'

Interestingly, removing the intermediate
level 'union u' makes the code pass.

The questions I'm seeking an answer to:
1. Is this a compiler bug or a display of undefined behaviour?
2. Is this gcc4-specific or only in combination with PowerPC?

Best regards,

Marcel
-- _ _
_| |_|_|
|_ |_ Marcel van Kervinck
|_| ma*****@bitpit.net

----------------------------------------------------------------
#include <assert.h>

typedef struct {
union {
unsigned char bytes[2];
} u;
} vector_t;

int main(void)
{
int i;
for (i=0; i<2; i++) {
vector_t v = {{{0,}}};
assert(v.u.bytes[1] == 0);
v.u.bytes[1]++;
}
}
----------------------------------------------------------------
Nov 14 '05 #1
Share this Question
Share on Google+
34 Replies


P: n/a
Marcel van Kervinck wrote:
Dear all,

I would like to confirm my suspicion of a compiler
bug in gcc4 for MacOSX. The code example below expects
that the initializer of 'v' sets all elements in
v.u.bytes[] to zero, as specified by the C99 standard:

"""21 If there are fewer initializers in a brace-enclosed
list than there are elements or members of an
aggregate, [...] the remainder of the aggregate shall
be initialized implicitly the same as objects that
have static storage duration."""
(ref: ANSI+ISO+IEC+8999-1999, 6.7.8 Initialization, p.127)

However, the code only works as expected on some platforms:

system cpu compiler result
------ --- -------- ------
SunOS-5.8 UltraSPARC-IIe gcc-2.95.3 returns OK
FreeBSD-4.11 Pentium2 gcc-2.95.4 returns OK
SunOS-5.8 UltraSPARC-IIi gcc-3.1.1 returns OK
Darwin-7.9.0 PowerPC-G4 gcc-3.3 returns OK
Linux-2.4.29 Celeron gcc-3.3.5 returns OK
FreeBSD-5.4 Pentium4 gcc-3.4.2 returns OK
Darwin-8.0.0 PowerPC-G4 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'
Darwin-8.0.0 PowerPC-G5 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'

Interestingly, removing the intermediate
level 'union u' makes the code pass.

The questions I'm seeking an answer to:
1. Is this a compiler bug or a display of undefined behaviour?
2. Is this gcc4-specific or only in combination with PowerPC?
The problem is that without your telling us how you invoke gcc,
we cannot tell.
Did you compile with "-std=c99 -pedantic"?
Did you check gcc.gnu.org/c99status.html?

Apart from that, gnu.gcc.help may be a better place to ask.

Cheers
Michael
Best regards,

Marcel
-- _ _
_| |_|_|
|_ |_ Marcel van Kervinck
|_| ma*****@bitpit.net

----------------------------------------------------------------
#include <assert.h>

typedef struct {
union {
unsigned char bytes[2];
} u;
} vector_t;

int main(void)
{
int i;
for (i=0; i<2; i++) {
vector_t v = {{{0,}}};
assert(v.u.bytes[1] == 0);
v.u.bytes[1]++;
}
}
----------------------------------------------------------------

--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 14 '05 #2

P: n/a
In comp.lang.c Michael Mair <Mi**********@invalid.invalid> wrote:
Marcel van Kervinck wrote:
I would like to confirm my suspicion of a compiler
bug in gcc4 for MacOSX. The code example below expects
that the initializer of 'v' sets all elements in
v.u.bytes[] to zero, as specified by the C99 standard: [snip]
Darwin-8.0.0 PowerPC-G4 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'
Darwin-8.0.0 PowerPC-G5 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'

Interestingly, removing the intermediate
level 'union u' makes the code pass.

The questions I'm seeking an answer to:
1. Is this a compiler bug or a display of undefined behaviour?
2. Is this gcc4-specific or only in combination with PowerPC? The problem is that without your telling us how you invoke gcc,
we cannot tell.
Did you compile with "-std=c99 -pedantic"?
Did you check gcc.gnu.org/c99status.html?


I don't see anything in the code which is C99 specific.

[snip]
#include <assert.h>

typedef struct {
union {
unsigned char bytes[2];
} u;
} vector_t;

int main(void)
{
int i;
for (i=0; i<2; i++) {
vector_t v = {{{0,}}};
assert(v.u.bytes[1] == 0);
v.u.bytes[1]++;
}
}


If the `assert' fails, then it's most probably a compiler bug.
But I am not an authority here (writing from clc).

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #3

P: n/a
S.Tobias wrote:
In comp.lang.c Michael Mair <Mi**********@invalid.invalid> wrote:
Marcel van Kervinck wrote:
I would like to confirm my suspicion of a compiler
bug in gcc4 for MacOSX. The code example below expects
that the initializer of 'v' sets all elements in
v.u.bytes[] to zero, as specified by the C99 standard:
[snip]

Darwin-8.0.0 PowerPC-G4 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'
Darwin-8.0.0 PowerPC-G5 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'

Interestingly, removing the intermediate
level 'union u' makes the code pass.

The questions I'm seeking an answer to:
1. Is this a compiler bug or a display of undefined behaviour?
2. Is this gcc4-specific or only in combination with PowerPC?
The problem is that without your telling us how you invoke gcc,
we cannot tell.
Did you compile with "-std=c99 -pedantic"?
Did you check gcc.gnu.org/c99status.html?

I don't see anything in the code which is C99 specific.


C89 requires either a return statement in main() or another
way of not running into the end of main() (e.g. exit() or
abort()). C99 allows you to fall off the end of main()...

So, given a "return 0;", the code could also be compiled with
"-std=c89 -pedantic" (or equivalently with "-ansi -pedantic"

Cheers
Michael
[snip]

#include <assert.h>

typedef struct {
union {
unsigned char bytes[2];
} u;
} vector_t;

int main(void)
{
int i;
for (i=0; i<2; i++) {
vector_t v = {{{0,}}};
assert(v.u.bytes[1] == 0);
v.u.bytes[1]++;
}
}

If the `assert' fails, then it's most probably a compiler bug.
But I am not an authority here (writing from clc).

--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 14 '05 #4

P: n/a
In comp.std.c Michael Mair <Mi**********@invalid.invalid> wrote:
S.Tobias wrote:
In comp.lang.c Michael Mair <Mi**********@invalid.invalid> wrote:
Marcel van Kervinck wrote:
I would like to confirm my suspicion of a compiler
bug in gcc4 for MacOSX. The code example below expects
that the initializer of 'v' sets all elements in
v.u.bytes[] to zero, as specified by the C99 standard:


[snip]

Darwin-8.0.0 PowerPC-G4 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'
Darwin-8.0.0 PowerPC-G5 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'

Interestingly, removing the intermediate
level 'union u' makes the code pass.

The questions I'm seeking an answer to:
1. Is this a compiler bug or a display of undefined behaviour?
2. Is this gcc4-specific or only in combination with PowerPC?


The problem is that without your telling us how you invoke gcc,
we cannot tell.
Did you compile with "-std=c99 -pedantic"?
Did you check gcc.gnu.org/c99status.html?

I don't see anything in the code which is C99 specific. C89 requires either a return statement in main() or another
way of not running into the end of main() (e.g. exit() or
abort()). C99 allows you to fall off the end of main()... So, given a "return 0;", the code could also be compiled with
"-std=c89 -pedantic" (or equivalently with "-ansi -pedantic"
Thanks for your response,

Please don't divert from the question, which is about the
failing assert on the initialized value.

The compiler settings are mostly irrelevant for reproducing,
but a good example would be simply gcc -o bug bug.c

C99 doesn't require an explicit return from the initial
invokation of main, as explained in page 13 of the standard:
"""reaching the } that terminates the
main function returns a value of 0"""

Thanks,

Marcel

#include <assert.h>

typedef struct {
union {
unsigned char bytes[2];
} u;
} vector_t;

int main(void)
{
int i;
for (i=0; i<2; i++) {
vector_t v = {{{0,}}};
assert(v.u.bytes[1] == 0);
v.u.bytes[1]++;
}
}

If the `assert' fails, then it's most probably a compiler bug.
But I am not an authority here (writing from clc).


--
E-Mail: Mine is an /at/ gmx /dot/ de address.

Nov 14 '05 #5

P: n/a
Marcel van Kervinck wrote:
In comp.std.c Michael Mair <Mi**********@invalid.invalid> wrote:
S.Tobias wrote:
In comp.lang.c Michael Mair <Mi**********@invalid.invalid> wrote:
Marcel van Kervinck wrote:
>I would like to confirm my suspicion of a compiler
>bug in gcc4 for MacOSX. The code example below expects
>that the initializer of 'v' sets all elements in
>v.u.bytes[] to zero, as specified by the C99 standard:

[snip]

>Darwin-8.0.0 PowerPC-G4 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'
>Darwin-8.0.0 PowerPC-G5 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'
>
>Interestingly, removing the intermediate
>level 'union u' makes the code pass.
>
>The questions I'm seeking an answer to:
>1. Is this a compiler bug or a display of undefined behaviour?
>2. Is this gcc4-specific or only in combination with PowerPC?
The problem is that without your telling us how you invoke gcc,
we cannot tell.
Did you compile with "-std=c99 -pedantic"?
Did you check gcc.gnu.org/c99status.html?
I don't see anything in the code which is C99 specific.
C89 requires either a return statement in main() or another
way of not running into the end of main() (e.g. exit() or
abort()). C99 allows you to fall off the end of main()...
So, given a "return 0;", the code could also be compiled with
"-std=c89 -pedantic" (or equivalently with "-ansi -pedantic"

Thanks for your response,

Please don't divert from the question, which is about the
failing assert on the initialized value.

The compiler settings are mostly irrelevant for reproducing,
but a good example would be simply gcc -o bug bug.c


This is wrong.
gcc has the default setting "-std=gnu89" which is neither C89
nor C99 and may do as GNU wants.
So, unless you can confirm that you compiled in C89 mode or the
C99-like mode _including_ "-pedantic", there is nothing to be
added.
If you compiled with what C99 you can get from gcc and the
C99 status page does not report some sort of error at
initialisation, then you have a bug. Otherwise, there may be
just some unspecified behaviour w.r.t. the GNU standard,
which in the case of your platform might be specified
just the other way round.
So, please, just _answer_ the two questions given above,
either for yourself, or here.
Once more: gnu.gcc.help may be a better place to ask.

Cheers
Michael
C99 doesn't require an explicit return from the initial
invokation of main, as explained in page 13 of the standard:
"""reaching the } that terminates the
main function returns a value of 0"""

Thanks,

Marcel
>#include <assert.h>
>
>typedef struct {
> union {
> unsigned char bytes[2];
> } u;
>} vector_t;
>
>int main(void)
>{
> int i;
> for (i=0; i<2; i++) {
> vector_t v = {{{0,}}};
> assert(v.u.bytes[1] == 0);
> v.u.bytes[1]++;
> }
>}
If the `assert' fails, then it's most probably a compiler bug.
But I am not an authority here (writing from clc).

--
E-Mail: Mine is an /at/ gmx /dot/ de address.

--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 14 '05 #6

P: n/a
Using the lcc-win32 compiler, the code works without any assertion failure
Using gcc-2.96 it works too
Using gcc 3.34it works.

So, it looks like a bug in that version of gcc
Nov 14 '05 #7

P: n/a
In article <42***********************@news.wanadoo.fr>,
ja***@jacob.remcomp.fr says...
Using the lcc-win32 compiler, the code works without any assertion failure
Using gcc-2.96 it works too
Using gcc 3.34it works.

So, it looks like a bug in that version of gcc


I just tried in on 10.4.1 Tiger w/gcc 4.0.0.
Using -std=c99 -pedantic it fails.
Adding return 0; and changing to -std=c89 also fails.

Is should be taken up with the gcc maintainers.

--
Randy Howard (2reply remove FOOBAR)
"If the evidence doesn't seem to fit a particular conspiracy theory,
just create a bigger conspiracy theory." --Robert D. Hicks
Nov 14 '05 #8

P: n/a
jacob navia wrote:
Using the lcc-win32 compiler, the code works without any assertion failure
Using gcc-2.96 it works too
Using gcc 3.34it works.

So, it looks like a bug in that version of gcc


Jacob, you have been around here long enough to know to quote sufficient
of the message you are replying to for people to see what you are
replying to. I don't know about Thunderbird 0.9 (though I would be
surprised if it was different), but the current version certainly helps
in this by quoting the material for you by default.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #9

P: n/a
In comp.lang.c Michael Mair <Mi**********@invalid.invalid> wrote:
Marcel van Kervinck wrote:
In comp.std.c Michael Mair <Mi**********@invalid.invalid> wrote:
S.Tobias wrote:
In comp.lang.c Michael Mair <Mi**********@invalid.invalid> wrote:The problem is that without your telling us how you invoke gcc,
>we cannot tell.
>Did you compile with "-std=c99 -pedantic"?
>Did you check gcc.gnu.org/c99status.html? I don't see anything in the code which is C99 specific. C89 requires either a return statement in main() or another
way of not running into the end of main() (e.g. exit() or
abort()). C99 allows you to fall off the end of main()...

I don't agree. In C89 you could "safely" fall-off the initial
`main', it's the termination status that was undefined (or,
perhaps, better to say "unspecified"), not the behaviour.

Please don't divert from the question, which is about the
failing assert on the initialized value.
He was merely replying to my remark, giving me a hint that
I might have missed. His answer was justified.
And diversions are one of the main features of clc, ISTM.

BTW, I compiled your program with como (both in C89 and C99 mode)
and had no warnings or failed assertions.
Once more: gnu.gcc.help may be a better place to ask.


I think so too.
C99 doesn't require an explicit return from the initial
invokation of main, as explained in page 13 of the standard:
"""reaching the } that terminates the
main function returns a value of 0"""


Not in C89, this appeared in C99.

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #10

P: n/a
In comp.lang.c S.Tobias <si***@famous.bedbug.pals.invalid> wrote:
I don't agree. In C89 you could "safely" fall-off the initial
`main', it's the termination status that was undefined (or,
perhaps, better to say "unspecified"), not the behaviour.


I forgot to add:
http://groups-beta.google.com/group/...e=source&hl=en

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #11

P: n/a
Flash Gordon wrote:
jacob navia wrote:
Using the lcc-win32 compiler, the code works without any assertion
failure
Using gcc-2.96 it works too
Using gcc 3.34it works.

So, it looks like a bug in that version of gcc

Jacob, you have been around here long enough to know to quote sufficient
of the message you are replying to for people to see what you are
replying to. I don't know about Thunderbird 0.9 (though I would be
surprised if it was different), but the current version certainly helps
in this by quoting the material for you by default.

Excuse me, I deleted the quote to make the message more concise and
avoid repeating. Bad idea.

I was answering to this thread:
Bug in gcc4 initialisers suspected

Dear all,

I would like to confirm my suspicion of a compiler
bug in gcc4 for MacOSX. The code example below expects
that the initializer of 'v' sets all elements in
v.u.bytes[] to zero, as specified by the C99 standard:

"""21 If there are fewer initializers in a brace-enclosed
list than there are elements or members of an
aggregate, [...] the remainder of the aggregate shall
be initialized implicitly the same as objects that
have static storage duration."""
(ref: ANSI+ISO+IEC+8999-1999, 6.7.8 Initialization, p.127)

However, the code only works as expected on some platforms:

system cpu compiler result
------ --- -------- ------
SunOS-5.8 UltraSPARC-IIe gcc-2.95.3 returns OK
FreeBSD-4.11 Pentium2 gcc-2.95.4 returns OK
SunOS-5.8 UltraSPARC-IIi gcc-3.1.1 returns OK
Darwin-7.9.0 PowerPC-G4 gcc-3.3 returns OK
Linux-2.4.29 Celeron gcc-3.3.5 returns OK
FreeBSD-5.4 Pentium4 gcc-3.4.2 returns OK
Darwin-8.0.0 PowerPC-G4 gcc-4.0.0 failed assertion `v.u.bytes[1]
== 0'
Darwin-8.0.0 PowerPC-G5 gcc-4.0.0 failed assertion `v.u.bytes[1]
== 0'

Interestingly, removing the intermediate
level 'union u' makes the code pass.

The questions I'm seeking an answer to:
1. Is this a compiler bug or a display of undefined behaviour?
2. Is this gcc4-specific or only in combination with PowerPC?

Best regards,

Marcel
-- _ _
_| |_|_|
|_ |_ Marcel van Kervinck
|_| ma*****@bitpit.net

----------------------------------------------------------------
#include <assert.h>

typedef struct {
union {
unsigned char bytes[2];
} u;
} vector_t;

int main(void)
{
int i;
for (i=0; i<2; i++) {
vector_t v = {{{0,}}};
assert(v.u.bytes[1] == 0);
v.u.bytes[1]++;
}
}
----------------------------------------------------------------
Nov 14 '05 #12

P: n/a
Marcel van Kervinck wrote:
....
The compiler settings are mostly irrelevant for reproducing,
but a good example would be simply gcc -o bug bug.c
The compiler settings are not irrelevant; whether or not this behavior
is a bug or a feature depends upon what standard it's being compared
against. With the options you've chosen, gcc makes no claims to conform
to any version of the C standard. The only thing that's relevant to the
question of whether the behavior is a bug or a feature is the
documentation of gcc itself, and the question is off-topic for a group

Your question can only be on-topic for this group if it the C standard
is relevant. That requires that you use the set of options that are
supposed to make gcc conform to the C standard (-std=C99 -pedantic).
C99 doesn't require an explicit return from the initial
invokation of main, as explained in page 13 of the standard:
"""reaching the } that terminates the
main function returns a value of 0"""


With the compiler options you've chose, what C99 requires is
irrelevant.

If you use the compiler options that make C99 the relevant standard,
and you still get assertion failures, then the compiler is failing to
conform to a standard its creators say its supposed to conform to, and
you should therefore file a bug report. If you can only reproduce the
problem in non-conforming mode, then you should check with the gcc
documentation to find out what is promised when using that set of
options.

Nov 14 '05 #13

P: n/a
In comp.lang.c ku****@wizard.net wrote:
If you use the compiler options that make C99 the relevant standard,
and you still get assertion failures, then the compiler is failing to
conform to a standard its creators say its supposed to conform to, and
you should therefore file a bug report.


Thank you very much,

The reason I cross-posted to comp.std.c is precisely because I
was wondering if I'd missed something in the standard that can
be an excuse for the failing assert. (Like a mis-interpretation
of 'aggregate' or missing some rules for unions.) This doesn't
seem to be the case, so I'll consider it a compiler bug now.

The program is failing with any gcc4 settings, including the
ones suggested by various posters (except -DNDEBUG=1, for the
hair-splitters :-) That is what I intended to say with
'irrelevant': the settings really don't make a difference so
I didn't like to be overspecific. I didn't want to say it is
unimportant to try. It is and I did. The outcome is that it
doesn't matter, so we can forget about it as a factor: It was
going to be either a bug in the compiler or in the program.
Given its nature (basic initalisation) it ought to be fixed
both in gcc-mode and in C99 mode.

I'ld like to express my thanks to the many people who had the
flexibility of mind to look through any ambiguity and made
an actual effort to look at the little program and the standard.
And also to those who took the time to test their compiler for
it, using any settings that they regarded as relevant, before
sharing their opinion.

A bug report is filed with both the vendor and the gcc team.

Follow-ups are best directed to the gnu groups.

Best regards,

Marcel
-- _ _
_| |_|_|
|_ |_ Marcel van Kervinck
|_| ma*****@bitpit.net
Nov 14 '05 #14

P: n/a
S.Tobias wrote:
In comp.lang.c S.Tobias <si***@famous.bedbug.pals.invalid> wrote:
I don't agree. In C89 you could "safely" fall-off the initial
`main', it's the termination status that was undefined (or,
perhaps, better to say "unspecified"), not the behaviour.


I forgot to add:
http://groups-beta.google.com/group/...e=source&hl=en


Thank you, I did not know that (in fact, the compilers I am usually
working with complain -- directly or indirectly -- about the missing
return statement when forced into standard mode).
Is this the consensus of comp.std.c or just an interpretation of the
scripture?

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 14 '05 #15

P: n/a
Michael Mair <Mi**********@invalid.invalid> writes:
S.Tobias wrote:
In comp.lang.c S.Tobias <si***@famous.bedbug.pals.invalid> wrote:
I don't agree. In C89 you could "safely" fall-off the initial
`main', it's the termination status that was undefined (or,
perhaps, better to say "unspecified"), not the behaviour.
[...]
Thank you, I did not know that (in fact, the compilers I am usually
working with complain -- directly or indirectly -- about the missing
return statement when forced into standard mode).
Is this the consensus of comp.std.c or just an interpretation of the
scripture?


C90 5.1.2.2.3:

A return from the initial call to the main function is equivalent
to calling the exit function with the value returned by the main
function as its argument. If the main function executes a return
that specifies no value, the termination status returned to the
host environment is undefined.

C90 6.6.6.4:

Reaching the } that terminates a function is equivalent to
executing a return statement without an expression.

C99 5.1.2.2.3:

If the return type of the main function is a type compatible with
int, a return from the initial call to the main function is
equivalent to calling the exit function with the value returned by
the main function as its argument; reaching the } that
terminates the main function returns a value of 0. If the return
type is not compatible with int, the termination status returned
to the host environment is unspecified.

Nevertheless, compilers are allowed to complain (issue diagnostics)
even when the behavior is well-defined.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #16

P: n/a
Keith Thompson wrote:
Michael Mair <Mi**********@invalid.invalid> writes:
S.Tobias wrote:
In comp.lang.c S.Tobias <si***@famous.bedbug.pals.invalid> wrote:
I don't agree. In C89 you could "safely" fall-off the initial
`main', it's the termination status that was undefined (or,
perhaps, better to say "unspecified"), not the behaviour.


[...]
Thank you, I did not know that (in fact, the compilers I am usually
working with complain -- directly or indirectly -- about the missing
return statement when forced into standard mode).
Is this the consensus of comp.std.c or just an interpretation of the
scripture?

C90 5.1.2.2.3:

A return from the initial call to the main function is equivalent
to calling the exit function with the value returned by the main
function as its argument. If the main function executes a return
that specifies no value, the termination status returned to the
host environment is undefined.

C90 6.6.6.4:

Reaching the } that terminates a function is equivalent to
executing a return statement without an expression.

C99 5.1.2.2.3:

If the return type of the main function is a type compatible with
int, a return from the initial call to the main function is
equivalent to calling the exit function with the value returned by
the main function as its argument; reaching the } that
terminates the main function returns a value of 0. If the return
type is not compatible with int, the termination status returned
to the host environment is unspecified.

Nevertheless, compilers are allowed to complain (issue diagnostics)
even when the behavior is well-defined.


Thank you very much :-)

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 14 '05 #17

P: n/a
Groovy hepcat Marcel van Kervinck was jivin' on 17 May 2005 15:37:00
GMT in comp.lang.c.
Bug in gcc4 initialisers suspected's a cool scene! Dig it!
I would like to confirm my suspicion of a compiler
bug in gcc4 for MacOSX. The code example below expects
that the initializer of 'v' sets all elements in
v.u.bytes[] to zero, as specified by the C99 standard:

"""21 If there are fewer initializers in a brace-enclosed
list than there are elements or members of an
aggregate, [...] the remainder of the aggregate shall
be initialized implicitly the same as objects that
have static storage duration."""
(ref: ANSI+ISO+IEC+8999-1999, 6.7.8 Initialization, p.127)

However, the code only works as expected on some platforms:
(Code moved here into the body of the post from the OP's sig block.
It's not a good idea to put the code in your sig block.)
#include <assert.h>

typedef struct {
union {
unsigned char bytes[2];
} u;
} vector_t;

int main(void)
{
int i;
for (i=0; i<2; i++) {
vector_t v = {{{0,}}};
assert(v.u.bytes[1] == 0);
v.u.bytes[1]++;
}
} system cpu compiler result
------ --- -------- ------
SunOS-5.8 UltraSPARC-IIe gcc-2.95.3 returns OK
FreeBSD-4.11 Pentium2 gcc-2.95.4 returns OK
SunOS-5.8 UltraSPARC-IIi gcc-3.1.1 returns OK
Darwin-7.9.0 PowerPC-G4 gcc-3.3 returns OK
Linux-2.4.29 Celeron gcc-3.3.5 returns OK
FreeBSD-5.4 Pentium4 gcc-3.4.2 returns OK
Darwin-8.0.0 PowerPC-G4 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'
Darwin-8.0.0 PowerPC-G5 gcc-4.0.0 failed assertion `v.u.bytes[1] == 0'

Interestingly, removing the intermediate
level 'union u' makes the code pass.
That's odd. Are you sure the compiler is handling the union
correctly? Try printing sizeof v.u and seeing whether this is what you
expect. Maybe the array is being treated as two union members instead
of one. If so, then it's a bug. Or maybe I'm way off base here.
The questions I'm seeking an answer to:
1. Is this a compiler bug or a display of undefined behaviour?
Looks like a bug to me. But there may have been some nuance I've
missed that makes this legal. I can't say for sure.
2. Is this gcc4-specific or only in combination with PowerPC?


I don't know. I don't have gcc4 or a PowerPC, so I can't test it
here.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
Nov 14 '05 #18

P: n/a
Groovy hepcat Marcel van Kervinck was jivin' on 18 May 2005 02:23:11
GMT in comp.lang.c.
Re: Bug in gcc4 initialisers suspected's a cool scene! Dig it!
In comp.std.c Michael Mair <Mi**********@invalid.invalid> wrote:
S.Tobias wrote:
In comp.lang.c Michael Mair <Mi**********@invalid.invalid> wrote:

Marcel van Kervinck wrote:

>I would like to confirm my suspicion of a compiler
>bug in gcc4 for MacOSX. The code example below expects
>that the initializer of 'v' sets all elements in
>v.u.bytes[] to zero, as specified by the C99 standard:

The problem is that without your telling us how you invoke gcc,
we cannot tell.
Did you compile with "-std=c99 -pedantic"?
Did you check gcc.gnu.org/c99status.html?

I don't see anything in the code which is C99 specific.
C89 requires either a return statement in main() or another
way of not running into the end of main() (e.g. exit() or
abort()). C99 allows you to fall off the end of main()...

So, given a "return 0;", the code could also be compiled with
"-std=c89 -pedantic" (or equivalently with "-ansi -pedantic"


The compiler settings are mostly irrelevant for reproducing,


They're not irrelevant here. We need to know that the compiler was
invoked in the strictest standard conforming mode.
but a good example would be simply gcc -o bug bug.c


Then you may be seeing behaviour relying on some kind of obscure
extention or something. Who knows? Invoke the compiler with -std=c99
-pedantic or -ansi -pedantic, as Michael already suggested, and then
tell us what happens.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
Nov 14 '05 #19

P: n/a
Marcel van Kervinck wrote:
Dear all,

I would like to confirm my suspicion of a compiler
bug in gcc4 for MacOSX. The code example below expects
that the initializer of 'v' sets all elements in
v.u.bytes[] to zero, as specified by the C99 standard:
(snip)
typedef struct {
union {
unsigned char bytes[2];
} u;
} vector_t;


It seems that none of the posts so far have mentioned the union.

As I understand, though I could be wrong, the standard sets the
value of the variable to zero, not just bytes. (The distinction
is important when using memset()).

As some variable types might have non-zero bit representation when
the value is zero, and a union could have more than one type of
variable, it seems slightly possible that the restriction is lifted
for unions. I might even wonder about using initializers when you
can't specify which of the union variables is being initialized.

Still, on most machines float, double, and pointers should initialize
with all bits zero, and most systems do just that.

Consider:

typedef struct {
union {
double d;
unsigned char bytes[2];
} u;
} vector_t;

int main(void)
{
int i;
for (i=0; i<2; i++) {
vector_t v = {{{1}}};
assert(v.u.bytes[0] == 1);
v.u.bytes[1]++;
}
}

-- glen

Nov 14 '05 #20

P: n/a
[Newsgroups restricted to c.l.c. only]

In comp.lang.c glen herrmannsfeldt <ga*@ugcs.caltech.edu> wrote:
Marcel van Kervinck wrote:
Dear all,

I would like to confirm my suspicion of a compiler
bug in gcc4 for MacOSX. The code example below expects
that the initializer of 'v' sets all elements in
v.u.bytes[] to zero, as specified by the C99 standard: (snip) typedef struct {
union {
unsigned char bytes[2];
} u;
} vector_t;

It seems that none of the posts so far have mentioned the union.
The question was about initialization of a (deeply) nested member.
As I understand, though I could be wrong, the standard sets the
value of the variable to zero, not just bytes. (The distinction
is important when using memset()).
I don't understand what you're trying to say. Everything is
about values, not bytes or representations.
As some variable types might have non-zero bit representation when
the value is zero, and a union could have more than one type of
variable, it seems slightly possible that the restriction is lifted
for unions.
Initializers of aggregates or unions always initialize (recursively and
in order) their members, not "union as a whole". The representation
of a union is that of the last stored to member, plus some unspecified
bytes of other members and padding.
I might even wonder about using initializers when you
can't specify which of the union variables is being initialized.
Initializer for a union always initializes the first member.
Still, on most machines float, double, and pointers should initialize
with all bits zero, and most systems do just that.
Maybe. Maybe not.
Consider: typedef struct {
union {
double d;
unsigned char bytes[2];
} u;
} vector_t; int main(void)
{
int i;
for (i=0; i<2; i++) {
vector_t v = {{{1}}}; v.u.d is initialized with `1'.
assert(v.u.bytes[0] == 1); This is unspecified, even if we know the representation of the `double' type.
v.u.bytes[1]++;
}
}

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #21

P: n/a
glen herrmannsfeldt wrote:
Marcel van Kervinck wrote:
I would like to confirm my suspicion of a compiler
bug in gcc4 for MacOSX. The code example below expects
that the initializer of 'v' sets all elements in
v.u.bytes[] to zero, as specified by the C99 standard: (snip)
typedef struct {
union {
unsigned char bytes[2];
} u;
} vector_t;

...
As I understand, though I could be wrong, the standard sets the
value of the variable to zero, not just bytes. (The distinction
is important when using memset()).


Default initialization gives zero values as if by assignment
(i.e. null pointer values for pointer types). There is a
requirement, spelled out in C99, that all-0 bits (including
padding) be a valid representation of zero for all integer
types. (Not for floating types or pointers, however.)
As some variable types might have non-zero bit representation when
the value is zero, and a union could have more than one type of
variable, it seems slightly possible that the restriction is lifted
for unions. I might even wonder about using initializers when you
can't specify which of the union variables is being initialized.


Default initialization applies to the first member of the
union. In C99 one can explicitly specify which member is
initialized, using a "designated initializer".
Nov 14 '05 #22

P: n/a
"Douglas A. Gwyn" <DA****@null.net> writes:
[...]
Default initialization gives zero values as if by assignment
(i.e. null pointer values for pointer types). There is a
requirement, spelled out in C99, that all-0 bits (including
padding) be a valid representation of zero for all integer
types. (Not for floating types or pointers, however.)


But it's still possible, I think, for some representation other than
all-bits-zero to be a valid representation of 0 for an integer type.
In other words (assuming the necessary #includes et al):

int all_bits_zero;
int numerically_zero;

memset(&all_bits_zero, 0, sizeof(int));
numerically_zero = 0;

The language requires (all_bits_zero == numerically_zero) to evaluate
to 1, but memcmp(&all_bits_zero, &numerically_zero, sizeof(int)) may
or may not return 0.

For the memcmp() to return a non-0 value, type int would have to have
padding bits, and one or more of them would have to be set to 1 by the
initialization. I wouldn't expect any system other than the DS9K to
actually behave this way.

Am I correct?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #23

P: n/a
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.org> wrote:
"Douglas A. Gwyn" <DA****@null.net> writes:
[...]
Default initialization gives zero values as if by assignment
(i.e. null pointer values for pointer types). There is a
requirement, spelled out in C99, that all-0 bits (including
padding) be a valid representation of zero for all integer
types. (Not for floating types or pointers, however.)


But it's still possible, I think, for some representation other than
all-bits-zero to be a valid representation of 0 for an integer type.
In other words (assuming the necessary #includes et al):

int all_bits_zero;
int numerically_zero;

memset(&all_bits_zero, 0, sizeof(int));
numerically_zero = 0;

The language requires (all_bits_zero == numerically_zero) to evaluate
to 1, but memcmp(&all_bits_zero, &numerically_zero, sizeof(int)) may
or may not return 0.

For the memcmp() to return a non-0 value, type int would have to have
padding bits, and one or more of them would have to be set to 1 by the
initialization. I wouldn't expect any system other than the DS9K to
actually behave this way.


I think there is one DSP made by Texas Instruments that uses 32 bit int,
and 40 bit longs, stored in 64 bits. Registers are 32 bits, but the
processor implements 40 bit operations which use pairs of registers
(seems some people want just a little bit more than 32 bit of precision,
with little extra cost).

Lets say I write

long x = 0x5311111153;

It seems possible that an optimising compiler would generate machine
code like

"load 0x11111153 into register reg0"
"store reg0 into lower 32 bit of x"
"store reg0 into higher 32 bit of x"

setting the padding bits in x to 0x111111. Unless the compiler actively
makes sure that the padding bits are always zero, I could imagine that
the padding bits become non-zero when storing zero. Maybe if I write

unsigned long long x = 0xffffff00_00000000;
unsigned long y = (unsigned long) x;

If x is not used after the assignment, the compiler could use the same
memory for x and y, and treat the cast as a no-op because all the
non-padding bits are unchanged. y equals 0, but memcmp would not return
0. (All assuming unsigned long is 40 bits + 24 padding bits).
Nov 14 '05 #24

P: n/a
Keith Thompson wrote:

"Douglas A. Gwyn" <DA****@null.net> writes:
[...]
Default initialization gives zero values as if by assignment
(i.e. null pointer values for pointer types). There is a
requirement, spelled out in C99, that all-0 bits (including
padding) be a valid representation of zero for all integer
types. (Not for floating types or pointers, however.)


But it's still possible, I think, for some representation other than
all-bits-zero to be a valid representation of 0 for an integer type.
In other words (assuming the necessary #includes et al):

int all_bits_zero;
int numerically_zero;

memset(&all_bits_zero, 0, sizeof(int));
numerically_zero = 0;

The language requires (all_bits_zero == numerically_zero) to evaluate
to 1, but memcmp(&all_bits_zero, &numerically_zero, sizeof(int)) may
or may not return 0.

For the memcmp() to return a non-0 value, type int would have to have
padding bits, and one or more of them would have to be set to 1 by the
initialization. I wouldn't expect any system other than the DS9K to
actually behave this way.

Am I correct?


If numerically_zero contains a bit pattern for negative zero,
it will compare equal to zero
and also have a different bit pattern from all_bits_zero.

--
pete
Nov 14 '05 #25

P: n/a
Christian Bau <ch***********@cbau.freeserve.co.uk> writes:
[...]
Maybe if I write

unsigned long long x = 0xffffff00_00000000;
unsigned long y = (unsigned long) x;

If x is not used after the assignment, the compiler could use the same
memory for x and y, and treat the cast as a no-op because all the
non-padding bits are unchanged. y equals 0, but memcmp would not return
0. (All assuming unsigned long is 40 bits + 24 padding bits).


More plausibly, if x is not used after the assignment, the whole thing
could be replaced by the equivalent of

unsigned long y = 0;

But if the initialization of x isn't constant, I suppose what you
describe might be possible.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #26

P: n/a
pete <pf*****@mindspring.com> writes:
[snip]
If numerically_zero contains a bit pattern for negative zero,
it will compare equal to zero
and also have a different bit pattern from all_bits_zero.


Is the integer constant 0 allowed to evaluate to negative zero?
(I'll check this later, when my copy of the standard is handy.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #27

P: n/a
Keith Thompson <ks***@mib.org> writes:
Is the integer constant 0 allowed to evaluate to negative zero?


No. C99 6.2.6.2:

3 If the implementation supports negative zeros, they shall be
generated only by:

- the &, |, ^, ~, <<, and >> operators with arguments that
produce such a value;

- the +, -, *, /, and % operators where one argument is a
negative zero and the result is zero;

- compound assignment operators based on the above cases.

--
"C has its problems, but a language designed from scratch would have some too,
and we know C's problems."
--Bjarne Stroustrup
Nov 14 '05 #28

P: n/a
Keith Thompson wrote:
But it's still possible, I think, for some representation other than
all-bits-zero to be a valid representation of 0 for an integer type.


Yes, in fact every ones-complement and every sign/magnitude
representation scheme provides two representations for the
value zero. Integer types (other than unsigned char) may
also contain "padding" bits that might be non-0. As a
rule, for a given type the value is uniquely determined by
the representation, but not vice versa.
Nov 14 '05 #29

P: n/a
Keith Thompson wrote:
Is the integer constant 0 allowed to evaluate to negative zero?


That doesn't make sense. The integer constant 0 has a value of 0.
Any integer "negative zero" representation also has a value of 0.
Nov 14 '05 #30

P: n/a
"Douglas A. Gwyn" <DA****@null.net> writes:
Keith Thompson wrote:
Is the integer constant 0 allowed to evaluate to negative zero?


That doesn't make sense. The integer constant 0 has a value of 0.
Any integer "negative zero" representation also has a value of 0.


Is it legal for the following:

int x;
x = 0;

to result in a "negative zero" representation being stored in x?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #31

P: n/a
Keith Thompson wrote:
"Douglas A. Gwyn" <DA****@null.net> writes:
Keith Thompson wrote:
Is the integer constant 0 allowed to evaluate to negative zero?


That doesn't make sense. The integer constant 0 has a value of 0.
Any integer "negative zero" representation also has a value of 0.


Is it legal for the following:

int x;
x = 0;

to result in a "negative zero" representation being stored in x?


No. Ben Pfaff has already (June 3) quoted the relevant clause:
6.2.6.2p3.

Nov 14 '05 #32

P: n/a
In comp.std.c Michael Mair <Mi**********@invalid.invalid> wrote:
The compiler settings are mostly irrelevant for reproducing,
but a good example would be simply gcc -o bug bug.c

This is wrong.
gcc has the default setting "-std=gnu89" which is neither C89
nor C99 and may do as GNU wants.
So, unless you can confirm that you compiled in C89 mode or the
C99-like mode _including_ "-pedantic", there is nothing to be
added.


Gcc may do what it wants with invalid programs.
My man pages say that a valid ISO C program should compile
properly without requiring -pedantic, -std or -ansi. (Expect
some rare exceptions that are not applicible here.)

And yes, also with your suggested flags the bug appeared.
No difference. The suggestion is still appreciated.

In the meantime the vendor simply went ahead and fixed
the problem. They reported to me today that in the Xcode
download of June 6 the problem is solved. I checked and
it is ok now. The gcc version is still the same (4.0.0),
so perhaps it was a bug in their build. Great response
from Apple!!

Best regards,

Marcel
>>#include <assert.h>
>>
>>typedef struct {
>> union {
>> unsigned char bytes[2];
>> } u;
>>} vector_t;
>>
>>int main(void)
>>{
>> int i;
>> for (i=0; i<2; i++) {
>> vector_t v = {{{0,}}};
>> assert(v.u.bytes[1] == 0);
>> v.u.bytes[1]++;
>> }
>>}

Nov 14 '05 #33

P: n/a
S.Tobias <si***@FamOuS.BedBuG.pAlS.INVALID> wrote:
>
> I would like to confirm my suspicion of a compiler
> bug in gcc4 for MacOSX. The code example below expects
> that the initializer of 'v' sets all elements in
> v.u.bytes[] to zero, as specified by the C99 standard: > typedef struct {
> union {
> unsigned char bytes[2];
> } u;
> } vector_t;
It seems that none of the posts so far have mentioned the union.
The question was about initialization of a (deeply) nested member.

For the record. The question mentioned that the union was 'relevant',
yes even essential, in producing the observed behavior. Read:
> Interestingly, removing the intermediate
> level 'union u' makes the code pass.

Nov 14 '05 #34

P: n/a
Marcel van Kervinck wrote:
In comp.std.c Michael Mair <Mi**********@invalid.invalid> wrote:
The compiler settings are mostly irrelevant for reproducing,
but a good example would be simply gcc -o bug bug.c This is wrong.
gcc has the default setting "-std=gnu89" which is neither C89
nor C99 and may do as GNU wants.
So, unless you can confirm that you compiled in C89 mode or the
C99-like mode _including_ "-pedantic", there is nothing to be
added.


Gcc may do what it wants with invalid programs.


Whether or not this program is invalid depends upon which standard
you're judging it against. Your first message on this group mentioned
the C99 standard, under which it is valid.
My man pages say that a valid ISO C program should compile
properly without requiring -pedantic, -std or -ansi. (Expect
some rare exceptions that are not applicible here.)


On the man page on our system, that comment is made only about
-pendantic; not about -std or -ansi. The -std=C99 option is essential
if your code makes any use of C99-specific features. Arguably, code
that uses those features might qualify as rare.

However, the statement about -pedantic is basically correct, and also
applies to -ansi. They are seldom needed to make a valid ISO C program
compile properly. Their primary purpose is to make sure than an invalid
ISO C program fails to compile, as it should.

Nov 14 '05 #35

This discussion thread is closed

Replies have been disabled for this discussion.