forked from OSchip/llvm-project
Revert r121528 as it breaks a simple testcase, which leads to, among
other things, libcxx not building. llvm-svn: 131573
This commit is contained in:
parent
77e0610d7c
commit
d0cdd1fab1
|
@ -2644,13 +2644,6 @@ public:
|
||||||
void DefineImplicitDestructor(SourceLocation CurrentLocation,
|
void DefineImplicitDestructor(SourceLocation CurrentLocation,
|
||||||
CXXDestructorDecl *Destructor);
|
CXXDestructorDecl *Destructor);
|
||||||
|
|
||||||
/// \brief Build an exception spec for destructors that don't have one.
|
|
||||||
///
|
|
||||||
/// C++11 says that user-defined destructors with no exception spec get one
|
|
||||||
/// that looks as if the destructor was implicitly declared.
|
|
||||||
void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
|
|
||||||
CXXDestructorDecl *Destructor);
|
|
||||||
|
|
||||||
/// \brief Declare all inherited constructors for the given class.
|
/// \brief Declare all inherited constructors for the given class.
|
||||||
///
|
///
|
||||||
/// \param ClassDecl The class declaration into which the inherited
|
/// \param ClassDecl The class declaration into which the inherited
|
||||||
|
|
|
@ -4143,25 +4143,14 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||||
// This is a C++ destructor declaration.
|
// This is a C++ destructor declaration.
|
||||||
if (DC->isRecord()) {
|
if (DC->isRecord()) {
|
||||||
R = CheckDestructorDeclarator(D, R, SC);
|
R = CheckDestructorDeclarator(D, R, SC);
|
||||||
CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
|
|
||||||
|
|
||||||
CXXDestructorDecl *NewDD = CXXDestructorDecl::Create(Context, Record,
|
NewFD = CXXDestructorDecl::Create(Context,
|
||||||
|
cast<CXXRecordDecl>(DC),
|
||||||
D.getSourceRange().getBegin(),
|
D.getSourceRange().getBegin(),
|
||||||
NameInfo, R, TInfo,
|
NameInfo, R, TInfo,
|
||||||
isInline,
|
isInline,
|
||||||
/*isImplicitlyDeclared=*/false);
|
/*isImplicitlyDeclared=*/false);
|
||||||
NewFD = NewDD;
|
|
||||||
isVirtualOkay = true;
|
isVirtualOkay = true;
|
||||||
|
|
||||||
// If the class is complete, then we now create the implicit exception
|
|
||||||
// specification. If the class is incomplete or dependent, we can't do
|
|
||||||
// it yet.
|
|
||||||
if (getLangOptions().CPlusPlus0x && !Record->isDependentType() &&
|
|
||||||
Record->getDefinition() && !Record->isBeingDefined() &&
|
|
||||||
R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) {
|
|
||||||
AdjustDestructorExceptionSpec(Record, NewDD);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
|
Diag(D.getIdentifierLoc(), diag::err_destructor_not_member);
|
||||||
|
|
||||||
|
@ -8139,11 +8128,6 @@ void Sema::ActOnFields(Scope* S,
|
||||||
Convs->setAccess(I, (*I)->getAccess());
|
Convs->setAccess(I, (*I)->getAccess());
|
||||||
|
|
||||||
if (!CXXRecord->isDependentType()) {
|
if (!CXXRecord->isDependentType()) {
|
||||||
// Adjust user-defined destructor exception spec.
|
|
||||||
if (getLangOptions().CPlusPlus0x &&
|
|
||||||
CXXRecord->hasUserDeclaredDestructor())
|
|
||||||
AdjustDestructorExceptionSpec(CXXRecord,CXXRecord->getDestructor());
|
|
||||||
|
|
||||||
// Add any implicitly-declared members to this class.
|
// Add any implicitly-declared members to this class.
|
||||||
AddImplicitlyDeclaredMembersToClass(CXXRecord);
|
AddImplicitlyDeclaredMembersToClass(CXXRecord);
|
||||||
|
|
||||||
|
|
|
@ -6222,18 +6222,18 @@ Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) {
|
||||||
|
|
||||||
if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
|
if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
|
||||||
ExceptSpec.CalledDecl(
|
ExceptSpec.CalledDecl(
|
||||||
LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
|
LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Virtual base-class destructors.
|
// Virtual base-class destructors.
|
||||||
for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
|
for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(),
|
||||||
BEnd = ClassDecl->vbases_end();
|
BEnd = ClassDecl->vbases_end();
|
||||||
B != BEnd; ++B) {
|
B != BEnd; ++B) {
|
||||||
if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
|
if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
|
||||||
ExceptSpec.CalledDecl(
|
ExceptSpec.CalledDecl(
|
||||||
LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
|
LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Field destructors.
|
// Field destructors.
|
||||||
for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
|
for (RecordDecl::field_iterator F = ClassDecl->field_begin(),
|
||||||
FEnd = ClassDecl->field_end();
|
FEnd = ClassDecl->field_end();
|
||||||
|
@ -6241,7 +6241,7 @@ Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) {
|
||||||
if (const RecordType *RecordTy
|
if (const RecordType *RecordTy
|
||||||
= Context.getBaseElementType(F->getType())->getAs<RecordType>())
|
= Context.getBaseElementType(F->getType())->getAs<RecordType>())
|
||||||
ExceptSpec.CalledDecl(
|
ExceptSpec.CalledDecl(
|
||||||
LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
|
LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExceptSpec;
|
return ExceptSpec;
|
||||||
|
@ -6254,7 +6254,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
|
||||||
// inline public member of its class.
|
// inline public member of its class.
|
||||||
|
|
||||||
ImplicitExceptionSpecification Spec =
|
ImplicitExceptionSpecification Spec =
|
||||||
ComputeDefaultedDtorExceptionSpec(ClassDecl);
|
ComputeDefaultedDtorExceptionSpec(ClassDecl);
|
||||||
FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
|
FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
|
||||||
|
|
||||||
// Create the actual destructor declaration.
|
// Create the actual destructor declaration.
|
||||||
|
@ -6329,35 +6329,6 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *classDecl,
|
|
||||||
CXXDestructorDecl *destructor) {
|
|
||||||
// C++11 [class.dtor]p3:
|
|
||||||
// A declaration of a destructor that does not have an exception-
|
|
||||||
// specification is implicitly considered to have the same exception-
|
|
||||||
// specification as an implicit declaration.
|
|
||||||
const FunctionProtoType *dtorType = destructor->getType()->
|
|
||||||
getAs<FunctionProtoType>();
|
|
||||||
if (dtorType->hasExceptionSpec())
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImplicitExceptionSpecification exceptSpec =
|
|
||||||
ComputeDefaultedDtorExceptionSpec(classDecl);
|
|
||||||
|
|
||||||
// Replace the destructor's type.
|
|
||||||
FunctionProtoType::ExtProtoInfo epi;
|
|
||||||
epi.ExceptionSpecType = exceptSpec.getExceptionSpecType();
|
|
||||||
epi.NumExceptions = exceptSpec.size();
|
|
||||||
epi.Exceptions = exceptSpec.data();
|
|
||||||
QualType ty = Context.getFunctionType(Context.VoidTy, 0, 0, epi);
|
|
||||||
|
|
||||||
destructor->setType(ty);
|
|
||||||
|
|
||||||
// FIXME: If the destructor has a body that could throw, and the newly created
|
|
||||||
// spec doesn't allow exceptions, we should emit a warning, because this
|
|
||||||
// change in behavior can break conforming C++03 programs at runtime.
|
|
||||||
// However, we don't have a body yet, so it needs to be done somewhere else.
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Builds a statement that copies the given entity from \p From to
|
/// \brief Builds a statement that copies the given entity from \p From to
|
||||||
/// \c To.
|
/// \c To.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,127 +0,0 @@
|
||||||
// RUN: %clang_cc1 -std=c++0x -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s
|
|
||||||
|
|
||||||
struct A {
|
|
||||||
~A();
|
|
||||||
};
|
|
||||||
|
|
||||||
struct B {
|
|
||||||
~B() throw(int);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct C {
|
|
||||||
B b;
|
|
||||||
~C() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct D {
|
|
||||||
~D() noexcept(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct E {
|
|
||||||
D d;
|
|
||||||
~E() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
void foo() {
|
|
||||||
A a;
|
|
||||||
C c;
|
|
||||||
E e;
|
|
||||||
// CHECK: invoke void @_ZN1ED1Ev
|
|
||||||
// CHECK: invoke void @_ZN1CD1Ev
|
|
||||||
// CHECK: call void @_ZN1AD1Ev
|
|
||||||
}
|
|
||||||
|
|
||||||
struct F {
|
|
||||||
D d;
|
|
||||||
~F();
|
|
||||||
};
|
|
||||||
F::~F() noexcept(false) {}
|
|
||||||
|
|
||||||
struct G {
|
|
||||||
D d;
|
|
||||||
~G();
|
|
||||||
};
|
|
||||||
G::~G() {}
|
|
||||||
|
|
||||||
struct H {
|
|
||||||
B b;
|
|
||||||
~H();
|
|
||||||
};
|
|
||||||
H::~H() throw(int) {}
|
|
||||||
|
|
||||||
struct I {
|
|
||||||
B b;
|
|
||||||
~I();
|
|
||||||
};
|
|
||||||
I::~I() {}
|
|
||||||
|
|
||||||
// Template variants.
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct TA {
|
|
||||||
~TA();
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct TB {
|
|
||||||
~TB() throw(int);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct TC {
|
|
||||||
TB<T> b;
|
|
||||||
~TC() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct TD {
|
|
||||||
~TD() noexcept(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct TE {
|
|
||||||
TD<T> d;
|
|
||||||
~TE() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
void tfoo() {
|
|
||||||
TA<int> a;
|
|
||||||
TC<int> c;
|
|
||||||
TE<int> e;
|
|
||||||
// CHECK: invoke void @_ZN2TEIiED1Ev
|
|
||||||
// CHECK: invoke void @_ZN2TCIiED1Ev
|
|
||||||
// CHECK: call void @_ZN2TAIiED1Ev
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct TF {
|
|
||||||
TD<T> d;
|
|
||||||
~TF();
|
|
||||||
};
|
|
||||||
template <typename T>
|
|
||||||
TF<T>::~TF() noexcept(false) {}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct TG {
|
|
||||||
TD<T> d;
|
|
||||||
~TG();
|
|
||||||
};
|
|
||||||
template <typename T>
|
|
||||||
TG<T>::~TG() {}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct TH {
|
|
||||||
TB<T> b;
|
|
||||||
~TH();
|
|
||||||
};
|
|
||||||
template <typename T>
|
|
||||||
TH<T>::~TH() {}
|
|
||||||
|
|
||||||
void tinst() {
|
|
||||||
TF<int> f;
|
|
||||||
TG<int> g;
|
|
||||||
TH<int> h;
|
|
||||||
}
|
|
||||||
// CHECK: define linkonce_odr void @_ZN2THIiED1Ev
|
|
||||||
// CHECK: _ZTIi
|
|
||||||
// CHECK: __cxa_call_unexpected
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
struct non_trivial {
|
struct non_trivial {
|
||||||
non_trivial();
|
non_trivial();
|
||||||
~non_trivial() noexcept(false);
|
~non_trivial();
|
||||||
};
|
};
|
||||||
non_trivial::non_trivial() {}
|
non_trivial::non_trivial() {}
|
||||||
non_trivial::~non_trivial() noexcept(false) {}
|
non_trivial::~non_trivial() {}
|
||||||
|
|
||||||
// We use a virtual base to ensure that the constructor
|
// We use a virtual base to ensure that the constructor
|
||||||
// delegation optimization (complete->base) can't be
|
// delegation optimization (complete->base) can't be
|
||||||
|
|
|
@ -159,7 +159,7 @@ namespace test8 {
|
||||||
// CHECK-NEXT: bitcast
|
// CHECK-NEXT: bitcast
|
||||||
// CHECK-NEXT: invoke void @_ZN5test81AC1ERKS0_(
|
// CHECK-NEXT: invoke void @_ZN5test81AC1ERKS0_(
|
||||||
// CHECK: call i8* @__cxa_begin_catch
|
// CHECK: call i8* @__cxa_begin_catch
|
||||||
// CHECK-NEXT: call void @_ZN5test81AD1Ev(
|
// CHECK-NEXT: invoke void @_ZN5test81AD1Ev(
|
||||||
// CHECK: call void @__cxa_end_catch()
|
// CHECK: call void @__cxa_end_catch()
|
||||||
// CHECK: ret void
|
// CHECK: ret void
|
||||||
}
|
}
|
||||||
|
@ -272,7 +272,7 @@ namespace test11 {
|
||||||
|
|
||||||
// PR7686
|
// PR7686
|
||||||
namespace test12 {
|
namespace test12 {
|
||||||
struct A { ~A() noexcept(false); };
|
struct A { ~A(); };
|
||||||
bool opaque(const A&);
|
bool opaque(const A&);
|
||||||
|
|
||||||
// CHECK: define void @_ZN6test124testEv()
|
// CHECK: define void @_ZN6test124testEv()
|
||||||
|
@ -392,8 +392,8 @@ namespace test15 {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace test16 {
|
namespace test16 {
|
||||||
struct A { A(); ~A() noexcept(false); };
|
struct A { A(); ~A(); };
|
||||||
struct B { int x; B(const A &); ~B() noexcept(false); };
|
struct B { int x; B(const A &); ~B(); };
|
||||||
void foo();
|
void foo();
|
||||||
bool cond();
|
bool cond();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
|
||||||
|
|
||||||
|
struct X
|
||||||
|
{ virtual ~X() {} };
|
||||||
|
|
||||||
|
struct Y : X
|
||||||
|
{ virtual ~Y() {} };
|
Loading…
Reference in New Issue