resolve potentially global namespaced functions
When we see `define('Foo', 'Bar')` in a namespace, we don't know if it is talking about the global define function or the a local namespace one. What should we do? Does marking constants Dynamic that aren't actually dynamic break anything? Without this, HPHP creates a creates a CodeError.js
Closes #771
Esse commit está contido em:
@@ -44,6 +44,7 @@
|
||||
#include "hphp/compiler/expression/constant_expression.h"
|
||||
#include "hphp/compiler/expression/expression_list.h"
|
||||
#include "hphp/compiler/expression/array_pair_expression.h"
|
||||
#include "hphp/compiler/expression/simple_function_call.h"
|
||||
#include "hphp/runtime/ext/ext_json.h"
|
||||
#include "hphp/runtime/base/zend/zend_printf.h"
|
||||
#include "hphp/runtime/base/program_functions.h"
|
||||
@@ -158,6 +159,10 @@ void AnalysisResult::parseOnDemandBy(const string &name,
|
||||
}
|
||||
}
|
||||
|
||||
void AnalysisResult::addNSFallbackFunc(ConstructPtr c, FileScopePtr fs) {
|
||||
m_nsFallbackFuncs.insert(std::make_pair(c, fs));
|
||||
}
|
||||
|
||||
FileScopePtr AnalysisResult::findFileScope(const std::string &name) const {
|
||||
StringToFileScopePtrMap::const_iterator iter = m_files.find(name);
|
||||
if (iter != m_files.end()) {
|
||||
@@ -541,6 +546,17 @@ void AnalysisResult::checkClassDerivations() {
|
||||
}
|
||||
}
|
||||
|
||||
void AnalysisResult::resolveNSFallbackFuncs() {
|
||||
for (auto &pair : m_nsFallbackFuncs) {
|
||||
SimpleFunctionCallPtr sfc =
|
||||
static_pointer_cast<SimpleFunctionCall>(pair.first);
|
||||
sfc->resolveNSFallbackFunc(
|
||||
shared_from_this(),
|
||||
pair.second
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void AnalysisResult::collectFunctionsAndClasses(FileScopePtr fs) {
|
||||
const StringToFunctionScopePtrMap &funcs = fs->getFunctions();
|
||||
|
||||
@@ -625,6 +641,7 @@ void AnalysisResult::analyzeProgram(bool system /* = false */) {
|
||||
}
|
||||
|
||||
checkClassDerivations();
|
||||
resolveNSFallbackFuncs();
|
||||
|
||||
// Analyze All
|
||||
Logger::Verbose("Analyzing All");
|
||||
|
||||
@@ -148,6 +148,8 @@ public:
|
||||
void addEntryPoint(const std::string &name);
|
||||
void addEntryPoints(const std::vector<std::string> &names);
|
||||
|
||||
void addNSFallbackFunc(ConstructPtr c, FileScopePtr fs);
|
||||
|
||||
void loadBuiltinFunctions();
|
||||
void loadBuiltins();
|
||||
void analyzeProgram(bool system = false);
|
||||
@@ -302,6 +304,7 @@ private:
|
||||
Package *m_package;
|
||||
bool m_parseOnDemand;
|
||||
std::vector<std::string> m_parseOnDemandDirs;
|
||||
std::set<std::pair<ConstructPtr, FileScopePtr> > m_nsFallbackFuncs;
|
||||
Phase m_phase;
|
||||
StringToFileScopePtrMap m_files;
|
||||
FileScopePtrVec m_fileScopes;
|
||||
@@ -364,6 +367,8 @@ private:
|
||||
*/
|
||||
void checkClassDerivations();
|
||||
|
||||
void resolveNSFallbackFuncs();
|
||||
|
||||
int getFileSize(FileScopePtr fs);
|
||||
|
||||
public:
|
||||
|
||||
@@ -132,6 +132,21 @@ void SimpleFunctionCall::deepCopy(SimpleFunctionCallPtr exp) {
|
||||
|
||||
void SimpleFunctionCall::onParse(AnalysisResultConstPtr ar, FileScopePtr fs) {
|
||||
StaticClassName::onParse(ar, fs);
|
||||
mungeIfSpecialFunction(ar, fs);
|
||||
|
||||
if (m_type == FunType::Unknown && !m_class && m_className.empty()) {
|
||||
ar->parseOnDemandByFunction(m_name);
|
||||
int pos = m_name.rfind('\\');
|
||||
std::string short_name = m_name.substr(pos + 1);
|
||||
auto iter = FunctionTypeMap.find(short_name);
|
||||
if (iter != FunctionTypeMap.end()) {
|
||||
ar->lock()->addNSFallbackFunc(shared_from_this(), fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleFunctionCall::mungeIfSpecialFunction(AnalysisResultConstPtr ar,
|
||||
FileScopePtr fs) {
|
||||
ConstructPtr self = shared_from_this();
|
||||
switch (m_type) {
|
||||
case FunType::Define:
|
||||
@@ -220,15 +235,28 @@ void SimpleFunctionCall::onParse(AnalysisResultConstPtr ar, FileScopePtr fs) {
|
||||
fs->setAttribute(FileScope::ContainsCompact);
|
||||
break;
|
||||
case FunType::Unknown:
|
||||
if (!m_class && m_className.empty()) {
|
||||
ar->parseOnDemandByFunction(m_name);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleFunctionCall::resolveNSFallbackFunc(
|
||||
AnalysisResultConstPtr ar, FileScopePtr fs) {
|
||||
if (ar->findFunction(m_name)) {
|
||||
// the fully qualified name for this function exists, nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
int pos = m_name.rfind('\\');
|
||||
std::string short_name = m_name.substr(pos + 1);
|
||||
auto iter = FunctionTypeMap.find(m_name);
|
||||
assert(iter != FunctionTypeMap.end());
|
||||
m_type = iter->second;
|
||||
mungeIfSpecialFunction(ar, fs);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// static analysis functions
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ public:
|
||||
void setLocalThis(const std::string &name) { m_localThis = name; }
|
||||
bool isCallToFunction(const char *name) const;
|
||||
bool isCompilerCallToFunction(const char *name) const;
|
||||
void resolveNSFallbackFunc(AnalysisResultConstPtr ar, FileScopePtr fs);
|
||||
protected:
|
||||
enum class FunType {
|
||||
Unknown,
|
||||
@@ -118,6 +119,8 @@ private:
|
||||
ExpressionPtr funcName,
|
||||
ClassScopePtr &clsScope);
|
||||
std::string getThisString(bool withArrow);
|
||||
void mungeIfSpecialFunction(AnalysisResultConstPtr ar, FileScopePtr fs);
|
||||
|
||||
std::string m_localThis;
|
||||
void *m_extra; // e.g., raw pointer to the symbol defined
|
||||
};
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário