diff options
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 23 | ||||
| -rw-r--r-- | clang/test/CXX/class.access/p4.cpp | 6 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/throw-expression-dtor.cpp | 14 |
3 files changed, 40 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 203bc358a71..da64c4824b5 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -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; } diff --git a/clang/test/CXX/class.access/p4.cpp b/clang/test/CXX/class.access/p4.cpp index c1c5199ad45..552c52f977e 100644 --- a/clang/test/CXX/class.access/p4.cpp +++ b/clang/test/CXX/class.access/p4.cpp @@ -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}} +} diff --git a/clang/test/CodeGenCXX/throw-expression-dtor.cpp b/clang/test/CodeGenCXX/throw-expression-dtor.cpp new file mode 100644 index 00000000000..5cda625bbf9 --- /dev/null +++ b/clang/test/CodeGenCXX/throw-expression-dtor.cpp @@ -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; +} + |

