Skip to content

Commit 6c36638

Browse files
authored
Merge pull request #12616 from ethereum/missingOverrideRequirement
Fix missing override errors when indirectly inheriting interfaces.
2 parents 7c0ac95 + c47da51 commit 6c36638

9 files changed

+131
-3
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Bugfixes:
1919
* Control Flow Graph: Perform proper virtual lookup for modifiers for uninitialized variable and unreachable code analysis.
2020
* General: ``string.concat`` now properly takes strings as arguments and returns ``string memory``. It was accidentally introduced as a copy of ``bytes.concat`` before.
2121
* Immutables: Fix wrong error when the constructor of a base contract uses ``return`` and the derived contract contains immutable variables.
22+
* Inheritance: Consider functions in all ancestors during override analysis.
2223
* IR Generator: Add missing cleanup during the conversion of fixed bytes types to smaller fixed bytes types.
2324
* IR Generator: Add missing cleanup for indexed event arguments of value type.
2425
* IR Generator: Fix internal error when copying reference types in calldata and storage to struct or array members in memory.

libsolidity/analysis/OverrideChecker.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -897,10 +897,11 @@ OverrideChecker::OverrideProxyBySignatureMultiSet const& OverrideChecker::inheri
897897
if (var->isPublic())
898898
functionsInBase.emplace(OverrideProxy{var});
899899

900-
for (OverrideProxy const& func: inheritedFunctions(*base))
901-
functionsInBase.insert(func);
902-
903900
result += functionsInBase;
901+
902+
for (OverrideProxy const& func: inheritedFunctions(*base))
903+
if (!functionsInBase.count(func))
904+
result.insert(func);
904905
}
905906

906907
m_inheritedFunctions[&_contract] = result;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
interface IBase {
2+
function foo() external view;
3+
}
4+
5+
contract Base is IBase {
6+
function foo() public virtual view {}
7+
}
8+
9+
interface IExt is IBase {}
10+
11+
contract Ext is IExt, Base {}
12+
13+
contract T { function foo() public virtual view {} }
14+
15+
contract Impl is Ext, T {
16+
function foo() public view override(IBase, Base, T) {}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
abstract contract IBase {
2+
function foo() external view virtual;
3+
}
4+
5+
contract Base is IBase {
6+
function foo() public virtual override view {}
7+
}
8+
9+
abstract contract IExt is IBase {}
10+
11+
contract Ext is IExt, Base {}
12+
13+
contract T { function foo() public virtual view {} }
14+
15+
contract Impl is Ext, T {
16+
function foo() public view override(IBase, Base, T) {}
17+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
interface IBase {
2+
function foo() external view;
3+
}
4+
5+
contract Base is IBase {
6+
function foo() public virtual view {}
7+
}
8+
9+
interface IExt is IBase {}
10+
11+
contract Ext is IExt, Base {}
12+
13+
contract Impl is Ext {
14+
function foo() public view {}
15+
}
16+
// ----
17+
// TypeError 9456: (211-240): Overriding function is missing "override" specifier.
18+
// TypeError 4327: (211-240): Function needs to specify overridden contracts "Base" and "IBase".
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
interface IBase {
2+
function foo() external view;
3+
}
4+
5+
contract Base is IBase {
6+
function foo() public virtual view {}
7+
}
8+
9+
interface IExt is IBase {}
10+
11+
contract Ext is IExt, Base {}
12+
13+
contract Impl is Ext {
14+
function foo() public view override (IBase, Base) {}
15+
}
16+
// ----
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
interface IBase {
2+
function foo() external view;
3+
}
4+
5+
contract Base1 is IBase { function foo() public virtual view {} }
6+
contract Base2 is IBase { function foo() public virtual view {} }
7+
8+
interface IExt1a is IBase {}
9+
interface IExt1b is IBase {}
10+
interface IExt2a is IBase {}
11+
interface IExt2b is IBase {}
12+
13+
contract Ext1 is IExt1a, IExt1b, Base1 {}
14+
contract Ext2 is IExt2a, IExt2b, Base2 {}
15+
16+
contract Impl is Ext1, Ext2 {
17+
function foo() public view {}
18+
}
19+
// ----
20+
// TypeError 9456: (424-453): Overriding function is missing "override" specifier.
21+
// TypeError 9456: (424-453): Overriding function is missing "override" specifier.
22+
// TypeError 4327: (424-453): Function needs to specify overridden contracts "Base1", "Base2" and "IBase".
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
interface IBase {
2+
function foo() external view;
3+
}
4+
5+
contract Base1 is IBase { function foo() public virtual view {} }
6+
contract Base2 is IBase { function foo() public virtual view {} }
7+
8+
interface IExt1a is IBase {}
9+
interface IExt1b is IBase {}
10+
interface IExt2a is IBase {}
11+
interface IExt2b is IBase {}
12+
13+
contract Ext1 is IExt1a, IExt1b, Base1 {}
14+
contract Ext2 is IExt2a, IExt2b, Base2 {}
15+
16+
contract Impl is Ext1, Ext2 {
17+
function foo() public view override (IBase, Base1, Base2) {}
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
interface IBase {
2+
function foo() external view;
3+
}
4+
5+
contract Base1 is IBase { function foo() public virtual view {} }
6+
contract Base2 is IBase { function foo() public virtual view {} }
7+
8+
interface IExt1a is IBase {}
9+
abstract contract IExt1b is IBase {}
10+
abstract contract IExt2a is IBase {}
11+
interface IExt2b is IBase {}
12+
13+
contract Ext1 is IExt1a, IExt1b, Base1 {}
14+
contract Ext2 is IExt2a, IExt2b, Base2 {}
15+
16+
contract Impl is Ext1, Ext2 {
17+
function foo() public view override (IBase, Base1, Base2) {}
18+
}

0 commit comments

Comments
 (0)