This is the mail archive of the
mailing list for the libstdc++ project.
Re: c++/6546: static const members optimization failure
- From: Gabriel Dos Reis <gdr at codesourcery dot com>
- To: Nathan Myers <ncm-nospam at cantrip dot org>
- Cc: libstdc++ at gcc dot gnu dot org, mmitchel at gcc dot gnu dot org
- Date: 06 Jul 2002 14:28:16 +0200
- Subject: Re: c++/6546: static const members optimization failure
- Organization: CodeSourcery, LLC
- References: <email@example.com> <20020628001724.B23519@mta.itasoftware.com> <firstname.lastname@example.org> <20020629043156.A8525@cantrip.org> <email@example.com> <20020701191214.A39845@cantrip.org>
Nathan Myers <firstname.lastname@example.org> writes:
| > | The context is an inline
| > | function expanded in a context that doesn't need an lvalue.
| > No. Firstly the declaration of std::min is this:
| > template<typename T> inline const T& min(const T&, const T&)
| > which clearly expects an lvalue (when an lvalue is not provided, a
| > temporary is created to hold the rvalue in order to satisfy that
| > requirement, but you already knew that).
| > Therefore at the point of function call, foo::bar has to be defined --
| > it is the compiler job to generate code in order to meet that
| > requirement.
| False. It is the compiler's job to enforce semantic requirements, and
| (separately) to generate code that implements the required computation.
| The distinction matters, as will be seen.
One of the key point you're missing here is that the compiler is free
to generate code to enforce semantics requirements.
| > Inlining appears later. But inlining doesn't mean that the semantics
| > restrictions can be violated. Inlining isn't macro substitution.
| > After inlining, the compiler can do constant propagation and replace
| > foo::bar with its manifest value. But that doesn't invalidate previous
| > semantics restrictions.
| Here is where you neglect the first key fact. Optimization is allowed
| to crush out abstraction overhead.
Yes, but optimization is not allowed to transmute program semantics,
that is what I was talking about. And it is appearant in the above
quote that I'm not missing the role of optimization which is to reduce
Reducing abstraction penalty does not mean (for the compiler) that it
should neglect the semantics requirements.
| Demanding an lvalue is detectable
| solely in the linkage behavior;
| there is no way for a program to
| cause a different function to be executed based on whether the lvalue
| is used as one.
The program you posted just did that. And I gave an explanation of
what was going on.
| > | In fact, in gcc-2.95, the memory references were optimized away
| > | just fine. The compiler was entirely justified in eliding the
| > | memory references.
| > The compiler can elide memory reference, but requiring foo::bar to be
| > defined is also a requirement of the language definition. The fact
| > that it failed to do so was a bug.
| Here is the second place where Gaby neglected a key fact, leading
| to a wrong conclusion. In fact, the standard does *not* require
| that an implementation report that foo::bar is not defined.
Before the language got changed (thus in the GCC-2.95 era) it said:
9.4.2 - Static data members [class.static.data]
-4- ... the member can appear in integral constant 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.
Here the standard is explicit. A definition for foo::bar is required,
and since the standard does not say "no diagnostic is required", the
compiler has to enforce the semantics restrictions. And GCC-2.95 was
And the standard was unnecessarily picky. Then the language got
changed to require definition only if foo::bar's address is taken,
which is what your program is doing.
-5- There shall be exactly one definition of a static data member that
is used in a program; no diagnostic is required; see basic.def.odr. ...
I interepret this rule as a latitude for not diagnosing *multiple*
definitions. [basic.def.ord] says in it first paragraph:
No translation unit shall contain more than one definition of any
variable, function, class type, enumeration type or template.
| Some background is needed to understand how that came about.
You story is interesting, but I don't think it is relevant here; and
actually I did know about it.
Finally, it you do really feel strongly about this, please submit a
patch (I realize that this list is not the right one to conduct this