Skip to content

Commit cfb4616

Browse files
authored
fix: Properly handle override keyword in multilevel inherit (#2449)
1 parent 5ab63fa commit cfb4616

File tree

4 files changed

+378
-89
lines changed

4 files changed

+378
-89
lines changed

Diff for: src/program.ts

+38-8
Original file line numberDiff line numberDiff line change
@@ -1367,6 +1367,41 @@ export class Program extends DiagnosticEmitter {
13671367
}
13681368
}
13691369

1370+
// check override
1371+
for (let i = 0, k = queuedExtends.length; i < k; i++) {
1372+
let prototype = queuedExtends[i];
1373+
let instanesMembers = prototype.instanceMembers;
1374+
if (instanesMembers) {
1375+
let members = Map_values(instanesMembers);
1376+
for (let j = 0, k = members.length; j < k; j++) {
1377+
let member = members[j];
1378+
let declaration = member.declaration;
1379+
if (declaration.is(CommonFlags.OVERRIDE)) {
1380+
let basePrototype = prototype.basePrototype;
1381+
let hasOverride = false;
1382+
while (basePrototype) {
1383+
let instanceMembers = basePrototype.instanceMembers;
1384+
if (instanceMembers) {
1385+
if (instanceMembers.has(member.name)) {
1386+
hasOverride = true;
1387+
break;
1388+
}
1389+
}
1390+
basePrototype = basePrototype.basePrototype;
1391+
}
1392+
if (!hasOverride) {
1393+
let basePrototype = assert(prototype.basePrototype);
1394+
this.error(
1395+
DiagnosticCode.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0,
1396+
declaration.name.range,
1397+
basePrototype.name
1398+
);
1399+
}
1400+
}
1401+
}
1402+
}
1403+
}
1404+
13701405
// resolve prototypes of implemented interfaces
13711406
for (let i = 0, k = queuedImplements.length; i < k; ++i) {
13721407
let thisPrototype = queuedImplements[i];
@@ -1468,11 +1503,12 @@ export class Program extends DiagnosticEmitter {
14681503
// TODO: make this work with interfaaces as well
14691504
var thisInstanceMembers = thisPrototype.instanceMembers;
14701505
if (thisInstanceMembers) {
1506+
let thisMembers = Map_values(thisInstanceMembers);
14711507
do {
14721508
let baseInstanceMembers = basePrototype.instanceMembers;
14731509
if (baseInstanceMembers) {
1474-
for (let _values = Map_values(thisInstanceMembers), j = 0, l = _values.length; j < l; ++j) {
1475-
let thisMember = _values[j];
1510+
for (let j = 0, l = thisMembers.length; j < l; ++j) {
1511+
let thisMember = thisMembers[j];
14761512
if (
14771513
!thisMember.isAny(CommonFlags.CONSTRUCTOR | CommonFlags.PRIVATE) &&
14781514
baseInstanceMembers.has(thisMember.name)
@@ -1550,12 +1586,6 @@ export class Program extends DiagnosticEmitter {
15501586
}
15511587
}
15521588
}
1553-
if (thisMember.is(CommonFlags.OVERRIDE) && !baseInstanceMembers.has(thisMember.name)) {
1554-
this.error(
1555-
DiagnosticCode.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0,
1556-
thisMember.identifierNode.range, basePrototype.name
1557-
);
1558-
}
15591589
}
15601590
}
15611591
let nextPrototype = basePrototype.basePrototype;

Diff for: tests/compiler/class-overloading-cast.debug.wat

+166-28
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
(type $i32_i32_i32_=>_i32 (func (param i32 i32 i32) (result i32)))
1111
(type $none_=>_i32 (func (result i32)))
1212
(type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32)))
13+
(type $i32_f32_=>_i32 (func (param i32 f32) (result i32)))
1314
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
1415
(global $~lib/rt/itcms/total (mut i32) (i32.const 0))
1516
(global $~lib/rt/itcms/threshold (mut i32) (i32.const 0))
@@ -30,10 +31,10 @@
3031
(global $class-overloading-cast/v3 (mut i32) (i32.const 0))
3132
(global $~lib/native/ASC_SHRINK_LEVEL i32 (i32.const 0))
3233
(global $class-overloading-cast/c (mut i32) (i32.const 0))
33-
(global $~lib/rt/__rtti_base i32 (i32.const 592))
34-
(global $~lib/memory/__data_end i32 (i32.const 676))
35-
(global $~lib/memory/__stack_pointer (mut i32) (i32.const 17060))
36-
(global $~lib/memory/__heap_base i32 (i32.const 17060))
34+
(global $~lib/rt/__rtti_base i32 (i32.const 624))
35+
(global $~lib/memory/__data_end i32 (i32.const 732))
36+
(global $~lib/memory/__stack_pointer (mut i32) (i32.const 17116))
37+
(global $~lib/memory/__heap_base i32 (i32.const 17116))
3738
(global $~started (mut i32) (i32.const 0))
3839
(memory $0 1)
3940
(data (i32.const 12) "<\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00(\00\00\00A\00l\00l\00o\00c\00a\00t\00i\00o\00n\00 \00t\00o\00o\00 \00l\00a\00r\00g\00e\00\00\00\00\00")
@@ -48,7 +49,8 @@
4849
(data (i32.const 444) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00B\00\00\00\00\00\00\00\00\00\00\00")
4950
(data (i32.const 476) "L\00\00\00\00\00\00\00\00\00\00\00\01\00\00\002\00\00\00c\00l\00a\00s\00s\00-\00o\00v\00e\00r\00l\00o\00a\00d\00i\00n\00g\00-\00c\00a\00s\00t\00.\00t\00s\00\00\00\00\00\00\00\00\00\00\00")
5051
(data (i32.const 556) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00a\00\00\00\00\00\00\00\00\00\00\00")
51-
(data (i32.const 592) "\n\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\04\00\00\00 \00\00\00\00\00\00\00 \00\00\00\04\00\00\00 \00\00\00\07\00\00\00 \00\00\00\00\00\00\00 \00\00\00\t\00\00\00 \00\00\00\00\00\00\00")
52+
(data (i32.const 588) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\02\00\00\00D\00\00\00\00\00\00\00\00\00\00\00")
53+
(data (i32.const 624) "\0d\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\04\00\00\00 \00\00\00\00\00\00\00 \00\00\00\04\00\00\00 \00\00\00\07\00\00\00 \00\00\00\00\00\00\00 \00\00\00\t\00\00\00 \00\00\00\00\00\00\00 \00\00\00\0b\00\00\00 \00\00\00\0c\00\00\00 \00\00\00\00\00\00\00")
5254
(table $0 1 1 funcref)
5355
(elem $0 (i32.const 1))
5456
(export "memory" (memory $0))
@@ -2292,6 +2294,9 @@
22922294
(func $class-overloading-cast/A<~lib/string/String>#foo (param $this i32) (param $a i32) (result i32)
22932295
i32.const 432
22942296
)
2297+
(func $class-overloading-cast/D#bar (param $this i32) (param $a f32) (result i32)
2298+
i32.const 608
2299+
)
22952300
(func $class-overloading-cast/B<i32,f64>#foo (param $this i32) (param $a i32) (result i32)
22962301
i32.const 464
22972302
)
@@ -2417,29 +2422,38 @@
24172422
)
24182423
(func $~lib/rt/__visit_members (param $0 i32) (param $1 i32)
24192424
block $invalid
2420-
block $class-overloading-cast/A<~lib/string/String>
2421-
block $class-overloading-cast/C
2422-
block $class-overloading-cast/A<f64>
2423-
block $class-overloading-cast/B<f64,~lib/string/String>
2424-
block $class-overloading-cast/B<i32,~lib/string/String>
2425-
block $class-overloading-cast/A<i32>
2426-
block $class-overloading-cast/B<i32,f64>
2427-
block $~lib/arraybuffer/ArrayBufferView
2428-
block $~lib/string/String
2429-
block $~lib/arraybuffer/ArrayBuffer
2425+
block $class-overloading-cast/A<f32>
2426+
block $class-overloading-cast/B<f32,f64>
2427+
block $class-overloading-cast/D
2428+
block $class-overloading-cast/A<~lib/string/String>
2429+
block $class-overloading-cast/C
2430+
block $class-overloading-cast/A<f64>
2431+
block $class-overloading-cast/B<f64,~lib/string/String>
2432+
block $class-overloading-cast/B<i32,~lib/string/String>
2433+
block $class-overloading-cast/A<i32>
2434+
block $class-overloading-cast/B<i32,f64>
2435+
block $~lib/arraybuffer/ArrayBufferView
2436+
block $~lib/string/String
2437+
block $~lib/arraybuffer/ArrayBuffer
2438+
local.get $0
2439+
i32.const 8
2440+
i32.sub
2441+
i32.load $0
2442+
br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $class-overloading-cast/B<i32,f64> $class-overloading-cast/A<i32> $class-overloading-cast/B<i32,~lib/string/String> $class-overloading-cast/B<f64,~lib/string/String> $class-overloading-cast/A<f64> $class-overloading-cast/C $class-overloading-cast/A<~lib/string/String> $class-overloading-cast/D $class-overloading-cast/B<f32,f64> $class-overloading-cast/A<f32> $invalid
2443+
end
2444+
return
2445+
end
2446+
return
2447+
end
24302448
local.get $0
2431-
i32.const 8
2432-
i32.sub
2433-
i32.load $0
2434-
br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $class-overloading-cast/B<i32,f64> $class-overloading-cast/A<i32> $class-overloading-cast/B<i32,~lib/string/String> $class-overloading-cast/B<f64,~lib/string/String> $class-overloading-cast/A<f64> $class-overloading-cast/C $class-overloading-cast/A<~lib/string/String> $invalid
2449+
local.get $1
2450+
call $~lib/arraybuffer/ArrayBufferView~visit
2451+
return
24352452
end
24362453
return
24372454
end
24382455
return
24392456
end
2440-
local.get $0
2441-
local.get $1
2442-
call $~lib/arraybuffer/ArrayBufferView~visit
24432457
return
24442458
end
24452459
return
@@ -2472,8 +2486,8 @@
24722486
global.get $~lib/memory/__data_end
24732487
i32.lt_s
24742488
if
2475-
i32.const 17088
24762489
i32.const 17136
2490+
i32.const 17184
24772491
i32.const 1
24782492
i32.const 1
24792493
call $~lib/builtins/abort
@@ -2543,7 +2557,7 @@
25432557
if
25442558
i32.const 0
25452559
i32.const 496
2546-
i32.const 17
2560+
i32.const 26
25472561
i32.const 1
25482562
call $~lib/builtins/abort
25492563
unreachable
@@ -2572,7 +2586,7 @@
25722586
if
25732587
i32.const 0
25742588
i32.const 496
2575-
i32.const 18
2589+
i32.const 27
25762590
i32.const 1
25772591
call $~lib/builtins/abort
25782592
unreachable
@@ -2601,7 +2615,7 @@
26012615
if
26022616
i32.const 0
26032617
i32.const 496
2604-
i32.const 19
2618+
i32.const 28
26052619
i32.const 1
26062620
call $~lib/builtins/abort
26072621
unreachable
@@ -2638,7 +2652,7 @@
26382652
if
26392653
i32.const 0
26402654
i32.const 496
2641-
i32.const 23
2655+
i32.const 32
26422656
i32.const 1
26432657
call $~lib/builtins/abort
26442658
unreachable
@@ -2672,7 +2686,37 @@
26722686
if
26732687
i32.const 0
26742688
i32.const 496
2675-
i32.const 24
2689+
i32.const 33
2690+
i32.const 1
2691+
call $~lib/builtins/abort
2692+
unreachable
2693+
end
2694+
i32.const 0
2695+
call $class-overloading-cast/D#constructor
2696+
local.set $0
2697+
global.get $~lib/memory/__stack_pointer
2698+
local.get $0
2699+
i32.store $0 offset=8
2700+
local.get $0
2701+
f32.const 2.5
2702+
call $class-overloading-cast/D#bar
2703+
local.set $0
2704+
global.get $~lib/memory/__stack_pointer
2705+
local.get $0
2706+
i32.store $0
2707+
local.get $0
2708+
i32.const 608
2709+
local.set $0
2710+
global.get $~lib/memory/__stack_pointer
2711+
local.get $0
2712+
i32.store $0 offset=4
2713+
local.get $0
2714+
call $~lib/string/String.__eq
2715+
i32.eqz
2716+
if
2717+
i32.const 0
2718+
i32.const 496
2719+
i32.const 35
26762720
i32.const 1
26772721
call $~lib/builtins/abort
26782722
unreachable
@@ -2898,4 +2942,98 @@
28982942
global.set $~lib/memory/__stack_pointer
28992943
local.get $1
29002944
)
2945+
(func $class-overloading-cast/A<f32>#constructor (param $0 i32) (result i32)
2946+
(local $1 i32)
2947+
global.get $~lib/memory/__stack_pointer
2948+
i32.const 4
2949+
i32.sub
2950+
global.set $~lib/memory/__stack_pointer
2951+
call $~stack_check
2952+
global.get $~lib/memory/__stack_pointer
2953+
i32.const 0
2954+
i32.store $0
2955+
local.get $0
2956+
i32.eqz
2957+
if
2958+
global.get $~lib/memory/__stack_pointer
2959+
i32.const 0
2960+
i32.const 12
2961+
call $~lib/rt/itcms/__new
2962+
local.tee $0
2963+
i32.store $0
2964+
end
2965+
local.get $0
2966+
local.set $1
2967+
global.get $~lib/memory/__stack_pointer
2968+
i32.const 4
2969+
i32.add
2970+
global.set $~lib/memory/__stack_pointer
2971+
local.get $1
2972+
)
2973+
(func $class-overloading-cast/B<f32,f64>#constructor (param $0 i32) (result i32)
2974+
(local $1 i32)
2975+
global.get $~lib/memory/__stack_pointer
2976+
i32.const 4
2977+
i32.sub
2978+
global.set $~lib/memory/__stack_pointer
2979+
call $~stack_check
2980+
global.get $~lib/memory/__stack_pointer
2981+
i32.const 0
2982+
i32.store $0
2983+
local.get $0
2984+
i32.eqz
2985+
if
2986+
global.get $~lib/memory/__stack_pointer
2987+
i32.const 0
2988+
i32.const 11
2989+
call $~lib/rt/itcms/__new
2990+
local.tee $0
2991+
i32.store $0
2992+
end
2993+
global.get $~lib/memory/__stack_pointer
2994+
local.get $0
2995+
call $class-overloading-cast/A<f32>#constructor
2996+
local.tee $0
2997+
i32.store $0
2998+
local.get $0
2999+
local.set $1
3000+
global.get $~lib/memory/__stack_pointer
3001+
i32.const 4
3002+
i32.add
3003+
global.set $~lib/memory/__stack_pointer
3004+
local.get $1
3005+
)
3006+
(func $class-overloading-cast/D#constructor (param $0 i32) (result i32)
3007+
(local $1 i32)
3008+
global.get $~lib/memory/__stack_pointer
3009+
i32.const 4
3010+
i32.sub
3011+
global.set $~lib/memory/__stack_pointer
3012+
call $~stack_check
3013+
global.get $~lib/memory/__stack_pointer
3014+
i32.const 0
3015+
i32.store $0
3016+
local.get $0
3017+
i32.eqz
3018+
if
3019+
global.get $~lib/memory/__stack_pointer
3020+
i32.const 0
3021+
i32.const 10
3022+
call $~lib/rt/itcms/__new
3023+
local.tee $0
3024+
i32.store $0
3025+
end
3026+
global.get $~lib/memory/__stack_pointer
3027+
local.get $0
3028+
call $class-overloading-cast/B<f32,f64>#constructor
3029+
local.tee $0
3030+
i32.store $0
3031+
local.get $0
3032+
local.set $1
3033+
global.get $~lib/memory/__stack_pointer
3034+
i32.const 4
3035+
i32.add
3036+
global.set $~lib/memory/__stack_pointer
3037+
local.get $1
3038+
)
29013039
)

0 commit comments

Comments
 (0)