diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ARCMigrate/TransRetainReleaseDealloc.cpp | 9 | ||||
-rw-r--r-- | lib/ARCMigrate/TransformActions.cpp | 2 | ||||
-rw-r--r-- | lib/ARCMigrate/Transforms.cpp | 9 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 2 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 2 | ||||
-rw-r--r-- | lib/AST/Stmt.cpp | 12 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGExprComplex.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 17 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 3 |
16 files changed, 71 insertions, 18 deletions
diff --git a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp index c177363b18..fe80a43a6a 100644 --- a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp +++ b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp @@ -116,11 +116,16 @@ private: return true; } - if (ParenExpr *parenE = dyn_cast_or_null<ParenExpr>(StmtMap->getParent(E))) + Stmt *parent = StmtMap->getParent(E); + + if (ImplicitCastExpr *castE = dyn_cast_or_null<ImplicitCastExpr>(parent)) + return tryRemoving(castE); + + if (ParenExpr *parenE = dyn_cast_or_null<ParenExpr>(parent)) return tryRemoving(parenE); if (BinaryOperator * - bopE = dyn_cast_or_null<BinaryOperator>(StmtMap->getParent(E))) { + bopE = dyn_cast_or_null<BinaryOperator>(parent)) { if (bopE->getOpcode() == BO_Comma && bopE->getLHS() == E && isRemovable(bopE)) { Pass.TA.replace(bopE->getSourceRange(), bopE->getRHS()->getSourceRange()); diff --git a/lib/ARCMigrate/TransformActions.cpp b/lib/ARCMigrate/TransformActions.cpp index 45a3d473e6..2ae979896a 100644 --- a/lib/ARCMigrate/TransformActions.cpp +++ b/lib/ARCMigrate/TransformActions.cpp @@ -313,7 +313,7 @@ void TransformActionsImpl::removeStmt(Stmt *S) { assert(IsInTransaction && "Actions only allowed during a transaction"); ActionData data; data.Kind = Act_RemoveStmt; - data.S = S; + data.S = S->IgnoreImplicit(); // important for uniquing CachedActions.push_back(data); } diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp index 1a98833fe0..80c52d7940 100644 --- a/lib/ARCMigrate/Transforms.cpp +++ b/lib/ARCMigrate/Transforms.cpp @@ -180,12 +180,9 @@ private: void mark(Stmt *S) { if (!S) return; - if (LabelStmt *Label = dyn_cast<LabelStmt>(S)) - return mark(Label->getSubStmt()); - if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(S)) - return mark(CE->getSubExpr()); - if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S)) - return mark(EWC->getSubExpr()); + while (LabelStmt *Label = dyn_cast<LabelStmt>(S)) + S = Label->getSubStmt(); + S = S->IgnoreImplicit(); if (Expr *E = dyn_cast<Expr>(S)) Removables.insert(E); } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 3002e305ac..5d8789fdda 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1102,6 +1102,8 @@ const char *CastExpr::getCastKindName() const { return "ObjCConsumeObject"; case CK_ObjCProduceObject: return "ObjCProduceObject"; + case CK_ObjCReclaimReturnedObject: + return "ObjCReclaimReturnedObject"; } llvm_unreachable("Unhandled cast kind!"); diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index cc8c50198c..9943222b1d 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1819,6 +1819,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_UserDefinedConversion: case CK_ObjCProduceObject: case CK_ObjCConsumeObject: + case CK_ObjCReclaimReturnedObject: return false; case CK_LValueToRValue: @@ -2325,6 +2326,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_IntegralComplexToBoolean: case CK_ObjCProduceObject: case CK_ObjCConsumeObject: + case CK_ObjCReclaimReturnedObject: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index e293f324ab..fd6f21d43b 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -85,6 +85,18 @@ bool Stmt::CollectingStats(bool Enable) { return StatSwitch; } +Stmt *Stmt::IgnoreImplicit() { + Stmt *s = this; + + if (ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(s)) + s = ewc->getSubExpr(); + + while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(s)) + s = ice->getSubExpr(); + + return s; +} + namespace { struct good {}; struct bad {}; diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index d9e565a440..289eaa08fb 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -2011,7 +2011,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_MemberPointerToBoolean: case CK_AnyPointerToBlockPointerCast: case CK_ObjCProduceObject: - case CK_ObjCConsumeObject: { + case CK_ObjCConsumeObject: + case CK_ObjCReclaimReturnedObject: { // These casts only produce lvalues when we're binding a reference to a // temporary realized from a (converted) pure rvalue. Emit the expression // as a value, copy it into a temporary, and return an lvalue referring to diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 99e95842eb..93f93b77e8 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -360,6 +360,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { case CK_IntegralComplexToFloatingComplex: case CK_ObjCProduceObject: case CK_ObjCConsumeObject: + case CK_ObjCReclaimReturnedObject: llvm_unreachable("cast kind invalid for aggregate types"); } } diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index 95dcc0b3ae..a88f112a16 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -407,6 +407,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op, case CK_IntegralComplexToBoolean: case CK_ObjCProduceObject: case CK_ObjCConsumeObject: + case CK_ObjCReclaimReturnedObject: llvm_unreachable("invalid cast kind for complex value"); case CK_FloatingRealToComplex: diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index e88c28737c..42e1450125 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -582,6 +582,7 @@ public: case CK_Dynamic: case CK_ObjCProduceObject: case CK_ObjCConsumeObject: + case CK_ObjCReclaimReturnedObject: return 0; // These might need to be supported for constexpr. diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index e7ae6b5708..84457cbbfe 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1109,6 +1109,11 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { return CGF.EmitARCRetainScalarExpr(E); case CK_ObjCConsumeObject: return CGF.EmitObjCConsumeObject(E->getType(), Visit(E)); + case CK_ObjCReclaimReturnedObject: { + llvm::Value *value = Visit(E); + value = CGF.EmitARCRetainAutoreleasedReturnValue(value); + return CGF.EmitObjCConsumeObject(E->getType(), value); + } case CK_FloatingRealToComplex: case CK_FloatingComplexCast: diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index d8ce1f4a75..1b271ef2af 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -2333,6 +2333,14 @@ tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) { return TryEmitResult(result, true); } + // For reclaims, emit the subexpression as a retained call and + // skip the consumption. + case CK_ObjCReclaimReturnedObject: { + llvm::Value *result = emitARCRetainCall(CGF, ce->getSubExpr()); + if (resultType) result = CGF.Builder.CreateBitCast(result, resultType); + return TryEmitResult(result, true); + } + case CK_GetObjCProperty: { llvm::Value *result = emitARCRetainCall(CGF, ce); if (resultType) result = CGF.Builder.CreateBitCast(result, resultType); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 35b6e9abc9..8bad032911 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -3543,6 +3543,7 @@ static bool findRetainCycleOwner(Expr *e, RetainCycleOwner &owner) { case CK_BitCast: case CK_LValueBitCast: case CK_LValueToRValue: + case CK_ObjCReclaimReturnedObject: e = cast->getSubExpr(); continue; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 6ae48dd28c..4c096fe0ec 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -4039,13 +4039,12 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { ReturnsRetained = (D && D->hasAttr<NSReturnsRetainedAttr>()); } - if (ReturnsRetained) { - ExprNeedsCleanups = true; - E = ImplicitCastExpr::Create(Context, E->getType(), - CK_ObjCConsumeObject, E, 0, - VK_RValue); - } - return Owned(E); + ExprNeedsCleanups = true; + + CastKind ck = (ReturnsRetained ? CK_ObjCConsumeObject + : CK_ObjCReclaimReturnedObject); + return Owned(ImplicitCastExpr::Create(Context, E->getType(), ck, E, 0, + VK_RValue)); } if (!getLangOptions().CPlusPlus) diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 17a7401d65..fa51098f1a 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -1771,6 +1771,20 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, << castRange << castExpr->getSourceRange(); } +/// Look for an ObjCReclaimReturnedObject cast and destroy it. +static Expr *maybeUndoReclaimObject(Expr *e) { + // For now, we just undo operands that are *immediately* reclaim + // expressions, which prevents the vast majority of potential + // problems here. To catch them all, we'd need to rebuild arbitrary + // value-propagating subexpressions --- we can't reliably rebuild + // in-place because of expression sharing. + if (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e)) + if (ice->getCastKind() == CK_ObjCReclaimReturnedObject) + return ice->getSubExpr(); + + return e; +} + ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, ObjCBridgeCastKind Kind, SourceLocation BridgeKeywordLoc, @@ -1815,6 +1829,9 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, // Okay: id -> CF switch (Kind) { case OBC_Bridge: + // Reclaiming a value that's going to be __bridge-casted to CF + // is very dangerous, so we don't do it. + SubExpr = maybeUndoReclaimObject(SubExpr); break; case OBC_BridgeRetained: diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 4aa5e350bc..fbaa8490e9 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -2194,7 +2194,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, // The analyzer doesn't do anything special with these casts, // since it understands retain/release semantics already. case CK_ObjCProduceObject: - case CK_ObjCConsumeObject: // Fall-through. + case CK_ObjCConsumeObject: + case CK_ObjCReclaimReturnedObject: // Fall-through. // True no-ops. case CK_NoOp: case CK_FunctionToPointerDecay: { |