void AnalysisResult::analyzeProgram(ConstructPtr c) const { if (!c) return; for (auto i = 0, n = c->getKidCount(); i < n; ++i) { analyzeProgram(c->getNthKid(i)); } c->analyzeProgram(AnalysisResultConstRawPtr{this}); }
void ClassScope::informClosuresAboutScopeClone( ConstructPtr root, FunctionScopePtr outerScope, AnalysisResultPtr ar) { if (!root) { return; } for (int i = 0; i < root->getKidCount(); i++) { ConstructPtr cons = root->getNthKid(i); ClosureExpressionPtr closure = dynamic_pointer_cast<ClosureExpression>(cons); if (!closure) { informClosuresAboutScopeClone(cons, outerScope, ar); continue; } FunctionStatementPtr func = closure->getClosureFunction(); HPHP::FunctionScopePtr funcScope = func->getFunctionScope(); assert(funcScope->isClosure()); funcScope->addClonedTraitOuterScope(outerScope); // Don't need to recurse } }
void walk_ast(ConstructPtr node) { if (!node) return; if (dynamic_pointer_cast<MethodStatement>(node)) { // Don't descend into nested non-closure functions, or functions // in the psuedo-main. return; } if (auto ce = dynamic_pointer_cast<ClosureExpression>(node)) { visit_closure(ce); return; } for (int i = 0; i < node->getKidCount(); ++i) { walk_ast(node->getNthKid(i)); } }
bool ClosureExpression::hasStaticLocalsImpl(ConstructPtr root) { if (!root) { return false; } if (root->getFunctionScope() != m_func->getFunctionScope()) { // new scope, new statics return false; } for (int i = 0; i < root->getKidCount(); i++) { ConstructPtr cons = root->getNthKid(i); if (StatementPtr s = dynamic_pointer_cast<Statement>(cons)) { if (s->is(Statement::KindOfStaticStatement)) { return true; } } if (hasStaticLocalsImpl(cons)) { return true; } } return false; }
// Returns: whether or not $this is implicitly used in this part of the AST, // e.g. via a call using parent::. bool walk_ast(ConstructPtr node) { if (!node) return false; if (dynamic_pointer_cast<MethodStatement>(node)) { // Don't descend into nested non-closure functions, or functions // in the pseudo-main. return false; } if (auto ce = dynamic_pointer_cast<ClosureExpression>(node)) { return visit_closure(ce); } auto ret = false; if (auto fc = dynamic_pointer_cast<FunctionCall>(node)) { if (fc->isParent()) ret = true; } for (int i = 0; i < node->getKidCount(); ++i) { if (walk_ast(node->getNthKid(i))) ret = true; } return ret; }
void AliasManager::collectAliasInfoRecur(ConstructPtr cs) { if (!cs) { return; } if (StatementPtr s = dpc(Statement, cs)) { switch (s->getKindOf()) { case Statement::KindOfFunctionStatement: case Statement::KindOfMethodStatement: case Statement::KindOfClassStatement: case Statement::KindOfInterfaceStatement: return; default: break; } } int nkid = cs->getKidCount(); for (int i = 0; i < nkid; i++) { ConstructPtr kid = cs->getNthKid(i); if (kid) { collectAliasInfoRecur(kid); } } if (ExpressionPtr e = dpc(Expression, cs)) { int context = e->getContext(); switch (e->getKindOf()) { case Expression::KindOfAssignmentExpression: { AssignmentExpressionPtr ae = spc(AssignmentExpression, e); ExpressionPtr var = ae->getVariable(); ExpressionPtr val = ae->getValue(); if (var->is(Expression::KindOfSimpleVariable)) { const std::string &name = spc(SimpleVariable, var)->getName(); AliasInfo &ai = m_aliasInfo[name]; if (val->getContext() & Expression::RefValue) { ai.setIsRefTo(); m_variables->addUsed(name); } else { Expression::checkUsed(m_arp, var, val); } } } break; case Expression::KindOfListAssignment: { ListAssignmentPtr la = spc(ListAssignment, e); ExpressionListPtr vars = la->getVariables(); for (int i = vars->getCount(); i--; ) { ExpressionPtr v = (*vars)[i]; if (v && v->is(Expression::KindOfSimpleVariable)) { SimpleVariablePtr sv = spc(SimpleVariable, v); m_variables->addUsed(sv->getName()); } } } break; case Expression::KindOfSimpleVariable: { const std::string &name = spc(SimpleVariable, e)->getName(); if (context & Expression::RefValue) { AliasInfo &ai = m_aliasInfo[name]; ai.addRefLevel(0); } if (!(context & (Expression::AssignmentLHS | Expression::UnsetContext))) { m_variables->addUsed(name); } } break; case Expression::KindOfDynamicVariable: if (context & Expression::RefValue) { m_wildRefs = true; } break; case Expression::KindOfArrayElementExpression: { int n = 1; while (n < 10 && e->is(Expression::KindOfArrayElementExpression)) { e = spc(ArrayElementExpression, e)->getVariable(); } if (e->is(Expression::KindOfSimpleVariable)) { const std::string &name = spc(SimpleVariable, e)->getName(); if (context & Expression::RefValue) { AliasInfo &ai = m_aliasInfo[name]; ai.addRefLevel(n); } m_variables->addUsed(name); // need this for UnsetContext } } break; case Expression::KindOfObjectPropertyExpression: { e = spc(ObjectPropertyExpression, e)->getObject(); if (e->is(Expression::KindOfSimpleVariable)) { const std::string &name = spc(SimpleVariable, e)->getName(); if (context & Expression::RefValue) { AliasInfo &ai = m_aliasInfo[name]; ai.addRefLevel(1); } m_variables->addUsed(name); // need this for UnsetContext } } break; default: break; } } else { StatementPtr s = spc(Statement, cs); switch (s->getKindOf()) { case Statement::KindOfCatchStatement: { const std::string &name = spc(CatchStatement, s)->getVariable(); m_variables->addUsed(name); break; } default: break; } } }