]> granicus.if.org Git - clang/commitdiff
Emit global destructors even if the destroyed object has no initializers or has
authorJohn McCall <rjmccall@apple.com>
Fri, 30 Jul 2010 04:56:58 +0000 (04:56 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 30 Jul 2010 04:56:58 +0000 (04:56 +0000)
an initializer requiring temporary object disposal.

Fixes rdar:://problem/8246444.

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

lib/CodeGen/CGDeclCXX.cpp
test/CodeGenCXX/global-init.cpp

index 0293c5c125fe71d3bd5829ede39d4ba6162988c7..ddb1abc70a164b847413939d834eae9e52be7210 100644 (file)
@@ -45,19 +45,15 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
   CodeGenModule &CGM = CGF.CGM;
   ASTContext &Context = CGF.getContext();
   
-  const Expr *Init = D.getInit();
   QualType T = D.getType();
-  if (!CGF.hasAggregateLLVMType(T) || T->isAnyComplexType())
-    return;
-                                
-  // Avoid generating destructor(s) for initialized objects. 
-  if (!isa<CXXConstructExpr>(Init))
-    return;
   
+  // Drill down past array types.
   const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
   if (Array)
     T = Context.getBaseElementType(Array);
   
+  /// If that's not a record, we're done.
+  /// FIXME:  __attribute__((cleanup)) ?
   const RecordType *RT = T->getAs<RecordType>();
   if (!RT)
     return;
index 8dd3b4eb14b353ea0f7da5cbed79a1689d017bbf..07db598900ce0b2e486671af9f81920d99dff223 100644 (file)
@@ -37,6 +37,22 @@ namespace test1 {
   const int z = ~y;    // This also gets deferred, but gets "undeferred" before y.
   int test() { return z; }
 // CHECK:      define i32 @_ZN5test14testEv() {
+
+  // All of these initializers end up delayed, so we check them later.
+}
+
+// <rdar://problem/8246444>
+namespace test2 {
+  struct allocator { allocator(); ~allocator(); };
+  struct A { A(const allocator &a = allocator()); ~A(); };
+
+  A a;
+// CHECK: call void @_ZN5test29allocatorC1Ev(
+// CHECK: invoke void @_ZN5test21AC1ERKNS_9allocatorE(
+// CHECK: call void @_ZN5test29allocatorD1Ev(
+// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN5test21AD1Ev {{.*}} @_ZN5test21aE
+}
+
 // CHECK:      define internal void [[TEST1_Z_INIT:@.*]]()
 // CHECK:        load i32* @_ZN5test1L1yE
 // CHECK-NEXT:   xor
@@ -46,8 +62,7 @@ namespace test1 {
 // CHECK-NEXT:   sub
 // CHECK-NEXT:   store i32 {{.*}}, i32* @_ZN5test1L1yE
 
-// Later on, we check that y is initialized before z.
-}
+// At the end of the file, we check that y is initialized before z.
 
 // CHECK: define internal void @_GLOBAL__I_a() section "__TEXT,__StaticInit,regular,pure_instructions" {
 // CHECK:   call void [[TEST1_Y_INIT]]