Allow derived->base conversions with compatible qualifiers (#7415)

Move the existing derived->base conversion earlier in
`PerformBuiltinConversion`, into the block that handles qualifier
conversions. This allows, for example, converting from `partial Derived`
to `partial Base` -- see the tests in
`toolchain/check/testdata/class/inheritance/derived_to_base.carbon`.
This commit is contained in:
Nicholas Bishop
2026-06-24 21:08:24 +00:00
committed by GitHub
parent f2d99f31f0
commit 885b1110d5
20 changed files with 345 additions and 288 deletions
@@ -75,8 +75,8 @@ fn Call(b: Cpp.B*) {
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define void @_CConvertVal.Main(ptr %b) #0 !dbg !18 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc13_13.1.base = getelementptr inbounds nuw [8 x i8], ptr %b, i32 0, i32 0, !dbg !23
// CHECK:STDOUT: call void @_CAcceptVal.Main(ptr %.loc13_13.1.base), !dbg !24
// CHECK:STDOUT: %.loc13_13.2.a = getelementptr inbounds nuw [4 x i8], ptr %b, i32 0, i32 0, !dbg !23
// CHECK:STDOUT: call void @_CAcceptVal.Main(ptr %.loc13_13.2.a), !dbg !24
// CHECK:STDOUT: ret void, !dbg !25
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -120,10 +120,10 @@ fn Call(b: Cpp.B*) {
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define i32 @_CAccessVal.Main(ptr %b) #0 !dbg !11 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc7_11.1.base = getelementptr inbounds nuw [8 x i8], ptr %b, i32 0, i32 0, !dbg !18
// CHECK:STDOUT: %.loc7_11.3.a = getelementptr inbounds nuw [4 x i8], ptr %.loc7_11.1.base, i32 0, i32 0, !dbg !18
// CHECK:STDOUT: %.loc7_11.4 = load i32, ptr %.loc7_11.3.a, align 4, !dbg !18
// CHECK:STDOUT: ret i32 %.loc7_11.4, !dbg !19
// CHECK:STDOUT: %.loc7_11.2.a = getelementptr inbounds nuw [4 x i8], ptr %b, i32 0, i32 0, !dbg !18
// CHECK:STDOUT: %.loc7_11.4.a = getelementptr inbounds nuw [4 x i8], ptr %.loc7_11.2.a, i32 0, i32 0, !dbg !18
// CHECK:STDOUT: %.loc7_11.5 = load i32, ptr %.loc7_11.4.a, align 4, !dbg !18
// CHECK:STDOUT: ret i32 %.loc7_11.5, !dbg !19
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: attributes #0 = { nounwind }
@@ -162,8 +162,8 @@ fn Call(b: Cpp.B*) {
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define void @_CCall.Main(ptr %b) #0 !dbg !11 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc7_4.2.base = getelementptr inbounds nuw [8 x i8], ptr %b, i32 0, i32 0, !dbg !17
// CHECK:STDOUT: call void @_ZN1A1fEv(ptr %.loc7_4.2.base), !dbg !17
// CHECK:STDOUT: %.loc7_4.3.a = getelementptr inbounds nuw [4 x i8], ptr %b, i32 0, i32 0, !dbg !17
// CHECK:STDOUT: call void @_ZN1A1fEv(ptr %.loc7_4.3.a), !dbg !17
// CHECK:STDOUT: ret void, !dbg !18
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -111,8 +111,8 @@ fn DoThing() {
// CHECK:STDOUT: %.loc31_44.8.base = getelementptr inbounds nuw [16 x i8], ptr %.loc31_44.7.base, i32 0, i32 0, !dbg !33
// CHECK:STDOUT: %.loc31_44.9.vptr = getelementptr inbounds nuw [8 x i8], ptr %.loc31_44.8.base, i32 0, i32 0, !dbg !33
// CHECK:STDOUT: store ptr getelementptr inbounds inrange(-16, 24) ({ [5 x ptr] }, ptr @_ZTVN6Carbon7DerivedE, i32 0, i32 0, i32 2), ptr %.loc31_44.9.vptr, align 8, !dbg !33
// CHECK:STDOUT: %.loc32_11.2.base = getelementptr inbounds nuw { [16 x i8] }, ptr %d.var, i32 0, i32 0, !dbg !35
// CHECK:STDOUT: call void @_Z3UseR4Base(ptr %.loc32_11.2.base), !dbg !36
// CHECK:STDOUT: %.loc32_11.3.base = getelementptr inbounds nuw [16 x i8], ptr %d.var, i32 0, i32 0, !dbg !35
// CHECK:STDOUT: call void @_Z3UseR4Base(ptr %.loc32_11.3.base), !dbg !36
// CHECK:STDOUT: call void @"_COp.8185e3504351afa8:core.Destroy.Core"(ptr %d.var), !dbg !32
// CHECK:STDOUT: ret void, !dbg !37
// CHECK:STDOUT: }
@@ -262,11 +262,11 @@ fn F(ref r: Cpp.A) {
// CHECK:STDOUT: ; Function Attrs: nounwind
// CHECK:STDOUT: define void @_CUseVal.Main(ptr %a) #0 !dbg !11 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc7_4.2.base = getelementptr inbounds nuw [16 x i8], ptr %a, i32 0, i32 0, !dbg !17
// CHECK:STDOUT: %Base.virt0.call.vtable = load ptr, ptr %.loc7_4.2.base, align 8, !dbg !17
// CHECK:STDOUT: %.loc7_4.3.vptr = getelementptr inbounds nuw [8 x i8], ptr %a, i32 0, i32 0, !dbg !17
// CHECK:STDOUT: %Base.virt0.call.vtable = load ptr, ptr %.loc7_4.3.vptr, align 8, !dbg !17
// CHECK:STDOUT: %Base.virt0.call = getelementptr ptr, ptr %Base.virt0.call.vtable, i32 0, !dbg !17
// CHECK:STDOUT: %Base.virt0.call.memptr.virtualfn = load ptr, ptr %Base.virt0.call, align 8, !dbg !17
// CHECK:STDOUT: call void %Base.virt0.call.memptr.virtualfn(ptr %.loc7_4.2.base), !dbg !17
// CHECK:STDOUT: call void %Base.virt0.call.memptr.virtualfn(ptr %.loc7_4.3.vptr), !dbg !17
// CHECK:STDOUT: %A.virt1.call.vtable = load ptr, ptr %a, align 8, !dbg !18
// CHECK:STDOUT: %A.virt1.call = getelementptr ptr, ptr %A.virt1.call.vtable, i32 1, !dbg !18
// CHECK:STDOUT: %A.virt1.call.memptr.virtualfn = load ptr, ptr %A.virt1.call, align 8, !dbg !18