Skip to content

Commit bc74f07

Browse files
Reports an error on unimplemented modifiers in a function definition.
1 parent 8de575f commit bc74f07

File tree

7 files changed

+77
-16
lines changed

7 files changed

+77
-16
lines changed

Changelog.md

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

3536

3637
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: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -629,16 +629,31 @@ 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+
!m_currentContract->abstract()
647+
)
634648
{
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-
);
649+
m_errorReporter.typeError(
650+
9113_error,
651+
_modifier.location(),
652+
"Cannot call unimplemented modifier."
653+
);
641654
}
655+
}
656+
642657
}
643658
else
644659
// 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: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
pragma solidity >= 0.5.0;
2+
3+
contract A {
4+
modifier m() virtual { _; }
5+
}
6+
abstract contract B {
7+
modifier m() virtual;
8+
}
9+
contract C is A, B {
10+
modifier m() override(A, B) { _; }
11+
function f() B.m public {}
12+
}
13+
// ----
14+
// TypeError 9113: (240-243): Cannot call unimplemented modifier.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
pragma solidity >= 0.5.0;
2+
3+
abstract contract A {
4+
modifier m() virtual;
5+
}
6+
contract B is A {
7+
modifier m() virtual override { _; }
8+
}
9+
contract C is B {
10+
function f() A.m public {}
11+
}
12+
// ----
13+
// TypeError 9113: (212-215): Cannot call unimplemented modifier.

0 commit comments

Comments
 (0)