[cfe-dev] ::delete behaves differently in clang and gcc when class has a virtual destructor

Patrick Pelletier ppelletier at oblong.com
Tue Jul 5 16:26:40 PDT 2011


I'm reluctant to allege a bug in clang, since so far my experience has 
been that when clang's behavior differs from gcc, clang is being more 
standards-compliant than gcc.

However, in this particular case, I haven't been able to find any 
documentation that indicates that Standard C++ is supposed to do what 
clang seems to be doing.  So, I'd like to ask whether there's a 
possibility that this is a clang bug, or whether it's just a very 
obscure corner of the standard that I haven't been able to find any 
mention of.

First of all, here are the assumptions I'm starting with:

a) the "delete" expression calls the object's destructor, followed by 
calling "operator delete" on the object

b) "::delete" is the same as "delete", except that instead of calling 
"operator delete", it calls "::operator delete"

If these assumptions are correct, then in the program below, I would 
expect case 1 to call Foo's operator delete, but I would not expect case 
2 or case 3 to call Foo's operator delete.  (Indeed, based on my 
assumptions above, I would expect case 2 and case 3 to be identical; my 
belief is that case 3 is just a manual de-sugaring of case 2.)

When compiled with gcc, the program below behaves as I would expect.  
However, when compiled with clang, the program as written (i. e. with 
the virtual destructor) does not behave as I expect, in that Foo's 
operator delete is called in case 2.  (Although still not in case 3.)

The presence of the virtual destructor is important.  If I simply remove 
the word "virtual" from the declaration of ~Foo(), then the program 
behaves identically in clang and gcc, and both are what I expect.  (i. 
e. case 1 is the only case that calls Foo's operator delete.)

Thanks for any light you can shed on this behavior, and my apologies if 
this is indeed expected behavior that I am unaware of.

--Patrick


ppelletier at pumpkin:~/misc$ uname -a
Linux pumpkin 2.6.32-21-generic #32-Ubuntu SMP Fri Apr 16 08:09:38 UTC 
2010 x86_64 GNU/Linux
ppelletier at pumpkin:~/misc$ cat delete-test.C
#include <iostream>

static const char *msg;

class Foo
{ const int n;
public:
  Foo (int n_in);
  virtual ~Foo ();
  void operator delete (void *);
};

Foo::Foo (int n_in)  :  n (n_in)
{ }

Foo::~Foo ()
{ std::cerr << "destructor for " << n << std::endl; }

void Foo::operator delete (void *)
{ std::cerr << msg << std::endl; }

int main (int argc, char **argv)
{ msg = "[1] I would expect this to be printed (and it is)";
  Foo *f1 = new Foo (1);
  delete f1;
  msg = "[2] I would not expect this to be printed (gcc doesn't, clang 
does)";
  Foo *f2 = new Foo (2);
  ::delete f2;
  msg = "[3] This should not be printed either (and it isn't)";
  Foo *f3 = new Foo (3);
  f3 -> ~Foo ();
  ::operator delete (f3);
  return 0;
}
ppelletier at pumpkin:~/misc$ 
/home/ppelletier/src/asan/asan_clang_Linux/bin/clang++ --version
clang version 3.0 (trunk 133511)
Target: x86_64-unknown-linux-gnu
Thread model: posix
ppelletier at pumpkin:~/misc$ g++ --version
g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ppelletier at pumpkin:~/misc$ 
/home/ppelletier/src/asan/asan_clang_Linux/bin/clang++ -O3 -Wall -o 
delete-test-clang delete-test.C
ppelletier at pumpkin:~/misc$ g++ -O3 -Wall -o delete-test-gcc delete-test.C
ppelletier at pumpkin:~/misc$ ./delete-test-clang
destructor for 1
[1] I would expect this to be printed (and it is)
destructor for 2
[2] I would not expect this to be printed (gcc doesn't, clang does)
destructor for 3
ppelletier at pumpkin:~/misc$ ./delete-test-gcc
destructor for 1
[1] I would expect this to be printed (and it is)
destructor for 2
destructor for 3
ppelletier at pumpkin:~/misc$




More information about the cfe-dev mailing list