]> granicus.if.org Git - clang/commitdiff
Test destructors in delete expressions and of temporaries for throwing.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Fri, 10 Sep 2010 23:27:10 +0000 (23:27 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Fri, 10 Sep 2010 23:27:10 +0000 (23:27 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113664 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/Expr.cpp
test/CXX/expr/expr.unary/expr.unary.noexcept/sema.cpp

index 65dafae35e472387664b80aa20b7937c151a5504..c9dae17f808559f6c7caaa64e30c7aeb9c2b838b 100644 (file)
@@ -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:
index 5182709c89ddc4745024fa13f31b427651596cdc..0605746a58569c6f1bfde85fb6515af911681eae 100644 (file)
@@ -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 {