diff options
-rw-r--r-- | .travis.yml | 1 | ||||
-rw-r--r-- | Changelog.md | 3 | ||||
-rw-r--r-- | docs/grammar.txt | 23 | ||||
-rw-r--r-- | docs/index.rst | 9 | ||||
-rw-r--r-- | docs/layout-of-source-files.rst | 4 | ||||
-rw-r--r-- | docs/miscellaneous.rst | 1 | ||||
-rw-r--r-- | libevmasm/PeepholeOptimiser.cpp | 2 | ||||
-rw-r--r-- | libsolidity/ast/AST.cpp | 3 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 42 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 22 |
10 files changed, 94 insertions, 16 deletions
diff --git a/.travis.yml b/.travis.yml index 2160d175..820125cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -71,6 +71,7 @@ matrix: dist: trusty sudo: required compiler: gcc + node_js: stable services: - docker before_install: diff --git a/Changelog.md b/Changelog.md index 9faf0f8e..a82e8744 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,8 @@ ### 0.4.8 (unreleased) +BugFixes: + * Type checker, code generator: enable access to events of base contracts' names. + ### 0.4.7 (2016-12-15) Features: diff --git a/docs/grammar.txt b/docs/grammar.txt index c9f7f448..b5d2b780 100644 --- a/docs/grammar.txt +++ b/docs/grammar.txt @@ -14,7 +14,7 @@ ContractDefinition = ( 'contract' | 'library' ) Identifier ContractPart = StateVariableDeclaration | UsingForDeclaration | StructDefinition | ModifierDefinition | FunctionDefinition | EventDefinition | EnumDefinition -InheritanceSpecifier = Identifier ( '(' Expression ( ',' Expression )* ')' )? +InheritanceSpecifier = UserDefinedTypeName ( '(' Expression ( ',' Expression )* ')' )? StateVariableDeclaration = TypeName ( 'public' | 'internal' | 'private' )? Identifier ('=' Expression)? ';' UsingForDeclaration = 'using' Identifier 'for' ('*' | TypeName) ';' @@ -36,7 +36,15 @@ TypeNameList = '(' ( TypeName (',' TypeName )* )? ')' // semantic restriction: mappings and structs (recursively) containing mappings // are not allowed in argument lists VariableDeclaration = TypeName Identifier -TypeName = ElementaryTypeName | Identifier StorageLocation? | Mapping | ArrayTypeName | FunctionTypeName + +TypeName = ElementaryTypeName + | UserDefinedTypeName StorageLocation? + | Mapping + | ArrayTypeName + | FunctionTypeName + +UserDefinedTypeName = Identifier ( '.' Identifier )* + Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')' ArrayTypeName = TypeName '[' Expression? ']' StorageLocation? FunctionTypeName = 'function' TypeNameList ( 'internal' | 'external' | 'constant' | 'payable' )* @@ -69,7 +77,7 @@ Expression = | Expression '**' Expression | Expression ('*' | '/' | '%') Expression | Expression ('+' | '-') Expression - | Expression ('<<' | '>>') + | Expression ('<<' | '>>') Expression | Expression '&' Expression | Expression '^' Expression | Expression '|' Expression @@ -82,7 +90,12 @@ Expression = | Expression? (',' Expression) | PrimaryExpression -PrimaryExpression = Identifier | BooleanLiteral | NumberLiteral | HexLiteral | StringLiteral +PrimaryExpression = Identifier + | BooleanLiteral + | NumberLiteral + | HexLiteral + | StringLiteral + | ElementaryTypeNameExpression FunctionCall = ( PrimaryExpression | NewExpression | TypeName ) ( ( '.' Identifier ) | ( '[' Expression ']' ) )* '(' Expression? ( ',' Expression )* ')' NewExpression = 'new' Identifier @@ -100,6 +113,8 @@ Identifier = [a-zA-Z_] [a-zA-Z_0-9]* HexNumber = '0x' [0-9a-fA-F]+ DecimalNumber = [0-9]+ +ElementaryTypeNameExpression = ElementaryTypeName + ElementaryTypeName = 'address' | 'bool' | 'string' | 'var' | Int | Uint | Byte | Fixed | Ufixed diff --git a/docs/index.rst b/docs/index.rst index 9bee1515..cb79687b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -87,6 +87,15 @@ Solidity Tools * `evmdis <https://github.com/Arachnid/evmdis>`_ EVM Disassembler that performs static analysis on the bytecode to provide a higher level of abstraction than raw EVM operations. +Third-Party Solidity Parsers and Grammars +----------------------------------------- + +* `solidity-parser <https://github.com/ConsenSys/solidity-parser>`_ + Solidity parser for JavaScript + +* `Solidity Grammar for ANTLR 4 <https://github.com/federicobond/solidity-antlr4>`_ + Solidity grammar for the ANTLR 4 parser generator + Language Documentation ---------------------- diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst index 17ac8c6f..dff48be3 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -96,8 +96,8 @@ Use in Actual Compilers When the compiler is invoked, it is not only possible to specify how to discover the first element of a path, but it is possible to specify path prefix remappings so that e.g. ``github.com/ethereum/dapp-bin/library`` is remapped to -``/usr/local/dapp-bin/library`` and the compiler will read the files from there. If -remapping keys are prefixes of each other, the longest is tried first. This +``/usr/local/dapp-bin/library`` and the compiler will read the files from there. +If multiple remappings can be applied, the one with the longest key is tried first. This allows for a "fallback-remapping" with e.g. ``""`` maps to ``"/usr/local/include/solidity"``. Furthermore, these remappings can depend on the context, which allows you to configure packages to diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 4a9dad87..378c3c96 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -570,3 +570,4 @@ Language Grammar ================ .. literalinclude:: grammar.txt + :language: none diff --git a/libevmasm/PeepholeOptimiser.cpp b/libevmasm/PeepholeOptimiser.cpp index b96b0295..923ffa67 100644 --- a/libevmasm/PeepholeOptimiser.cpp +++ b/libevmasm/PeepholeOptimiser.cpp @@ -120,7 +120,7 @@ struct OpPop: SimplePeepholeOptimizerMethod<OpPop, 2> if (instructionInfo(instr).ret == 1 && !instructionInfo(instr).sideEffects) { for (int j = 0; j < instructionInfo(instr).args; j++) - *_out = Instruction::POP; + *_out = {Instruction::POP, _op.location()}; return true; } } diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 3cd1dfbe..78d8949c 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -217,6 +217,9 @@ vector<Declaration const*> const& ContractDefinition::inheritableMembers() const for (EnumDefinition const* e: definedEnums()) addInheritableMember(e); + + for (EventDefinition const* e: events()) + addInheritableMember(e); } return *m_inheritableMembers; } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index a7fb8408..3922da88 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -908,19 +908,43 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) solAssert(_memberAccess.annotation().type, "_memberAccess has no type"); if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type.get())) { - if (funType->location() != FunctionType::Location::Internal) - { - _memberAccess.expression().accept(*this); - m_context << funType->externalIdentifier(); - } - else + switch (funType->location()) { + case FunctionType::Location::Internal: // We do not visit the expression here on purpose, because in the case of an // internal library function call, this would push the library address forcing // us to link against it although we actually do not need it. - auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.annotation().referencedDeclaration); - solAssert(!!function, "Function not found in member access"); - utils().pushCombinedFunctionEntryLabel(*function); + if (auto const* function = dynamic_cast<FunctionDefinition const*>(_memberAccess.annotation().referencedDeclaration)) + utils().pushCombinedFunctionEntryLabel(*function); + else + solAssert(false, "Function not found in member access"); + break; + case FunctionType::Location::Event: + if (!dynamic_cast<EventDefinition const*>(_memberAccess.annotation().referencedDeclaration)) + solAssert(false, "event not found"); + // no-op, because the parent node will do the job + break; + case FunctionType::Location::External: + case FunctionType::Location::Creation: + case FunctionType::Location::DelegateCall: + case FunctionType::Location::CallCode: + case FunctionType::Location::Send: + case FunctionType::Location::Bare: + case FunctionType::Location::BareCallCode: + case FunctionType::Location::BareDelegateCall: + _memberAccess.expression().accept(*this); + m_context << funType->externalIdentifier(); + break; + case FunctionType::Location::Log0: + case FunctionType::Location::Log1: + case FunctionType::Location::Log2: + case FunctionType::Location::Log3: + case FunctionType::Location::Log4: + case FunctionType::Location::ECRecover: + case FunctionType::Location::SHA256: + case FunctionType::Location::RIPEMD160: + default: + solAssert(false, "unsupported member function"); } } else if (dynamic_cast<TypeType const*>(_memberAccess.annotation().type.get())) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 94d4fb7f..d8539524 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -2770,6 +2770,28 @@ BOOST_AUTO_TEST_CASE(event_no_arguments) BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit()"))); } +BOOST_AUTO_TEST_CASE(event_access_through_base_name) +{ + char const* sourceCode = R"( + contract A { + event x(); + } + contract B is A { + function f() returns (uint) { + A.x(); + return 1; + } + } + )"; + compileAndRun(sourceCode); + callContractFunction("f()"); + BOOST_REQUIRE_EQUAL(m_logs.size(), 1); + BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); + BOOST_CHECK(m_logs[0].data.empty()); + BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); + BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("x()"))); +} + BOOST_AUTO_TEST_CASE(event_anonymous) { char const* sourceCode = R"( |