aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md1
-rw-r--r--libsolidity/analysis/ContractLevelChecker.cpp53
-rw-r--r--test/libsolidity/syntaxTests/inheritance/override/implement_interface_by_public_variable.sol7
-rw-r--r--test/libsolidity/syntaxTests/inheritance/override/implement_internal_function_by_public_variable.sol9
-rw-r--r--test/libsolidity/syntaxTests/inheritance/override/implement_private_function_by_public_variable.sol7
-rw-r--r--test/libsolidity/syntaxTests/inheritance/override/implement_public_function_by_public_variable.sol9
-rw-r--r--test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol1
7 files changed, 66 insertions, 21 deletions
diff --git a/Changelog.md b/Changelog.md
index 630801e4..7aa5a6be 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -27,6 +27,7 @@ Bugfixes:
* Type Checker: Fixed internal error when trying to create abstract contract in some cases.
* Type Checker: Fixed internal error related to double declaration of events.
* Type Checker: Disallow inline arrays of mapping type.
+ * Type Checker: Consider abstract function to be implemented by public state variable.
Build System:
* Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67.
diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp
index 58dcfe4d..6dc564de 100644
--- a/libsolidity/analysis/ContractLevelChecker.cpp
+++ b/libsolidity/analysis/ContractLevelChecker.cpp
@@ -219,29 +219,40 @@ void ContractLevelChecker::checkAbstractFunctions(ContractDefinition const& _con
using FunTypeAndFlag = std::pair<FunctionTypePointer, bool>;
map<string, vector<FunTypeAndFlag>> functions;
- // Search from base to derived
- for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts))
- for (FunctionDefinition const* function: contract->definedFunctions())
+ auto registerFunction = [&](Declaration const& _declaration, FunctionTypePointer const& _type, bool _implemented)
+ {
+ auto& overloads = functions[_declaration.name()];
+ auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag)
{
- // Take constructors out of overload hierarchy
- if (function->isConstructor())
- continue;
- auto& overloads = functions[function->name()];
- FunctionTypePointer funType = make_shared<FunctionType>(*function)->asCallableFunction(false);
- auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag)
- {
- return funType->hasEqualParameterTypes(*_funAndFlag.first);
- });
- if (it == overloads.end())
- overloads.push_back(make_pair(funType, function->isImplemented()));
- else if (it->second)
- {
- if (!function->isImplemented())
- m_errorReporter.typeError(function->location(), "Redeclaring an already implemented function as abstract");
- }
- else if (function->isImplemented())
- it->second = true;
+ return _type->hasEqualParameterTypes(*_funAndFlag.first);
+ });
+ if (it == overloads.end())
+ overloads.push_back(make_pair(_type, _implemented));
+ else if (it->second)
+ {
+ if (!_implemented)
+ m_errorReporter.typeError(_declaration.location(), "Redeclaring an already implemented function as abstract");
}
+ else if (_implemented)
+ it->second = true;
+ };
+
+ // Search from base to derived, collect all functions and update
+ // the 'implemented' flag.
+ for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts))
+ {
+ for (VariableDeclaration const* v: contract->stateVariables())
+ if (v->isPartOfExternalInterface())
+ registerFunction(*v, make_shared<FunctionType>(*v), true);
+
+ for (FunctionDefinition const* function: contract->definedFunctions())
+ if (!function->isConstructor())
+ registerFunction(
+ *function,
+ make_shared<FunctionType>(*function)->asCallableFunction(false),
+ function->isImplemented()
+ );
+ }
// Set to not fully implemented if at least one flag is false.
for (auto const& it: functions)
diff --git a/test/libsolidity/syntaxTests/inheritance/override/implement_interface_by_public_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/implement_interface_by_public_variable.sol
new file mode 100644
index 00000000..49f7c33b
--- /dev/null
+++ b/test/libsolidity/syntaxTests/inheritance/override/implement_interface_by_public_variable.sol
@@ -0,0 +1,7 @@
+interface X { function test() external returns (uint256); }
+contract Y is X {
+ uint256 public test = 42;
+}
+contract T {
+ constructor() public { new Y(); }
+}
diff --git a/test/libsolidity/syntaxTests/inheritance/override/implement_internal_function_by_public_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/implement_internal_function_by_public_variable.sol
new file mode 100644
index 00000000..32fac25c
--- /dev/null
+++ b/test/libsolidity/syntaxTests/inheritance/override/implement_internal_function_by_public_variable.sol
@@ -0,0 +1,9 @@
+contract X { function test() internal returns (uint256); }
+contract Y is X {
+ uint256 public test = 42;
+}
+contract T {
+ constructor() public { new Y(); }
+}
+// ----
+// DeclarationError: (81-105): Identifier already declared.
diff --git a/test/libsolidity/syntaxTests/inheritance/override/implement_private_function_by_public_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/implement_private_function_by_public_variable.sol
new file mode 100644
index 00000000..c58e24b6
--- /dev/null
+++ b/test/libsolidity/syntaxTests/inheritance/override/implement_private_function_by_public_variable.sol
@@ -0,0 +1,7 @@
+contract X { function test() private returns (uint256); }
+contract Y is X {
+ uint256 public test = 42;
+}
+contract T {
+ constructor() public { new Y(); }
+}
diff --git a/test/libsolidity/syntaxTests/inheritance/override/implement_public_function_by_public_variable.sol b/test/libsolidity/syntaxTests/inheritance/override/implement_public_function_by_public_variable.sol
new file mode 100644
index 00000000..7a59c137
--- /dev/null
+++ b/test/libsolidity/syntaxTests/inheritance/override/implement_public_function_by_public_variable.sol
@@ -0,0 +1,9 @@
+contract X { function test() public returns (uint256); }
+contract Y is X {
+ uint256 public test = 42;
+}
+contract T {
+ constructor() public { new Y(); }
+}
+// ----
+// DeclarationError: (79-103): Identifier already declared.
diff --git a/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol b/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol
index 0f05cc8e..fb7f3fbd 100644
--- a/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol
+++ b/test/libsolidity/syntaxTests/inheritance/override/state_variable_function.sol
@@ -6,3 +6,4 @@ contract C is A {
}
// ----
// DeclarationError: (50-85): Identifier already declared.
+// TypeError: (50-85): Redeclaring an already implemented function as abstract