]> granicus.if.org Git - clang/commitdiff
Do full-expression cleanups in a much more sensible way that still lets
authorJohn McCall <rjmccall@apple.com>
Tue, 12 Jul 2011 00:15:30 +0000 (00:15 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 12 Jul 2011 00:15:30 +0000 (00:15 +0000)
people write useful cleanup classes.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134942 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCleanup.cpp
lib/CodeGen/CGException.cpp
lib/CodeGen/CGObjC.cpp
lib/CodeGen/CGTemporaries.cpp
lib/CodeGen/CodeGenFunction.h

index f75253bf78839945219298d845a1e5df2ca9ac33..4147c241c2578fc420d4a915417bfa7911778d3f 100644 (file)
@@ -256,9 +256,7 @@ void CodeGenFunction::initFullExprCleanup() {
   if (cleanup.isEHCleanup()) cleanup.setTestFlagInEHCleanup();
 }
 
-EHScopeStack::Cleanup::~Cleanup() {
-  llvm_unreachable("Cleanup is indestructable");
-}
+void EHScopeStack::Cleanup::anchor() {}
 
 /// All the branch fixups on the EH stack have propagated out past the
 /// outermost normal cleanup; resolve them all by adding cases to the
index 35429e3b8415de1048464e33f6726188f01cf30b..c25b9a688313c94063d54143a0f3dd06a5181667 100644 (file)
@@ -323,9 +323,10 @@ static llvm::Constant *getCleanupValue(CodeGenFunction &CGF) {
 namespace {
   /// A cleanup to free the exception object if its initialization
   /// throws.
-  struct FreeException {
-    static void Emit(CodeGenFunction &CGF, bool forEH,
-                     llvm::Value *exn) {
+  struct FreeException : EHScopeStack::Cleanup {
+    llvm::Value *exn;
+    FreeException(llvm::Value *exn) : exn(exn) {}
+    void Emit(CodeGenFunction &CGF, bool forEH) {
       CGF.Builder.CreateCall(getFreeExceptionFn(CGF), exn)
         ->setDoesNotThrow();
     }
index 2f0d827fc3b3027d675cf8152c51fdaeb37b7f6f..8ea481f23a5728b78b7c6bb8430588ca0361c413 100644 (file)
@@ -1902,23 +1902,6 @@ namespace {
     CallReleaseForObject(QualType type, llvm::Value *addr,
                          CodeGenFunction::Destroyer *destroyer)
       : ObjCReleasingCleanup(type, addr, destroyer) {}
-
-    using ObjCReleasingCleanup::Emit;
-    static void Emit(CodeGenFunction &CGF, bool IsForEH,
-                     QualType type, llvm::Value *addr,
-                     CodeGenFunction::Destroyer *destroyer) {
-      // EHScopeStack::Cleanup objects can never have their destructors called,
-      // so use placement new to construct our temporary object.
-      union {
-        void* align;
-        char data[sizeof(CallReleaseForObject)];
-      };
-      
-      CallReleaseForObject *Object
-        = new (&align) CallReleaseForObject(type, addr, destroyer);
-      Object->Emit(CGF, IsForEH);
-      (void)data[0];
-    }
   };
 
   /// A cleanup that calls @objc_storeStrong(nil) on all the objects to
@@ -1965,22 +1948,6 @@ namespace {
   struct CallWeakReleaseForObject : ObjCReleasingCleanup {
     CallWeakReleaseForObject(QualType type, llvm::Value *addr)
       : ObjCReleasingCleanup(type, addr, CodeGenFunction::destroyARCWeak) {}
-
-    using ObjCReleasingCleanup::Emit;
-    static void Emit(CodeGenFunction &CGF, bool IsForEH,
-                     QualType type, llvm::Value *addr) {
-      // EHScopeStack::Cleanup objects can never have their destructors called,
-      // so use placement new to construct our temporary object.
-      union {
-        void* align;
-        char data[sizeof(CallWeakReleaseForObject)];
-      };
-      
-      CallWeakReleaseForObject *Object
-        = new (&align) CallWeakReleaseForObject(type, addr);
-      Object->Emit(CGF, IsForEH);
-      (void)data[0];
-    }
   };
 
   
index 3b4c50910bf865669e1c69cc9c13dd9515cb07d6..7e07b4e5c8ce4c297ac80d2cc55a7666cfef2a3f 100644 (file)
@@ -16,9 +16,12 @@ using namespace clang;
 using namespace CodeGen;
 
 namespace {
-  struct DestroyTemporary {
-    static void Emit(CodeGenFunction &CGF, bool forEH,
-                     const CXXDestructorDecl *dtor, llvm::Value *addr) {
+  struct DestroyTemporary : EHScopeStack::Cleanup {
+    const CXXDestructorDecl *dtor;
+    llvm::Value *addr;
+    DestroyTemporary(const CXXDestructorDecl *dtor, llvm::Value *addr)
+      : dtor(dtor), addr(addr) {}
+    void Emit(CodeGenFunction &CGF, bool forEH) {
       CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*ForVirtualBase=*/false,
                                 addr);
     }
index 968222e334abd3948b158c13ad14686eeb595462..74324e4dc0cdef83e502b66823e9c1faa0ad1ed5 100644 (file)
@@ -181,15 +181,13 @@ public:
   /// Cleanup implementations should generally be declared in an
   /// anonymous namespace.
   class Cleanup {
+    // Anchor the construction vtable.
+    virtual void anchor();
   public:
-    // Anchor the construction vtable.  We use the destructor because
-    // gcc gives an obnoxious warning if there are virtual methods
-    // with an accessible non-virtual destructor.  Unfortunately,
-    // declaring this destructor makes it non-trivial, but there
-    // doesn't seem to be any other way around this warning.
-    //
-    // This destructor will never be called.
-    virtual ~Cleanup();
+    // Provide a virtual destructor to suppress a very common warning
+    // that unfortunately cannot be suppressed without this.  Cleanups
+    // should not rely on this destructor ever being called.
+    virtual ~Cleanup() {}
 
     /// Emit the cleanup.  For normal cleanups, this is run in the
     /// same EH context as when the cleanup was pushed, i.e. the
@@ -201,38 +199,6 @@ public:
     virtual void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) = 0;
   };
 
-  /// UnconditionalCleanupN stores its N parameters and just passes
-  /// them to the real cleanup function.
-  template <class T, class A0>
-  class UnconditionalCleanup1 : public Cleanup {
-    A0 a0;
-  public:
-    UnconditionalCleanup1(A0 a0) : a0(a0) {}
-    void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
-      T::Emit(CGF, IsForEHCleanup, a0);
-    }
-  };
-
-  template <class T, class A0, class A1>
-  class UnconditionalCleanup2 : public Cleanup {
-    A0 a0; A1 a1;
-  public:
-    UnconditionalCleanup2(A0 a0, A1 a1) : a0(a0), a1(a1) {}
-    void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
-      T::Emit(CGF, IsForEHCleanup, a0, a1);
-    }
-  };
-
-  template <class T, class A0, class A1, class A2>
-  class UnconditionalCleanup3 : public Cleanup {
-    A0 a0; A1 a1; A2 a2;
-  public:
-    UnconditionalCleanup3(A0 a0, A1 a1, A2 a2) : a0(a0), a1(a1), a2(a2) {}
-    void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
-      T::Emit(CGF, IsForEHCleanup, a0, a1, a2);
-    }
-  };
-
   /// ConditionalCleanupN stores the saved form of its N parameters,
   /// then restores them and performs the cleanup.
   template <class T, class A0>
@@ -242,7 +208,7 @@ public:
 
     void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
       A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
-      T::Emit(CGF, IsForEHCleanup, a0);
+      T(a0).Emit(CGF, IsForEHCleanup);
     }
 
   public:
@@ -260,7 +226,7 @@ public:
     void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
       A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
       A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
-      T::Emit(CGF, IsForEHCleanup, a0, a1);
+      T(a0, a1).Emit(CGF, IsForEHCleanup);
     }
 
   public:
@@ -281,12 +247,12 @@ public:
       A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
       A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
       A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved);
-      T::Emit(CGF, IsForEHCleanup, a0, a1, a2);
+      T(a0, a1, a2).Emit(CGF, IsForEHCleanup);
     }
     
   public:
     ConditionalCleanup3(A0_saved a0, A1_saved a1, A2_saved a2)
-    : a0_saved(a0), a1_saved(a1), a2_saved(a2) {}
+      : a0_saved(a0), a1_saved(a1), a2_saved(a2) {}
   };
 
 private:
@@ -696,10 +662,8 @@ public:
   void pushFullExprCleanup(CleanupKind kind, A0 a0) {
     // If we're not in a conditional branch, or if none of the
     // arguments requires saving, then use the unconditional cleanup.
-    if (!isInConditionalBranch()) {
-      typedef EHScopeStack::UnconditionalCleanup1<T, A0> CleanupType;
-      return EHStack.pushCleanup<CleanupType>(kind, a0);
-    }
+    if (!isInConditionalBranch())
+      return EHStack.pushCleanup<T>(kind, a0);
 
     typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
 
@@ -715,10 +679,8 @@ public:
   void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1) {
     // If we're not in a conditional branch, or if none of the
     // arguments requires saving, then use the unconditional cleanup.
-    if (!isInConditionalBranch()) {
-      typedef EHScopeStack::UnconditionalCleanup2<T, A0, A1> CleanupType;
-      return EHStack.pushCleanup<CleanupType>(kind, a0, a1);
-    }
+    if (!isInConditionalBranch())
+      return EHStack.pushCleanup<T>(kind, a0, a1);
 
     typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
     typename DominatingValue<A1>::saved_type a1_saved = saveValueInCond(a1);
@@ -736,8 +698,7 @@ public:
     // If we're not in a conditional branch, or if none of the
     // arguments requires saving, then use the unconditional cleanup.
     if (!isInConditionalBranch()) {
-      typedef EHScopeStack::UnconditionalCleanup3<T, A0, A1, A2> CleanupType;
-      return EHStack.pushCleanup<CleanupType>(kind, a0, a1, a2);
+      return EHStack.pushCleanup<T>(kind, a0, a1, a2);
     }
     
     typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);