diff --git a/toolchain/check/cpp/import.cpp b/toolchain/check/cpp/import.cpp index a952a7caecb9..f4a73a81ebf2 100644 --- a/toolchain/check/cpp/import.cpp +++ b/toolchain/check/cpp/import.cpp @@ -254,9 +254,20 @@ static auto GetParentNameScopeId(Context& context, clang::Decl* clang_decl) auto class_inst_id = LookupClangDeclInstId(context, SemIR::ClangDeclKey(tag_decl)); CARBON_CHECK(class_inst_id.has_value()); - return context.classes() - .Get(context.insts().GetAs(class_inst_id).class_id) - .scope_id; + auto class_inst = context.insts().Get(class_inst_id); + auto class_id = SemIR::ClassId::None; + if (auto class_decl = class_inst.TryAs()) { + // Common case: the tag was imported as a new Carbon class. + class_id = class_decl->class_id; + } else { + // Rare case: the tag was imported as an existing Carbon class. This + // happens for C++ classes that get mapped to Carbon prelude types, such + // as `std::string_view`. + // TODO: In this case, should we import the C++ class declaration and use + // it as the parent, rather than using the existing Carbon class? + class_id = class_inst.As().class_id; + } + return context.classes().Get(class_id).scope_id; } if (isa(parent_decl)) { diff --git a/toolchain/check/testdata/interop/cpp/class/base.carbon b/toolchain/check/testdata/interop/cpp/class/base.carbon index 6317465e8c3d..dae6b30c4896 100644 --- a/toolchain/check/testdata/interop/cpp/class/base.carbon +++ b/toolchain/check/testdata/interop/cpp/class/base.carbon @@ -119,6 +119,16 @@ fn CallQualified(d: Cpp.Derived) { //@dump-sem-ir-end } +fn CallBaseQualifiedByDerived(d: Cpp.Derived, b: Cpp.Base) { + //@dump-sem-ir-begin + // `Cpp.Derived.f` names a member of `Cpp.Base`, so we allow that to be used + // when `self` is a `Cpp.Base` or anything that implicitly converts to + // `Cpp.Base`, such as `Cpp.Derived`. + d.(Cpp.Derived.f)(); + b.(Cpp.Derived.f)(); + //@dump-sem-ir-end +} + // --- multiple_inheritance.h struct A { int a; }; @@ -740,3 +750,23 @@ class V { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: fn @CallBaseQualifiedByDerived(%d.param: %Derived, %b.param: %Base) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %d.ref: %Derived = name_ref d, %d +// CHECK:STDOUT: %Cpp.ref.loc23: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Derived.ref.loc23: type = name_ref Derived, imports.%Derived.decl [concrete = constants.%Derived] +// CHECK:STDOUT: %f.ref.loc23: %Derived.f.cpp_overload_set.type = name_ref f, imports.%Derived.f.cpp_overload_set.value [concrete = constants.%Derived.f.cpp_overload_set.value] +// CHECK:STDOUT: %bound_method.loc23: = bound_method %d.ref, %f.ref.loc23 +// CHECK:STDOUT: %.loc23_3.1: ref %Base = class_element_access %d.ref, element0 +// CHECK:STDOUT: %.loc23_3.2: ref %Base = converted %d.ref, %.loc23_3.1 +// CHECK:STDOUT: %.loc23_3.3: %Base = acquire_value %.loc23_3.2 +// CHECK:STDOUT: %f__carbon_thunk.call.loc23: init %empty_tuple.type = call imports.%f__carbon_thunk.decl(%.loc23_3.3) +// CHECK:STDOUT: %b.ref: %Base = name_ref b, %b +// CHECK:STDOUT: %Cpp.ref.loc24: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Derived.ref.loc24: type = name_ref Derived, imports.%Derived.decl [concrete = constants.%Derived] +// CHECK:STDOUT: %f.ref.loc24: %Derived.f.cpp_overload_set.type = name_ref f, imports.%Derived.f.cpp_overload_set.value [concrete = constants.%Derived.f.cpp_overload_set.value] +// CHECK:STDOUT: %bound_method.loc24: = bound_method %b.ref, %f.ref.loc24 +// CHECK:STDOUT: %f__carbon_thunk.call.loc24: init %empty_tuple.type = call imports.%f__carbon_thunk.decl(%b.ref) +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interop/cpp/class/method.carbon b/toolchain/check/testdata/interop/cpp/class/method.carbon index ee61e7e076a0..7d1c0da155e9 100644 --- a/toolchain/check/testdata/interop/cpp/class/method.carbon +++ b/toolchain/check/testdata/interop/cpp/class/method.carbon @@ -169,6 +169,24 @@ fn CallF(v: Cpp.HasQualifiers, p: Cpp.HasQualifiers*) { //@dump-sem-ir-end } +// --- use_object_param_qualifiers_qualified.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "object_param_qualifiers.h"; + +fn F(v: Cpp.HasQualifiers, p: Cpp.HasQualifiers*) { + //@dump-sem-ir-begin + v.(Cpp.HasQualifiers.const_this)(); + v.(Cpp.HasQualifiers.const_ref_this)(); + + p->(Cpp.HasQualifiers.plain)(); + p->(Cpp.HasQualifiers.ref_this)(); + p->(Cpp.HasQualifiers.const_this)(); + p->(Cpp.HasQualifiers.const_ref_this)(); + //@dump-sem-ir-end +} + // --- explicit_object_param.h struct Another { @@ -416,6 +434,114 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) { // CHECK:STDOUT: // CHECK:STDOUT: fn @DestroyOp.loc8(%self.param: %i32) = "no_op"; // CHECK:STDOUT: +// CHECK:STDOUT: --- use_object_param_qualifiers_qualified.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %HasQualifiers: type = class_type @HasQualifiers [concrete] +// CHECK:STDOUT: %pattern_type.e15: type = pattern_type %HasQualifiers [concrete] +// CHECK:STDOUT: %ptr.ec3: type = ptr_type %HasQualifiers [concrete] +// CHECK:STDOUT: %HasQualifiers.const_this.cpp_overload_set.type: type = cpp_overload_set_type @HasQualifiers.const_this.cpp_overload_set [concrete] +// CHECK:STDOUT: %HasQualifiers.const_this.cpp_overload_set.value: %HasQualifiers.const_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.const_this.cpp_overload_set [concrete] +// CHECK:STDOUT: %const_this__carbon_thunk.type: type = fn_type @const_this__carbon_thunk [concrete] +// CHECK:STDOUT: %const_this__carbon_thunk: %const_this__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %HasQualifiers.const_ref_this.cpp_overload_set.type: type = cpp_overload_set_type @HasQualifiers.const_ref_this.cpp_overload_set [concrete] +// CHECK:STDOUT: %HasQualifiers.const_ref_this.cpp_overload_set.value: %HasQualifiers.const_ref_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.const_ref_this.cpp_overload_set [concrete] +// CHECK:STDOUT: %const_ref_this__carbon_thunk.type: type = fn_type @const_ref_this__carbon_thunk [concrete] +// CHECK:STDOUT: %const_ref_this__carbon_thunk: %const_ref_this__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: %HasQualifiers.plain.cpp_overload_set.type: type = cpp_overload_set_type @HasQualifiers.plain.cpp_overload_set [concrete] +// CHECK:STDOUT: %HasQualifiers.plain.cpp_overload_set.value: %HasQualifiers.plain.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.plain.cpp_overload_set [concrete] +// CHECK:STDOUT: %HasQualifiers.plain.type: type = fn_type @HasQualifiers.plain [concrete] +// CHECK:STDOUT: %HasQualifiers.plain: %HasQualifiers.plain.type = struct_value () [concrete] +// CHECK:STDOUT: %HasQualifiers.ref_this.cpp_overload_set.type: type = cpp_overload_set_type @HasQualifiers.ref_this.cpp_overload_set [concrete] +// CHECK:STDOUT: %HasQualifiers.ref_this.cpp_overload_set.value: %HasQualifiers.ref_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.ref_this.cpp_overload_set [concrete] +// CHECK:STDOUT: %HasQualifiers.ref_this.type: type = fn_type @HasQualifiers.ref_this [concrete] +// CHECK:STDOUT: %HasQualifiers.ref_this: %HasQualifiers.ref_this.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .HasQualifiers = %HasQualifiers.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %HasQualifiers.decl: type = class_decl @HasQualifiers [concrete = constants.%HasQualifiers] {} {} +// CHECK:STDOUT: %HasQualifiers.const_this.cpp_overload_set.value: %HasQualifiers.const_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.const_this.cpp_overload_set [concrete = constants.%HasQualifiers.const_this.cpp_overload_set.value] +// CHECK:STDOUT: %const_this__carbon_thunk.decl: %const_this__carbon_thunk.type = fn_decl @const_this__carbon_thunk [concrete = constants.%const_this__carbon_thunk] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %HasQualifiers.const_ref_this.cpp_overload_set.value: %HasQualifiers.const_ref_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.const_ref_this.cpp_overload_set [concrete = constants.%HasQualifiers.const_ref_this.cpp_overload_set.value] +// CHECK:STDOUT: %const_ref_this__carbon_thunk.decl: %const_ref_this__carbon_thunk.type = fn_decl @const_ref_this__carbon_thunk [concrete = constants.%const_ref_this__carbon_thunk] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: %HasQualifiers.plain.cpp_overload_set.value: %HasQualifiers.plain.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.plain.cpp_overload_set [concrete = constants.%HasQualifiers.plain.cpp_overload_set.value] +// CHECK:STDOUT: %HasQualifiers.plain.decl: %HasQualifiers.plain.type = fn_decl @HasQualifiers.plain [concrete = constants.%HasQualifiers.plain] { +// CHECK:STDOUT: %self.patt: %pattern_type.e15 = ref_binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.e15 = ref_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: ref %HasQualifiers = ref_param call_param0 +// CHECK:STDOUT: %self: ref %HasQualifiers = ref_binding self, %self.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %HasQualifiers.ref_this.cpp_overload_set.value: %HasQualifiers.ref_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.ref_this.cpp_overload_set [concrete = constants.%HasQualifiers.ref_this.cpp_overload_set.value] +// CHECK:STDOUT: %HasQualifiers.ref_this.decl: %HasQualifiers.ref_this.type = fn_decl @HasQualifiers.ref_this [concrete = constants.%HasQualifiers.ref_this] { +// CHECK:STDOUT: %self.patt: %pattern_type.e15 = ref_binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: %pattern_type.e15 = ref_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %self.param: ref %HasQualifiers = ref_param call_param0 +// CHECK:STDOUT: %self: ref %HasQualifiers = ref_binding self, %self.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%v.param: %HasQualifiers, %p.param: %ptr.ec3) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %v.ref.loc8: %HasQualifiers = name_ref v, %v +// CHECK:STDOUT: %Cpp.ref.loc8: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %HasQualifiers.ref.loc8: type = name_ref HasQualifiers, imports.%HasQualifiers.decl [concrete = constants.%HasQualifiers] +// CHECK:STDOUT: %const_this.ref.loc8: %HasQualifiers.const_this.cpp_overload_set.type = name_ref const_this, imports.%HasQualifiers.const_this.cpp_overload_set.value [concrete = constants.%HasQualifiers.const_this.cpp_overload_set.value] +// CHECK:STDOUT: %bound_method.loc8: = bound_method %v.ref.loc8, %const_this.ref.loc8 +// CHECK:STDOUT: %const_this__carbon_thunk.call.loc8: init %empty_tuple.type = call imports.%const_this__carbon_thunk.decl(%v.ref.loc8) +// CHECK:STDOUT: %v.ref.loc9: %HasQualifiers = name_ref v, %v +// CHECK:STDOUT: %Cpp.ref.loc9: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %HasQualifiers.ref.loc9: type = name_ref HasQualifiers, imports.%HasQualifiers.decl [concrete = constants.%HasQualifiers] +// CHECK:STDOUT: %const_ref_this.ref.loc9: %HasQualifiers.const_ref_this.cpp_overload_set.type = name_ref const_ref_this, imports.%HasQualifiers.const_ref_this.cpp_overload_set.value [concrete = constants.%HasQualifiers.const_ref_this.cpp_overload_set.value] +// CHECK:STDOUT: %bound_method.loc9: = bound_method %v.ref.loc9, %const_ref_this.ref.loc9 +// CHECK:STDOUT: %const_ref_this__carbon_thunk.call.loc9: init %empty_tuple.type = call imports.%const_ref_this__carbon_thunk.decl(%v.ref.loc9) +// CHECK:STDOUT: %p.ref.loc11: %ptr.ec3 = name_ref p, %p +// CHECK:STDOUT: %Cpp.ref.loc11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %HasQualifiers.ref.loc11: type = name_ref HasQualifiers, imports.%HasQualifiers.decl [concrete = constants.%HasQualifiers] +// CHECK:STDOUT: %plain.ref: %HasQualifiers.plain.cpp_overload_set.type = name_ref plain, imports.%HasQualifiers.plain.cpp_overload_set.value [concrete = constants.%HasQualifiers.plain.cpp_overload_set.value] +// CHECK:STDOUT: %.loc11: ref %HasQualifiers = deref %p.ref.loc11 +// CHECK:STDOUT: %bound_method.loc11: = bound_method %.loc11, %plain.ref +// CHECK:STDOUT: %HasQualifiers.plain.call: init %empty_tuple.type = call imports.%HasQualifiers.plain.decl(%.loc11) +// CHECK:STDOUT: %p.ref.loc12: %ptr.ec3 = name_ref p, %p +// CHECK:STDOUT: %Cpp.ref.loc12: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %HasQualifiers.ref.loc12: type = name_ref HasQualifiers, imports.%HasQualifiers.decl [concrete = constants.%HasQualifiers] +// CHECK:STDOUT: %ref_this.ref: %HasQualifiers.ref_this.cpp_overload_set.type = name_ref ref_this, imports.%HasQualifiers.ref_this.cpp_overload_set.value [concrete = constants.%HasQualifiers.ref_this.cpp_overload_set.value] +// CHECK:STDOUT: %.loc12: ref %HasQualifiers = deref %p.ref.loc12 +// CHECK:STDOUT: %bound_method.loc12: = bound_method %.loc12, %ref_this.ref +// CHECK:STDOUT: %HasQualifiers.ref_this.call: init %empty_tuple.type = call imports.%HasQualifiers.ref_this.decl(%.loc12) +// CHECK:STDOUT: %p.ref.loc13: %ptr.ec3 = name_ref p, %p +// CHECK:STDOUT: %Cpp.ref.loc13: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %HasQualifiers.ref.loc13: type = name_ref HasQualifiers, imports.%HasQualifiers.decl [concrete = constants.%HasQualifiers] +// CHECK:STDOUT: %const_this.ref.loc13: %HasQualifiers.const_this.cpp_overload_set.type = name_ref const_this, imports.%HasQualifiers.const_this.cpp_overload_set.value [concrete = constants.%HasQualifiers.const_this.cpp_overload_set.value] +// CHECK:STDOUT: %.loc13_4.1: ref %HasQualifiers = deref %p.ref.loc13 +// CHECK:STDOUT: %bound_method.loc13: = bound_method %.loc13_4.1, %const_this.ref.loc13 +// CHECK:STDOUT: %.loc13_4.2: %HasQualifiers = acquire_value %.loc13_4.1 +// CHECK:STDOUT: %const_this__carbon_thunk.call.loc13: init %empty_tuple.type = call imports.%const_this__carbon_thunk.decl(%.loc13_4.2) +// CHECK:STDOUT: %p.ref.loc14: %ptr.ec3 = name_ref p, %p +// CHECK:STDOUT: %Cpp.ref.loc14: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %HasQualifiers.ref.loc14: type = name_ref HasQualifiers, imports.%HasQualifiers.decl [concrete = constants.%HasQualifiers] +// CHECK:STDOUT: %const_ref_this.ref.loc14: %HasQualifiers.const_ref_this.cpp_overload_set.type = name_ref const_ref_this, imports.%HasQualifiers.const_ref_this.cpp_overload_set.value [concrete = constants.%HasQualifiers.const_ref_this.cpp_overload_set.value] +// CHECK:STDOUT: %.loc14_4.1: ref %HasQualifiers = deref %p.ref.loc14 +// CHECK:STDOUT: %bound_method.loc14: = bound_method %.loc14_4.1, %const_ref_this.ref.loc14 +// CHECK:STDOUT: %.loc14_4.2: %HasQualifiers = acquire_value %.loc14_4.1 +// CHECK:STDOUT: %const_ref_this__carbon_thunk.call.loc14: init %empty_tuple.type = call imports.%const_ref_this__carbon_thunk.decl(%.loc14_4.2) +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- call_explicit_object_param.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/interop/cpp/stdlib/string_view.carbon b/toolchain/check/testdata/interop/cpp/stdlib/string_view.carbon index 293d1f270e3d..d43c14faeb89 100644 --- a/toolchain/check/testdata/interop/cpp/stdlib/string_view.carbon +++ b/toolchain/check/testdata/interop/cpp/stdlib/string_view.carbon @@ -24,6 +24,10 @@ namespace std { basic_string_view() = default; size_t size() const { return size_; } + constexpr bool starts_with(basic_string_view sv) const { + return false; + } + private: const CharT* data_; size_t size_; @@ -36,7 +40,9 @@ namespace std { auto Consume(std::string_view sv) -> void; auto Produce() -> std::string_view; -// --- import_multiple.carbon +struct DerivedFromStringView : std::string_view {}; + +// --- pass_and_return.carbon library "[[@TEST_NAME]]"; @@ -54,7 +60,19 @@ fn G() -> str { } //@dump-sem-ir-end -// CHECK:STDOUT: --- import_multiple.carbon +// --- call_base_method.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "string_view.h"; + +//@dump-sem-ir-begin +fn StarstWith(a: str, b: str) -> bool { + return a.(Cpp.DerivedFromStringView.starts_with)(b); +} +//@dump-sem-ir-end + +// CHECK:STDOUT: --- pass_and_return.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %F.type: type = fn_type @F [concrete] @@ -140,3 +158,77 @@ fn G() -> str { // CHECK:STDOUT: return %.loc14 to %return.param // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- call_base_method.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %str: type = class_type @String [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %pattern_type.461: type = pattern_type %str [concrete] +// CHECK:STDOUT: %Bool.type: type = fn_type @Bool [concrete] +// CHECK:STDOUT: %Bool: %Bool.type = struct_value () [concrete] +// CHECK:STDOUT: %.650: form = init_form bool, call_param2 [concrete] +// CHECK:STDOUT: %pattern_type.831: type = pattern_type bool [concrete] +// CHECK:STDOUT: %StarstWith.type: type = fn_type @StarstWith [concrete] +// CHECK:STDOUT: %StarstWith: %StarstWith.type = struct_value () [concrete] +// CHECK:STDOUT: %DerivedFromStringView: type = class_type @DerivedFromStringView [concrete] +// CHECK:STDOUT: %DerivedFromStringView.starts_with.cpp_overload_set.type: type = cpp_overload_set_type @DerivedFromStringView.starts_with.cpp_overload_set [concrete] +// CHECK:STDOUT: %DerivedFromStringView.starts_with.cpp_overload_set.value: %DerivedFromStringView.starts_with.cpp_overload_set.type = cpp_overload_set_value @DerivedFromStringView.starts_with.cpp_overload_set [concrete] +// CHECK:STDOUT: %ptr.85f: type = ptr_type %str [concrete] +// CHECK:STDOUT: %ptr.bb2: type = ptr_type bool [concrete] +// CHECK:STDOUT: %starts_with__carbon_thunk.type: type = fn_type @starts_with__carbon_thunk [concrete] +// CHECK:STDOUT: %starts_with__carbon_thunk: %starts_with__carbon_thunk.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .DerivedFromStringView = %DerivedFromStringView.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %DerivedFromStringView.decl: type = class_decl @DerivedFromStringView [concrete = constants.%DerivedFromStringView] {} {} +// CHECK:STDOUT: %DerivedFromStringView.starts_with.cpp_overload_set.value: %DerivedFromStringView.starts_with.cpp_overload_set.type = cpp_overload_set_value @DerivedFromStringView.starts_with.cpp_overload_set [concrete = constants.%DerivedFromStringView.starts_with.cpp_overload_set.value] +// CHECK:STDOUT: %starts_with__carbon_thunk.decl: %starts_with__carbon_thunk.type = fn_decl @starts_with__carbon_thunk [concrete = constants.%starts_with__carbon_thunk] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %StarstWith.decl: %StarstWith.type = fn_decl @StarstWith [concrete = constants.%StarstWith] { +// CHECK:STDOUT: %a.patt: %pattern_type.461 = value_binding_pattern a [concrete] +// CHECK:STDOUT: %a.param_patt: %pattern_type.461 = value_param_pattern %a.patt, call_param0 [concrete] +// CHECK:STDOUT: %b.patt: %pattern_type.461 = value_binding_pattern b [concrete] +// CHECK:STDOUT: %b.param_patt: %pattern_type.461 = value_param_pattern %b.patt, call_param1 [concrete] +// CHECK:STDOUT: %return.patt: %pattern_type.831 = return_slot_pattern [concrete] +// CHECK:STDOUT: %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt, call_param2 [concrete] +// CHECK:STDOUT: } { +// CHECK:STDOUT: %Bool.call: init type = call constants.%Bool() [concrete = bool] +// CHECK:STDOUT: %.loc7_34.1: type = value_of_initializer %Bool.call [concrete = bool] +// CHECK:STDOUT: %.loc7_34.2: type = converted %Bool.call, %.loc7_34.1 [concrete = bool] +// CHECK:STDOUT: %.loc7_34.3: form = init_form %.loc7_34.2, call_param2 [concrete = constants.%.650] +// CHECK:STDOUT: %a.param: %str = value_param call_param0 +// CHECK:STDOUT: %a: %str = value_binding a, %a.param +// CHECK:STDOUT: %b.param: %str = value_param call_param1 +// CHECK:STDOUT: %b: %str = value_binding b, %b.param +// CHECK:STDOUT: %return.param: ref bool = out_param call_param2 +// CHECK:STDOUT: %return: ref bool = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @StarstWith(%a.param: %str, %b.param: %str) -> out %return.param: bool { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: %str = name_ref a, %a +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %DerivedFromStringView.ref: type = name_ref DerivedFromStringView, imports.%DerivedFromStringView.decl [concrete = constants.%DerivedFromStringView] +// CHECK:STDOUT: %starts_with.ref: %DerivedFromStringView.starts_with.cpp_overload_set.type = name_ref starts_with, imports.%DerivedFromStringView.starts_with.cpp_overload_set.value [concrete = constants.%DerivedFromStringView.starts_with.cpp_overload_set.value] +// CHECK:STDOUT: %bound_method: = bound_method %a.ref, %starts_with.ref +// CHECK:STDOUT: %b.ref: %str = name_ref b, %b +// CHECK:STDOUT: %.loc8_52: ref %str = value_as_ref %b.ref +// CHECK:STDOUT: %addr.loc8_53.1: %ptr.85f = addr_of %.loc8_52 +// CHECK:STDOUT: %.loc8_53.1: ref bool = temporary_storage +// CHECK:STDOUT: %addr.loc8_53.2: %ptr.bb2 = addr_of %.loc8_53.1 +// CHECK:STDOUT: %starts_with__carbon_thunk.call: init %empty_tuple.type = call imports.%starts_with__carbon_thunk.decl(%a.ref, %addr.loc8_53.1, %addr.loc8_53.2) +// CHECK:STDOUT: %.loc8_53.2: init bool = in_place_init %starts_with__carbon_thunk.call, %.loc8_53.1 +// CHECK:STDOUT: return %.loc8_53.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: