From: "John Ratliff" <webmaster@technoplaza.net>
To: <gcc-help@gcc.gnu.org>
Subject: RE: C++ static integer class constants...
Date: Sun, 16 Oct 2005 19:45:00 -0000 [thread overview]
Message-ID: <20051016194500.Mva6l9I2eoJTBCxk7sG6M5f5zfrA1RaRo2G7FNLi6x4@z> (raw)
In-Reply-To: <20051016174434.GB3165@hymen>
I forgot to hit reply to all, but I wanted this to go to the list.
> After reading Ryan's post, I looked at the (draft) standard. It says:
>
> 4 If a static data member is of const integral or const enumeration
> type, its declaration in the class definition can specify a constant-
> initializer which shall be an integral constant expression
> (_expr.const_). In that case, the member can appear in integral con-
> stant expressions within its scope. The member shall still be defined
> in a namespace scope if it is used in the program and the namespace
> scope definition shall not contain an initializer.
>
> If I understand this correctly, even const static members need to have
> a definition somewhere. Maybe this is "needed" so that you may always
> take the address of such const static members.
>
> So the compiler is free to use the constant as if they were variables,
> if it needs to. Your code compiles OK if the line
>
> int offset = (redundant ? B : A);
>
> is replaced by
>
> if(redundant)
> offset = B;
> else
> offset = A;
>
> I don't know why, but it does work here.
This seems like a definite bug. The fact that it works in 3.4.2 and not in
3.3.3 seems like a probable bug to me, but I will ask this question in a
standard C++ newsgroup so that someone intimately familiar with the standard
can give me a definitive answer, but I still think g++ 3.3 is wrong and g++
3.4 is right.
If I were taking the address of the constant, sure, it would have to have
storage space and I wouldn't expect it any other way.
I was looking at the assembly generated by each compiler. There is a
striking difference. Here is foo::method(bool redundant) in x86 assembly
generated by mingw/g++ 3.4.2. I have commented the relevant sections.
-----------------------------------------------
.globl __ZNK3foo6methodEb
.def __ZNK3foo6methodEb; .scl 2; .type 32;
.endef
__ZNK3foo6methodEb:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
movl 12(%ebp), %eax
movb %al, -1(%ebp) ; move redundant (%al) to stack
cmpb $0, -1(%ebp) ; if redundant is false
je L12 ; goto L12
movl $8184, -16(%ebp) ; move 8184 (0x1FF8) into -16(%ebp) (aka
offset)
jmp L13 ; goto L13
L12:
movl $8, -16(%ebp) ; move 8 into offset
L13:
movl -16(%ebp), %eax ; return std::pair blah blah blah
movl %eax, -8(%ebp)
movl 8(%ebp), %eax
addl -8(%ebp), %eax
incl %eax
movzbl (%eax), %eax
movb %al, -11(%ebp)
leal -11(%ebp), %eax
movl %eax, 8(%esp)
movl 8(%ebp), %edx
movl -8(%ebp), %eax
movzbl (%eax,%edx), %eax
movb %al, -12(%ebp)
leal -12(%ebp), %eax
movl %eax, 4(%esp)
leal -10(%ebp), %eax
movl %eax, (%esp)
call __ZNSt4pairIhhEC1ERKhS2_
movzwl -10(%ebp), %eax
leave
ret
-----------------------------------------------
And here is g++ 3.3.3's assembly output. As you can see, it's not even
trying to use it as a constant. This is why storage space is required.
-----------------------------------------------
_ZNK3foo6methodEb:
.LFB1535:
pushl %ebp
.LCFI14:
movl %esp, %ebp
.LCFI15:
subl $24, %esp
.LCFI16:
movl 16(%ebp), %eax
movb %al, -1(%ebp) ; move al (redundant) to stack
cmpb $0, -1(%ebp) ; is redundant false?
je .L6 ; then jump to .L6
movl _ZN3foo1BE, %eax ; move B (storage space required) to eax
movl %eax, -16(%ebp) ; put eax on the stack
jmp .L7
.L6:
movl _ZN3foo1AE, %eax ; move A (storage space required) to eax
movl %eax, -16(%ebp) ; and put eax on the stack
.L7:
movl -16(%ebp), %eax ; ??? why is it moving it just to move it
back?
movl %eax, -8(%ebp) ; whatever, the rest is return std::pair
blah blah
subl $4, %esp
movl 12(%ebp), %eax
addl -8(%ebp), %eax
incl %eax
movb (%eax), %al
movb %al, -9(%ebp)
leal -9(%ebp), %eax
pushl %eax
movl 12(%ebp), %edx
movl -8(%ebp), %eax
movb (%eax,%edx), %al
movb %al, -10(%ebp)
leal -10(%ebp), %eax
pushl %eax
pushl 8(%ebp)
.LCFI17:
call _ZNSt4pairIhhEC1ERKhS2_
addl $16, %esp
movl 8(%ebp), %eax
leave
ret $4
-----------------------------------------------
If you replace the ternary operator with the if as you suggested, the
assembly looks more like the 3.4.2 version. This is why it compiles, and
makes it seem more and more like a bug. Clearly it's capable of doing what I
think it should do, but chooses not to when presented with the ternary
operator.
>
> So you need to define those constants somewhere, but the compiler may
> use the initializer in the class scope, if it is able to do so. For
> some reason, GCC couldn't use the initializer in the first case, so it
> is using the address of the constants. Go figure.
The assembly output and changing from ternary to if proves it can use the
initializer, but chooses not to.
Thanks,
--John Ratliff
next prev parent reply other threads:[~2005-10-16 19:45 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-10-16 15:26 Ryan Mansfield
2005-10-16 16:16 ` John Ratliff
2005-10-16 16:16 ` John Ratliff
2005-10-16 16:42 ` John Ratliff
2005-10-16 16:42 ` John Ratliff
[not found] ` <43528310.03f34613.6a05.0e40SMTPIN_ADDED@mx.gmail.com>
2005-10-16 17:43 ` Alex J. Dam
[not found] ` <4352a3b2.42389977.3b5e.60fdSMTPIN_ADDED@mx.gmail.com>
2005-10-16 19:29 ` Alex J. Dam
2005-10-16 19:53 ` John Ratliff
2005-10-16 19:53 ` John Ratliff
2005-10-16 19:45 ` John Ratliff
2005-10-16 19:45 ` John Ratliff [this message]
[not found] <0IOJ0024ULK8BF@emroute1.cind.ornl.gov>
2005-10-18 12:26 ` Ernest L. Williams Jr.
[not found] <87oe5pb5dp.fsf@totally-fudged-out-message-id>
2005-10-17 19:17 ` Florian Weimer
2005-10-18 6:19 ` John Ratliff
2005-10-18 6:19 ` John Ratliff
[not found] <200510160743.j9G7hVoa010304@inbound-smtp-1.corp.adobe.com>
2005-10-17 12:05 ` John Love-Jensen
2005-10-17 17:50 ` John Ratliff
2005-10-17 17:50 ` John Ratliff
[not found] ` <4353e481.0829b6d6.64bd.18a4SMTPIN_ADDED@mx.gmail.com>
2005-10-17 18:07 ` corey taylor
2005-10-17 20:04 ` John Ratliff
2005-10-17 20:04 ` John Ratliff
[not found] <20051016195314.7EFB824AEF5@lax-gw02.mroute.net>
2005-10-17 9:09 ` Nathan Sidwell
2005-10-17 19:21 ` Florian Weimer
[not found] <20051016200125.C061F13137C@arvo.suso.org>
2005-10-16 21:36 ` John Ratliff
2005-10-16 21:36 ` John Ratliff
[not found] <435202e6.3d759d8f.4550.fffff1e6SMTPIN_ADDED@mx.gmail.com>
2005-10-16 14:50 ` Alex J. Dam
2005-10-17 19:13 ` Florian Weimer
-- strict thread matches above, loose matches on Subject: below --
2005-10-16 7:35 John Ratliff
2005-10-16 7:35 John Ratliff
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20051016194500.Mva6l9I2eoJTBCxk7sG6M5f5zfrA1RaRo2G7FNLi6x4@z \
--to=webmaster@technoplaza.net \
--cc=gcc-help@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).