mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Public state variables are implementing external functions.
This commit is contained in:
parent
cc00d8172b
commit
0668a9ecfb
@ -27,6 +27,7 @@ Bugfixes:
|
|||||||
* Type Checker: Fixed internal error when trying to create abstract contract in some cases.
|
* 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: Fixed internal error related to double declaration of events.
|
||||||
* Type Checker: Disallow inline arrays of mapping type.
|
* Type Checker: Disallow inline arrays of mapping type.
|
||||||
|
* Type Checker: Consider abstract function to be implemented by public state variable.
|
||||||
|
|
||||||
Build System:
|
Build System:
|
||||||
* Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67.
|
* Emscripten: Upgrade to Emscripten SDK 1.37.21 and boost 1.67.
|
||||||
|
@ -219,29 +219,40 @@ void ContractLevelChecker::checkAbstractFunctions(ContractDefinition const& _con
|
|||||||
using FunTypeAndFlag = std::pair<FunctionTypePointer, bool>;
|
using FunTypeAndFlag = std::pair<FunctionTypePointer, bool>;
|
||||||
map<string, vector<FunTypeAndFlag>> functions;
|
map<string, vector<FunTypeAndFlag>> functions;
|
||||||
|
|
||||||
// Search from base to derived
|
auto registerFunction = [&](Declaration const& _declaration, FunctionTypePointer const& _type, bool _implemented)
|
||||||
for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.annotation().linearizedBaseContracts))
|
{
|
||||||
for (FunctionDefinition const* function: contract->definedFunctions())
|
auto& overloads = functions[_declaration.name()];
|
||||||
|
auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag)
|
||||||
{
|
{
|
||||||
// Take constructors out of overload hierarchy
|
return _type->hasEqualParameterTypes(*_funAndFlag.first);
|
||||||
if (function->isConstructor())
|
});
|
||||||
continue;
|
if (it == overloads.end())
|
||||||
auto& overloads = functions[function->name()];
|
overloads.push_back(make_pair(_type, _implemented));
|
||||||
FunctionTypePointer funType = make_shared<FunctionType>(*function)->asCallableFunction(false);
|
else if (it->second)
|
||||||
auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag)
|
{
|
||||||
{
|
if (!_implemented)
|
||||||
return funType->hasEqualParameterTypes(*_funAndFlag.first);
|
m_errorReporter.typeError(_declaration.location(), "Redeclaring an already implemented function as abstract");
|
||||||
});
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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.
|
// Set to not fully implemented if at least one flag is false.
|
||||||
for (auto const& it: functions)
|
for (auto const& it: functions)
|
||||||
|
@ -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(); }
|
||||||
|
}
|
@ -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.
|
@ -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(); }
|
||||||
|
}
|
@ -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.
|
@ -6,3 +6,4 @@ contract C is A {
|
|||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// DeclarationError: (50-85): Identifier already declared.
|
// DeclarationError: (50-85): Identifier already declared.
|
||||||
|
// TypeError: (50-85): Redeclaring an already implemented function as abstract
|
||||||
|
Loading…
Reference in New Issue
Block a user