aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-09-14 20:51:14 +0800
committerAlex Beregszaszi <alex@rtfs.hu>2017-09-16 19:31:13 +0800
commit06965458080dcaff6a8c486acc500b64b26a078f (patch)
treed9d6d913ab3b3d3b9b2dc150a82a4f1bbfc5fdf4 /libsolidity
parentb687d74c47c5814ce159bf16a2da2158c1a15879 (diff)
downloaddexon-solidity-06965458080dcaff6a8c486acc500b64b26a078f.tar.gz
dexon-solidity-06965458080dcaff6a8c486acc500b64b26a078f.tar.zst
dexon-solidity-06965458080dcaff6a8c486acc500b64b26a078f.zip
Check for interface types of members and cache recursion check.
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/ast/Types.cpp65
-rw-r--r--libsolidity/ast/Types.h4
2 files changed, 48 insertions, 21 deletions
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index c7843b90..83a5b465 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -1788,14 +1788,33 @@ MemberList::MemberMap StructType::nativeMembers(ContractDefinition const*) const
TypePointer StructType::interfaceType(bool _inLibrary) const
{
+ if (!canBeUsedExternally(_inLibrary))
+ return TypePointer();
+
+ // Has to fulfill canBeUsedExternally(_inLibrary) == !!interfaceType(_inLibrary)
if (_inLibrary && location() == DataLocation::Storage)
return shared_from_this();
- else if (!recursive())
- // TODO this might not be enough, we have to convert all members to
- // their interfaceType
+ else
return copyForLocation(DataLocation::Memory, true);
+}
+
+bool StructType::canBeUsedExternally(bool _inLibrary) const
+{
+ if (_inLibrary && location() == DataLocation::Storage)
+ return true;
+ else if (recursive())
+ return false;
else
- return TypePointer();
+ {
+ // Check that all members have interface types.
+ // We pass "false" to canBeUsedExternally (_inLibrary), because this struct will be
+ // passed by value and thus the encoding does not differ, but it will disallow
+ // mappings.
+ for (auto const& var: m_struct.members())
+ if (!var->annotation().type->canBeUsedExternally(false))
+ return false;
+ }
+ return true;
}
TypePointer StructType::copyForLocation(DataLocation _location, bool _isPointer) const
@@ -1887,25 +1906,29 @@ set<string> StructType::membersMissingInMemory() const
bool StructType::recursive() const
{
- set<StructDefinition const*> structsSeen;
- function<bool(StructType const*)> check = [&](StructType const* t) -> bool
+ if (!m_recursive.is_initialized())
{
- StructDefinition const* str = &t->structDefinition();
- if (structsSeen.count(str))
- return true;
- structsSeen.insert(str);
- for (ASTPointer<VariableDeclaration> const& variable: str->members())
+ set<StructDefinition const*> structsSeen;
+ function<bool(StructType const*)> check = [&](StructType const* t) -> bool
{
- Type const* memberType = variable->annotation().type.get();
- while (dynamic_cast<ArrayType const*>(memberType))
- memberType = dynamic_cast<ArrayType const*>(memberType)->baseType().get();
- if (StructType const* innerStruct = dynamic_cast<StructType const*>(memberType))
- if (check(innerStruct))
- return true;
- }
- return false;
- };
- return check(this);
+ StructDefinition const* str = &t->structDefinition();
+ if (structsSeen.count(str))
+ return true;
+ structsSeen.insert(str);
+ for (ASTPointer<VariableDeclaration> const& variable: str->members())
+ {
+ Type const* memberType = variable->annotation().type.get();
+ while (dynamic_cast<ArrayType const*>(memberType))
+ memberType = dynamic_cast<ArrayType const*>(memberType)->baseType().get();
+ if (StructType const* innerStruct = dynamic_cast<StructType const*>(memberType))
+ if (check(innerStruct))
+ return true;
+ }
+ return false;
+ };
+ m_recursive = check(this);
+ }
+ return *m_recursive;
}
TypePointer EnumType::unaryOperatorResult(Token::Value _operator) const
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index cb439693..8ba55521 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -32,6 +32,7 @@
#include <boost/noncopyable.hpp>
#include <boost/rational.hpp>
+#include <boost/optional.hpp>
#include <memory>
#include <string>
@@ -748,6 +749,7 @@ public:
return location() == DataLocation::Storage ? std::make_shared<IntegerType>(256) : shared_from_this();
}
virtual TypePointer interfaceType(bool _inLibrary) const override;
+ virtual bool canBeUsedExternally(bool _inLibrary) const override;
TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override;
@@ -774,6 +776,8 @@ public:
private:
StructDefinition const& m_struct;
+ /// Cache for the recursive() function.
+ mutable boost::optional<bool> m_recursive;
};
/**