forked from OSchip/llvm-project
[Win32 ABI] Defer operator delete checks until vtable is marked used
We were previously checking at every destructor declaration, but that was a bit excessive. Since the deleting destructor is emitted with the vtable, do the check when the vtable is marked used. Differential Revision: http://llvm-reviews.chandlerc.com/D2851 llvm-svn: 202046
This commit is contained in:
parent
dc59a36caa
commit
3d79154aec
|
@ -2307,8 +2307,12 @@ public:
|
|||
bool isImplicitlyDeclared);
|
||||
static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID);
|
||||
|
||||
void setOperatorDelete(FunctionDecl *OD) { OperatorDelete = OD; }
|
||||
const FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
|
||||
void setOperatorDelete(FunctionDecl *OD) {
|
||||
cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete = OD;
|
||||
}
|
||||
const FunctionDecl *getOperatorDelete() const {
|
||||
return cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete;
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
|
|
|
@ -6290,15 +6290,6 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
|
|||
SemaRef.AdjustDestructorExceptionSpec(Record, NewDD);
|
||||
}
|
||||
|
||||
// The Microsoft ABI requires that we perform the destructor body
|
||||
// checks (i.e. operator delete() lookup) at every declaration, as
|
||||
// any translation unit may need to emit a deleting destructor.
|
||||
if (SemaRef.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
|
||||
!Record->isDependentType() && Record->getDefinition() &&
|
||||
!Record->isBeingDefined() && !NewDD->isDeleted()) {
|
||||
SemaRef.CheckDestructor(NewDD);
|
||||
}
|
||||
|
||||
IsVirtualOkay = true;
|
||||
return NewDD;
|
||||
|
||||
|
|
|
@ -4479,15 +4479,6 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Record->hasUserDeclaredDestructor()) {
|
||||
// The Microsoft ABI requires that we perform the destructor body
|
||||
// checks (i.e. operator delete() lookup) in any translataion unit, as
|
||||
// any translation unit may need to emit a deleting destructor.
|
||||
if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
|
||||
!Record->getDestructor()->isDeleted())
|
||||
CheckDestructor(Record->getDestructor());
|
||||
}
|
||||
}
|
||||
|
||||
// C++11 [dcl.constexpr]p8: A constexpr specifier for a non-static member
|
||||
|
@ -12345,6 +12336,18 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
|
|||
// Otherwise, we can early exit.
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// The Microsoft ABI requires that we perform the destructor body
|
||||
// checks (i.e. operator delete() lookup) when the vtable is marked used, as
|
||||
// the deleting destructor is emitted with the vtable, not with the
|
||||
// destructor definition as in the Itanium ABI.
|
||||
// If it has a definition, we do the check at that point instead.
|
||||
if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
|
||||
Class->hasUserDeclaredDestructor() &&
|
||||
!Class->getDestructor()->isDefined() &&
|
||||
!Class->getDestructor()->isDeleted()) {
|
||||
CheckDestructor(Class->getDestructor());
|
||||
}
|
||||
}
|
||||
|
||||
// Local classes need to have their virtual members marked
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple
|
||||
// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple
|
||||
// RUN: %clang_cc1 -std=c++1y %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple
|
||||
|
||||
// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -triple %ms_abi_triple -DMSABI
|
||||
// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -triple %ms_abi_triple -DMSABI
|
||||
// RUN: %clang_cc1 -std=c++1y %s -verify -fexceptions -fcxx-exceptions -pedantic-errors -triple %ms_abi_triple -DMSABI
|
||||
// RUN: %clang_cc1 -std=c++98 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++11 %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
// RUN: %clang_cc1 -std=c++1y %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
|
||||
|
||||
// PR13819 -- __SIZE_TYPE__ is incompatible.
|
||||
typedef __SIZE_TYPE__ size_t; // expected-error 0-1 {{extension}}
|
||||
|
@ -538,30 +534,17 @@ namespace dr250 { // dr250: yes
|
|||
|
||||
namespace dr252 { // dr252: yes
|
||||
struct A {
|
||||
#ifdef MSABI
|
||||
// expected-note@+2 {{found}}
|
||||
#endif
|
||||
void operator delete(void*); // expected-note {{found}}
|
||||
};
|
||||
struct B {
|
||||
#ifdef MSABI
|
||||
// expected-note@+2 {{found}}
|
||||
#endif
|
||||
void operator delete(void*); // expected-note {{found}}
|
||||
};
|
||||
struct C : A, B {
|
||||
#ifdef MSABI
|
||||
// expected-error@+2 {{'operator delete' found in multiple base classes}}
|
||||
#endif
|
||||
virtual ~C();
|
||||
};
|
||||
C::~C() {} // expected-error {{'operator delete' found in multiple base classes}}
|
||||
|
||||
struct D {
|
||||
#ifdef MSABI
|
||||
// expected-note@+3 {{here}} MSABI
|
||||
// expected-error@+3 {{no suitable member 'operator delete'}}
|
||||
#endif
|
||||
void operator delete(void*, int); // expected-note {{here}}
|
||||
virtual ~D();
|
||||
};
|
||||
|
@ -577,10 +560,6 @@ namespace dr252 { // dr252: yes
|
|||
struct F {
|
||||
// If both functions are available, the first one is a placement delete.
|
||||
void operator delete(void*, size_t);
|
||||
#ifdef MSABI
|
||||
// expected-note@+3 {{here}}
|
||||
// expected-error@+3 {{attempt to use a deleted function}}
|
||||
#endif
|
||||
void operator delete(void*) = delete; // expected-error 0-1{{extension}} expected-note {{here}}
|
||||
virtual ~F();
|
||||
};
|
||||
|
|
|
@ -29,18 +29,12 @@ namespace test0 {
|
|||
namespace test1 {
|
||||
class A {
|
||||
public:
|
||||
#ifdef MSABI
|
||||
// expected-note@+2 {{declared here}}
|
||||
#endif
|
||||
static void operator delete(void *p) {}; // expected-note {{member 'operator delete' declared here}}
|
||||
virtual ~A();
|
||||
};
|
||||
|
||||
class B : protected A {
|
||||
public:
|
||||
#ifdef MSABI
|
||||
// expected-note@+2 {{declared here}}
|
||||
#endif
|
||||
static void operator delete(void *, size_t) {}; // expected-note {{member 'operator delete' declared here}}
|
||||
~B();
|
||||
};
|
||||
|
@ -50,9 +44,6 @@ namespace test1 {
|
|||
using A::operator delete;
|
||||
using B::operator delete;
|
||||
|
||||
#ifdef MSABI
|
||||
// expected-error@+2 {{multiple suitable 'operator delete' functions in 'C'}}
|
||||
#endif
|
||||
~C();
|
||||
};
|
||||
|
||||
|
@ -62,22 +53,12 @@ namespace test1 {
|
|||
// ...at the point of definition of a virtual destructor...
|
||||
namespace test2 {
|
||||
struct A {
|
||||
#ifdef MSABI
|
||||
// expected-error@+3 {{no suitable member 'operator delete' in 'A'}}
|
||||
// expected-note@+3 {{declared here}}
|
||||
#endif
|
||||
virtual ~A();
|
||||
static void operator delete(void*, const int &);
|
||||
};
|
||||
|
||||
struct B {
|
||||
#ifdef MSABI
|
||||
// expected-error@+2 {{no suitable member 'operator delete' in 'B'}}
|
||||
#endif
|
||||
virtual ~B();
|
||||
#ifdef MSABI
|
||||
// expected-note@+2 {{declared here}}
|
||||
#endif
|
||||
static void operator delete(void*, const int &); // expected-note {{declared here}}
|
||||
};
|
||||
B::~B() {} // expected-error {{no suitable member 'operator delete' in 'B'}}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
// RUN: %clang_cc1 -triple %itanium_abi_triple -fsyntax-only %s
|
||||
// RUN: %clang_cc1 -triple %ms_abi_triple -verify -DMSVC_ABI %s
|
||||
// RUN: %clang_cc1 -triple %ms_abi_triple -verify %s
|
||||
|
||||
namespace Test1 {
|
||||
|
||||
// Should be accepted under the Itanium ABI (first RUN line) but rejected
|
||||
// under the Microsoft ABI (second RUN line), as Microsoft ABI requires
|
||||
// operator delete() lookups to be done at all virtual destructor declaration
|
||||
// points.
|
||||
// operator delete() lookups to be done when vtables are marked used.
|
||||
|
||||
struct A {
|
||||
void operator delete(void *); // expected-note {{member found by ambiguous name lookup}}
|
||||
|
@ -24,6 +23,10 @@ struct VC : A, B {
|
|||
virtual ~VC(); // expected-error {{member 'operator delete' found in multiple base classes of different types}}
|
||||
};
|
||||
|
||||
void f(VC vc) {
|
||||
// This marks VC's vtable used.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Test2 {
|
||||
|
|
Loading…
Reference in New Issue