summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp23
-rw-r--r--clang/test/CXX/class.access/p4.cpp6
-rw-r--r--clang/test/CodeGenCXX/throw-expression-dtor.cpp14
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;
+}
+
OpenPOWER on IntegriCloud