From 6331c408b5eb4ea3c645b5df04a33f70748894c4 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 13 Feb 2012 22:16:19 +0000 Subject: Deal with a horrible C++11 special case. If a non-literal type has a constexpr constructor, and that constructor is used to initialize an object of static storage duration such that all members and bases are initialized by constant expressions, constant initialization is performed. In this case, the object can still have a non-trivial destructor, and if it does, we must emit a dynamic initializer which performs no initialization and instead simply registers that destructor. llvm-svn: 150419 --- clang/lib/CodeGen/CodeGenModule.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index fde217e..2ebea59 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1359,7 +1359,9 @@ CharUnits CodeGenModule::GetTargetTypeStoreSize(llvm::Type *Ty) const { void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { llvm::Constant *Init = 0; QualType ASTTy = D->getType(); - bool NonConstInit = false; + CXXRecordDecl *RD = ASTTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + bool NeedsGlobalCtor = false; + bool NeedsGlobalDtor = RD && !RD->hasTrivialDestructor(); const VarDecl *InitDecl; const Expr *InitExpr = D->getAnyInitializer(InitDecl); @@ -1385,15 +1387,16 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { if (getLangOptions().CPlusPlus) { Init = EmitNullConstant(T); - NonConstInit = true; + NeedsGlobalCtor = true; } else { ErrorUnsupported(D, "static initializer"); Init = llvm::UndefValue::get(getTypes().ConvertType(T)); } } else { // We don't need an initializer, so remove the entry for the delayed - // initializer position (just in case this entry was delayed). - if (getLangOptions().CPlusPlus) + // initializer position (just in case this entry was delayed) if we + // also don't need to register a destructor. + if (getLangOptions().CPlusPlus && !NeedsGlobalDtor) DelayedCXXInitPosition.erase(D); } } @@ -1448,7 +1451,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { // If it is safe to mark the global 'constant', do so now. GV->setConstant(false); - if (!NonConstInit && DeclIsConstantGlobal(Context, D, true)) + if (!NeedsGlobalCtor && !NeedsGlobalDtor && + DeclIsConstantGlobal(Context, D, true)) GV->setConstant(true); GV->setAlignment(getContext().getDeclAlign(D).getQuantity()); @@ -1464,8 +1468,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { SetCommonAttributes(D, GV); // Emit the initializer function if necessary. - if (NonConstInit) - EmitCXXGlobalVarDeclInitFunc(D, GV); + if (NeedsGlobalCtor || NeedsGlobalDtor) + EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor); // Emit global variable debug information. if (CGDebugInfo *DI = getModuleDebugInfo()) -- cgit v1.1