Skip to content

Commit bca764a

Browse files
Reports an error on unimplemented modifiers in a function definition.
1 parent 215bbe2 commit bca764a

File tree

7 files changed

+78
-16
lines changed

7 files changed

+78
-16
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Bugfixes:
3030
* Type Checker: Fix internal compiler error when attempting to use an invalid external function type on pre-byzantium EVMs.
3131
* Type Checker: Make errors about (nested) mapping type in event or error parameter into fatal type errors.
3232
* Type Checker: Fix internal compiler error when overriding receive ether function with one having different parameters during inheritance.
33+
* Type Checker: Fix internal compiler error when overriding an implemented modifier with an unimplemented one.
3334

3435

3536
AST Changes:

libsolidity/analysis/OverrideChecker.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,19 @@ void OverrideChecker::checkOverride(OverrideProxy const& _overriding, OverridePr
573573
);
574574
}
575575

576+
if (_overriding.unimplemented() && !_super.unimplemented())
577+
{
578+
solAssert(!_overriding.isVariable() || !_overriding.unimplemented(), "");
579+
overrideError(
580+
_overriding,
581+
_super,
582+
4593_error,
583+
"Overriding an implemented " + _super.astNodeName() +
584+
" with an unimplemented " + _overriding.astNodeName() +
585+
" is not allowed."
586+
);
587+
}
588+
576589
if (_super.isFunction())
577590
{
578591
FunctionType const* functionType = _overriding.functionType();
@@ -613,14 +626,6 @@ void OverrideChecker::checkOverride(OverrideProxy const& _overriding, OverridePr
613626
stateMutabilityToString(_overriding.stateMutability()) +
614627
"\"."
615628
);
616-
617-
if (_overriding.unimplemented() && !_super.unimplemented())
618-
overrideError(
619-
_overriding,
620-
_super,
621-
4593_error,
622-
"Overriding an implemented function with an unimplemented function is not allowed."
623-
);
624629
}
625630
}
626631

libsolidity/analysis/TypeChecker.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -629,16 +629,30 @@ void TypeChecker::visitManually(
629629
if (auto modifierDecl = dynamic_cast<ModifierDefinition const*>(declaration))
630630
{
631631
parameters = &modifierDecl->parameters();
632-
if (auto const* modifierContract = dynamic_cast<ContractDefinition const*>(modifierDecl->scope()))
633-
if (m_currentContract)
632+
solAssert(modifierDecl->annotation().contract, "");
633+
auto const* modifierContract = dynamic_cast<ContractDefinition const*>(modifierDecl->scope());
634+
solAssert(modifierContract, "");
635+
if (m_currentContract)
636+
{
637+
if (!contains(m_currentContract->annotation().linearizedBaseContracts, modifierContract))
638+
m_errorReporter.typeError(
639+
9428_error,
640+
_modifier.location(),
641+
"Can only use modifiers defined in the current contract or in base contracts."
642+
);
643+
644+
if (m_currentContract->derivesFrom(*modifierDecl->annotation().contract) &&
645+
!modifierDecl->isImplemented()
646+
)
634647
{
635-
if (!contains(m_currentContract->annotation().linearizedBaseContracts, modifierContract))
636-
m_errorReporter.typeError(
637-
9428_error,
638-
_modifier.location(),
639-
"Can only use modifiers defined in the current contract or in base contracts."
640-
);
648+
m_errorReporter.typeError(
649+
9113_error,
650+
_modifier.location(),
651+
"Cannot call unimplemented modifier."
652+
);
641653
}
654+
}
655+
642656
}
643657
else
644658
// check parameters for Base constructors

test/libsolidity/syntaxTests/inheritance/virtual/modifier_virtual_err.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ library test {
55
}
66
// ----
77
// TypeError 3275: (19-38): Modifiers in a library cannot be virtual.
8+
// TypeError 9113: (56-57): Cannot call unimplemented modifier.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
contract A {
2+
modifier m() virtual { _; }
3+
}
4+
abstract contract B is A {
5+
modifier m() virtual override;
6+
}
7+
contract C is B {
8+
function f() m public {}
9+
}
10+
// ----
11+
// TypeError 4593: (78-108): Overriding an implemented modifier with an unimplemented modifier is not allowed.
12+
// TypeError 9113: (146-147): Cannot call unimplemented modifier.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity >= 0.5.0;
3+
4+
contract A {
5+
modifier m() virtual { _; }
6+
}
7+
abstract contract B {
8+
modifier m() virtual;
9+
}
10+
contract C is A, B {
11+
modifier m() override(A, B) { _; }
12+
function f() B.m public {}
13+
}
14+
// ----
15+
// TypeError 9113: (240-243): Cannot call unimplemented modifier.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity >= 0.5.0;
3+
4+
abstract contract A {
5+
modifier m() virtual;
6+
}
7+
contract B is A {
8+
modifier m() virtual override { _; }
9+
}
10+
contract C is B {
11+
function f() A.m public {}
12+
}
13+
// ----
14+
// TypeError 9113: (212-215): Cannot call unimplemented modifier.

0 commit comments

Comments
 (0)