2 +----------------------------------------------------------------------+
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"
31 ///////////////////////////////////////////////////////////////////////////////
32 // constructors/destructors
34 CatchStatement::CatchStatement
35 (STATEMENT_CONSTRUCTOR_PARAMETERS
,
36 const std::string
&className
, const std::string
&variable
,
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
);
68 ///////////////////////////////////////////////////////////////////////////////
71 ///////////////////////////////////////////////////////////////////////////////
72 // static analysis functions
74 void CatchStatement::analyzeProgram(AnalysisResultPtr ar
) {
75 addUserClass(ar
, m_className
);
76 m_variable
->analyzeProgram(ar
);
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 {
100 return ConstructPtr();
103 int CatchStatement::getKidCount() const {
104 return 2 + (m_finallyStmt
? 1 : 0);
107 void CatchStatement::setNthKid(int n
, ConstructPtr cp
) {
110 m_variable
= dynamic_pointer_cast
<SimpleVariable
>(cp
);
113 m_stmt
= dynamic_pointer_cast
<Statement
>(cp
);
116 m_finallyStmt
= dynamic_pointer_cast
<Statement
>(cp
);
123 void CatchStatement::inferTypes(AnalysisResultPtr ar
) {
124 ClassScopePtr cls
= resolveClassWithChecks();
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;
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
);