void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { // For an assignment to work, the value on the right has // to be compatible with the value on the left. assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(), E->getRHS()->getType()) && "Invalid assignment"); LValue LHS = CGF.EmitLValue(E->getLHS()); // We have to special case property setters, otherwise we must have // a simple lvalue (no aggregates inside vectors, bitfields). if (LHS.isPropertyRef()) { llvm::Value *AggLoc = DestPtr; if (!AggLoc) AggLoc = CGF.CreateMemTemp(E->getRHS()->getType()); CGF.EmitAggExpr(E->getRHS(), AggLoc, VolatileDest); CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(), RValue::getAggregate(AggLoc, VolatileDest)); } else if (LHS.isKVCRef()) { llvm::Value *AggLoc = DestPtr; if (!AggLoc) AggLoc = CGF.CreateMemTemp(E->getRHS()->getType()); CGF.EmitAggExpr(E->getRHS(), AggLoc, VolatileDest); CGF.EmitObjCPropertySet(LHS.getKVCRefExpr(), RValue::getAggregate(AggLoc, VolatileDest)); } else { bool RequiresGCollection = false; if (CGF.getContext().getLangOptions().getGCMode()) RequiresGCollection = TypeRequiresGCollection(E->getLHS()->getType()); // Codegen the RHS so that it stores directly into the LHS. CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), LHS.isVolatileQualified(), false, false, RequiresGCollection); EmitFinalDestCopy(E, LHS, true); } }
void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { // For an assignment to work, the value on the right has // to be compatible with the value on the left. assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(), E->getRHS()->getType()) && "Invalid assignment"); if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->getLHS())) if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) if (VD->hasAttr<BlocksAttr>() && E->getRHS()->HasSideEffects(CGF.getContext())) { // When __block variable on LHS, the RHS must be evaluated first // as it may change the 'forwarding' field via call to Block_copy. LValue RHS = CGF.EmitLValue(E->getRHS()); LValue LHS = CGF.EmitLValue(E->getLHS()); bool GCollection = false; if (CGF.getContext().getLangOptions().getGCMode()) GCollection = TypeRequiresGCollection(E->getLHS()->getType()); Dest = AggValueSlot::forLValue(LHS, true, GCollection); EmitFinalDestCopy(E, RHS, true); return; } LValue LHS = CGF.EmitLValue(E->getLHS()); // We have to special case property setters, otherwise we must have // a simple lvalue (no aggregates inside vectors, bitfields). if (LHS.isPropertyRef()) { const ObjCPropertyRefExpr *RE = LHS.getPropertyRefExpr(); QualType ArgType = RE->getSetterArgType(); RValue Src; if (ArgType->isReferenceType()) Src = CGF.EmitReferenceBindingToExpr(E->getRHS(), 0); else { AggValueSlot Slot = EnsureSlot(E->getRHS()->getType()); CGF.EmitAggExpr(E->getRHS(), Slot); Src = Slot.asRValue(); } CGF.EmitStoreThroughPropertyRefLValue(Src, LHS); } else { bool GCollection = false; if (CGF.getContext().getLangOptions().getGCMode()) GCollection = TypeRequiresGCollection(E->getLHS()->getType()); // Codegen the RHS so that it stores directly into the LHS. AggValueSlot LHSSlot = AggValueSlot::forLValue(LHS, true, GCollection); CGF.EmitAggExpr(E->getRHS(), LHSSlot, false); EmitFinalDestCopy(E, LHS, true); } }