[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