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 65dafae..c9dae17 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1457,11 +1457,32 @@
}
case CXXDeleteExprClass: {
- // FIXME: check if destructor might throw
CanThrowResult CT = CanCalleeThrow(
cast<CXXDeleteExpr>(this)->getOperatorDelete());
if (CT == CT_Can)
return CT;
+ const Expr *Arg = cast<CXXDeleteExpr>(this)->getArgument();
+ // Unwrap exactly one implicit cast, which converts all pointers to void*.
+ if (const ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
+ Arg = Cast->getSubExpr();
+ if (const PointerType *PT = Arg->getType()->getAs<PointerType>()) {
+ if (const RecordType *RT = PT->getPointeeType()->getAs<RecordType>()) {
+ CanThrowResult CT2 = CanCalleeThrow(
+ cast<CXXRecordDecl>(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<CXXBindTemporaryExpr>(this)->getTemporary()->getDestructor());
+ if (CT == CT_Can)
+ return CT;
return MergeCanThrow(CT, CanSubExprsThrow(C, this));
}
@@ -1486,8 +1507,7 @@
case ParenListExprClass:
case VAArgExprClass:
case CXXDefaultArgExprClass:
- case CXXBindTemporaryExprClass:
- case CXXExprWithTemporariesClass: // FIXME: this thing calls destructors
+ case CXXExprWithTemporariesClass:
case ObjCIvarRefExprClass:
case ObjCIsaExprClass:
case ShuffleVectorExprClass: