Make sure to check the accessibility of and mark the destructor for the

operand of a throw expression.  Fixes PR7281.

llvm-svn: 105408
This commit is contained in:
Eli Friedman 2010-06-03 20:39:03 +00:00
parent d83e3e7750
commit 91a3d27ec0
3 changed files with 40 additions and 3 deletions

View File

@ -458,11 +458,28 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) {
return true;
E = Res.takeAs<Expr>();
// If the exception has class type, we need additional handling.
const RecordType *RecordTy = Ty->getAs<RecordType>();
if (!RecordTy)
return false;
CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
// If we are throwing a polymorphic class type or pointer thereof,
// exception handling will make use of the vtable.
if (const RecordType *RecordTy = Ty->getAs<RecordType>())
MarkVTableUsed(ThrowLoc, cast<CXXRecordDecl>(RecordTy->getDecl()));
MarkVTableUsed(ThrowLoc, RD);
// If the class has a non-trivial destructor, we must be able to call it.
if (RD->hasTrivialDestructor())
return false;
CXXDestructorDecl *Destructor =
const_cast<CXXDestructorDecl*>(RD->getDestructor(Context));
if (!Destructor)
return false;
MarkDeclarationReferenced(E->getExprLoc(), Destructor);
CheckDestructorAccess(E->getExprLoc(), Destructor,
PDiag(diag::err_access_dtor_temp) << Ty);
return false;
}

View File

@ -420,3 +420,9 @@ namespace test15 {
template class B<int>; // expected-note {{in instantiation}}
template class B<long>; // expected-note 4 {{in instantiation}}
}
// PR7281
namespace test16 {
class A { ~A(); }; // expected-note {{declared private here}}
void b() { throw A(); } // expected-error{{temporary of type 'test16::A' has private destructor}}
}

View File

@ -0,0 +1,14 @@
// RUN: %clang_cc1 %s -emit-llvm-only -verify
// PR7281
class A {
public:
~A();
};
class B : public A {
void ice_throw();
};
void B::ice_throw() {
throw *this;
}