diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 18 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 41 |
2 files changed, 43 insertions, 16 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 034525cff67..cbad66c8bc8 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -321,6 +321,13 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr( llvm::Value *Object = createReferenceTemporary(*this, M, E); LValue RefTempDst = MakeAddrLValue(Object, M->getType()); + if (llvm::GlobalVariable *Var = dyn_cast<llvm::GlobalVariable>(Object)) { + // We should not have emitted the initializer for this temporary as a + // constant. + assert(!Var->hasInitializer()); + Var->setInitializer(CGM.EmitNullConstant(E->getType())); + } + EmitScalarInit(E, M->getExtendingDecl(), RefTempDst, false); pushTemporaryCleanup(*this, M, E, Object); @@ -343,7 +350,16 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr( // Create and initialize the reference temporary. llvm::Value *Object = createReferenceTemporary(*this, M, E); - EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true); + if (llvm::GlobalVariable *Var = dyn_cast<llvm::GlobalVariable>(Object)) { + // If the temporary is a global and has a constant initializer, we may + // have already initialized it. + if (!Var->hasInitializer()) { + Var->setInitializer(CGM.EmitNullConstant(E->getType())); + EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true); + } + } else { + EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true); + } pushTemporaryCleanup(*this, M, E, Object); // Perform derived-to-base casts and/or field accesses, to get from the diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 4865a9174c9..824d2a04662 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2615,15 +2615,16 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &Str, } llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary( - const MaterializeTemporaryExpr *E, const Expr *Inner) { + const MaterializeTemporaryExpr *E, const Expr *Init) { assert((E->getStorageDuration() == SD_Static || E->getStorageDuration() == SD_Thread) && "not a global temporary"); const VarDecl *VD = cast<VarDecl>(E->getExtendingDecl()); // If we're not materializing a subobject of the temporary, keep the // cv-qualifiers from the type of the MaterializeTemporaryExpr. - if (Inner == E->GetTemporaryExpr()) - Inner = E; + QualType MaterializedType = Init->getType(); + if (Init == E->GetTemporaryExpr()) + MaterializedType = E->getType(); llvm::Constant *&Slot = MaterializedGlobalTemporaryMap[E]; if (Slot) @@ -2637,34 +2638,44 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalTemporary( getCXXABI().getMangleContext().mangleReferenceTemporary(VD, Out); Out.flush(); - llvm::Constant *InitialValue = 0; APValue *Value = 0; if (E->getStorageDuration() == SD_Static) { - // We might have a constant initializer for this temporary. + // We might have a cached constant initializer for this temporary. Note + // that this might have a different value from the value computed by + // evaluating the initializer if the surrounding constant expression + // modifies the temporary. Value = getContext().getMaterializedTemporaryValue(E, false); if (Value && Value->isUninit()) Value = 0; } - bool Constant; + // Try evaluating it now, it might have a constant initializer. + Expr::EvalResult EvalResult; + if (!Value && Init->EvaluateAsRValue(EvalResult, getContext()) && + !EvalResult.hasSideEffects()) + Value = &EvalResult.Val; + + llvm::Constant *InitialValue = 0; + bool Constant = false; + llvm::Type *Type; if (Value) { // The temporary has a constant initializer, use it. - InitialValue = EmitConstantValue(*Value, Inner->getType(), 0); - Constant = isTypeConstant(Inner->getType(), /*ExcludeCtor*/Value); + InitialValue = EmitConstantValue(*Value, MaterializedType, 0); + Constant = isTypeConstant(MaterializedType, /*ExcludeCtor*/Value); + Type = InitialValue->getType(); } else { - // No constant initializer, the initialization will be provided when we + // No initializer, the initialization will be provided when we // initialize the declaration which performed lifetime extension. - InitialValue = EmitNullConstant(Inner->getType()); - Constant = false; + Type = getTypes().ConvertTypeForMem(MaterializedType); } // Create a global variable for this lifetime-extended temporary. llvm::GlobalVariable *GV = - new llvm::GlobalVariable(getModule(), InitialValue->getType(), Constant, - llvm::GlobalValue::PrivateLinkage, InitialValue, - Name.c_str()); + new llvm::GlobalVariable(getModule(), Type, Constant, + llvm::GlobalValue::PrivateLinkage, + InitialValue, Name.c_str()); GV->setAlignment( - getContext().getTypeAlignInChars(Inner->getType()).getQuantity()); + getContext().getTypeAlignInChars(MaterializedType).getQuantity()); if (VD->getTLSKind()) setTLSMode(GV, *VD); Slot = GV; |