aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGExpr.cpp')
-rw-r--r--lib/CodeGen/CGExpr.cpp253
1 files changed, 124 insertions, 129 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index a0dd158533..fe0d070105 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -228,157 +228,152 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
InitializedDecl);
}
- RValue RV;
if (E->isGLValue()) {
// Emit the expression as an lvalue.
LValue LV = CGF.EmitLValue(E);
+ assert(LV.isSimple());
+ return LV.getAddress();
+ }
+
+ if (!ObjCARCReferenceLifetimeType.isNull()) {
+ ReferenceTemporary = CreateReferenceTemporary(CGF,
+ ObjCARCReferenceLifetimeType,
+ InitializedDecl);
- if (LV.isSimple())
- return LV.getAddress();
- // We have to load the lvalue.
- RV = CGF.EmitLoadOfLValue(LV);
- } else {
- if (!ObjCARCReferenceLifetimeType.isNull()) {
- ReferenceTemporary = CreateReferenceTemporary(CGF,
- ObjCARCReferenceLifetimeType,
- InitializedDecl);
-
-
- LValue RefTempDst = CGF.MakeAddrLValue(ReferenceTemporary,
- ObjCARCReferenceLifetimeType);
+ LValue RefTempDst = CGF.MakeAddrLValue(ReferenceTemporary,
+ ObjCARCReferenceLifetimeType);
- CGF.EmitScalarInit(E, dyn_cast_or_null<ValueDecl>(InitializedDecl),
- RefTempDst, false);
-
- bool ExtendsLifeOfTemporary = false;
- if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(InitializedDecl)) {
- if (Var->extendsLifetimeOfTemporary())
- ExtendsLifeOfTemporary = true;
- } else if (InitializedDecl && isa<FieldDecl>(InitializedDecl)) {
+ CGF.EmitScalarInit(E, dyn_cast_or_null<ValueDecl>(InitializedDecl),
+ RefTempDst, false);
+
+ bool ExtendsLifeOfTemporary = false;
+ if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(InitializedDecl)) {
+ if (Var->extendsLifetimeOfTemporary())
ExtendsLifeOfTemporary = true;
- }
-
- if (!ExtendsLifeOfTemporary) {
- // Since the lifetime of this temporary isn't going to be extended,
- // we need to clean it up ourselves at the end of the full expression.
- switch (ObjCARCReferenceLifetimeType.getObjCLifetime()) {
- case Qualifiers::OCL_None:
- case Qualifiers::OCL_ExplicitNone:
- case Qualifiers::OCL_Autoreleasing:
- break;
-
- case Qualifiers::OCL_Strong: {
- assert(!ObjCARCReferenceLifetimeType->isArrayType());
- CleanupKind cleanupKind = CGF.getARCCleanupKind();
- CGF.pushDestroy(cleanupKind,
- ReferenceTemporary,
- ObjCARCReferenceLifetimeType,
- CodeGenFunction::destroyARCStrongImprecise,
- cleanupKind & EHCleanup);
- break;
- }
+ } else if (InitializedDecl && isa<FieldDecl>(InitializedDecl)) {
+ ExtendsLifeOfTemporary = true;
+ }
+
+ if (!ExtendsLifeOfTemporary) {
+ // Since the lifetime of this temporary isn't going to be extended,
+ // we need to clean it up ourselves at the end of the full expression.
+ switch (ObjCARCReferenceLifetimeType.getObjCLifetime()) {
+ case Qualifiers::OCL_None:
+ case Qualifiers::OCL_ExplicitNone:
+ case Qualifiers::OCL_Autoreleasing:
+ break;
- case Qualifiers::OCL_Weak:
- assert(!ObjCARCReferenceLifetimeType->isArrayType());
- CGF.pushDestroy(NormalAndEHCleanup,
- ReferenceTemporary,
- ObjCARCReferenceLifetimeType,
- CodeGenFunction::destroyARCWeak,
- /*useEHCleanupForArray*/ true);
- break;
- }
+ case Qualifiers::OCL_Strong: {
+ assert(!ObjCARCReferenceLifetimeType->isArrayType());
+ CleanupKind cleanupKind = CGF.getARCCleanupKind();
+ CGF.pushDestroy(cleanupKind,
+ ReferenceTemporary,
+ ObjCARCReferenceLifetimeType,
+ CodeGenFunction::destroyARCStrongImprecise,
+ cleanupKind & EHCleanup);
+ break;
+ }
- ObjCARCReferenceLifetimeType = QualType();
+ case Qualifiers::OCL_Weak:
+ assert(!ObjCARCReferenceLifetimeType->isArrayType());
+ CGF.pushDestroy(NormalAndEHCleanup,
+ ReferenceTemporary,
+ ObjCARCReferenceLifetimeType,
+ CodeGenFunction::destroyARCWeak,
+ /*useEHCleanupForArray*/ true);
+ break;
}
- return ReferenceTemporary;
- }
-
- SmallVector<SubobjectAdjustment, 2> Adjustments;
- E = E->skipRValueSubobjectAdjustments(Adjustments);
- if (const OpaqueValueExpr *opaque = dyn_cast<OpaqueValueExpr>(E))
- if (opaque->getType()->isRecordType())
- return CGF.EmitOpaqueValueLValue(opaque).getAddress();
-
- // Create a reference temporary if necessary.
- AggValueSlot AggSlot = AggValueSlot::ignored();
- if (CGF.hasAggregateEvaluationKind(E->getType())) {
- ReferenceTemporary = CreateReferenceTemporary(CGF, E->getType(),
- InitializedDecl);
- CharUnits Alignment = CGF.getContext().getTypeAlignInChars(E->getType());
- AggValueSlot::IsDestructed_t isDestructed
- = AggValueSlot::IsDestructed_t(InitializedDecl != 0);
- AggSlot = AggValueSlot::forAddr(ReferenceTemporary, Alignment,
- Qualifiers(), isDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased);
+ ObjCARCReferenceLifetimeType = QualType();
}
- if (InitializedDecl) {
- if (const InitListExpr *ILE = dyn_cast<InitListExpr>(E)) {
- if (ILE->initializesStdInitializerList()) {
- ReferenceInitializerList = ILE;
- }
- }
- else if (const RecordType *RT =
- E->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()){
- // Get the destructor for the reference temporary.
- CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
- if (!ClassDecl->hasTrivialDestructor())
- ReferenceTemporaryDtor = ClassDecl->getDestructor();
+ return ReferenceTemporary;
+ }
+
+ SmallVector<SubobjectAdjustment, 2> Adjustments;
+ E = E->skipRValueSubobjectAdjustments(Adjustments);
+ if (const OpaqueValueExpr *opaque = dyn_cast<OpaqueValueExpr>(E))
+ if (opaque->getType()->isRecordType())
+ return CGF.EmitOpaqueValueLValue(opaque).getAddress();
+
+ // Create a reference temporary if necessary.
+ AggValueSlot AggSlot = AggValueSlot::ignored();
+ if (CGF.hasAggregateEvaluationKind(E->getType())) {
+ ReferenceTemporary = CreateReferenceTemporary(CGF, E->getType(),
+ InitializedDecl);
+ CharUnits Alignment = CGF.getContext().getTypeAlignInChars(E->getType());
+ AggValueSlot::IsDestructed_t isDestructed
+ = AggValueSlot::IsDestructed_t(InitializedDecl != 0);
+ AggSlot = AggValueSlot::forAddr(ReferenceTemporary, Alignment,
+ Qualifiers(), isDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased);
+ }
+
+ if (InitializedDecl) {
+ if (const InitListExpr *ILE = dyn_cast<InitListExpr>(E)) {
+ if (ILE->initializesStdInitializerList()) {
+ ReferenceInitializerList = ILE;
}
}
+ else if (const RecordType *RT =
+ E->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()){
+ // Get the destructor for the reference temporary.
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (!ClassDecl->hasTrivialDestructor())
+ ReferenceTemporaryDtor = ClassDecl->getDestructor();
+ }
+ }
- RV = CGF.EmitAnyExpr(E, AggSlot);
-
- // Check if need to perform derived-to-base casts and/or field accesses, to
- // get from the temporary object we created (and, potentially, for which we
- // extended the lifetime) to the subobject we're binding the reference to.
- if (!Adjustments.empty()) {
- llvm::Value *Object = RV.getAggregateAddr();
- for (unsigned I = Adjustments.size(); I != 0; --I) {
- SubobjectAdjustment &Adjustment = Adjustments[I-1];
- switch (Adjustment.Kind) {
- case SubobjectAdjustment::DerivedToBaseAdjustment:
- Object =
- CGF.GetAddressOfBaseClass(Object,
- Adjustment.DerivedToBase.DerivedClass,
- Adjustment.DerivedToBase.BasePath->path_begin(),
- Adjustment.DerivedToBase.BasePath->path_end(),
- /*NullCheckValue=*/false);
- break;
-
- case SubobjectAdjustment::FieldAdjustment: {
- LValue LV = CGF.MakeAddrLValue(Object, E->getType());
- LV = CGF.EmitLValueForField(LV, Adjustment.Field);
- if (LV.isSimple()) {
- Object = LV.getAddress();
- break;
- }
+ RValue RV = CGF.EmitAnyExpr(E, AggSlot);
+
+ // Check if need to perform derived-to-base casts and/or field accesses, to
+ // get from the temporary object we created (and, potentially, for which we
+ // extended the lifetime) to the subobject we're binding the reference to.
+ if (!Adjustments.empty()) {
+ llvm::Value *Object = RV.getAggregateAddr();
+ for (unsigned I = Adjustments.size(); I != 0; --I) {
+ SubobjectAdjustment &Adjustment = Adjustments[I-1];
+ switch (Adjustment.Kind) {
+ case SubobjectAdjustment::DerivedToBaseAdjustment:
+ Object =
+ CGF.GetAddressOfBaseClass(Object,
+ Adjustment.DerivedToBase.DerivedClass,
+ Adjustment.DerivedToBase.BasePath->path_begin(),
+ Adjustment.DerivedToBase.BasePath->path_end(),
+ /*NullCheckValue=*/false);
+ break;
- // For non-simple lvalues, we actually have to create a copy of
- // the object we're binding to.
- QualType T = Adjustment.Field->getType().getNonReferenceType()
- .getUnqualifiedType();
- Object = CreateReferenceTemporary(CGF, T, InitializedDecl);
- LValue TempLV = CGF.MakeAddrLValue(Object,
- Adjustment.Field->getType());
- CGF.EmitStoreThroughLValue(CGF.EmitLoadOfLValue(LV), TempLV);
- break;
- }
-
- case SubobjectAdjustment::MemberPointerAdjustment: {
- llvm::Value *Ptr = CGF.EmitScalarExpr(Adjustment.Ptr.RHS);
- Object = CGF.CGM.getCXXABI().EmitMemberDataPointerAddress(
- CGF, Object, Ptr, Adjustment.Ptr.MPT);
+ case SubobjectAdjustment::FieldAdjustment: {
+ LValue LV = CGF.MakeAddrLValue(Object, E->getType());
+ LV = CGF.EmitLValueForField(LV, Adjustment.Field);
+ if (LV.isSimple()) {
+ Object = LV.getAddress();
break;
}
- }
+
+ // For non-simple lvalues, we actually have to create a copy of
+ // the object we're binding to.
+ QualType T = Adjustment.Field->getType().getNonReferenceType()
+ .getUnqualifiedType();
+ Object = CreateReferenceTemporary(CGF, T, InitializedDecl);
+ LValue TempLV = CGF.MakeAddrLValue(Object,
+ Adjustment.Field->getType());
+ CGF.EmitStoreThroughLValue(CGF.EmitLoadOfLValue(LV), TempLV);
+ break;
}
- return Object;
+ case SubobjectAdjustment::MemberPointerAdjustment: {
+ llvm::Value *Ptr = CGF.EmitScalarExpr(Adjustment.Ptr.RHS);
+ Object = CGF.CGM.getCXXABI().EmitMemberDataPointerAddress(
+ CGF, Object, Ptr, Adjustment.Ptr.MPT);
+ break;
+ }
+ }
}
+
+ return Object;
}
if (RV.isAggregate())