Always use type expressions whenever a class name may appear in the code.
[hiphop-php.git] / hphp / compiler / statement / catch_statement.cpp
blob100b79ace963c50dc400ee25148803ea7654ae80
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/compiler/statement/catch_statement.h"
18 #include "hphp/compiler/analysis/analysis_result.h"
19 #include "hphp/compiler/analysis/block_scope.h"
20 #include "hphp/compiler/analysis/function_scope.h"
21 #include "hphp/compiler/analysis/variable_table.h"
22 #include "hphp/compiler/expression/modifier_expression.h"
23 #include "hphp/compiler/expression/scalar_expression.h"
24 #include "hphp/compiler/analysis/code_error.h"
25 #include "hphp/util/util.h"
26 #include "hphp/compiler/analysis/class_scope.h"
27 #include "hphp/compiler/option.h"
29 using namespace HPHP;
31 ///////////////////////////////////////////////////////////////////////////////
32 // constructors/destructors
34 CatchStatement::CatchStatement
35 (STATEMENT_CONSTRUCTOR_PARAMETERS,
36 const std::string &className, const std::string &variable,
37 StatementPtr stmt)
38 : Statement(STATEMENT_CONSTRUCTOR_PARAMETER_VALUES(CatchStatement)),
39 StaticClassName(ExpressionPtr(
40 new ScalarExpression(scope, loc,
41 T_STRING, className, false))),
42 m_variable(new SimpleVariable(scope, loc, variable)),
43 m_stmt(stmt), m_valid(true) {
44 m_variable->setContext(Expression::LValue);
47 CatchStatement::CatchStatement
48 (STATEMENT_CONSTRUCTOR_PARAMETERS,
49 const std::string &className, const std::string &variable,
50 StatementPtr stmt, StatementPtr finallyStmt)
51 : Statement(STATEMENT_CONSTRUCTOR_PARAMETER_VALUES(CatchStatement)),
52 StaticClassName(ExpressionPtr(
53 new ScalarExpression(scope, loc,
54 T_STRING, className, false))),
55 m_variable(new SimpleVariable(scope, loc, variable)),
56 m_stmt(stmt), m_finallyStmt(finallyStmt), m_valid(true) {
57 m_variable->setContext(Expression::LValue);
60 StatementPtr CatchStatement::clone() {
61 CatchStatementPtr stmt(new CatchStatement(*this));
62 stmt->m_stmt = Clone(m_stmt);
63 stmt->m_variable = Clone(m_variable);
64 stmt->m_finallyStmt = Clone(m_finallyStmt);
65 return stmt;
68 ///////////////////////////////////////////////////////////////////////////////
69 // parser functions
71 ///////////////////////////////////////////////////////////////////////////////
72 // static analysis functions
74 void CatchStatement::analyzeProgram(AnalysisResultPtr ar) {
75 addUserClass(ar, m_className);
76 m_variable->analyzeProgram(ar);
77 (void)resolveClass();
78 if (m_stmt) m_stmt->analyzeProgram(ar);
79 if (m_variable->isThis()) {
80 // catch (Exception $this) { ... }
81 // See note in alias_manager.cpp about why this forces a variable table
82 VariableTablePtr variables(getScope()->getVariables());
83 variables->forceVariants(ar, VariableTable::AnyVars);
84 variables->setAttribute(VariableTable::ContainsLDynamicVariable);
88 ConstructPtr CatchStatement::getNthKid(int n) const {
89 switch (n) {
90 case 0:
91 return m_variable;
92 case 1:
93 return m_stmt;
94 case 2:
95 return m_finallyStmt;
96 default:
97 assert(false);
98 break;
100 return ConstructPtr();
103 int CatchStatement::getKidCount() const {
104 return 2 + (m_finallyStmt ? 1 : 0);
107 void CatchStatement::setNthKid(int n, ConstructPtr cp) {
108 switch (n) {
109 case 0:
110 m_variable = dynamic_pointer_cast<SimpleVariable>(cp);
111 break;
112 case 1:
113 m_stmt = dynamic_pointer_cast<Statement>(cp);
114 break;
115 case 2:
116 m_finallyStmt = dynamic_pointer_cast<Statement>(cp);
117 default:
118 assert(false);
119 break;
123 void CatchStatement::inferTypes(AnalysisResultPtr ar) {
124 ClassScopePtr cls = resolveClassWithChecks();
125 TypePtr type;
126 m_valid = cls || isRedeclared();
128 // This can never be a specific exception type, because a future exception
129 // class may be re-declaring, then generated code like this won't work with
130 // DynamicObjectData: p_exception v_e = e;
131 type = Type::Object;
133 m_variable->inferAndCheck(ar, type, true);
134 if (m_stmt) m_stmt->inferTypes(ar);
137 ///////////////////////////////////////////////////////////////////////////////
139 void CatchStatement::outputCodeModel(CodeGenerator &cg) {
140 cg.printObjectHeader("CatchStatement", 4);
141 cg.printPropertyHeader("class");
142 cg.printTypeExpression(m_origClassName);
143 cg.printPropertyHeader("variableName");
144 cg.printValue(m_variable->getName());
145 cg.printPropertyHeader("block");
146 cg.printAsEnclosedBlock(m_stmt);
147 cg.printPropertyHeader("sourceLocation");
148 cg.printLocation(this->getLocation());
149 cg.printObjectFooter();
152 ///////////////////////////////////////////////////////////////////////////////
153 // code generation functions
155 void CatchStatement::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
156 cg_printf(" catch (%s $%s) ", m_origClassName.c_str(),
157 m_variable->getName().c_str());
158 cg_indentBegin("{\n");
159 if (m_stmt) m_stmt->outputPHP(cg, ar);
160 cg_indentEnd("}");