aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/ast
diff options
context:
space:
mode:
authorChase McDermott <chasemcd1745@tamu.edu>2018-08-07 21:58:34 +0800
committerchriseth <chris@ethereum.org>2018-08-15 00:07:15 +0800
commit683bce18690cc2790b68289278a5d84995472fda (patch)
tree18188cf8f612e9178e68c858c541b7444c263287 /libsolidity/ast
parentcc2dcf5c312bbc8cd7ad5e2b4dfbdb084f77fe03 (diff)
downloaddexon-solidity-683bce18690cc2790b68289278a5d84995472fda.tar.gz
dexon-solidity-683bce18690cc2790b68289278a5d84995472fda.tar.zst
dexon-solidity-683bce18690cc2790b68289278a5d84995472fda.zip
Refactor data location check.
Diffstat (limited to 'libsolidity/ast')
-rw-r--r--libsolidity/ast/AST.cpp121
-rw-r--r--libsolidity/ast/AST.h16
2 files changed, 118 insertions, 19 deletions
diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp
index 23797d52..a376e55d 100644
--- a/libsolidity/ast/AST.cpp
+++ b/libsolidity/ast/AST.cpp
@@ -418,6 +418,7 @@ bool VariableDeclaration::isLocalVariable() const
{
auto s = scope();
return
+ dynamic_cast<FunctionTypeName const*>(s) ||
dynamic_cast<CallableDeclaration const*>(s) ||
dynamic_cast<Block const*>(s) ||
dynamic_cast<ForStatement const*>(s);
@@ -425,14 +426,18 @@ bool VariableDeclaration::isLocalVariable() const
bool VariableDeclaration::isCallableParameter() const
{
- auto const* callable = dynamic_cast<CallableDeclaration const*>(scope());
- if (!callable)
- return false;
- for (auto const& variable: callable->parameters())
- if (variable.get() == this)
- return true;
- if (callable->returnParameterList())
- for (auto const& variable: callable->returnParameterList()->parameters())
+ if (isReturnParameter())
+ return true;
+
+ vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
+
+ if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
+ parameters = &funTypeName->parameterTypes();
+ else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
+ parameters = &callable->parameters();
+
+ if (parameters)
+ for (auto const& variable: *parameters)
if (variable.get() == this)
return true;
return false;
@@ -445,11 +450,16 @@ bool VariableDeclaration::isLocalOrReturn() const
bool VariableDeclaration::isReturnParameter() const
{
- auto const* callable = dynamic_cast<CallableDeclaration const*>(scope());
- if (!callable)
- return false;
- if (callable->returnParameterList())
- for (auto const& variable: callable->returnParameterList()->parameters())
+ vector<ASTPointer<VariableDeclaration>> const* returnParameters = nullptr;
+
+ if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
+ returnParameters = &funTypeName->returnParameterTypes();
+ else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
+ if (callable->returnParameterList())
+ returnParameters = &callable->returnParameterList()->parameters();
+
+ if (returnParameters)
+ for (auto const& variable: *returnParameters)
if (variable.get() == this)
return true;
return false;
@@ -457,15 +467,88 @@ bool VariableDeclaration::isReturnParameter() const
bool VariableDeclaration::isExternalCallableParameter() const
{
- auto const* callable = dynamic_cast<CallableDeclaration const*>(scope());
- if (!callable || callable->visibility() != Declaration::Visibility::External)
+ if (!isCallableParameter())
return false;
- for (auto const& variable: callable->parameters())
- if (variable.get() == this)
- return true;
+
+ if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
+ if (callable->visibility() == Declaration::Visibility::External)
+ return !isReturnParameter();
+
return false;
}
+bool VariableDeclaration::isInternalCallableParameter() const
+{
+ if (!isCallableParameter())
+ return false;
+
+ if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
+ return funTypeName->visibility() == Declaration::Visibility::Internal;
+ else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
+ return callable->visibility() <= Declaration::Visibility::Internal;
+ return false;
+}
+
+bool VariableDeclaration::isLibraryFunctionParameter() const
+{
+ if (!isCallableParameter())
+ return false;
+ if (auto const* funDef = dynamic_cast<FunctionDefinition const*>(scope()))
+ return dynamic_cast<ContractDefinition const&>(*funDef->scope()).isLibrary();
+ else
+ return false;
+}
+
+bool VariableDeclaration::isEventParameter() const
+{
+ return dynamic_cast<EventDefinition const*>(scope()) != nullptr;
+}
+
+bool VariableDeclaration::hasReferenceOrMappingType() const
+{
+ solAssert(typeName(), "");
+ solAssert(typeName()->annotation().type, "Can only be called after reference resolution");
+ TypePointer const& type = typeName()->annotation().type;
+ return type->category() == Type::Category::Mapping || dynamic_cast<ReferenceType const*>(type.get());
+}
+
+set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() const
+{
+ using Location = VariableDeclaration::Location;
+
+ if (!hasReferenceOrMappingType() || isStateVariable() || isEventParameter())
+ return set<Location>{ Location::Default };
+ else if (isStateVariable() && isConstant())
+ return set<Location>{ Location::Memory };
+ else if (isExternalCallableParameter())
+ {
+ set<Location> locations{ Location::CallData };
+ if (isLibraryFunctionParameter())
+ locations.insert(Location::Storage);
+ return locations;
+ }
+ else if (isCallableParameter())
+ {
+ set<Location> locations{ Location::Memory };
+ if (isInternalCallableParameter() || isLibraryFunctionParameter())
+ locations.insert(Location::Storage);
+ return locations;
+ }
+ else if (isLocalVariable())
+ {
+ solAssert(typeName(), "");
+ solAssert(typeName()->annotation().type, "Can only be called after reference resolution");
+ if (typeName()->annotation().type->category() == Type::Category::Mapping)
+ return set<Location>{ Location::Storage };
+ else
+ // TODO: add Location::Calldata once implemented for local variables.
+ return set<Location>{ Location::Memory, Location::Storage };
+ }
+ else
+ // Struct members etc.
+ return set<Location>{ Location::Default };
+}
+
TypePointer VariableDeclaration::type() const
{
return annotation().type;
@@ -580,7 +663,7 @@ bool Literal::passesAddressChecksum() const
return dev::passesAddressChecksum(value(), true);
}
-std::string Literal::getChecksummedAddress() const
+string Literal::getChecksummedAddress() const
{
solAssert(isHexNumber(), "Expected hex number");
/// Pad literal to be a proper hex address.
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index 69c6fa05..b953211d 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -685,6 +685,8 @@ public:
virtual bool isLValue() const override;
virtual bool isPartOfExternalInterface() const override { return isPublic(); }
+ /// @returns true iff this variable is the parameter (or return parameter) of a function
+ /// (or function type name or event) or declared inside a function body.
bool isLocalVariable() const;
/// @returns true if this variable is a parameter or return parameter of a function.
bool isCallableParameter() const;
@@ -693,13 +695,27 @@ public:
/// @returns true if this variable is a local variable or return parameter.
bool isLocalOrReturn() const;
/// @returns true if this variable is a parameter (not return parameter) of an external function.
+ /// This excludes parameters of external function type names.
bool isExternalCallableParameter() const;
+ /// @returns true if this variable is a parameter or return parameter of an internal function
+ /// or a function type of internal visibility.
+ bool isInternalCallableParameter() const;
+ /// @returns true iff this variable is a parameter(or return parameter of a library function
+ bool isLibraryFunctionParameter() const;
/// @returns true if the type of the variable does not need to be specified, i.e. it is declared
/// in the body of a function or modifier.
+ /// @returns true if this variable is a parameter of an event.
+ bool isEventParameter() const;
+ /// @returns true if the type of the variable is a reference or mapping type, i.e.
+ /// array, struct or mapping. These types can take a data location (and often require it).
+ /// Can only be called after reference resolution.
+ bool hasReferenceOrMappingType() const;
bool isStateVariable() const { return m_isStateVariable; }
bool isIndexed() const { return m_isIndexed; }
bool isConstant() const { return m_isConstant; }
Location referenceLocation() const { return m_location; }
+ /// @returns a set of allowed storage locations for the variable.
+ std::set<Location> allowedDataLocations() const;
virtual TypePointer type() const override;