diff --git a/hphp/compiler/analysis/analysis_result.cpp b/hphp/compiler/analysis/analysis_result.cpp index a8e91bba4..9850e30bb 100644 --- a/hphp/compiler/analysis/analysis_result.cpp +++ b/hphp/compiler/analysis/analysis_result.cpp @@ -236,8 +236,8 @@ ClassScopePtr AnalysisResult::findClass(const std::string &name, return ClassScopePtr(); } -const ClassScopePtrVec &AnalysisResult::findRedeclaredClasses -(const std::string &name) const { +const ClassScopePtrVec & +AnalysisResult::findRedeclaredClasses(const std::string &name) const { StringToClassScopePtrVecMap::const_iterator iter = m_classDecs.find(name); if (iter == m_classDecs.end()) { static ClassScopePtrVec empty; diff --git a/hphp/compiler/analysis/analysis_result.h b/hphp/compiler/analysis/analysis_result.h index a7b6a5f7c..256e9b461 100644 --- a/hphp/compiler/analysis/analysis_result.h +++ b/hphp/compiler/analysis/analysis_result.h @@ -236,12 +236,14 @@ public: ClassScopePtr findClass(const std::string &className) const; ClassScopePtr findClass(const std::string &className, FindClassBy by); + /** * Find all the redeclared classes by the name, excluding system classes. * Note that system classes cannot be redeclared. */ const ClassScopePtrVec &findRedeclaredClasses( const std::string &className) const; + /** * Find all the classes by the name, including system classes. */ diff --git a/hphp/compiler/expression/simple_function_call.cpp b/hphp/compiler/expression/simple_function_call.cpp index c13dba92d..9403c05fc 100644 --- a/hphp/compiler/expression/simple_function_call.cpp +++ b/hphp/compiler/expression/simple_function_call.cpp @@ -46,41 +46,42 @@ using namespace HPHP; /////////////////////////////////////////////////////////////////////////////// // statics -std::map SimpleFunctionCall::FunctionTypeMap; +std::map + SimpleFunctionCall::FunctionTypeMap; void SimpleFunctionCall::InitFunctionTypeMap() { if (FunctionTypeMap.empty()) { - FunctionTypeMap["define"] = DefineFunction; - FunctionTypeMap["create_function"] = CreateFunction; + FunctionTypeMap["define"] = FunType::Define; + FunctionTypeMap["create_function"] = FunType::Create; - FunctionTypeMap["func_get_arg"] = VariableArgumentFunction; - FunctionTypeMap["func_get_args"] = VariableArgumentFunction; - FunctionTypeMap["func_num_args"] = VariableArgumentFunction; + FunctionTypeMap["func_get_arg"] = FunType::VariableArgument; + FunctionTypeMap["func_get_args"] = FunType::VariableArgument; + FunctionTypeMap["func_num_args"] = FunType::VariableArgument; - FunctionTypeMap["extract"] = ExtractFunction; - FunctionTypeMap["compact"] = CompactFunction; + FunctionTypeMap["extract"] = FunType::Extract; + FunctionTypeMap["compact"] = FunType::Compact; - FunctionTypeMap["shell_exec"] = ShellExecFunction; - FunctionTypeMap["exec"] = ShellExecFunction; - FunctionTypeMap["passthru"] = ShellExecFunction; - FunctionTypeMap["system"] = ShellExecFunction; + FunctionTypeMap["shell_exec"] = FunType::ShellExec; + FunctionTypeMap["exec"] = FunType::ShellExec; + FunctionTypeMap["passthru"] = FunType::ShellExec; + FunctionTypeMap["system"] = FunType::ShellExec; - FunctionTypeMap["defined"] = DefinedFunction; - FunctionTypeMap["function_exists"] = FunctionExistsFunction; - FunctionTypeMap["class_exists"] = ClassExistsFunction; - FunctionTypeMap["interface_exists"] = InterfaceExistsFunction; - FunctionTypeMap["constant"] = ConstantFunction; + FunctionTypeMap["defined"] = FunType::Defined; + FunctionTypeMap["function_exists"] = FunType::FunctionExists; + FunctionTypeMap["class_exists"] = FunType::ClassExists; + FunctionTypeMap["interface_exists"] = FunType::InterfaceExists; + FunctionTypeMap["constant"] = FunType::Constant; - FunctionTypeMap["unserialize"] = UnserializeFunction; - FunctionTypeMap["apc_fetch"] = UnserializeFunction; + FunctionTypeMap["unserialize"] = FunType::Unserialize; + FunctionTypeMap["apc_fetch"] = FunType::Unserialize; - FunctionTypeMap["get_defined_vars"] = GetDefinedVarsFunction; + FunctionTypeMap["get_defined_vars"] = FunType::GetDefinedVars; - FunctionTypeMap["fb_call_user_func_safe"] = FBCallUserFuncSafeFunction; + FunctionTypeMap["fb_call_user_func_safe"] = FunType::FBCallUserFuncSafe; FunctionTypeMap["fb_call_user_func_array_safe"] = - FBCallUserFuncSafeFunction; + FunType::FBCallUserFuncSafe; FunctionTypeMap["fb_call_user_func_safe_return"] = - FBCallUserFuncSafeFunction; + FunType::FBCallUserFuncSafe; } } @@ -100,7 +101,7 @@ SimpleFunctionCall::SimpleFunctionCall ExpressionPtr cls) : FunctionCall(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(SimpleFunctionCall), ExpressionPtr(), name, hadBackslash, params, cls), - m_type(UnknownType), m_dynamicConstant(false), + m_type(FunType::Unknown), m_dynamicConstant(false), m_builtinFunction(false), m_fromCompiler(false), m_dynamicInvoke(false), m_transformed(false), m_no_volatile_check(false), m_safe(0), m_extra(nullptr) { @@ -108,8 +109,7 @@ SimpleFunctionCall::SimpleFunctionCall if (!m_class && m_className.empty()) { m_dynamicInvoke = Option::DynamicInvokeFunctions.find(m_name) != Option::DynamicInvokeFunctions.end(); - std::map::const_iterator iter = - FunctionTypeMap.find(m_name); + auto iter = FunctionTypeMap.find(m_name); if (iter != FunctionTypeMap.end()) { m_type = iter->second; } @@ -134,7 +134,7 @@ void SimpleFunctionCall::onParse(AnalysisResultConstPtr ar, FileScopePtr fs) { StaticClassName::onParse(ar, fs); ConstructPtr self = shared_from_this(); switch (m_type) { - case DefineFunction: + case FunType::Define: if (Option::ParseTimeOpts && m_params && unsigned(m_params->getCount() - 2) <= 1u) { // need to register the constant before AnalyzeAll, so that @@ -168,7 +168,7 @@ void SimpleFunctionCall::onParse(AnalysisResultConstPtr ar, FileScopePtr fs) { } } break; - case CreateFunction: + case FunType::Create: if (Option::ParseTimeOpts && m_params->getCount() == 2 && (*m_params)[0]->isLiteralString() && @@ -182,7 +182,7 @@ void SimpleFunctionCall::onParse(AnalysisResultConstPtr ar, FileScopePtr fs) { ar->appendExtraCode(fs->getName(), code); } break; - case VariableArgumentFunction: + case FunType::VariableArgument: /* Note: At this point, we dont have a function scope, so we set @@ -194,16 +194,16 @@ void SimpleFunctionCall::onParse(AnalysisResultConstPtr ar, FileScopePtr fs) { */ fs->setAttribute(FileScope::VariableArgument); break; - case ExtractFunction: + case FunType::Extract: fs->setAttribute(FileScope::ContainsLDynamicVariable); fs->setAttribute(FileScope::ContainsExtract); break; - case CompactFunction: { + case FunType::Compact: { // If all the parameters in the compact() call are statically known, // there is no need to create a variable table. vector literals; if (false && m_params->flattenLiteralStrings(literals)) { - m_type = StaticCompactFunction; + m_type = FunType::StaticCompact; m_params->clearElements(); for (unsigned i = 0; i < literals.size(); i++) { m_params->addElement(literals[i]); @@ -214,12 +214,12 @@ void SimpleFunctionCall::onParse(AnalysisResultConstPtr ar, FileScopePtr fs) { fs->setAttribute(FileScope::ContainsCompact); break; } - case GetDefinedVarsFunction: + case FunType::GetDefinedVars: fs->setAttribute(FileScope::ContainsDynamicVariable); fs->setAttribute(FileScope::ContainsGetDefinedVars); fs->setAttribute(FileScope::ContainsCompact); break; - case UnknownType: + case FunType::Unknown: if (!m_class && m_className.empty()) { ar->parseOnDemandByFunction(m_name); } @@ -329,12 +329,12 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) { // check for dynamic constant and volatile function/class if (!m_class && m_className.empty() && - (m_type == DefineFunction || - m_type == DefinedFunction || - m_type == FunctionExistsFunction || - m_type == FBCallUserFuncSafeFunction || - m_type == ClassExistsFunction || - m_type == InterfaceExistsFunction) && + (m_type == FunType::Define || + m_type == FunType::Defined || + m_type == FunType::FunctionExists || + m_type == FunType::FBCallUserFuncSafe || + m_type == FunType::ClassExists || + m_type == FunType::InterfaceExists) && m_params && m_params->getCount() >= 1) { ExpressionPtr value = (*m_params)[0]; if (value->isScalar()) { @@ -343,7 +343,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) { if (name && name->isLiteralString()) { string symbol = name->getLiteralString(); switch (m_type) { - case DefineFunction: { + case FunType::Define: { ConstantTableConstPtr constants = ar->getConstants(); // system constant if (constants->isPresent(symbol)) { @@ -365,7 +365,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) { } break; } - case DefinedFunction: { + case FunType::Defined: { ConstantTablePtr constants = ar->getConstants(); if (!constants->isPresent(symbol)) { // user constant @@ -373,15 +373,15 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) { if (block) { // found the constant constants = block->getConstants(); // set to be dynamic - if (m_type == DefinedFunction) { + if (m_type == FunType::Defined) { constants->setDynamic(ar, symbol, true); } } } break; } - case FBCallUserFuncSafeFunction: - case FunctionExistsFunction: + case FunType::FBCallUserFuncSafe: + case FunType::FunctionExists: if (!m_no_volatile_check) { FunctionScopePtr func = ar->findFunction(Util::toLower(symbol)); if (func && func->isUserFunction()) { @@ -389,8 +389,8 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) { } break; } - case InterfaceExistsFunction: - case ClassExistsFunction: + case FunType::InterfaceExists: + case FunType::ClassExists: if (!m_no_volatile_check) { ClassScopePtr cls = ar->findClass(Util::toLower(symbol)); if (cls && cls->isUserClass()) { @@ -402,8 +402,8 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) { assert(false); } } - } else if ((m_type == InterfaceExistsFunction || - m_type == ClassExistsFunction) && + } else if ((m_type == FunType::InterfaceExists || + m_type == FunType::ClassExists) && value->is(KindOfSimpleVariable)) { SimpleVariablePtr name = dynamic_pointer_cast(value); if (name && name->getSymbol()) { @@ -413,14 +413,14 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) { } } - if (m_type == StaticCompactFunction) { + if (m_type == FunType::StaticCompact) { FunctionScopePtr fs = getFunctionScope(); VariableTablePtr vt = fs->getVariables(); if (vt->isPseudoMainTable() || vt->getAttribute(VariableTable::ContainsDynamicVariable)) { // When there is a variable table already, we will keep the ordinary // compact() call. - m_type = CompactFunction; + m_type = FunType::Compact; } else { // compact('a', 'b', 'c') becomes compact('a', $a, 'b', $b, 'c', $c) vector new_params; @@ -455,14 +455,14 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) { } } - if (m_type == UnserializeFunction) { + if (m_type == FunType::Unserialize) { ar->forceClassVariants(getOriginalClass(), false); } if (m_params) { markRefParams(m_funcScope, m_name, canInvokeFewArgs()); } } else if (ar->getPhase() == AnalysisResult::AnalyzeFinal) { - if (!m_fromCompiler && m_type == UnknownType && + if (!m_fromCompiler && m_type == FunType::Unknown && !m_class && !m_redeclared && !m_dynamicInvoke && !m_funcScope && (m_className.empty() || (m_classScope && @@ -491,12 +491,12 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) { } bool SimpleFunctionCall::readsLocals() const { - return m_type == GetDefinedVarsFunction || - m_type == CompactFunction; + return m_type == FunType::GetDefinedVars || + m_type == FunType::Compact; } bool SimpleFunctionCall::writesLocals() const { - return m_type == ExtractFunction; + return m_type == FunType::Extract; } void SimpleFunctionCall::updateVtFlags() { @@ -509,7 +509,7 @@ void SimpleFunctionCall::updateVtFlags() { if ((m_classScope && (isSelf() || isParent()) && m_funcScope->usesLSB()) || isStatic() || - m_type == FBCallUserFuncSafeFunction || + m_type == FunType::FBCallUserFuncSafe || m_name == "call_user_func" || m_name == "call_user_func_array" || m_name == "forward_static_call" || @@ -520,23 +520,25 @@ void SimpleFunctionCall::updateVtFlags() { } } } - if (m_type != UnknownType) { + if (m_type != FunType::Unknown) { VariableTablePtr vt = getScope()->getVariables(); switch (m_type) { - case ExtractFunction: + case FunType::Extract: vt->setAttribute(VariableTable::ContainsLDynamicVariable); vt->setAttribute(VariableTable::ContainsExtract); break; - case CompactFunction: + case FunType::Compact: vt->setAttribute(VariableTable::ContainsDynamicVariable); - case StaticCompactFunction: + case FunType::StaticCompact: vt->setAttribute(VariableTable::ContainsCompact); break; - case GetDefinedVarsFunction: + case FunType::GetDefinedVars: vt->setAttribute(VariableTable::ContainsDynamicVariable); vt->setAttribute(VariableTable::ContainsGetDefinedVars); vt->setAttribute(VariableTable::ContainsCompact); break; + default: + break; } } } @@ -571,7 +573,7 @@ bool SimpleFunctionCall::isSimpleDefine(StringData **outName, bool SimpleFunctionCall::isDefineWithoutImpl(AnalysisResultConstPtr ar) { if (m_class || !m_className.empty()) return false; - if (m_type == DefineFunction && m_params && + if (m_type == FunType::Define && m_params && unsigned(m_params->getCount() - 2) <= 1u) { if (m_dynamicConstant) return false; ScalarExpressionPtr name = @@ -603,7 +605,7 @@ ExpressionPtr SimpleFunctionCall::optimize(AnalysisResultConstPtr ar) { } if (!m_funcScope->isUserFunction()) { - if (m_type == ExtractFunction && m_params && m_params->getCount() >= 1) { + if (m_type == FunType::Extract && m_params && m_params->getCount() >= 1) { ExpressionPtr vars = (*m_params)[0]; while (vars) { if (vars->is(KindOfUnaryOpExpression) && @@ -746,7 +748,7 @@ ExpressionPtr SimpleFunctionCall::optimize(AnalysisResultConstPtr ar) { } if (!m_classScope && !m_funcScope->isUserFunction()) { - if (m_type == UnknownType && m_funcScope->isFoldable()) { + if (m_type == FunType::Unknown && m_funcScope->isFoldable()) { Array arr; if (m_params) { if (!m_params->isScalar()) return ExpressionPtr(); @@ -778,7 +780,7 @@ ExpressionPtr SimpleFunctionCall::optimize(AnalysisResultConstPtr ar) { } } - if (m_type != UnknownType || m_safe) { + if (m_type != FunType::Unknown || m_safe) { return ExpressionPtr(); } @@ -799,16 +801,16 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) { } if (!m_class && m_className.empty() && - (m_type == DefineFunction || - m_type == DefinedFunction || - m_type == FBCallUserFuncSafeFunction || - m_type == FunctionExistsFunction || - m_type == ClassExistsFunction || - m_type == InterfaceExistsFunction) && + (m_type == FunType::Define || + m_type == FunType::Defined || + m_type == FunType::FBCallUserFuncSafe || + m_type == FunType::FunctionExists || + m_type == FunType::ClassExists || + m_type == FunType::InterfaceExists) && m_params && - (m_type == DefineFunction ? + (m_type == FunType::Define ? unsigned(m_params->getCount() - 2) <= 1u : - m_type == FBCallUserFuncSafeFunction ? m_params->getCount() >= 1 : + m_type == FunType::FBCallUserFuncSafe ? m_params->getCount() >= 1 : m_params->getCount() == 1)) { ExpressionPtr value = (*m_params)[0]; if (value->isScalar()) { @@ -816,7 +818,7 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) { if (name && name->isLiteralString()) { string symbol = name->getLiteralString(); switch (m_type) { - case DefineFunction: { + case FunType::Define: { ConstantTableConstPtr constants = ar->getConstants(); // system constant if (constants->isPresent(symbol)) { @@ -851,7 +853,7 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) { } break; } - case DefinedFunction: { + case FunType::Defined: { if (symbol == "false" || symbol == "true" || symbol == "null") { @@ -886,14 +888,14 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) { } break; } - case FBCallUserFuncSafeFunction: - case FunctionExistsFunction: { + case FunType::FBCallUserFuncSafe: + case FunType::FunctionExists: { const std::string &lname = Util::toLower(symbol); if (Option::DynamicInvokeFunctions.find(lname) == Option::DynamicInvokeFunctions.end()) { FunctionScopePtr func = ar->findFunction(lname); if (!func) { - if (m_type == FunctionExistsFunction && + if (m_type == FunType::FunctionExists && Option::WholeProgram) { return CONSTANT("false"); } @@ -902,13 +904,13 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) { if (!m_no_volatile_check && func->isUserFunction()) { func->setVolatile(); } - if (!func->isVolatile() && m_type == FunctionExistsFunction) { + if (!func->isVolatile() && m_type == FunType::FunctionExists) { return CONSTANT("true"); } } break; } - case InterfaceExistsFunction: { + case FunType::InterfaceExists: { ClassScopePtrVec classes = ar->findClasses(Util::toLower(symbol)); bool interfaceFound = false; for (ClassScopePtrVec::const_iterator it = classes.begin(); @@ -932,7 +934,7 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) { } break; } - case ClassExistsFunction: { + case FunType::ClassExists: { ClassScopePtrVec classes = ar->findClasses(Util::toLower(symbol)); bool classFound = false; for (ClassScopePtrVec::const_iterator it = classes.begin(); @@ -966,7 +968,7 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) { } ExpressionPtr SimpleFunctionCall::postOptimize(AnalysisResultConstPtr ar) { - if (m_type == StaticCompactFunction) { + if (m_type == FunType::StaticCompact) { for (int i = 0; i < m_params->getCount(); i += 2) { ExpressionPtr e = (*m_params)[i + 1]; if (e->is(KindOfUnaryOpExpression) && @@ -1037,7 +1039,7 @@ TypePtr SimpleFunctionCall::inferAndCheck(AnalysisResultPtr ar, TypePtr type, // handling define("CONSTANT", ...); if (!m_class && m_className.empty()) { - if (m_type == DefineFunction && m_params && + if (m_type == FunType::Define && m_params && unsigned(m_params->getCount() - 2) <= 1u) { ScalarExpressionPtr name = dynamic_pointer_cast((*m_params)[0]); @@ -1097,7 +1099,7 @@ TypePtr SimpleFunctionCall::inferAndCheck(AnalysisResultPtr ar, TypePtr type, if (getScope()->isFirstPass()) { Compiler::Error(Compiler::BadDefine, self); } - } else if (m_type == ExtractFunction || m_type == GetDefinedVarsFunction) { + } else if (m_type == FunType::Extract || m_type == FunType::GetDefinedVars) { getScope()->getVariables()->forceVariants(ar, VariableTable::AnyVars); } } diff --git a/hphp/compiler/expression/simple_function_call.h b/hphp/compiler/expression/simple_function_call.h index 03ec6b3a3..ff7410751 100644 --- a/hphp/compiler/expression/simple_function_call.h +++ b/hphp/compiler/expression/simple_function_call.h @@ -41,9 +41,9 @@ public: bool isDefineWithoutImpl(AnalysisResultConstPtr ar); void setValid() { m_valid = true; } void setFromCompiler() { m_fromCompiler = true; } - void setThrowFatal() { m_type = ThrowFatalFunction; } - int isFatalFunction() const { return m_type == ThrowFatalFunction; } - int isStaticCompact() const { return m_type == StaticCompactFunction; } + void setThrowFatal() { m_type = FunType::ThrowFatal; } + int isFatalFunction() const { return m_type == FunType::ThrowFatal; } + int isStaticCompact() const { return m_type == FunType::StaticCompact; } // define(, ); bool isSimpleDefine(StringData **name, TypedValue *value) const; @@ -74,30 +74,28 @@ public: bool isCallToFunction(const char *name) const; bool isCompilerCallToFunction(const char *name) const; protected: - enum FunctionType { - UnknownType, - DefineFunction, - CreateFunction, - VariableArgumentFunction, - ExtractFunction, - CompactFunction, - StaticCompactFunction, // compact() with statically known variable names - ShellExecFunction, - ConstantFunction, - DefinedFunction, - FunctionExistsFunction, - ClassExistsFunction, - InterfaceExistsFunction, - UnserializeFunction, - GetDefinedVarsFunction, - FBCallUserFuncSafeFunction, - ThrowFatalFunction, - - LastType, // marker, not a valid type + enum class FunType { + Unknown, + Define, + Create, + VariableArgument, + Extract, + Compact, + StaticCompact, // compact() with statically known variable names + ShellExec, + Constant, + Defined, + FunctionExists, + ClassExists, + InterfaceExists, + Unserialize, + GetDefinedVars, + FBCallUserFuncSafe, + ThrowFatal, }; - static std::map FunctionTypeMap; - int m_type; + static std::map FunctionTypeMap; + FunType m_type; unsigned m_dynamicConstant : 1; unsigned m_builtinFunction : 1; unsigned m_fromCompiler : 1; diff --git a/hphp/compiler/statement/function_statement.cpp b/hphp/compiler/statement/function_statement.cpp index b959922f9..5cd40799c 100644 --- a/hphp/compiler/statement/function_statement.cpp +++ b/hphp/compiler/statement/function_statement.cpp @@ -66,6 +66,7 @@ void FunctionStatement::onParse(AnalysisResultConstPtr ar, FileScopePtr scope) { } } } + // note it's important to add to scope, not a pushed FunctionContainer, // as a function may be declared inside a class's method, yet this function // is a global function, not a class method.