diff --git a/toolchain/check/testdata/interop/cpp/function/operators.carbon b/toolchain/check/testdata/interop/cpp/function/operators.carbon index 25f376e686b1..85db1ba061e1 100644 --- a/toolchain/check/testdata/interop/cpp/function/operators.carbon +++ b/toolchain/check/testdata/interop/cpp/function/operators.carbon @@ -520,6 +520,32 @@ fn F() { let or_result: Cpp.C = operator||(c1, c2); } +// ============================================================================ +// Operand is an inner class +// ============================================================================ + +// --- inner_class.h + +class O { + public: + class C {}; +}; +auto operator+(O::C lhs, O::C rhs) -> O::C; + +// --- import_inner_class.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "inner_class.h"; + +fn F() { + //@dump-sem-ir-begin + let c1: Cpp.O.C = Cpp.O.C.C(); + let c2: Cpp.O.C = Cpp.O.C.C(); + let c3: Cpp.O.C = c1 + c2; + //@dump-sem-ir-end +} + // ============================================================================ // Member operator // ============================================================================ @@ -1765,6 +1791,127 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- import_inner_class.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %O: type = class_type @O [concrete] +// CHECK:STDOUT: %C: type = class_type @C [concrete] +// CHECK:STDOUT: %pattern_type.b28: type = pattern_type %C [concrete] +// CHECK:STDOUT: %C.C.type: type = fn_type @C.C [concrete] +// CHECK:STDOUT: %C.C: %C.C.type = struct_value () [concrete] +// CHECK:STDOUT: %ptr.de2: type = ptr_type %C [concrete] +// CHECK:STDOUT: %C__carbon_thunk.type: type = fn_type @C__carbon_thunk [concrete] +// CHECK:STDOUT: %C__carbon_thunk: %C__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %operator+__carbon_thunk.type: type = fn_type @operator+__carbon_thunk [concrete] +// CHECK:STDOUT: %operator+__carbon_thunk: %operator+__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %T.as.Destroy.impl.Op.type.ac8: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(%C) [concrete] +// CHECK:STDOUT: %T.as.Destroy.impl.Op.362: %T.as.Destroy.impl.Op.type.ac8 = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .O = %O.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %O.decl: type = class_decl @O [concrete = constants.%O] {} {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} +// CHECK:STDOUT: %C.C.decl: %C.C.type = fn_decl @C.C [concrete = constants.%C.C] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %C__carbon_thunk.decl: %C__carbon_thunk.type = fn_decl @C__carbon_thunk [concrete = constants.%C__carbon_thunk] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %operator+__carbon_thunk.decl: %operator+__carbon_thunk.type = fn_decl @operator+__carbon_thunk [concrete = constants.%operator+__carbon_thunk] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %c1.patt: %pattern_type.b28 = binding_pattern c1 [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.ref.loc8_21: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %O.ref.loc8_24: type = name_ref O, imports.%O.decl [concrete = constants.%O] +// CHECK:STDOUT: %C.ref.loc8_26: type = name_ref C, imports.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %C.ref.loc8_28: %C.C.type = name_ref C, imports.%C.C.decl [concrete = constants.%C.C] +// CHECK:STDOUT: %.loc8_31.1: ref %C = temporary_storage +// CHECK:STDOUT: %addr.loc8_31.1: %ptr.de2 = addr_of %.loc8_31.1 +// CHECK:STDOUT: %C__carbon_thunk.call.loc8: init %empty_tuple.type = call imports.%C__carbon_thunk.decl(%addr.loc8_31.1) +// CHECK:STDOUT: %.loc8_31.2: init %C = in_place_init %C__carbon_thunk.call.loc8, %.loc8_31.1 +// CHECK:STDOUT: %.loc8_16: type = splice_block %C.ref.loc8_16 [concrete = constants.%C] { +// CHECK:STDOUT: %Cpp.ref.loc8_11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %O.ref.loc8_14: type = name_ref O, imports.%O.decl [concrete = constants.%O] +// CHECK:STDOUT: %C.ref.loc8_16: type = name_ref C, imports.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_31.3: ref %C = temporary %.loc8_31.1, %.loc8_31.2 +// CHECK:STDOUT: %.loc8_31.4: %C = bind_value %.loc8_31.3 +// CHECK:STDOUT: %c1: %C = bind_name c1, %.loc8_31.4 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %c2.patt: %pattern_type.b28 = binding_pattern c2 [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.ref.loc9_21: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %O.ref.loc9_24: type = name_ref O, imports.%O.decl [concrete = constants.%O] +// CHECK:STDOUT: %C.ref.loc9_26: type = name_ref C, imports.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %C.ref.loc9_28: %C.C.type = name_ref C, imports.%C.C.decl [concrete = constants.%C.C] +// CHECK:STDOUT: %.loc9_31.1: ref %C = temporary_storage +// CHECK:STDOUT: %addr.loc9_31.1: %ptr.de2 = addr_of %.loc9_31.1 +// CHECK:STDOUT: %C__carbon_thunk.call.loc9: init %empty_tuple.type = call imports.%C__carbon_thunk.decl(%addr.loc9_31.1) +// CHECK:STDOUT: %.loc9_31.2: init %C = in_place_init %C__carbon_thunk.call.loc9, %.loc9_31.1 +// CHECK:STDOUT: %.loc9_16: type = splice_block %C.ref.loc9_16 [concrete = constants.%C] { +// CHECK:STDOUT: %Cpp.ref.loc9_11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %O.ref.loc9_14: type = name_ref O, imports.%O.decl [concrete = constants.%O] +// CHECK:STDOUT: %C.ref.loc9_16: type = name_ref C, imports.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc9_31.3: ref %C = temporary %.loc9_31.1, %.loc9_31.2 +// CHECK:STDOUT: %.loc9_31.4: %C = bind_value %.loc9_31.3 +// CHECK:STDOUT: %c2: %C = bind_name c2, %.loc9_31.4 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %c3.patt: %pattern_type.b28 = binding_pattern c3 [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %c1.ref: %C = name_ref c1, %c1 +// CHECK:STDOUT: %c2.ref: %C = name_ref c2, %c2 +// CHECK:STDOUT: %.loc10_24.1: ref %C = temporary_storage +// CHECK:STDOUT: %.loc10_21: ref %C = value_as_ref %c1.ref +// CHECK:STDOUT: %addr.loc10_24.1: %ptr.de2 = addr_of %.loc10_21 +// CHECK:STDOUT: %.loc10_26: ref %C = value_as_ref %c2.ref +// CHECK:STDOUT: %addr.loc10_24.2: %ptr.de2 = addr_of %.loc10_26 +// CHECK:STDOUT: %addr.loc10_24.3: %ptr.de2 = addr_of %.loc10_24.1 +// CHECK:STDOUT: %operator+__carbon_thunk.call: init %empty_tuple.type = call imports.%operator+__carbon_thunk.decl(%addr.loc10_24.1, %addr.loc10_24.2, %addr.loc10_24.3) +// CHECK:STDOUT: %.loc10_24.2: init %C = in_place_init %operator+__carbon_thunk.call, %.loc10_24.1 +// CHECK:STDOUT: %.loc10_16: type = splice_block %C.ref.loc10 [concrete = constants.%C] { +// CHECK:STDOUT: %Cpp.ref.loc10: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %O.ref.loc10: type = name_ref O, imports.%O.decl [concrete = constants.%O] +// CHECK:STDOUT: %C.ref.loc10: type = name_ref C, imports.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc10_24.3: ref %C = temporary %.loc10_24.1, %.loc10_24.2 +// CHECK:STDOUT: %.loc10_24.4: %C = bind_value %.loc10_24.3 +// CHECK:STDOUT: %c3: %C = bind_name c3, %.loc10_24.4 +// CHECK:STDOUT: %T.as.Destroy.impl.Op.bound.loc10: = bound_method %.loc10_24.3, constants.%T.as.Destroy.impl.Op.362 +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc10: = bound_method %.loc10_24.3, %T.as.Destroy.impl.Op.specific_fn.1 +// CHECK:STDOUT: %addr.loc10_24.4: %ptr.de2 = addr_of %.loc10_24.3 +// CHECK:STDOUT: %T.as.Destroy.impl.Op.call.loc10: init %empty_tuple.type = call %bound_method.loc10(%addr.loc10_24.4) +// CHECK:STDOUT: %T.as.Destroy.impl.Op.bound.loc9: = bound_method %.loc9_31.3, constants.%T.as.Destroy.impl.Op.362 +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc9: = bound_method %.loc9_31.3, %T.as.Destroy.impl.Op.specific_fn.2 +// CHECK:STDOUT: %addr.loc9_31.2: %ptr.de2 = addr_of %.loc9_31.3 +// CHECK:STDOUT: %T.as.Destroy.impl.Op.call.loc9: init %empty_tuple.type = call %bound_method.loc9(%addr.loc9_31.2) +// CHECK:STDOUT: %T.as.Destroy.impl.Op.bound.loc8: = bound_method %.loc8_31.3, constants.%T.as.Destroy.impl.Op.362 +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method.loc8: = bound_method %.loc8_31.3, %T.as.Destroy.impl.Op.specific_fn.3 +// CHECK:STDOUT: %addr.loc8_31.2: %ptr.de2 = addr_of %.loc8_31.3 +// CHECK:STDOUT: %T.as.Destroy.impl.Op.call.loc8: init %empty_tuple.type = call %bound_method.loc8(%addr.loc8_31.2) +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_todo_import_member__add_with.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants {