2016-09-01 07:24:08 +08:00
|
|
|
// RUN: %clang_cc1 -fsyntax-only -triple %itanium_abi_triple -verify -std=c++98 %s
|
|
|
|
// RUN: %clang_cc1 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify -std=c++98 %s
|
|
|
|
// RUN: %clang_cc1 -fsyntax-only -triple %itanium_abi_triple -verify -std=c++11 %s
|
|
|
|
// RUN: %clang_cc1 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify -std=c++11 %s
|
2010-08-04 08:31:26 +08:00
|
|
|
|
2016-09-01 07:24:08 +08:00
|
|
|
typedef __typeof(sizeof(int)) size_t;
|
2010-08-04 08:31:26 +08:00
|
|
|
|
|
|
|
// PR7803
|
|
|
|
namespace test0 {
|
|
|
|
class A {
|
|
|
|
public:
|
|
|
|
static void operator delete(void *p) {};
|
|
|
|
virtual ~A();
|
|
|
|
};
|
|
|
|
|
|
|
|
class B : protected A {
|
|
|
|
public:
|
|
|
|
~B();
|
|
|
|
};
|
|
|
|
|
|
|
|
class C : protected B {
|
|
|
|
public:
|
|
|
|
using B::operator delete;
|
|
|
|
~C();
|
|
|
|
};
|
|
|
|
|
|
|
|
// Shouldn't have an error.
|
|
|
|
C::~C() {}
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace test1 {
|
|
|
|
class A {
|
|
|
|
public:
|
2016-10-11 02:54:32 +08:00
|
|
|
static void operator delete(void *p) {};
|
2010-08-04 08:31:26 +08:00
|
|
|
virtual ~A();
|
|
|
|
};
|
|
|
|
|
|
|
|
class B : protected A {
|
|
|
|
public:
|
2016-10-11 02:54:32 +08:00
|
|
|
static void operator delete(void *, size_t) {};
|
2010-08-04 08:31:26 +08:00
|
|
|
~B();
|
|
|
|
};
|
|
|
|
|
|
|
|
class C : protected B {
|
|
|
|
public:
|
|
|
|
using A::operator delete;
|
|
|
|
using B::operator delete;
|
|
|
|
|
2010-08-04 09:04:25 +08:00
|
|
|
~C();
|
|
|
|
};
|
|
|
|
|
2016-10-11 02:54:32 +08:00
|
|
|
// We assume that the intent is to treat C::operator delete(void*, size_t) as
|
|
|
|
// /not/ being a usual deallocation function, as it would be if it were
|
|
|
|
// declared with in C directly.
|
|
|
|
C::~C() {}
|
|
|
|
|
|
|
|
struct D {
|
|
|
|
void operator delete(void*); // expected-note {{member 'operator delete' declared here}}
|
|
|
|
void operator delete(void*, ...); // expected-note {{member 'operator delete' declared here}}
|
|
|
|
virtual ~D();
|
|
|
|
};
|
|
|
|
// FIXME: The standard doesn't say this is ill-formed, but presumably either
|
|
|
|
// it should be or the variadic operator delete should not be a usual
|
|
|
|
// deallocation function.
|
|
|
|
D::~D() {} // expected-error {{multiple suitable 'operator delete' functions in 'D'}}
|
2010-08-04 09:04:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// ...at the point of definition of a virtual destructor...
|
|
|
|
namespace test2 {
|
|
|
|
struct A {
|
|
|
|
virtual ~A();
|
|
|
|
static void operator delete(void*, const int &);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct B {
|
|
|
|
virtual ~B();
|
|
|
|
static void operator delete(void*, const int &); // expected-note {{declared here}}
|
|
|
|
};
|
|
|
|
B::~B() {} // expected-error {{no suitable member 'operator delete' in 'B'}}
|
|
|
|
|
2016-09-01 07:24:08 +08:00
|
|
|
#if __cplusplus < 201103L
|
2010-08-04 09:04:25 +08:00
|
|
|
struct CBase { virtual ~CBase(); };
|
|
|
|
struct C : CBase { // expected-error {{no suitable member 'operator delete' in 'C'}}
|
|
|
|
static void operator delete(void*, const int &); // expected-note {{declared here}}
|
2010-08-04 08:31:26 +08:00
|
|
|
};
|
2010-08-04 09:04:25 +08:00
|
|
|
void test() {
|
|
|
|
C c; // expected-note {{first required here}}
|
|
|
|
}
|
2016-09-01 07:24:08 +08:00
|
|
|
#else
|
|
|
|
struct CBase { virtual ~CBase(); }; // expected-note {{overridden virtual function is here}}
|
2016-11-01 02:18:29 +08:00
|
|
|
struct C : CBase { // expected-error {{deleted function '~C' cannot override a non-deleted function}} expected-note 2{{requires an unambiguous, accessible 'operator delete'}}
|
2016-09-01 07:24:08 +08:00
|
|
|
static void operator delete(void*, const int &);
|
|
|
|
};
|
|
|
|
void test() {
|
|
|
|
C c; // expected-error {{attempt to use a deleted function}}
|
|
|
|
}
|
|
|
|
#endif
|
2010-08-04 08:31:26 +08:00
|
|
|
}
|
2010-08-04 09:07:02 +08:00
|
|
|
|
|
|
|
// PR7346
|
|
|
|
namespace test3 {
|
|
|
|
struct A {
|
2014-01-14 03:48:13 +08:00
|
|
|
#ifdef MSABI
|
|
|
|
// expected-error@+2 {{no suitable member 'operator delete' in 'A'}}
|
|
|
|
#endif
|
2010-08-04 09:07:02 +08:00
|
|
|
virtual ~A();
|
2014-01-14 03:48:13 +08:00
|
|
|
#ifdef MSABI
|
|
|
|
// expected-note@+2 {{declared here}}
|
|
|
|
#endif
|
2010-08-04 09:07:02 +08:00
|
|
|
static void operator delete(void*, const int &);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct B : A {
|
|
|
|
virtual ~B() {}
|
|
|
|
static void operator delete(void*);
|
|
|
|
};
|
Don't let virtual calls and dynamic casts call Sema::MarkVTableUsed().
clang currently calls MarkVTableUsed() for classes that get their virtual
methods called or that participate in a dynamic_cast. This is unnecessary,
since CodeGen only emits vtables when it generates constructor, destructor, and
vtt code. (*)
Note that Sema::MarkVTableUsed() doesn't cause the emission of a vtable.
Its main user-visible effect is that it instantiates virtual member functions
of template classes, to make sure that if codegen decides to write a vtable
all the entries in the vtable are defined.
While this shouldn't change the behavior of codegen (other than being faster),
it does make clang more permissive: virtual methods of templates (in particular
destructors) end up being instantiated less often. In particular, classes that
have members that are smart pointers to incomplete types will now get their
implicit virtual destructor instantiated less frequently. For example, this
used to not compile but does now compile:
template <typename T> struct OwnPtr {
~OwnPtr() { static_assert((sizeof(T) > 0), "TypeMustBeComplete"); }
};
class ScriptLoader;
struct Base { virtual ~Base(); };
struct Sub : public Base {
virtual void someFun() const {}
OwnPtr<ScriptLoader> m_loader;
};
void f(Sub *s) { s->someFun(); }
The more permissive behavior matches both gcc (where this is not often
observable, since in practice most things with virtual methods have a key
function, and Sema::DefineUsedVTables() skips vtables for classes with key
functions) and cl (which is my motivation for this change) – this fixes
PR20337. See this issue and the review thread for some discussions about
optimizations.
This is similar to r213109 in spirit. r225761 was a prerequisite for this
change.
Various tests relied on "a->f()" marking a's vtable as used (in the sema
sense), switch these to just construct a on the stack. This forces
instantiation of the implicit constructor, which will mark the vtable as used.
(*) The exception is -fapple-kext mode: In this mode, qualified calls to
virtual functions (`a->Base::f()`) still go through the vtable, and since the
vtable pointer off this doesn't point to Base's vtable, this needs to reference
Base's vtable directly. To keep this working, keep referencing the vtable for
virtual calls in apple kext mode.
llvm-svn: 227073
2015-01-26 14:23:36 +08:00
|
|
|
|
|
|
|
void f() {
|
|
|
|
#ifdef MSABI
|
|
|
|
// expected-note@+2 {{implicit default constructor for 'test3::B' first required here}}
|
|
|
|
#endif
|
|
|
|
B use_vtable;
|
|
|
|
}
|
2010-08-04 09:07:02 +08:00
|
|
|
}
|