From: Anders Carlsson Date: Sun, 16 Aug 2009 07:36:22 +0000 (+0000) Subject: Add an IsInitializer flag to EmitAnyExpr. This is used to prevent temporaries from... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=14c5cbf59cffee52275230922283a247de407712;p=clang Add an IsInitializer flag to EmitAnyExpr. This is used to prevent temporaries from being destroyed when they're bound to a reference variable. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79179 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCXXTemp.cpp b/lib/CodeGen/CGCXXTemp.cpp index 04d3842daa..30de1115c0 100644 --- a/lib/CodeGen/CGCXXTemp.cpp +++ b/lib/CodeGen/CGCXXTemp.cpp @@ -84,11 +84,13 @@ void CodeGenFunction::PopCXXTemporary() { RValue CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, llvm::Value *AggLoc, - bool isAggLocVolatile) { + bool IsAggLocVolatile, + bool IsInitializer) { // If we shouldn't destroy the temporaries, just emit the // child expression. if (!E->shouldDestroyTemporaries()) - return EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile); + return EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile, + /*IgnoreResult=*/false, IsInitializer); // Keep track of the current cleanup stack depth. size_t CleanupStackDepth = CleanupEntries.size(); @@ -96,7 +98,8 @@ CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, unsigned OldNumLiveTemporaries = LiveTemporaries.size(); - RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile); + RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile, + /*IgnoreResult=*/false, IsInitializer); // Pop temporaries. while (LiveTemporaries.size() > OldNumLiveTemporaries) diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index c12f23130e..cadd964950 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -361,8 +361,8 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { Loc = Builder.CreateStructGEP(DeclPtr, needsCopyDispose*2+4, "x"); } if (Ty->isReferenceType()) { - llvm::Value *V = EmitReferenceBindingToExpr(Init, Ty).getScalarVal(); - EmitStoreOfScalar(V, Loc, false, Ty); + RValue RV = EmitReferenceBindingToExpr(Init, Ty, /*IsInitializer=*/true); + EmitStoreOfScalar(RV.getScalarVal(), Loc, false, Ty); } else if (!hasAggregateLLVMType(Init->getType())) { llvm::Value *V = EmitScalarExpr(Init); EmitStoreOfScalar(V, Loc, D.getType().isVolatileQualified(), diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index d806fb3b72..3818f56df9 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -49,30 +49,36 @@ llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) { /// aggregate expression, the aggloc/agglocvolatile arguments indicate where /// the result should be returned. RValue CodeGenFunction::EmitAnyExpr(const Expr *E, llvm::Value *AggLoc, - bool isAggLocVolatile, bool IgnoreResult) { + bool IsAggLocVolatile, bool IgnoreResult, + bool IsInitializer) { if (!hasAggregateLLVMType(E->getType())) return RValue::get(EmitScalarExpr(E, IgnoreResult)); else if (E->getType()->isAnyComplexType()) return RValue::getComplex(EmitComplexExpr(E, false, false, IgnoreResult, IgnoreResult)); - EmitAggExpr(E, AggLoc, isAggLocVolatile, IgnoreResult); - return RValue::getAggregate(AggLoc, isAggLocVolatile); + EmitAggExpr(E, AggLoc, IsAggLocVolatile, IgnoreResult, IsInitializer); + return RValue::getAggregate(AggLoc, IsAggLocVolatile); } /// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result /// will always be accessible even if no aggregate location is /// provided. -RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E, llvm::Value *AggLoc, - bool isAggLocVolatile) { - if (!AggLoc && hasAggregateLLVMType(E->getType()) && +RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E, + bool IsAggLocVolatile, + bool IsInitializer) { + llvm::Value *AggLoc = 0; + + if (hasAggregateLLVMType(E->getType()) && !E->getType()->isAnyComplexType()) AggLoc = CreateTempAlloca(ConvertType(E->getType()), "agg.tmp"); - return EmitAnyExpr(E, AggLoc, isAggLocVolatile); + return EmitAnyExpr(E, AggLoc, IsAggLocVolatile, /*IgnoreResult=*/false, + IsInitializer); } RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, - QualType DestType) { + QualType DestType, + bool IsInitializer) { RValue Val; if (E->isLvalue(getContext()) == Expr::LV_Valid) { // Emit the expr as an lvalue. @@ -81,7 +87,8 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E, return RValue::get(LV.getAddress()); Val = EmitLoadOfLValue(LV, E->getType()); } else { - Val = EmitAnyExprToTemp(E); + Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false, + IsInitializer); } if (Val.isAggregate()) { diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 0cf9cd3e3a..68341a12b1 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -36,12 +36,13 @@ class VISIBILITY_HIDDEN AggExprEmitter : public StmtVisitor { llvm::Value *DestPtr; bool VolatileDest; bool IgnoreResult; - + bool IsInitializer; public: AggExprEmitter(CodeGenFunction &cgf, llvm::Value *destPtr, bool v, - bool ignore) + bool ignore, bool isinit) : CGF(cgf), Builder(CGF.Builder), - DestPtr(destPtr), VolatileDest(v), IgnoreResult(ignore) { + DestPtr(destPtr), VolatileDest(v), IgnoreResult(ignore), + IsInitializer(isinit) { } //===--------------------------------------------------------------------===// @@ -214,7 +215,8 @@ void AggExprEmitter::VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) { void AggExprEmitter::VisitBinComma(const BinaryOperator *E) { CGF.EmitAnyExpr(E->getLHS(), 0, false, true); - CGF.EmitAggExpr(E->getRHS(), DestPtr, VolatileDest); + CGF.EmitAggExpr(E->getRHS(), DestPtr, VolatileDest, + /*IgnoreResult=*/false, IsInitializer); } void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) { @@ -323,7 +325,9 @@ void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { } else Visit(E->getSubExpr()); - CGF.PushCXXTemporary(E->getTemporary(), Val); + // Don't make this a live temporary if we're emitting an initializer expr. + if (!IsInitializer) + CGF.PushCXXTemporary(E->getTemporary(), Val); } void @@ -339,7 +343,7 @@ AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) { } void AggExprEmitter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { - CGF.EmitCXXExprWithTemporaries(E, DestPtr, VolatileDest); + CGF.EmitCXXExprWithTemporaries(E, DestPtr, VolatileDest, IsInitializer); } void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) { @@ -510,13 +514,14 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { /// the value of the aggregate expression is not needed. If VolatileDest is /// true, DestPtr cannot be 0. void CodeGenFunction::EmitAggExpr(const Expr *E, llvm::Value *DestPtr, - bool VolatileDest, bool IgnoreResult) { + bool VolatileDest, bool IgnoreResult, + bool IsInitializer) { assert(E && hasAggregateLLVMType(E->getType()) && "Invalid aggregate expression to emit"); assert ((DestPtr != 0 || VolatileDest == false) && "volatile aggregate can't be 0"); - AggExprEmitter(*this, DestPtr, VolatileDest, IgnoreResult) + AggExprEmitter(*this, DestPtr, VolatileDest, IgnoreResult, IsInitializer) .Visit(const_cast(E)); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 3110ac00af..3bf17b32b3 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -513,7 +513,8 @@ public: /// /// \param IgnoreResult - True if the resulting value isn't used. RValue EmitAnyExpr(const Expr *E, llvm::Value *AggLoc = 0, - bool isAggLocVolatile = false, bool IgnoreResult = false); + bool IsAggLocVolatile = false, bool IgnoreResult = false, + bool IsInitializer = false); // EmitVAListRef - Emit a "reference" to a va_list; this is either the address // or the value of the expression, depending on how va_list is defined. @@ -521,8 +522,8 @@ public: /// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result will /// always be accessible even if no aggregate location is provided. - RValue EmitAnyExprToTemp(const Expr *E, llvm::Value *AggLoc = 0, - bool isAggLocVolatile = false); + RValue EmitAnyExprToTemp(const Expr *E, bool IsAggLocVolatile = false, + bool IsInitializer = false); /// EmitAggregateCopy - Emit an aggrate copy. /// @@ -862,7 +863,8 @@ public: /// EmitReferenceBindingToExpr - Emits a reference binding to the passed in /// expression. Will emit a temporary variable if E is not an LValue. - RValue EmitReferenceBindingToExpr(const Expr* E, QualType DestType); + RValue EmitReferenceBindingToExpr(const Expr* E, QualType DestType, + bool IsInitializer = false); //===--------------------------------------------------------------------===// // Expression Emission @@ -872,7 +874,7 @@ public: /// EmitScalarExpr - Emit the computation of the specified expression of LLVM /// scalar type, returning the result. - llvm::Value *EmitScalarExpr(const Expr *E , bool IgnoreResultAssign=false); + llvm::Value *EmitScalarExpr(const Expr *E , bool IgnoreResultAssign = false); /// EmitScalarConversion - Emit a conversion from the specified type to the /// specified destination type, both of which are LLVM scalar types. @@ -890,7 +892,7 @@ public: /// aggregate type. The result is computed into DestPtr. Note that if /// DestPtr is null, the value of the aggregate expression is not needed. void EmitAggExpr(const Expr *E, llvm::Value *DestPtr, bool VolatileDest, - bool IgnoreResult = false); + bool IgnoreResult = false, bool IsInitializer = false); /// EmitGCMemmoveCollectable - Emit special API for structs with object /// pointers. @@ -946,7 +948,8 @@ public: RValue EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, llvm::Value *AggLoc = 0, - bool isAggLocVolatile = false); + bool IsAggLocVolatile = false, + bool IsInitializer = false); //===--------------------------------------------------------------------===// // Internal Helpers