This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Inconsistencies in "#pragma interface" and "extern template" (fwd)
- To: gcc-bugs at gcc dot gnu dot org
- Subject: Inconsistencies in "#pragma interface" and "extern template" (fwd)
- From: "Todd Vierling" <tvpobox at hotmail dot com>
- Date: Mon, 31 Jan 2000 13:10:09 EST
- Reply-To: tv at pobox dot com
ATTENTION CYGNUS ADMINS: I had to resend this thing from Hotmail because
the gcc.gnu.org mail server, egcs.cygnus.com, is using ORBS's dain-bramaged
RBL, which includes not only cable and DSL addresses [my server is on
cable], but my cable provider's SMTP relay[!]. Could you please use
something more sane, like MAPS's RBL? After all, ezmlm enforces list
membership in order to post at all....
*************************
...Please make sure all replies do go to the list (even if you Cc: to me).
The following test case, making use of the GNU C extensions "#pragma
interface" and "extern template", has some interesting results on 2.95.2
which are quite inconsistent with previous egcs and gcc releases (and even
with gcc 2.95.2 on different platforms). Is this change accidental or
otherwise?
Preface note [because I've received this response before]: The problem is
/not/ solved where the symbols are weak or the code is dumped into extra
".text$foo..." sections. Some platforms, including NetBSD/i386 1.4.1 here,
use object formats that are capable of neither specially-named text sections
nor ".linkonce" attributes. On those platforms, even with a weak symbol,
the executable still ends up with multiple copies of the code.
********** x.h **********
#ifndef X_H
#define X_H
#pragma interface "x.h"
class foo
{
public:
foo() {}
virtual ~foo() {}
};
template <class X>
class bar : public foo
{
public:
bar() {}
virtual ~bar() {}
};
template <class X>
class baz : public bar<X>
{
public:
baz() {}
virtual int getint() { return -42; }
};
#ifdef EXT_CLASS
__extension__ extern template class bar<int>;
__extension__ extern template class baz<int>;
#endif
#ifdef EXT_FUNC
__extension__ extern template int baz<int>::getfoo();
#endif
#endif
********** x.cc **********
#include "x.h"
int main(void)
{
return baz<int>().getint();
}
**************************
Here, I list all the symbols related to "foo", "bar", and "baz" for
different configurations (output of "nm -Cg x.o | egrep 'foo|ba[rz]'"). The
top configuration shows the results I expected, which correspond to historic
gcc behavior, and seem to be the same on all platforms I've tried, with gcc
2.[78].x or egcs 1.[01].x.
##
## Cygwin b20.1, "gcc version egcs-2.91.57 19980901 (egcs-1.1 release)"
[Cygnus]
## NetBSD/i386 1.4.1, "gcc version egcs-2.91.60 19981201 (egcs-1.1.1
release)" [*]
##
## [*] Same results, with weak (W) symbols instead of (T)ext or (D)ata
##
## compiled with "c++ -O0 -c x.cc"
U foo::~foo(void)
00000000 T bar<int>::~bar(void)
00000000 T baz<int>::~baz(void)
U foo::foo(void)
00000000 T bar<int>::bar(void)
00000000 T baz<int>::baz(void)
U foo type_info function
00000000 T bar<int> type_info function
00000000 T baz<int> type_info function
U foo type_info node
00000010 C bar<int> type_info node
00000010 C baz<int> type_info node
00000000 D bar<int> virtual table
00000000 D baz<int> virtual table
00000000 T baz<int>::getfoo(void)
##
## compiled with "c++ -O0 -DEXT_CLASS -c x.cc"
U baz<int>::~baz(void)
U baz<int>::baz(void)
U baz<int>::getfoo(void)
##
## compiled with "c++ -O0 -DEXT_FUNC -c x.cc"
U foo::~foo(void)
00000000 T bar<int>::~bar(void)
00000000 T baz<int>::~baz(void)
U foo::foo(void)
00000000 T bar<int>::bar(void)
00000000 T baz<int>::baz(void)
U foo type_info function
00000000 T bar<int> type_info function
00000000 T baz<int> type_info function
U foo type_info node
00000010 C bar<int> type_info node
00000010 C baz<int> type_info node
00000000 D bar<int> virtual table
00000000 D baz<int> virtual table
U baz<int>::getfoo(void)
##
## compiled with "c++ -O0 -DEXT_CLASS -DEXT_FUNC -c x.cc"
U baz<int>::~baz(void)
U baz<int>::baz(void)
U baz<int>::getfoo(void)
##
##########
Now, here's the odd results.
##
## Cygwin b20.1, "gcc version 2.95.2 19991024 (release)" (Mumit Khan)
##
## [*] Compiler did not honor "#pragma interface" (all four tests)
##
## [**] Though the compiler externalized the type_info, vtable, and
## implicit destructor via "extern template class", this method was
## instantiated locally anyway.
##
## compiled with "c++ -O0 -c x.cc"
00000000 T foo::~foo(void) [*]
00000000 T bar<int>::~bar(void)
00000000 T baz<int>::~baz(void)
00000000 T foo::foo(void) [*]
00000000 T bar<int>::bar(void)
00000000 T baz<int>::baz(void)
00000000 T foo type_info function [*]
00000000 T bar<int> type_info function
00000000 T baz<int> type_info function
00000010 C foo type_info node [*]
00000010 C bar<int> type_info node
00000010 C baz<int> type_info node
00000000 D foo virtual table [*]
00000000 D bar<int> virtual table
00000000 D baz<int> virtual table
00000000 T baz<int>::getfoo(void)
##
## compiled with "c++ -O0 -DEXT_CLASS -c x.cc"
00000000 T foo::~foo(void)
00000000 T bar<int>::~bar(void) [**]
U baz<int>::~baz(void)
00000000 T foo::foo(void)
00000000 T bar<int>::bar(void) [**]
00000000 T baz<int>::baz(void) [**]
00000000 T foo type_info function
00000010 C foo type_info node
00000000 D foo virtual table
U bar<int> virtual table
U baz<int> virtual table
00000000 T baz<int>::getfoo(void) [**]
##
## compiled with "c++ -O0 -DEXT_FUNC -c x.cc"
00000000 T foo::~foo(void)
00000000 T bar<int>::~bar(void)
00000000 T baz<int>::~baz(void)
00000000 T foo::foo(void)
00000000 T bar<int>::bar(void)
00000000 T baz<int>::baz(void)
00000000 T foo type_info function
00000000 T bar<int> type_info function
00000000 T baz<int> type_info function
00000010 C foo type_info node
00000010 C bar<int> type_info node
00000010 C baz<int> type_info node
00000000 D foo virtual table
00000000 D bar<int> virtual table
00000000 D baz<int> virtual table
U baz<int>::getfoo(void)
##
## compiled with "c++ -O0 -DEXT_CLASS -DEXT_FUNC -c x.cc"
00000000 T foo::~foo(void)
00000000 T bar<int>::~bar(void) [**]
U baz<int>::~baz(void)
00000000 T foo::foo(void)
00000000 T bar<int>::bar(void) [**]
00000000 T baz<int>::baz(void) [**]
00000000 T foo type_info function
00000010 C foo type_info node
00000000 D foo virtual table
U bar<int> virtual table
U baz<int> virtual table
U baz<int>::getfoo(void)
##
## NetBSD/i386, "gcc version 2.95.2 19991024 (release)"
##
## [*] Though the compiler externalized the type_info, vtable, and
## implicit destructor via "extern template class", this method was
## instantiated locally anyway.
##
## compiled with "c++ -O0 -c x.cc"
U foo::~foo(void)
0000034c W bar<int>::~bar(void)
0000011c W baz<int>::~baz(void)
U foo::foo(void)
00000260 W bar<int>::bar(void)
00000140 W baz<int>::baz(void)
U foo type_info function
00000094 W bar<int> type_info function
000000e0 W baz<int> type_info function
U foo type_info node
0000000c C bar<int> type_info node
0000000c C baz<int> type_info node
00000378 W bar<int> virtual table
00000240 W baz<int> virtual table
0000022c W baz<int>::getfoo(void)
##
## compiled with "c++ -O0 -DEXT_CLASS -c x.cc"
U foo::~foo(void)
0000026c W bar<int>::~bar(void) [*]
U baz<int>::~baz(void)
U foo::foo(void)
00000180 W bar<int>::bar(void) [*]
0000008c W baz<int>::baz(void) [*]
U bar<int> virtual table
U baz<int> virtual table
0000016c W baz<int>::getfoo(void) [*]
##
## compiled with "c++ -O0 -DEXT_FUNC -c x.cc"
U foo::~foo(void)
0000034c W bar<int>::~bar(void)
0000011c W baz<int>::~baz(void)
U foo::foo(void)
00000260 W bar<int>::bar(void)
00000140 W baz<int>::baz(void)
U foo type_info function
00000094 W bar<int> type_info function
000000e0 W baz<int> type_info function
U foo type_info node
0000000c C bar<int> type_info node
0000000c C baz<int> type_info node
00000378 W bar<int> virtual table
00000240 W baz<int> virtual table
U baz<int>::getfoo(void)
##
## compiled with "c++ -O0 -DEXT_CLASS -DEXT_FUNC -c x.cc"
U foo::~foo(void)
0000024c W bar<int>::~bar(void) [*]
U baz<int>::~baz(void)
U foo::foo(void)
0000016c W bar<int>::bar(void) [*]
0000008c W baz<int>::baz(void) [*]
U bar<int> virtual table
U baz<int> virtual table
U baz<int>::getfoo(void)
##
--
-- Todd Vierling (tv@pobox.com)
______________________________________________________
Get Your Private, Free Email at http://www.hotmail.com