This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/21280] [4.0/4.1 Regression] #pragma interface, templates, and "inline function used but never defined"
- From: "prw at ceiriog1 dot demon dot co dot uk" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 30 Apr 2005 07:37:12 -0000
- Subject: [Bug c++/21280] [4.0/4.1 Regression] #pragma interface, templates, and "inline function used but never defined"
- References: <20050429085941.21280.jens.maurer@gmx.net>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- Additional Comments From prw at ceiriog1 dot demon dot co dot uk 2005-04-30 07:37 -------
I may have a discovered a related bug with a large program using
STL (hash_set). I've tried to simplify somewhat, and I have some
comments arising from some hacking with gdb (ddd). As a previous
poster on duplicate Bug #20584 observed, it seems to be related
to #pragma interface. In this example the problem is with the
~hash_set destructor, which is never defined explicitly but needs
to be synthesized to destroy the _M_ht member. This destructor
is never instantiated anywhere.
This problem occurs with the 4.0.0 distribution.
Just do g++ bug-example.cc (if you can't reproduce the warning,
I will post the preprocessed source also).
FILE bug-example.h ------------------------------------------------------------
#pragma interface
#include <ext/hash_set>
using __gnu_cxx::hash_set;
template <class Value, class HashFcn, class EqualKey>
class SetData:
public hash_set<Value *, HashFcn, EqualKey>
{
int i;
public:
SetData(void) {i = 1;}
int foo() {}
};
typedef int Loc;
struct Loc_hash {
size_t operator()(Loc *const &loc) const
{
return *loc;
}
};
struct Loc_eq {
bool operator()(Loc *const &loc1, Loc *const &loc2) const
{
return (*loc1 == *loc2);
}
};
typedef SetData<Loc,Loc_hash,Loc_eq> LocSet;
FILE bug-example.cc ----------------------------------------------------------
// If this is set we are OK.
// #pragma implementation
#include "bug-example.h"
/* ==================
Compile with -DEG1: We are OK
Compile with -DEG2: We get a warning:
bug-example.h:13: warning: inline function $-1òø__gnu_cxx::hash_set<Loc*,
Loc_hash, Loc_eq, std::allocator<Loc*> >::~hash_set()òù used but never defined
~hash_set is not declared explicitly; but it is synthesized since one of
the members (_M_ht) has a non-trivial destructor.
Try setting the following breakpoint:
(gdb) info b 1
Num Type Disp Enb Address What
1 breakpoint keep y 0x080d295f in lazily_declare_fn at
../../gcc/cp/method.c:1055
stop only if !({<text variable, no debug info>} 0x599b60 <strncmp>)
(type->type.name->decl.name->identifier.id.str, "hash_set", 8)
breakpoint already hit 2 times
For EG1: Hit a breakpoint here:
(gdb) c
Breakpoint 1, lazily_declare_fn (sfk=sfk_destructor, type=0x41746bd0) at
../../gcc/cp/method.c:1055
(gdb) p type->type.name->decl.name->identifier.id.str
$10 = (const unsigned char *) 0x8e6706a
"hash_set<Loc*,Loc_hash,Loc_eq,std::allocator<Loc*> >"
(gdb) p input_location
$11 = {
file = 0x8e2cc88 "bug-example.cc",
line = xx (i.e. LocSet x;)
}
(If the SetData/LocSet constructor fails, then the superclass destructors
must be called to clean up - the compiler therefore needs to synthesize
~hash_set).
For EG2, ~hash_set is not declared until instantiate_pending_templates
(called from finish_file):
(gdb) c
Breakpoint 1, lazily_declare_fn (sfk=sfk_destructor, type=0x41746c3c) at
../../gcc/cp/method.c:1055
(gdb) p input_location
$13 = {
file = 0x8e5cc40 "bug-example.h",
line = xx (i.e. SetData(void) {i = 1;})
}
Since "bug-example.h" contains #pragma interface this does not get
compiled. It should, since it really comes from the "hash_set"
header, which does not have #pragma interface.
I have a very comple example in which this warning actually leads to a
linker error, but in this small example I have not yet worked out how
to make a destructor call which does not cause ~hash_set to be
properly instantiated - but believe me, it can and does happen.
===================== */
main()
{
#if defined(EG1)
LocSet x;
int i=1;
x.insert(&i);
#else
LocSet *x = new LocSet;
int i=1;
x->insert(&i);
#endif
}
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21280