diff options
Diffstat (limited to 'clang')
| -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; +} +  | 

