Files
carbon-lang/toolchain/check/testdata/class/virtual_modifiers.carbon
T
David Blaikie d79a374ad4 Skip vptr when performing object initialization (#4490)
The cehck for vptr could be done differently (is this class dynamic and
its base class non-dynamic), and if we change the layout (to put the
vptr after any base) then this code will break (could add an assertion
that the vptr isn't present apart from at the start of the field list if
that'd seem worthwhile).

There's still later issues with lowering (if this patch causes crashes
in lowering, do they result in fuzz failures/need to be avoided before
this change is submitted?)
2024-11-06 18:27:40 +00:00

249 lines
10 KiB
Plaintext

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/virtual_modifiers.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/virtual_modifiers.carbon
// --- modifiers.carbon
package Modifiers;
base class Base {
virtual fn H();
impl fn I();
}
abstract class Abstract {
abstract fn J();
virtual fn K();
impl fn L();
}
// --- todo_fail_later_base.carbon
package FailLaterBase;
import Modifiers;
base class Derived {
virtual fn F();
extend base: Modifiers.Base;
}
// --- init.carbon
package Init;
import Modifiers;
fn F() {
var v: Modifiers.Base = {};
}
// CHECK:STDOUT: --- modifiers.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Base: type = class_type @Base [template]
// CHECK:STDOUT: %H.type: type = fn_type @H [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %H: %H.type = struct_value () [template]
// CHECK:STDOUT: %I.type: type = fn_type @I [template]
// CHECK:STDOUT: %I: %I.type = struct_value () [template]
// CHECK:STDOUT: %.2: type = ptr_type <vtable> [template]
// CHECK:STDOUT: %.3: type = struct_type {.<vptr>: %.2} [template]
// CHECK:STDOUT: %.4: <witness> = complete_type_witness %.3 [template]
// CHECK:STDOUT: %Abstract: type = class_type @Abstract [template]
// CHECK:STDOUT: %J.type: type = fn_type @J [template]
// CHECK:STDOUT: %J: %J.type = struct_value () [template]
// CHECK:STDOUT: %K.type: type = fn_type @K [template]
// CHECK:STDOUT: %K: %K.type = struct_value () [template]
// CHECK:STDOUT: %L.type: type = fn_type @L [template]
// CHECK:STDOUT: %L: %L.type = struct_value () [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .Base = %Base.decl
// CHECK:STDOUT: .Abstract = %Abstract.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %Base.decl: type = class_decl @Base [template = constants.%Base] {} {}
// CHECK:STDOUT: %Abstract.decl: type = class_decl @Abstract [template = constants.%Abstract] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Base {
// CHECK:STDOUT: %H.decl: %H.type = fn_decl @H [template = constants.%H] {} {}
// CHECK:STDOUT: %I.decl: %I.type = fn_decl @I [template = constants.%I] {} {}
// CHECK:STDOUT: %.loc8: <witness> = complete_type_witness %.3 [template = constants.%.4]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Base
// CHECK:STDOUT: .H = %H.decl
// CHECK:STDOUT: .I = %I.decl
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Abstract {
// CHECK:STDOUT: %J.decl: %J.type = fn_decl @J [template = constants.%J] {} {}
// CHECK:STDOUT: %K.decl: %K.type = fn_decl @K [template = constants.%K] {} {}
// CHECK:STDOUT: %L.decl: %L.type = fn_decl @L [template = constants.%L] {} {}
// CHECK:STDOUT: %.loc16: <witness> = complete_type_witness %.3 [template = constants.%.4]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Abstract
// CHECK:STDOUT: .J = %J.decl
// CHECK:STDOUT: .K = %K.decl
// CHECK:STDOUT: .L = %L.decl
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: virtual fn @H();
// CHECK:STDOUT:
// CHECK:STDOUT: impl fn @I();
// CHECK:STDOUT:
// CHECK:STDOUT: abstract fn @J();
// CHECK:STDOUT:
// CHECK:STDOUT: virtual fn @K();
// CHECK:STDOUT:
// CHECK:STDOUT: impl fn @L();
// CHECK:STDOUT:
// CHECK:STDOUT: --- todo_fail_later_base.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Derived: type = class_type @Derived [template]
// CHECK:STDOUT: %F.type: type = fn_type @F [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %F: %F.type = struct_value () [template]
// CHECK:STDOUT: %Base: type = class_type @Base [template]
// CHECK:STDOUT: %.2: type = ptr_type <vtable> [template]
// CHECK:STDOUT: %.3: type = struct_type {.<vptr>: %.2} [template]
// CHECK:STDOUT: %.4: <witness> = complete_type_witness %.3 [template]
// CHECK:STDOUT: %.5: type = ptr_type %.3 [template]
// CHECK:STDOUT: %.6: type = unbound_element_type %Derived, %Base [template]
// CHECK:STDOUT: %.7: type = struct_type {.<vptr>: %.2, .base: %Base} [template]
// CHECK:STDOUT: %.8: <witness> = complete_type_witness %.7 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Modifiers: <namespace> = namespace file.%Modifiers.import, [template] {
// CHECK:STDOUT: .Base = %import_ref.1
// CHECK:STDOUT: import Modifiers//default
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref Modifiers//default, inst+3, loaded [template = constants.%Base]
// CHECK:STDOUT: %import_ref.2 = import_ref Modifiers//default, inst+4, unloaded
// CHECK:STDOUT: %import_ref.3 = import_ref Modifiers//default, inst+5, unloaded
// CHECK:STDOUT: %import_ref.4 = import_ref Modifiers//default, inst+9, unloaded
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .Modifiers = imports.%Modifiers
// CHECK:STDOUT: .Derived = %Derived.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %Modifiers.import = import Modifiers
// CHECK:STDOUT: %Derived.decl: type = class_decl @Derived [template = constants.%Derived] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Derived {
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} {}
// CHECK:STDOUT: %Modifiers.ref: <namespace> = name_ref Modifiers, imports.%Modifiers [template = imports.%Modifiers]
// CHECK:STDOUT: %Base.ref: type = name_ref Base, imports.%import_ref.1 [template = constants.%Base]
// CHECK:STDOUT: %.loc8: %.6 = base_decl %Base, element0 [template]
// CHECK:STDOUT: %.loc9: <witness> = complete_type_witness %.7 [template = constants.%.8]
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Derived
// CHECK:STDOUT: .F = %F.decl
// CHECK:STDOUT: .base = %.loc8
// CHECK:STDOUT: extend name_scope4
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Base {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = imports.%import_ref.2
// CHECK:STDOUT: .H = imports.%import_ref.3
// CHECK:STDOUT: .I = imports.%import_ref.4
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: virtual fn @F();
// CHECK:STDOUT:
// CHECK:STDOUT: --- init.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %F.type: type = fn_type @F [template]
// CHECK:STDOUT: %.1: type = tuple_type () [template]
// CHECK:STDOUT: %F: %F.type = struct_value () [template]
// CHECK:STDOUT: %Base: type = class_type @Base [template]
// CHECK:STDOUT: %.2: type = ptr_type <vtable> [template]
// CHECK:STDOUT: %.3: type = struct_type {.<vptr>: %.2} [template]
// CHECK:STDOUT: %.4: <witness> = complete_type_witness %.3 [template]
// CHECK:STDOUT: %.5: type = ptr_type %.3 [template]
// CHECK:STDOUT: %.6: type = struct_type {} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Modifiers: <namespace> = namespace file.%Modifiers.import, [template] {
// CHECK:STDOUT: .Base = %import_ref.1
// CHECK:STDOUT: import Modifiers//default
// CHECK:STDOUT: }
// CHECK:STDOUT: %import_ref.1: type = import_ref Modifiers//default, inst+3, loaded [template = constants.%Base]
// CHECK:STDOUT: %import_ref.2 = import_ref Modifiers//default, inst+4, unloaded
// CHECK:STDOUT: %import_ref.3 = import_ref Modifiers//default, inst+5, unloaded
// CHECK:STDOUT: %import_ref.4 = import_ref Modifiers//default, inst+9, unloaded
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [template] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .Modifiers = imports.%Modifiers
// CHECK:STDOUT: .F = %F.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %Modifiers.import = import Modifiers
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Base {
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = imports.%import_ref.2
// CHECK:STDOUT: .H = imports.%import_ref.3
// CHECK:STDOUT: .I = imports.%import_ref.4
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Modifiers.ref: <namespace> = name_ref Modifiers, imports.%Modifiers [template = imports.%Modifiers]
// CHECK:STDOUT: %Base.ref: type = name_ref Base, imports.%import_ref.1 [template = constants.%Base]
// CHECK:STDOUT: %v.var: ref %Base = var v
// CHECK:STDOUT: %v: ref %Base = bind_name v, %v.var
// CHECK:STDOUT: %.loc7_28.1: %.6 = struct_literal ()
// CHECK:STDOUT: %.loc7_28.2: init %Base = class_init (<error>), %v.var [template = <error>]
// CHECK:STDOUT: %.loc7_29: init %Base = converted %.loc7_28.1, %.loc7_28.2 [template = <error>]
// CHECK:STDOUT: assign %v.var, %.loc7_29
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: