Bug 10591 - PCH breaks anonymous namespaces
Summary: PCH breaks anonymous namespaces
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.4.0
: P3 normal
Target Milestone: 4.2.0
Assignee: Geoff Keating
URL:
Keywords: visibility
: 21179 26895 29085 34309 (view as bug list)
Depends on:
Blocks:
 
Reported: 2003-05-01 23:26 UTC by Wolfgang Bangerth
Modified: 2007-12-08 20:29 UTC (History)
19 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2005-12-17 00:31:50


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Wolfgang Bangerth 2003-05-01 23:26:00 UTC
Members of anonymous namespaces are very much like static
variables/functions, except that they are given external
linkage but a name that is mangled in a way so as to
make them unique. This is not the case if it happens in
a header file that is then precompiled, subsequently
leading to linker errors due to duplicate symbols.

Example:

echo 'namespace { int i; }' > x.h
echo '#include "x.h"'       > a.cc
echo '#include "x.h"'       > b.cc
echo 'int main () {}'      >> b.cc

/home/bangerth/bin/gcc-3.4-pre/bin/c++ -c x.h
/home/bangerth/bin/gcc-3.4-pre/bin/c++ -c a.cc
/home/bangerth/bin/gcc-3.4-pre/bin/c++ -c b.cc
/home/bangerth/bin/gcc-3.4-pre/bin/c++ a.o b.o

b.o(.bss+0x0): multiple definition of `(anonymous namespace)::i'
a.o(.bss+0x0): first defined here
collect2: ld returned 1 exit status

The reason is the mangled name this variable is given:
g/x> nm a.o
00000000 B _ZN20_GLOBAL__N_x.huNZudc1iE
g/x> nm b.o
00000000 B _ZN20_GLOBAL__N_x.huNZudc1iE
00000000 T main

The standard says that they must be unique every time,
but obviously they are not.

This situation is a little unfortunate, since for example
boost uses such variables in anonymous namespaces in some
headers, meaning that one cannot use precompiled headers
in conjunction with boost.

W.

Release:
unknown

Environment:
present mainline (3.4)
Comment 1 Wolfgang Bangerth 2003-05-01 23:38:51 UTC
Responsible-Changed-From-To: unassigned->geoffk
Responsible-Changed-Why: Master of pch and author of a very much related patch for
    non-pch quite recently -- what a lucky coincidence :-)
Comment 2 Geoff Keating 2003-06-20 21:24:03 UTC
What we want to do with this is to stop giving anonymous namespace members
globally-visible names, and then we don't need to make their names unique.
Comment 3 Wolfgang Bangerth 2003-06-20 21:38:22 UTC
Subject: Re:  Members of anonymous namespaces get name mangled with header name

> What we want to do with this is to stop giving anonymous
> namespace members globally-visible names, and then we don't need to make
> their names unique.

Yes, except for the open question of how this would interfere with "export". 
Not that I care about this at the moment, but should be considered before a 
fix.

On the other hand, I care very much about this particular PR, since one cannot 
use PCH with BOOST at present :-( I am mostly neutral whether this is fixed 
by munging names of giving them internal linkage, as long as it's being 
fixed...

W.

-------------------------------------------------------------------------
Wolfgang Bangerth              email:            bangerth@ices.utexas.edu
                               www: http://www.ices.utexas.edu/~bangerth/

Comment 4 Geoff Keating 2003-06-20 23:02:44 UTC
Subject: Re:  Members of anonymous namespaces get name mangled with header name

> From: Wolfgang Bangerth <bangerth@ices.utexas.edu>
> Date: Fri, 20 Jun 2003 16:37:39 -0500

> > What we want to do with this is to stop giving anonymous
> > namespace members globally-visible names, and then we don't need to make
> > their names unique.
> 
> Yes, except for the open question of how this would interfere with "export". 
> Not that I care about this at the moment, but should be considered before a 
> fix.

I don't see how it could possibly interfere with the current export
non-implementation.  If export gets implemented in future, it'll
require some way to communicate information between translation units,
and while it's doing that it can also ensure that names are unique
(which will surely be one of the smallest problems that need to be
solved).

Comment 5 Wolfgang Bangerth 2003-06-20 23:08:50 UTC
Subject: Re:  Members of anonymous namespaces get name mangled with header name


> I don't see how it could possibly interfere with the current export
> non-implementation.  If export gets implemented in future, it'll
> require some way to communicate information between translation units,
> and while it's doing that it can also ensure that names are unique
> (which will surely be one of the smallest problems that need to be
> solved).

I totally agree. I don't see a problem there either. That was just one of the 
reasons I heard a while back when this topic was brought up before. (No, 
don't ask me when and where this was.) I'd favor going the way with internal 
linkage now, and think about the interaction with export when that is 
imminent. AFAIK, nobody ever even uttered he'd be interested in implementing 
export...

W.

-------------------------------------------------------------------------
Wolfgang Bangerth              email:            bangerth@ices.utexas.edu
                               www: http://www.ices.utexas.edu/~bangerth/

Comment 6 Kevin Atkinson 2004-02-03 19:14:11 UTC
A similar issue was brought up in the thread "Anonymous Namespaces" found
here http://gcc.gnu.org/ml/gcc/2004-01/msg02323.html and
http://gcc.gnu.org/ml/gcc/2004-02/msg00001.html .

The new unit-at-a-time optimizer is unable to optimize functions inside
anonymous namespaces namespace becuase they technically have external linkage.

The solution seams to be "to make the C++ front end not use (TREE_PUBLIC(x) ==
false) to mean a symbol with internal linkage.  Instead, a language-specific
decl flag ought to be allocated to mean exactly 'internal linkage',
and all local symbols ought to get TREE_PUBLIC false." according to Zack Weinberg.

I hope this will get fixed in time for Gcc 3.4.  I know nothing of Gcc internals
so I can't do it myself so I am hoping someone else will.
Comment 7 Lars Gullik Bjønnes 2004-08-18 16:05:26 UTC
Are there any plans to fix this for 3.5. f.ex.?
Comment 8 Andrew Pinski 2005-04-23 15:31:20 UTC
*** Bug 21179 has been marked as a duplicate of this bug. ***
Comment 9 Charles Pence 2005-08-01 02:24:03 UTC
Three months later, any movement on this bug?  How is the PCH code in the 4.0
branch?  PCH support would be a godsend to people supporting large C++ projects
on GCC.
Comment 10 Geoff Keating 2005-08-01 04:31:24 UTC
Subject: Re:  Members of anonymous namespaces should be 'static'


On 31/07/2005, at 7:24 PM, cpence at gmail dot com wrote:

> Three months later, any movement on this bug?  How is the PCH code  
> in the 4.0
> branch?  PCH support would be a godsend to people supporting large C 
> ++ projects
> on GCC.

There aren't any particular plans I know of to work on this bug,  
although I'd be happy to hear of some.  As far as I know PCH works  
fine in the 4.0 branch (but this bug isn't fixed).
Comment 11 Geoff Keating 2005-09-04 18:34:05 UTC
Although members of anonymous namespaces can be made 'static' on every target, they can all be given 
the same name on targets with weak symbol support, since on other targets the typeinfo is compared by 
name so different types must be given different names.
Comment 12 Benjamin Kosnik 2005-09-13 02:46:15 UTC

See:

http://gcc.gnu.org/ml/gcc-patches/2005-09/msg00772.html

This is a great idea. It would allow anonymous namespaces to be useful, and more
designs (at least g++ designs) could use them.

-benjamin
Comment 13 Geoff Keating 2006-03-09 00:35:31 UTC
*** Bug 25915 has been marked as a duplicate of this bug. ***
Comment 14 Geoff Keating 2006-03-09 00:37:05 UTC
This is the same original report as bug 25915, which then was generalised as follows:

Any entity which could be defined more than once (like a class or an inline
function) but whose token stream refers to a function or variable which is not
TREE_PUBLIC, actually can't be defined more than once, and so every part of
such entity can be made not-TREE_PUBLIC.

Exception: if the object referred to is 'const', is of scalar type, is
initialized with a constant expression, and the value but not the address of
the object is used, it doesn't count.  For additional details, including
additional cases where this applies and an explanation of how it applies to
templates, see [basic.def.odr] paragraph 5.
Comment 15 Geoff Keating 2006-03-09 00:44:28 UTC
Another case is when someone writes

struct a_struct __attribute__((visibility(hidden)));
void foo(a_struct &) { }

Even though "foo" is not marked hidden it should still be hidden, because it could be overloaded in a different shared object with a parameter which has type 'a_struct &' but is a different type.

This is especially important when 'func' is 'operator ==' or similar.
Comment 16 Geoff Keating 2006-03-09 00:48:54 UTC
Oops!  I got confused about visibility vs. TREE_PUBLIC.  I think it would be better to track the visibility stuff under a different bug.  The previous comment does apply when something is in an anonymous namespace, but it's only an optimisation, not required for correctness, since at the moment we give things in an anonymous namespace a random name to avoid exactly this kind of problem.
Comment 17 Geoff Keating 2006-03-09 00:53:37 UTC
I made 26612 to track the similar situation with visibility.
Comment 18 Jason Merrill 2006-03-21 18:22:54 UTC
I think the summary is misleading; the change requested is an optimization.  The testcase breaks because PCH breaks anonymous namespace naming so that it gets the same name in all translation units.  I assume that the same problem happens with other users of get_file_function_name.
Comment 19 Charles Pence 2006-03-21 19:12:47 UTC
@#18: I disagree.  This bug is the only thing preventing anonymous namespaces from working together with PCH.  As such, it's a bug, insofar as it keeps a _very_ worthwhile feature (namely, precompiling massive C++ headers like Boost) from working.
Comment 20 Jason Merrill 2006-03-21 19:19:34 UTC
Subject: Re:  use ODR rules to make C++ objects not be TREE_PUBLIC

Sorry I wasn't clear; I agree that this is an important bug.  I meant 
that fixing the unique anonymous namespace name in the presence of PCH 
is the right way to fix it.

Jason
Comment 21 Andrew Pinski 2006-03-28 03:06:06 UTC
*** Bug 26895 has been marked as a duplicate of this bug. ***
Comment 22 Jason Merrill 2006-04-05 22:26:24 UTC
The PCH problem with get_file_function_name is independent of the question of giving anonymous namespace members internal linkage.  We still need to give them distinct names; we are giving up on address comparison of type_infos because of problems with plugins.
Comment 23 Geoff Keating 2006-04-07 00:55:18 UTC
(In reply to comment #22)
> The PCH problem with get_file_function_name is independent of the question of
> giving anonymous namespace members internal linkage.  We still need to give
> them distinct names; we are giving up on address comparison of type_infos
> because of problems with plugins.

If you're giving up address comparison on type_info, you still have to find a way where two typeinfo objects with the same C++ name can be different, due to this example:

A shared object contains

class A { };
class B __attribute__((visibility("hidden"))) : class A { };
void f () { throw new B(); }

A main program contains:

class A { };
extern void f();
class B __attribute__((visibility("hidden"))) { int x; };  // not an A
int main() {
  try {
    f();
  } catch (B * p) {
    abort();
  } catch (A * p) {
    exit (0);
  }
  abort();
}

This program should not abort, because the 'B' in the main program is not the same as the 'B' in the dylib.

My suggestion would be to include &__dso_handle in the typeinfo for objects with hidden visibility, and also compare that.

Now, if you're doing this for visibility, you can also do it for anonymous namespaces.  Just find any address in the translation unit that contains the anonymous namespace (hey, how about the address of the typeinfo itself?), and consistently include that address in the typeinfo, and compare that.
Comment 24 Jason Merrill 2006-06-30 21:30:21 UTC
Did my recent visibility patch fix this?
Comment 25 Andrew Pinski 2006-07-05 03:01:49 UTC
Fixed for 4.2.0.
Comment 26 Andrew Pinski 2006-09-14 16:01:48 UTC
*** Bug 29085 has been marked as a duplicate of this bug. ***
Comment 27 Loban Rahman 2007-01-27 03:32:05 UTC
Would it be possible to backport this fix to the 4.1 tree? It would prove very, very useful.
Comment 28 Andrew Pinski 2007-12-08 20:29:04 UTC
*** Bug 34309 has been marked as a duplicate of this bug. ***