diff --git a/hphp/compiler/analysis/analysis_result.cpp b/hphp/compiler/analysis/analysis_result.cpp index 06e108c4d..9ec130058 100644 --- a/hphp/compiler/analysis/analysis_result.cpp +++ b/hphp/compiler/analysis/analysis_result.cpp @@ -423,6 +423,16 @@ void AnalysisResult::markRedeclaringClasses() { } } + auto markRedeclaring = [&] (const std::string& name) { + auto it = m_classDecs.find(name); + if (it != m_classDecs.end()) { + auto& classes = it->second; + for (unsigned int i = 0; i < classes.size(); ++i) { + classes[i]->setRedeclaring(ar, i); + } + } + }; + /* * In WholeProgram mode, during parse time we collected all * class_alias calls so we can mark the targets of such calls @@ -446,19 +456,19 @@ void AnalysisResult::markRedeclaringClasses() { * as redeclaring for now. */ for (auto& kv : m_classAliases) { - auto markRedeclaring = [&] (const std::string& name) { - auto it = m_classDecs.find(name); - if (it != m_classDecs.end()) { - auto& classes = it->second; - for (unsigned int i = 0; i < classes.size(); ++i) { - classes[i]->setRedeclaring(ar, i); - } - } - }; - markRedeclaring(Util::toLower(kv.first)); markRedeclaring(Util::toLower(kv.second)); } + + /* + * Similar to class_alias, when a type alias is declared with the + * same name as a class in the program, we need to make sure the + * class is marked redeclaring. It is possible in some requests + * that things like 'instanceof Foo' will not mean the same thing. + */ + for (auto& name : m_typeAliasNames) { + markRedeclaring(Util::toLower(name)); + } } /////////////////////////////////////////////////////////////////////////////// @@ -643,6 +653,8 @@ void AnalysisResult::collectFunctionsAndClasses(FileScopePtr fs) { m_classAliases.insert(fs->getClassAliases().begin(), fs->getClassAliases().end()); + m_typeAliasNames.insert(fs->getTypeAliasNames().begin(), + fs->getTypeAliasNames().end()); } static bool by_filename(const FileScopePtr &f1, const FileScopePtr &f2) { diff --git a/hphp/compiler/analysis/analysis_result.h b/hphp/compiler/analysis/analysis_result.h index 3a4a84594..d77f9bd21 100644 --- a/hphp/compiler/analysis/analysis_result.h +++ b/hphp/compiler/analysis/analysis_result.h @@ -324,6 +324,9 @@ private: // Only in WholeProgram mode. See markRedeclaringClasses. std::multimap m_classAliases; + // Names of type aliases. + std::set m_typeAliasNames; + bool m_classForcedVariants[2]; StatementPtrVec m_stmts; diff --git a/hphp/compiler/analysis/file_scope.h b/hphp/compiler/analysis/file_scope.h index add19363c..378b79b1f 100644 --- a/hphp/compiler/analysis/file_scope.h +++ b/hphp/compiler/analysis/file_scope.h @@ -145,6 +145,14 @@ public: return m_classAliasMap; } + void addTypeAliasName(const std::string& name) { + m_typeAliasNames.insert(name); + } + + std::set const& getTypeAliasNames() const { + return m_typeAliasNames; + } + /** * Called only by World */ @@ -217,6 +225,11 @@ private: // This is only needed in WholeProgram mode. std::multimap m_classAliasMap; + // Set of names that are on the left hand side of type alias + // declarations. We need this to make sure we don't mark classes + // with the same name Unique. + std::set m_typeAliasNames; + FunctionScopePtr createPseudoMain(AnalysisResultConstPtr ar); void setFileLevel(StatementListPtr stmt); }; diff --git a/hphp/compiler/parser/parser.cpp b/hphp/compiler/parser/parser.cpp index c07c97258..cdc0fb8ad 100644 --- a/hphp/compiler/parser/parser.cpp +++ b/hphp/compiler/parser/parser.cpp @@ -1634,7 +1634,9 @@ void Parser::onGoto(Token &out, Token &label, bool limited) { } void Parser::onTypedef(Token& out, const Token& name, const Token& type) { - out->stmt = NEW_STMT(TypedefStatement, name.text(), type.text()); + auto td_stmt = NEW_STMT(TypedefStatement, name.text(), type.text()); + td_stmt->onParse(m_ar, m_file); + out->stmt = td_stmt; } void Parser::onTypeAnnotation(Token& out, const Token& name, diff --git a/hphp/compiler/statement/typedef_statement.cpp b/hphp/compiler/statement/typedef_statement.cpp index 826324a62..e83401bda 100644 --- a/hphp/compiler/statement/typedef_statement.cpp +++ b/hphp/compiler/statement/typedef_statement.cpp @@ -15,6 +15,8 @@ */ #include "hphp/compiler/statement/typedef_statement.h" +#include "hphp/compiler/analysis/file_scope.h" + namespace HPHP { ////////////////////////////////////////////////////////////////////// @@ -57,6 +59,10 @@ void TypedefStatement::inferTypes(AnalysisResultPtr) {} void TypedefStatement::outputPHP(CodeGenerator& cg, AnalysisResultPtr ar) { } +void TypedefStatement::onParse(AnalysisResultConstPtr ar, FileScopePtr scope) { + scope->addTypeAliasName(name); +} + ////////////////////////////////////////////////////////////////////// } diff --git a/hphp/compiler/statement/typedef_statement.h b/hphp/compiler/statement/typedef_statement.h index f81c91d5c..1466654cd 100644 --- a/hphp/compiler/statement/typedef_statement.h +++ b/hphp/compiler/statement/typedef_statement.h @@ -25,7 +25,7 @@ namespace HPHP { ////////////////////////////////////////////////////////////////////// -struct TypedefStatement : Statement { +struct TypedefStatement : Statement, IParseHandler { explicit TypedefStatement(STATEMENT_CONSTRUCTOR_PARAMETERS, const std::string& name, const std::string& value); @@ -33,6 +33,10 @@ struct TypedefStatement : Statement { DECLARE_STATEMENT_VIRTUAL_FUNCTIONS; +public: // IParseHandler + void onParse(AnalysisResultConstPtr, FileScopePtr); + +public: const std::string name; const std::string value; };