------- 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

Reply via email to