void FunctionScope::init(AnalysisResultConstPtr ar) { m_dynamicInvoke = false; if (isNamed("__autoload")) { setVolatile(); } // FileScope's flags are from parser, but VariableTable has more flags // coming from type inference phase. So we are tranferring these flags // just for better modularization between FileScope and VariableTable. if (m_attribute & FileScope::ContainsDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsDynamicVariable); } if (m_attribute & FileScope::ContainsLDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsLDynamicVariable); } if (m_attribute & FileScope::ContainsExtract) { m_variables->setAttribute(VariableTable::ContainsExtract); } if (m_attribute & FileScope::ContainsAssert) { m_variables->setAttribute(VariableTable::ContainsAssert); } if (m_attribute & FileScope::ContainsCompact) { m_variables->setAttribute(VariableTable::ContainsCompact); } if (m_attribute & FileScope::ContainsUnset) { m_variables->setAttribute(VariableTable::ContainsUnset); } if (m_attribute & FileScope::ContainsGetDefinedVars) { m_variables->setAttribute(VariableTable::ContainsGetDefinedVars); } if (m_stmt && Option::AllVolatile && !m_pseudoMain && !m_method) { m_volatile = true; } if (!m_method && Option::DynamicInvokeFunctions.find(m_scopeName) != Option::DynamicInvokeFunctions.end()) { setDynamicInvoke(); } if (m_modifiers) { m_virtual = m_modifiers->isAbstract(); } if (m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); StatementListPtr stmts = stmt->getStmts(); if (stmts) { for (int i = 0; i < stmts->getCount(); i++) { StatementPtr stmt = (*stmts)[i]; stmt->setFileLevel(); if (stmt->is(Statement::KindOfExpStatement)) { ExpStatementPtr expStmt = dynamic_pointer_cast<ExpStatement>(stmt); ExpressionPtr exp = expStmt->getExpression(); exp->setTopLevel(); } } } } }
void FileScope::setFileLevel(StatementListPtr stmtList) { for (int i = 0; i < stmtList->getCount(); i++) { StatementPtr stmt = (*stmtList)[i]; stmt->setFileLevel(); if (stmt->is(Statement::KindOfExpStatement)) { ExpStatementPtr expStmt = dynamic_pointer_cast<ExpStatement>(stmt); ExpressionPtr exp = expStmt->getExpression(); exp->setFileLevel(); } if (stmt->is(Statement::KindOfStatementList)) { setFileLevel(dynamic_pointer_cast<StatementList>(stmt)); } } }
bool StatementList::mergeConcatAssign() { if (Option::LocalCopyProp) { return false; } else { // check for vector string concat assignment such as // $space = " "; // $a .= "hello"; // $a .= $space; // $a .= "world!"; // turn into (for constant folding and concat sequence) // $a .= " " . "hello " . $space . "world!"; unsigned int i = 0; bool merged = false; do { std::string lhsName; int length = 0; for (; i < m_stmts.size(); i++) { StatementPtr stmt = m_stmts[i]; if (!stmt->is(Statement::KindOfExpStatement)) break; ExpStatementPtr expStmt = dynamic_pointer_cast<ExpStatement>(stmt); ExpressionPtr exp = expStmt->getExpression(); // check the first assignment if (exp->is(Expression::KindOfAssignmentExpression)) { AssignmentExpressionPtr assignment_exp = dynamic_pointer_cast<AssignmentExpression>(exp); ExpressionPtr variable = assignment_exp->getVariable(); ExpressionPtr value = assignment_exp->getValue(); std::string variableName = variable->getText(); if (variableName.find("->") != std::string::npos) break; if (value->hasEffect()) break; // cannot turn $a .= $b; a .= $a into $a .= $b . $a; if (value->getText().find(variableName) != std::string::npos) break; if (lhsName.empty()) { lhsName = variable->getText(); length++; continue; } else { break; } } else if (!exp->is(Expression::KindOfBinaryOpExpression)) { break; } BinaryOpExpressionPtr binaryOpExp = dynamic_pointer_cast<BinaryOpExpression>(exp); if (binaryOpExp->getOp() != T_CONCAT_EQUAL) break; ExpressionPtr exp1 = binaryOpExp->getExp1(); std::string exp1Text = exp1->getText(); if (exp1Text.find("->") != std::string::npos) break; ExpressionPtr exp2 = binaryOpExp->getExp2(); if (exp2->hasEffect()) break; if (exp2->getText().find(exp1Text) != std::string::npos) break; if (lhsName.empty()) { lhsName = exp1Text; length++; } else if (lhsName == exp1Text) { length++; } else { break; } } if (length > 1) { // replace m_stmts[j] to m_stmts[i - 1] with a new statement unsigned j = i - length; ExpStatementPtr expStmt; ExpressionPtr exp; BinaryOpExpressionPtr binaryOpExp; ExpressionPtr var; ExpressionPtr exp1; ExpressionPtr exp2; bool isAssignment = false; expStmt = dynamic_pointer_cast<ExpStatement>(m_stmts[j++]); exp = expStmt->getExpression(); if (exp->is(Expression::KindOfAssignmentExpression)) { isAssignment = true; AssignmentExpressionPtr assignment_exp = dynamic_pointer_cast<AssignmentExpression>(exp); var = assignment_exp->getVariable(); exp1 = assignment_exp->getValue(); } else { binaryOpExp = dynamic_pointer_cast<BinaryOpExpression>(exp); var = binaryOpExp->getExp1(); exp1 = binaryOpExp->getExp2(); } for (; j < i; j++) { expStmt = dynamic_pointer_cast<ExpStatement>(m_stmts[j]); exp = expStmt->getExpression(); binaryOpExp = dynamic_pointer_cast<BinaryOpExpression>(exp); exp2 = binaryOpExp->getExp2(); exp1 = BinaryOpExpressionPtr (new BinaryOpExpression(getScope(), getLocation(), Expression::KindOfBinaryOpExpression, exp1, exp2, '.')); } if (isAssignment) { exp = AssignmentExpressionPtr (new AssignmentExpression(exp->getScope(), exp->getLocation(), Expression::KindOfAssignmentExpression, var, exp1, false)); } else { exp = BinaryOpExpressionPtr (new BinaryOpExpression(getScope(), getLocation(), Expression::KindOfBinaryOpExpression, var, exp1, T_CONCAT_EQUAL)); } expStmt = ExpStatementPtr (new ExpStatement(getScope(), getLocation(), Statement::KindOfExpStatement, exp)); m_stmts[i - length] = expStmt; for (j = i - (length - 1); i > j; i--) removeElement(j); merged = true; } else if (length == 0) { i++; } } while (i < m_stmts.size()); return merged; } }
void FunctionScope::init(AnalysisResultConstPtr ar) { m_dynamicInvoke = false; bool canInline = true; if (m_pseudoMain) { canInline = false; m_variables->forceVariants(ar, VariableTable::AnyVars); setReturnType(ar, Type::Variant); } if (m_refReturn) { m_returnType = Type::Variant; } if (!strcasecmp(m_name.c_str(), "__autoload")) { setVolatile(); } // FileScope's flags are from parser, but VariableTable has more flags // coming from type inference phase. So we are tranferring these flags // just for better modularization between FileScope and VariableTable. if (m_attribute & FileScope::ContainsDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsDynamicVariable); } if (m_attribute & FileScope::ContainsLDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsLDynamicVariable); } if (m_attribute & FileScope::ContainsExtract) { m_variables->setAttribute(VariableTable::ContainsExtract); } if (m_attribute & FileScope::ContainsAssert) { m_variables->setAttribute(VariableTable::ContainsAssert); } if (m_attribute & FileScope::ContainsCompact) { m_variables->setAttribute(VariableTable::ContainsCompact); } if (m_attribute & FileScope::ContainsUnset) { m_variables->setAttribute(VariableTable::ContainsUnset); } if (m_attribute & FileScope::ContainsGetDefinedVars) { m_variables->setAttribute(VariableTable::ContainsGetDefinedVars); } if (m_stmt && Option::AllVolatile && !m_pseudoMain && !m_method) { m_volatile = true; } m_dynamic = Option::IsDynamicFunction(m_method, m_name) || Option::EnableEval == Option::FullEval || Option::AllDynamic; if (!m_method && Option::DynamicInvokeFunctions.find(m_name) != Option::DynamicInvokeFunctions.end()) { setDynamicInvoke(); } if (m_modifiers) { m_virtual = m_modifiers->isAbstract(); } if (m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); StatementListPtr stmts = stmt->getStmts(); if (stmts) { if (stmts->getRecursiveCount() > Option::InlineFunctionThreshold) canInline = false; for (int i = 0; i < stmts->getCount(); i++) { StatementPtr stmt = (*stmts)[i]; stmt->setFileLevel(); if (stmt->is(Statement::KindOfExpStatement)) { ExpStatementPtr expStmt = dynamic_pointer_cast<ExpStatement>(stmt); ExpressionPtr exp = expStmt->getExpression(); exp->setTopLevel(); } } } } else { canInline = false; } m_inlineable = canInline; }
FunctionScope::FunctionScope(AnalysisResultPtr ar, bool method, const std::string &name, StatementPtr stmt, bool reference, int minParam, int maxParam, ModifierExpressionPtr modifiers, int attribute, const std::string &docComment, FileScopePtr file, bool inPseudoMain /* = false */) : BlockScope(name, docComment, stmt, BlockScope::FunctionScope), m_method(method), m_file(file), m_minParam(0), m_maxParam(0), m_attribute(attribute), m_refReturn(reference), m_modifiers(modifiers), m_virtual(false), m_overriding(false), m_redeclaring(-1), m_volatile(false), m_ignored(false), m_pseudoMain(inPseudoMain), m_magicMethod(false), m_system(false), m_inlineable(false), m_sep(false), m_containsThis(false), m_staticMethodAutoFixed(false), m_callTempCountMax(0), m_callTempCountCurrent(0) { bool canInline = true; if (inPseudoMain) { canInline = false; m_variables->forceVariants(ar); setReturnType(ar, Type::Variant); } setParamCounts(ar, minParam, maxParam); if (m_refReturn) { m_returnType = Type::Variant; } // FileScope's flags are from parser, but VariableTable has more flags // coming from type inference phase. So we are tranferring these two // flags just for better modularization between FileScope and VariableTable. if (m_attribute & FileScope::ContainsDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsDynamicVariable); } if (m_attribute & FileScope::ContainsLDynamicVariable) { m_variables->setAttribute(VariableTable::ContainsLDynamicVariable); } if (m_attribute & FileScope::ContainsExtract) { m_variables->setAttribute(VariableTable::ContainsExtract); } if (m_attribute & FileScope::ContainsCompact) { m_variables->setAttribute(VariableTable::ContainsCompact); } if (m_attribute & FileScope::ContainsUnset) { m_variables->setAttribute(VariableTable::ContainsUnset); } if (m_attribute & FileScope::ContainsGetDefinedVars) { m_variables->setAttribute(VariableTable::ContainsGetDefinedVars); } if (m_stmt && Option::AllVolatile) { m_volatile = true; } m_dynamic = Option::IsDynamicFunction(method, m_name) || Option::EnableEval == Option::FullEval; if (modifiers) { m_virtual = modifiers->isAbstract(); } if (m_stmt) { MethodStatementPtr stmt = dynamic_pointer_cast<MethodStatement>(m_stmt); StatementListPtr stmts = stmt->getStmts(); if (stmts) { if (stmts->getRecursiveCount() > Option::InlineFunctionThreshold) canInline = false; for (int i = 0; i < stmts->getCount(); i++) { StatementPtr stmt = (*stmts)[i]; stmt->setFileLevel(); if (stmt->is(Statement::KindOfExpStatement)) { ExpStatementPtr expStmt = dynamic_pointer_cast<ExpStatement>(stmt); ExpressionPtr exp = expStmt->getExpression(); exp->setTopLevel(); } } } } else { canInline = false; } m_inlineable = canInline; }