diff options
Diffstat (limited to 'lib')
30 files changed, 1456 insertions, 650 deletions
diff --git a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp index bf2517f119..6eb82093cf 100644 --- a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp +++ b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp @@ -160,12 +160,14 @@ private: if (!E) return false; E = E->IgnoreParenCasts(); + + // Also look through property-getter sugar. + if (PseudoObjectExpr *pseudoOp = dyn_cast<PseudoObjectExpr>(E)) + E = pseudoOp->getResultExpr()->IgnoreImplicit(); + if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) return (ME->isInstanceMessage() && ME->getSelector() == DelegateSel); - if (ObjCPropertyRefExpr *propE = dyn_cast<ObjCPropertyRefExpr>(E)) - return propE->getGetterSelector() == DelegateSel; - return false; } diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp index 69fb2e8949..3bfa15c6e0 100644 --- a/lib/ARCMigrate/TransUnbridgedCasts.cpp +++ b/lib/ARCMigrate/TransUnbridgedCasts.cpp @@ -236,7 +236,15 @@ private: } } - if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E->getSubExpr())){ + Expr *subExpr = E->getSubExpr(); + + // Look through pseudo-object expressions. + if (PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(subExpr)) { + subExpr = pseudo->getResultExpr(); + assert(subExpr && "no result for pseudo-object of non-void type?"); + } + + if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(subExpr)) { if (implCE->getCastKind() == CK_ARCConsumeObject) return rewriteToBridgedCast(E, OBC_BridgeRetained); if (implCE->getCastKind() == CK_ARCReclaimReturnedObject) diff --git a/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp b/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp index 7c533bcf3a..d1f08aac28 100644 --- a/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp +++ b/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp @@ -78,6 +78,15 @@ public: return true; } + bool VisitPseudoObjectExpr(PseudoObjectExpr *POE) { + if (isZeroingPropIvar(POE) && isRemovable(POE)) { + Transaction Trans(Pass.TA); + Pass.TA.removeStmt(POE); + } + + return true; + } + bool VisitBinaryOperator(BinaryOperator *BOE) { if (isZeroingPropIvar(BOE) && isRemovable(BOE)) { Transaction Trans(Pass.TA); @@ -142,17 +151,21 @@ private: } bool isZeroingPropIvar(Expr *E) { - BinaryOperator *BOE = dyn_cast_or_null<BinaryOperator>(E); - if (!BOE) return false; + E = E->IgnoreParens(); + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) + return isZeroingPropIvar(BO); + if (PseudoObjectExpr *PO = dyn_cast<PseudoObjectExpr>(E)) + return isZeroingPropIvar(PO); + return false; + } + bool isZeroingPropIvar(BinaryOperator *BOE) { if (BOE->getOpcode() == BO_Comma) return isZeroingPropIvar(BOE->getLHS()) && isZeroingPropIvar(BOE->getRHS()); if (BOE->getOpcode() != BO_Assign) - return false; - - ASTContext &Ctx = Pass.Ctx; + return false; Expr *LHS = BOE->getLHS(); if (ObjCIvarRefExpr *IV = dyn_cast<ObjCIvarRefExpr>(LHS)) { @@ -172,25 +185,38 @@ private: if (!IvarBacksPropertySynthesis) return false; } - else if (ObjCPropertyRefExpr *PropRefExp = dyn_cast<ObjCPropertyRefExpr>(LHS)) { - // TODO: Using implicit property decl. - if (PropRefExp->isImplicitProperty()) - return false; - if (ObjCPropertyDecl *PDecl = PropRefExp->getExplicitProperty()) { - if (!SynthesizedProperties.count(PDecl)) - return false; - } - } else return false; - Expr *RHS = BOE->getRHS(); - bool RHSIsNull = RHS->isNullPointerConstant(Ctx, - Expr::NPC_ValueDependentIsNull); - if (RHSIsNull) + return isZero(BOE->getRHS()); + } + + bool isZeroingPropIvar(PseudoObjectExpr *PO) { + BinaryOperator *BO = dyn_cast<BinaryOperator>(PO->getSyntacticForm()); + if (!BO) return false; + if (BO->getOpcode() != BO_Assign) return false; + + ObjCPropertyRefExpr *PropRefExp = + dyn_cast<ObjCPropertyRefExpr>(BO->getLHS()->IgnoreParens()); + if (!PropRefExp) return false; + + // TODO: Using implicit property decl. + if (PropRefExp->isImplicitProperty()) + return false; + + if (ObjCPropertyDecl *PDecl = PropRefExp->getExplicitProperty()) { + if (!SynthesizedProperties.count(PDecl)) + return false; + } + + return isZero(cast<OpaqueValueExpr>(BO->getRHS())->getSourceExpr()); + } + + bool isZero(Expr *E) { + if (E->isNullPointerConstant(Pass.Ctx, Expr::NPC_ValueDependentIsNull)) return true; - return isZeroingPropIvar(RHS); + return isZeroingPropIvar(E); } }; diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index a4daea2287..4c31bbd3d7 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -640,7 +640,11 @@ void Decl::CheckAccessDeclContext() const { } DeclContext *Decl::getNonClosureContext() { - DeclContext *DC = getDeclContext(); + return getDeclContext()->getNonClosureAncestor(); +} + +DeclContext *DeclContext::getNonClosureAncestor() { + DeclContext *DC = this; // This is basically "while (DC->isClosure()) DC = DC->getParent();" // except that it's significantly more efficient to cast to a known diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 3239973688..6eb6116b01 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1694,6 +1694,19 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, R1 = getSourceRange(); return true; + case PseudoObjectExprClass: { + const PseudoObjectExpr *PO = cast<PseudoObjectExpr>(this); + + // Only complain about things that have the form of a getter. + if (isa<UnaryOperator>(PO->getSyntacticForm()) || + isa<BinaryOperator>(PO->getSyntacticForm())) + return false; + + Loc = getExprLoc(); + R1 = getSourceRange(); + return true; + } + case StmtExprClass: { // Statement exprs don't logically have side effects themselves, but are // sometimes used in macros in ways that give them a type that is unused. @@ -2598,6 +2611,9 @@ Expr::isNullPointerConstant(ASTContext &Ctx, } else if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(this)) { return M->GetTemporaryExpr()->isNullPointerConstant(Ctx, NPC); + } else if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(this)) { + if (const Expr *Source = OVE->getSourceExpr()) + return Source->isNullPointerConstant(Ctx, NPC); } // C++0x nullptr_t is always a null pointer constant. @@ -3306,6 +3322,72 @@ const OpaqueValueExpr *OpaqueValueExpr::findInCopyConstruct(const Expr *e) { return cast<OpaqueValueExpr>(e); } +PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &Context, EmptyShell sh, + unsigned numSemanticExprs) { + void *buffer = Context.Allocate(sizeof(PseudoObjectExpr) + + (1 + numSemanticExprs) * sizeof(Expr*), + llvm::alignOf<PseudoObjectExpr>()); + return new(buffer) PseudoObjectExpr(sh, numSemanticExprs); +} + +PseudoObjectExpr::PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs) + : Expr(PseudoObjectExprClass, shell) { + PseudoObjectExprBits.NumSubExprs = numSemanticExprs + 1; +} + +PseudoObjectExpr *PseudoObjectExpr::Create(ASTContext &C, Expr *syntax, + ArrayRef<Expr*> semantics, + unsigned resultIndex) { + assert(syntax && "no syntactic expression!"); + assert(semantics.size() && "no semantic expressions!"); + + QualType type; + ExprValueKind VK; + if (resultIndex == NoResult) { + type = C.VoidTy; + VK = VK_RValue; + } else { + assert(resultIndex < semantics.size()); + type = semantics[resultIndex]->getType(); + VK = semantics[resultIndex]->getValueKind(); + assert(semantics[resultIndex]->getObjectKind() == OK_Ordinary); + } + + void *buffer = C.Allocate(sizeof(PseudoObjectExpr) + + (1 + semantics.size()) * sizeof(Expr*), + llvm::alignOf<PseudoObjectExpr>()); + return new(buffer) PseudoObjectExpr(type, VK, syntax, semantics, + resultIndex); +} + +PseudoObjectExpr::PseudoObjectExpr(QualType type, ExprValueKind VK, + Expr *syntax, ArrayRef<Expr*> semantics, + unsigned resultIndex) + : Expr(PseudoObjectExprClass, type, VK, OK_Ordinary, + /*filled in at end of ctor*/ false, false, false, false) { + PseudoObjectExprBits.NumSubExprs = semantics.size() + 1; + PseudoObjectExprBits.ResultIndex = resultIndex + 1; + + for (unsigned i = 0, e = semantics.size() + 1; i != e; ++i) { + Expr *E = (i == 0 ? syntax : semantics[i-1]); + getSubExprsBuffer()[i] = E; + + if (E->isTypeDependent()) + ExprBits.TypeDependent = true; + if (E->isValueDependent()) + ExprBits.ValueDependent = true; + if (E->isInstantiationDependent()) + ExprBits.InstantiationDependent = true; + if (E->containsUnexpandedParameterPack()) + ExprBits.ContainsUnexpandedParameterPack = true; + + if (isa<OpaqueValueExpr>(E)) + assert(cast<OpaqueValueExpr>(E)->getSourceExpr() != 0 && + "opaque-value semantic expressions for pseudo-object " + "operations must have sources"); + } +} + //===----------------------------------------------------------------------===// // ExprIterator. //===----------------------------------------------------------------------===// diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 594ae69ec4..1251b96fba 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -232,6 +232,11 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return ClassifyExprValueKind(Lang, E, cast<OpaqueValueExpr>(E)->getValueKind()); + // Pseudo-object expressions can produce l-values with reference magic. + case Expr::PseudoObjectExprClass: + return ClassifyExprValueKind(Lang, E, + cast<PseudoObjectExpr>(E)->getValueKind()); + // Implicit casts are lvalues if they're lvalue casts. Other than that, we // only specifically record class temporaries. case Expr::ImplicitCastExprClass: diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 3011b7f25f..9c9e473f7b 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -3450,6 +3450,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { case Expr::AsTypeExprClass: case Expr::ObjCIndirectCopyRestoreExprClass: case Expr::MaterializeTemporaryExprClass: + case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: return ICEDiag(2, E->getLocStart()); diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 889cf513bb..b2e1d20ca0 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -2257,6 +2257,7 @@ recurse: case Expr::CXXNoexceptExprClass: case Expr::CUDAKernelCallExprClass: case Expr::AsTypeExprClass: + case Expr::PseudoObjectExprClass: case Expr::AtomicExprClass: { // As bad as this diagnostic is, it's better than crashing. diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index 54e62fe35b..2248343199 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -148,6 +148,7 @@ namespace { void VisitCompoundAssignOperator(CompoundAssignOperator *Node); void VisitAddrLabelExpr(AddrLabelExpr *Node); void VisitBlockExpr(BlockExpr *Node); + void VisitOpaqueValueExpr(OpaqueValueExpr *Node); // C++ void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node); @@ -524,6 +525,15 @@ void StmtDumper::VisitBlockExpr(BlockExpr *Node) { DumpSubTree(block->getBody()); } +void StmtDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) { + DumpExpr(Node); + + if (Expr *Source = Node->getSourceExpr()) { + OS << '\n'; + DumpSubTree(Source); + } +} + // GNU extensions. void StmtDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) { diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 5b1654c924..04617bf9ac 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1027,6 +1027,10 @@ void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) { OS << ")"; } +void StmtPrinter::VisitPseudoObjectExpr(PseudoObjectExpr *Node) { + PrintExpr(Node->getSyntacticForm()); +} + void StmtPrinter::VisitAtomicExpr(AtomicExpr *Node) { const char *Name = 0; switch (Node->getOp()) { diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index db97e59804..5a6b771b9a 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -475,6 +475,15 @@ void StmtProfiler::VisitGenericSelectionExpr(const GenericSelectionExpr *S) { } } +void StmtProfiler::VisitPseudoObjectExpr(const PseudoObjectExpr *S) { + VisitExpr(S); + for (PseudoObjectExpr::const_semantics_iterator + i = S->semantics_begin(), e = S->semantics_end(); i != e; ++i) + // Normally, we would not profile the source expressions of OVEs. + if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(*i)) + Visit(OVE->getSourceExpr()); +} + void StmtProfiler::VisitAtomicExpr(const AtomicExpr *S) { VisitExpr(S); ID.AddInteger(S->getOp()); diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 48888f672e..73879214f3 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -344,6 +344,7 @@ private: CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S); CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S); CFGBlock *VisitReturnStmt(ReturnStmt *R); + CFGBlock *VisitPseudoObjectExpr(PseudoObjectExpr *E); CFGBlock *VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E, AddStmtChoice asc); CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc); @@ -981,6 +982,9 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) { case Stmt::OpaqueValueExprClass: return Block; + case Stmt::PseudoObjectExprClass: + return VisitPseudoObjectExpr(cast<PseudoObjectExpr>(S)); + case Stmt::ReturnStmtClass: return VisitReturnStmt(cast<ReturnStmt>(S)); @@ -1907,6 +1911,31 @@ CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { return NYS(); } +CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) { + autoCreateBlock(); + + // Add the PseudoObject as the last thing. + appendStmt(Block, E); + + CFGBlock *lastBlock = Block; + + // Before that, evaluate all of the semantics in order. In + // CFG-land, that means appending them in reverse order. + for (unsigned i = E->getNumSemanticExprs(); i != 0; ) { + Expr *Semantic = E->getSemanticExpr(--i); + + // If the semantic is an opaque value, we're being asked to bind + // it to its source expression. + if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic)) + Semantic = OVE->getSourceExpr(); + + if (CFGBlock *B = Visit(Semantic)) + lastBlock = B; + } + + return lastBlock; +} + CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) { CFGBlock *LoopSuccessor = NULL; diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp index cd6f09f2a7..f0dbc532b2 100644 --- a/lib/Analysis/LiveVariables.cpp +++ b/lib/Analysis/LiveVariables.cpp @@ -288,6 +288,18 @@ void TransferFunctions::Visit(Stmt *S) { } break; } + case Stmt::PseudoObjectExprClass: { + // A pseudo-object operation only directly consumes its result + // expression. + Expr *child = cast<PseudoObjectExpr>(S)->getResultExpr(); + if (!child) return; + if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(child)) + child = OV->getSourceExpr(); + child = child->IgnoreParens(); + val.liveStmts = LV.SSetFact.add(val.liveStmts, child); + return; + } + // FIXME: These cases eventually shouldn't be needed. case Stmt::ExprWithCleanupsClass: { S = cast<ExprWithCleanups>(S)->getSubExpr(); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 9ad3ae8352..d7371141f3 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -672,6 +672,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { return EmitStringLiteralLValue(cast<StringLiteral>(E)); case Expr::ObjCEncodeExprClass: return EmitObjCEncodeExprLValue(cast<ObjCEncodeExpr>(E)); + case Expr::PseudoObjectExprClass: + return EmitPseudoObjectLValue(cast<PseudoObjectExpr>(E)); case Expr::BlockDeclRefExprClass: return EmitBlockDeclRefLValue(cast<BlockDeclRefExpr>(E)); @@ -2768,3 +2770,86 @@ void CodeGenFunction::SetFPAccuracy(llvm::Value *Val, unsigned AccuracyN, cast<llvm::Instruction>(Val)->setMetadata(llvm::LLVMContext::MD_fpaccuracy, Node); } + +namespace { + struct LValueOrRValue { + LValue LV; + RValue RV; + }; +} + +static LValueOrRValue emitPseudoObjectExpr(CodeGenFunction &CGF, + const PseudoObjectExpr *E, + bool forLValue, + AggValueSlot slot) { + llvm::SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques; + + // Find the result expression, if any. + const Expr *resultExpr = E->getResultExpr(); + LValueOrRValue result; + + for (PseudoObjectExpr::const_semantics_iterator + i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) { + const Expr *semantic = *i; + + // If this semantic expression is an opaque value, bind it + // to the result of its source expression. + if (const OpaqueValueExpr *ov = dyn_cast<OpaqueValueExpr>(semantic)) { + + // If this is the result expression, we may need to evaluate + // directly into the slot. + typedef CodeGenFunction::OpaqueValueMappingData OVMA; + OVMA opaqueData; + if (ov == resultExpr && ov->isRValue() && !forLValue && + CodeGenFunction::hasAggregateLLVMType(ov->getType()) && + !ov->getType()->isAnyComplexType()) { + CGF.EmitAggExpr(ov->getSourceExpr(), slot); + + LValue LV = CGF.MakeAddrLValue(slot.getAddr(), ov->getType()); + opaqueData = OVMA::bind(CGF, ov, LV); + result.RV = slot.asRValue(); + + // Otherwise, emit as normal. + } else { + opaqueData = OVMA::bind(CGF, ov, ov->getSourceExpr()); + + // If this is the result, also evaluate the result now. + if (ov == resultExpr) { + if (forLValue) + result.LV = CGF.EmitLValue(ov); + else + result.RV = CGF.EmitAnyExpr(ov, slot); + } + } + + opaques.push_back(opaqueData); + + // Otherwise, if the expression is the result, evaluate it + // and remember the result. + } else if (semantic == resultExpr) { + if (forLValue) + result.LV = CGF.EmitLValue(semantic); + else + result.RV = CGF.EmitAnyExpr(semantic, slot); + + // Otherwise, evaluate the expression in an ignored context. + } else { + CGF.EmitIgnoredExpr(semantic); + } + } + + // Unbind all the opaques now. + for (unsigned i = 0, e = opaques.size(); i != e; ++i) + opaques[i].unbind(CGF); + + return result; +} + +RValue CodeGenFunction::EmitPseudoObjectRValue(const PseudoObjectExpr *E, + AggValueSlot slot) { + return emitPseudoObjectExpr(*this, E, false, slot).RV; +} + +LValue CodeGenFunction::EmitPseudoObjectLValue(const PseudoObjectExpr *E) { + return emitPseudoObjectExpr(*this, E, true, AggValueSlot::ignored()).LV; +} diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 0fa143391d..ffbc2e0732 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -148,6 +148,15 @@ public: void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E); void VisitOpaqueValueExpr(OpaqueValueExpr *E); + void VisitPseudoObjectExpr(PseudoObjectExpr *E) { + if (E->isGLValue()) { + LValue LV = CGF.EmitPseudoObjectLValue(E); + return EmitFinalDestCopy(E, LV); + } + + CGF.EmitPseudoObjectRValue(E, EnsureSlot(E->getType())); + } + void VisitVAArgExpr(VAArgExpr *E); void EmitInitializationToLValue(Expr *E, LValue Address); diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index b6c416bc35..c09278c14e 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -137,6 +137,10 @@ public: return CGF.getOpaqueRValueMapping(E).getComplexVal(); } + ComplexPairTy VisitPseudoObjectExpr(PseudoObjectExpr *E) { + return CGF.EmitPseudoObjectRValue(E).getComplexVal(); + } + // FIXME: CompoundLiteralExpr ComplexPairTy EmitCast(CastExpr::CastKind CK, Expr *Op, QualType DestTy); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 50c5057f3e..83ca159aa5 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -197,6 +197,10 @@ public: return llvm::ConstantInt::get(ConvertType(E->getType()),E->getPackLength()); } + Value *VisitPseudoObjectExpr(PseudoObjectExpr *E) { + return CGF.EmitPseudoObjectRValue(E).getScalarVal(); + } + Value *VisitOpaqueValueExpr(OpaqueValueExpr *E) { if (E->isGLValue()) return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E)); diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 0cd98ee319..f164103723 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -2231,6 +2231,59 @@ static bool shouldEmitSeparateBlockRetain(const Expr *e) { return true; } +/// Try to emit a PseudoObjectExpr at +1. +/// +/// This massively duplicates emitPseudoObjectRValue. +static TryEmitResult tryEmitARCRetainPseudoObject(CodeGenFunction &CGF, + const PseudoObjectExpr *E) { + llvm::SmallVector<CodeGenFunction::OpaqueValueMappingData, 4> opaques; + + // Find the result expression. + const Expr *resultExpr = E->getResultExpr(); + assert(resultExpr); + TryEmitResult result; + + for (PseudoObjectExpr::const_semantics_iterator + i = E->semantics_begin(), e = E->semantics_end(); i != e; ++i) { + const Expr *semantic = *i; + + // If this semantic expression is an opaque value, bind it + // to the result of its source expression. + if (const OpaqueValueExpr *ov = dyn_cast<OpaqueValueExpr>(semantic)) { + typedef CodeGenFunction::OpaqueValueMappingData OVMA; + OVMA opaqueData; + + // If this semantic is the result of the pseudo-object + // expression, try to evaluate the source as +1. + if (ov == resultExpr) { + assert(!OVMA::shouldBindAsLValue(ov)); + result = tryEmitARCRetainScalarExpr(CGF, ov->getSourceExpr()); + opaqueData = OVMA::bind(CGF, ov, RValue::get(result.getPointer())); + + // Otherwise, just bind it. + } else { + opaqueData = OVMA::bind(CGF, ov, ov->getSourceExpr()); + } + opaques.push_back(opaqueData); + + // Otherwise, if the expression is the result, evaluate it + // and remember the result. + } else if (semantic == resultExpr) { + result = tryEmitARCRetainScalarExpr(CGF, semantic); + + // Otherwise, evaluate the expression in an ignored context. + } else { + CGF.EmitIgnoredExpr(semantic); + } + } + + // Unbind all the opaques now. + for (unsigned i = 0, e = opaques.size(); i != e; ++i) + opaques[i].unbind(CGF); + + return result; +} + static TryEmitResult tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) { // Look through cleanups. @@ -2356,6 +2409,17 @@ tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) { llvm::Value *result = emitARCRetainCall(CGF, e); if (resultType) result = CGF.Builder.CreateBitCast(result, resultType); return TryEmitResult(result, true); + + // Look through pseudo-object expressions. + } else if (const PseudoObjectExpr *pseudo = dyn_cast<PseudoObjectExpr>(e)) { + TryEmitResult result + = tryEmitARCRetainPseudoObject(CGF, pseudo); + if (resultType) { + llvm::Value *value = result.getPointer(); + value = CGF.Builder.CreateBitCast(value, resultType); + result.setPointer(value); + } + return result; } // Conservatively halt the search at any other expression kind. diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index 489e600b3d..bc94e8ebc9 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -27,6 +27,7 @@ namespace clang { class ObjCPropertyRefExpr; namespace CodeGen { + class AggValueSlot; class CGBitFieldInfo; /// RValue - This trivial value class is used to represent the result of an @@ -452,7 +453,7 @@ public: RValue asRValue() const { return RValue::getAggregate(getAddr(), isVolatile()); } - + void setZeroed(bool V = true) { ZeroedFlag = V; } IsZeroed_t isZeroed() const { return IsZeroed_t(ZeroedFlag); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 4940e21c8b..0b31ce43a9 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -950,20 +950,86 @@ public: public: PeepholeProtection() : Inst(0) {} - }; + }; - /// An RAII object to set (and then clear) a mapping for an OpaqueValueExpr. - class OpaqueValueMapping { - CodeGenFunction &CGF; + /// A non-RAII class containing all the information about a bound + /// opaque value. OpaqueValueMapping, below, is a RAII wrapper for + /// this which makes individual mappings very simple; using this + /// class directly is useful when you have a variable number of + /// opaque values or don't want the RAII functionality for some + /// reason. + class OpaqueValueMappingData { const OpaqueValueExpr *OpaqueValue; bool BoundLValue; CodeGenFunction::PeepholeProtection Protection; + OpaqueValueMappingData(const OpaqueValueExpr *ov, + bool boundLValue) + : OpaqueValue(ov), BoundLValue(boundLValue) {} public: + OpaqueValueMappingData() : OpaqueValue(0) {} + static bool shouldBindAsLValue(const Expr * |