Getting rid of static initializers

52 views
Skip to first unread message

Taras Glek

unread,
Jun 16, 2010, 7:06:49 PM6/16/10
to Mike Hommey
Hi,
I believe we should move away from using static initializers in our
code. These run before main() executes, slowing down our startup. They
show up as backwards io on Linux, see:
http://blog.mozilla.com/tglek/2010/05/27/startup-backward-constructors/

Not only do they increase the cpu time for reaching main(), but they
also cause code to be paged in, that wouldn't otherwise be paged
in(slowdown cold startup). These also hurt other applications that
happen to link to libxul but not necessarily use most of it.

Mike Hommey posted some prototype patches for getting rid of the
majority of static initializers:
https://bugzilla.mozilla.org/show_bug.cgi?id=569629

It is pretty easily to automatically monitor tree against these, by
using readelf to measure the size of .ctors section on Linux.

I'm proposing that people look out for these during review and an
automated checker if any slip through.

Thoughts?
Taras

Boris Zbarsky

unread,
Jun 16, 2010, 11:02:34 PM6/16/10
to
On 6/16/10 7:06 PM, Taras Glek wrote:
> Mike Hommey posted some prototype patches for getting rid of the
> majority of static initializers:
> https://bugzilla.mozilla.org/show_bug.cgi?id=569629

So the replacement with functions for things that have a ctor introduces
one extra branch at each consumer, right? (Not saying that's
necessarily a problem; just want to understand the change.)

-Boris

Henri Sivonen

unread,
Jun 17, 2010, 2:50:04 AM6/17/10
to Taras Glek, Mike Hommey, dev-pl...@lists.mozilla.org
"Taras Glek" <tg...@mozilla.com> wrote:

> I believe we should move away from using static initializers in our
> code.

Just to make sure I understood:
This doesn't affect array initializers for static const arrays or C-style struct initializers for static const structs, right?

As for calls to C++ constructors in static initializers, banning those is already the second thing in the C++ Portability Guide right after the warning about templates:
https://developer.mozilla.org/en/C___Portability_Guide

--
Henri Sivonen
hsiv...@iki.fi
http://hsivonen.iki.fi/

Neil

unread,
Jun 17, 2010, 4:51:49 AM6/17/10
to
Henri Sivonen wrote:

>"Taras Glek" <tg...@mozilla.com> wrote:
>
>>I believe we should move away from using static initializers in our code.
>>
>>
>Just to make sure I understood:
>This doesn't affect array initializers for static const arrays or C-style struct initializers for static const structs, right?
>
>

Right; those are both POD types, so they're unaffected.

>As for calls to C++ constructors in static initializers, banning those is already the second thing in the C++ Portability Guide right after the warning about templates:
>https://developer.mozilla.org/en/C___Portability_Guide
>
>

Given this, the number of C++ static objects disappoints me somewhat. Do
these objects have destructors? That makes things even worse, I believe.

--
Warning: May contain traces of nuts.

Taras Glek

unread,
Jun 17, 2010, 1:26:16 PM6/17/10
to Henri Sivonen, Mike Hommey, dev-pl...@lists.mozilla.org
On 06/16/2010 11:50 PM, Henri Sivonen wrote:
> "Taras Glek"<tg...@mozilla.com> wrote:
>
>> I believe we should move away from using static initializers in our
>> code.
>
> Just to make sure I understood:
> This doesn't affect array initializers for static const arrays or C-style struct initializers for static const structs, right?

Yes.

>
> As for calls to C++ constructors in static initializers, banning those is already the second thing in the C++ Portability Guide right after the warning about templates:
> https://developer.mozilla.org/en/C___Portability_Guide

Great! Guess I wasn't the only person unaware of these.

Taras

Taras Glek

unread,
Jul 15, 2010, 3:01:30 PM7/15/10
to
On 06/16/2010 04:06 PM, Taras Glek wrote:
> Hi,
> I believe we should move away from using static initializers in our
> code. These run before main() executes, slowing down our startup. They
> show up as backwards io on Linux, see:
> http://blog.mozilla.com/tglek/2010/05/27/startup-backward-constructors/
>
> Not only do they increase the cpu time for reaching main(), but they
> also cause code to be paged in, that wouldn't otherwise be paged
> in(slowdown cold startup). These also hurt other applications that
> happen to link to libxul but not necessarily use most of it.
>
> Mike Hommey posted some prototype patches for getting rid of the
> majority of static initializers:
> https://bugzilla.mozilla.org/show_bug.cgi?id=569629
>
> It is pretty easily to automatically monitor tree against these, by
> using readelf to measure the size of .ctors section on Linux.

Filed https://bugzilla.mozilla.org/show_bug.cgi?id=579131 to get this
into our automated regression tracking.

Taras

Scott Meyers

unread,
Jul 19, 2010, 5:12:54 PM7/19/10
to

A quick glance through this list of portability guidelines suggests that it was
written at least 10 years ago. The revision history shows the last update as
being made in 2001, although the "Original Document Information" shows a last
update of 2007. I'm not sure how to interpret that.

Other than a general recognition that Mozilla must compile for a very large
number of platforms, I don't know what portability challenges Mozilla faces, but
as somebody who specializes in C++ and who routinely offers advice to teams
writing cross-platform C++ software, the C++ portability rules look like they
could use a serious re-evaluation. The standard for C++ has been stable for
some 13 years now, and what used to be common portability headaches have long
since been resolved by most compiler vendors. For example, the first rule ("Be
*very* careful when writing C++ templates"), aside from being so general as to
be essentially useless, is motivated by the behavior of templates as being of
dubious portability. That was a valid concern for many years, but it has been
almost as many years since the concern was alleviated for virtually everybody I
know. For example, the poster child compiler for bad template support on hosted
(i.e., non-embedded) systems (Visual C++) was upgraded to offer quite reasonable
template support in 2003.

Regarding the specific language feature at issue here (static initializers), I'd
be interested to know if any of the compilers used by Mozilla still generate bad
code for them. It's been a *long* time since I heard anybody complain about
this problem.

Again, I'm not familiar with the specific compilers Mozilla uses (is there a
list somewhere?), but my guess is that the vast majority of the advice in the
C++ portability guidelines is based on information at least a decade old.
Perhaps some of it is still valid, but my guess is that much is not. Given that
we're now on the cusp of the next version of C++ becoming available (C++0x), my
guess is that a reassessment of the C++ portability rules would be timely, anyway.

> Great! Guess I wasn't the only person unaware of these.

But note the different motivations. The portability guidelines warn against the
use of static constructors (by which they presumably mean the use of objects of
static storage duration that have non-trivial constructors), because they claim
that some compilers important to Mozilla generate bad code for them. Your
concern is quite different: that use of such constructors leads to performance
problems.

Scott

Boris Zbarsky

unread,
Jul 19, 2010, 5:31:57 PM7/19/10
to
On 7/19/10 5:12 PM, Scott Meyers wrote:
> A quick glance through this list of portability guidelines suggests that
> it was written at least 10 years ago. The revision history shows the
> last update as being made in 2001, although the "Original Document
> Information" shows a last update of 2007. I'm not sure how to interpret
> that.

People updating the document just haven't been updating the "revision
history" section.

As of this writing, the page says:

Page last modified 13:35, 20 Jun 2010 by rutsky

> Other than a general recognition that Mozilla must compile for a very
> large number of platforms, I don't know what portability challenges
> Mozilla faces, but as somebody who specializes in C++ and who routinely
> offers advice to teams writing cross-platform C++ software, the C++
> portability rules look like they could use a serious re-evaluation.

Yep. They've been undergoing that, in fact. The document may not be
fully up-to-date on that, though...

> Regarding the specific language feature at issue here (static
> initializers), I'd be interested to know if any of the compilers used by
> Mozilla still generate bad code for them. It's been a *long* time since
> I heard anybody complain about this problem.

See
http://blog.mozilla.com/tglek/2010/05/27/startup-backward-constructors/
for a complaint from about 2 months ago on a modern compiler... Though
if you mean "incorrect" by bad, then of course that's a separate issue.

> Again, I'm not familiar with the specific compilers Mozilla uses (is
> there a list somewhere?)

https://developer.mozilla.org/en/Supported_build_configurations

This doesn't list the gcc versions; we are currently using 4.2 on Mac
and I think 4.4 on Linux but trying to move to 4.5; we need to be able
to compile with some set of older versions, though. What set seems to
depend on what linux distros and such are stuck with.

-Boris

L. David Baron

unread,
Jul 19, 2010, 6:20:42 PM7/19/10
to dev-pl...@lists.mozilla.org
On Monday 2010-07-19 14:12 -0700, Scott Meyers wrote:
> Regarding the specific language feature at issue here (static
> initializers), I'd be interested to know if any of the compilers
> used by Mozilla still generate bad code for them. It's been a
> *long* time since I heard anybody complain about this problem.

Bad code being generated isn't the only reason they could be bad for
portability, though.

They are bad for portability because the order in which they
execute is undefined, and varies between platforms. This can lead
to bugs when code in file A has an API that assumes a static
constructor in that file has already run, and code in file B has a
static constructor that calls into the API in file A. If the static
constructor in B runs first, then the assumptions of the code in A
are violated.

A similar problem could happen with XPCOM components if a static
constructor calls into code that requires loading an XPCOM
component, whose loading in turn requires something from the
component in which the first constructor lives.

They are bad for portability because static constructors in shared
libraries are generally run while the system's shared library loader
is holding a lock, so any locking operations inside static
constructors have a risk of causing AB-BA deadlocks. However, the
exact set of operations with which they can cause deadlocks can vary
between platforms.

They're also, as noted in this thread, bad for startup performance.


(For the record, my memory is that the last compiler that had
trouble with them was gcc on OpenBSD; it's possible that the OpenBSD
folks had some piece of the stack disabled for security reasons --
perhaps sensible ones. But this was quite a few years ago --
perhaps 2002-ish?)

> Again, I'm not familiar with the specific compilers Mozilla uses (is
> there a list somewhere?), but my guess is that the vast majority of
> the advice in the C++ portability guidelines is based on information
> at least a decade old. Perhaps some of it is still valid, but my
> guess is that much is not. Given that we're now on the cusp of the
> next version of C++ becoming available (C++0x), my guess is that a
> reassessment of the C++ portability rules would be timely, anyway.

Some of it does need revision, yes. (I think I'll strike the
templates item and replace it with a reminder to use this-> when
invoking methods on a base class that is a template.) But I think a
large number of the rules are still valid.

-David

--
L. David Baron http://dbaron.org/
Mozilla Corporation http://www.mozilla.com/

Scott Meyers

unread,
Jul 19, 2010, 7:37:52 PM7/19/10
to
Boris Zbarsky wrote:
> See
> http://blog.mozilla.com/tglek/2010/05/27/startup-backward-constructors/
> for a complaint from about 2 months ago on a modern compiler... Though
> if you mean "incorrect" by bad, then of course that's a separate issue.

The portability guide specifically refers to compilers generating incorrect
code, i.e., code yielding behavior that does not conform to the C++98 standard,
so that's what I was referring to. I realize that "bad" was a poor choice of
term, since conformant code that runs slowly or makes poor use of machine
resources can certainly be called "bad." In this case, the portability guide
talks about correctness, so that's what I was limiting my comments to.

Regarding Taras' gcc modification to run initializers forward, I didn't look
into it enough to know whether it is conformant with the C++98 standard. The
order of construction of non-local statics within a single translation unit is
defined (top to bottom), so you can't reverse that order, but my impression is
that he's only reversing the initialization order of non-local statics in
different translation units, and that should be fine.

> This doesn't list the gcc versions; we are currently using 4.2 on Mac
> and I think 4.4 on Linux but trying to move to 4.5; we need to be able
> to compile with some set of older versions, though. What set seems to
> depend on what linux distros and such are stuck with.

Anything 4.x should be highly conformant to the C++98 standard and not pose
unusual portability headaches, to the best of my knowledge. It looks like
Mozilla uses MSVC under Windows, but the last three versions of that compiler
should, again, have few conformance problems.

Scott


Scott Meyers

unread,
Jul 19, 2010, 7:55:52 PM7/19/10
to
L. David Baron wrote:
> Bad code being generated isn't the only reason they could be bad for
> portability, though.

I agree, but it is the only justification given in the portability guide.

> They are bad for portability because the order in which they
> execute is undefined, and varies between platforms. This can lead
> to bugs when code in file A has an API that assumes a static
> constructor in that file has already run, and code in file B has a
> static constructor that calls into the API in file A. If the static
> constructor in B runs first, then the assumptions of the code in A
> are violated.

Yep, code like that is broken, i.e., yields undefined behavior. However, the
order in which non-local statics are initialized is not completely undefined,
it's only undefined when the non-local statics are in different translation
units. Not that that makes debugging such things any more fun :-)

> A similar problem could happen with XPCOM components if a static
> constructor calls into code that requires loading an XPCOM
> component, whose loading in turn requires something from the
> component in which the first constructor lives.

I don't know anything about XPCOM, so I can't help you here, sorry.

> They are bad for portability because static constructors in shared
> libraries are generally run while the system's shared library loader
> is holding a lock, so any locking operations inside static
> constructors have a risk of causing AB-BA deadlocks. However, the
> exact set of operations with which they can cause deadlocks can vary
> between platforms.
>
> They're also, as noted in this thread, bad for startup performance.

To be clear, I'm not advocating the use of non-local statics, I'm simply
questioning the justification given in the portability guide condemning their use.

> (For the record, my memory is that the last compiler that had
> trouble with them was gcc on OpenBSD; it's possible that the OpenBSD
> folks had some piece of the stack disabled for security reasons --
> perhaps sensible ones. But this was quite a few years ago --
> perhaps 2002-ish?)

This is consistent with my primary point: that the portability guidelines
should be reviewed to take the current state of technology into account.

Scott

Boris Zbarsky

unread,
Jul 19, 2010, 9:52:18 PM7/19/10
to
On 7/19/10 7:37 PM, Scott Meyers wrote:
>> This doesn't list the gcc versions; we are currently using 4.2 on Mac
>> and I think 4.4 on Linux but trying to move to 4.5; we need to be able
>> to compile with some set of older versions, though. What set seems to
>> depend on what linux distros and such are stuck with.
>
> Anything 4.x should be highly conformant to the C++98 standard and not
> pose unusual portability headaches

I should note that we had some serious portability headaches with
templates in gcc 4.0 (it would fail to compile perfectly valid code).
And I seem to recall the JS team running into that with 4.2 as well. So
we're not quite out of the woods yet. :(

-Boris

Scott Meyers

unread,
Jul 19, 2010, 10:51:12 PM7/19/10
to

Well, we'll never be completely out of the woods, if for no other reason than
they keep inventing new woods :-) But the fact that you've had serious problems
with gcc 4 compared to other compilers is both surprising and distressing.

Can you elaborate (or point me to places that do) on the kinds of problems
you've run into?

Thanks,

Scott

Boris Zbarsky

unread,
Jul 19, 2010, 11:19:06 PM7/19/10
to
On 7/19/10 10:51 PM, Scott Meyers wrote:
> Well, we'll never be completely out of the woods, if for no other reason
> than they keep inventing new woods :-) But the fact that you've had
> serious problems with gcc 4 compared to other compilers is both
> surprising and distressing.
>
> Can you elaborate (or point me to places that do) on the kinds of
> problems you've run into?

Sure. See https://bugzilla.mozilla.org/show_bug.cgi?id=486356#c13 for
example. The relevant code compiled with gcc 4.2 and msvc but not gcc 4.0.

-Boris

Scott Meyers

unread,
Jul 19, 2010, 11:48:24 PM7/19/10
to
Boris Zbarsky wrote:
> Sure. See https://bugzilla.mozilla.org/show_bug.cgi?id=486356#c13 for
> example. The relevant code compiled with gcc 4.2 and msvc but not gcc 4.0.

I can't see enough source code there to see what's going on, but if there's a
compilation discrepancy among gcc 4.0, 4.2, and msvc in code meant to be
production code, that would certainly qualify as a contemporary portability
headache.

Scott

L. David Baron

unread,
Jul 20, 2010, 12:35:09 AM7/20/10
to dev-pl...@lists.mozilla.org
On Monday 2010-07-19 20:48 -0700, Scott Meyers wrote:
> I can't see enough source code there to see what's going on, but if
> there's a compilation discrepancy among gcc 4.0, 4.2, and msvc in
> code meant to be production code, that would certainly qualify as a
> contemporary portability headache.

To see what sort of portability problems causing compilation errors
we're actually running into lately, I looked through a few sources:
* commits from @sun.com addresses back to January for Sun Studio issues
* commits with "bustage" back to start of March, skimming messages for
things that looked compiler-related.
* http://llvm.org/bugs/show_bug.cgi?id=5511 for clang issues

I'd note that this is biased towards things that actually ended up
in our repository. Anything complex is likely to be submitted to
the try server (which tests the patch on our build farm and unit
tests) before being pushed, so there's a bias against reporting
gcc/MSVC differences here, except for those in patches that people
thought were trivial enough to push without testing.

This list also doesn't list any portability issues other than
compilation errors, such as dependencies on undefined
order-of-evaluation behavior (which we've definitely had a few of)
or optimization bugs due to strict aliasing rules.

And I probably missed a good bit even within the time period I was
examining. However, it is some real data.


These are listed by the compiler that has the error, not the compiler
whose behavior is wrong (which in some cases I'm not sure of).

clang:
needs this-> in templates (I think it's right here and gcc+MSVC
are wrong):
https://bugzilla.mozilla.org/show_bug.cgi?id=573210
https://bugzilla.mozilla.org/show_bug.cgi?id=576363
https://bugzilla.mozilla.org/show_bug.cgi?id=579692
https://bugzilla.mozilla.org/show_bug.cgi?id=579786
https://bugzilla.mozilla.org/show_bug.cgi?id=579788

inline in C (but not C++):
http://code.google.com/p/webm/issues/detail?id=114

stricter about static_cast to incomplete types in templates:
https://bugzilla.mozilla.org/show_bug.cgi?id=576367

other name lookup issues in templates:
https://bugzilla.mozilla.org/show_bug.cgi?id=579686

not allowing return foo in functions returning void:
https://bugzilla.mozilla.org/show_bug.cgi?id=579689

gcc:
stricter about toplevel semicolons:
http://hg.mozilla.org/mozilla-central/rev/360f7ec9f2fe
http://hg.mozilla.org/mozilla-central/rev/30efe2f7e288
http://hg.mozilla.org/mozilla-central/rev/633756e2a580
http://hg.mozilla.org/mozilla-central/rev/6290189437fc
stricter about , at end of enum list:
http://hg.mozilla.org/mozilla-central/rev/2db1618de875
http://hg.mozilla.org/mozilla-central/rev/3a726b459ad3
requires () after sizeof:
http://hg.mozilla.org/mozilla-central/rev/2d0ad835761c

Sun Studio:
automatic conversions and ?: :
http://hg.mozilla.org/mozilla-central/rev/6c1fcdfdc2c8
http://hg.mozilla.org/mozilla-central/rev/57452ab7c299
http://hg.mozilla.org/mozilla-central/rev/431eab8cf6ab

sizeof arguments:
http://hg.mozilla.org/mozilla-central/rev/5b8da2154030

name mangling and typedefs:
http://hg.mozilla.org/mozilla-central/rev/4a598b0e35dc
http://hg.mozilla.org/mozilla-central/rev/5c9e056e348a

enums not allowing 64 bit values:
http://hg.mozilla.org/mozilla-central/rev/02d5f18da8b7

I skipped various linkage issues, including some due to portability
differences related to |inline|, which I consider an unavoidable
problem with the C/C++'s use of the preprocessor.

I noticed that I didn't run into:
* MSVC giving an error due to no return at the end of a function
returning non-void
* having to forward-declare and then declare-as-friends nested
classes for compilers that don't give nested classes access to
private members of parent class (per C++98 rather than C++03)
We used to hit both of these at decent frequency (the first was a
gcc vs. MSVC difference; the second was related to second-tier
compilers, perhaps older versions of Sun Studio, or maybe it was
IBM's compiler on AIX?)

Scott Meyers

unread,
Jul 21, 2010, 1:02:48 AM7/21/10
to
L. David Baron wrote:
> To see what sort of portability problems causing compilation errors
> we're actually running into lately, I looked through a few sources:

Thanks for taking the time to do this.

> These are listed by the compiler that has the error, not the compiler
> whose behavior is wrong (which in some cases I'm not sure of).

A lot of these don't give me enough information to see what is going on, but I
can figure enough out to see that one source of problems is invalid code that
compiles on some compilers and not on others. This, of course, is a portability
problem, but -- color me näive -- I was thinking only of valid code that some
compilers incorrectly reject. It had not occurred to me that a problem at least
as vexing in practice would be code that shouldn't compile at all but that some
compilers accept. Sigh. Thanks for the reality check.

Scott

Neil

unread,
Jul 21, 2010, 5:13:46 AM7/21/10
to
L. David Baron wrote:

>I noticed that I didn't run into:
>
>
> * MSVC giving an error due to no return at the end of a function
> returning non-void
> * having to forward-declare and then declare-as-friends nested
> classes for compilers that don't give nested classes access to
> private members of parent class (per C++98 rather than C++03)
>
>We used to hit both of these at decent frequency (the first was a gcc vs. MSVC difference; the second was related to second-tier compilers, perhaps older versions of Sun Studio, or maybe it was IBM's compiler on AIX?)
>

Visual C++ 6 didn't give nested classes access to private members of
parent classes.

Boris Zbarsky

unread,
Jul 21, 2010, 1:56:03 PM7/21/10
to
On 7/19/10 5:12 PM, Scott Meyers wrote:
> For example, the first rule ("Be *very* careful when
> writing C++ templates"), aside from being so general as to be
> essentially useless, is motivated by the behavior of templates as being
> of dubious portability. That was a valid concern for many years, but it
> has been almost as many years since the concern was alleviated for
> virtually everybody I know.

Well, sort of. We get things like
https://bugzilla.mozilla.org/show_bug.cgi?id=580590 every so often....

-Boris

Uli Link

unread,
Jul 21, 2010, 2:12:52 PM7/21/10
to
Scott Meyers schrieb:

C++ code compiling on GCC doesn't imply it's valid ANSI C++ even if
usually the GCC 4.x will compile standard conforming code.
C++ standard intentionally doesn't have var arg macros, although C99 has
them. Templates are the C++ way after the EoL of the last cfront
compilers 10 years ago.
So it's harder for a C/C++ compiler(better: preprocessor) to reject in
C++ mode when sharing the very same preprocessor.
Extensive use of __attribute__(visibility) is also a non-standard and
non-portable workaround for incorrect scoping of static inline.
There object formats other then ELF like COFF or XCOFF.

<https://bugzilla.mozilla.org/show_bug.cgi?id=526450> or
<https://bugzilla.mozilla.org/show_bug.cgi?id=526436#c1> for e.g.

The worst I saw was when trying to fix
<https://bugzilla.mozilla.org/show_bug.cgi?id=501924#c9>
a reinterpret cast of an only forward declared class hidden within a
macro hell, all static inline.
An alltime favourite for winning the most cryptic C++ contest ;-) even
if this may or may not be a compiler or maybe linker issue, as I cannot
really determine what code will be feed into the compiler stages 1 and
2... and the problem appears at link time :-( This isn't legacy code.

8 out of 10 porting bugs on AIX with IBM's XLC/C++ compiler are non-ANSI
code, the remaining 1 a compiler bug.

libffi only compiles with GCC (even if it is only C language...) used by
js/ctypes...

General porting issue: now I'm aware of 3 different locations where
machine/operating system specifics are capsuled. This should be reduced
to exactly one. And not a private implementation in every new source
dir. (atomic locks in nspr, js and chromium instead of using the nspr)

--
Uli Link
Porting Mozilla et al. to AIX for more than 6 years now.
<http://www.linkitup.de/ForAIX/Firefox>


Uli Link

unread,
Jul 21, 2010, 2:22:10 PM7/21/10
to
Boris Zbarsky schrieb:

Yeah... I always appreciate the work and bugs found by the Solaris team.
IBM's XLC/C++ is even more strict and the support from IBM is close to null.

--
Uli Link

Scott Meyers

unread,
Jul 21, 2010, 2:30:35 PM7/21/10
to
Uli Link wrote:
> C++ code compiling on GCC doesn't imply it's valid ANSI C++ even if
> usually the GCC 4.x will compile standard conforming code.

I agree, but it seems clear from looking through the bug reports that people are
checking in code that works on their compiler (often, but not always, gcc) under
the impression that the code is portable, even if in fact it's not valid
standard C++ code. This is always going to be a problem: nonstandard code is
pretty much by definition not portable.

> C++ standard intentionally doesn't have var arg macros, although C99 has
> them.

C++ has them, too, because C's <stdarg.h> is included as part of C++98. (Note
that this predates C99.)

> The worst I saw was when trying to fix
> <https://bugzilla.mozilla.org/show_bug.cgi?id=501924#c9>
> a reinterpret cast of an only forward declared class hidden within a
> macro hell, all static inline.

In all likelihood, the static inline wasn't the problem, it was the macro (or
macros). There's a reason C++ prefers consts and inlines to macros when both
will do (which isn't always the case).

> An alltime favourite for winning the most cryptic C++ contest ;-) even
> if this may or may not be a compiler or maybe linker issue, as I cannot
> really determine what code will be feed into the compiler stages 1 and
> 2... and the problem appears at link time :-( This isn't legacy code.

It sounds like it's just poorly written code, but of course it's easy to throw
stones without seeing the context.

Scott

Mike Shaver

unread,
Jul 21, 2010, 2:30:46 PM7/21/10
to Uli Link, dev-pl...@lists.mozilla.org
On Wed, Jul 21, 2010 at 2:22 PM, Uli Link <ul.mc...@linkitup.de> wrote:
> Boris Zbarsky schrieb:

>> Well, sort of. We get things like
>> https://bugzilla.mozilla.org/show_bug.cgi?id=580590 every so often....
>>
>> -Boris
>
> Yeah... I always appreciate the work and bugs found by the Solaris team.
> IBM's XLC/C++ is even more strict and the support from IBM is close to null.

Are you saying that the behaviour there (automatically including a C
file because the header contained templates) is a case of Sun Studio
simply being more strict? My interpretation was...less charitable.

Mike

Scott Meyers

unread,
Jul 21, 2010, 2:37:40 PM7/21/10
to
Boris Zbarsky wrote:
> Well, sort of. We get things like
> https://bugzilla.mozilla.org/show_bug.cgi?id=580590 every so often....

Ugh, this compiler behavior (assuming the bug report is describing it
accurately) is so broken, it hurts to read about it. My instinct would be to
look into disabling the default behavior, which (again if accurately described)
is just plain pathological.

On the other hand, I'd also check to see if the compiler really behaves as
described, because the description looks enough like what I believe we used to
call the exclusion model for template instantiation that I think it's possible
the person reporting the bug is seeing that and thinking he's seeing something else.

Scott

Zack Weinberg

unread,
Jul 21, 2010, 2:44:44 PM7/21/10
to Scott Meyers, dev-pl...@lists.mozilla.org
Scott Meyers <Neve...@aristeia.com> wrote:

> Uli Link wrote:
> > C++ standard intentionally doesn't have var arg macros, although
> > C99 has them.
>
> C++ has them, too, because C's <stdarg.h> is included as part of
> C++98. (Note that this predates C99.)

I think he's talking about

#define variadic(a, b, ...) something(a, b, __VA_ARGS__)

not about <stdarg.h>. Variadic macros are useful even in the presence
of templates, and have been adopted in C++1x (although still without
the comma-eater, sigh) but it's true that they're not in C++03.

zw

Scott Meyers

unread,
Jul 21, 2010, 2:54:56 PM7/21/10
to
Zack Weinberg wrote:
> I think he's talking about
>
> #define variadic(a, b, ...) something(a, b, __VA_ARGS__)
>
> not about <stdarg.h>. Variadic macros are useful even in the presence
> of templates, and have been adopted in C++1x (although still without
> the comma-eater, sigh) but it's true that they're not in C++03.

Ah, thanks for the clarification.

FWIW, the C++ community is generally trying to refer to the forthcoming revised
C++ standard as "C++0x", not "C++1x". Think of "C++0x" as a code name, not as
an indicator of when the standard will be adopted, even though that's how the
code name came about in the first place :-|

Scott

Uli Link

unread,
Jul 21, 2010, 2:57:22 PM7/21/10
to
Mike Shaver schrieb:

A static template class of template function in a.cpp is out of scope
outside a.cpp. Therefore moved to the common header. I've met a few
porting bugs where GCC obviously resolved to out of scope members.

I agree that the automatically enrollment of a .cpp is weird. But I
totally aggree avoiding globally compiler flags altering template
behaviour. This *will* have side effects.

--
Uli Link

Uli Link

unread,
Jul 21, 2010, 3:14:10 PM7/21/10
to
Zack Weinberg schrieb:

> Scott Meyers<Neve...@aristeia.com> wrote:
>> Uli Link wrote:
>>> C++ standard intentionally doesn't have var arg macros, although
>>> C99 has them.
>>
>> C++ has them, too, because C's<stdarg.h> is included as part of
>> C++98. (Note that this predates C99.)
>
> I think he's talking about
>
> #define variadic(a, b, ...) something(a, b, __VA_ARGS__)
>

Yes, THX :-)

Without 'b,' it will work when enabling a orthogonal language extension
flag.
<http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/index.jsp?topic=/com.ibm.vacpp7a.doc/language/ref/clrapxgpp.htm>

> not about<stdarg.h>. Variadic macros are useful even in the presence
> of templates, and have been adopted in C++1x (although still without
> the comma-eater, sigh) but it's true that they're not in C++03.

Therefore they should not be used without a *very good* reason.
If you have to read/understand macros not written today by yourself...

--
Uli Link

Boris Zbarsky

unread,
Jul 21, 2010, 3:35:02 PM7/21/10
to
On 7/21/10 2:37 PM, Scott Meyers wrote:
> On the other hand, I'd also check to see if the compiler really behaves
> as described, because the description looks enough like what I believe
> we used to call the exclusion model for template instantiation that I
> think it's possible the person reporting the bug is seeing that and
> thinking he's seeing something else.

The relevant compiler documentation is at
http://docs.sun.com/app/docs/doc/820-7599/6nirkt6ok?a=view

The bug seems to have described it correctly with one caveat; the
inclusion of the .cpp file only happens if the header contains template
declarations and not the corresponding template definitions.

-Boris

Uli Link

unread,
Jul 21, 2010, 3:47:57 PM7/21/10
to
Scott Meyers schrieb:

> Boris Zbarsky wrote:
>> Well, sort of. We get things like
>> https://bugzilla.mozilla.org/show_bug.cgi?id=580590 every so often....
>
> Ugh, this compiler behavior (assuming the bug report is describing it
> accurately) is so broken, it hurts to read about it. My instinct would
> be to look into disabling the default behavior, which (again if
> accurately described) is just plain pathological.

This is when compiler vendors are trying to emulate GCC behaviour for
developers convenience with legacy code *and* new C++0x features
together with significantly less developers in the compiler teams.
And the optimizer must support more complex CPU types.
And shorter life cycles.

--
Uli Link

Scott Meyers

unread,
Jul 21, 2010, 4:07:57 PM7/21/10
to
Boris Zbarsky wrote:
> The relevant compiler documentation is at
> http://docs.sun.com/app/docs/doc/820-7599/6nirkt6ok?a=view

This is pretty much what used to happen with the exclusion model, except the
search took place during linking, not compilation.

What's a little odd is this part of the bug report:

> But FilteringWrapper.cpp and XrayWrapper.cpp have static functions / variables,
> it will introduce multiple declaration.

There's nothing inherently wrong with this, but it does seem strange to have a
single source file with both template definitions as well as definitions for
(presumably) non-template statics. The root of the problem is that including
such a file into multiple TUs yields at most one copy of each template
instantiation, but multiple copies of each non-template static.

With the exclusion model, there'd be only one copy of everything, but Sun seems
to treat exclusion-model file organizations by default as inclusion-model file
organizations, and that leads to the problem identified in the bug report.

Scott

Scott Meyers

unread,
Jul 21, 2010, 6:07:40 PM7/21/10
to
Scott Meyers wrote:
> With the exclusion model, there'd be only one copy of everything

I realize now that this is probably wrong, because each time a new template
instantiation was required, the file would be processed again (as a new TU).
This suggests that Sun's approach yields the same semantics as the exclusion
model and that people putting non-templates in such files are the cause of the
problem. The only time there'd be a difference in semantics (between exclusion
model and what Sun does) would be for templates whose .h file is included
multiple times but which is instantiated for only a single set of template
arguments. Even then, the source file would constitute a bug waiting to happen.

Scott

Neil

unread,
Jul 22, 2010, 4:53:10 AM7/22/10
to
Uli Link wrote:

> The worst I saw was when trying to fix
> <https://bugzilla.mozilla.org/show_bug.cgi?id=501924#c9>
> a reinterpret cast of an only forward declared class hidden within a
> macro hell, all static inline.

I'm glad you got some benefit out of do_QueryObject. In fact it was
QueryAccessNode that motivated me to write do_QueryObject in the first
place.

Reply all
Reply to author
Forward
0 new messages