bool trans::hasSideEffects(Expr *E, ASTContext &Ctx) { if (!E || !E->HasSideEffects(Ctx)) return false; E = E->IgnoreParenCasts(); ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E); if (!ME) return true; switch (ME->getMethodFamily()) { case OMF_autorelease: case OMF_dealloc: case OMF_release: case OMF_retain: switch (ME->getReceiverKind()) { case ObjCMessageExpr::SuperInstance: return false; case ObjCMessageExpr::Instance: return hasSideEffects(ME->getInstanceReceiver(), Ctx); default: break; } break; default: break; } return true; }
// match expr against [_x delegate] or [self.x delegate] static bool matchObjCMessageExprForInterestingDelegate(const ObjCMessageExpr &expr, const ObjCImplFacts &facts, const ObjCIvarDecl **foundIvar, const ObjCPropertyDecl **foundProperty) { // want an instance message to a non-null receiver const Expr *receiver = expr.getInstanceReceiver(); if (!receiver) { return false; } const ObjCIvarDecl *ivarDecl = matchIvarLValueExpression(*receiver); if (!ivarDecl) { return false; } if (facts._ivarFactsMap.find(ivarDecl) == facts._ivarFactsMap.end()) { // not an interesting ivar (no entry) return false; } // is this a getter to an assign property? const ObjCPropertyDecl *propDecl = matchObjCMessageWithPropertyGetter(expr); if (propDecl) { if (propDecl->getSetterKind() != ObjCPropertyDecl::Assign) { return false; } // here we go! *foundIvar = ivarDecl; *foundProperty = propDecl; return true; } return false; }
void TransferFunctions::Visit(Stmt *S) { if (observer) observer->observeStmt(S, currentBlock, val); StmtVisitor<TransferFunctions>::Visit(S); if (isa<Expr>(S)) { val.liveStmts = LV.SSetFact.remove(val.liveStmts, S); } // Mark all children expressions live. switch (S->getStmtClass()) { default: break; case Stmt::StmtExprClass: { // For statement expressions, look through the compound statement. S = cast<StmtExpr>(S)->getSubStmt(); break; } case Stmt::CXXMemberCallExprClass: { // Include the implicit "this" pointer as being live. CXXMemberCallExpr *CE = cast<CXXMemberCallExpr>(S); if (Expr *ImplicitObj = CE->getImplicitObjectArgument()) { AddLiveStmt(val.liveStmts, LV.SSetFact, ImplicitObj); } break; } case Stmt::ObjCMessageExprClass: { // In calls to super, include the implicit "self" pointer as being live. ObjCMessageExpr *CE = cast<ObjCMessageExpr>(S); if (CE->getReceiverKind() == ObjCMessageExpr::SuperInstance) val.liveDecls = LV.DSetFact.add(val.liveDecls, LV.analysisContext.getSelfDecl()); break; } case Stmt::DeclStmtClass: { const DeclStmt *DS = cast<DeclStmt>(S); if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) { for (const VariableArrayType* VA = FindVA(VD->getType()); VA != nullptr; VA = FindVA(VA->getElementType())) { AddLiveStmt(val.liveStmts, LV.SSetFact, VA->getSizeExpr()); } } 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(); break; } case Stmt::CXXBindTemporaryExprClass: { S = cast<CXXBindTemporaryExpr>(S)->getSubExpr(); break; } case Stmt::UnaryExprOrTypeTraitExprClass: { // No need to unconditionally visit subexpressions. return; } } for (Stmt *Child : S->children()) { if (Child) AddLiveStmt(val.liveStmts, LV.SSetFact, Child); } }