Search code examples
c++visual-studiodestructorplacement-new

Compile error when explicitly calling the base class destructor on a derived pointer


Just like the title says. The following contrived example seems to work on codepad: http://codepad.org/4cgGmvDQ and under GCC 4.1.2 on my Linux box.

#include<stdlib.h>
#include<new>

class IBase
{
public:
    virtual ~IBase(){}
};

class B : public IBase
{
public:
    virtual ~B(){}
};

class D : public B
{
public:
    virtual ~D(){ }
};

int main()
{
    void* p = malloc(sizeof(D));

    D* d = new(p) D();

    B* b = static_cast<B*>(d);

    b->~IBase();

    free(p);
}

But Visual Studio Pro 2012 11.0.61030.00 Update 4 fails with:

main.cpp(30): error C2300: 'B' : class does not have a destructor called '~IBase'

Obviously the example could easily be reworked to avoid the issue, but my actual code base doesn't give me any other options. Is anyone familiar with this particular failing of the Microsoft compiler?


Solution

  • This is not a bug in MSVC. From the standard, §3.4.5 [basic.lookup.classref]/p2-3 (quoting N3936, emphasis mine):

    If the id-expression in a class member access (5.2.5) is an unqualified-id, [...]

    If the unqualified-id is ~type-name, the type-name is looked up in the context of the entire postfix-expression. If the type T of the object expression is of a class type C, the type-name is also looked up in the scope of class C. At least one of the lookups shall find a name that refers to (possibly cv-qualified) T.

    In your code, T is B, and lookup for IBase obviously can't find a name that refers to B. Therefore, your code is ill-formed. If g++ accepts it, it's either a bug or an extension.

    Since it sounds like the actual type B represents is "unspeakable" in your real code, but IBase is OK to write, the simplest solution would be simply to cast b to IBase *.