From bff76c1ca0433f88874fded8990f39292483d9f0 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 1 Nov 2016 17:18:00 +0100 Subject: [PATCH 01/10] analysis: report errors when inheritance causes collision --- libsolidity/analysis/NameAndTypeResolver.cpp | 26 +++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 2a33a5015..fc107ba01 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -289,7 +289,31 @@ void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base) for (auto const& declaration: nameAndDeclaration.second) // Import if it was declared in the base, is not the constructor and is visible in derived classes if (declaration->scope() == &_base && declaration->isVisibleInDerivedContracts()) - m_currentScope->registerDeclaration(*declaration); + if (!m_currentScope->registerDeclaration(*declaration)) + { + SourceLocation firstDeclarationLocation; + SourceLocation secondDeclarationLocation; + Declaration const* conflictingDeclaration = m_currentScope->conflictingDeclaration(*declaration); + solAssert(conflictingDeclaration, ""); + + if (declaration->location().start < conflictingDeclaration->location().start) + { + firstDeclarationLocation = declaration->location(); + secondDeclarationLocation = conflictingDeclaration->location(); + } + else + { + firstDeclarationLocation = conflictingDeclaration->location(); + secondDeclarationLocation = declaration->location(); + } + + reportDeclarationError( + secondDeclarationLocation, + "Identifier already declared.", + firstDeclarationLocation, + "The previous declaration is here:" + ); + } } void NameAndTypeResolver::linearizeBaseContracts(ContractDefinition& _contract) From 42b672617392ecb294447f73fd011092cd58702b Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 2 Dec 2016 16:06:01 +0100 Subject: [PATCH 02/10] analysis: allow some shadowings explicitly --- libsolidity/analysis/NameAndTypeResolver.cpp | 8 +++ test/libsolidity/SolidityEndToEndTest.cpp | 54 ------------------- .../SolidityNameAndTypeResolution.cpp | 23 +++++++- 3 files changed, 29 insertions(+), 56 deletions(-) diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index fc107ba01..002ff8116 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -296,6 +296,14 @@ void NameAndTypeResolver::importInheritedScope(ContractDefinition const& _base) Declaration const* conflictingDeclaration = m_currentScope->conflictingDeclaration(*declaration); solAssert(conflictingDeclaration, ""); + // Usual shadowing is not an error + if (dynamic_cast(declaration) && dynamic_cast(conflictingDeclaration)) + continue; + + // Usual shadowing is not an error + if (dynamic_cast(declaration) && dynamic_cast(conflictingDeclaration)) + continue; + if (declaration->location().start < conflictingDeclaration->location().start) { firstDeclarationLocation = declaration->location(); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index d85395240..191618317 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -4869,60 +4869,6 @@ BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes) BOOST_CHECK(callContractFunction("ok()") == encodeArgs(false)); } -BOOST_AUTO_TEST_CASE(proper_overwriting_accessor_by_function) -{ - // bug #1798 - char const* sourceCode = R"( - contract attribute { - bool ok = false; - } - contract func { - function ok() returns (bool) { return true; } - } - - contract attr_func is attribute, func { - function checkOk() returns (bool) { return ok(); } - } - contract func_attr is func, attribute { - function checkOk() returns (bool) { return ok; } - } - )"; - compileAndRun(sourceCode, 0, "attr_func"); - BOOST_CHECK(callContractFunction("ok()") == encodeArgs(true)); - compileAndRun(sourceCode, 0, "func_attr"); - BOOST_CHECK(callContractFunction("checkOk()") == encodeArgs(false)); -} - - -BOOST_AUTO_TEST_CASE(overwriting_inheritance) -{ - // bug #1798 - char const* sourceCode = R"( - contract A { - function ok() returns (uint) { return 1; } - } - contract B { - function ok() returns (uint) { return 2; } - } - contract C { - uint ok = 6; - } - contract AB is A, B { - function ok() returns (uint) { return 4; } - } - contract reversedE is C, AB { - function checkOk() returns (uint) { return ok(); } - } - contract E is AB, C { - function checkOk() returns (uint) { return ok; } - } - )"; - compileAndRun(sourceCode, 0, "reversedE"); - BOOST_CHECK(callContractFunction("checkOk()") == encodeArgs(4)); - compileAndRun(sourceCode, 0, "E"); - BOOST_CHECK(callContractFunction("checkOk()") == encodeArgs(6)); -} - BOOST_AUTO_TEST_CASE(struct_assign_reference_to_struct) { char const* sourceCode = R"( diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 576421fdf..11ce99974 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -1056,7 +1056,7 @@ BOOST_AUTO_TEST_CASE(modifier_overrides_function) contract A { modifier mod(uint a) { _; } } contract B is A { function mod(uint a) { } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(function_overrides_modifier) @@ -1065,7 +1065,7 @@ BOOST_AUTO_TEST_CASE(function_overrides_modifier) contract A { function mod(uint a) { } } contract B is A { modifier mod(uint a) { _; } } )"; - CHECK_ERROR(text, TypeError, ""); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(modifier_returns_value) @@ -4304,6 +4304,25 @@ BOOST_AUTO_TEST_CASE(illegal_override_payable_nonpayable) CHECK_ERROR(text, TypeError, ""); } +BOOST_AUTO_TEST_CASE(function_variable_mixin) +{ + // bug #1798 (cpp-ethereum), related to #1286 (solidity) + char const* text = R"( + contract attribute { + bool ok = false; + } + contract func { + function ok() returns (bool) { return true; } + } + + contract attr_func is attribute, func { + function checkOk() returns (bool) { return ok(); } + } + )"; + CHECK_ERROR(text, DeclarationError, ""); +} + + BOOST_AUTO_TEST_CASE(payable_constant_conflict) { char const* text = R"( From 91d4e8e0bab6f5285103af6ef84a7813cfbb61a2 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Fri, 2 Dec 2016 16:24:53 +0100 Subject: [PATCH 03/10] analysis: changes necessary to compile std/StandardToken.sol --- libsolidity/analysis/DeclarationContainer.cpp | 13 ++++++- libsolidity/analysis/NameAndTypeResolver.cpp | 38 +++++++++++++++---- libsolidity/analysis/TypeChecker.cpp | 19 +++++++++- 3 files changed, 58 insertions(+), 12 deletions(-) diff --git a/libsolidity/analysis/DeclarationContainer.cpp b/libsolidity/analysis/DeclarationContainer.cpp index 1599b83ac..f8c12c5bd 100644 --- a/libsolidity/analysis/DeclarationContainer.cpp +++ b/libsolidity/analysis/DeclarationContainer.cpp @@ -44,10 +44,19 @@ Declaration const* DeclarationContainer::conflictingDeclaration( if (dynamic_cast(&_declaration)) { - // check that all other declarations with the same name are functions + // check that all other declarations with the same name are functions or a public state variable for (Declaration const* declaration: declarations) - if (!dynamic_cast(declaration)) + { + if (dynamic_cast(declaration)) + continue; + if (auto variableDeclaration = dynamic_cast(declaration)) + { + if (variableDeclaration->isStateVariable() && !variableDeclaration->isConstant() && variableDeclaration->isPublic()) + continue; return declaration; + } + return declaration; + } } else if (declarations.size() == 1 && declarations.front() == &_declaration) return nullptr; diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 002ff8116..ee05910c8 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -260,20 +260,42 @@ vector NameAndTypeResolver::cleanedDeclarations( for (auto it = _declarations.begin(); it != _declarations.end(); ++it) { solAssert(*it, ""); - // the declaration is functionDefinition while declarations > 1 - FunctionDefinition const& functionDefinition = dynamic_cast(**it); - FunctionType functionType(functionDefinition); - for (auto parameter: functionType.parameterTypes() + functionType.returnParameterTypes()) - if (!parameter) - reportFatalDeclarationError(_identifier.location(), "Function type can not be used in this context"); + // the declaration is functionDefinition or a VariableDeclaration while declarations > 1 + solAssert(dynamic_cast(*it) || dynamic_cast(*it), + "Found overloading involving something not a function or a variable"); + + shared_ptr functionType {}; + + if (FunctionDefinition const* functionDefinition = dynamic_cast(*it)) + { + functionType = make_shared(*functionDefinition); + for (auto parameter: functionType->parameterTypes() + functionType->returnParameterTypes()) + if (!parameter) + reportFatalDeclarationError(_identifier.location(), "Function type can not be used in this context"); + } + else + { + VariableDeclaration const* variableDeclaration = dynamic_cast(*it); + functionType = make_shared(*variableDeclaration); + } + solAssert(functionType, "failed to determine the function type of the overloaded"); if (uniqueFunctions.end() == find_if( uniqueFunctions.begin(), uniqueFunctions.end(), [&](Declaration const* d) { - FunctionType newFunctionType(dynamic_cast(*d)); - return functionType.hasEqualArgumentTypes(newFunctionType); + if (FunctionDefinition const* functionDefinition = dynamic_cast(d)) + { + FunctionType const newFunctionType(*functionDefinition); + return functionType->hasEqualArgumentTypes(newFunctionType); + } + else if (VariableDeclaration const* variableDeclaration = dynamic_cast(d)) + { + FunctionType const newFunctionType(*variableDeclaration); + return functionType->hasEqualArgumentTypes(newFunctionType); + } + return false; // to make compiler happy } )) uniqueFunctions.push_back(*it); diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e414e27c4..67c8ac175 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1500,8 +1500,23 @@ bool TypeChecker::visit(Identifier const& _identifier) if (!annotation.referencedDeclaration) { if (!annotation.argumentTypes) - fatalTypeError(_identifier.location(), "Unable to determine overloaded type."); - if (annotation.overloadedDeclarations.empty()) + { + // The identifier should be a public state variable shadowing other functions + vector candidates; + + for (Declaration const* declaration: annotation.overloadedDeclarations) + { + if (VariableDeclaration const* variableDeclaration = dynamic_cast(declaration)) + candidates.push_back(declaration); + } + if (candidates.empty()) + fatalTypeError(_identifier.location(), "No matching declaration found after variable lookup."); + else if (candidates.size() == 1) + annotation.referencedDeclaration = candidates.front(); + else + fatalTypeError(_identifier.location(), "No unique declaration found after variable lookup."); + } + else if (annotation.overloadedDeclarations.empty()) fatalTypeError(_identifier.location(), "No candidates for overload resolution found."); else if (annotation.overloadedDeclarations.size() == 1) annotation.referencedDeclaration = *annotation.overloadedDeclarations.begin(); From 0216f34010343af6285305b59d47db62261c03c6 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 5 Dec 2016 12:03:07 +0100 Subject: [PATCH 04/10] analysis: avoid emscripten build failure --- libsolidity/analysis/NameAndTypeResolver.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index ee05910c8..260965ae3 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -264,11 +264,11 @@ vector NameAndTypeResolver::cleanedDeclarations( solAssert(dynamic_cast(*it) || dynamic_cast(*it), "Found overloading involving something not a function or a variable"); - shared_ptr functionType {}; + unique_ptr functionType {}; if (FunctionDefinition const* functionDefinition = dynamic_cast(*it)) { - functionType = make_shared(*functionDefinition); + functionType = unique_ptr(new FunctionType(*functionDefinition)); for (auto parameter: functionType->parameterTypes() + functionType->returnParameterTypes()) if (!parameter) reportFatalDeclarationError(_identifier.location(), "Function type can not be used in this context"); @@ -276,7 +276,7 @@ vector NameAndTypeResolver::cleanedDeclarations( else { VariableDeclaration const* variableDeclaration = dynamic_cast(*it); - functionType = make_shared(*variableDeclaration); + functionType = unique_ptr(new FunctionType(*variableDeclaration)); } solAssert(functionType, "failed to determine the function type of the overloaded"); From 9602318eab7affca78b8b5db018e9e646f40e84e Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Wed, 14 Dec 2016 14:18:11 +0100 Subject: [PATCH 05/10] test: allow multiple errors in modifier-function overriding --- test/libsolidity/SolidityNameAndTypeResolution.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 11ce99974..9f6ea2b3b 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -1056,7 +1056,9 @@ BOOST_AUTO_TEST_CASE(modifier_overrides_function) contract A { modifier mod(uint a) { _; } } contract B is A { function mod(uint a) { } } )"; - CHECK_ERROR(text, DeclarationError, ""); + // Error: Identifier already declared. + // Error: Override changes modifier to function. + CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(function_overrides_modifier) @@ -1065,7 +1067,9 @@ BOOST_AUTO_TEST_CASE(function_overrides_modifier) contract A { function mod(uint a) { } } contract B is A { modifier mod(uint a) { _; } } )"; - CHECK_ERROR(text, DeclarationError, ""); + // Error: Identifier already declared. + // Error: Override changes function to modifier. + CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(modifier_returns_value) From bd6e65a89c1e90a01740c61af84b17be7ade26a0 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 3 Jan 2017 19:40:50 +0100 Subject: [PATCH 06/10] docs: document the resriction about a function and an event of the same name, and so on --- docs/contracts.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/contracts.rst b/docs/contracts.rst index e82b7495f..edc42c3d7 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -877,6 +877,13 @@ cannot be resolved. A simple rule to remember is to specify the base classes in the order from "most base-like" to "most derived". +Inheriting Different Kinds of Members of the Same Name +====================================================== + +When the inheritance results in a contract with a function and a modifier of the same name, it is considered as an error. +This error is produced also by an event and a modifier of the same name, and a function and an event of the same name. +As an exception, a state variable accessor can override a public function. + .. index:: ! contract;abstract, ! abstract contract ****************** From e254a59bd29b7bf226197eaa836fc163be16ef09 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Mon, 9 Jan 2017 18:32:02 +0100 Subject: [PATCH 07/10] Changelog: add a line about #1479 --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 8a005eed2..81f08c9fb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Features: BugFixes: * Type checker, code generator: enable access to events of base contracts' names. * Imports: ``import ".dir/a"`` is not a relative path. Relative paths begin with directory ``.`` or ``..``. + * Type checker, disallow inheritances of different kinds (e.g. a function and a modifier) of members of the same name ### 0.4.7 (2016-12-15) From eda147f47bb5a0dfbed50aa2c2224daebafa76a8 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 10 Jan 2017 16:26:13 +0100 Subject: [PATCH 08/10] ast: add Declaration::functionType() --- libsolidity/analysis/NameAndTypeResolver.cpp | 21 +++---- libsolidity/ast/AST.cpp | 61 ++++++++++++++++++++ libsolidity/ast/AST.h | 12 ++++ 3 files changed, 80 insertions(+), 14 deletions(-) diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 260965ae3..47a9df1bd 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -264,22 +264,15 @@ vector NameAndTypeResolver::cleanedDeclarations( solAssert(dynamic_cast(*it) || dynamic_cast(*it), "Found overloading involving something not a function or a variable"); - unique_ptr functionType {}; - - if (FunctionDefinition const* functionDefinition = dynamic_cast(*it)) - { - functionType = unique_ptr(new FunctionType(*functionDefinition)); - for (auto parameter: functionType->parameterTypes() + functionType->returnParameterTypes()) - if (!parameter) - reportFatalDeclarationError(_identifier.location(), "Function type can not be used in this context"); - } - else - { - VariableDeclaration const* variableDeclaration = dynamic_cast(*it); - functionType = unique_ptr(new FunctionType(*variableDeclaration)); - } + shared_ptr functionType { (*it)->functionType(false) }; + if (!functionType) + functionType = (*it)->functionType(true); solAssert(functionType, "failed to determine the function type of the overloaded"); + for (auto parameter: functionType->parameterTypes() + functionType->returnParameterTypes()) + if (!parameter) + reportFatalDeclarationError(_identifier.location(), "Function type can not be used in this context"); + if (uniqueFunctions.end() == find_if( uniqueFunctions.begin(), uniqueFunctions.end(), diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 78d8949ca..ac92eaa32 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -274,6 +274,45 @@ TypeDeclarationAnnotation& EnumDefinition::annotation() const return static_cast(*m_annotation); } +shared_ptr FunctionDefinition::functionType(bool _internal) const +{ + if (_internal) + { + switch (visibility()) + { + case Declaration::Visibility::Default: + solAssert(false, "visibility() should not return Default"); + case Declaration::Visibility::Private: + case Declaration::Visibility::Internal: + case Declaration::Visibility::Public: + return make_shared(*this, _internal); + case Declaration::Visibility::External: + return {}; + default: + solAssert(false, "visibility() should not return a Visibility"); + } + } + else + { + switch (visibility()) + { + case Declaration::Visibility::Default: + solAssert(false, "visibility() should not return Default"); + case Declaration::Visibility::Private: + case Declaration::Visibility::Internal: + return {}; + case Declaration::Visibility::Public: + case Declaration::Visibility::External: + return make_shared(*this, _internal); + default: + solAssert(false, "visibility() should not return a Visibility"); + } + } + + // To make the compiler happy + return {}; +} + TypePointer FunctionDefinition::type() const { return make_shared(*this); @@ -365,6 +404,28 @@ TypePointer VariableDeclaration::type() const return annotation().type; } +shared_ptr VariableDeclaration::functionType(bool _internal) const +{ + if (_internal) + return {}; + switch (visibility()) + { + case Declaration::Visibility::Default: + solAssert(false, "visibility() should not return Default"); + case Declaration::Visibility::Private: + case Declaration::Visibility::Internal: + return {}; + case Declaration::Visibility::Public: + case Declaration::Visibility::External: + return make_shared(*this); + default: + solAssert(false, "visibility() should not return a Visibility"); + } + + // To make the compiler happy + return {}; +} + VariableDeclarationAnnotation& VariableDeclaration::annotation() const { if (!m_annotation) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index ab4be1eaf..088d68dbe 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -171,6 +171,10 @@ public: /// This can only be called once types of variable declarations have already been resolved. virtual TypePointer type() const = 0; + /// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned. + /// @returns null when it is not accessible as a function. + virtual std::shared_ptr functionType(bool /*_internal*/) const { return {}; } + protected: virtual Visibility defaultVisibility() const { return Visibility::Public; } @@ -581,6 +585,10 @@ public: virtual TypePointer type() const override; + /// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned. + /// @returns null when it is not accessible as a function. + virtual std::shared_ptr functionType(bool /*_internal*/) const override; + virtual FunctionDefinitionAnnotation& annotation() const override; private: @@ -643,6 +651,10 @@ public: virtual TypePointer type() const override; + /// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned. + /// @returns null when it is not accessible as a function. + virtual std::shared_ptr functionType(bool /*_internal*/) const override; + virtual VariableDeclarationAnnotation& annotation() const override; protected: From 7fea4b7360d1db01a33fd2c5a90e966880232e47 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 10 Jan 2017 16:34:55 +0100 Subject: [PATCH 09/10] analysis: use Declaration::functionType() in another location --- libsolidity/analysis/NameAndTypeResolver.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 47a9df1bd..08323243a 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -278,17 +278,10 @@ vector NameAndTypeResolver::cleanedDeclarations( uniqueFunctions.end(), [&](Declaration const* d) { - if (FunctionDefinition const* functionDefinition = dynamic_cast(d)) - { - FunctionType const newFunctionType(*functionDefinition); - return functionType->hasEqualArgumentTypes(newFunctionType); - } - else if (VariableDeclaration const* variableDeclaration = dynamic_cast(d)) - { - FunctionType const newFunctionType(*variableDeclaration); - return functionType->hasEqualArgumentTypes(newFunctionType); - } - return false; // to make compiler happy + shared_ptr newFunctionType { d->functionType(false) }; + if (!newFunctionType) + newFunctionType = d->functionType(true); + return newFunctionType && functionType->hasEqualArgumentTypes(*newFunctionType); } )) uniqueFunctions.push_back(*it); From abc24420a7837557e5160db8af83ea3be5a371c3 Mon Sep 17 00:00:00 2001 From: Yoichi Hirai Date: Tue, 10 Jan 2017 18:55:36 +0100 Subject: [PATCH 10/10] ast: events have FunctionType too --- libsolidity/ast/AST.cpp | 18 +++++++++++++----- libsolidity/ast/AST.h | 7 ++++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index ac92eaa32..6f7a64dcb 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -274,7 +274,7 @@ TypeDeclarationAnnotation& EnumDefinition::annotation() const return static_cast(*m_annotation); } -shared_ptr FunctionDefinition::functionType(bool _internal) const +shared_ptr FunctionDefinition::functionType(bool _internal) const { if (_internal) { @@ -285,7 +285,7 @@ shared_ptr FunctionDefinition::functionType(bool _internal) case Declaration::Visibility::Private: case Declaration::Visibility::Internal: case Declaration::Visibility::Public: - return make_shared(*this, _internal); + return make_shared(*this, _internal); case Declaration::Visibility::External: return {}; default: @@ -303,7 +303,7 @@ shared_ptr FunctionDefinition::functionType(bool _internal) return {}; case Declaration::Visibility::Public: case Declaration::Visibility::External: - return make_shared(*this, _internal); + return make_shared(*this, _internal); default: solAssert(false, "visibility() should not return a Visibility"); } @@ -347,6 +347,14 @@ TypePointer EventDefinition::type() const return make_shared(*this); } +std::shared_ptr EventDefinition::functionType(bool _internal) const +{ + if (_internal) + return make_shared(*this); + else + return {}; +} + EventDefinitionAnnotation& EventDefinition::annotation() const { if (!m_annotation) @@ -404,7 +412,7 @@ TypePointer VariableDeclaration::type() const return annotation().type; } -shared_ptr VariableDeclaration::functionType(bool _internal) const +shared_ptr VariableDeclaration::functionType(bool _internal) const { if (_internal) return {}; @@ -417,7 +425,7 @@ shared_ptr VariableDeclaration::functionType(bool _internal) return {}; case Declaration::Visibility::Public: case Declaration::Visibility::External: - return make_shared(*this); + return make_shared(*this); default: solAssert(false, "visibility() should not return a Visibility"); } diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 088d68dbe..2d0924089 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -173,7 +173,7 @@ public: /// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned. /// @returns null when it is not accessible as a function. - virtual std::shared_ptr functionType(bool /*_internal*/) const { return {}; } + virtual std::shared_ptr functionType(bool /*_internal*/) const { return {}; } protected: virtual Visibility defaultVisibility() const { return Visibility::Public; } @@ -587,7 +587,7 @@ public: /// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned. /// @returns null when it is not accessible as a function. - virtual std::shared_ptr functionType(bool /*_internal*/) const override; + virtual std::shared_ptr functionType(bool /*_internal*/) const override; virtual FunctionDefinitionAnnotation& annotation() const override; @@ -653,7 +653,7 @@ public: /// @param _internal false indicates external interface is concerned, true indicates internal interface is concerned. /// @returns null when it is not accessible as a function. - virtual std::shared_ptr functionType(bool /*_internal*/) const override; + virtual std::shared_ptr functionType(bool /*_internal*/) const override; virtual VariableDeclarationAnnotation& annotation() const override; @@ -752,6 +752,7 @@ public: bool isAnonymous() const { return m_anonymous; } virtual TypePointer type() const override; + virtual std::shared_ptr functionType(bool /*_internal*/) const override; virtual EventDefinitionAnnotation& annotation() const override;