Update the MSVC compiler options
[hiphop-php.git] / hphp / compiler / analysis / function_scope.h
blobaf468a9a53e59d5bb5ac567e84f0c4c0b05abe83
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2015 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"
21 #include <list>
22 #include <set>
23 #include <utility>
24 #include <vector>
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"
32 namespace HPHP {
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);
47 class CodeGenerator;
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;
59 /**
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 {
66 public:
67 /**
68 * User defined functions.
70 FunctionScope(AnalysisResultConstPtr ar, bool method,
71 const std::string &originalName, StatementPtr stmt,
72 bool reference, int minParam, int maxParam,
73 ModifierExpressionPtr modifiers, int attribute,
74 const std::string &docComment,
75 FileScopePtr file,
76 const std::vector<UserAttributePtr> &attrs,
77 bool inPseudoMain = false);
79 FunctionScope(FunctionScopePtr orig, AnalysisResultConstPtr ar,
80 const std::string &originalName,
81 StatementPtr stmt, ModifierExpressionPtr modifiers, bool user);
83 /**
84 * System functions.
86 FunctionScope(bool method, const std::string &name, bool reference);
87 void setParamCounts(AnalysisResultConstPtr ar,
88 int minParam, int numDeclParam);
89 void setParamName(int index, const std::string &name);
90 void setRefParam(int index);
91 bool hasRefParam(int max) const;
93 void addModifier(int mod);
95 bool hasUserAttr(const char *attr) const;
97 /**
98 * What kind of function this is.
100 bool isUserFunction() const { return !m_system && !isNative(); }
101 bool isSystem() const { return m_system; }
102 bool isPublic() const;
103 bool isProtected() const;
104 bool isPrivate() const;
105 bool isStatic() const;
106 bool isAbstract() const;
107 bool isNative() const;
108 bool isFinal() const;
109 bool isMagic() const;
110 bool isBuiltin() const override { return !getStmt() || isNative(); }
111 bool isRefParam(int index) const;
112 bool isRefReturn() const { return m_refReturn;}
113 bool isDynamicInvoke() const { return m_dynamicInvoke; }
114 void setDynamicInvoke();
115 bool hasImpl() const;
116 bool isParamCoerceMode() const;
117 bool mayContainThis();
118 bool isClosure() const;
119 bool isGenerator() const { return m_generator; }
120 void setGenerator(bool f) { m_generator = f; }
121 bool isAsync() const { return m_async; }
122 void setAsync(bool f) { m_async = f; }
124 int nextInlineIndex() { return ++m_inlineIndex; }
126 bool usesLSB() const { return !m_noLSB; }
127 void clearUsesLSB() { m_noLSB = true; }
128 bool nextLSB() const { return m_nextLSB; }
129 void setNextLSB(bool f) { m_nextLSB = f; }
131 void setHasGoto() { m_hasGoto = true; }
132 void setHasTry() { m_hasTry = true; }
133 bool hasGoto() const { return m_hasGoto; }
134 bool hasTry() const { return m_hasTry; }
135 unsigned getNewID() { return m_nextID++; }
137 bool needsLocalThis() const;
139 bool isNamed(const char* n) const;
140 bool isNamed(const std::string& n) const {
141 return isNamed(n.c_str());
145 * Either __construct or a class-name constructor.
147 bool isConstructor(ClassScopePtr cls) const;
149 const std::string &getParamName(int index) const;
151 // const std::string &name() const {
152 // return getName();
153 // }
155 int getRedeclaringId() const {
156 return m_redeclaring;
159 void setSystem() {
160 m_system = true;
161 m_volatile = false;
165 * Tell this function about another outer scope that contains it.
167 void addClonedTraitOuterScope(FunctionScopePtr scope) {
168 m_clonedTraitOuterScope.push_back(scope);
172 * Get/set original name of the function, without case being lowered.
174 const std::string &getOriginalName() const;
175 void setOriginalName(const std::string &name) { m_scopeName = name; }
177 std::string getDocName() const;
178 std::string getDocFullName() const;
181 * If class method, returns class::name, otherwise just name.
183 std::string getOriginalFullName() const;
186 * Whether this function can take variable number of arguments.
188 bool allowsVariableArguments() const;
189 bool hasVariadicParam() const;
190 bool usesVariableArgumentFunc() const;
191 bool isReferenceVariableArgument() const;
192 void setVariableArgument(int reference);
195 * Whether this function has no side effects
197 bool hasEffect() const;
198 void setNoEffect();
201 * Whether this function can be constant folded
203 bool isFoldable() const;
204 void setIsFoldable();
207 * If this is a builtin function and does not need an ActRec
209 bool noFCallBuiltin() const;
210 void setNoFCallBuiltin();
213 * If this is a builtin (C++ or PHP) and can be redefined
215 bool allowOverride() const;
216 void setAllowOverride();
218 bool needsFinallyLocals() const;
221 * Whether this function is a runtime helper function
223 void setHelperFunction();
226 * Whether this function returns reference or has reference parameters.
228 bool containsReference() const;
231 * Whether this function contains a usage of $this
233 bool containsThis() const { return m_containsThis;}
234 void setContainsThis(bool f = true);
235 bool containsBareThis() const { return m_containsBareThis; }
236 bool containsRefThis() const { return m_containsBareThis & 2; }
237 void setContainsBareThis(bool f, bool ref = false);
239 * How many parameters a caller should provide.
241 int getMinParamCount() const { return m_minParam; }
242 int getDeclParamCount() const { return m_numDeclParams; }
243 int getMaxParamCount() const {
244 return hasVariadicParam() ? (m_numDeclParams-1) : m_numDeclParams;
246 int getOptionalParamCount() const { return getMaxParamCount() - m_minParam;}
248 void setOptFunction(FunctionOptPtr fn) { m_optFunction = fn; }
249 FunctionOptPtr getOptFunction() const { return m_optFunction; }
252 * Whether this is a virtual function that needs dynamic dispatch
254 void setVirtual() { m_virtual = true;}
255 bool isVirtual() const { return m_virtual;}
256 void setHasOverride() { m_hasOverride = true; }
257 bool hasOverride() const { return m_hasOverride; }
260 * Whether same function name was declared twice or more.
262 void setRedeclaring(int redecId) {
263 m_redeclaring = redecId;
264 setVolatile(); // redeclared function is also volatile
266 bool isRedeclaring() const { return m_redeclaring >= 0;}
268 void setLocalRedeclaring() { m_localRedeclaring = true; }
269 bool isLocalRedeclaring() const { return m_localRedeclaring; }
271 /* For function_exists */
272 void setVolatile() { m_volatile = true; }
273 bool isVolatile() const { return m_volatile; }
274 bool isPersistent() const { return m_persistent; }
275 void setPersistent(bool p) { m_persistent = p; }
277 /* Indicates if a function may need to use a VarEnv or varargs (aka
278 * extraArgs) at run time */
279 bool mayUseVV() const;
281 typedef hphp_hash_map<std::string, ExpressionPtr, string_hashi,
282 string_eqstri> UserAttributeMap;
284 UserAttributeMap& userAttributes() { return m_userAttributes;}
286 std::vector<std::string> getUserAttributeStringParams(const std::string& key);
289 * Override BlockScope::outputPHP() to generate return type.
291 void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) override;
293 * Serialize the iface, not everything.
295 void serialize(JSON::CodeError::OutputStream &out) const override;
296 void serialize(JSON::DocTarget::OutputStream &out) const override;
298 bool inPseudoMain() const override {
299 return m_pseudoMain;
302 void setClosureVars(ExpressionListPtr closureVars) {
303 m_closureVars = closureVars;
306 ExpressionListPtr getClosureVars() const {
307 return m_closureVars;
310 void getClosureUseVars(ParameterExpressionPtrIdxPairVec &useVars,
311 bool filterUsed = true);
313 void addCaller(BlockScopePtr caller, bool careAboutReturn = true);
314 void addNewObjCaller(BlockScopePtr caller);
316 class FunctionInfo {
317 public:
318 explicit FunctionInfo(int rva = -1)
319 : m_maybeStatic(false)
321 * Note: m_maybeRefReturn used to implement an optimization to
322 * avoid unbox checks when we call functions where we know no
323 * function with that name returns by reference. This isn't
324 * correct, however, because __call can return by reference, so
325 * it's disabled here. (The default to enable it should be
326 * 'false'.)
328 , m_maybeRefReturn(true)
329 , m_refVarArg(rva)
332 bool isRefParam(int p) const {
333 if (m_refVarArg >= 0 && p >= m_refVarArg) return true;
334 return (m_refParams.find(p) != m_refParams.end());
337 void setRefVarArg(int rva) {
338 if (rva > m_refVarArg) m_refVarArg = rva;
341 void setRefParam(int p) {
342 m_refParams.insert(p);
345 void setMaybeStatic() { m_maybeStatic = true; }
346 bool getMaybeStatic() { return m_maybeStatic; }
348 void setMaybeRefReturn() { m_maybeRefReturn = true; }
349 bool getMaybeRefReturn() { return m_maybeRefReturn; }
351 private:
352 bool m_maybeStatic; // this could be a static method
353 bool m_maybeRefReturn;
354 int m_refVarArg; // -1: no ref varargs;
355 // otherwise, any arg >= m_refVarArg is a reference
356 std::set<int> m_refParams; // set of ref arg positions
359 using FunctionInfoPtr = std::shared_ptr<FunctionInfo>;
360 using StringToFunctionInfoPtrMap = hphp_string_imap<FunctionInfoPtr>;
361 static void RecordFunctionInfo(std::string fname, FunctionScopePtr func);
362 static FunctionInfoPtr GetFunctionInfo(const std::string& fname);
364 private:
365 void init(AnalysisResultConstPtr ar);
367 static StringToFunctionInfoPtrMap s_refParamInfo;
369 int m_minParam;
370 int m_numDeclParams;
371 int m_attribute;
372 std::vector<std::string> m_paramNames;
373 std::vector<bool> m_refs;
374 ModifierExpressionPtr m_modifiers;
375 UserAttributeMap m_userAttributes;
377 unsigned m_hasVoid : 1;
378 unsigned m_method : 1;
379 unsigned m_refReturn : 1; // whether it's "function &get_reference()"
380 unsigned m_virtual : 1;
381 unsigned m_hasOverride : 1;
382 unsigned m_dynamicInvoke : 1;
383 unsigned m_volatile : 1; // for function_exists
384 unsigned m_persistent : 1;
385 unsigned m_pseudoMain : 1;
386 unsigned m_system : 1;
387 unsigned m_containsThis : 1; // contains a usage of $this?
388 unsigned m_containsBareThis : 2; // $this outside object-context,
389 // 2 if in reference context
390 unsigned m_generator : 1;
391 unsigned m_async : 1;
392 unsigned m_noLSB : 1;
393 unsigned m_nextLSB : 1;
394 unsigned m_hasTry : 1;
395 unsigned m_hasGoto : 1;
396 unsigned m_localRedeclaring : 1;
398 int m_redeclaring; // multiple definition of the same function
399 int m_inlineIndex;
400 FunctionOptPtr m_optFunction;
401 ExpressionListPtr m_closureVars;
402 ExpressionListPtr m_closureValues;
403 unsigned m_nextID; // used when cloning generators for traits
404 std::list<FunctionScopeRawPtr> m_clonedTraitOuterScope;
407 ///////////////////////////////////////////////////////////////////////////////
409 #endif // incl_HPHP_FUNCTION_SCOPE_H_