From: Sebastian Redl Date: Fri, 10 Sep 2010 23:27:10 +0000 (+0000) Subject: Test destructors in delete expressions and of temporaries for throwing. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0b34cf7399e61ef33dc5a3af405351822eeb5f3e;p=clang Test destructors in delete expressions and of temporaries for throwing. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113664 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 65dafae35e..c9dae17f80 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1457,11 +1457,32 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { } case CXXDeleteExprClass: { - // FIXME: check if destructor might throw CanThrowResult CT = CanCalleeThrow( cast(this)->getOperatorDelete()); if (CT == CT_Can) return CT; + const Expr *Arg = cast(this)->getArgument(); + // Unwrap exactly one implicit cast, which converts all pointers to void*. + if (const ImplicitCastExpr *Cast = dyn_cast(Arg)) + Arg = Cast->getSubExpr(); + if (const PointerType *PT = Arg->getType()->getAs()) { + if (const RecordType *RT = PT->getPointeeType()->getAs()) { + CanThrowResult CT2 = CanCalleeThrow( + cast(RT->getDecl())->getDestructor()); + if (CT2 == CT_Can) + return CT2; + CT = MergeCanThrow(CT, CT2); + } + } + return MergeCanThrow(CT, CanSubExprsThrow(C, this)); + } + + case CXXBindTemporaryExprClass: { + // The bound temporary has to be destroyed again, which might throw. + CanThrowResult CT = CanCalleeThrow( + cast(this)->getTemporary()->getDestructor()); + if (CT == CT_Can) + return CT; return MergeCanThrow(CT, CanSubExprsThrow(C, this)); } @@ -1486,8 +1507,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { case ParenListExprClass: case VAArgExprClass: case CXXDefaultArgExprClass: - case CXXBindTemporaryExprClass: - case CXXExprWithTemporariesClass: // FIXME: this thing calls destructors + case CXXExprWithTemporariesClass: case ObjCIvarRefExprClass: case ObjCIsaExprClass: case ShuffleVectorExprClass: diff --git a/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp b/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp index 5182709c89..0605746a58 100644 --- a/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp +++ b/test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp @@ -86,9 +86,19 @@ struct S2 { void *operator new(__typeof__(sizeof(int)) sz, int) throw(); +struct Bad1 { + ~Bad1() throw(int); +}; +struct Bad2 { + void operator delete(void*) throw(int); +}; + void implicits() { N(new int); P(new (0) int); + P(delete (int*)0); + N(delete (Bad1*)0); + N(delete (Bad2*)0); N(S2()); P(S2(0, 0)); S2 s; @@ -98,7 +108,7 @@ void implicits() { P(s - 0); N(static_cast(s)); P(static_cast(s)); - // FIXME: test destructors of temporaries + N(Bad1()); } struct V {