From 85aca0f6a9da02bda705690fd56d0aa713604f08 Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 30 Jul 2010 04:56:58 +0000 Subject: [PATCH] Emit global destructors even if the destroyed object has no initializers or has 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 | 10 +++------- test/CodeGenCXX/global-init.cpp | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index 0293c5c125..ddb1abc70a 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -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(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(); if (!RT) return; diff --git a/test/CodeGenCXX/global-init.cpp b/test/CodeGenCXX/global-init.cpp index 8dd3b4eb14..07db598900 100644 --- a/test/CodeGenCXX/global-init.cpp +++ b/test/CodeGenCXX/global-init.cpp @@ -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. +} + +// +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]] -- 2.40.0