Merge pull request #8436 from ethereum/fixCallingBaseFunction

Fix calling unimplemented base function.
This commit is contained in:
Daniel Kirchner 2020-03-06 11:41:30 +01:00 committed by GitHub
commit 78ce4b9611
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 15 deletions

View File

@ -10,6 +10,7 @@ Compiler Features:
Bugfixes:
* Inheritance: Fix incorrect error on calling unimplemented base functions.
* isoltest: Added new keyword `wei` to express function value in semantic tests
* Standard-JSON-Interface: Fix a bug related to empty filenames and imports.
* SMTChecker: Fix internal errors when analysing tuples.

View File

@ -1703,22 +1703,21 @@ void TypeChecker::typeCheckFunctionCall(
if (_functionType->kind() == FunctionType::Kind::Declaration)
{
m_errorReporter.typeError(
_functionCall.location(),
"Cannot call function via contract type name."
);
if (
m_scope->derivesFrom(*_functionType->declaration().annotation().contract) &&
!dynamic_cast<FunctionDefinition const&>(_functionType->declaration()).isImplemented()
)
m_errorReporter.typeError(
_functionCall.location(),
"Cannot call unimplemented base function."
);
else
m_errorReporter.typeError(
_functionCall.location(),
"Cannot call function via contract type name."
);
return;
}
if (_functionType->kind() == FunctionType::Kind::Internal && _functionType->hasDeclaration())
if (auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(&_functionType->declaration()))
// functionDefinition->annotation().contract != m_scope ensures that this is a qualified access,
// e.g. ``A.f();`` instead of a simple function call like ``f();`` (the latter is valid for unimplemented
// functions).
if (functionDefinition->annotation().contract != m_scope && !functionDefinition->isImplemented())
m_errorReporter.typeError(
_functionCall.location(),
"Cannot call unimplemented base function."
);
// Check for unsupported use of bare static call
if (

View File

@ -3471,7 +3471,15 @@ MemberList::MemberMap TypeType::nativeMembers(ContractDefinition const* _current
continue;
if (!contract.isLibrary() && inDerivingScope && declaration->isVisibleInDerivedContracts())
members.emplace_back(declaration->name(), declaration->type(), declaration);
{
if (
auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(declaration);
functionDefinition && !functionDefinition->isImplemented()
)
members.emplace_back(declaration->name(), declaration->typeViaContractName(), declaration);
else
members.emplace_back(declaration->name(), declaration->type(), declaration);
}
else if (
(contract.isLibrary() && declaration->isVisibleAsLibraryMember()) ||
declaration->isVisibleViaContractTypeAccess()

View File

@ -0,0 +1,14 @@
abstract contract I
{
function a() internal view virtual returns(uint256);
}
abstract contract V is I
{
function b() public view returns(uint256) { return a(); }
}
contract C is V
{
function a() internal view override returns (uint256) { return 42;}
}
// ----
// b() -> 42

View File

@ -0,0 +1,8 @@
abstract contract I
{
function a() internal view virtual returns(uint256);
}
abstract contract V is I
{
function b() public view returns(uint256) { return a(); }
}