aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/AST/Expr.cpp26
-rw-r--r--test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp12
2 files changed, 34 insertions, 4 deletions
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<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 @@ 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<int>(s));
P(static_cast<float>(s));
- // FIXME: test destructors of temporaries
+ N(Bad1());
}
struct V {