diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index 8c8c88af7070..a21af9563113 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -352,6 +352,7 @@ cc_library( "//toolchain/sem_ir:file", "//toolchain/sem_ir:stringify", "//toolchain/sem_ir:typed_insts", + "@llvm-project//clang:ast", "@llvm-project//llvm:Support", ], ) diff --git a/toolchain/check/convert.cpp b/toolchain/check/convert.cpp index d920edfebc84..71eaa6fbe8a8 100644 --- a/toolchain/check/convert.cpp +++ b/toolchain/check/convert.cpp @@ -16,6 +16,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/control_flow.h" #include "toolchain/check/core_identifier.h" +#include "toolchain/check/cpp/export.h" #include "toolchain/check/diagnostic_helpers.h" #include "toolchain/check/eval.h" #include "toolchain/check/impl_lookup.h" @@ -501,6 +502,25 @@ static auto ConvertTupleToArray(Context& context, SemIR::TupleType tuple_type, .dest_id = return_slot_arg_id}); } +// Performs a conversion from a function to a C++ function pointer type. +static auto ConvertFunctionToCppPointer(Context& context, SemIR::LocId loc_id, + SemIR::FunctionType src_type, + SemIR::CppFunctionPointerType dest_type, + SemIR::InstId value_id, + ConversionTarget target) + -> SemIR::InstId { + if (!ExportFunctionToCppPointerConversion(context, value_id, src_type, + dest_type, target.diagnose)) { + return SemIR::ErrorInst::InstId; + } + + return AddInst( + context, loc_id, + {.type_id = target.type_id, + .function_ref_id = value_id, + .function_id = src_type.function_id}); +} + // Performs a conversion from a tuple to a tuple type. This function only // converts the type, and does not perform a final conversion to the requested // expression category. @@ -1630,6 +1650,17 @@ static auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id, } } + // Function types can convert to C++ function pointer types. + if (auto fn_ptr_type = + context.types().TryGetAs( + target.type_id)) { + if (auto src_fn_type = + context.types().TryGetAs(value_type_id)) { + return ConvertFunctionToCppPointer(context, loc_id, *src_fn_type, + *fn_ptr_type, value_id, target); + } + } + // Split the qualifiers off the target type. // TODO: Most conversions should probably be looking at the unqualified target // type. diff --git a/toolchain/check/cpp/export.cpp b/toolchain/check/cpp/export.cpp index 192a36d54b62..356810801c15 100644 --- a/toolchain/check/cpp/export.cpp +++ b/toolchain/check/cpp/export.cpp @@ -745,7 +745,7 @@ static auto MapToCppThunkParamType(Context& context, SemIR::TypeId type_id) } // Build FunctionInfo for an export of the given Carbon function. Exports the -// name scope if necessary. +// name scope if necessary. Returns `nullopt` if an error was diagnosed. static auto BuildFunctionInfo(Context& context, SemIR::LocId loc_id, SemIR::FunctionId callee_function_id) -> std::optional { @@ -1512,8 +1512,10 @@ static auto ExportGenericFunctionToCpp(Context& context, SemIR::LocId loc_id, return template_decl; } -auto ExportFunctionToCpp(Context& context, SemIR::LocId loc_id, - SemIR::FunctionId callee_function_id) +// Exports the given function to C++ and returns the exported `NamedDecl`, +// or `nullptr` if an error was diagnosed. +static auto ExportFunctionToCpp(Context& context, SemIR::LocId loc_id, + SemIR::FunctionId callee_function_id) -> clang::NamedDecl* { auto target = BuildFunctionInfo(context, loc_id, callee_function_id); if (!target) { @@ -1531,6 +1533,93 @@ auto ExportFunctionToCpp(Context& context, SemIR::LocId loc_id, return ExportNonGenericFunctionToCpp(context, loc_id, *target); } +auto GetOrExportFunctionToCpp(Context& context, SemIR::LocId loc_id, + SemIR::FunctionId function_id) + -> clang::NamedDecl* { + SemIR::Function& function = context.functions().Get(function_id); + if (auto clang_decl_id = + context.clang_decls().LookupId(function.first_decl_id()); + clang_decl_id.has_value()) { + return llvm::cast( + context.clang_decls().Get(clang_decl_id).decl()); + } + + auto* named_decl = ExportFunctionToCpp(context, loc_id, function_id); + if (!named_decl) { + return nullptr; + } + + if (auto* function_template_decl = + llvm::dyn_cast(named_decl)) { + context.clang_decls().Add( + {.key = SemIR::ClangDeclKey::ForNonFunctionDecl(function_template_decl), + .inst_id = function.first_decl_id()}); + return function_template_decl; + } + + auto* clang_function_decl = llvm::cast(named_decl); + + SemIR::ClangDeclSignature thunk_signature{ + .kind = SemIR::ClangDeclSignature::Normal, + .num_params = static_cast(clang_function_decl->getNumParams())}; + thunk_signature.passing_modes.assign( + thunk_signature.num_params, + SemIR::ClangDeclSignature::PassingMode::ByValue); + context.clang_decls().Add( + {.key = SemIR::ClangDeclKey::ForFunctionDecl( + clang_function_decl, + context.clang_decl_signatures().Add(std::move(thunk_signature))), + .inst_id = function.first_decl_id()}); + return clang_function_decl; +} + +auto ExportFunctionToCppPointerConversion( + Context& context, SemIR::InstId src_id, SemIR::FunctionType src_type, + SemIR::CppFunctionPointerType dest_type, bool diagnose) -> bool { + if (src_type.specific_id.has_value()) { + context.TODO( + src_id, + "can't convert generic function specific to a C++ function pointer"); + return false; + } + auto* src_clang_decl = GetOrExportFunctionToCpp(context, SemIR::LocId(src_id), + src_type.function_id); + if (src_clang_decl == nullptr) { + return false; + } + + CARBON_CHECK(!src_clang_decl->isTemplateDecl(), + "can't form a pointer to a template"); + + const auto* exported_fn_type = + src_clang_decl->getFunctionType() + ->getAsCanonical(); + auto dest_function_ptr_type_info = + context.clang_function_pointer_types().Get(dest_type.clang_type_id); + const auto* dest_fn_type = + dest_function_ptr_type_info.clang_type->getPointeeType() + ->getAsCanonical(); + + if (exported_fn_type != dest_fn_type) { + if (diagnose) { + auto function = context.functions().Get(src_type.function_id); + CARBON_DIAGNOSTIC(ExportedFunctionPtrTypeMismatch, Error, + "can't convert exported function type to `{0}`", + CppType); + CARBON_DIAGNOSTIC(ExportedFromFunction, Note, + "function exported with type `{0}`", CppType); + context.emitter() + .Build(src_id, ExportedFunctionPtrTypeMismatch, dest_fn_type) + .Note(function.first_decl_id(), ExportedFromFunction, + exported_fn_type) + .Emit(); + } + return false; + } + + return true; +} + // Returns whether the given class has any abstract methods. static auto HasAnyAbstractMethods(Context& context, const SemIR::Class& class_info, diff --git a/toolchain/check/cpp/export.h b/toolchain/check/cpp/export.h index 36edc233c435..3ed7e363fd71 100644 --- a/toolchain/check/cpp/export.h +++ b/toolchain/check/cpp/export.h @@ -77,11 +77,21 @@ auto ExportFieldToCpp(Context& context, SemIR::InstId field_inst_id, SemIR::FieldDecl field_decl, SemIR::SpecificId specific_id) -> clang::FieldDecl*; -// Get a `clang::FunctionDecl` that can be used to call a Carbon function. -// If the function is generic, a `clang::FunctionTemplateDecl` will be -// created instead. -auto ExportFunctionToCpp(Context& context, SemIR::LocId loc_id, - SemIR::FunctionId function_id) -> clang::NamedDecl*; +// Returns the `ClangDeclId` of a `clang::FunctionDecl` or +// `clang::FunctionTemplateDecl` that can be used to call the given function. +// Returns null if an error was diagnosed. +auto GetOrExportFunctionToCpp(Context& context, SemIR::LocId loc_id, + SemIR::FunctionId function_id) + -> clang::NamedDecl*; + +// Exports the necessary declarations to permit conversion from the given +// Carbon function type to the given C++ function pointer type. If the +// conversion would be invalid, this will return false, and if `diagnose` is +// true it will also emit one or more diagnostics explaining the reason it would +// be invalid. In those diagnostics, `src_id` is the source of the conversion. +auto ExportFunctionToCppPointerConversion( + Context& context, SemIR::InstId src_id, SemIR::FunctionType src_type, + SemIR::CppFunctionPointerType dest_type, bool diagnose) -> bool; // Exports a Carbon virtual function as a C++ `clang::FunctionDecl` declaration. // Does not emit a definition. diff --git a/toolchain/check/cpp/generate_ast.cpp b/toolchain/check/cpp/generate_ast.cpp index 5a75ac6a540e..a7a553044309 100644 --- a/toolchain/check/cpp/generate_ast.cpp +++ b/toolchain/check/cpp/generate_ast.cpp @@ -165,9 +165,6 @@ class CarbonExternalASTSource : public SemIR::ReadOnlyASTSource { auto MapInstIdToClangDeclOrType(LookupResult lookup) -> std::variant; - auto GetOrExportFunctionToCpp(SemIR::InstId target_inst_id, - SemIR::FunctionId function_id) - -> clang::NamedDecl*; // Get a current best-effort location for the current position within C++ // processing. auto GetCurrentCppLocId() -> SemIR::LocId { @@ -233,7 +230,7 @@ auto CarbonExternalASTSource::MapInstIdToClangDeclOrType(LookupResult lookup) context_->types().GetTypeInstId(target_inst.type_id()); auto callee = GetCallee(context_->sem_ir(), target_inst_id); if (auto* callee_function = std::get_if(&callee)) { - return GetOrExportFunctionToCpp(target_inst_id, + return GetOrExportFunctionToCpp(*context_, SemIR::LocId(target_inst_id), callee_function->function_id); } else if (auto generic_class = context_->insts().TryGetAs( @@ -255,46 +252,6 @@ auto CarbonExternalASTSource::MapInstIdToClangDeclOrType(LookupResult lookup) } } -auto CarbonExternalASTSource::GetOrExportFunctionToCpp( - SemIR::InstId target_inst_id, SemIR::FunctionId function_id) - -> clang::NamedDecl* { - SemIR::Function& function = context_->functions().Get(function_id); - if (const auto* clang_decl = - context_->clang_decls().Lookup(function.first_decl_id())) { - return cast(clang_decl->decl()); - } - - auto* named_decl = - ExportFunctionToCpp(*context_, SemIR::LocId(target_inst_id), function_id); - if (!named_decl) { - return nullptr; - } - - if (auto* function_template_decl = - llvm::dyn_cast(named_decl)) { - context_->clang_decls().Add( - {.key = SemIR::ClangDeclKey::ForNonFunctionDecl(function_template_decl), - .inst_id = function.first_decl_id()}); - return function_template_decl; - } - - auto* clang_function_decl = llvm::cast(named_decl); - - SemIR::ClangDeclSignature thunk_signature; - thunk_signature.kind = SemIR::ClangDeclSignature::Normal; - thunk_signature.num_params = - static_cast(clang_function_decl->getNumParams()); - thunk_signature.passing_modes.assign( - thunk_signature.num_params, - SemIR::ClangDeclSignature::PassingMode::ByValue); - context_->clang_decls().Add( - {.key = SemIR::ClangDeclKey::ForFunctionDecl( - clang_function_decl, - context_->clang_decl_signatures().Add(std::move(thunk_signature))), - .inst_id = function.first_decl_id()}); - return clang_function_decl; -} - auto CarbonExternalASTSource::BuildCarbonNamespace() -> void { static const llvm::StringLiteral carbon_namespace_name = "Carbon"; auto& ast_context = context_->ast_context(); diff --git a/toolchain/check/cpp/impl_lookup.cpp b/toolchain/check/cpp/impl_lookup.cpp index 2b42996f73c6..d2a42551f414 100644 --- a/toolchain/check/cpp/impl_lookup.cpp +++ b/toolchain/check/cpp/impl_lookup.cpp @@ -133,6 +133,12 @@ static auto BuildCopyWitness(Context& context, SemIR::LocId loc_id, -> SemIR::InstId { auto& clang_sema = context.clang_sema(); + if (context.constant_values().InstIs( + query_self_const_id)) { + return BuildPrimitiveCopyWitness(context, loc_id, query_self_const_id, + query_specific_interface); + } + auto* tag_decl = TypeAsTagDecl(context, query_self_const_id); if (!tag_decl) { return SemIR::InstId::None; diff --git a/toolchain/check/cpp/import.cpp b/toolchain/check/cpp/import.cpp index 0660c20a7276..772fc49694d8 100644 --- a/toolchain/check/cpp/import.cpp +++ b/toolchain/check/cpp/import.cpp @@ -1992,13 +1992,6 @@ static auto ImportFunction(Context& context, SemIR::LocId loc_id, static auto DefineAsThunkCall(Context& context, SemIR::LocId loc_id, const CalleeFunctionInfo& callee_info, SemIR::Function& function) -> void { - Diagnostics::AnnotationScope annotate_diagnostics( - &context.emitter(), [&](auto& builder) { - CARBON_DIAGNOSTIC(InCppThunk, Note, - "in thunk for C++ function used here"); - builder.Note(loc_id, InCppThunk); - }); - clang::FunctionDecl* thunk_clang_decl = BuildCppThunk(context, callee_info); if (thunk_clang_decl == nullptr) { return; @@ -2075,6 +2068,12 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id, context.insts().GetAs(*function_decl_id).function_id; SemIR::Function& imported_function = context.functions().Get(function_id); if (IsCppThunkRequired(context, callee_info)) { + Diagnostics::AnnotationScope annotate_diagnostics( + &context.emitter(), [&](auto& builder) { + CARBON_DIAGNOSTIC(InCppThunk, Note, + "in thunk for C++ function used here"); + builder.Note(loc_id, InCppThunk); + }); DefineAsThunkCall(context, loc_id, callee_info, imported_function); } else { // Inform Clang that the function has been referenced. This will trigger diff --git a/toolchain/check/cpp/type_mapping.cpp b/toolchain/check/cpp/type_mapping.cpp index 102dbb930a9e..e50037c517ff 100644 --- a/toolchain/check/cpp/type_mapping.cpp +++ b/toolchain/check/cpp/type_mapping.cpp @@ -284,6 +284,20 @@ static auto TryMapType(Context& context, SemIR::TypeId type_id) case SemIR::FloatLiteralType::Kind: { return context.ast_context().DoubleTy; } + case CARBON_KIND(SemIR::FunctionType function_type): { + auto decl_id = + context.functions().Get(function_type.function_id).first_decl_id(); + const auto* clang_decl = GetOrExportFunctionToCpp( + context, SemIR::LocId(decl_id), function_type.function_id); + if (clang_decl == nullptr) { + return clang::QualType(); + } + clang::QualType clang_fn_type(clang_decl->getFunctionType(), /*Quals=*/0); + clang::QualType clang_ptr_type = + context.ast_context().getPointerType(clang_fn_type); + return context.ast_context().getAttributedType( + clang::attr::TypeNonNull, clang_ptr_type, clang_ptr_type); + } case CARBON_KIND(SemIR::PointerType pointer_type): { return WrappedType{ .inner_type_id = diff --git a/toolchain/check/custom_witness.cpp b/toolchain/check/custom_witness.cpp index d10f818870fb..ee7487116354 100644 --- a/toolchain/check/custom_witness.cpp +++ b/toolchain/check/custom_witness.cpp @@ -188,6 +188,7 @@ static auto IsBuiltinWithTrivialDestruction(Context& context, case SemIR::FacetType::Kind: case SemIR::FloatType::Kind: case SemIR::FormType::Kind: + case SemIR::FunctionType::Kind: case SemIR::IntLiteralType::Kind: case SemIR::IntType::Kind: case SemIR::PointerType::Kind: diff --git a/toolchain/check/diagnostic_emitter.cpp b/toolchain/check/diagnostic_emitter.cpp index 49532d45c4cb..2452310d3310 100644 --- a/toolchain/check/diagnostic_emitter.cpp +++ b/toolchain/check/diagnostic_emitter.cpp @@ -8,6 +8,7 @@ #include #include +#include "clang/AST/TypeBase.h" #include "common/raw_string_ostream.h" #include "toolchain/check/diagnostic_helpers.h" #include "toolchain/sem_ir/absolute_node_ref.h" @@ -143,6 +144,9 @@ auto DiagnosticEmitter::ConvertArg(llvm::Any arg) const -> llvm::Any { specific_interface_raw->specific_interface_id); return StringifySpecificInterface(*sem_ir_, specific_interface); } + if (auto* clang_type = llvm::any_cast(&arg)) { + return clang_type->type.getAsString(); + } return DiagnosticEmitterBase::ConvertArg(arg); } diff --git a/toolchain/check/diagnostic_helpers.h b/toolchain/check/diagnostic_helpers.h index 8305cae67baf..690428fb8431 100644 --- a/toolchain/check/diagnostic_helpers.h +++ b/toolchain/check/diagnostic_helpers.h @@ -7,6 +7,7 @@ #include +#include "clang/AST/TypeBase.h" #include "llvm/ADT/APSInt.h" #include "toolchain/parse/node_ids.h" #include "toolchain/sem_ir/ids.h" @@ -147,6 +148,16 @@ struct SpecificInterfaceIdAsRawType { SemIR::SpecificInterfaceId specific_interface_id; }; +// A C++ type, for rendering in a diagnostic. +struct CppType { + using DiagnosticType = Diagnostics::TypeInfo; + + explicit(false) CppType(clang::QualType type) : type(type) {} + explicit(false) CppType(const clang::Type* type) : type(type, 0) {} + + clang::QualType type; +}; + } // namespace Carbon::Check #endif // CARBON_TOOLCHAIN_CHECK_DIAGNOSTIC_HELPERS_H_ diff --git a/toolchain/check/impl_lookup.cpp b/toolchain/check/impl_lookup.cpp index 837ab98d8057..0a4bdb9a77cd 100644 --- a/toolchain/check/impl_lookup.cpp +++ b/toolchain/check/impl_lookup.cpp @@ -143,6 +143,22 @@ static auto FindAssociatedImportIRs( push_args(specific_id); break; } + case CARBON_KIND(SemIR::ClangFunctionPointerTypeId _): { + // C++ function pointer types aren't actually members of the `Cpp` + // package, because they don't have declarations in C++, or even names + // as such. However, they need to be associated with `ImportIRId::Cpp` + // in order for impl lookup to find their implementations of core + // interfaces like `Copy`. + // + // TODO: we can probably avoid this special case (and many others) by + // mapping C++ function pointers to instances of a parameterized + // prelude type, which can implement interfaces like `Copy` using + // builtins. However, that prelude type will need to take the + // parameter and return types as generic parameters, so we can't do + // that until we support variadics. + result.push_back(SemIR::ImportIRId::Cpp); + break; + } default: { break; } diff --git a/toolchain/check/testdata/generic/template/call.carbon b/toolchain/check/testdata/generic/template/call.carbon index f79b52f5c813..70ed8a5f834f 100644 --- a/toolchain/check/testdata/generic/template/call.carbon +++ b/toolchain/check/testdata/generic/template/call.carbon @@ -20,17 +20,10 @@ fn F[template G: type](H: G, x: X) { } fn TakeX(unused x: X) {} -// CHECK:STDERR: fail_todo_dependent_call_nonconst_arg.carbon:[[@LINE+14]]:23: error: expression cannot be used as a value [UseOfNonExprAsValue] -// CHECK:STDERR: fn GoodCall(x: X) { F(TakeX, x); } -// CHECK:STDERR: ^~~~~ -// CHECK:STDERR: fail_todo_dependent_call_nonconst_arg.carbon:[[@LINE-8]]:24: note: initializing function parameter [InCallToFunctionParam] -// CHECK:STDERR: fn F[template G: type](H: G, x: X) { -// CHECK:STDERR: ^~~~ -// CHECK:STDERR: // CHECK:STDERR: fail_todo_dependent_call_nonconst_arg.carbon:[[@LINE+7]]:21: error: unable to monomorphize specific `F()` [ResolvingSpecificHere] // CHECK:STDERR: fn GoodCall(x: X) { F(TakeX, x); } // CHECK:STDERR: ^ -// CHECK:STDERR: fail_todo_dependent_call_nonconst_arg.carbon:[[@LINE-14]]:3: note: value of type `` is not callable [CallToNonCallable] +// CHECK:STDERR: fail_todo_dependent_call_nonconst_arg.carbon:[[@LINE-7]]:3: note: value of type `` is not callable [CallToNonCallable] // CHECK:STDERR: H(x); // CHECK:STDERR: ^~~~ // CHECK:STDERR: @@ -47,17 +40,10 @@ fn F[template G: type](H: G, x: X) { fn TakeY(unused y: Y) {} // TODO: should fail, but not because of UseOfNonExprAsValue -// CHECK:STDERR: fail_dependent_call_nonconst_arg_wrong_type.carbon:[[@LINE+14]]:22: error: expression cannot be used as a value [UseOfNonExprAsValue] -// CHECK:STDERR: fn BadCall(x: X) { F(TakeY, x); } -// CHECK:STDERR: ^~~~~ -// CHECK:STDERR: fail_dependent_call_nonconst_arg_wrong_type.carbon:[[@LINE-9]]:24: note: initializing function parameter [InCallToFunctionParam] -// CHECK:STDERR: fn F[template G: type](H: G, x: X) { -// CHECK:STDERR: ^~~~ -// CHECK:STDERR: // CHECK:STDERR: fail_dependent_call_nonconst_arg_wrong_type.carbon:[[@LINE+7]]:20: error: unable to monomorphize specific `F()` [ResolvingSpecificHere] // CHECK:STDERR: fn BadCall(x: X) { F(TakeY, x); } // CHECK:STDERR: ^ -// CHECK:STDERR: fail_dependent_call_nonconst_arg_wrong_type.carbon:[[@LINE-15]]:3: note: value of type `` is not callable [CallToNonCallable] +// CHECK:STDERR: fail_dependent_call_nonconst_arg_wrong_type.carbon:[[@LINE-8]]:3: note: value of type `` is not callable [CallToNonCallable] // CHECK:STDERR: H(x); // CHECK:STDERR: ^~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/index/fail_invalid_base.carbon b/toolchain/check/testdata/index/fail_invalid_base.carbon index fc174eabf6a4..88a70b7d1839 100644 --- a/toolchain/check/testdata/index/fail_invalid_base.carbon +++ b/toolchain/check/testdata/index/fail_invalid_base.carbon @@ -21,9 +21,9 @@ namespace N; var a: i32 = N[0]; fn F(); -// CHECK:STDERR: fail_invalid_base.carbon:[[@LINE+4]]:14: error: expression cannot be used as a value [UseOfNonExprAsValue] +// CHECK:STDERR: fail_invalid_base.carbon:[[@LINE+4]]:14: error: cannot access member of interface `Core.IndexWith(Core.IntLiteral)` in type `` that does not implement that interface [MissingImplInMemberAccess] // CHECK:STDERR: var b: i32 = F[1]; -// CHECK:STDERR: ^ +// CHECK:STDERR: ^~~~ // CHECK:STDERR: var b: i32 = F[1]; @@ -56,13 +56,13 @@ var d: i32 = {.a: i32, .b: i32}[0]; // CHECK:STDOUT: %b.patt: %pattern_type.6b6 = ref_binding_pattern b [concrete] // CHECK:STDOUT: %b.var_patt: %pattern_type.6b6 = var_pattern %b.patt [concrete] // CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete] +// CHECK:STDOUT: %IndexWith.type.df6: type = generic_interface_type @IndexWith [concrete] +// CHECK:STDOUT: %IndexWith.generic: %IndexWith.type.df6 = struct_value () [concrete] // CHECK:STDOUT: %c.patt: %pattern_type.6b6 = ref_binding_pattern c [concrete] // CHECK:STDOUT: %c.var_patt: %pattern_type.6b6 = var_pattern %c.patt [concrete] // CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete] // CHECK:STDOUT: %struct_type.a.b.cfd: type = struct_type {.a: Core.IntLiteral, .b: Core.IntLiteral} [concrete] // CHECK:STDOUT: %struct: %struct_type.a.b.cfd = struct_value (%int_1, %int_2) [concrete] -// CHECK:STDOUT: %IndexWith.type.df6: type = generic_interface_type @IndexWith [concrete] -// CHECK:STDOUT: %IndexWith.generic: %IndexWith.type.df6 = struct_value () [concrete] // CHECK:STDOUT: %d.patt: %pattern_type.6b6 = ref_binding_pattern d [concrete] // CHECK:STDOUT: %d.var_patt: %pattern_type.6b6 = var_pattern %d.patt [concrete] // CHECK:STDOUT: %struct_type.a.b.b4c: type = struct_type {.a: %i32, .b: %i32} [concrete] diff --git a/toolchain/check/testdata/interop/cpp/function/import/decayed_param.carbon b/toolchain/check/testdata/interop/cpp/function/import/decayed_param.carbon index 953e457ffefd..dcc1b95fe719 100644 --- a/toolchain/check/testdata/interop/cpp/function/import/decayed_param.carbon +++ b/toolchain/check/testdata/interop/cpp/function/import/decayed_param.carbon @@ -31,6 +31,8 @@ fn F() { Cpp.TakesArray(&n[0]); Cpp.TakesArray(Cpp.nullptr); + + Cpp.TakesFunction(G); //@dump-sem-ir-end } @@ -44,12 +46,6 @@ fn G(n: i32) -> i32; fn F() { //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_call_params_2.carbon:[[@LINE+4]]:21: error: call argument of type `` is not supported [CppCallArgTypeNotSupported] - // CHECK:STDERR: Cpp.TakesFunction(G); - // CHECK:STDERR: ^ - // CHECK:STDERR: - Cpp.TakesFunction(G); - // CHECK:STDERR: fail_todo_call_params_2.carbon:[[@LINE+4]]:21: error: call argument of type `` is not supported [CppCallArgTypeNotSupported] // CHECK:STDERR: Cpp.TakesFunction(Cpp.Function); // CHECK:STDERR: ^~~~~~~~~~~~ @@ -58,9 +54,9 @@ fn F() { var n: array(i32, 42); // CHECK:STDERR: fail_todo_call_params_2.carbon:[[@LINE+8]]:26: error: no matching function for call to 'TakesFunction' [CppInteropParseError] - // CHECK:STDERR: 31 | Cpp.TakesFunction(&n[0]); + // CHECK:STDERR: 25 | Cpp.TakesFunction(&n[0]); // CHECK:STDERR: | ^ - // CHECK:STDERR: fail_todo_call_params_2.carbon:[[@LINE-22]]:10: in file included here [InCppInclude] + // CHECK:STDERR: fail_todo_call_params_2.carbon:[[@LINE-16]]:10: in file included here [InCppInclude] // CHECK:STDERR: ./params.h:3:6: note: candidate function not viable: no known conversion from 'int * _Nonnull' to 'int (*)(int)' for 1st argument [CppInteropParseNote] // CHECK:STDERR: 3 | void TakesFunction(int f(int)); // CHECK:STDERR: | ^ ~~~~~~~~~~ @@ -73,7 +69,7 @@ fn F() { // CHECK:STDERR: fail_todo_call_params_2.carbon:[[@LINE+8]]:21: note: type `Cpp.nullptr_t` does not implement interface `Core.ImplicitAs()` [MissingImplInMemberAccessInContext] // CHECK:STDERR: Cpp.TakesFunction(Cpp.nullptr); // CHECK:STDERR: ^~~~~~~~~~~ - // CHECK:STDERR: fail_todo_call_params_2.carbon:[[@LINE-35]]:10: in file included here [InCppInclude] + // CHECK:STDERR: fail_todo_call_params_2.carbon:[[@LINE-29]]:10: in file included here [InCppInclude] // CHECK:STDERR: ./params.h:3:24: note: initializing function parameter [InCallToFunctionParam] // CHECK:STDERR: void TakesFunction(int f(int)); // CHECK:STDERR: ^ @@ -90,6 +86,8 @@ fn F() { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] // CHECK:STDOUT: %pattern_type.6b6: type = pattern_type %i32 [concrete] +// CHECK:STDOUT: %G.type: type = fn_type @G [concrete] +// CHECK:STDOUT: %G: %G.type = struct_value () [concrete] // CHECK:STDOUT: %int_42: Core.IntLiteral = int_value 42 [concrete] // CHECK:STDOUT: %array_type.d58: type = array_type %int_42, %i32 [concrete] // CHECK:STDOUT: %pattern_type.c07: type = pattern_type %array_type.d58 [concrete] @@ -204,6 +202,12 @@ fn F() { // CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.bound: = bound_method %uninit, %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.60f [concrete] // CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.specific_fn: = specific_function %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.60f, @Cpp.nullptr_t.as.ImplicitAs.impl.Convert(%i32) [concrete] // CHECK:STDOUT: %bound_method.518: = bound_method %uninit, %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.specific_fn [concrete] +// CHECK:STDOUT: %TakesFunction.cpp_overload_set.type: type = cpp_overload_set_type @TakesFunction.cpp_overload_set [concrete] +// CHECK:STDOUT: %TakesFunction.cpp_overload_set.value: %TakesFunction.cpp_overload_set.type = cpp_overload_set_value @TakesFunction.cpp_overload_set [concrete] +// CHECK:STDOUT: %.659: type = cpp_fn_ptr_type clang_function_pointer_type7E000000 [concrete] +// CHECK:STDOUT: %TakesFunction.type: type = fn_type @TakesFunction [concrete] +// CHECK:STDOUT: %TakesFunction: %TakesFunction.type = struct_value () [concrete] +// CHECK:STDOUT: %.266: %.659 = cpp_addr_of_fn %G, @G [concrete] // CHECK:STDOUT: %self.param_patt.705: %pattern_type.6b6 = ref_param_pattern [concrete] // CHECK:STDOUT: %self.patt.70d: %pattern_type.6b6 = wrapper_binding_pattern self, %self.param_patt.705 [concrete] // CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.type.dfcbdb.6: type = fn_type @Destroy.WithSelf.SubobjectDestroy.loc10_3.1 [concrete] @@ -266,6 +270,7 @@ fn F() { // CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { // CHECK:STDOUT: .TakesArray = %TakesArray.cpp_overload_set.value // CHECK:STDOUT: .nullptr = @F.%uninit +// CHECK:STDOUT: .TakesFunction = %TakesFunction.cpp_overload_set.value // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import_ref.083: @T.as_type.as.DefaultOrUnformed.impl.52f.%T.as_type.as.DefaultOrUnformed.impl.Op.type (%T.as_type.as.DefaultOrUnformed.impl.Op.type.215) = import_ref Core//prelude/default, loc{{\d+_\d+}}, loaded [symbolic = @T.as_type.as.DefaultOrUnformed.impl.52f.%T.as_type.as.DefaultOrUnformed.impl.Op (constants.%T.as_type.as.DefaultOrUnformed.impl.Op.f65)] @@ -300,6 +305,12 @@ fn F() { // CHECK:STDOUT: %OptionalAs.impl_witness_table.2e9 = impl_witness_table (%Core.import_ref.017d8), @T.as_type.as.OptionalAs.impl [concrete] // CHECK:STDOUT: %Core.import_ref.49d: @Cpp.nullptr_t.as.ImplicitAs.impl.%Cpp.nullptr_t.as.ImplicitAs.impl.Convert.type (%Cpp.nullptr_t.as.ImplicitAs.impl.Convert.type.1b3) = import_ref Core//prelude/types/cpp/nullptr, loc{{\d+_\d+}}, loaded [symbolic = @Cpp.nullptr_t.as.ImplicitAs.impl.%Cpp.nullptr_t.as.ImplicitAs.impl.Convert (constants.%Cpp.nullptr_t.as.ImplicitAs.impl.Convert.208)] // CHECK:STDOUT: %ImplicitAs.impl_witness_table.898 = impl_witness_table (%Core.import_ref.49d), @Cpp.nullptr_t.as.ImplicitAs.impl [concrete] +// CHECK:STDOUT: %TakesFunction.cpp_overload_set.value: %TakesFunction.cpp_overload_set.type = cpp_overload_set_value @TakesFunction.cpp_overload_set [concrete = constants.%TakesFunction.cpp_overload_set.value] +// CHECK:STDOUT: %TakesFunction.decl: %TakesFunction.type = fn_decl @TakesFunction [concrete = constants.%TakesFunction] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generated { @@ -438,6 +449,12 @@ fn F() { // CHECK:STDOUT: %TakesArray.call.loc13: init %empty_tuple.type = call imports.%TakesArray.decl(%.loc13_21.4) // CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc13: = bound_method %.loc13_21.3, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.4 // CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc13: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc13(%.loc13_21.3) +// CHECK:STDOUT: %Cpp.ref.loc15: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %TakesFunction.ref: %TakesFunction.cpp_overload_set.type = name_ref TakesFunction, imports.%TakesFunction.cpp_overload_set.value [concrete = constants.%TakesFunction.cpp_overload_set.value] +// CHECK:STDOUT: %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G] +// CHECK:STDOUT: %.loc15_21.1: %.659 = cpp_addr_of_fn %G.ref, @G [concrete = constants.%.266] +// CHECK:STDOUT: %.loc15_21.2: %.659 = converted %G.ref, %.loc15_21.1 [concrete = constants.%.266] +// CHECK:STDOUT: %TakesFunction.call: init %empty_tuple.type = call imports.%TakesFunction.decl(%.loc15_21.2) // CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc10: = bound_method %n.var, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.7 // CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc10: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc10(%n.var) // CHECK:STDOUT: @@ -677,8 +694,6 @@ fn F() { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] // CHECK:STDOUT: %pattern_type.6b6: type = pattern_type %i32 [concrete] -// CHECK:STDOUT: %G.type: type = fn_type @G [concrete] -// CHECK:STDOUT: %G: %G.type = struct_value () [concrete] // CHECK:STDOUT: %TakesFunction.cpp_overload_set.type: type = cpp_overload_set_type @TakesFunction.cpp_overload_set [concrete] // CHECK:STDOUT: %TakesFunction.cpp_overload_set.value: %TakesFunction.cpp_overload_set.type = cpp_overload_set_value @TakesFunction.cpp_overload_set [concrete] // CHECK:STDOUT: %Function.cpp_overload_set.type: type = cpp_overload_set_type @Function.cpp_overload_set [concrete] @@ -722,15 +737,15 @@ fn F() { // CHECK:STDOUT: %TakesFunction: %TakesFunction.type = struct_value () [concrete] // CHECK:STDOUT: %self.param_patt.705: %pattern_type.6b6 = ref_param_pattern [concrete] // CHECK:STDOUT: %self.patt.70d: %pattern_type.6b6 = wrapper_binding_pattern self, %self.param_patt.705 [concrete] -// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.type.dfcbdb.2: type = fn_type @Destroy.WithSelf.SubobjectDestroy.loc22_3.1 [concrete] +// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.type.dfcbdb.2: type = fn_type @Destroy.WithSelf.SubobjectDestroy.loc16_3.1 [concrete] // CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.d01daf.2: %Destroy.WithSelf.SubobjectDestroy.type.dfcbdb.2 = struct_value () [concrete] -// CHECK:STDOUT: %Destroy.WithSelf.Op.type.ef016f.2: type = fn_type @Destroy.WithSelf.Op.loc22_3.1 [concrete] +// CHECK:STDOUT: %Destroy.WithSelf.Op.type.ef016f.2: type = fn_type @Destroy.WithSelf.Op.loc16_3.1 [concrete] // CHECK:STDOUT: %Destroy.WithSelf.Op.403171.2: %Destroy.WithSelf.Op.type.ef016f.2 = struct_value () [concrete] -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.type.fbceb5.2: type = fn_type @Destroy.WithSelf.SelfDestruct.loc22_3.1 [concrete] +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.type.fbceb5.2: type = fn_type @Destroy.WithSelf.SelfDestruct.loc16_3.1 [concrete] // CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.db3fdb.2: %Destroy.WithSelf.SelfDestruct.type.fbceb5.2 = struct_value () [concrete] // CHECK:STDOUT: %self.param_patt.087: %pattern_type.c07 = ref_param_pattern [concrete] // CHECK:STDOUT: %self.patt.b22: %pattern_type.c07 = wrapper_binding_pattern self, %self.param_patt.087 [concrete] -// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.type.dfcbdb.3: type = fn_type @Destroy.WithSelf.SubobjectDestroy.loc22_3.2 [concrete] +// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.type.dfcbdb.3: type = fn_type @Destroy.WithSelf.SubobjectDestroy.loc16_3.2 [concrete] // CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.d01daf.3: %Destroy.WithSelf.SubobjectDestroy.type.dfcbdb.3 = struct_value () [concrete] // CHECK:STDOUT: %int_41: Core.IntLiteral = int_value 41 [concrete] // CHECK:STDOUT: %int_40: Core.IntLiteral = int_value 40 [concrete] @@ -772,9 +787,9 @@ fn F() { // CHECK:STDOUT: %int_3: Core.IntLiteral = int_value 3 [concrete] // CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete] // CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete] -// CHECK:STDOUT: %Destroy.WithSelf.Op.type.ef016f.3: type = fn_type @Destroy.WithSelf.Op.loc22_3.2 [concrete] +// CHECK:STDOUT: %Destroy.WithSelf.Op.type.ef016f.3: type = fn_type @Destroy.WithSelf.Op.loc16_3.2 [concrete] // CHECK:STDOUT: %Destroy.WithSelf.Op.403171.3: %Destroy.WithSelf.Op.type.ef016f.3 = struct_value () [concrete] -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.type.fbceb5.3: type = fn_type @Destroy.WithSelf.SelfDestruct.loc22_3.2 [concrete] +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.type.fbceb5.3: type = fn_type @Destroy.WithSelf.SelfDestruct.loc16_3.2 [concrete] // CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.db3fdb.3: %Destroy.WithSelf.SelfDestruct.type.fbceb5.3 = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -801,28 +816,28 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generated { -// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.decl.763c71.1: %Destroy.WithSelf.SubobjectDestroy.type.dfcbdb.2 = fn_decl @Destroy.WithSelf.SubobjectDestroy.loc22_3.1 [concrete = constants.%Destroy.WithSelf.SubobjectDestroy.d01daf.2] { +// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.decl.763c71.1: %Destroy.WithSelf.SubobjectDestroy.type.dfcbdb.2 = fn_decl @Destroy.WithSelf.SubobjectDestroy.loc16_3.1 [concrete = constants.%Destroy.WithSelf.SubobjectDestroy.d01daf.2] { // CHECK:STDOUT: %self.param_patt: %pattern_type.6b6 = ref_param_pattern [concrete = constants.%self.param_patt.705] // CHECK:STDOUT: %self.patt: %pattern_type.6b6 = wrapper_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.70d] // CHECK:STDOUT: } { // CHECK:STDOUT: %self.param: ref %i32 = ref_param call_param0 // CHECK:STDOUT: %self: ref %i32 = wrapper_binding self, %self.param // CHECK:STDOUT: } -// CHECK:STDOUT: %Destroy.WithSelf.Op.decl.5f94cf.1: %Destroy.WithSelf.Op.type.ef016f.2 = fn_decl @Destroy.WithSelf.Op.loc22_3.1 [concrete = constants.%Destroy.WithSelf.Op.403171.2] { +// CHECK:STDOUT: %Destroy.WithSelf.Op.decl.5f94cf.1: %Destroy.WithSelf.Op.type.ef016f.2 = fn_decl @Destroy.WithSelf.Op.loc16_3.1 [concrete = constants.%Destroy.WithSelf.Op.403171.2] { // CHECK:STDOUT: %self.param_patt: %pattern_type.6b6 = ref_param_pattern [concrete = constants.%self.param_patt.705] // CHECK:STDOUT: %self.patt: %pattern_type.6b6 = wrapper_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.70d] // CHECK:STDOUT: } { // CHECK:STDOUT: %self.param: ref %i32 = ref_param call_param0 // CHECK:STDOUT: %self: ref %i32 = wrapper_binding self, %self.param // CHECK:STDOUT: } -// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.decl.763c71.2: %Destroy.WithSelf.SubobjectDestroy.type.dfcbdb.3 = fn_decl @Destroy.WithSelf.SubobjectDestroy.loc22_3.2 [concrete = constants.%Destroy.WithSelf.SubobjectDestroy.d01daf.3] { +// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.decl.763c71.2: %Destroy.WithSelf.SubobjectDestroy.type.dfcbdb.3 = fn_decl @Destroy.WithSelf.SubobjectDestroy.loc16_3.2 [concrete = constants.%Destroy.WithSelf.SubobjectDestroy.d01daf.3] { // CHECK:STDOUT: %self.param_patt: %pattern_type.c07 = ref_param_pattern [concrete = constants.%self.param_patt.087] // CHECK:STDOUT: %self.patt: %pattern_type.c07 = wrapper_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.b22] // CHECK:STDOUT: } { // CHECK:STDOUT: %self.param: ref %array_type.d58 = ref_param call_param0 // CHECK:STDOUT: %self: ref %array_type.d58 = wrapper_binding self, %self.param // CHECK:STDOUT: } -// CHECK:STDOUT: %Destroy.WithSelf.Op.decl.5f94cf.2: %Destroy.WithSelf.Op.type.ef016f.3 = fn_decl @Destroy.WithSelf.Op.loc22_3.2 [concrete = constants.%Destroy.WithSelf.Op.403171.3] { +// CHECK:STDOUT: %Destroy.WithSelf.Op.decl.5f94cf.2: %Destroy.WithSelf.Op.type.ef016f.3 = fn_decl @Destroy.WithSelf.Op.loc16_3.2 [concrete = constants.%Destroy.WithSelf.Op.403171.3] { // CHECK:STDOUT: %self.param_patt: %pattern_type.c07 = ref_param_pattern [concrete = constants.%self.param_patt.087] // CHECK:STDOUT: %self.patt: %pattern_type.c07 = wrapper_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.b22] // CHECK:STDOUT: } { @@ -833,23 +848,20 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %Cpp.ref.loc14: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Cpp.ref.loc14_3: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %TakesFunction.ref.loc14: %TakesFunction.cpp_overload_set.type = name_ref TakesFunction, imports.%TakesFunction.cpp_overload_set.value [concrete = constants.%TakesFunction.cpp_overload_set.value] -// CHECK:STDOUT: %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G] -// CHECK:STDOUT: %Cpp.ref.loc20_3: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %TakesFunction.ref.loc20: %TakesFunction.cpp_overload_set.type = name_ref TakesFunction, imports.%TakesFunction.cpp_overload_set.value [concrete = constants.%TakesFunction.cpp_overload_set.value] -// CHECK:STDOUT: %Cpp.ref.loc20_21: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Cpp.ref.loc14_21: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %Function.ref: %Function.cpp_overload_set.type = name_ref Function, imports.%Function.cpp_overload_set.value [concrete = constants.%Function.cpp_overload_set.value] // CHECK:STDOUT: %n.var: ref %array_type.d58 = var_storage %n.var_patt // CHECK:STDOUT: %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%array_type.d58, (constants.%DefaultOrUnformed.impl_witness.06a) [concrete = constants.%DefaultOrUnformed.facet] -// CHECK:STDOUT: %.loc22_24.1: %DefaultOrUnformed.type = converted constants.%array_type.d58, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet] -// CHECK:STDOUT: %as_type: type = facet_access_type %.loc22_24.1 [concrete = constants.%array_type.d58] -// CHECK:STDOUT: %.loc22_24.2: type = converted %.loc22_24.1, %as_type [concrete = constants.%array_type.d58] +// CHECK:STDOUT: %.loc16_24.1: %DefaultOrUnformed.type = converted constants.%array_type.d58, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet] +// CHECK:STDOUT: %as_type: type = facet_access_type %.loc16_24.1 [concrete = constants.%array_type.d58] +// CHECK:STDOUT: %.loc16_24.2: type = converted %.loc16_24.1, %as_type [concrete = constants.%array_type.d58] // CHECK:STDOUT: -// CHECK:STDOUT: %.loc22_3: ref %array_type.d58 = splice_block %n.var {} -// CHECK:STDOUT: %T.as_type.as.DefaultOrUnformed.impl.Op.call: init %array_type.d58 to %.loc22_3 = call %T.as_type.as.DefaultOrUnformed.impl.Op.specific_fn() +// CHECK:STDOUT: %.loc16_3: ref %array_type.d58 = splice_block %n.var {} +// CHECK:STDOUT: %T.as_type.as.DefaultOrUnformed.impl.Op.call: init %array_type.d58 to %.loc16_3 = call %T.as_type.as.DefaultOrUnformed.impl.Op.specific_fn() // CHECK:STDOUT: assign %n.var, %T.as_type.as.DefaultOrUnformed.impl.Op.call -// CHECK:STDOUT: %.loc22_23: type = splice_block %array_type [concrete = constants.%array_type.d58] { +// CHECK:STDOUT: %.loc16_23: type = splice_block %array_type [concrete = constants.%array_type.d58] { // CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %int_42: Core.IntLiteral = int_value 42 [concrete = constants.%int_42] // CHECK:STDOUT: %array_type: type = array_type %int_42, %i32 [concrete = constants.%array_type.d58] @@ -859,218 +871,218 @@ fn F() { // CHECK:STDOUT: %n.patt: %pattern_type.c07 = ref_binding_pattern n [concrete = constants.%n.patt.dac] // CHECK:STDOUT: %n.var_patt: %pattern_type.c07 = var_pattern %n.patt [concrete = constants.%n.var_patt] // CHECK:STDOUT: } -// CHECK:STDOUT: %Cpp.ref.loc31: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %TakesFunction.ref.loc31: %TakesFunction.cpp_overload_set.type = name_ref TakesFunction, imports.%TakesFunction.cpp_overload_set.value [concrete = constants.%TakesFunction.cpp_overload_set.value] +// CHECK:STDOUT: %Cpp.ref.loc25: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %TakesFunction.ref.loc25: %TakesFunction.cpp_overload_set.type = name_ref TakesFunction, imports.%TakesFunction.cpp_overload_set.value [concrete = constants.%TakesFunction.cpp_overload_set.value] // CHECK:STDOUT: %n.ref: ref %array_type.d58 = name_ref n, %n // CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6] // CHECK:STDOUT: %impl.elem0: %.b7a = impl_witness_access constants.%ImplicitAs.impl_witness.a2a, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.e39] -// CHECK:STDOUT: %bound_method.loc31_24.1: = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] +// CHECK:STDOUT: %bound_method.loc25_24.1: = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] // CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] -// CHECK:STDOUT: %bound_method.loc31_24.2: = bound_method %int_0, %specific_fn [concrete = constants.%bound_method] -// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc31_24.2(%int_0) [concrete = constants.%int_0.3c0] -// CHECK:STDOUT: %.loc31_24.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.3c0] -// CHECK:STDOUT: %.loc31_24.2: %i32 = converted %int_0, %.loc31_24.1 [concrete = constants.%int_0.3c0] -// CHECK:STDOUT: %.loc31_25: ref %i32 = array_index %n.ref, %.loc31_24.2 -// CHECK:STDOUT: %addr: %ptr.d08 = addr_of %.loc31_25 -// CHECK:STDOUT: %Cpp.ref.loc44_3: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %TakesFunction.ref.loc44: %TakesFunction.cpp_overload_set.type = name_ref TakesFunction, imports.%TakesFunction.cpp_overload_set.value [concrete = constants.%TakesFunction.cpp_overload_set.value] -// CHECK:STDOUT: %Cpp.ref.loc44_21: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %bound_method.loc25_24.2: = bound_method %int_0, %specific_fn [concrete = constants.%bound_method] +// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc25_24.2(%int_0) [concrete = constants.%int_0.3c0] +// CHECK:STDOUT: %.loc25_24.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.3c0] +// CHECK:STDOUT: %.loc25_24.2: %i32 = converted %int_0, %.loc25_24.1 [concrete = constants.%int_0.3c0] +// CHECK:STDOUT: %.loc25_25: ref %i32 = array_index %n.ref, %.loc25_24.2 +// CHECK:STDOUT: %addr: %ptr.d08 = addr_of %.loc25_25 +// CHECK:STDOUT: %Cpp.ref.loc38_3: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %TakesFunction.ref.loc38: %TakesFunction.cpp_overload_set.type = name_ref TakesFunction, imports.%TakesFunction.cpp_overload_set.value [concrete = constants.%TakesFunction.cpp_overload_set.value] +// CHECK:STDOUT: %Cpp.ref.loc38_21: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: // CHECK:STDOUT: %nullptr.ref: %Cpp.nullptr_t = name_ref nullptr, %uninit [concrete = constants.%uninit] -// CHECK:STDOUT: %.loc44: %.659 = converted %nullptr.ref, [concrete = ] +// CHECK:STDOUT: %.loc38: %.659 = converted %nullptr.ref, [concrete = ] // CHECK:STDOUT: %TakesFunction.call: init %empty_tuple.type = call imports.%TakesFunction.decl() // CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound: = bound_method %n.var, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.3 // CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound(%n.var) // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Destroy.WithSelf.SubobjectDestroy.loc22_3.1(%self.param: ref %i32) = "no_op"; +// CHECK:STDOUT: fn @Destroy.WithSelf.SubobjectDestroy.loc16_3.1(%self.param: ref %i32) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Destroy.WithSelf.Op.loc22_3.1(%self.param: ref %i32) = "no_op"; +// CHECK:STDOUT: fn @Destroy.WithSelf.Op.loc16_3.1(%self.param: ref %i32) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Destroy.WithSelf.SelfDestruct.loc22_3.1(%self.param: ref %i32) { +// CHECK:STDOUT: fn @Destroy.WithSelf.SelfDestruct.loc16_3.1(%self.param: ref %i32) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %Destroy.WithSelf.Op.call: init %empty_tuple.type = call generated.%Destroy.WithSelf.Op.decl.5f94cf.1(%self.param) // CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.call: init %empty_tuple.type = call generated.%Destroy.WithSelf.SubobjectDestroy.decl.763c71.1(%self.param) // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Destroy.WithSelf.SubobjectDestroy.loc22_3.2(%self.param: ref %array_type.d58) { +// CHECK:STDOUT: fn @Destroy.WithSelf.SubobjectDestroy.loc16_3.2(%self.param: ref %array_type.d58) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %int_41: Core.IntLiteral = int_value 41 [concrete = constants.%int_41] -// CHECK:STDOUT: %.loc22_3.1: ref %i32 = array_index %self.param, %int_41 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.1: = bound_method %.loc22_3.1, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.1: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.1(%.loc22_3.1) +// CHECK:STDOUT: %.loc16_3.1: ref %i32 = array_index %self.param, %int_41 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.1: = bound_method %.loc16_3.1, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.1: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.1(%.loc16_3.1) // CHECK:STDOUT: %int_40: Core.IntLiteral = int_value 40 [concrete = constants.%int_40] -// CHECK:STDOUT: %.loc22_3.2: ref %i32 = array_index %self.param, %int_40 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.2: = bound_method %.loc22_3.2, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.2: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.2(%.loc22_3.2) +// CHECK:STDOUT: %.loc16_3.2: ref %i32 = array_index %self.param, %int_40 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.2: = bound_method %.loc16_3.2, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.2: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.2(%.loc16_3.2) // CHECK:STDOUT: %int_39: Core.IntLiteral = int_value 39 [concrete = constants.%int_39] -// CHECK:STDOUT: %.loc22_3.3: ref %i32 = array_index %self.param, %int_39 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.3: = bound_method %.loc22_3.3, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.3: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.3(%.loc22_3.3) +// CHECK:STDOUT: %.loc16_3.3: ref %i32 = array_index %self.param, %int_39 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.3: = bound_method %.loc16_3.3, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.3: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.3(%.loc16_3.3) // CHECK:STDOUT: %int_38: Core.IntLiteral = int_value 38 [concrete = constants.%int_38] -// CHECK:STDOUT: %.loc22_3.4: ref %i32 = array_index %self.param, %int_38 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.4: = bound_method %.loc22_3.4, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.4: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.4(%.loc22_3.4) +// CHECK:STDOUT: %.loc16_3.4: ref %i32 = array_index %self.param, %int_38 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.4: = bound_method %.loc16_3.4, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.4: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.4(%.loc16_3.4) // CHECK:STDOUT: %int_37: Core.IntLiteral = int_value 37 [concrete = constants.%int_37] -// CHECK:STDOUT: %.loc22_3.5: ref %i32 = array_index %self.param, %int_37 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.5: = bound_method %.loc22_3.5, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.5: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.5(%.loc22_3.5) +// CHECK:STDOUT: %.loc16_3.5: ref %i32 = array_index %self.param, %int_37 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.5: = bound_method %.loc16_3.5, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.5: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.5(%.loc16_3.5) // CHECK:STDOUT: %int_36: Core.IntLiteral = int_value 36 [concrete = constants.%int_36] -// CHECK:STDOUT: %.loc22_3.6: ref %i32 = array_index %self.param, %int_36 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.6: = bound_method %.loc22_3.6, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.6: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.6(%.loc22_3.6) +// CHECK:STDOUT: %.loc16_3.6: ref %i32 = array_index %self.param, %int_36 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.6: = bound_method %.loc16_3.6, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.6: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.6(%.loc16_3.6) // CHECK:STDOUT: %int_35: Core.IntLiteral = int_value 35 [concrete = constants.%int_35] -// CHECK:STDOUT: %.loc22_3.7: ref %i32 = array_index %self.param, %int_35 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.7: = bound_method %.loc22_3.7, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.7: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.7(%.loc22_3.7) +// CHECK:STDOUT: %.loc16_3.7: ref %i32 = array_index %self.param, %int_35 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.7: = bound_method %.loc16_3.7, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.7: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.7(%.loc16_3.7) // CHECK:STDOUT: %int_34: Core.IntLiteral = int_value 34 [concrete = constants.%int_34] -// CHECK:STDOUT: %.loc22_3.8: ref %i32 = array_index %self.param, %int_34 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.8: = bound_method %.loc22_3.8, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.8: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.8(%.loc22_3.8) +// CHECK:STDOUT: %.loc16_3.8: ref %i32 = array_index %self.param, %int_34 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.8: = bound_method %.loc16_3.8, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.8: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.8(%.loc16_3.8) // CHECK:STDOUT: %int_33: Core.IntLiteral = int_value 33 [concrete = constants.%int_33] -// CHECK:STDOUT: %.loc22_3.9: ref %i32 = array_index %self.param, %int_33 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.9: = bound_method %.loc22_3.9, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.9: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.9(%.loc22_3.9) +// CHECK:STDOUT: %.loc16_3.9: ref %i32 = array_index %self.param, %int_33 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.9: = bound_method %.loc16_3.9, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.9: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.9(%.loc16_3.9) // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32] -// CHECK:STDOUT: %.loc22_3.10: ref %i32 = array_index %self.param, %int_32 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.10: = bound_method %.loc22_3.10, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.10: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.10(%.loc22_3.10) +// CHECK:STDOUT: %.loc16_3.10: ref %i32 = array_index %self.param, %int_32 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.10: = bound_method %.loc16_3.10, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.10: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.10(%.loc16_3.10) // CHECK:STDOUT: %int_31: Core.IntLiteral = int_value 31 [concrete = constants.%int_31] -// CHECK:STDOUT: %.loc22_3.11: ref %i32 = array_index %self.param, %int_31 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.11: = bound_method %.loc22_3.11, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.11: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.11(%.loc22_3.11) +// CHECK:STDOUT: %.loc16_3.11: ref %i32 = array_index %self.param, %int_31 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.11: = bound_method %.loc16_3.11, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.11: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.11(%.loc16_3.11) // CHECK:STDOUT: %int_30: Core.IntLiteral = int_value 30 [concrete = constants.%int_30] -// CHECK:STDOUT: %.loc22_3.12: ref %i32 = array_index %self.param, %int_30 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.12: = bound_method %.loc22_3.12, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.12: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.12(%.loc22_3.12) +// CHECK:STDOUT: %.loc16_3.12: ref %i32 = array_index %self.param, %int_30 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.12: = bound_method %.loc16_3.12, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.12: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.12(%.loc16_3.12) // CHECK:STDOUT: %int_29: Core.IntLiteral = int_value 29 [concrete = constants.%int_29] -// CHECK:STDOUT: %.loc22_3.13: ref %i32 = array_index %self.param, %int_29 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.13: = bound_method %.loc22_3.13, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.13: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.13(%.loc22_3.13) +// CHECK:STDOUT: %.loc16_3.13: ref %i32 = array_index %self.param, %int_29 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.13: = bound_method %.loc16_3.13, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.13: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.13(%.loc16_3.13) // CHECK:STDOUT: %int_28: Core.IntLiteral = int_value 28 [concrete = constants.%int_28] -// CHECK:STDOUT: %.loc22_3.14: ref %i32 = array_index %self.param, %int_28 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.14: = bound_method %.loc22_3.14, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.14: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.14(%.loc22_3.14) +// CHECK:STDOUT: %.loc16_3.14: ref %i32 = array_index %self.param, %int_28 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.14: = bound_method %.loc16_3.14, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.14: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.14(%.loc16_3.14) // CHECK:STDOUT: %int_27: Core.IntLiteral = int_value 27 [concrete = constants.%int_27] -// CHECK:STDOUT: %.loc22_3.15: ref %i32 = array_index %self.param, %int_27 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.15: = bound_method %.loc22_3.15, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.15: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.15(%.loc22_3.15) +// CHECK:STDOUT: %.loc16_3.15: ref %i32 = array_index %self.param, %int_27 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.15: = bound_method %.loc16_3.15, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.15: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.15(%.loc16_3.15) // CHECK:STDOUT: %int_26: Core.IntLiteral = int_value 26 [concrete = constants.%int_26] -// CHECK:STDOUT: %.loc22_3.16: ref %i32 = array_index %self.param, %int_26 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.16: = bound_method %.loc22_3.16, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.16: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.16(%.loc22_3.16) +// CHECK:STDOUT: %.loc16_3.16: ref %i32 = array_index %self.param, %int_26 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.16: = bound_method %.loc16_3.16, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.16: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.16(%.loc16_3.16) // CHECK:STDOUT: %int_25: Core.IntLiteral = int_value 25 [concrete = constants.%int_25] -// CHECK:STDOUT: %.loc22_3.17: ref %i32 = array_index %self.param, %int_25 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.17: = bound_method %.loc22_3.17, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.17: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.17(%.loc22_3.17) +// CHECK:STDOUT: %.loc16_3.17: ref %i32 = array_index %self.param, %int_25 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.17: = bound_method %.loc16_3.17, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.17: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.17(%.loc16_3.17) // CHECK:STDOUT: %int_24: Core.IntLiteral = int_value 24 [concrete = constants.%int_24] -// CHECK:STDOUT: %.loc22_3.18: ref %i32 = array_index %self.param, %int_24 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.18: = bound_method %.loc22_3.18, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.18: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.18(%.loc22_3.18) +// CHECK:STDOUT: %.loc16_3.18: ref %i32 = array_index %self.param, %int_24 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.18: = bound_method %.loc16_3.18, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.18: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.18(%.loc16_3.18) // CHECK:STDOUT: %int_23: Core.IntLiteral = int_value 23 [concrete = constants.%int_23] -// CHECK:STDOUT: %.loc22_3.19: ref %i32 = array_index %self.param, %int_23 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.19: = bound_method %.loc22_3.19, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.19: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.19(%.loc22_3.19) +// CHECK:STDOUT: %.loc16_3.19: ref %i32 = array_index %self.param, %int_23 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.19: = bound_method %.loc16_3.19, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.19: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.19(%.loc16_3.19) // CHECK:STDOUT: %int_22: Core.IntLiteral = int_value 22 [concrete = constants.%int_22] -// CHECK:STDOUT: %.loc22_3.20: ref %i32 = array_index %self.param, %int_22 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.20: = bound_method %.loc22_3.20, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.20: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.20(%.loc22_3.20) +// CHECK:STDOUT: %.loc16_3.20: ref %i32 = array_index %self.param, %int_22 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.20: = bound_method %.loc16_3.20, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.20: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.20(%.loc16_3.20) // CHECK:STDOUT: %int_21: Core.IntLiteral = int_value 21 [concrete = constants.%int_21] -// CHECK:STDOUT: %.loc22_3.21: ref %i32 = array_index %self.param, %int_21 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.21: = bound_method %.loc22_3.21, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.21: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.21(%.loc22_3.21) +// CHECK:STDOUT: %.loc16_3.21: ref %i32 = array_index %self.param, %int_21 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.21: = bound_method %.loc16_3.21, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.21: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.21(%.loc16_3.21) // CHECK:STDOUT: %int_20: Core.IntLiteral = int_value 20 [concrete = constants.%int_20] -// CHECK:STDOUT: %.loc22_3.22: ref %i32 = array_index %self.param, %int_20 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.22: = bound_method %.loc22_3.22, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.22: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.22(%.loc22_3.22) +// CHECK:STDOUT: %.loc16_3.22: ref %i32 = array_index %self.param, %int_20 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.22: = bound_method %.loc16_3.22, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.22: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.22(%.loc16_3.22) // CHECK:STDOUT: %int_19: Core.IntLiteral = int_value 19 [concrete = constants.%int_19] -// CHECK:STDOUT: %.loc22_3.23: ref %i32 = array_index %self.param, %int_19 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.23: = bound_method %.loc22_3.23, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.23: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.23(%.loc22_3.23) +// CHECK:STDOUT: %.loc16_3.23: ref %i32 = array_index %self.param, %int_19 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.23: = bound_method %.loc16_3.23, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.23: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.23(%.loc16_3.23) // CHECK:STDOUT: %int_18: Core.IntLiteral = int_value 18 [concrete = constants.%int_18] -// CHECK:STDOUT: %.loc22_3.24: ref %i32 = array_index %self.param, %int_18 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.24: = bound_method %.loc22_3.24, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.24: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.24(%.loc22_3.24) +// CHECK:STDOUT: %.loc16_3.24: ref %i32 = array_index %self.param, %int_18 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.24: = bound_method %.loc16_3.24, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.24: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.24(%.loc16_3.24) // CHECK:STDOUT: %int_17: Core.IntLiteral = int_value 17 [concrete = constants.%int_17] -// CHECK:STDOUT: %.loc22_3.25: ref %i32 = array_index %self.param, %int_17 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.25: = bound_method %.loc22_3.25, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.25: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.25(%.loc22_3.25) +// CHECK:STDOUT: %.loc16_3.25: ref %i32 = array_index %self.param, %int_17 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.25: = bound_method %.loc16_3.25, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.25: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.25(%.loc16_3.25) // CHECK:STDOUT: %int_16: Core.IntLiteral = int_value 16 [concrete = constants.%int_16] -// CHECK:STDOUT: %.loc22_3.26: ref %i32 = array_index %self.param, %int_16 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.26: = bound_method %.loc22_3.26, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.26: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.26(%.loc22_3.26) +// CHECK:STDOUT: %.loc16_3.26: ref %i32 = array_index %self.param, %int_16 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.26: = bound_method %.loc16_3.26, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.26: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.26(%.loc16_3.26) // CHECK:STDOUT: %int_15: Core.IntLiteral = int_value 15 [concrete = constants.%int_15] -// CHECK:STDOUT: %.loc22_3.27: ref %i32 = array_index %self.param, %int_15 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.27: = bound_method %.loc22_3.27, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.27: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.27(%.loc22_3.27) +// CHECK:STDOUT: %.loc16_3.27: ref %i32 = array_index %self.param, %int_15 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.27: = bound_method %.loc16_3.27, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.27: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.27(%.loc16_3.27) // CHECK:STDOUT: %int_14: Core.IntLiteral = int_value 14 [concrete = constants.%int_14] -// CHECK:STDOUT: %.loc22_3.28: ref %i32 = array_index %self.param, %int_14 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.28: = bound_method %.loc22_3.28, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.28: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.28(%.loc22_3.28) +// CHECK:STDOUT: %.loc16_3.28: ref %i32 = array_index %self.param, %int_14 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.28: = bound_method %.loc16_3.28, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.28: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.28(%.loc16_3.28) // CHECK:STDOUT: %int_13: Core.IntLiteral = int_value 13 [concrete = constants.%int_13] -// CHECK:STDOUT: %.loc22_3.29: ref %i32 = array_index %self.param, %int_13 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.29: = bound_method %.loc22_3.29, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.29: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.29(%.loc22_3.29) +// CHECK:STDOUT: %.loc16_3.29: ref %i32 = array_index %self.param, %int_13 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.29: = bound_method %.loc16_3.29, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.29: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.29(%.loc16_3.29) // CHECK:STDOUT: %int_12: Core.IntLiteral = int_value 12 [concrete = constants.%int_12] -// CHECK:STDOUT: %.loc22_3.30: ref %i32 = array_index %self.param, %int_12 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.30: = bound_method %.loc22_3.30, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.30: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.30(%.loc22_3.30) +// CHECK:STDOUT: %.loc16_3.30: ref %i32 = array_index %self.param, %int_12 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.30: = bound_method %.loc16_3.30, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.30: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.30(%.loc16_3.30) // CHECK:STDOUT: %int_11: Core.IntLiteral = int_value 11 [concrete = constants.%int_11] -// CHECK:STDOUT: %.loc22_3.31: ref %i32 = array_index %self.param, %int_11 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.31: = bound_method %.loc22_3.31, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.31: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.31(%.loc22_3.31) +// CHECK:STDOUT: %.loc16_3.31: ref %i32 = array_index %self.param, %int_11 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.31: = bound_method %.loc16_3.31, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.31: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.31(%.loc16_3.31) // CHECK:STDOUT: %int_10: Core.IntLiteral = int_value 10 [concrete = constants.%int_10] -// CHECK:STDOUT: %.loc22_3.32: ref %i32 = array_index %self.param, %int_10 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.32: = bound_method %.loc22_3.32, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.32: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.32(%.loc22_3.32) +// CHECK:STDOUT: %.loc16_3.32: ref %i32 = array_index %self.param, %int_10 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.32: = bound_method %.loc16_3.32, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.32: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.32(%.loc16_3.32) // CHECK:STDOUT: %int_9: Core.IntLiteral = int_value 9 [concrete = constants.%int_9] -// CHECK:STDOUT: %.loc22_3.33: ref %i32 = array_index %self.param, %int_9 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.33: = bound_method %.loc22_3.33, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.33: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.33(%.loc22_3.33) +// CHECK:STDOUT: %.loc16_3.33: ref %i32 = array_index %self.param, %int_9 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.33: = bound_method %.loc16_3.33, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.33: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.33(%.loc16_3.33) // CHECK:STDOUT: %int_8: Core.IntLiteral = int_value 8 [concrete = constants.%int_8] -// CHECK:STDOUT: %.loc22_3.34: ref %i32 = array_index %self.param, %int_8 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.34: = bound_method %.loc22_3.34, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.34: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.34(%.loc22_3.34) +// CHECK:STDOUT: %.loc16_3.34: ref %i32 = array_index %self.param, %int_8 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.34: = bound_method %.loc16_3.34, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.34: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.34(%.loc16_3.34) // CHECK:STDOUT: %int_7: Core.IntLiteral = int_value 7 [concrete = constants.%int_7] -// CHECK:STDOUT: %.loc22_3.35: ref %i32 = array_index %self.param, %int_7 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.35: = bound_method %.loc22_3.35, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.35: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.35(%.loc22_3.35) +// CHECK:STDOUT: %.loc16_3.35: ref %i32 = array_index %self.param, %int_7 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.35: = bound_method %.loc16_3.35, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.35: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.35(%.loc16_3.35) // CHECK:STDOUT: %int_6: Core.IntLiteral = int_value 6 [concrete = constants.%int_6] -// CHECK:STDOUT: %.loc22_3.36: ref %i32 = array_index %self.param, %int_6 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.36: = bound_method %.loc22_3.36, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.36: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.36(%.loc22_3.36) +// CHECK:STDOUT: %.loc16_3.36: ref %i32 = array_index %self.param, %int_6 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.36: = bound_method %.loc16_3.36, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.36: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.36(%.loc16_3.36) // CHECK:STDOUT: %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5] -// CHECK:STDOUT: %.loc22_3.37: ref %i32 = array_index %self.param, %int_5 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.37: = bound_method %.loc22_3.37, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.37: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.37(%.loc22_3.37) +// CHECK:STDOUT: %.loc16_3.37: ref %i32 = array_index %self.param, %int_5 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.37: = bound_method %.loc16_3.37, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.37: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.37(%.loc16_3.37) // CHECK:STDOUT: %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4] -// CHECK:STDOUT: %.loc22_3.38: ref %i32 = array_index %self.param, %int_4 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.38: = bound_method %.loc22_3.38, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.38: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.38(%.loc22_3.38) +// CHECK:STDOUT: %.loc16_3.38: ref %i32 = array_index %self.param, %int_4 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.38: = bound_method %.loc16_3.38, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.38: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.38(%.loc16_3.38) // CHECK:STDOUT: %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3] -// CHECK:STDOUT: %.loc22_3.39: ref %i32 = array_index %self.param, %int_3 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.39: = bound_method %.loc22_3.39, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.39: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.39(%.loc22_3.39) +// CHECK:STDOUT: %.loc16_3.39: ref %i32 = array_index %self.param, %int_3 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.39: = bound_method %.loc16_3.39, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.39: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.39(%.loc16_3.39) // CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2] -// CHECK:STDOUT: %.loc22_3.40: ref %i32 = array_index %self.param, %int_2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.40: = bound_method %.loc22_3.40, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.40: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.40(%.loc22_3.40) +// CHECK:STDOUT: %.loc16_3.40: ref %i32 = array_index %self.param, %int_2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.40: = bound_method %.loc16_3.40, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.40: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.40(%.loc16_3.40) // CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1] -// CHECK:STDOUT: %.loc22_3.41: ref %i32 = array_index %self.param, %int_1 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.41: = bound_method %.loc22_3.41, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.41: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.41(%.loc22_3.41) +// CHECK:STDOUT: %.loc16_3.41: ref %i32 = array_index %self.param, %int_1 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.41: = bound_method %.loc16_3.41, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.41: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.41(%.loc16_3.41) // CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6] -// CHECK:STDOUT: %.loc22_3.42: ref %i32 = array_index %self.param, %int_0 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc22_3.42: = bound_method %.loc22_3.42, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc22_3.42: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc22_3.42(%.loc22_3.42) +// CHECK:STDOUT: %.loc16_3.42: ref %i32 = array_index %self.param, %int_0 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.bound.loc16_3.42: = bound_method %.loc16_3.42, constants.%Destroy.WithSelf.SelfDestruct.db3fdb.2 +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.call.loc16_3.42: init %empty_tuple.type = call %Destroy.WithSelf.SelfDestruct.bound.loc16_3.42(%.loc16_3.42) // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Destroy.WithSelf.Op.loc22_3.2(%self.param: ref %array_type.d58) = "no_op"; +// CHECK:STDOUT: fn @Destroy.WithSelf.Op.loc16_3.2(%self.param: ref %array_type.d58) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Destroy.WithSelf.SelfDestruct.loc22_3.2(%self.param: ref %array_type.d58) { +// CHECK:STDOUT: fn @Destroy.WithSelf.SelfDestruct.loc16_3.2(%self.param: ref %array_type.d58) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %Destroy.WithSelf.Op.call: init %empty_tuple.type = call generated.%Destroy.WithSelf.Op.decl.5f94cf.2(%self.param) // CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.call: init %empty_tuple.type = call generated.%Destroy.WithSelf.SubobjectDestroy.decl.763c71.2(%self.param) diff --git a/toolchain/check/testdata/interop/cpp/function/import/function_ptr.carbon b/toolchain/check/testdata/interop/cpp/function/import/function_ptr.carbon index 63b78eaceacb..306b15cf854c 100644 --- a/toolchain/check/testdata/interop/cpp/function/import/function_ptr.carbon +++ b/toolchain/check/testdata/interop/cpp/function/import/function_ptr.carbon @@ -9,6 +9,7 @@ // TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/function/import/function_ptr.carbon // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/function/import/function_ptr.carbon +// CHECK:STDERR: error: calling function with incomplete return type 'C' [CppInteropParseError] // --- simple_callback.h @@ -29,7 +30,7 @@ fn F() { //@dump-sem-ir-end } -// --- fail_todo_convert_fn_ptr.carbon +// --- convert_fn_ptr.carbon library "[[@TEST_NAME]]"; import Cpp library "simple_callback.h"; @@ -38,15 +39,11 @@ fn MyCallback(arg: f32) -> i32; fn F() { //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_convert_fn_ptr.carbon:[[@LINE+4]]:41: error: expression cannot be used as a value [UseOfNonExprAsValue] - // CHECK:STDERR: var unused fn_ptr: Cpp.CallbackType = MyCallback; - // CHECK:STDERR: ^~~~~~~~~~ - // CHECK:STDERR: var unused fn_ptr: Cpp.CallbackType = MyCallback; //@dump-sem-ir-end } -// --- fail_todo_pass_fn_ptr.carbon +// --- pass_fn_ptr.carbon library "[[@TEST_NAME]]"; import Cpp library "simple_callback.h"; @@ -55,10 +52,6 @@ fn MyCallback(arg: f32) -> i32; fn F() { //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_pass_fn_ptr.carbon:[[@LINE+4]]:20: error: call argument of type `` is not supported [CppCallArgTypeNotSupported] - // CHECK:STDERR: Cpp.TakeCallback(MyCallback); - // CHECK:STDERR: ^~~~~~~~~~ - // CHECK:STDERR: Cpp.TakeCallback(MyCallback); //@dump-sem-ir-end } @@ -95,7 +88,7 @@ fn F() { //@dump-sem-ir-end } -// --- fail_todo_convert_complex_fn_ptr.carbon +// --- convert_complex_fn_ptr.carbon library "[[@TEST_NAME]]"; import Cpp library "complex_callback.h"; @@ -104,15 +97,11 @@ fn MyCallback(arg: Cpp.C) -> Cpp.C; fn F() { //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_convert_complex_fn_ptr.carbon:[[@LINE+4]]:41: error: expression cannot be used as a value [UseOfNonExprAsValue] - // CHECK:STDERR: var unused fn_ptr: Cpp.CallbackType = MyCallback; - // CHECK:STDERR: ^~~~~~~~~~ - // CHECK:STDERR: var unused fn_ptr: Cpp.CallbackType = MyCallback; //@dump-sem-ir-end } -// --- fail_todo_pass_complex_fn_ptr.carbon +// --- pass_complex_fn_ptr.carbon library "[[@TEST_NAME]]"; import Cpp library "complex_callback.h"; @@ -121,11 +110,6 @@ fn MyCallback(arg: Cpp.C) -> Cpp.C; fn F() { //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_pass_complex_fn_ptr.carbon:[[@LINE+5]]:27: error: call argument of type `` is not supported [CppCallArgTypeNotSupported] - // CHECK:STDERR: Cpp.TakeComplexCallback(MyCallback); - // CHECK:STDERR: ^~~~~~~~~~ - // CHECK:STDERR: - // CHECK:STDERR: error: calling function with incomplete return type 'C' [CppInteropParseError] Cpp.TakeComplexCallback(MyCallback); //@dump-sem-ir-end } @@ -170,9 +154,6 @@ library "[[@TEST_NAME]]"; import Cpp library "forward_decl.h"; fn F() { - // CHECK:STDERR: fail_use_forward_decl.carbon:[[@LINE+16]]:3: note: in thunk for C++ function used here [InCppThunk] - // CHECK:STDERR: Cpp.ReturnCallback()(); - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: fail_use_forward_decl.carbon:[[@LINE+13]]:3: note: in thunk for C++ function pointer type used here [InCppFunctionPointerThunk] // CHECK:STDERR: Cpp.ReturnCallback()(); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~ @@ -180,7 +161,7 @@ fn F() { // CHECK:STDERR: fail_use_forward_decl.carbon:[[@LINE+9]]:3: error: function returns incomplete type `Cpp.C` [IncompleteTypeInFunctionReturnType] // CHECK:STDERR: Cpp.ReturnCallback()(); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: fail_use_forward_decl.carbon:[[@LINE-13]]:10: in file included here [InCppInclude] + // CHECK:STDERR: fail_use_forward_decl.carbon:[[@LINE-10]]:10: in file included here [InCppInclude] // CHECK:STDERR: ./forward_decl.h:2:7: note: class was forward declared here [ClassForwardDeclaredHere] // CHECK:STDERR: class C; // CHECK:STDERR: ^ @@ -189,6 +170,43 @@ fn F() { Cpp.ReturnCallback()(); } +// --- fail_convert_generic_arg.carbon +library "[[@TEST_NAME]]"; + +import Cpp inline '''c++ +using MyCallbackType = void(*)(int); +'''; + +fn MyCallback(generic arg: i32); + +fn F() { + // CHECK:STDERR: fail_convert_generic_arg.carbon:[[@LINE+4]]:43: error: semantics TODO: `binding maps to a non-type template parameter` [SemanticsTodo] + // CHECK:STDERR: var unused fn_ptr: Cpp.MyCallbackType = MyCallback; + // CHECK:STDERR: ^~~~~~~~~~ + // CHECK:STDERR: + var unused fn_ptr: Cpp.MyCallbackType = MyCallback; +} + +// --- fail_convert_type_mismatch.carbon +library "[[@TEST_NAME]]"; + +import Cpp inline '''c++ +using MyCallbackType = void(*)(int); +'''; + +fn MyCallback(arg: i32) -> i32; + +fn F() { + // CHECK:STDERR: fail_convert_type_mismatch.carbon:[[@LINE+7]]:43: error: can't convert exported function type to `void (int)` [ExportedFunctionPtrTypeMismatch] + // CHECK:STDERR: var unused fn_ptr: Cpp.MyCallbackType = MyCallback; + // CHECK:STDERR: ^~~~~~~~~~ + // CHECK:STDERR: fail_convert_type_mismatch.carbon:[[@LINE-6]]:1: note: function exported with type `int (int)` [ExportedFromFunction] + // CHECK:STDERR: fn MyCallback(arg: i32) -> i32; + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + var unused fn_ptr: Cpp.MyCallbackType = MyCallback; +} + // CHECK:STDOUT: --- relay_fn_ptr.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -238,24 +256,36 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_convert_fn_ptr.carbon +// CHECK:STDOUT: --- convert_fn_ptr.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %f32.c73: type = class_type @Float, @Float(%int_32) [concrete] +// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] // CHECK:STDOUT: %MyCallback.type: type = fn_type @MyCallback [concrete] // CHECK:STDOUT: %MyCallback: %MyCallback.type = struct_value () [concrete] // CHECK:STDOUT: %.659: type = cpp_fn_ptr_type clang_function_pointer_type41000000 [concrete] // CHECK:STDOUT: %pattern_type.4b7: type = pattern_type %.659 [concrete] // CHECK:STDOUT: %fn_ptr.patt: %pattern_type.4b7 = ref_binding_pattern fn_ptr [concrete] // CHECK:STDOUT: %fn_ptr.var_patt: %pattern_type.4b7 = var_pattern %fn_ptr.patt [concrete] +// CHECK:STDOUT: %.fc9: %.659 = cpp_addr_of_fn %MyCallback, @MyCallback [concrete] +// CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] +// CHECK:STDOUT: %Copy.WithSelf.Op.type.7f5: type = fn_type @Copy.WithSelf.Op.2 [concrete] +// CHECK:STDOUT: %Copy.WithSelf.Op.416: %Copy.WithSelf.Op.type.7f5 = struct_value () [concrete] +// CHECK:STDOUT: %custom_witness.bab: = custom_witness (%Copy.WithSelf.Op.416), @Copy [concrete] +// CHECK:STDOUT: %Copy.facet.8df: %Copy.type = facet_value %.659, (%custom_witness.bab) [concrete] +// CHECK:STDOUT: %Copy.WithSelf.Op.type.adb: type = fn_type @Copy.WithSelf.Op.1, @Copy.WithSelf(%Copy.facet.8df) [concrete] +// CHECK:STDOUT: %.e6b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.adb, %Copy.facet.8df [concrete] +// CHECK:STDOUT: %Copy.WithSelf.Op.bound: = bound_method %.fc9, %Copy.WithSelf.Op.416 [concrete] // CHECK:STDOUT: %self.param_patt.952: %pattern_type.4b7 = ref_param_pattern [concrete] // CHECK:STDOUT: %self.patt.a35: %pattern_type.4b7 = wrapper_binding_pattern self, %self.param_patt.952 [concrete] -// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.type.dfc: type = fn_type @Destroy.WithSelf.SubobjectDestroy.loc13 [concrete] +// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.type.dfc: type = fn_type @Destroy.WithSelf.SubobjectDestroy.loc9 [concrete] // CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.d01: %Destroy.WithSelf.SubobjectDestroy.type.dfc = struct_value () [concrete] -// CHECK:STDOUT: %Destroy.WithSelf.Op.type.ef0: type = fn_type @Destroy.WithSelf.Op.loc13 [concrete] +// CHECK:STDOUT: %Destroy.WithSelf.Op.type.ef0: type = fn_type @Destroy.WithSelf.Op.loc9 [concrete] // CHECK:STDOUT: %Destroy.WithSelf.Op.403: %Destroy.WithSelf.Op.type.ef0 = struct_value () [concrete] -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.type.fbc: type = fn_type @Destroy.WithSelf.SelfDestruct.loc13 [concrete] +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.type.fbc: type = fn_type @Destroy.WithSelf.SelfDestruct.loc9 [concrete] // CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.db3: %Destroy.WithSelf.SelfDestruct.type.fbc = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -267,14 +297,14 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generated { -// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.decl: %Destroy.WithSelf.SubobjectDestroy.type.dfc = fn_decl @Destroy.WithSelf.SubobjectDestroy.loc13 [concrete = constants.%Destroy.WithSelf.SubobjectDestroy.d01] { +// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.decl: %Destroy.WithSelf.SubobjectDestroy.type.dfc = fn_decl @Destroy.WithSelf.SubobjectDestroy.loc9 [concrete = constants.%Destroy.WithSelf.SubobjectDestroy.d01] { // CHECK:STDOUT: %self.param_patt: %pattern_type.4b7 = ref_param_pattern [concrete = constants.%self.param_patt.952] // CHECK:STDOUT: %self.patt: %pattern_type.4b7 = wrapper_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.a35] // CHECK:STDOUT: } { // CHECK:STDOUT: %self.param: ref %.659 = ref_param call_param0 // CHECK:STDOUT: %self: ref %.659 = wrapper_binding self, %self.param // CHECK:STDOUT: } -// CHECK:STDOUT: %Destroy.WithSelf.Op.decl: %Destroy.WithSelf.Op.type.ef0 = fn_decl @Destroy.WithSelf.Op.loc13 [concrete = constants.%Destroy.WithSelf.Op.403] { +// CHECK:STDOUT: %Destroy.WithSelf.Op.decl: %Destroy.WithSelf.Op.type.ef0 = fn_decl @Destroy.WithSelf.Op.loc9 [concrete = constants.%Destroy.WithSelf.Op.403] { // CHECK:STDOUT: %self.param_patt: %pattern_type.4b7 = ref_param_pattern [concrete = constants.%self.param_patt.952] // CHECK:STDOUT: %self.patt: %pattern_type.4b7 = wrapper_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.a35] // CHECK:STDOUT: } { @@ -287,8 +317,14 @@ fn F() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %fn_ptr.var: ref %.659 = var_storage %fn_ptr.var_patt // CHECK:STDOUT: %MyCallback.ref: %MyCallback.type = name_ref MyCallback, file.%MyCallback.decl [concrete = constants.%MyCallback] -// CHECK:STDOUT: assign %fn_ptr.var, -// CHECK:STDOUT: %.loc13: type = splice_block %CallbackType.ref [concrete = constants.%.659] { +// CHECK:STDOUT: %.loc9_3.1: %.659 = cpp_addr_of_fn %MyCallback.ref, @MyCallback [concrete = constants.%.fc9] +// CHECK:STDOUT: %.loc9_3.2: %.659 = converted %MyCallback.ref, %.loc9_3.1 [concrete = constants.%.fc9] +// CHECK:STDOUT: +// CHECK:STDOUT: %impl.elem0: %.e6b = impl_witness_access constants.%custom_witness.bab, element0 [concrete = constants.%Copy.WithSelf.Op.416] +// CHECK:STDOUT: %bound_method: = bound_method %.loc9_3.2, %impl.elem0 [concrete = constants.%Copy.WithSelf.Op.bound] +// CHECK:STDOUT: %Copy.WithSelf.Op.call: init %.659 = call %bound_method(%.loc9_3.2) [concrete = constants.%.fc9] +// CHECK:STDOUT: assign %fn_ptr.var, %Copy.WithSelf.Op.call +// CHECK:STDOUT: %.loc9_25: type = splice_block %CallbackType.ref [concrete = constants.%.659] { // CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %CallbackType.ref: type = name_ref CallbackType, constants.%.659 [concrete = constants.%.659] // CHECK:STDOUT: } @@ -302,25 +338,39 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Destroy.WithSelf.SubobjectDestroy.loc13(%self.param: ref %.659) = "no_op"; +// CHECK:STDOUT: fn @MyCallback__carbon_thunk(%_.param.loc9_41.1: ref %f32.c73, %_.param.loc9_41.2: ref %i32) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: +// CHECK:STDOUT: %.loc9: %f32.c73 = acquire_value %_.param.loc9_41.1 +// CHECK:STDOUT: +// CHECK:STDOUT: assign %_.param.loc9_41.2, %MyCallback.call +// CHECK:STDOUT: +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Destroy.WithSelf.Op.loc13(%self.param: ref %.659) = "no_op"; +// CHECK:STDOUT: fn @Destroy.WithSelf.SubobjectDestroy.loc9(%self.param: ref %.659) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Destroy.WithSelf.SelfDestruct.loc13(%self.param: ref %.659) { +// CHECK:STDOUT: fn @Destroy.WithSelf.Op.loc9(%self.param: ref %.659) = "no_op"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Destroy.WithSelf.SelfDestruct.loc9(%self.param: ref %.659) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %Destroy.WithSelf.Op.call: init %empty_tuple.type = call generated.%Destroy.WithSelf.Op.decl(%self.param) // CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.call: init %empty_tuple.type = call generated.%Destroy.WithSelf.SubobjectDestroy.decl(%self.param) // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_pass_fn_ptr.carbon +// CHECK:STDOUT: --- pass_fn_ptr.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: type: type = facet_type [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %MyCallback.type: type = fn_type @MyCallback [concrete] // CHECK:STDOUT: %MyCallback: %MyCallback.type = struct_value () [concrete] // CHECK:STDOUT: %TakeCallback.cpp_overload_set.type: type = cpp_overload_set_type @TakeCallback.cpp_overload_set [concrete] // CHECK:STDOUT: %TakeCallback.cpp_overload_set.value: %TakeCallback.cpp_overload_set.type = cpp_overload_set_value @TakeCallback.cpp_overload_set [concrete] +// CHECK:STDOUT: %.659: type = cpp_fn_ptr_type clang_function_pointer_type61000000 [concrete] +// CHECK:STDOUT: %TakeCallback.type: type = fn_type @TakeCallback [concrete] +// CHECK:STDOUT: %TakeCallback: %TakeCallback.type = struct_value () [concrete] +// CHECK:STDOUT: %.fc9: %.659 = cpp_addr_of_fn %MyCallback, @MyCallback [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -329,6 +379,11 @@ fn F() { // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: %TakeCallback.cpp_overload_set.value: %TakeCallback.cpp_overload_set.type = cpp_overload_set_value @TakeCallback.cpp_overload_set [concrete = constants.%TakeCallback.cpp_overload_set.value] +// CHECK:STDOUT: %TakeCallback.decl: %TakeCallback.type = fn_decl @TakeCallback [concrete = constants.%TakeCallback] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -336,6 +391,9 @@ fn F() { // CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %TakeCallback.ref: %TakeCallback.cpp_overload_set.type = name_ref TakeCallback, imports.%TakeCallback.cpp_overload_set.value [concrete = constants.%TakeCallback.cpp_overload_set.value] // CHECK:STDOUT: %MyCallback.ref: %MyCallback.type = name_ref MyCallback, file.%MyCallback.decl [concrete = constants.%MyCallback] +// CHECK:STDOUT: %.loc9_20.1: %.659 = cpp_addr_of_fn %MyCallback.ref, @MyCallback [concrete = constants.%.fc9] +// CHECK:STDOUT: %.loc9_20.2: %.659 = converted %MyCallback.ref, %.loc9_20.1 [concrete = constants.%.fc9] +// CHECK:STDOUT: %TakeCallback.call: init %empty_tuple.type = call imports.%TakeCallback.decl(%.loc9_20.2) // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: @@ -569,7 +627,7 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_convert_complex_fn_ptr.carbon +// CHECK:STDOUT: --- convert_complex_fn_ptr.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: type: type = facet_type [concrete] @@ -581,13 +639,22 @@ fn F() { // CHECK:STDOUT: %pattern_type.4b7: type = pattern_type %.659 [concrete] // CHECK:STDOUT: %fn_ptr.patt: %pattern_type.4b7 = ref_binding_pattern fn_ptr [concrete] // CHECK:STDOUT: %fn_ptr.var_patt: %pattern_type.4b7 = var_pattern %fn_ptr.patt [concrete] +// CHECK:STDOUT: %.fc9: %.659 = cpp_addr_of_fn %MyCallback, @MyCallback [concrete] +// CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] +// CHECK:STDOUT: %Copy.WithSelf.Op.type.7f5: type = fn_type @Copy.WithSelf.Op.2 [concrete] +// CHECK:STDOUT: %Copy.WithSelf.Op.416: %Copy.WithSelf.Op.type.7f5 = struct_value () [concrete] +// CHECK:STDOUT: %custom_witness.bab: = custom_witness (%Copy.WithSelf.Op.416), @Copy [concrete] +// CHECK:STDOUT: %Copy.facet.8df: %Copy.type = facet_value %.659, (%custom_witness.bab) [concrete] +// CHECK:STDOUT: %Copy.WithSelf.Op.type.adb: type = fn_type @Copy.WithSelf.Op.1, @Copy.WithSelf(%Copy.facet.8df) [concrete] +// CHECK:STDOUT: %.e6b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.adb, %Copy.facet.8df [concrete] +// CHECK:STDOUT: %Copy.WithSelf.Op.bound: = bound_method %.fc9, %Copy.WithSelf.Op.416 [concrete] // CHECK:STDOUT: %self.param_patt.952: %pattern_type.4b7 = ref_param_pattern [concrete] // CHECK:STDOUT: %self.patt.a35: %pattern_type.4b7 = wrapper_binding_pattern self, %self.param_patt.952 [concrete] -// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.type.dfc: type = fn_type @Destroy.WithSelf.SubobjectDestroy.loc13 [concrete] +// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.type.dfc: type = fn_type @Destroy.WithSelf.SubobjectDestroy.loc9 [concrete] // CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.d01: %Destroy.WithSelf.SubobjectDestroy.type.dfc = struct_value () [concrete] -// CHECK:STDOUT: %Destroy.WithSelf.Op.type.ef0: type = fn_type @Destroy.WithSelf.Op.loc13 [concrete] +// CHECK:STDOUT: %Destroy.WithSelf.Op.type.ef0: type = fn_type @Destroy.WithSelf.Op.loc9 [concrete] // CHECK:STDOUT: %Destroy.WithSelf.Op.403: %Destroy.WithSelf.Op.type.ef0 = struct_value () [concrete] -// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.type.fbc: type = fn_type @Destroy.WithSelf.SelfDestruct.loc13 [concrete] +// CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.type.fbc: type = fn_type @Destroy.WithSelf.SelfDestruct.loc9 [concrete] // CHECK:STDOUT: %Destroy.WithSelf.SelfDestruct.db3: %Destroy.WithSelf.SelfDestruct.type.fbc = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -601,14 +668,14 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generated { -// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.decl: %Destroy.WithSelf.SubobjectDestroy.type.dfc = fn_decl @Destroy.WithSelf.SubobjectDestroy.loc13 [concrete = constants.%Destroy.WithSelf.SubobjectDestroy.d01] { +// CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.decl: %Destroy.WithSelf.SubobjectDestroy.type.dfc = fn_decl @Destroy.WithSelf.SubobjectDestroy.loc9 [concrete = constants.%Destroy.WithSelf.SubobjectDestroy.d01] { // CHECK:STDOUT: %self.param_patt: %pattern_type.4b7 = ref_param_pattern [concrete = constants.%self.param_patt.952] // CHECK:STDOUT: %self.patt: %pattern_type.4b7 = wrapper_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.a35] // CHECK:STDOUT: } { // CHECK:STDOUT: %self.param: ref %.659 = ref_param call_param0 // CHECK:STDOUT: %self: ref %.659 = wrapper_binding self, %self.param // CHECK:STDOUT: } -// CHECK:STDOUT: %Destroy.WithSelf.Op.decl: %Destroy.WithSelf.Op.type.ef0 = fn_decl @Destroy.WithSelf.Op.loc13 [concrete = constants.%Destroy.WithSelf.Op.403] { +// CHECK:STDOUT: %Destroy.WithSelf.Op.decl: %Destroy.WithSelf.Op.type.ef0 = fn_decl @Destroy.WithSelf.Op.loc9 [concrete = constants.%Destroy.WithSelf.Op.403] { // CHECK:STDOUT: %self.param_patt: %pattern_type.4b7 = ref_param_pattern [concrete = constants.%self.param_patt.952] // CHECK:STDOUT: %self.patt: %pattern_type.4b7 = wrapper_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.a35] // CHECK:STDOUT: } { @@ -621,8 +688,14 @@ fn F() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %fn_ptr.var: ref %.659 = var_storage %fn_ptr.var_patt // CHECK:STDOUT: %MyCallback.ref: %MyCallback.type = name_ref MyCallback, file.%MyCallback.decl [concrete = constants.%MyCallback] -// CHECK:STDOUT: assign %fn_ptr.var, -// CHECK:STDOUT: %.loc13: type = splice_block %CallbackType.ref [concrete = constants.%.659] { +// CHECK:STDOUT: %.loc9_3.1: %.659 = cpp_addr_of_fn %MyCallback.ref, @MyCallback [concrete = constants.%.fc9] +// CHECK:STDOUT: %.loc9_3.2: %.659 = converted %MyCallback.ref, %.loc9_3.1 [concrete = constants.%.fc9] +// CHECK:STDOUT: +// CHECK:STDOUT: %impl.elem0: %.e6b = impl_witness_access constants.%custom_witness.bab, element0 [concrete = constants.%Copy.WithSelf.Op.416] +// CHECK:STDOUT: %bound_method: = bound_method %.loc9_3.2, %impl.elem0 [concrete = constants.%Copy.WithSelf.Op.bound] +// CHECK:STDOUT: %Copy.WithSelf.Op.call: init %.659 = call %bound_method(%.loc9_3.2) [concrete = constants.%.fc9] +// CHECK:STDOUT: assign %fn_ptr.var, %Copy.WithSelf.Op.call +// CHECK:STDOUT: %.loc9_25: type = splice_block %CallbackType.ref [concrete = constants.%.659] { // CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %CallbackType.ref: type = name_ref CallbackType, constants.%.659 [concrete = constants.%.659] // CHECK:STDOUT: } @@ -636,26 +709,41 @@ fn F() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Destroy.WithSelf.SubobjectDestroy.loc13(%self.param: ref %.659) = "no_op"; +// CHECK:STDOUT: fn @MyCallback__carbon_thunk(%_.param.loc9_41.1: ref %C, %_.param.loc9_41.2: ref %C) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: +// CHECK:STDOUT: %.loc9_41.1: ref %C = splice_block %_.param.loc9_41.2 {} +// CHECK:STDOUT: %.loc9_41.2: %C = acquire_value %_.param.loc9_41.1 +// CHECK:STDOUT: +// CHECK:STDOUT: assign %_.param.loc9_41.2, %MyCallback.call +// CHECK:STDOUT: +// CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Destroy.WithSelf.Op.loc13(%self.param: ref %.659) = "no_op"; +// CHECK:STDOUT: fn @Destroy.WithSelf.SubobjectDestroy.loc9(%self.param: ref %.659) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: fn @Destroy.WithSelf.SelfDestruct.loc13(%self.param: ref %.659) { +// CHECK:STDOUT: fn @Destroy.WithSelf.Op.loc9(%self.param: ref %.659) = "no_op"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Destroy.WithSelf.SelfDestruct.loc9(%self.param: ref %.659) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %Destroy.WithSelf.Op.call: init %empty_tuple.type = call generated.%Destroy.WithSelf.Op.decl(%self.param) // CHECK:STDOUT: %Destroy.WithSelf.SubobjectDestroy.call: init %empty_tuple.type = call generated.%Destroy.WithSelf.SubobjectDestroy.decl(%self.param) // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_pass_complex_fn_ptr.carbon +// CHECK:STDOUT: --- pass_complex_fn_ptr.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: type: type = facet_type [concrete] // CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %MyCallback.type: type = fn_type @MyCallback [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %MyCallback: %MyCallback.type = struct_value () [concrete] // CHECK:STDOUT: %TakeComplexCallback.cpp_overload_set.type: type = cpp_overload_set_type @TakeComplexCallback.cpp_overload_set [concrete] // CHECK:STDOUT: %TakeComplexCallback.cpp_overload_set.value: %TakeComplexCallback.cpp_overload_set.type = cpp_overload_set_value @TakeComplexCallback.cpp_overload_set [concrete] +// CHECK:STDOUT: %.659: type = cpp_fn_ptr_type clang_function_pointer_type69000000 [concrete] +// CHECK:STDOUT: %TakeComplexCallback.type: type = fn_type @TakeComplexCallback [concrete] +// CHECK:STDOUT: %TakeComplexCallback: %TakeComplexCallback.type = struct_value () [concrete] +// CHECK:STDOUT: %.fc9: %.659 = cpp_addr_of_fn %MyCallback, @MyCallback [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -666,6 +754,11 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: %TakeComplexCallback.cpp_overload_set.value: %TakeComplexCallback.cpp_overload_set.type = cpp_overload_set_value @TakeComplexCallback.cpp_overload_set [concrete = constants.%TakeComplexCallback.cpp_overload_set.value] +// CHECK:STDOUT: %TakeComplexCallback.decl: %TakeComplexCallback.type = fn_decl @TakeComplexCallback [concrete = constants.%TakeComplexCallback] { +// CHECK:STDOUT: +// CHECK:STDOUT: } { +// CHECK:STDOUT: +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -673,6 +766,9 @@ fn F() { // CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %TakeComplexCallback.ref: %TakeComplexCallback.cpp_overload_set.type = name_ref TakeComplexCallback, imports.%TakeComplexCallback.cpp_overload_set.value [concrete = constants.%TakeComplexCallback.cpp_overload_set.value] // CHECK:STDOUT: %MyCallback.ref: %MyCallback.type = name_ref MyCallback, file.%MyCallback.decl [concrete = constants.%MyCallback] +// CHECK:STDOUT: %.loc9_27.1: %.659 = cpp_addr_of_fn %MyCallback.ref, @MyCallback [concrete = constants.%.fc9] +// CHECK:STDOUT: %.loc9_27.2: %.659 = converted %MyCallback.ref, %.loc9_27.1 [concrete = constants.%.fc9] +// CHECK:STDOUT: %TakeComplexCallback.call: init %empty_tuple.type = call imports.%TakeComplexCallback.decl(%.loc9_27.2) // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/pointer/fail_deref_function.carbon b/toolchain/check/testdata/pointer/fail_deref_function.carbon index ae91d452cd22..278a8639b11b 100644 --- a/toolchain/check/testdata/pointer/fail_deref_function.carbon +++ b/toolchain/check/testdata/pointer/fail_deref_function.carbon @@ -13,14 +13,14 @@ // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/pointer/fail_deref_function.carbon fn A() { - // CHECK:STDERR: fail_deref_function.carbon:[[@LINE+4]]:4: error: expression cannot be used as a value [UseOfNonExprAsValue] + // CHECK:STDERR: fail_deref_function.carbon:[[@LINE+4]]:3: error: cannot dereference operand of non-pointer type `` [DerefOfNonPointer] // CHECK:STDERR: *A; - // CHECK:STDERR: ^ + // CHECK:STDERR: ^ // CHECK:STDERR: *A; - // CHECK:STDERR: fail_deref_function.carbon:[[@LINE+4]]:3: error: expression cannot be used as a value [UseOfNonExprAsValue] + // CHECK:STDERR: fail_deref_function.carbon:[[@LINE+4]]:4: error: cannot apply `->` operator to non-pointer type `` [ArrowOperatorOfNonPointer] // CHECK:STDERR: A->foo; - // CHECK:STDERR: ^ + // CHECK:STDERR: ^~ // CHECK:STDERR: A->foo; } @@ -52,9 +52,9 @@ fn A() { // CHECK:STDOUT: fn @A() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %A.ref.loc20: %A.type = name_ref A, file.%A.decl [concrete = constants.%A] -// CHECK:STDOUT: %.loc20: ref = deref [concrete = ] +// CHECK:STDOUT: %.loc20: ref = deref %A.ref.loc20 [concrete = ] // CHECK:STDOUT: %A.ref.loc25: %A.type = name_ref A, file.%A.decl [concrete = constants.%A] -// CHECK:STDOUT: %.loc25: ref = deref [concrete = ] +// CHECK:STDOUT: %.loc25: ref = deref %A.ref.loc25 [concrete = ] // CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/struct/fail_member_of_function.carbon b/toolchain/check/testdata/struct/fail_member_of_function.carbon index 75227f3a258d..a78864890de4 100644 --- a/toolchain/check/testdata/struct/fail_member_of_function.carbon +++ b/toolchain/check/testdata/struct/fail_member_of_function.carbon @@ -13,9 +13,9 @@ // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/struct/fail_member_of_function.carbon fn A() { - // CHECK:STDERR: fail_member_of_function.carbon:[[@LINE+4]]:3: error: expression cannot be used as a value [UseOfNonExprAsValue] + // CHECK:STDERR: fail_member_of_function.carbon:[[@LINE+4]]:3: error: type `` does not support qualified expressions [QualifiedExprUnsupported] // CHECK:STDERR: A.y; - // CHECK:STDERR: ^ + // CHECK:STDERR: ^~~ // CHECK:STDERR: A.y; } @@ -47,7 +47,6 @@ fn A() { // CHECK:STDOUT: fn @A() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A] -// CHECK:STDOUT: %y.ref: = name_ref y, [concrete = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/diagnostics/kind.def b/toolchain/diagnostics/kind.def index ac764b61b3e9..0818cf79aec8 100644 --- a/toolchain/diagnostics/kind.def +++ b/toolchain/diagnostics/kind.def @@ -570,6 +570,8 @@ CARBON_DIAGNOSTIC_KIND(QualifiedExprInIncompleteFacetTypeScope) CARBON_DIAGNOSTIC_KIND(QualifiedExprUnsupported) CARBON_DIAGNOSTIC_KIND(QualifiedExprNameNotFound) CARBON_DIAGNOSTIC_KIND(UseOfNonExprAsValue) +CARBON_DIAGNOSTIC_KIND(ExportedFunctionPtrTypeMismatch) +CARBON_DIAGNOSTIC_KIND(ExportedFromFunction) // Modifier checking. CARBON_DIAGNOSTIC_KIND(ModifierNotAllowedOnDeclaration) diff --git a/toolchain/lower/constant.cpp b/toolchain/lower/constant.cpp index c0dee609caed..7704756c8988 100644 --- a/toolchain/lower/constant.cpp +++ b/toolchain/lower/constant.cpp @@ -200,6 +200,11 @@ static auto EmitAsConstant(ConstantContext& context, SemIR::AddrOf inst) return context.GetConstant(inst.lvalue_id); } +static auto EmitAsConstant(ConstantContext& context, + SemIR::CppAddrOfFunction inst) -> llvm::Constant* { + return context.GetFunction(inst.function_id); +} + static auto EmitAsConstant(ConstantContext& context, SemIR::VtablePtr inst) -> llvm::Constant* { return context.GetVtable(inst.vtable_id, inst.specific_id); diff --git a/toolchain/lower/handle.cpp b/toolchain/lower/handle.cpp index 33a3516e7d46..2a71fb3b874a 100644 --- a/toolchain/lower/handle.cpp +++ b/toolchain/lower/handle.cpp @@ -96,6 +96,12 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, context.SetLocal(inst_id, context.GetValue(inst.value_id)); } +auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, + SemIR::CppAddrOfFunction inst) -> void { + context.SetLocal( + inst_id, context.specific_file_context().GetFunction(inst.function_id)); +} + auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, SemIR::ExportDecl inst) -> void { if (IsNamespace(context, inst_id)) { diff --git a/toolchain/lower/testdata/interop/cpp/function/import/function_ptr.carbon b/toolchain/lower/testdata/interop/cpp/function/import/function_ptr.carbon index 64a1fd2f1c42..85c38bc01bcc 100644 --- a/toolchain/lower/testdata/interop/cpp/function/import/function_ptr.carbon +++ b/toolchain/lower/testdata/interop/cpp/function/import/function_ptr.carbon @@ -27,6 +27,28 @@ fn F() { Cpp.TakeCallback(Cpp.GetCallback()); } +// --- convert_fn_ptr.carbon +library "[[@TEST_NAME]]"; + +import Cpp library "simple_callback.h"; + +fn MyCallback(arg: f32) -> i32; + +fn F() { + var unused fn_ptr: Cpp.CallbackType = MyCallback; +} + +// --- pass_fn_ptr.carbon +library "[[@TEST_NAME]]"; + +import Cpp library "simple_callback.h"; + +fn MyCallback(arg: f32) -> i32; + +fn F() { + Cpp.TakeCallback(MyCallback); +} + // --- call_fn_ptr.carbon library "[[@TEST_NAME]]"; @@ -63,6 +85,28 @@ fn F() { Cpp.TakeComplexCallback(Cpp.GetComplexCallback()); } +// --- convert_complex_fn_ptr.carbon +library "[[@TEST_NAME]]"; + +import Cpp library "complex_callback.h"; + +fn MyCallback(arg: Cpp.C) -> Cpp.C; + +fn F() { + var unused fn_ptr: Cpp.CallbackType = MyCallback; +} + +// --- pass_complex_fn_ptr.carbon +library "[[@TEST_NAME]]"; + +import Cpp library "complex_callback.h"; + +fn MyCallback(arg: Cpp.C) -> Cpp.C; + +fn F() { + Cpp.TakeComplexCallback(MyCallback); +} + // --- call_complex_fn_ptr.carbon library "[[@TEST_NAME]]"; @@ -134,66 +178,43 @@ fn F() { // CHECK:STDOUT: !24 = !{!23, !22, i64 0} // CHECK:STDOUT: // CHECK:STDOUT: ; --- -// CHECK:STDOUT: ; ModuleID = 'call_fn_ptr.carbon' -// CHECK:STDOUT: source_filename = "call_fn_ptr.carbon" +// CHECK:STDOUT: ; ModuleID = 'convert_fn_ptr.carbon' +// CHECK:STDOUT: source_filename = "convert_fn_ptr.carbon" // CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" // CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" // CHECK:STDOUT: -// CHECK:STDOUT: @float.943 = internal constant float 1.000000e+00 +// CHECK:STDOUT: declare i32 @_CMyCallback.Main(float) // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CF.Main() #0 !dbg !32 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %x.var = alloca i32, align 4, !dbg !33 -// CHECK:STDOUT: %.loc6_41.3.temp = alloca float, align 4, !dbg !35 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %x.var), !dbg !33 -// CHECK:STDOUT: %GetCallback.call = call ptr @_Z11GetCallbackv(), !dbg !34 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc6_41.3.temp), !dbg !35 -// CHECK:STDOUT: %__invoke__carbon_thunk.call = call i32 @.carbon_thunk.__(ptr %GetCallback.call, ptr @float.943), !dbg !34 -// CHECK:STDOUT: store i32 %__invoke__carbon_thunk.call, ptr %x.var, align 4, !dbg !33 -// CHECK:STDOUT: call void @"_CSelfDestruct.c73f6eecd880c71a:core.Destroy.Core"(ptr @float.943), !dbg !35 -// CHECK:STDOUT: call void @"_CSelfDestruct.f58524831c37807e:core.Destroy.Core"(ptr %x.var), !dbg !33 -// CHECK:STDOUT: ret void, !dbg !37 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: declare noundef ptr @_Z11GetCallbackv() #1 -// CHECK:STDOUT: -// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable -// CHECK:STDOUT: define internal noundef i32 @.carbon_thunk.__(ptr noundef %this, ptr noundef %0) #2 { -// CHECK:STDOUT: entry: -// CHECK:STDOUT: %this.addr = alloca ptr, align 8 -// CHECK:STDOUT: %.addr = alloca ptr, align 8 -// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !47 -// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !50 -// CHECK:STDOUT: %1 = load ptr, ptr %this.addr, align 8, !tbaa !47 -// CHECK:STDOUT: %2 = load ptr, ptr %.addr, align 8, !tbaa !50 -// CHECK:STDOUT: %3 = load float, ptr %2, align 4, !tbaa !51 -// CHECK:STDOUT: %call = call noundef i32 %1(float noundef %3) -// CHECK:STDOUT: ret i32 %call +// CHECK:STDOUT: %fn_ptr.var = alloca ptr, align 8, !dbg !33 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %fn_ptr.var), !dbg !33 +// CHECK:STDOUT: store ptr @_CMyCallback.Main, ptr %fn_ptr.var, align 8, !dbg !33 +// CHECK:STDOUT: call void @"_CSelfDestruct.659d177172b60c17:core.Destroy.Core"(ptr %fn_ptr.var), !dbg !33 +// CHECK:STDOUT: ret void, !dbg !35 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define weak_odr void @"_CSelfDestruct.c73f6eecd880c71a:core.Destroy.Core"(ptr %self) #0 !dbg !38 { +// CHECK:STDOUT: define void @_CMyCallback__carbon_thunk.Main(ptr %_, ptr %_1) #0 !dbg !36 { // CHECK:STDOUT: entry: +// CHECK:STDOUT: %.loc8 = load float, ptr %_, align 4, !dbg !39 +// CHECK:STDOUT: %MyCallback.call = call i32 @_CMyCallback.Main(float %.loc8), !dbg !40 +// CHECK:STDOUT: store i32 %MyCallback.call, ptr %_1, align 4, !dbg !39 // CHECK:STDOUT: ret void, !dbg !40 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define weak_odr void @"_CSelfDestruct.f58524831c37807e:core.Destroy.Core"(ptr %self) #0 !dbg !42 { +// CHECK:STDOUT: define weak_odr void @"_CSelfDestruct.659d177172b60c17:core.Destroy.Core"(ptr %self) #0 !dbg !42 { // CHECK:STDOUT: entry: // CHECK:STDOUT: ret void, !dbg !44 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) -// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #3 -// CHECK:STDOUT: -// CHECK:STDOUT: ; uselistorder directives -// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 1, 0 } +// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #1 // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { nounwind } -// CHECK:STDOUT: attributes #1 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } -// CHECK:STDOUT: attributes #2 = { alwaysinline mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } -// CHECK:STDOUT: attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } +// CHECK:STDOUT: attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.dbg.cu = !{!26} // CHECK:STDOUT: !llvm.module.flags = !{!17, !18, !19, !2, !3} @@ -214,30 +235,190 @@ fn F() { // CHECK:STDOUT: !22 = !{!"int", !21, i64 0} // CHECK:STDOUT: !23 = !{!"__libc_errno", !22, i64 0} // CHECK:STDOUT: !24 = !{!23, !22, i64 0} -// CHECK:STDOUT: !25 = !DIFile(filename: "call_fn_ptr.carbon", directory: "") +// CHECK:STDOUT: !25 = !DIFile(filename: "convert_fn_ptr.carbon", directory: "") // CHECK:STDOUT: !26 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !25, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) // CHECK:STDOUT: !27 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -// CHECK:STDOUT: !30 = !{null, !27} +// CHECK:STDOUT: !30 = !{null, !8, !27} // CHECK:STDOUT: !31 = !DISubroutineType(types: !30) -// CHECK:STDOUT: !32 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !25, line: 5, type: !7, spFlags: DISPFlagDefinition, unit: !26) -// CHECK:STDOUT: !33 = !DILocation(line: 6, column: 3, scope: !32) -// CHECK:STDOUT: !34 = !DILocation(line: 6, column: 23, scope: !32) -// CHECK:STDOUT: !35 = !DILocation(line: 6, column: 41, scope: !32) -// CHECK:STDOUT: !37 = !DILocation(line: 5, column: 1, scope: !32) -// CHECK:STDOUT: !38 = distinct !DISubprogram(name: "SelfDestruct", linkageName: "_CSelfDestruct.c73f6eecd880c71a:core.Destroy.Core", scope: null, file: !25, line: 6, type: !12, spFlags: DISPFlagDefinition, unit: !26, retainedNodes: !41) -// CHECK:STDOUT: !39 = !DILocalVariable(arg: 1, scope: !38, type: !8) -// CHECK:STDOUT: !40 = !DILocation(line: 6, column: 41, scope: !38) -// CHECK:STDOUT: !41 = !{!39} -// CHECK:STDOUT: !42 = distinct !DISubprogram(name: "SelfDestruct", linkageName: "_CSelfDestruct.f58524831c37807e:core.Destroy.Core", scope: null, file: !25, line: 6, type: !31, spFlags: DISPFlagDefinition, unit: !26, retainedNodes: !45) -// CHECK:STDOUT: !43 = !DILocalVariable(arg: 1, scope: !42, type: !27) -// CHECK:STDOUT: !44 = !DILocation(line: 6, column: 3, scope: !42) +// CHECK:STDOUT: !32 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !25, line: 7, type: !7, spFlags: DISPFlagDefinition, unit: !26) +// CHECK:STDOUT: !33 = !DILocation(line: 8, column: 3, scope: !32) +// CHECK:STDOUT: !35 = !DILocation(line: 7, column: 1, scope: !32) +// CHECK:STDOUT: !36 = distinct !DISubprogram(name: "MyCallback__carbon_thunk", linkageName: "_CMyCallback__carbon_thunk.Main", scope: null, file: !25, line: 8, type: !31, spFlags: DISPFlagDefinition, unit: !26, retainedNodes: !41) +// CHECK:STDOUT: !37 = !DILocalVariable(arg: 1, scope: !36, type: !8) +// CHECK:STDOUT: !38 = !DILocalVariable(arg: 2, scope: !36, type: !27) +// CHECK:STDOUT: !39 = !DILocation(line: 8, column: 41, scope: !36) +// CHECK:STDOUT: !40 = !DILocation(line: 5, column: 1, scope: !36) +// CHECK:STDOUT: !41 = !{!37, !38} +// CHECK:STDOUT: !42 = distinct !DISubprogram(name: "SelfDestruct", linkageName: "_CSelfDestruct.659d177172b60c17:core.Destroy.Core", scope: null, file: !25, line: 8, type: !12, spFlags: DISPFlagDefinition, unit: !26, retainedNodes: !45) +// CHECK:STDOUT: !43 = !DILocalVariable(arg: 1, scope: !42, type: !8) +// CHECK:STDOUT: !44 = !DILocation(line: 8, column: 3, scope: !42) // CHECK:STDOUT: !45 = !{!43} -// CHECK:STDOUT: !46 = !{!"any pointer", !21, i64 0} -// CHECK:STDOUT: !47 = !{!46, !46, i64 0} -// CHECK:STDOUT: !48 = !{!"float", !21, i64 0} -// CHECK:STDOUT: !49 = !{!"p1 float", !46, i64 0} -// CHECK:STDOUT: !50 = !{!49, !49, i64 0} -// CHECK:STDOUT: !51 = !{!48, !48, i64 0} +// CHECK:STDOUT: +// CHECK:STDOUT: ; --- +// CHECK:STDOUT: ; ModuleID = 'pass_fn_ptr.carbon' +// CHECK:STDOUT: source_filename = "pass_fn_ptr.carbon" +// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" +// CHECK:STDOUT: +// CHECK:STDOUT: declare i32 @_CMyCallback.Main(float) +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CF.Main() #0 !dbg !48 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z12TakeCallbackPFifE(ptr @_CMyCallback.Main), !dbg !49 +// CHECK:STDOUT: ret void, !dbg !50 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CMyCallback__carbon_thunk.Main(ptr %_, ptr %_1) #0 !dbg !51 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %.loc5 = load float, ptr %_, align 4, !dbg !54 +// CHECK:STDOUT: %MyCallback.call = call i32 @_CMyCallback.Main(float %.loc5), !dbg !54 +// CHECK:STDOUT: store i32 %MyCallback.call, ptr %_1, align 4, !dbg !54 +// CHECK:STDOUT: ret void, !dbg !54 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z12TakeCallbackPFifE(ptr noundef) #1 +// CHECK:STDOUT: +// CHECK:STDOUT: attributes #0 = { nounwind } +// CHECK:STDOUT: attributes #1 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: +// CHECK:STDOUT: !llvm.dbg.cu = !{!47} +// CHECK:STDOUT: !llvm.module.flags = !{!17, !18, !19, !2, !3} +// CHECK:STDOUT: !llvm.errno.tbaa = !{!24} +// CHECK:STDOUT: +// CHECK:STDOUT: !2 = !{i32 7, !"Dwarf Version", i32 5} +// CHECK:STDOUT: !3 = !{i32 2, !"Debug Info Version", i32 3} +// CHECK:STDOUT: !6 = !{null} +// CHECK:STDOUT: !7 = !DISubroutineType(types: !6) +// CHECK:STDOUT: !8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +// CHECK:STDOUT: !17 = !{i32 8, !"PIC Level", i32 2} +// CHECK:STDOUT: !18 = !{i32 7, !"PIE Level", i32 2} +// CHECK:STDOUT: !19 = !{i32 7, !"uwtable", i32 2} +// CHECK:STDOUT: !20 = !{!"Simple C++ TBAA"} +// CHECK:STDOUT: !21 = !{!"omnipotent char", !20, i64 0} +// CHECK:STDOUT: !22 = !{!"int", !21, i64 0} +// CHECK:STDOUT: !23 = !{!"__libc_errno", !22, i64 0} +// CHECK:STDOUT: !24 = !{!23, !22, i64 0} +// CHECK:STDOUT: !27 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +// CHECK:STDOUT: !30 = !{null, !8, !27} +// CHECK:STDOUT: !31 = !DISubroutineType(types: !30) +// CHECK:STDOUT: !46 = !DIFile(filename: "pass_fn_ptr.carbon", directory: "") +// CHECK:STDOUT: !47 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !46, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !48 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !46, line: 7, type: !7, spFlags: DISPFlagDefinition, unit: !47) +// CHECK:STDOUT: !49 = !DILocation(line: 8, column: 3, scope: !48) +// CHECK:STDOUT: !50 = !DILocation(line: 7, column: 1, scope: !48) +// CHECK:STDOUT: !51 = distinct !DISubprogram(name: "MyCallback__carbon_thunk", linkageName: "_CMyCallback__carbon_thunk.Main", scope: null, file: !46, line: 5, type: !31, spFlags: DISPFlagDefinition, unit: !47, retainedNodes: !55) +// CHECK:STDOUT: !52 = !DILocalVariable(arg: 1, scope: !51, type: !8) +// CHECK:STDOUT: !53 = !DILocalVariable(arg: 2, scope: !51, type: !27) +// CHECK:STDOUT: !54 = !DILocation(line: 5, column: 1, scope: !51) +// CHECK:STDOUT: !55 = !{!52, !53} +// CHECK:STDOUT: +// CHECK:STDOUT: ; --- +// CHECK:STDOUT: ; ModuleID = 'call_fn_ptr.carbon' +// CHECK:STDOUT: source_filename = "call_fn_ptr.carbon" +// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" +// CHECK:STDOUT: +// CHECK:STDOUT: @float.943 = internal constant float 1.000000e+00 +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CF.Main() #0 !dbg !62 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %x.var = alloca i32, align 4, !dbg !63 +// CHECK:STDOUT: %.loc6_41.3.temp = alloca float, align 4, !dbg !65 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %x.var), !dbg !63 +// CHECK:STDOUT: %GetCallback.call = call ptr @_Z11GetCallbackv(), !dbg !64 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc6_41.3.temp), !dbg !65 +// CHECK:STDOUT: %__invoke__carbon_thunk.call = call i32 @.carbon_thunk.__(ptr %GetCallback.call, ptr @float.943), !dbg !64 +// CHECK:STDOUT: store i32 %__invoke__carbon_thunk.call, ptr %x.var, align 4, !dbg !63 +// CHECK:STDOUT: call void @"_CSelfDestruct.c73f6eecd880c71a:core.Destroy.Core"(ptr @float.943), !dbg !65 +// CHECK:STDOUT: call void @"_CSelfDestruct.f58524831c37807e:core.Destroy.Core"(ptr %x.var), !dbg !63 +// CHECK:STDOUT: ret void, !dbg !67 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: declare noundef ptr @_Z11GetCallbackv() #1 +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable +// CHECK:STDOUT: define internal noundef i32 @.carbon_thunk.__(ptr noundef %this, ptr noundef %0) #2 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %this.addr = alloca ptr, align 8 +// CHECK:STDOUT: %.addr = alloca ptr, align 8 +// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !77 +// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !80 +// CHECK:STDOUT: %1 = load ptr, ptr %this.addr, align 8, !tbaa !77 +// CHECK:STDOUT: %2 = load ptr, ptr %.addr, align 8, !tbaa !80 +// CHECK:STDOUT: %3 = load float, ptr %2, align 4, !tbaa !81 +// CHECK:STDOUT: %call = call noundef i32 %1(float noundef %3) +// CHECK:STDOUT: ret i32 %call +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define weak_odr void @"_CSelfDestruct.c73f6eecd880c71a:core.Destroy.Core"(ptr %self) #0 !dbg !68 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: ret void, !dbg !70 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define weak_odr void @"_CSelfDestruct.f58524831c37807e:core.Destroy.Core"(ptr %self) #0 !dbg !72 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: ret void, !dbg !74 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #3 +// CHECK:STDOUT: +// CHECK:STDOUT: ; uselistorder directives +// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 1, 0 } +// CHECK:STDOUT: +// CHECK:STDOUT: attributes #0 = { nounwind } +// CHECK:STDOUT: attributes #1 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #2 = { alwaysinline mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } +// CHECK:STDOUT: +// CHECK:STDOUT: !llvm.dbg.cu = !{!57} +// CHECK:STDOUT: !llvm.module.flags = !{!17, !18, !19, !2, !3} +// CHECK:STDOUT: !llvm.errno.tbaa = !{!24} +// CHECK:STDOUT: +// CHECK:STDOUT: !2 = !{i32 7, !"Dwarf Version", i32 5} +// CHECK:STDOUT: !3 = !{i32 2, !"Debug Info Version", i32 3} +// CHECK:STDOUT: !6 = !{null} +// CHECK:STDOUT: !7 = !DISubroutineType(types: !6) +// CHECK:STDOUT: !8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +// CHECK:STDOUT: !11 = !{null, !8} +// CHECK:STDOUT: !12 = !DISubroutineType(types: !11) +// CHECK:STDOUT: !17 = !{i32 8, !"PIC Level", i32 2} +// CHECK:STDOUT: !18 = !{i32 7, !"PIE Level", i32 2} +// CHECK:STDOUT: !19 = !{i32 7, !"uwtable", i32 2} +// CHECK:STDOUT: !20 = !{!"Simple C++ TBAA"} +// CHECK:STDOUT: !21 = !{!"omnipotent char", !20, i64 0} +// CHECK:STDOUT: !22 = !{!"int", !21, i64 0} +// CHECK:STDOUT: !23 = !{!"__libc_errno", !22, i64 0} +// CHECK:STDOUT: !24 = !{!23, !22, i64 0} +// CHECK:STDOUT: !27 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +// CHECK:STDOUT: !56 = !DIFile(filename: "call_fn_ptr.carbon", directory: "") +// CHECK:STDOUT: !57 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !56, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !60 = !{null, !27} +// CHECK:STDOUT: !61 = !DISubroutineType(types: !60) +// CHECK:STDOUT: !62 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !56, line: 5, type: !7, spFlags: DISPFlagDefinition, unit: !57) +// CHECK:STDOUT: !63 = !DILocation(line: 6, column: 3, scope: !62) +// CHECK:STDOUT: !64 = !DILocation(line: 6, column: 23, scope: !62) +// CHECK:STDOUT: !65 = !DILocation(line: 6, column: 41, scope: !62) +// CHECK:STDOUT: !67 = !DILocation(line: 5, column: 1, scope: !62) +// CHECK:STDOUT: !68 = distinct !DISubprogram(name: "SelfDestruct", linkageName: "_CSelfDestruct.c73f6eecd880c71a:core.Destroy.Core", scope: null, file: !56, line: 6, type: !12, spFlags: DISPFlagDefinition, unit: !57, retainedNodes: !71) +// CHECK:STDOUT: !69 = !DILocalVariable(arg: 1, scope: !68, type: !8) +// CHECK:STDOUT: !70 = !DILocation(line: 6, column: 41, scope: !68) +// CHECK:STDOUT: !71 = !{!69} +// CHECK:STDOUT: !72 = distinct !DISubprogram(name: "SelfDestruct", linkageName: "_CSelfDestruct.f58524831c37807e:core.Destroy.Core", scope: null, file: !56, line: 6, type: !61, spFlags: DISPFlagDefinition, unit: !57, retainedNodes: !75) +// CHECK:STDOUT: !73 = !DILocalVariable(arg: 1, scope: !72, type: !27) +// CHECK:STDOUT: !74 = !DILocation(line: 6, column: 3, scope: !72) +// CHECK:STDOUT: !75 = !{!73} +// CHECK:STDOUT: !76 = !{!"any pointer", !21, i64 0} +// CHECK:STDOUT: !77 = !{!76, !76, i64 0} +// CHECK:STDOUT: !78 = !{!"float", !21, i64 0} +// CHECK:STDOUT: !79 = !{!"p1 float", !76, i64 0} +// CHECK:STDOUT: !80 = !{!79, !79, i64 0} +// CHECK:STDOUT: !81 = !{!78, !78, i64 0} // CHECK:STDOUT: // CHECK:STDOUT: ; --- // CHECK:STDOUT: ; ModuleID = 'relay_complex_fn_ptr.carbon' @@ -246,11 +427,11 @@ fn F() { // CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define void @_CF.Main() #0 !dbg !54 { +// CHECK:STDOUT: define void @_CF.Main() #0 !dbg !84 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %GetComplexCallback.call = call ptr @_Z18GetComplexCallbackv(), !dbg !55 -// CHECK:STDOUT: call void @_Z19TakeComplexCallbackPF1CS_E(ptr %GetComplexCallback.call), !dbg !56 -// CHECK:STDOUT: ret void, !dbg !57 +// CHECK:STDOUT: %GetComplexCallback.call = call ptr @_Z18GetComplexCallbackv(), !dbg !85 +// CHECK:STDOUT: call void @_Z19TakeComplexCallbackPF1CS_E(ptr %GetComplexCallback.call), !dbg !86 +// CHECK:STDOUT: ret void, !dbg !87 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: declare noundef ptr @_Z18GetComplexCallbackv() #1 @@ -260,7 +441,7 @@ fn F() { // CHECK:STDOUT: attributes #0 = { nounwind } // CHECK:STDOUT: attributes #1 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: -// CHECK:STDOUT: !llvm.dbg.cu = !{!53} +// CHECK:STDOUT: !llvm.dbg.cu = !{!83} // CHECK:STDOUT: !llvm.module.flags = !{!17, !18, !19, !2, !3} // CHECK:STDOUT: !llvm.errno.tbaa = !{!24} // CHECK:STDOUT: @@ -276,12 +457,142 @@ fn F() { // CHECK:STDOUT: !22 = !{!"int", !21, i64 0} // CHECK:STDOUT: !23 = !{!"__libc_errno", !22, i64 0} // CHECK:STDOUT: !24 = !{!23, !22, i64 0} -// CHECK:STDOUT: !52 = !DIFile(filename: "relay_complex_fn_ptr.carbon", directory: "") -// CHECK:STDOUT: !53 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !52, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) -// CHECK:STDOUT: !54 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !52, line: 5, type: !7, spFlags: DISPFlagDefinition, unit: !53) -// CHECK:STDOUT: !55 = !DILocation(line: 6, column: 27, scope: !54) -// CHECK:STDOUT: !56 = !DILocation(line: 6, column: 3, scope: !54) -// CHECK:STDOUT: !57 = !DILocation(line: 5, column: 1, scope: !54) +// CHECK:STDOUT: !82 = !DIFile(filename: "relay_complex_fn_ptr.carbon", directory: "") +// CHECK:STDOUT: !83 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !82, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !84 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !82, line: 5, type: !7, spFlags: DISPFlagDefinition, unit: !83) +// CHECK:STDOUT: !85 = !DILocation(line: 6, column: 27, scope: !84) +// CHECK:STDOUT: !86 = !DILocation(line: 6, column: 3, scope: !84) +// CHECK:STDOUT: !87 = !DILocation(line: 5, column: 1, scope: !84) +// CHECK:STDOUT: +// CHECK:STDOUT: ; --- +// CHECK:STDOUT: ; ModuleID = 'convert_complex_fn_ptr.carbon' +// CHECK:STDOUT: source_filename = "convert_complex_fn_ptr.carbon" +// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_CMyCallback.Main(ptr sret([4 x i8]), ptr) +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CF.Main() #0 !dbg !94 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %fn_ptr.var = alloca ptr, align 8, !dbg !95 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %fn_ptr.var), !dbg !95 +// CHECK:STDOUT: store ptr @_CMyCallback.Main, ptr %fn_ptr.var, align 8, !dbg !95 +// CHECK:STDOUT: call void @"_CSelfDestruct.659d177172b60c17:core.Destroy.Core"(ptr %fn_ptr.var), !dbg !95 +// CHECK:STDOUT: ret void, !dbg !97 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CMyCallback__carbon_thunk.Main(ptr %_, ptr %_1) #0 !dbg !98 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_CMyCallback.Main(ptr %_1, ptr %_), !dbg !102 +// CHECK:STDOUT: ret void, !dbg !102 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define weak_odr void @"_CSelfDestruct.659d177172b60c17:core.Destroy.Core"(ptr %self) #0 !dbg !104 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: ret void, !dbg !106 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #1 +// CHECK:STDOUT: +// CHECK:STDOUT: attributes #0 = { nounwind } +// CHECK:STDOUT: attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } +// CHECK:STDOUT: +// CHECK:STDOUT: !llvm.dbg.cu = !{!89} +// CHECK:STDOUT: !llvm.module.flags = !{!17, !18, !19, !2, !3} +// CHECK:STDOUT: !llvm.errno.tbaa = !{!24} +// CHECK:STDOUT: +// CHECK:STDOUT: !2 = !{i32 7, !"Dwarf Version", i32 5} +// CHECK:STDOUT: !3 = !{i32 2, !"Debug Info Version", i32 3} +// CHECK:STDOUT: !6 = !{null} +// CHECK:STDOUT: !7 = !DISubroutineType(types: !6) +// CHECK:STDOUT: !8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +// CHECK:STDOUT: !11 = !{null, !8} +// CHECK:STDOUT: !12 = !DISubroutineType(types: !11) +// CHECK:STDOUT: !17 = !{i32 8, !"PIC Level", i32 2} +// CHECK:STDOUT: !18 = !{i32 7, !"PIE Level", i32 2} +// CHECK:STDOUT: !19 = !{i32 7, !"uwtable", i32 2} +// CHECK:STDOUT: !20 = !{!"Simple C++ TBAA"} +// CHECK:STDOUT: !21 = !{!"omnipotent char", !20, i64 0} +// CHECK:STDOUT: !22 = !{!"int", !21, i64 0} +// CHECK:STDOUT: !23 = !{!"__libc_errno", !22, i64 0} +// CHECK:STDOUT: !24 = !{!23, !22, i64 0} +// CHECK:STDOUT: !88 = !DIFile(filename: "convert_complex_fn_ptr.carbon", directory: "") +// CHECK:STDOUT: !89 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !88, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !92 = !{null, !8, !8} +// CHECK:STDOUT: !93 = !DISubroutineType(types: !92) +// CHECK:STDOUT: !94 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !88, line: 7, type: !7, spFlags: DISPFlagDefinition, unit: !89) +// CHECK:STDOUT: !95 = !DILocation(line: 8, column: 3, scope: !94) +// CHECK:STDOUT: !97 = !DILocation(line: 7, column: 1, scope: !94) +// CHECK:STDOUT: !98 = distinct !DISubprogram(name: "MyCallback__carbon_thunk", linkageName: "_CMyCallback__carbon_thunk.Main", scope: null, file: !88, line: 8, type: !93, spFlags: DISPFlagDefinition, unit: !89, retainedNodes: !103) +// CHECK:STDOUT: !99 = !DILocalVariable(arg: 1, scope: !98, type: !8) +// CHECK:STDOUT: !100 = !DILocalVariable(arg: 2, scope: !98, type: !8) +// CHECK:STDOUT: !102 = !DILocation(line: 5, column: 1, scope: !98) +// CHECK:STDOUT: !103 = !{!99, !100} +// CHECK:STDOUT: !104 = distinct !DISubprogram(name: "SelfDestruct", linkageName: "_CSelfDestruct.659d177172b60c17:core.Destroy.Core", scope: null, file: !88, line: 8, type: !12, spFlags: DISPFlagDefinition, unit: !89, retainedNodes: !107) +// CHECK:STDOUT: !105 = !DILocalVariable(arg: 1, scope: !104, type: !8) +// CHECK:STDOUT: !106 = !DILocation(line: 8, column: 3, scope: !104) +// CHECK:STDOUT: !107 = !{!105} +// CHECK:STDOUT: +// CHECK:STDOUT: ; --- +// CHECK:STDOUT: ; ModuleID = 'pass_complex_fn_ptr.carbon' +// CHECK:STDOUT: source_filename = "pass_complex_fn_ptr.carbon" +// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_CMyCallback.Main(ptr sret([4 x i8]), ptr) +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CF.Main() #0 !dbg !110 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z19TakeComplexCallbackPF1CS_E(ptr @_CMyCallback.Main), !dbg !111 +// CHECK:STDOUT: ret void, !dbg !112 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: nounwind +// CHECK:STDOUT: define void @_CMyCallback__carbon_thunk.Main(ptr %_, ptr %_1) #0 !dbg !113 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_CMyCallback.Main(ptr %_1, ptr %_), !dbg !116 +// CHECK:STDOUT: ret void, !dbg !116 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z19TakeComplexCallbackPF1CS_E(ptr noundef) #1 +// CHECK:STDOUT: +// CHECK:STDOUT: attributes #0 = { nounwind } +// CHECK:STDOUT: attributes #1 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: +// CHECK:STDOUT: !llvm.dbg.cu = !{!109} +// CHECK:STDOUT: !llvm.module.flags = !{!17, !18, !19, !2, !3} +// CHECK:STDOUT: !llvm.errno.tbaa = !{!24} +// CHECK:STDOUT: +// CHECK:STDOUT: !2 = !{i32 7, !"Dwarf Version", i32 5} +// CHECK:STDOUT: !3 = !{i32 2, !"Debug Info Version", i32 3} +// CHECK:STDOUT: !6 = !{null} +// CHECK:STDOUT: !7 = !DISubroutineType(types: !6) +// CHECK:STDOUT: !8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) +// CHECK:STDOUT: !17 = !{i32 8, !"PIC Level", i32 2} +// CHECK:STDOUT: !18 = !{i32 7, !"PIE Level", i32 2} +// CHECK:STDOUT: !19 = !{i32 7, !"uwtable", i32 2} +// CHECK:STDOUT: !20 = !{!"Simple C++ TBAA"} +// CHECK:STDOUT: !21 = !{!"omnipotent char", !20, i64 0} +// CHECK:STDOUT: !22 = !{!"int", !21, i64 0} +// CHECK:STDOUT: !23 = !{!"__libc_errno", !22, i64 0} +// CHECK:STDOUT: !24 = !{!23, !22, i64 0} +// CHECK:STDOUT: !92 = !{null, !8, !8} +// CHECK:STDOUT: !93 = !DISubroutineType(types: !92) +// CHECK:STDOUT: !108 = !DIFile(filename: "pass_complex_fn_ptr.carbon", directory: "") +// CHECK:STDOUT: !109 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !108, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !110 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !108, line: 7, type: !7, spFlags: DISPFlagDefinition, unit: !109) +// CHECK:STDOUT: !111 = !DILocation(line: 8, column: 3, scope: !110) +// CHECK:STDOUT: !112 = !DILocation(line: 7, column: 1, scope: !110) +// CHECK:STDOUT: !113 = distinct !DISubprogram(name: "MyCallback__carbon_thunk", linkageName: "_CMyCallback__carbon_thunk.Main", scope: null, file: !108, line: 5, type: !93, spFlags: DISPFlagDefinition, unit: !109, retainedNodes: !117) +// CHECK:STDOUT: !114 = !DILocalVariable(arg: 1, scope: !113, type: !8) +// CHECK:STDOUT: !115 = !DILocalVariable(arg: 2, scope: !113, type: !8) +// CHECK:STDOUT: !116 = !DILocation(line: 5, column: 1, scope: !113) +// CHECK:STDOUT: !117 = !{!114, !115} // CHECK:STDOUT: // CHECK:STDOUT: ; --- // CHECK:STDOUT: ; ModuleID = 'call_complex_fn_ptr.carbon' @@ -292,18 +603,18 @@ fn F() { // CHECK:STDOUT: %class.C = type { i32 } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define void @_CF.Main() #0 !dbg !62 { +// CHECK:STDOUT: define void @_CF.Main() #0 !dbg !122 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %x.var = alloca [4 x i8], align 4, !dbg !63 -// CHECK:STDOUT: %.loc6_58.1.temp = alloca [4 x i8], align 4, !dbg !65 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %x.var), !dbg !63 -// CHECK:STDOUT: %GetComplexCallback.call = call ptr @_Z18GetComplexCallbackv(), !dbg !64 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc6_58.1.temp), !dbg !65 -// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk.(ptr %.loc6_58.1.temp), !dbg !65 -// CHECK:STDOUT: call void @.carbon_thunk.__(ptr %GetComplexCallback.call, ptr %.loc6_58.1.temp, ptr %x.var), !dbg !64 -// CHECK:STDOUT: call void @"_CSelfDestruct.417eccf5eb8addbd:core.Destroy.Core"(ptr %.loc6_58.1.temp), !dbg !65 -// CHECK:STDOUT: call void @"_CSelfDestruct.417eccf5eb8addbd:core.Destroy.Core"(ptr %x.var), !dbg !63 -// CHECK:STDOUT: ret void, !dbg !67 +// CHECK:STDOUT: %x.var = alloca [4 x i8], align 4, !dbg !123 +// CHECK:STDOUT: %.loc6_58.1.temp = alloca [4 x i8], align 4, !dbg !125 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %x.var), !dbg !123 +// CHECK:STDOUT: %GetComplexCallback.call = call ptr @_Z18GetComplexCallbackv(), !dbg !124 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc6_58.1.temp), !dbg !125 +// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk.(ptr %.loc6_58.1.temp), !dbg !125 +// CHECK:STDOUT: call void @.carbon_thunk.__(ptr %GetComplexCallback.call, ptr %.loc6_58.1.temp, ptr %x.var), !dbg !124 +// CHECK:STDOUT: call void @"_CSelfDestruct.417eccf5eb8addbd:core.Destroy.Core"(ptr %.loc6_58.1.temp), !dbg !125 +// CHECK:STDOUT: call void @"_CSelfDestruct.417eccf5eb8addbd:core.Destroy.Core"(ptr %x.var), !dbg !123 +// CHECK:STDOUT: ret void, !dbg !127 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: declare noundef ptr @_Z18GetComplexCallbackv() #1 @@ -312,8 +623,8 @@ fn F() { // CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk.(ptr noundef %return) #2 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %return.addr = alloca ptr, align 8 -// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !73 -// CHECK:STDOUT: %0 = load ptr, ptr %return.addr, align 8, !tbaa !73 +// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !133 +// CHECK:STDOUT: %0 = load ptr, ptr %return.addr, align 8, !tbaa !133 // CHECK:STDOUT: call void @_ZN1CC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %0) // CHECK:STDOUT: ret void // CHECK:STDOUT: } @@ -325,21 +636,21 @@ fn F() { // CHECK:STDOUT: %.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 // CHECK:STDOUT: %agg.tmp = alloca %class.C, align 4 -// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !47 -// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !73 -// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !73 -// CHECK:STDOUT: %1 = load ptr, ptr %return.addr, align 8, !tbaa !73 -// CHECK:STDOUT: %2 = load ptr, ptr %this.addr, align 8, !tbaa !47 -// CHECK:STDOUT: %3 = load ptr, ptr %.addr, align 8, !tbaa !73 +// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !77 +// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !133 +// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !133 +// CHECK:STDOUT: %1 = load ptr, ptr %return.addr, align 8, !tbaa !133 +// CHECK:STDOUT: %2 = load ptr, ptr %this.addr, align 8, !tbaa !77 +// CHECK:STDOUT: %3 = load ptr, ptr %.addr, align 8, !tbaa !133 // CHECK:STDOUT: call void @_ZN1CC1ERKS_(ptr noundef nonnull align 4 dereferenceable(4) %agg.tmp, ptr noundef nonnull align 4 dereferenceable(4) %3) // CHECK:STDOUT: call void %2(ptr dead_on_unwind writable sret(%class.C) align 4 %1, ptr nofreeobj noundef align 4 dead_on_return dereferenceable(4) %agg.tmp) // CHECK:STDOUT: ret void // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define weak_odr void @"_CSelfDestruct.417eccf5eb8addbd:core.Destroy.Core"(ptr %self) #0 !dbg !68 { +// CHECK:STDOUT: define weak_odr void @"_CSelfDestruct.417eccf5eb8addbd:core.Destroy.Core"(ptr %self) #0 !dbg !128 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: ret void, !dbg !70 +// CHECK:STDOUT: ret void, !dbg !130 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) @@ -358,7 +669,7 @@ fn F() { // CHECK:STDOUT: attributes #2 = { alwaysinline mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: -// CHECK:STDOUT: !llvm.dbg.cu = !{!59} +// CHECK:STDOUT: !llvm.dbg.cu = !{!119} // CHECK:STDOUT: !llvm.module.flags = !{!17, !18, !19, !2, !3} // CHECK:STDOUT: !llvm.errno.tbaa = !{!24} // CHECK:STDOUT: @@ -377,21 +688,21 @@ fn F() { // CHECK:STDOUT: !22 = !{!"int", !21, i64 0} // CHECK:STDOUT: !23 = !{!"__libc_errno", !22, i64 0} // CHECK:STDOUT: !24 = !{!23, !22, i64 0} -// CHECK:STDOUT: !46 = !{!"any pointer", !21, i64 0} -// CHECK:STDOUT: !47 = !{!46, !46, i64 0} -// CHECK:STDOUT: !58 = !DIFile(filename: "call_complex_fn_ptr.carbon", directory: "") -// CHECK:STDOUT: !59 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !58, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) -// CHECK:STDOUT: !62 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !58, line: 5, type: !7, spFlags: DISPFlagDefinition, unit: !59) -// CHECK:STDOUT: !63 = !DILocation(line: 6, column: 3, scope: !62) -// CHECK:STDOUT: !64 = !DILocation(line: 6, column: 25, scope: !62) -// CHECK:STDOUT: !65 = !DILocation(line: 6, column: 50, scope: !62) -// CHECK:STDOUT: !67 = !DILocation(line: 5, column: 1, scope: !62) -// CHECK:STDOUT: !68 = distinct !DISubprogram(name: "SelfDestruct", linkageName: "_CSelfDestruct.417eccf5eb8addbd:core.Destroy.Core", scope: null, file: !58, line: 6, type: !12, spFlags: DISPFlagDefinition, unit: !59, retainedNodes: !71) -// CHECK:STDOUT: !69 = !DILocalVariable(arg: 1, scope: !68, type: !8) -// CHECK:STDOUT: !70 = !DILocation(line: 6, column: 50, scope: !68) -// CHECK:STDOUT: !71 = !{!69} -// CHECK:STDOUT: !72 = !{!"p1 _ZTS1C", !46, i64 0} -// CHECK:STDOUT: !73 = !{!72, !72, i64 0} +// CHECK:STDOUT: !76 = !{!"any pointer", !21, i64 0} +// CHECK:STDOUT: !77 = !{!76, !76, i64 0} +// CHECK:STDOUT: !118 = !DIFile(filename: "call_complex_fn_ptr.carbon", directory: "") +// CHECK:STDOUT: !119 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !118, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !122 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !118, line: 5, type: !7, spFlags: DISPFlagDefinition, unit: !119) +// CHECK:STDOUT: !123 = !DILocation(line: 6, column: 3, scope: !122) +// CHECK:STDOUT: !124 = !DILocation(line: 6, column: 25, scope: !122) +// CHECK:STDOUT: !125 = !DILocation(line: 6, column: 50, scope: !122) +// CHECK:STDOUT: !127 = !DILocation(line: 5, column: 1, scope: !122) +// CHECK:STDOUT: !128 = distinct !DISubprogram(name: "SelfDestruct", linkageName: "_CSelfDestruct.417eccf5eb8addbd:core.Destroy.Core", scope: null, file: !118, line: 6, type: !12, spFlags: DISPFlagDefinition, unit: !119, retainedNodes: !131) +// CHECK:STDOUT: !129 = !DILocalVariable(arg: 1, scope: !128, type: !8) +// CHECK:STDOUT: !130 = !DILocation(line: 6, column: 50, scope: !128) +// CHECK:STDOUT: !131 = !{!129} +// CHECK:STDOUT: !132 = !{!"p1 _ZTS1C", !76, i64 0} +// CHECK:STDOUT: !133 = !{!132, !132, i64 0} // CHECK:STDOUT: // CHECK:STDOUT: ; --- // CHECK:STDOUT: ; ModuleID = 'mention_forward_decl.carbon' @@ -400,22 +711,22 @@ fn F() { // CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define void @_CF.Main() #0 !dbg !77 { +// CHECK:STDOUT: define void @_CF.Main() #0 !dbg !137 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %callback.var = alloca ptr, align 8, !dbg !78 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %callback.var), !dbg !78 -// CHECK:STDOUT: %ReturnCallback.call = call ptr @_Z14ReturnCallbackv(), !dbg !79 -// CHECK:STDOUT: store ptr %ReturnCallback.call, ptr %callback.var, align 8, !dbg !78 -// CHECK:STDOUT: call void @"_CSelfDestruct.659d177172b60c17:core.Destroy.Core"(ptr %callback.var), !dbg !78 -// CHECK:STDOUT: ret void, !dbg !81 +// CHECK:STDOUT: %callback.var = alloca ptr, align 8, !dbg !138 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %callback.var), !dbg !138 +// CHECK:STDOUT: %ReturnCallback.call = call ptr @_Z14ReturnCallbackv(), !dbg !139 +// CHECK:STDOUT: store ptr %ReturnCallback.call, ptr %callback.var, align 8, !dbg !138 +// CHECK:STDOUT: call void @"_CSelfDestruct.659d177172b60c17:core.Destroy.Core"(ptr %callback.var), !dbg !138 +// CHECK:STDOUT: ret void, !dbg !141 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: declare noundef ptr @_Z14ReturnCallbackv() #1 // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define weak_odr void @"_CSelfDestruct.659d177172b60c17:core.Destroy.Core"(ptr %self) #0 !dbg !82 { +// CHECK:STDOUT: define weak_odr void @"_CSelfDestruct.659d177172b60c17:core.Destroy.Core"(ptr %self) #0 !dbg !142 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: ret void, !dbg !84 +// CHECK:STDOUT: ret void, !dbg !144 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) @@ -425,7 +736,7 @@ fn F() { // CHECK:STDOUT: attributes #1 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: attributes #2 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: -// CHECK:STDOUT: !llvm.dbg.cu = !{!76} +// CHECK:STDOUT: !llvm.dbg.cu = !{!136} // CHECK:STDOUT: !llvm.module.flags = !{!17, !18, !19, !2, !3} // CHECK:STDOUT: !llvm.errno.tbaa = !{!24} // CHECK:STDOUT: @@ -444,14 +755,14 @@ fn F() { // CHECK:STDOUT: !22 = !{!"int", !21, i64 0} // CHECK:STDOUT: !23 = !{!"__libc_errno", !22, i64 0} // CHECK:STDOUT: !24 = !{!23, !22, i64 0} -// CHECK:STDOUT: !75 = !DIFile(filename: "mention_forward_decl.carbon", directory: "") -// CHECK:STDOUT: !76 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !75, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) -// CHECK:STDOUT: !77 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !75, line: 5, type: !7, spFlags: DISPFlagDefinition, unit: !76) -// CHECK:STDOUT: !78 = !DILocation(line: 6, column: 3, scope: !77) -// CHECK:STDOUT: !79 = !DILocation(line: 6, column: 43, scope: !77) -// CHECK:STDOUT: !81 = !DILocation(line: 5, column: 1, scope: !77) -// CHECK:STDOUT: !82 = distinct !DISubprogram(name: "SelfDestruct", linkageName: "_CSelfDestruct.659d177172b60c17:core.Destroy.Core", scope: null, file: !75, line: 6, type: !12, spFlags: DISPFlagDefinition, unit: !76, retainedNodes: !85) -// CHECK:STDOUT: !83 = !DILocalVariable(arg: 1, scope: !82, type: !8) -// CHECK:STDOUT: !84 = !DILocation(line: 6, column: 3, scope: !82) -// CHECK:STDOUT: !85 = !{!83} +// CHECK:STDOUT: !135 = !DIFile(filename: "mention_forward_decl.carbon", directory: "") +// CHECK:STDOUT: !136 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !135, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !137 = distinct !DISubprogram(name: "F", linkageName: "_CF.Main", scope: null, file: !135, line: 5, type: !7, spFlags: DISPFlagDefinition, unit: !136) +// CHECK:STDOUT: !138 = !DILocation(line: 6, column: 3, scope: !137) +// CHECK:STDOUT: !139 = !DILocation(line: 6, column: 43, scope: !137) +// CHECK:STDOUT: !141 = !DILocation(line: 5, column: 1, scope: !137) +// CHECK:STDOUT: !142 = distinct !DISubprogram(name: "SelfDestruct", linkageName: "_CSelfDestruct.659d177172b60c17:core.Destroy.Core", scope: null, file: !135, line: 6, type: !12, spFlags: DISPFlagDefinition, unit: !136, retainedNodes: !145) +// CHECK:STDOUT: !143 = !DILocalVariable(arg: 1, scope: !142, type: !8) +// CHECK:STDOUT: !144 = !DILocation(line: 6, column: 3, scope: !142) +// CHECK:STDOUT: !145 = !{!143} // CHECK:STDOUT: diff --git a/toolchain/sem_ir/clang_decl.cpp b/toolchain/sem_ir/clang_decl.cpp index 863ec96acc65..af1d851f14c9 100644 --- a/toolchain/sem_ir/clang_decl.cpp +++ b/toolchain/sem_ir/clang_decl.cpp @@ -131,14 +131,14 @@ auto ClangDeclStore::LookupId(ClangDeclKey key) const -> ClangDeclId { return values_.Lookup(key); } -auto ClangDeclStore::Lookup(InstId inst_id, SpecificId specific_id) const - -> const ClangDecl* { +auto ClangDeclStore::LookupId(InstId inst_id, SpecificId specific_id) const + -> ClangDeclId { if (auto result = reverse_lookup_.Lookup( KeyContext::Key{.inst_id = inst_id, .specific_id = specific_id}, KeyContext(this))) { - return &Get(result.key()); + return result.key(); } - return nullptr; + return ClangDeclId::None; } auto ClangDeclStore::OutputYaml() const -> Yaml::OutputMapping { diff --git a/toolchain/sem_ir/clang_decl.h b/toolchain/sem_ir/clang_decl.h index 2a975673d2a2..87d7f7cb818a 100644 --- a/toolchain/sem_ir/clang_decl.h +++ b/toolchain/sem_ir/clang_decl.h @@ -214,10 +214,20 @@ class ClangDeclStore { // Looks up a `ClangDeclId` by `ClangDeclKey`. auto LookupId(ClangDeclKey key) const -> ClangDeclId; + // Looks up a `ClangDeclId` by `InstId` and optional `SpecificId`. + auto LookupId(InstId inst_id, SpecificId specific_id = SpecificId::None) const + -> ClangDeclId; + // Looks up a `ClangDecl` by `InstId` and optional `SpecificId`. Returns // nullptr if not found. auto Lookup(InstId inst_id, SpecificId specific_id = SpecificId::None) const - -> const ClangDecl*; + -> const ClangDecl* { + if (auto clang_decl_id = LookupId(inst_id, specific_id); + clang_decl_id.has_value()) { + return &Get(clang_decl_id); + } + return nullptr; + } auto OutputYaml() const -> Yaml::OutputMapping; diff --git a/toolchain/sem_ir/inst_kind.def b/toolchain/sem_ir/inst_kind.def index c2b2d112e298..717e53e03d95 100644 --- a/toolchain/sem_ir/inst_kind.def +++ b/toolchain/sem_ir/inst_kind.def @@ -59,6 +59,7 @@ CARBON_SEM_IR_INST_KIND(ConvertAction) CARBON_SEM_IR_INST_KIND(ConvertToCategoryAction) CARBON_SEM_IR_INST_KIND(ConvertToValueAction) CARBON_SEM_IR_INST_KIND(Converted) +CARBON_SEM_IR_INST_KIND(CppAddrOfFunction) CARBON_SEM_IR_INST_KIND(CppFunctionPointerType) CARBON_SEM_IR_INST_KIND(CppOverloadSetType) CARBON_SEM_IR_INST_KIND(CppOverloadSetValue) diff --git a/toolchain/sem_ir/typed_insts.h b/toolchain/sem_ir/typed_insts.h index afe9240e5a18..d4791d676f44 100644 --- a/toolchain/sem_ir/typed_insts.h +++ b/toolchain/sem_ir/typed_insts.h @@ -639,6 +639,23 @@ struct ConvertToValueAction { TypeInstId target_type_inst_id; }; +// A C++ function pointer to a Carbon function. +struct CppAddrOfFunction { + static constexpr auto Kind = + InstKind::CppAddrOfFunction.Define( + {.ir_name = "cpp_addr_of_fn", + .expr_category = ExprCategory::Value, + .constant_kind = InstConstantKind::WheneverPossible}); + + TypeId type_id; + + // The inst that refers to the Carbon function. + InstId function_ref_id; + + // The Carbon function. + FunctionId function_id; +}; + // The type of an overloaded C++ function. struct CppOverloadSetType { static constexpr auto Kind = @@ -957,7 +974,7 @@ struct FunctionDecl { static constexpr auto Kind = InstKind::FunctionDecl.Define( {.ir_name = "fn_decl", - .expr_category = ExprCategory::NotExpr, + .expr_category = ExprCategory::Value, .is_lowered = false}); TypeId type_id;