2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 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 "hphp/compiler/expression/user_attribute.h"
25 #include "hphp/compiler/analysis/block_scope.h"
26 #include "hphp/compiler/option.h"
27 #include "hphp/compiler/json.h"
29 #include "hphp/util/hash-map-typedefs.h"
30 #include "hphp/parser/parser.h"
33 ///////////////////////////////////////////////////////////////////////////////
35 DECLARE_BOOST_TYPES(Type
);
36 DECLARE_BOOST_TYPES(Construct
);
37 DECLARE_BOOST_TYPES(ExpressionList
);
38 DECLARE_BOOST_TYPES(FileScope
);
39 DECLARE_BOOST_TYPES(AnalysisResult
);
40 DECLARE_BOOST_TYPES(FunctionScope
);
41 DECLARE_BOOST_TYPES(Expression
);
42 DECLARE_BOOST_TYPES(SimpleFunctionCall
);
43 DECLARE_BOOST_TYPES(ClassScope
);
44 DECLARE_BOOST_TYPES(ParameterExpression
);
45 DECLARE_BOOST_TYPES(MethodStatement
);
49 typedef ExpressionPtr (*FunctionOptPtr
)(CodeGenerator
*cg
,
50 AnalysisResultConstPtr ar
,
51 SimpleFunctionCallPtr
, int);
53 typedef std::pair
< ParameterExpressionPtr
, int >
54 ParameterExpressionPtrIdxPair
;
56 typedef std::vector
< ParameterExpressionPtrIdxPair
>
57 ParameterExpressionPtrIdxPairVec
;
60 * A FunctionScope corresponds to a function declaration. We store all
61 * inferred types and analyzed results here, so not to pollute syntax trees.
63 class FunctionScope
: public BlockScope
,
64 public JSON::CodeError::ISerializable
,
65 public JSON::DocTarget::ISerializable
{
68 * User defined functions.
70 FunctionScope(AnalysisResultConstPtr ar
, bool method
,
71 const std::string
&name
, StatementPtr stmt
,
72 bool reference
, int minParam
, int maxParam
,
73 ModifierExpressionPtr modifiers
, int attribute
,
74 const std::string
&docComment
,
76 const std::vector
<UserAttributePtr
> &attrs
,
77 bool inPseudoMain
= false);
79 FunctionScope(FunctionScopePtr orig
, AnalysisResultConstPtr ar
,
80 const std::string
&name
, const std::string
&originalName
,
81 StatementPtr stmt
, ModifierExpressionPtr modifiers
, bool user
);
86 FunctionScope(bool method
, const std::string
&name
, bool reference
);
87 void setParamCounts(AnalysisResultConstPtr ar
, int minParam
, int maxParam
);
88 void setParamSpecs(AnalysisResultPtr ar
);
89 void setParamName(int index
, const std::string
&name
);
90 void setParamDefault(int index
, const char* value
, int64_t len
,
91 const std::string
&text
);
92 void setRefParam(int index
);
93 bool hasRefParam(int max
) const;
95 void addModifier(int mod
);
97 bool hasUserAttr(const char *attr
) const;
100 * What kind of function this is.
102 bool isUserFunction() const { return !m_system
&& !isNative(); }
103 bool isSystem() const { return m_system
; }
104 bool isDynamic() const { return m_dynamic
; }
105 bool isPublic() const;
106 bool isProtected() const;
107 bool isPrivate() const;
108 bool isStatic() const;
109 bool isAbstract() const;
110 bool isNative() const;
111 bool isFinal() const;
112 bool isMagic() const;
113 bool isBuiltin() const override
{ return !getStmt() || isNative(); }
114 bool isRefParam(int index
) const;
115 bool isRefReturn() const { return m_refReturn
;}
116 bool isDynamicInvoke() const { return m_dynamicInvoke
; }
117 void setDynamicInvoke();
118 bool hasImpl() const;
119 void setDirectInvoke() { m_directInvoke
= true; }
120 bool hasDirectInvoke() const { return m_directInvoke
; }
121 bool isZendParamMode() const;
122 bool mayContainThis();
123 bool isClosure() const;
124 bool isGenerator() const { return m_generator
; }
125 void setGenerator(bool f
) { m_generator
= f
; }
126 bool isAsync() const { return m_async
; }
127 void setAsync(bool f
) { m_async
= f
; }
129 bool needsClassParam();
131 void setInlineSameContext(bool f
) { m_inlineSameContext
= f
; }
132 bool getInlineSameContext() const { return m_inlineSameContext
; }
133 void setContextSensitive(bool f
) { m_contextSensitive
= f
; }
134 bool getContextSensitive() const { return m_contextSensitive
; }
135 void setInlineAsExpr(bool f
) { m_inlineAsExpr
= f
; }
136 bool getInlineAsExpr() const { return m_inlineAsExpr
; }
137 int nextInlineIndex() { return ++m_inlineIndex
; }
139 bool usesLSB() const { return !m_noLSB
; }
140 void clearUsesLSB() { m_noLSB
= true; }
141 bool nextLSB() const { return m_nextLSB
; }
142 void setNextLSB(bool f
) { m_nextLSB
= f
; }
144 void setHasGoto() { m_hasGoto
= true; }
145 void setHasTry() { m_hasTry
= true; }
146 bool hasGoto() const { return m_hasGoto
; }
147 bool hasTry() const { return m_hasTry
; }
148 unsigned getNewID() { return m_nextID
++; }
150 bool needsLocalThis() const;
153 * Either __construct or a class-name constructor.
155 bool isConstructor(ClassScopePtr cls
) const;
157 const std::string
&getParamName(int index
) const;
159 const std::string
&name() const {
163 int getRedeclaringId() const {
164 return m_redeclaring
;
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;
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 noFCallBuiltin() const;
222 void setNoFCallBuiltin();
225 * If this is a builtin (C++ or PHP) and can be redefined
227 bool allowOverride() const;
228 void setAllowOverride();
230 bool needsFinallyLocals() const;
233 * Whether this function is a runtime helper function
235 void setHelperFunction();
238 * Whether this function returns reference or has reference parameters.
240 bool containsReference() const;
243 * Whether this function contains a usage of $this
245 bool containsThis() const { return m_containsThis
;}
246 void setContainsThis(bool f
= true);
247 bool containsBareThis() const { return m_containsBareThis
; }
248 bool containsRefThis() const { return m_containsBareThis
& 2; }
249 void setContainsBareThis(bool f
, bool ref
= false);
251 * How many parameters a caller should provide.
253 int getMinParamCount() const { return m_minParam
;}
254 int getMaxParamCount() const { return m_maxParam
;}
255 int getOptionalParamCount() const { return m_maxParam
- m_minParam
;}
258 * What is the inferred type of this function's return.
259 * Note that for generators and async functions, this is different
260 * from what caller actually gets when calling the function.
262 void pushReturnType();
263 void setReturnType(AnalysisResultConstPtr ar
, TypePtr type
);
264 TypePtr
getReturnType() const {
265 return m_prevReturn
? m_prevReturn
: m_returnType
;
267 bool popReturnType();
268 void resetReturnType();
270 void addRetExprToFix(ExpressionPtr e
);
271 void clearRetExprs();
274 void setOptFunction(FunctionOptPtr fn
) { m_optFunction
= fn
; }
275 FunctionOptPtr
getOptFunction() const { return m_optFunction
; }
278 * Whether this is a virtual function that needs to go through invoke().
279 * A perfect virtual will be generated as C++ virtual function without
280 * going through invoke(), but rather directly generated as obj->foo().
281 * "Overriding" is only being used by magic methods, enforcing parameter
284 void setVirtual() { m_virtual
= true;}
285 bool isVirtual() const { return m_virtual
;}
286 void setHasOverride() { m_hasOverride
= true; }
287 bool hasOverride() const { return m_hasOverride
; }
288 void setPerfectVirtual();
289 bool isPerfectVirtual() const { return m_perfectVirtual
;}
290 void setOverriding(TypePtr returnType
, TypePtr param1
= TypePtr(),
291 TypePtr param2
= TypePtr());
292 bool isOverriding() const { return m_overriding
;}
295 * Whether same function name was declared twice or more.
297 void setRedeclaring(int redecId
) {
298 m_redeclaring
= redecId
;
299 setVolatile(); // redeclared function is also volatile
301 bool isRedeclaring() const { return m_redeclaring
>= 0;}
303 void setLocalRedeclaring() { m_localRedeclaring
= true; }
304 bool isLocalRedeclaring() const { return m_localRedeclaring
; }
306 /* For function_exists */
307 void setVolatile() { m_volatile
= true; }
308 bool isVolatile() const { return m_volatile
; }
309 bool isPersistent() const { return m_persistent
; }
310 void setPersistent(bool p
) { m_persistent
= p
; }
312 bool isInlined() const { return m_inlineable
; }
313 void disableInline() { m_inlineable
= false; }
315 /* Whether we need to worry about the named return value optimization
317 void setNRVOFix(bool flag
) { m_nrvoFix
= flag
; }
318 bool getNRVOFix() const { return m_nrvoFix
; }
320 /* Indicates if a function may need to use a VarEnv or varargs (aka
321 * extraArgs) at run time */
322 bool mayUseVV() const;
325 * Whether this function matches the specified one with same number of
326 * parameters and types and defaults, so to qualify for perfect virtuals.
328 bool matchParams(FunctionScopePtr func
);
331 * What is the inferred type of this function's parameter at specified
332 * index. Returns number of extra arguments to put into ArgumentArray.
334 int inferParamTypes(AnalysisResultPtr ar
, ConstructPtr exp
,
335 ExpressionListPtr params
, bool &valid
);
337 TypePtr
setParamType(AnalysisResultConstPtr ar
, int index
, TypePtr type
);
338 TypePtr
getParamType(int index
);
339 TypePtr
getParamTypeSpec(int index
) { return m_paramTypeSpecs
[index
]; }
341 typedef hphp_hash_map
<std::string
, ExpressionPtr
, string_hashi
,
342 string_eqstri
> UserAttributeMap
;
344 UserAttributeMap
& userAttributes() { return m_userAttributes
;}
346 std::vector
<std::string
> getUserAttributeStringParams(const std::string
& key
);
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 {
362 void setMagicMethod() {
363 m_magicMethod
= true;
365 bool isMagicMethod() const {
366 return m_magicMethod
;
369 void setStmtCloned(StatementPtr 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 void addCaller(BlockScopePtr caller
, bool careAboutReturn
= true);
385 void addNewObjCaller(BlockScopePtr caller
);
387 ReadWriteMutex
&getInlineMutex() { return m_inlineMutex
; }
389 DECLARE_EXTENDED_BOOST_TYPES(FunctionInfo
);
391 static void RecordFunctionInfo(std::string fname
, FunctionScopePtr func
);
393 static FunctionInfoPtr
GetFunctionInfo(std::string fname
);
397 explicit FunctionInfo(int rva
= -1)
398 : m_maybeStatic(false)
399 , m_maybeRefReturn(false)
403 bool isRefParam(int p
) const {
404 if (m_refVarArg
>= 0 && p
>= m_refVarArg
) return true;
405 return (m_refParams
.find(p
) != m_refParams
.end());
408 void setRefVarArg(int rva
) {
409 if (rva
> m_refVarArg
) m_refVarArg
= rva
;
412 void setRefParam(int p
) {
413 m_refParams
.insert(p
);
416 void setMaybeStatic() { m_maybeStatic
= true; }
417 bool getMaybeStatic() { return m_maybeStatic
; }
419 void setMaybeRefReturn() { m_maybeRefReturn
= true; }
420 bool getMaybeRefReturn() { return m_maybeRefReturn
; }
423 bool m_maybeStatic
; // this could be a static method
424 bool m_maybeRefReturn
;
425 int m_refVarArg
; // -1: no ref varargs;
426 // otherwise, any arg >= m_refVarArg is a reference
427 std::set
<int> m_refParams
; // set of ref arg positions
431 void init(AnalysisResultConstPtr ar
);
433 static StringToFunctionInfoPtrMap s_refParamInfo
;
438 std::vector
<std::string
> m_paramNames
;
439 TypePtrVec m_paramTypes
;
440 TypePtrVec m_paramTypeSpecs
;
441 std::vector
<std::string
> m_paramDefaults
;
442 std::vector
<std::string
> m_paramDefaultTexts
;
443 std::vector
<bool> m_refs
;
444 TypePtr m_returnType
;
445 TypePtr m_prevReturn
;
446 ModifierExpressionPtr m_modifiers
;
447 UserAttributeMap m_userAttributes
;
449 unsigned m_hasVoid
: 1;
450 unsigned m_method
: 1;
451 unsigned m_refReturn
: 1; // whether it's "function &get_reference()"
452 unsigned m_virtual
: 1;
453 unsigned m_hasOverride
: 1;
454 unsigned m_perfectVirtual
: 1;
455 unsigned m_dynamic
: 1;
456 unsigned m_dynamicInvoke
: 1;
457 unsigned m_overriding
: 1; // overriding a virtual function
458 unsigned m_volatile
: 1; // for function_exists
459 unsigned m_persistent
: 1;
460 unsigned m_pseudoMain
: 1;
461 unsigned m_magicMethod
: 1;
462 unsigned m_system
: 1;
463 unsigned m_inlineable
: 1;
464 unsigned m_containsThis
: 1; // contains a usage of $this?
465 unsigned m_containsBareThis
: 2; // $this outside object-context,
466 // 2 if in reference context
467 unsigned m_nrvoFix
: 1;
468 unsigned m_inlineAsExpr
: 1;
469 unsigned m_inlineSameContext
: 1;
470 unsigned m_contextSensitive
: 1;
471 unsigned m_directInvoke
: 1;
472 unsigned m_generator
: 1;
473 unsigned m_async
: 1;
474 unsigned m_noLSB
: 1;
475 unsigned m_nextLSB
: 1;
476 unsigned m_hasTry
: 1;
477 unsigned m_hasGoto
: 1;
478 unsigned m_localRedeclaring
: 1;
480 int m_redeclaring
; // multiple definition of the same function
481 StatementPtr m_stmtCloned
; // cloned method body stmt
483 FunctionOptPtr m_optFunction
;
484 ExpressionPtrVec m_retExprsToFix
;
485 ExpressionListPtr m_closureVars
;
486 ExpressionListPtr m_closureValues
;
487 ReadWriteMutex m_inlineMutex
;
488 unsigned m_nextID
; // used when cloning generators for traits
489 std::list
<FunctionScopeRawPtr
> m_clonedTraitOuterScope
;
492 ///////////////////////////////////////////////////////////////////////////////
494 #endif // incl_HPHP_FUNCTION_SCOPE_H_