aboutsummaryrefslogtreecommitdiffstats
path: root/AST.h
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2015-01-22 08:02:38 +0800
committerChristian <c@ethdev.com>2015-01-26 17:23:39 +0800
commit941c77c8fadd6195809cd2d572feb64478c4fb20 (patch)
treea4de3710aff5f3f2d9423565fd0e9ecc8708b5bf /AST.h
parent19793dab093ae36b5f2b4d1cabfbf54bed3125b1 (diff)
downloaddexon-solidity-941c77c8fadd6195809cd2d572feb64478c4fb20.tar.gz
dexon-solidity-941c77c8fadd6195809cd2d572feb64478c4fb20.tar.zst
dexon-solidity-941c77c8fadd6195809cd2d572feb64478c4fb20.zip
Type resolution for function modifiers.
Diffstat (limited to 'AST.h')
-rwxr-xr-xAST.h84
1 files changed, 67 insertions, 17 deletions
diff --git a/AST.h b/AST.h
index e48e45d3..ded30e9c 100755
--- a/AST.h
+++ b/AST.h
@@ -132,6 +132,8 @@ private:
class Declaration: public ASTNode
{
public:
+ enum class LValueType { NONE, LOCAL, STORAGE };
+
Declaration(Location const& _location, ASTPointer<ASTString> const& _name):
ASTNode(_location), m_name(_name), m_scope(nullptr) {}
@@ -142,6 +144,13 @@ public:
Declaration const* getScope() const { return m_scope; }
void setScope(Declaration const* _scope) { m_scope = _scope; }
+ /// @returns the type of expressions referencing this declaration.
+ /// The current contract has to be given since this context can change the type, especially of
+ /// contract types.
+ virtual TypePointer getType(ContractDefinition const* m_currentContract = nullptr) const = 0;
+ /// @returns the lvalue type of expressions referencing this declaration
+ virtual LValueType getLValueType() const { return LValueType::NONE; }
+
private:
ASTPointer<ASTString> m_name;
Declaration const* m_scope;
@@ -178,8 +187,11 @@ public:
std::vector<ASTPointer<InheritanceSpecifier>> const& getBaseContracts() const { return m_baseContracts; }
std::vector<ASTPointer<StructDefinition>> const& getDefinedStructs() const { return m_definedStructs; }
std::vector<ASTPointer<VariableDeclaration>> const& getStateVariables() const { return m_stateVariables; }
+ std::vector<ASTPointer<ModifierDefinition>> const& getFunctionModifiers() const { return m_functionModifiers; }
std::vector<ASTPointer<FunctionDefinition>> const& getDefinedFunctions() const { return m_definedFunctions; }
+ virtual TypePointer getType(ContractDefinition const* m_currentContract) const override;
+
/// Checks that there are no illegal overrides, that the constructor does not have a "returns"
/// and calls checkTypeRequirements on all its functions.
void checkTypeRequirements();
@@ -248,6 +260,8 @@ public:
std::vector<ASTPointer<VariableDeclaration>> const& getMembers() const { return m_members; }
+ virtual TypePointer getType(ContractDefinition const*) const override;
+
/// Checks that the members do not include any recursive structs and have valid types
/// (e.g. no functions).
void checkValidityOfMembers() const;
@@ -279,7 +293,20 @@ private:
std::vector<ASTPointer<VariableDeclaration>> m_parameters;
};
-class FunctionDefinition: public Declaration
+/**
+ * Abstract class that is added to each AST node that can store local variables.
+ */
+class VariableScope
+{
+public:
+ void addLocalVariable(VariableDeclaration const& _localVariable) { m_localVariables.push_back(&_localVariable); }
+ std::vector<VariableDeclaration const*> const& getLocalVariables() const { return m_localVariables; }
+
+private:
+ std::vector<VariableDeclaration const*> m_localVariables;
+};
+
+class FunctionDefinition: public Declaration, public VariableScope
{
public:
FunctionDefinition(Location const& _location, ASTPointer<ASTString> const& _name,
@@ -288,11 +315,13 @@ public:
ASTPointer<ASTString> const& _documentation,
ASTPointer<ParameterList> const& _parameters,
bool _isDeclaredConst,
+ std::vector<ASTPointer<ModifierInvocation>> const& _modifiers,
ASTPointer<ParameterList> const& _returnParameters,
ASTPointer<Block> const& _body):
Declaration(_location, _name), m_isPublic(_isPublic), m_isConstructor(_isConstructor),
m_parameters(_parameters),
m_isDeclaredConst(_isDeclaredConst),
+ m_functionModifiers(_modifiers),
m_returnParameters(_returnParameters),
m_body(_body),
m_documentation(_documentation)
@@ -304,6 +333,7 @@ public:
bool isPublic() const { return m_isPublic; }
bool isConstructor() const { return m_isConstructor; }
bool isDeclaredConst() const { return m_isDeclaredConst; }
+ std::vector<ASTPointer<ModifierInvocation>> const& getModifiers() const { return m_functionModifiers; }
std::vector<ASTPointer<VariableDeclaration>> const& getParameters() const { return m_parameters->getParameters(); }
ParameterList const& getParameterList() const { return *m_parameters; }
std::vector<ASTPointer<VariableDeclaration>> const& getReturnParameters() const { return m_returnParameters->getParameters(); }
@@ -313,8 +343,7 @@ public:
/// Can contain a nullptr in which case indicates absence of documentation
ASTPointer<ASTString> const& getDocumentation() const { return m_documentation; }
- void addLocalVariable(VariableDeclaration const& _localVariable) { m_localVariables.push_back(&_localVariable); }
- std::vector<VariableDeclaration const*> const& getLocalVariables() const { return m_localVariables; }
+ virtual TypePointer getType(ContractDefinition const*) const override;
/// Checks that all parameters have allowed types and calls checkTypeRequirements on the body.
void checkTypeRequirements();
@@ -329,11 +358,10 @@ private:
bool m_isConstructor;
ASTPointer<ParameterList> m_parameters;
bool m_isDeclaredConst;
+ std::vector<ASTPointer<ModifierInvocation>> m_functionModifiers;
ASTPointer<ParameterList> m_returnParameters;
ASTPointer<Block> m_body;
ASTPointer<ASTString> m_documentation;
-
- std::vector<VariableDeclaration const*> m_localVariables;
};
/**
@@ -353,10 +381,10 @@ public:
/// Returns the declared or inferred type. Can be an empty pointer if no type was explicitly
/// declared and there is no assignment to the variable that fixes the type.
- std::shared_ptr<Type const> const& getType() const { return m_type; }
+ TypePointer getType(ContractDefinition const* = nullptr) const { return m_type; }
void setType(std::shared_ptr<Type const> const& _type) { m_type = _type; }
- bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); }
+ virtual LValueType getLValueType() const override;
private:
ASTPointer<TypeName> m_typeName; ///< can be empty ("var")
@@ -367,7 +395,7 @@ private:
/**
* Definition of a function modifier.
*/
-class ModifierDefinition: public Declaration
+class ModifierDefinition: public Declaration, public VariableScope
{
public:
ModifierDefinition(Location const& _location,
@@ -385,6 +413,8 @@ public:
ParameterList const& getParameterList() const { return *m_parameters; }
Block const& getBody() const { return *m_body; }
+ virtual TypePointer getType(ContractDefinition const* = nullptr) const override;
+
/// @return A shared pointer of an ASTString.
/// Can contain a nullptr in which case indicates absence of documentation
ASTPointer<ASTString> const& getDocumentation() const { return m_documentation; }
@@ -398,6 +428,29 @@ private:
};
/**
+ * Invocation/usage of a modifier in a function header.
+ */
+class ModifierInvocation: public ASTNode
+{
+public:
+ ModifierInvocation(Location const& _location, ASTPointer<Identifier> const& _name,
+ std::vector<ASTPointer<Expression>> _arguments):
+ ASTNode(_location), m_modifierName(_name), m_arguments(_arguments) {}
+
+ virtual void accept(ASTVisitor& _visitor) override;
+ virtual void accept(ASTConstVisitor& _visitor) const override;
+
+ ASTPointer<Identifier> const& getName() const { return m_modifierName; }
+ std::vector<ASTPointer<Expression>> const& getArguments() const { return m_arguments; }
+
+ void checkTypeRequirements();
+
+private:
+ ASTPointer<Identifier> m_modifierName;
+ std::vector<ASTPointer<Expression>> m_arguments;
+};
+
+/**
* Pseudo AST node that is used as declaration for "this", "msg", "tx", "block" and the global
* functions when such an identifier is encountered. Will never have a valid location in the source code.
*/
@@ -411,7 +464,7 @@ public:
virtual void accept(ASTConstVisitor&) const override { BOOST_THROW_EXCEPTION(InternalCompilerError()
<< errinfo_comment("MagicVariableDeclaration used inside real AST.")); }
- std::shared_ptr<Type const> const& getType() const { return m_type; }
+ virtual TypePointer getType(ContractDefinition const* = nullptr) const override { return m_type; }
private:
std::shared_ptr<Type const> m_type;
@@ -737,16 +790,13 @@ private:
*/
class Expression: public ASTNode
{
-protected:
- enum class LValueType { NONE, LOCAL, STORAGE };
-
public:
- Expression(Location const& _location): ASTNode(_location), m_lvalue(LValueType::NONE), m_lvalueRequested(false) {}
+ Expression(Location const& _location): ASTNode(_location) {}
virtual void checkTypeRequirements() = 0;
std::shared_ptr<Type const> const& getType() const { return m_type; }
- bool isLValue() const { return m_lvalue != LValueType::NONE; }
- bool isLocalLValue() const { return m_lvalue == LValueType::LOCAL; }
+ bool isLValue() const { return m_lvalue != Declaration::LValueType::NONE; }
+ bool isLocalLValue() const { return m_lvalue == Declaration::LValueType::LOCAL; }
/// Helper function, infer the type via @ref checkTypeRequirements and then check that it
/// is implicitly convertible to @a _expectedType. If not, throw exception.
@@ -763,9 +813,9 @@ protected:
std::shared_ptr<Type const> m_type;
//! If this expression is an lvalue (i.e. something that can be assigned to) and is stored
//! locally or in storage. This is set during calls to @a checkTypeRequirements()
- LValueType m_lvalue;
+ Declaration::LValueType m_lvalue = Declaration::LValueType::NONE;
//! Whether the outer expression requested the address (true) or the value (false) of this expression.
- bool m_lvalueRequested;
+ bool m_lvalueRequested = false;
};
/// Assignment, can also be a compound assignment.