More fixing lint: various conversion constructors in compiler/
[hiphop-php.git] / hphp / compiler / analysis / function_scope.h
blob375069f4b1f519ff75e49197540d9cde6e8091d3
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010- 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 #ifndef incl_HPHP_FUNCTION_SCOPE_H_
18 #define incl_HPHP_FUNCTION_SCOPE_H_
20 #include <compiler/expression/user_attribute.h>
21 #include <compiler/analysis/block_scope.h>
22 #include <compiler/option.h>
24 #include <util/json.h>
25 #include <util/parser/parser.h>
27 namespace HPHP {
28 ///////////////////////////////////////////////////////////////////////////////
30 DECLARE_BOOST_TYPES(Type);
31 DECLARE_BOOST_TYPES(Construct);
32 DECLARE_BOOST_TYPES(ExpressionList);
33 DECLARE_BOOST_TYPES(FileScope);
34 DECLARE_BOOST_TYPES(AnalysisResult);
35 DECLARE_BOOST_TYPES(FunctionScope);
36 DECLARE_BOOST_TYPES(Expression);
37 DECLARE_BOOST_TYPES(SimpleFunctionCall);
38 DECLARE_BOOST_TYPES(ClassScope);
39 DECLARE_BOOST_TYPES(ParameterExpression);
40 DECLARE_BOOST_TYPES(MethodStatement);
42 class CodeGenerator;
44 typedef ExpressionPtr (*FunctionOptPtr)(CodeGenerator *cg,
45 AnalysisResultConstPtr ar,
46 SimpleFunctionCallPtr, int);
48 typedef std::pair< ParameterExpressionPtr, int >
49 ParameterExpressionPtrIdxPair;
51 typedef std::vector< ParameterExpressionPtrIdxPair >
52 ParameterExpressionPtrIdxPairVec;
54 /**
55 * A FunctionScope corresponds to a function declaration. We store all
56 * inferred types and analyzed results here, so not to pollute syntax trees.
58 class FunctionScope : public BlockScope,
59 public JSON::CodeError::ISerializable,
60 public JSON::DocTarget::ISerializable {
61 public:
62 /**
63 * User defined functions.
65 FunctionScope(AnalysisResultConstPtr ar, bool method,
66 const std::string &name, StatementPtr stmt,
67 bool reference, int minParam, int maxParam,
68 ModifierExpressionPtr modifiers, int attribute,
69 const std::string &docComment,
70 FileScopePtr file,
71 const std::vector<UserAttributePtr> &attrs,
72 bool inPseudoMain = false);
74 FunctionScope(FunctionScopePtr orig, AnalysisResultConstPtr ar,
75 const std::string &name, const std::string &originalName,
76 StatementPtr stmt, ModifierExpressionPtr modifiers);
78 /**
79 * System functions.
81 FunctionScope(bool method, const std::string &name, bool reference);
82 void setParamCounts(AnalysisResultConstPtr ar, int minParam, int maxParam);
83 void setParamSpecs(AnalysisResultPtr ar);
84 void setParamName(int index, const std::string &name);
85 void setParamDefault(int index, const char* value, int64_t len,
86 const std::string &text);
87 CStrRef getParamDefault(int index);
88 void setRefParam(int index);
89 bool hasRefParam(int max) const;
91 void addModifier(int mod);
93 /**
94 * What kind of function this is.
96 bool isUserFunction() const { return !m_system;}
97 bool isDynamic() const { return m_dynamic; }
98 bool isPublic() const;
99 bool isProtected() const;
100 bool isPrivate() const;
101 bool isStatic() const;
102 bool isAbstract() const;
103 bool isFinal() const;
104 bool isMagic() const;
105 bool isRefParam(int index) const;
106 bool isRefReturn() const { return m_refReturn;}
107 bool isDynamicInvoke() const { return m_dynamicInvoke; }
108 void setDynamicInvoke();
109 bool hasImpl() const;
110 void setDirectInvoke() { m_directInvoke = true; }
111 bool hasDirectInvoke() const { return m_directInvoke; }
112 bool mayContainThis();
113 bool isClosure() const;
114 bool isGenerator() const;
115 bool isGeneratorFromClosure() const;
116 int allocYieldLabel() { return ++m_yieldLabelCount; }
117 int getYieldLabelCount() const { return m_yieldLabelCount; }
118 bool hasGeneratorAsBody() const;
119 MethodStatementRawPtr getOrigGenStmt() const;
120 FunctionScopeRawPtr getOrigGenFS() const;
121 void setClosureGenerator() { m_closureGenerator = true; }
122 bool isClosureGenerator() const {
123 assert(!m_closureGenerator || isClosure());
124 return m_closureGenerator;
126 bool needsClassParam();
128 void setInlineSameContext(bool f) { m_inlineSameContext = f; }
129 bool getInlineSameContext() const { return m_inlineSameContext; }
130 void setContextSensitive(bool f) { m_contextSensitive = f; }
131 bool getContextSensitive() const { return m_contextSensitive; }
132 void setInlineAsExpr(bool f) { m_inlineAsExpr = f; }
133 bool getInlineAsExpr() const { return m_inlineAsExpr; }
134 int nextInlineIndex() { return ++m_inlineIndex; }
136 bool usesLSB() const { return !m_noLSB; }
137 void clearUsesLSB() { m_noLSB = true; }
138 bool nextLSB() const { return m_nextLSB; }
139 void setNextLSB(bool f) { m_nextLSB = f; }
141 void setHasGoto() { m_hasGoto = true; }
142 void setHasTry() { m_hasTry = true; }
143 bool hasGoto() const { return m_hasGoto; }
144 bool hasTry() const { return m_hasTry; }
145 unsigned getNewID() { return m_nextID++; }
147 bool needsLocalThis() const;
150 * Either __construct or a class-name constructor.
152 bool isConstructor(ClassScopePtr cls) const;
154 const std::string &getParamName(int index) const;
156 const std::string &name() const {
157 return getName();
160 virtual std::string getId() const;
161 std::string getInjectionId() const;
163 int getRedeclaringId() const {
164 return m_redeclaring;
167 void setDynamic() {
168 m_dynamic = true;
171 void setSystem() {
172 m_system = true;
173 m_volatile = false;
177 * Tell this function about another outer scope that contains it.
179 void addClonedTraitOuterScope(FunctionScopePtr scope) {
180 m_clonedTraitOuterScope.push_back(scope);
184 * Get/set original name of the function, without case being lowered.
186 const std::string &getOriginalName() const;
187 void setOriginalName(const std::string &name) { m_originalName = name; }
189 std::string getDocName() const;
190 std::string getDocFullName() const;
193 * If class method, returns class::name, otherwise just name.
195 std::string getFullName() const;
196 std::string getOriginalFullName() const;
199 * Whether this function can take variable number of arguments.
201 bool isVariableArgument() const;
202 bool isReferenceVariableArgument() const;
203 void setVariableArgument(int reference);
204 bool isMixedVariableArgument() const;
207 * Whether this function has no side effects
209 bool hasEffect() const;
210 void setNoEffect();
213 * Whether this function can be constant folded
215 bool isFoldable() const;
216 void setIsFoldable();
219 * If this is a builtin function and does not need an ActRec
221 bool needsActRec() const;
222 void setNeedsActRec();
225 * If this is a builtin and can be redefined
227 bool ignoreRedefinition() const;
228 void setIgnoreRedefinition();
231 * Whether this function is a runtime helper function
233 void setHelperFunction();
236 * Whether this function returns reference or has reference parameters.
238 bool containsReference() const;
241 * Whether this function contains a usage of $this
243 bool containsThis() const { return m_containsThis;}
244 void setContainsThis(bool f = true);
245 bool containsBareThis() const { return m_containsBareThis; }
246 bool containsRefThis() const { return m_containsBareThis & 2; }
247 void setContainsBareThis(bool f, bool ref = false);
249 * How many parameters a caller should provide.
251 int getMinParamCount() const { return m_minParam;}
252 int getMaxParamCount() const { return m_maxParam;}
253 int getOptionalParamCount() const { return m_maxParam - m_minParam;}
256 * What is the inferred type of this function's return.
258 void pushReturnType();
259 void setReturnType(AnalysisResultConstPtr ar, TypePtr type);
260 TypePtr getReturnType() const {
261 return m_prevReturn ? m_prevReturn : m_returnType;
263 bool popReturnType();
264 void resetReturnType();
266 void addRetExprToFix(ExpressionPtr e);
267 void clearRetExprs();
268 void fixRetExprs();
270 bool needsTypeCheckWrapper() const;
272 void setOptFunction(FunctionOptPtr fn) { m_optFunction = fn; }
273 FunctionOptPtr getOptFunction() const { return m_optFunction; }
276 * Whether this is a virtual function that needs to go through invoke().
277 * A perfect virtual will be generated as C++ virtual function without
278 * going through invoke(), but rather directly generated as obj->foo().
279 * "Overriding" is only being used by magic methods, enforcing parameter
280 * and return types.
282 void setVirtual() { m_virtual = true;}
283 bool isVirtual() const { return m_virtual;}
284 void setHasOverride() { m_hasOverride = true; }
285 bool hasOverride() const { return m_hasOverride; }
286 void setPerfectVirtual();
287 bool isPerfectVirtual() const { return m_perfectVirtual;}
288 void setOverriding(TypePtr returnType, TypePtr param1 = TypePtr(),
289 TypePtr param2 = TypePtr());
290 bool isOverriding() const { return m_overriding;}
293 * Whether same function name was declared twice or more.
295 void setRedeclaring(int redecId) {
296 m_redeclaring = redecId;
297 setVolatile(); // redeclared function is also volatile
299 bool isRedeclaring() const { return m_redeclaring >= 0;}
301 void setLocalRedeclaring() { m_localRedeclaring = true; }
302 bool isLocalRedeclaring() const { return m_localRedeclaring; }
304 /* For function_exists */
305 void setVolatile() { m_volatile = true; }
306 bool isVolatile() const { return m_volatile; }
307 bool isPersistent() const { return m_persistent; }
308 void setPersistent(bool p) { m_persistent = p; }
310 bool isInlined() const { return m_inlineable; }
311 void disableInline() { m_inlineable = false; }
313 /* Whether this function is brought in by a separable extension */
314 void setSepExtension() { m_sep = true;}
315 bool isSepExtension() const { return m_sep;}
317 /* Whether we need to worry about the named return value optimization
318 for this function */
319 void setNRVOFix(bool flag) { m_nrvoFix = flag; }
320 bool getNRVOFix() const { return m_nrvoFix; }
322 /* Indicates if a function may need to use a VarEnv or varargs (aka
323 * extraArgs) at run time */
324 bool mayUseVV() const;
327 * Whether this function matches the specified one with same number of
328 * parameters and types and defaults, so to qualify for perfect virtuals.
330 bool matchParams(FunctionScopePtr func);
333 * What is the inferred type of this function's parameter at specified
334 * index. Returns number of extra arguments to put into ArgumentArray.
336 int inferParamTypes(AnalysisResultPtr ar, ConstructPtr exp,
337 ExpressionListPtr params, bool &valid);
339 TypePtr setParamType(AnalysisResultConstPtr ar, int index, TypePtr type);
340 TypePtr getParamType(int index);
341 TypePtr getParamTypeSpec(int index) { return m_paramTypeSpecs[index]; }
343 typedef hphp_hash_map<std::string, ExpressionPtr, string_hashi,
344 string_eqstri> UserAttributeMap;
346 UserAttributeMap& userAttributes() { return m_userAttributes;}
349 * Override BlockScope::outputPHP() to generate return type.
351 virtual void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
353 * Serialize the iface, not everything.
355 void serialize(JSON::CodeError::OutputStream &out) const;
356 void serialize(JSON::DocTarget::OutputStream &out) const;
358 bool inPseudoMain() const {
359 return m_pseudoMain;
362 void setMagicMethod() {
363 m_magicMethod = true;
365 bool isMagicMethod() const {
366 return m_magicMethod;
369 void setStmtCloned(StatementPtr stmt) {
370 m_stmtCloned = stmt;
373 void setClosureVars(ExpressionListPtr closureVars) {
374 m_closureVars = closureVars;
377 ExpressionListPtr getClosureVars() const {
378 return m_closureVars;
381 void getClosureUseVars(ParameterExpressionPtrIdxPairVec &useVars,
382 bool filterUsed = true);
384 bool needsAnonClosureClass(ParameterExpressionPtrVec &useVars);
386 bool needsAnonClosureClass(ParameterExpressionPtrIdxPairVec &useVars);
388 void addCaller(BlockScopePtr caller, bool careAboutReturn = true);
389 void addNewObjCaller(BlockScopePtr caller);
391 ReadWriteMutex &getInlineMutex() { return m_inlineMutex; }
393 DECLARE_BOOST_TYPES(FunctionInfo);
395 static void RecordFunctionInfo(std::string fname, FunctionScopePtr func);
397 static FunctionInfoPtr GetFunctionInfo(std::string fname);
399 class FunctionInfo {
400 public:
401 explicit FunctionInfo(int rva = -1)
402 : m_maybeStatic(false)
403 , m_maybeRefReturn(false)
404 , m_refVarArg(rva)
407 bool isRefParam(int p) const {
408 if (m_refVarArg >= 0 && p >= m_refVarArg) return true;
409 return (m_refParams.find(p) != m_refParams.end());
412 void setRefVarArg(int rva) {
413 if (rva > m_refVarArg) m_refVarArg = rva;
416 void setRefParam(int p) {
417 m_refParams.insert(p);
420 void setMaybeStatic() { m_maybeStatic = true; }
421 bool getMaybeStatic() { return m_maybeStatic; }
423 void setMaybeRefReturn() { m_maybeRefReturn = true; }
424 bool getMaybeRefReturn() { return m_maybeRefReturn; }
426 private:
427 bool m_maybeStatic; // this could be a static method
428 bool m_maybeRefReturn;
429 int m_refVarArg; // -1: no ref varargs;
430 // otherwise, any arg >= m_refVarArg is a reference
431 std::set<int> m_refParams; // set of ref arg positions
434 private:
435 void init(AnalysisResultConstPtr ar);
437 static StringToFunctionInfoPtrMap s_refParamInfo;
439 int m_minParam;
440 int m_maxParam;
441 int m_attribute;
442 std::vector<std::string> m_paramNames;
443 TypePtrVec m_paramTypes;
444 TypePtrVec m_paramTypeSpecs;
445 std::vector<String> m_paramDefaults;
446 std::vector<std::string> m_paramDefaultTexts;
447 std::vector<bool> m_refs;
448 TypePtr m_returnType;
449 TypePtr m_prevReturn;
450 ModifierExpressionPtr m_modifiers;
451 UserAttributeMap m_userAttributes;
453 unsigned m_hasVoid : 1;
454 unsigned m_method : 1;
455 unsigned m_refReturn : 1; // whether it's "function &get_reference()"
456 unsigned m_virtual : 1;
457 unsigned m_hasOverride : 1;
458 unsigned m_perfectVirtual : 1;
459 unsigned m_dynamic : 1;
460 unsigned m_dynamicInvoke : 1;
461 unsigned m_overriding : 1; // overriding a virtual function
462 unsigned m_volatile : 1; // for function_exists
463 unsigned m_persistent : 1;
464 unsigned m_pseudoMain : 1;
465 unsigned m_magicMethod : 1;
466 unsigned m_system : 1;
467 unsigned m_inlineable : 1;
468 unsigned m_sep : 1;
469 unsigned m_containsThis : 1; // contains a usage of $this?
470 unsigned m_containsBareThis : 2; // $this outside object-context,
471 // 2 if in reference context
472 unsigned m_nrvoFix : 1;
473 unsigned m_inlineAsExpr : 1;
474 unsigned m_inlineSameContext : 1;
475 unsigned m_contextSensitive : 1;
476 unsigned m_directInvoke : 1;
477 unsigned m_closureGenerator : 1;
478 unsigned m_noLSB : 1;
479 unsigned m_nextLSB : 1;
480 unsigned m_hasTry : 1;
481 unsigned m_hasGoto : 1;
482 unsigned m_localRedeclaring : 1;
484 int m_redeclaring; // multiple definition of the same function
485 StatementPtr m_stmtCloned; // cloned method body stmt
486 int m_inlineIndex;
487 FunctionOptPtr m_optFunction;
488 ExpressionPtrVec m_retExprsToFix;
489 ExpressionListPtr m_closureVars;
490 ExpressionListPtr m_closureValues;
491 ReadWriteMutex m_inlineMutex;
492 unsigned m_nextID; // used when cloning generators for traits
493 int m_yieldLabelCount; // number of allocated yield labels
494 std::list<FunctionScopeRawPtr> m_clonedTraitOuterScope;
497 ///////////////////////////////////////////////////////////////////////////////
499 #endif // incl_HPHP_FUNCTION_SCOPE_H_