diff options
author | chriseth <c@ethdev.com> | 2015-10-06 18:35:10 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-10-06 20:20:06 +0800 |
commit | bf5b387954f93371e2c8fc77c01cbc709f570954 (patch) | |
tree | 4796d5154b68cdb7ee91450348fcab8eedcc254f | |
parent | bc609c55c0fa622a68fa9718c55046416c201b1d (diff) | |
download | dexon-solidity-bf5b387954f93371e2c8fc77c01cbc709f570954.tar.gz dexon-solidity-bf5b387954f93371e2c8fc77c01cbc709f570954.tar.zst dexon-solidity-bf5b387954f93371e2c8fc77c01cbc709f570954.zip |
Provide access to scoped structs.
-rw-r--r-- | libsolidity/AST.h | 8 | ||||
-rw-r--r-- | libsolidity/ASTJsonConverter.cpp | 5 | ||||
-rw-r--r-- | libsolidity/ASTPrinter.cpp | 3 | ||||
-rw-r--r-- | libsolidity/NameAndTypeResolver.cpp | 16 | ||||
-rw-r--r-- | libsolidity/NameAndTypeResolver.h | 10 | ||||
-rw-r--r-- | libsolidity/Parser.cpp | 11 | ||||
-rw-r--r-- | libsolidity/ReferencesResolver.cpp | 13 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 27 |
8 files changed, 72 insertions, 21 deletions
diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 1d2babbe..075c1ff5 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -712,17 +712,17 @@ private: class UserDefinedTypeName: public TypeName { public: - UserDefinedTypeName(SourceLocation const& _location, ASTPointer<ASTString> const& _name): - TypeName(_location), m_name(_name) {} + UserDefinedTypeName(SourceLocation const& _location, std::vector<ASTString> const& _namePath): + TypeName(_location), m_namePath(_namePath) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; - ASTString const& name() const { return *m_name; } + std::vector<ASTString> const& namePath() const { return m_namePath; } virtual UserDefinedTypeNameAnnotation& annotation() const override; private: - ASTPointer<ASTString> m_name; + std::vector<ASTString> m_namePath; }; /** diff --git a/libsolidity/ASTJsonConverter.cpp b/libsolidity/ASTJsonConverter.cpp index d0f76fb8..4c14f2b2 100644 --- a/libsolidity/ASTJsonConverter.cpp +++ b/libsolidity/ASTJsonConverter.cpp @@ -21,6 +21,7 @@ */ #include <libsolidity/ASTJsonConverter.h> +#include <boost/algorithm/string/join.hpp> #include <libsolidity/AST.h> using namespace std; @@ -144,7 +145,9 @@ bool ASTJsonConverter::visit(ElementaryTypeName const& _node) bool ASTJsonConverter::visit(UserDefinedTypeName const& _node) { - addJsonNode("UserDefinedTypeName", { make_pair("name", _node.name()) }); + addJsonNode("UserDefinedTypeName", { + make_pair("name", boost::algorithm::join(_node.namePath(), ".")) + }); return true; } diff --git a/libsolidity/ASTPrinter.cpp b/libsolidity/ASTPrinter.cpp index cebf6b8b..534f7c78 100644 --- a/libsolidity/ASTPrinter.cpp +++ b/libsolidity/ASTPrinter.cpp @@ -21,6 +21,7 @@ */ #include <libsolidity/ASTPrinter.h> +#include <boost/algorithm/string/join.hpp> #include <libsolidity/AST.h> using namespace std; @@ -151,7 +152,7 @@ bool ASTPrinter::visit(ElementaryTypeName const& _node) bool ASTPrinter::visit(UserDefinedTypeName const& _node) { - writeLine("UserDefinedTypeName \"" + _node.name() + "\""); + writeLine("UserDefinedTypeName \"" + boost::algorithm::join(_node.namePath(), ".") + "\""); printSourcePart(_node); return goDeeper(); } diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index 6b9b9584..d9f74ae1 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -130,6 +130,22 @@ vector<Declaration const*> NameAndTypeResolver::nameFromCurrentScope(ASTString c return m_currentScope->resolveName(_name, _recursive); } +Declaration const* NameAndTypeResolver::pathFromCurrentScope(vector<ASTString> const& _path, bool _recursive) +{ + solAssert(!_path.empty(), ""); + vector<Declaration const*> candidates = m_currentScope->resolveName(_path.front(), _recursive); + for (size_t i = 1; i < _path.size() && candidates.size() == 1; i++) + { + if (!m_scopes.count(candidates.front())) + return nullptr; + candidates = m_scopes.at(candidates.front()).resolveName(_path[i], false); + } + if (candidates.size() == 1) + return candidates.front(); + else + return nullptr; +} + vector<Declaration const*> NameAndTypeResolver::cleanedDeclarations( Identifier const& _identifier, vector<Declaration const*> const& _declarations diff --git a/libsolidity/NameAndTypeResolver.h b/libsolidity/NameAndTypeResolver.h index 528930f7..8e817a7c 100644 --- a/libsolidity/NameAndTypeResolver.h +++ b/libsolidity/NameAndTypeResolver.h @@ -36,9 +36,8 @@ namespace solidity { /** - * Resolves name references, types and checks types of all expressions. - * Specifically, it checks that all operations are valid for the inferred types. - * An exception is throw on the first error. + * Resolves name references, typenames and sets the (explicitly given) types for all variable + * declarations. */ class NameAndTypeResolver: private boost::noncopyable { @@ -61,6 +60,11 @@ public: /// resolving phase. std::vector<Declaration const*> nameFromCurrentScope(ASTString const& _name, bool _recursive = true); + /// Resolves a path starting from the "current" scope. Should only be called during the initial + /// resolving phase. + /// @note Returns a null pointer if any component in the path was not unique or not found. + Declaration const* pathFromCurrentScope(std::vector<ASTString> const& _path, bool _recursive = true); + /// returns the vector of declarations without repetitions static std::vector<Declaration const*> cleanedDeclarations( Identifier const& _identifier, diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index f3b654ea..94e9c0ea 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -522,7 +522,14 @@ ASTPointer<TypeName> Parser::parseTypeName(bool _allowVar) { ASTNodeFactory nodeFactory(*this); nodeFactory.markEndPosition(); - type = nodeFactory.createNode<UserDefinedTypeName>(expectIdentifierToken()); + vector<ASTString> identifierPath{*expectIdentifierToken()}; + while (m_scanner->currentToken() == Token::Period) + { + m_scanner->next(); + nodeFactory.markEndPosition(); + identifierPath.push_back(*expectIdentifierToken()); + } + type = nodeFactory.createNode<UserDefinedTypeName>(identifierPath); } else BOOST_THROW_EXCEPTION(createParserError("Expected type name")); @@ -1036,7 +1043,7 @@ ASTPointer<TypeName> Parser::typeNameIndexAccessStructure( ASTNodeFactory nodeFactory(*this, _primary); ASTPointer<TypeName> type; if (auto identifier = dynamic_cast<Identifier const*>(_primary.get())) - type = nodeFactory.createNode<UserDefinedTypeName>(make_shared<ASTString>(identifier->name())); + type = nodeFactory.createNode<UserDefinedTypeName>(vector<ASTString>{identifier->name()}); else if (auto typeName = dynamic_cast<ElementaryTypeNameExpression const*>(_primary.get())) type = nodeFactory.createNode<ElementaryTypeName>(typeName->typeToken()); else diff --git a/libsolidity/ReferencesResolver.cpp b/libsolidity/ReferencesResolver.cpp index f60ca1af..32c1728f 100644 --- a/libsolidity/ReferencesResolver.cpp +++ b/libsolidity/ReferencesResolver.cpp @@ -54,20 +54,13 @@ bool ReferencesResolver::visit(Return const& _return) bool ReferencesResolver::visit(UserDefinedTypeName const& _typeName) { - auto declarations = m_resolver.nameFromCurrentScope(_typeName.name()); - if (declarations.empty()) - BOOST_THROW_EXCEPTION( - DeclarationError() << - errinfo_sourceLocation(_typeName.location()) << - errinfo_comment("Undeclared identifier.") - ); - else if (declarations.size() > 1) + Declaration const* declaration = m_resolver.pathFromCurrentScope(_typeName.namePath()); + if (!declaration) BOOST_THROW_EXCEPTION( DeclarationError() << errinfo_sourceLocation(_typeName.location()) << - errinfo_comment("Duplicate identifier.") + errinfo_comment("Identifier not found or not unique.") ); - Declaration const* declaration = *declarations.begin(); _typeName.annotation().referencedDeclaration = declaration; return true; } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index c40a027a..b46b405d 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -5383,6 +5383,33 @@ BOOST_AUTO_TEST_CASE(internal_types_in_library) BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(4), u256(17))); } +BOOST_AUTO_TEST_CASE(using_library_structs) +{ + char const* sourceCode = R"( + library Lib { + struct Data { uint a; uint[] b; } + function set(Data storage _s) + { + _s.a = 7; + _s.b.length = 20; + _s.b[19] = 8; + } + } + contract Test { + mapping(string => Lib.Data) data; + function f() returns (uint a, uint b) + { + Lib.set(data["abc"]); + a = data["abc"].a; + b = data["abc"].b[19]; + } + } + )"; + compileAndRun(sourceCode, 0, "Lib"); + compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}}); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7), u256(8))); +} + BOOST_AUTO_TEST_CASE(short_strings) { // This test verifies that the byte array encoding that combines length and data works |