diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-13 22:16:19 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-13 22:16:19 +0000 |
commit | 7ca4850a3e3530fa6c93b64b740446e32c97f992 (patch) | |
tree | 4bdd8740e76bd15404199f6d10d6930bbab91cf3 /lib/CodeGen/CodeGenModule.cpp | |
parent | 5ad3af90dd09b482c61dca565be4b50efcd8021d (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150419 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CodeGenModule.cpp')
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index fde217efec..2ebea59264 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/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()) |