瀏覽代碼

Overload resolution support for more kinds of candidate. (#6071)

* Add support for template candidates by calling the suitable
`AddCandidate` function for them.
* Add support for overloading on `*this` qualifiers by calling
`AddMethodCandidate` when appropriate.
* Make mapping from Carbon arguments to Clang arguments a little more
faithful by mapping the Carbon expression category into the Clang value
kind.
Richard Smith 7 月之前
父節點
當前提交
b054e3d2b0

+ 2 - 8
toolchain/check/call.cpp

@@ -302,14 +302,8 @@ auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,
   }
   }
   if (callee_function.cpp_overload_set_id.has_value()) {
   if (callee_function.cpp_overload_set_id.has_value()) {
     auto self_id = callee_function.self_id;
     auto self_id = callee_function.self_id;
-    // TODO: Pass self_id into overload resolution so that it's taken into
-    // account when selecting the overload.
-    auto resolved_fn_id = PerformCppOverloadResolution(
-        context, loc_id, callee_function.cpp_overload_set_id, arg_ids);
-    if (!resolved_fn_id) {
-      return SemIR::ErrorInst::InstId;
-    }
-    callee_id = resolved_fn_id.value();
+    callee_id = PerformCppOverloadResolution(
+        context, loc_id, callee_function.cpp_overload_set_id, self_id, arg_ids);
     callee_function = GetCalleeFunction(context.sem_ir(), callee_id);
     callee_function = GetCalleeFunction(context.sem_ir(), callee_id);
     if (callee_function.is_error) {
     if (callee_function.is_error) {
       return SemIR::ErrorInst::InstId;
       return SemIR::ErrorInst::InstId;

+ 121 - 30
toolchain/check/cpp_overload_resolution.cpp

@@ -8,13 +8,117 @@
 #include "clang/Sema/Sema.h"
 #include "clang/Sema/Sema.h"
 #include "toolchain/check/cpp_import.h"
 #include "toolchain/check/cpp_import.h"
 #include "toolchain/check/cpp_type_mapping.h"
 #include "toolchain/check/cpp_type_mapping.h"
+#include "toolchain/sem_ir/expr_info.h"
+#include "toolchain/sem_ir/typed_insts.h"
 
 
 namespace Carbon::Check {
 namespace Carbon::Check {
 
 
+// Invents a Clang argument expression to use in overload resolution to
+// represent the given Carbon argument instruction.
+static auto InventClangArg(Context& context, SemIR::InstId arg_id)
+    -> clang::Expr* {
+  clang::ExprValueKind value_kind;
+  switch (SemIR::GetExprCategory(context.sem_ir(), arg_id)) {
+    case SemIR::ExprCategory::NotExpr:
+      CARBON_FATAL("Should not see these here");
+
+    case SemIR::ExprCategory::Error:
+      return nullptr;
+
+    case SemIR::ExprCategory::DurableRef:
+      value_kind = clang::ExprValueKind::VK_LValue;
+      break;
+
+    case SemIR::ExprCategory::EphemeralRef:
+      value_kind = clang::ExprValueKind::VK_XValue;
+      break;
+
+    case SemIR::ExprCategory::Value:
+    case SemIR::ExprCategory::Initializing:
+      value_kind = clang::ExprValueKind::VK_PRValue;
+      break;
+
+    case SemIR::ExprCategory::Mixed:
+      // TODO: Handle this by creating an InitListExpr.
+      value_kind = clang::ExprValueKind::VK_PRValue;
+      break;
+  }
+
+  if (context.insts().Get(arg_id).type_id() == SemIR::ErrorInst::TypeId) {
+    // The argument error has already been diagnosed.
+    return nullptr;
+  }
+
+  clang::QualType arg_cpp_type = MapToCppType(context, arg_id);
+  if (arg_cpp_type.isNull()) {
+    CARBON_DIAGNOSTIC(CppCallArgTypeNotSupported, Error,
+                      "call argument of type {0} is not supported",
+                      TypeOfInstId);
+    context.emitter().Emit(arg_id, CppCallArgTypeNotSupported, arg_id);
+    return nullptr;
+  }
+
+  // TODO: Avoid heap allocating more of these on every call. Either cache them
+  // somewhere or put them on the stack.
+  return new (context.ast_context()) clang::OpaqueValueExpr(
+      // TODO: Add location accordingly.
+      clang::SourceLocation(), arg_cpp_type.getNonReferenceType(), value_kind);
+}
+
+// Adds the given overload candidates to the candidate set.
+static auto AddOverloadCandidataes(clang::Sema& sema,
+                                   clang::OverloadCandidateSet& candidate_set,
+                                   const clang::UnresolvedSetImpl& functions,
+                                   clang::Expr* self_arg,
+                                   llvm::ArrayRef<clang::Expr*> args) -> void {
+  constexpr bool SuppressUserConversions = false;
+  constexpr bool PartialOverloading = false;
+  constexpr clang::TemplateArgumentListInfo* ExplicitTemplateArgs = nullptr;
+
+  for (auto found_decl : functions.pairs()) {
+    auto* decl = found_decl.getDecl()->getUnderlyingDecl();
+    auto* template_decl = dyn_cast<clang::FunctionTemplateDecl>(decl);
+    auto* fn_decl = template_decl ? template_decl->getTemplatedDecl()
+                                  : cast<clang::FunctionDecl>(decl);
+    auto* method_decl = dyn_cast<clang::CXXMethodDecl>(fn_decl);
+    if (method_decl && !method_decl->isStatic() &&
+        !isa<clang::CXXConstructorDecl>(fn_decl)) {
+      clang::QualType self_type;
+      clang::Expr::Classification self_classification;
+      if (self_arg) {
+        self_type = self_arg->getType();
+        self_classification = self_arg->Classify(sema.Context);
+      }
+      if (template_decl) {
+        sema.AddMethodTemplateCandidate(
+            template_decl, found_decl,
+            cast<clang::CXXRecordDecl>(template_decl->getDeclContext()),
+            ExplicitTemplateArgs, self_type, self_classification, args,
+            candidate_set, SuppressUserConversions, PartialOverloading);
+      } else {
+        sema.AddMethodCandidate(method_decl, found_decl,
+                                method_decl->getParent(), self_type,
+                                self_classification, args, candidate_set,
+                                SuppressUserConversions, PartialOverloading);
+      }
+    } else {
+      if (template_decl) {
+        sema.AddTemplateOverloadCandidate(
+            template_decl, found_decl, ExplicitTemplateArgs, args,
+            candidate_set, SuppressUserConversions, PartialOverloading);
+      } else {
+        sema.AddOverloadCandidate(fn_decl, found_decl, args, candidate_set,
+                                  SuppressUserConversions, PartialOverloading);
+      }
+    }
+  }
+}
+
 auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
 auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
                                   SemIR::CppOverloadSetId overload_set_id,
                                   SemIR::CppOverloadSetId overload_set_id,
+                                  SemIR::InstId self_id,
                                   llvm::ArrayRef<SemIR::InstId> arg_ids)
                                   llvm::ArrayRef<SemIR::InstId> arg_ids)
-    -> std::optional<SemIR::InstId> {
+    -> SemIR::InstId {
   Diagnostics::AnnotationScope annotate_diagnostics(
   Diagnostics::AnnotationScope annotate_diagnostics(
       &context.emitter(), [&](auto& builder) {
       &context.emitter(), [&](auto& builder) {
         CARBON_DIAGNOSTIC(InCallToCppFunction, Note,
         CARBON_DIAGNOSTIC(InCallToCppFunction, Note,
@@ -23,22 +127,21 @@ auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
       });
       });
 
 
   // Map Carbon call argument types to C++ types.
   // Map Carbon call argument types to C++ types.
+  clang::Expr* self_expr = nullptr;
+  if (self_id.has_value()) {
+    self_expr = InventClangArg(context, self_id);
+    if (!self_expr) {
+      return SemIR::ErrorInst::InstId;
+    }
+  }
   llvm::SmallVector<clang::Expr*> arg_exprs;
   llvm::SmallVector<clang::Expr*> arg_exprs;
   arg_exprs.reserve(arg_ids.size());
   arg_exprs.reserve(arg_ids.size());
   for (SemIR::InstId arg_id : arg_ids) {
   for (SemIR::InstId arg_id : arg_ids) {
-    clang::QualType arg_cpp_type = MapToCppType(context, arg_id);
-    if (arg_cpp_type.isNull()) {
-      CARBON_DIAGNOSTIC(CppCallArgTypeNotSupported, Error,
-                        "call argument of type {0} is not supported",
-                        TypeOfInstId);
-      context.emitter().Emit(loc_id, CppCallArgTypeNotSupported, arg_id);
-      return std::nullopt;
+    auto* arg_expr = InventClangArg(context, arg_id);
+    if (!arg_expr) {
+      return SemIR::ErrorInst::InstId;
     }
     }
-    // TODO: Allocate these on the stack.
-    arg_exprs.emplace_back(new (context.ast_context()) clang::OpaqueValueExpr(
-        // TODO: Add location accordingly.
-        clang::SourceLocation(), arg_cpp_type.getNonReferenceType(),
-        clang::ExprValueKind::VK_LValue));
+    arg_exprs.push_back(arg_expr);
   }
   }
 
 
   const SemIR::CppOverloadSet& overload_set =
   const SemIR::CppOverloadSet& overload_set =
@@ -54,20 +157,8 @@ auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
   CARBON_CHECK(ast);
   CARBON_CHECK(ast);
   clang::Sema& sema = ast->getSema();
   clang::Sema& sema = ast->getSema();
 
 
-  // TODO: Add support for method calls.
-  for (clang::NamedDecl* candidate : overload_set.candidate_functions) {
-    if (auto* fn_decl = dyn_cast<clang::FunctionDecl>(candidate)) {
-      sema.AddOverloadCandidate(
-          fn_decl, clang::DeclAccessPair::make(fn_decl, candidate->getAccess()),
-          arg_exprs, candidate_set);
-    } else if (isa<clang::FunctionTemplateDecl>(candidate)) {
-      CARBON_DIAGNOSTIC(CppTemplateFunctionNotSupported, Error,
-                        "template function is not supported");
-      context.emitter().Emit(loc_id, CppTemplateFunctionNotSupported);
-      return std::nullopt;
-    }
-    // TODO: Diagnose if it's neither of these types.
-  }
+  AddOverloadCandidataes(sema, candidate_set, overload_set.candidate_functions,
+                         self_expr, arg_exprs);
 
 
   // Find best viable function among the candidates.
   // Find best viable function among the candidates.
   clang::OverloadCandidateSet::iterator best_viable_fn;
   clang::OverloadCandidateSet::iterator best_viable_fn;
@@ -91,7 +182,7 @@ auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
                         SemIR::NameId);
                         SemIR::NameId);
       context.emitter().Emit(loc_id, CppOverloadingNoViableFunctionFound,
       context.emitter().Emit(loc_id, CppOverloadingNoViableFunctionFound,
                              overload_set.name_id);
                              overload_set.name_id);
-      return std::nullopt;
+      return SemIR::ErrorInst::InstId;
     }
     }
     case clang::OverloadingResult::OR_Ambiguous: {
     case clang::OverloadingResult::OR_Ambiguous: {
       // TODO: Add notes with the candidates.
       // TODO: Add notes with the candidates.
@@ -99,7 +190,7 @@ auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
                         "call to `{0}` is ambiguous", SemIR::NameId);
                         "call to `{0}` is ambiguous", SemIR::NameId);
       context.emitter().Emit(loc_id, CppOverloadingAmbiguousCandidatesFound,
       context.emitter().Emit(loc_id, CppOverloadingAmbiguousCandidatesFound,
                              overload_set.name_id);
                              overload_set.name_id);
-      return std::nullopt;
+      return SemIR::ErrorInst::InstId;
     }
     }
     case clang::OverloadingResult::OR_Deleted: {
     case clang::OverloadingResult::OR_Deleted: {
       // TODO: Add notes with the candidates.
       // TODO: Add notes with the candidates.
@@ -107,7 +198,7 @@ auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
                         "call to deleted function `{0}`", SemIR::NameId);
                         "call to deleted function `{0}`", SemIR::NameId);
       context.emitter().Emit(loc_id, CppOverloadingDeletedFunctionFound,
       context.emitter().Emit(loc_id, CppOverloadingDeletedFunctionFound,
                              overload_set.name_id);
                              overload_set.name_id);
-      return std::nullopt;
+      return SemIR::ErrorInst::InstId;
     }
     }
   }
   }
 }
 }

+ 4 - 3
toolchain/check/cpp_overload_resolution.h

@@ -13,8 +13,8 @@ namespace Carbon::Check {
 // Performs overloading resolution for a call to an overloaded C++ set. A set
 // Performs overloading resolution for a call to an overloaded C++ set. A set
 // with a single non-templated function goes through the same rules for
 // with a single non-templated function goes through the same rules for
 // overloading resolution. Uses Clang to find the best viable function for the
 // overloading resolution. Uses Clang to find the best viable function for the
-// call. Returns the resolved function, or `nullopt` if overload resolution
-// failed.
+// call. Returns the resolved function, or an error instruction if overload
+// resolution failed.
 //
 //
 // Note on non-overloaded functions: In C++, a single non-templated function is
 // Note on non-overloaded functions: In C++, a single non-templated function is
 // also treated as an overloaded set and goes through the overload resolution to
 // also treated as an overloaded set and goes through the overload resolution to
@@ -25,8 +25,9 @@ namespace Carbon::Check {
 // remain valid.
 // remain valid.
 auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
 auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
                                   SemIR::CppOverloadSetId overload_set_id,
                                   SemIR::CppOverloadSetId overload_set_id,
+                                  SemIR::InstId self_id,
                                   llvm::ArrayRef<SemIR::InstId> arg_ids)
                                   llvm::ArrayRef<SemIR::InstId> arg_ids)
-    -> std::optional<SemIR::InstId>;
+    -> SemIR::InstId;
 
 
 }  // namespace Carbon::Check
 }  // namespace Carbon::Check
 
 

+ 216 - 5
toolchain/check/testdata/interop/cpp/class/method.carbon

@@ -67,10 +67,12 @@ fn Value(v: Cpp.HasQualifiers) {
   // CHECK:STDERR:
   // CHECK:STDERR:
   v.volatile_this();
   v.volatile_this();
 
 
-  // CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+5]]:3: error: `addr self` method cannot be invoked on a value [AddrSelfIsNonRef]
+  // CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+7]]:3: error: no matching function for call to `ref_this` [CppOverloadingNoViableFunctionFound]
   // CHECK:STDERR:   v.ref_this();
   // CHECK:STDERR:   v.ref_this();
-  // CHECK:STDERR:   ^
-  // CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon: note: initializing function parameter [InCallToFunctionParam]
+  // CHECK:STDERR:   ^~~~~~~~~~~~
+  // CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
+  // CHECK:STDERR:   v.ref_this();
+  // CHECK:STDERR:   ^~~~~~~~~~~~
   // CHECK:STDERR:
   // CHECK:STDERR:
   v.ref_this();
   v.ref_this();
 
 
@@ -118,7 +120,7 @@ library "[[@TEST_NAME]]";
 import Cpp library "object_param_qualifiers.h";
 import Cpp library "object_param_qualifiers.h";
 
 
 fn Ref(p: Cpp.HasQualifiers*) {
 fn Ref(p: Cpp.HasQualifiers*) {
-  // CHECK:STDERR: fail_bad_object_param_qualifiers_ref_ref.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: object parameter type: struct HasQualifiers &&` [SemanticsTodo]
+  // CHECK:STDERR: fail_bad_object_param_qualifiers_ref_ref.carbon:[[@LINE+7]]:3: error: no matching function for call to `ref_ref_this` [CppOverloadingNoViableFunctionFound]
   // CHECK:STDERR:   p->ref_ref_this();
   // CHECK:STDERR:   p->ref_ref_this();
   // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~
   // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~
   // CHECK:STDERR: fail_bad_object_param_qualifiers_ref_ref.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
   // CHECK:STDERR: fail_bad_object_param_qualifiers_ref_ref.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
@@ -127,7 +129,7 @@ fn Ref(p: Cpp.HasQualifiers*) {
   // CHECK:STDERR:
   // CHECK:STDERR:
   p->ref_ref_this();
   p->ref_ref_this();
 
 
-  // CHECK:STDERR: fail_bad_object_param_qualifiers_ref_ref.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: object parameter type: const struct HasQualifiers &&` [SemanticsTodo]
+  // CHECK:STDERR: fail_bad_object_param_qualifiers_ref_ref.carbon:[[@LINE+7]]:3: error: no matching function for call to `const_ref_ref_this` [CppOverloadingNoViableFunctionFound]
   // CHECK:STDERR:   p->const_ref_ref_this();
   // CHECK:STDERR:   p->const_ref_ref_this();
   // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~
   // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~
   // CHECK:STDERR: fail_bad_object_param_qualifiers_ref_ref.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
   // CHECK:STDERR: fail_bad_object_param_qualifiers_ref_ref.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
@@ -137,6 +139,27 @@ fn Ref(p: Cpp.HasQualifiers*) {
   p->const_ref_ref_this();
   p->const_ref_ref_this();
 }
 }
 
 
+// --- object_param_qualifiers_overloaded.h
+
+struct HasQualifiers {
+  int* _Nonnull F() &;
+  int F() const &;
+  void F() volatile &;
+};
+
+// --- use_object_param_qualifiers_overloaded.carbon
+
+library "[[@TEST_NAME]]";
+
+import Cpp library "object_param_qualifiers_overloaded.h";
+
+fn CallF(v: Cpp.HasQualifiers, p: Cpp.HasQualifiers*) {
+  //@dump-sem-ir-begin
+  var a: i32 = v.F();
+  var b: i32* = p->F();
+  //@dump-sem-ir-end
+}
+
 // --- explicit_object_param.h
 // --- explicit_object_param.h
 
 
 struct Another {
 struct Another {
@@ -162,6 +185,31 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
   //@dump-sem-ir-end
   //@dump-sem-ir-end
 }
 }
 
 
+// --- explicit_object_param_overloaded.h
+
+struct Another {
+};
+
+struct ExplicitObjectParam {
+  void F(this ExplicitObjectParam);
+  void F(this int);
+  void F(this Another);
+};
+
+// --- call_explicit_object_param_overloaded.carbon
+
+library "[[@TEST_NAME]]";
+
+import Cpp library "explicit_object_param_overloaded.h";
+
+fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
+  //@dump-sem-ir-begin
+  e.F();
+  n.(Cpp.ExplicitObjectParam.F)();
+  a.(Cpp.ExplicitObjectParam.F)();
+  //@dump-sem-ir-end
+}
+
 // CHECK:STDOUT: --- use_object_param_qualifiers.carbon
 // CHECK:STDOUT: --- use_object_param_qualifiers.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT: constants {
@@ -268,6 +316,98 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
+// CHECK:STDOUT: --- use_object_param_qualifiers_overloaded.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %HasQualifiers: type = class_type @HasQualifiers [concrete]
+// CHECK:STDOUT:   %ptr.ec3: type = ptr_type %HasQualifiers [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
+// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
+// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
+// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]
+// CHECK:STDOUT:   %.4ab: type = cpp_overload_set_type @HasQualifiers.F.1 [concrete]
+// CHECK:STDOUT:   %empty_struct: %.4ab = struct_value () [concrete]
+// CHECK:STDOUT:   %const: type = const_type %HasQualifiers [concrete]
+// CHECK:STDOUT:   %ptr.2cb: type = ptr_type %const [concrete]
+// CHECK:STDOUT:   %F__carbon_thunk.type: type = fn_type @F__carbon_thunk [concrete]
+// CHECK:STDOUT:   %F__carbon_thunk: %F__carbon_thunk.type = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]
+// CHECK:STDOUT:   %pattern_type.fe8: type = pattern_type %ptr.235 [concrete]
+// CHECK:STDOUT:   %HasQualifiers.F.type.d208f0.2: type = fn_type @HasQualifiers.F.2 [concrete]
+// CHECK:STDOUT:   %HasQualifiers.F.efd4e4.2: %HasQualifiers.F.type.d208f0.2 = struct_value () [concrete]
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.type.f3e: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(%ptr.235) [concrete]
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.a18: %T.as.Destroy.impl.Op.type.f3e = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.5d5: type = ptr_type %ptr.235 [concrete]
+// CHECK:STDOUT:   %Int.as.Destroy.impl.Op.type.4f9: type = fn_type @Int.as.Destroy.impl.Op, @Int.as.Destroy.impl(%int_32) [concrete]
+// CHECK:STDOUT:   %Int.as.Destroy.impl.Op.796: %Int.as.Destroy.impl.Op.type.4f9 = struct_value () [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %.570: %.4ab = cpp_overload_set_value @HasQualifiers.F.1 [concrete = constants.%empty_struct]
+// CHECK:STDOUT:   %F__carbon_thunk.decl: %F__carbon_thunk.type = fn_decl @F__carbon_thunk [concrete = constants.%F__carbon_thunk] {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %HasQualifiers.F.decl.f862ea.2: %HasQualifiers.F.type.d208f0.2 = fn_decl @HasQualifiers.F.2 [concrete = constants.%HasQualifiers.F.efd4e4.2] {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @CallF(%v.param: %HasQualifiers, %p.param: %ptr.ec3) {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = binding_pattern a [concrete]
+// CHECK:STDOUT:     %a.var_patt: %pattern_type.7ce = var_pattern %a.patt [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %a.var: ref %i32 = var %a.var_patt
+// CHECK:STDOUT:   %v.ref: %HasQualifiers = name_ref v, %v
+// CHECK:STDOUT:   %F.ref.loc8: %.4ab = name_ref F, imports.%.570 [concrete = constants.%empty_struct]
+// CHECK:STDOUT:   %bound_method.loc8_17: <bound method> = bound_method %v.ref, %F.ref.loc8
+// CHECK:STDOUT:   %.loc8_16: ref %HasQualifiers = value_as_ref %v.ref
+// CHECK:STDOUT:   %addr.loc8_20: %ptr.ec3 = addr_of %.loc8_16
+// CHECK:STDOUT:   %.loc8_20.1: %ptr.2cb = as_compatible %addr.loc8_20
+// CHECK:STDOUT:   %.loc8_20.2: %ptr.2cb = converted %addr.loc8_20, %.loc8_20.1
+// CHECK:STDOUT:   %F__carbon_thunk.call: init %i32 = call imports.%F__carbon_thunk.decl(%.loc8_20.2)
+// CHECK:STDOUT:   assign %a.var, %F__carbon_thunk.call
+// CHECK:STDOUT:   %.loc8_10: type = splice_block %i32.loc8 [concrete = constants.%i32] {
+// CHECK:STDOUT:     %int_32.loc8: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc8: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %a: ref %i32 = bind_name a, %a.var
+// CHECK:STDOUT:   name_binding_decl {
+// CHECK:STDOUT:     %b.patt: %pattern_type.fe8 = binding_pattern b [concrete]
+// CHECK:STDOUT:     %b.var_patt: %pattern_type.fe8 = var_pattern %b.patt [concrete]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %b.var: ref %ptr.235 = var %b.var_patt
+// CHECK:STDOUT:   %p.ref: %ptr.ec3 = name_ref p, %p
+// CHECK:STDOUT:   %.loc9_18: ref %HasQualifiers = deref %p.ref
+// CHECK:STDOUT:   %F.ref.loc9: %.4ab = name_ref F, imports.%.570 [concrete = constants.%empty_struct]
+// CHECK:STDOUT:   %bound_method.loc9_18: <bound method> = bound_method %.loc9_18, %F.ref.loc9
+// CHECK:STDOUT:   %addr.loc9_18: %ptr.ec3 = addr_of %.loc9_18
+// CHECK:STDOUT:   %HasQualifiers.F.call: init %ptr.235 = call imports.%HasQualifiers.F.decl.f862ea.2(%addr.loc9_18)
+// CHECK:STDOUT:   assign %b.var, %HasQualifiers.F.call
+// CHECK:STDOUT:   %.loc9_13: type = splice_block %ptr.loc9 [concrete = constants.%ptr.235] {
+// CHECK:STDOUT:     %int_32.loc9: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
+// CHECK:STDOUT:     %i32.loc9: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
+// CHECK:STDOUT:     %ptr.loc9: type = ptr_type %i32.loc9 [concrete = constants.%ptr.235]
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %b: ref %ptr.235 = bind_name b, %b.var
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.bound: <bound method> = bound_method %b.var, constants.%T.as.Destroy.impl.Op.a18
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %bound_method.loc9_3: <bound method> = bound_method %b.var, %T.as.Destroy.impl.Op.specific_fn
+// CHECK:STDOUT:   %addr.loc9_3: %ptr.5d5 = addr_of %b.var
+// CHECK:STDOUT:   %T.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc9_3(%addr.loc9_3)
+// CHECK:STDOUT:   %Int.as.Destroy.impl.Op.bound: <bound method> = bound_method %a.var, constants.%Int.as.Destroy.impl.Op.796
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT:   %bound_method.loc8_3: <bound method> = bound_method %a.var, %Int.as.Destroy.impl.Op.specific_fn
+// CHECK:STDOUT:   %addr.loc8_3: %ptr.235 = addr_of %a.var
+// CHECK:STDOUT:   %Int.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method.loc8_3(%addr.loc8_3)
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
 // CHECK:STDOUT: --- call_explicit_object_param.carbon
 // CHECK:STDOUT: --- call_explicit_object_param.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT: constants {
@@ -345,3 +485,74 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
+// CHECK:STDOUT: --- call_explicit_object_param_overloaded.carbon
+// CHECK:STDOUT:
+// CHECK:STDOUT: constants {
+// CHECK:STDOUT:   %ExplicitObjectParam: type = class_type @ExplicitObjectParam [concrete]
+// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
+// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
+// CHECK:STDOUT:   %Another: type = class_type @Another [concrete]
+// CHECK:STDOUT:   %.3e2: type = cpp_overload_set_type @ExplicitObjectParam.F.1 [concrete]
+// CHECK:STDOUT:   %empty_struct: %.3e2 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.7f5: type = ptr_type %ExplicitObjectParam [concrete]
+// CHECK:STDOUT:   %F__carbon_thunk.type.eda1ac.1: type = fn_type @F__carbon_thunk.1 [concrete]
+// CHECK:STDOUT:   %F__carbon_thunk.0cd6a8.1: %F__carbon_thunk.type.eda1ac.1 = struct_value () [concrete]
+// CHECK:STDOUT:   %ExplicitObjectParam.F.type.5d25a8.2: type = fn_type @ExplicitObjectParam.F.2 [concrete]
+// CHECK:STDOUT:   %ExplicitObjectParam.F.28cf2e.2: %ExplicitObjectParam.F.type.5d25a8.2 = struct_value () [concrete]
+// CHECK:STDOUT:   %ptr.289: type = ptr_type %Another [concrete]
+// CHECK:STDOUT:   %F__carbon_thunk.type.eda1ac.2: type = fn_type @F__carbon_thunk.2 [concrete]
+// CHECK:STDOUT:   %F__carbon_thunk.0cd6a8.2: %F__carbon_thunk.type.eda1ac.2 = struct_value () [concrete]
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: imports {
+// CHECK:STDOUT:   %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
+// CHECK:STDOUT:     .ExplicitObjectParam = %ExplicitObjectParam.decl
+// CHECK:STDOUT:     .Another = %Another.decl
+// CHECK:STDOUT:     import Cpp//...
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %ExplicitObjectParam.decl: type = class_decl @ExplicitObjectParam [concrete = constants.%ExplicitObjectParam] {} {}
+// CHECK:STDOUT:   %Another.decl: type = class_decl @Another [concrete = constants.%Another] {} {}
+// CHECK:STDOUT:   %.037: %.3e2 = cpp_overload_set_value @ExplicitObjectParam.F.1 [concrete = constants.%empty_struct]
+// CHECK:STDOUT:   %F__carbon_thunk.decl.e1b8ec.1: %F__carbon_thunk.type.eda1ac.1 = fn_decl @F__carbon_thunk.1 [concrete = constants.%F__carbon_thunk.0cd6a8.1] {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %ExplicitObjectParam.F.decl.28f5af.2: %ExplicitObjectParam.F.type.5d25a8.2 = fn_decl @ExplicitObjectParam.F.2 [concrete = constants.%ExplicitObjectParam.F.28cf2e.2] {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %F__carbon_thunk.decl.e1b8ec.2: %F__carbon_thunk.type.eda1ac.2 = fn_decl @F__carbon_thunk.2 [concrete = constants.%F__carbon_thunk.0cd6a8.2] {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   }
+// CHECK:STDOUT: }
+// CHECK:STDOUT:
+// CHECK:STDOUT: fn @Call(%e.param: %ExplicitObjectParam, %n.param: %i32, %a.param: %Another) {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %e.ref: %ExplicitObjectParam = name_ref e, %e
+// CHECK:STDOUT:   %F.ref.loc8: %.3e2 = name_ref F, imports.%.037 [concrete = constants.%empty_struct]
+// CHECK:STDOUT:   %bound_method.loc8: <bound method> = bound_method %e.ref, %F.ref.loc8
+// CHECK:STDOUT:   %.loc8: ref %ExplicitObjectParam = value_as_ref %e.ref
+// CHECK:STDOUT:   %addr.loc8: %ptr.7f5 = addr_of %.loc8
+// CHECK:STDOUT:   %F__carbon_thunk.call.loc8: init %empty_tuple.type = call imports.%F__carbon_thunk.decl.e1b8ec.1(%addr.loc8)
+// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n
+// CHECK:STDOUT:   %Cpp.ref.loc9: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
+// CHECK:STDOUT:   %ExplicitObjectParam.ref.loc9: type = name_ref ExplicitObjectParam, imports.%ExplicitObjectParam.decl [concrete = constants.%ExplicitObjectParam]
+// CHECK:STDOUT:   %F.ref.loc9: %.3e2 = name_ref F, imports.%.037 [concrete = constants.%empty_struct]
+// CHECK:STDOUT:   %bound_method.loc9: <bound method> = bound_method %n.ref, %F.ref.loc9
+// CHECK:STDOUT:   %ExplicitObjectParam.F.call: init %empty_tuple.type = call imports.%ExplicitObjectParam.F.decl.28f5af.2(%n.ref)
+// CHECK:STDOUT:   %a.ref: %Another = name_ref a, %a
+// CHECK:STDOUT:   %Cpp.ref.loc10: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
+// CHECK:STDOUT:   %ExplicitObjectParam.ref.loc10: type = name_ref ExplicitObjectParam, imports.%ExplicitObjectParam.decl [concrete = constants.%ExplicitObjectParam]
+// CHECK:STDOUT:   %F.ref.loc10: %.3e2 = name_ref F, imports.%.037 [concrete = constants.%empty_struct]
+// CHECK:STDOUT:   %bound_method.loc10: <bound method> = bound_method %a.ref, %F.ref.loc10
+// CHECK:STDOUT:   %.loc10: ref %Another = value_as_ref %a.ref
+// CHECK:STDOUT:   %addr.loc10: %ptr.289 = addr_of %.loc10
+// CHECK:STDOUT:   %F__carbon_thunk.call.loc10: init %empty_tuple.type = call imports.%F__carbon_thunk.decl.e1b8ec.2(%addr.loc10)
+// CHECK:STDOUT:   <elided>
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 4 - 54
toolchain/check/testdata/interop/cpp/function/class.carbon

@@ -27,7 +27,7 @@ library "[[@TEST_NAME]]";
 import Cpp library "decl_value_param_type.h";
 import Cpp library "decl_value_param_type.h";
 
 
 fn F() {
 fn F() {
-  // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE+15]]:11: error: invalid use of incomplete type `Cpp.C` [IncompleteTypeInConversion]
+  // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE+8]]:11: error: invalid use of incomplete type `Cpp.C` [IncompleteTypeInConversion]
   // CHECK:STDERR:   Cpp.foo({} as Cpp.C);
   // CHECK:STDERR:   Cpp.foo({} as Cpp.C);
   // CHECK:STDERR:           ^~~~~~~~~~~
   // CHECK:STDERR:           ^~~~~~~~~~~
   // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE-6]]:10: in file included here [InCppInclude]
   // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE-6]]:10: in file included here [InCppInclude]
@@ -35,13 +35,6 @@ fn F() {
   // CHECK:STDERR: class C;
   // CHECK:STDERR: class C;
   // CHECK:STDERR:       ^
   // CHECK:STDERR:       ^
   // CHECK:STDERR:
   // CHECK:STDERR:
-  // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE+7]]:3: error: call argument of type `<error>` is not supported [CppCallArgTypeNotSupported]
-  // CHECK:STDERR:   Cpp.foo({} as Cpp.C);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
-  // CHECK:STDERR:   Cpp.foo({} as Cpp.C);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
   Cpp.foo({} as Cpp.C);
   Cpp.foo({} as Cpp.C);
 }
 }
 
 
@@ -65,13 +58,6 @@ fn F() {
   // CHECK:STDERR:               ^
   // CHECK:STDERR:               ^
   // CHECK:STDERR:
   // CHECK:STDERR:
   let c: Cpp.C;
   let c: Cpp.C;
-  // CHECK:STDERR: fail_import_decl_value_param_type_previously_imported.carbon:[[@LINE+7]]:3: error: call argument of type `<error>` is not supported [CppCallArgTypeNotSupported]
-  // CHECK:STDERR:   Cpp.foo(c);
-  // CHECK:STDERR:   ^~~~~~~~~~
-  // CHECK:STDERR: fail_import_decl_value_param_type_previously_imported.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
-  // CHECK:STDERR:   Cpp.foo(c);
-  // CHECK:STDERR:   ^~~~~~~~~~
-  // CHECK:STDERR:
   Cpp.foo(c);
   Cpp.foo(c);
 }
 }
 
 
@@ -93,7 +79,7 @@ library "[[@TEST_NAME]]";
 import Cpp library "double_decl_value_param_type.h";
 import Cpp library "double_decl_value_param_type.h";
 
 
 fn F() {
 fn F() {
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+15]]:12: error: invalid use of incomplete type `Cpp.C` [IncompleteTypeInConversion]
+  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+8]]:12: error: invalid use of incomplete type `Cpp.C` [IncompleteTypeInConversion]
   // CHECK:STDERR:   Cpp.foo1({} as Cpp.C);
   // CHECK:STDERR:   Cpp.foo1({} as Cpp.C);
   // CHECK:STDERR:            ^~~~~~~~~~~
   // CHECK:STDERR:            ^~~~~~~~~~~
   // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE-6]]:10: in file included here [InCppInclude]
   // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE-6]]:10: in file included here [InCppInclude]
@@ -101,29 +87,15 @@ fn F() {
   // CHECK:STDERR: class C;
   // CHECK:STDERR: class C;
   // CHECK:STDERR:       ^
   // CHECK:STDERR:       ^
   // CHECK:STDERR:
   // CHECK:STDERR:
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+7]]:3: error: call argument of type `<error>` is not supported [CppCallArgTypeNotSupported]
-  // CHECK:STDERR:   Cpp.foo1({} as Cpp.C);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
-  // CHECK:STDERR:   Cpp.foo1({} as Cpp.C);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
   Cpp.foo1({} as Cpp.C);
   Cpp.foo1({} as Cpp.C);
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+15]]:12: error: invalid use of incomplete type `Cpp.C` [IncompleteTypeInConversion]
+  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+8]]:12: error: invalid use of incomplete type `Cpp.C` [IncompleteTypeInConversion]
   // CHECK:STDERR:   Cpp.foo2({} as Cpp.C);
   // CHECK:STDERR:   Cpp.foo2({} as Cpp.C);
   // CHECK:STDERR:            ^~~~~~~~~~~
   // CHECK:STDERR:            ^~~~~~~~~~~
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE-22]]:10: in file included here [InCppInclude]
+  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE-15]]:10: in file included here [InCppInclude]
   // CHECK:STDERR: ./double_decl_value_param_type.h:2:7: note: class was forward declared here [ClassForwardDeclaredHere]
   // CHECK:STDERR: ./double_decl_value_param_type.h:2:7: note: class was forward declared here [ClassForwardDeclaredHere]
   // CHECK:STDERR: class C;
   // CHECK:STDERR: class C;
   // CHECK:STDERR:       ^
   // CHECK:STDERR:       ^
   // CHECK:STDERR:
   // CHECK:STDERR:
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+7]]:3: error: call argument of type `<error>` is not supported [CppCallArgTypeNotSupported]
-  // CHECK:STDERR:   Cpp.foo2({} as Cpp.C);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
-  // CHECK:STDERR:   Cpp.foo2({} as Cpp.C);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
   Cpp.foo2({} as Cpp.C);
   Cpp.foo2({} as Cpp.C);
 }
 }
 
 
@@ -633,14 +605,10 @@ fn F() {
 // CHECK:STDOUT: --- fail_todo_import_definition_single_data_member_value_param_type.carbon
 // CHECK:STDOUT: --- fail_todo_import_definition_single_data_member_value_param_type.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %C: type = class_type @C [concrete]
 // CHECK:STDOUT:   %C: type = class_type @C [concrete]
 // CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @As.Convert [concrete]
 // CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @As.Convert [concrete]
 // CHECK:STDOUT:   %empty_struct: %.c5d = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct: %.c5d = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %ptr.d9e: type = ptr_type %C [concrete]
-// CHECK:STDOUT:   %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
-// CHECK:STDOUT:   %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: imports {
@@ -651,11 +619,6 @@ fn F() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
 // CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct]
 // CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct]
-// CHECK:STDOUT:   %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] {
-// CHECK:STDOUT:     <elided>
-// CHECK:STDOUT:   } {
-// CHECK:STDOUT:     <elided>
-// CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: fn @F() {
@@ -666,22 +629,16 @@ fn F() {
 // CHECK:STDOUT:   %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%C.decl [concrete = constants.%C]
 // CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%C.decl [concrete = constants.%C]
 // CHECK:STDOUT:   %.loc15_14: %C = converted %.loc15_12, <error> [concrete = <error>]
 // CHECK:STDOUT:   %.loc15_14: %C = converted %.loc15_12, <error> [concrete = <error>]
-// CHECK:STDOUT:   %addr: %ptr.d9e = addr_of <error> [concrete = <error>]
-// CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_todo_import_definition_multiple_data_members_value_param_type.carbon
 // CHECK:STDOUT: --- fail_todo_import_definition_multiple_data_members_value_param_type.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %C: type = class_type @C [concrete]
 // CHECK:STDOUT:   %C: type = class_type @C [concrete]
 // CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @As.Convert [concrete]
 // CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @As.Convert [concrete]
 // CHECK:STDOUT:   %empty_struct: %.c5d = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct: %.c5d = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %ptr.d9e: type = ptr_type %C [concrete]
-// CHECK:STDOUT:   %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
-// CHECK:STDOUT:   %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: imports {
@@ -692,11 +649,6 @@ fn F() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
 // CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}
 // CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct]
 // CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct]
-// CHECK:STDOUT:   %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] {
-// CHECK:STDOUT:     <elided>
-// CHECK:STDOUT:   } {
-// CHECK:STDOUT:     <elided>
-// CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: fn @F() {
@@ -707,8 +659,6 @@ fn F() {
 // CHECK:STDOUT:   %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%C.decl [concrete = constants.%C]
 // CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%C.decl [concrete = constants.%C]
 // CHECK:STDOUT:   %.loc15_14: %C = converted %.loc15_12, <error> [concrete = <error>]
 // CHECK:STDOUT:   %.loc15_14: %C = converted %.loc15_12, <error> [concrete = <error>]
-// CHECK:STDOUT:   %addr: %ptr.d9e = addr_of <error> [concrete = <error>]
-// CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:

+ 58 - 18
toolchain/check/testdata/interop/cpp/function/function.carbon

@@ -153,7 +153,10 @@ fn F() {
 template<typename T>
 template<typename T>
 auto foo(T a) -> void;
 auto foo(T a) -> void;
 
 
-// --- fail_todo_import_template_function.carbon
+template<typename T>
+auto bar(T a) -> T;
+
+// --- import_template_function.carbon
 
 
 library "[[@TEST_NAME]]";
 library "[[@TEST_NAME]]";
 
 
@@ -161,17 +164,16 @@ import Cpp library "template_function.h";
 
 
 fn F() {
 fn F() {
   //@dump-sem-ir-begin
   //@dump-sem-ir-begin
-  // CHECK:STDERR: fail_todo_import_template_function.carbon:[[@LINE+7]]:3: error: template function is not supported [CppTemplateFunctionNotSupported]
-  // CHECK:STDERR:   Cpp.foo(1 as i32);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_todo_import_template_function.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
-  // CHECK:STDERR:   Cpp.foo(1 as i32);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
   Cpp.foo(1 as i32);
   Cpp.foo(1 as i32);
   //@dump-sem-ir-end
   //@dump-sem-ir-end
 }
 }
 
 
+fn G() -> i32 {
+  //@dump-sem-ir-begin
+  return Cpp.bar(1 as i32);
+  //@dump-sem-ir-end
+}
+
 // TODO: Add a test per unsupported param type. See https://github.com/carbon-language/carbon-lang/pull/5477/files/4321e21ed27d987fd71be182d292973fd9849df8#r2094655176
 // TODO: Add a test per unsupported param type. See https://github.com/carbon-language/carbon-lang/pull/5477/files/4321e21ed27d987fd71be182d292973fd9849df8#r2094655176
 
 
 // TODO: Add a test per unsupported return type. See https://github.com/carbon-language/carbon-lang/pull/5477/files/4321e21ed27d987fd71be182d292973fd9849df8#r2094655176
 // TODO: Add a test per unsupported return type. See https://github.com/carbon-language/carbon-lang/pull/5477/files/4321e21ed27d987fd71be182d292973fd9849df8#r2094655176
@@ -308,11 +310,12 @@ fn F() {
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
-// CHECK:STDOUT: --- fail_todo_import_template_function.carbon
+// CHECK:STDOUT: --- import_template_function.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @As.Convert [concrete]
-// CHECK:STDOUT:   %empty_struct: %.c5d = struct_value () [concrete]
+// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
+// CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @Core.IntLiteral.as.As.impl.Convert [concrete]
+// CHECK:STDOUT:   %empty_struct.109: %.c5d = struct_value () [concrete]
 // CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]
 // CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]
@@ -330,32 +333,69 @@ fn F() {
 // CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.As.impl.Convert.414, @Core.IntLiteral.as.As.impl.Convert(%int_32) [concrete]
 // CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.As.impl.Convert.414, @Core.IntLiteral.as.As.impl.Convert(%int_32) [concrete]
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.As.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.As.impl.Convert.specific_fn [concrete]
 // CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]
 // CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]
+// CHECK:STDOUT:   %foo.type: type = fn_type @foo [concrete]
+// CHECK:STDOUT:   %foo: %foo.type = struct_value () [concrete]
+// CHECK:STDOUT:   %.414: type = cpp_overload_set_type @Int.as.As.impl.Convert [concrete]
+// CHECK:STDOUT:   %empty_struct.540: %.414 = struct_value () [concrete]
+// CHECK:STDOUT:   %bar.type: type = fn_type @bar [concrete]
+// CHECK:STDOUT:   %bar: %bar.type = struct_value () [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT:   %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
 // CHECK:STDOUT:   %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
 // CHECK:STDOUT:     .foo = %.a21
 // CHECK:STDOUT:     .foo = %.a21
+// CHECK:STDOUT:     .bar = %.146
 // CHECK:STDOUT:     import Cpp//...
 // CHECK:STDOUT:     import Cpp//...
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   }
-// CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct]
+// CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @Core.IntLiteral.as.As.impl.Convert [concrete = constants.%empty_struct.109]
 // CHECK:STDOUT:   %Core.import_ref.99c: @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert.type (%Core.IntLiteral.as.As.impl.Convert.type.565) = import_ref Core//prelude/parts/int, loc32_39, loaded [symbolic = @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert (constants.%Core.IntLiteral.as.As.impl.Convert.d2c)]
 // CHECK:STDOUT:   %Core.import_ref.99c: @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert.type (%Core.IntLiteral.as.As.impl.Convert.type.565) = import_ref Core//prelude/parts/int, loc32_39, loaded [symbolic = @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert (constants.%Core.IntLiteral.as.As.impl.Convert.d2c)]
 // CHECK:STDOUT:   %As.impl_witness_table.5ad = impl_witness_table (%Core.import_ref.99c), @Core.IntLiteral.as.As.impl [concrete]
 // CHECK:STDOUT:   %As.impl_witness_table.5ad = impl_witness_table (%Core.import_ref.99c), @Core.IntLiteral.as.As.impl [concrete]
+// CHECK:STDOUT:   %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   }
+// CHECK:STDOUT:   %.146: %.414 = cpp_overload_set_value @Int.as.As.impl.Convert [concrete = constants.%empty_struct.540]
+// CHECK:STDOUT:   %bar.decl: %bar.type = fn_decl @bar [concrete = constants.%bar] {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   } {
+// CHECK:STDOUT:     <elided>
+// CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT:   %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
-// CHECK:STDOUT:   %foo.ref: %.c5d = name_ref foo, imports.%.a21 [concrete = constants.%empty_struct]
+// CHECK:STDOUT:   %foo.ref: %.c5d = name_ref foo, imports.%.a21 [concrete = constants.%empty_struct.109]
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
 // CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
 // CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
 // CHECK:STDOUT:   %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
 // CHECK:STDOUT:   %impl.elem0: %.351 = impl_witness_access constants.%As.impl_witness.080, element0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.414]
 // CHECK:STDOUT:   %impl.elem0: %.351 = impl_witness_access constants.%As.impl_witness.080, element0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.414]
-// CHECK:STDOUT:   %bound_method.loc15_13.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bound]
+// CHECK:STDOUT:   %bound_method.loc8_13.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bound]
 // CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.As.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.specific_fn]
 // CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.As.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.specific_fn]
-// CHECK:STDOUT:   %bound_method.loc15_13.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]
-// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call: init %i32 = call %bound_method.loc15_13.2(%int_1) [concrete = constants.%int_1.5d2]
-// CHECK:STDOUT:   %.loc15_13.1: %i32 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_1.5d2]
-// CHECK:STDOUT:   %.loc15_13.2: %i32 = converted %int_1, %.loc15_13.1 [concrete = constants.%int_1.5d2]
+// CHECK:STDOUT:   %bound_method.loc8_13.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call: init %i32 = call %bound_method.loc8_13.2(%int_1) [concrete = constants.%int_1.5d2]
+// CHECK:STDOUT:   %.loc8_13.1: %i32 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_1.5d2]
+// CHECK:STDOUT:   %.loc8_13.2: %i32 = converted %int_1, %.loc8_13.1 [concrete = constants.%int_1.5d2]
+// CHECK:STDOUT:   %foo.call: init %empty_tuple.type = call imports.%foo.decl(%.loc8_13.2)
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
+// CHECK:STDOUT: fn @G() -> %i32 {
+// CHECK:STDOUT: !entry:
+// CHECK:STDOUT:   %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
+// CHECK:STDOUT:   %bar.ref: %.414 = name_ref bar, imports.%.146 [concrete = constants.%empty_struct.540]
+// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
+// CHECK:STDOUT:   %int_32.loc14: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
+// CHECK:STDOUT:   %i32.loc14: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
+// CHECK:STDOUT:   %impl.elem0: %.351 = impl_witness_access constants.%As.impl_witness.080, element0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.414]
+// CHECK:STDOUT:   %bound_method.loc14_20.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bound]
+// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.As.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.specific_fn]
+// CHECK:STDOUT:   %bound_method.loc14_20.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]
+// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call: init %i32 = call %bound_method.loc14_20.2(%int_1) [concrete = constants.%int_1.5d2]
+// CHECK:STDOUT:   %.loc14_20.1: %i32 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_1.5d2]
+// CHECK:STDOUT:   %.loc14_20.2: %i32 = converted %int_1, %.loc14_20.1 [concrete = constants.%int_1.5d2]
+// CHECK:STDOUT:   %bar.call: init %i32 = call imports.%bar.decl(%.loc14_20.2)
+// CHECK:STDOUT:   return %bar.call to %return
+// CHECK:STDOUT: }
+// CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/interop/cpp/function/overloads.carbon

@@ -183,9 +183,9 @@ library "[[@TEST_NAME]]";
 import Cpp library "struct_literal_call_arg.h";
 import Cpp library "struct_literal_call_arg.h";
 
 
 fn F() {
 fn F() {
-  // CHECK:STDERR: fail_todo_import_struct_literal_call_arg.carbon:[[@LINE+7]]:3: error: call argument of type `{}` is not supported [CppCallArgTypeNotSupported]
+  // CHECK:STDERR: fail_todo_import_struct_literal_call_arg.carbon:[[@LINE+7]]:11: error: call argument of type `{}` is not supported [CppCallArgTypeNotSupported]
   // CHECK:STDERR:   Cpp.foo({});
   // CHECK:STDERR:   Cpp.foo({});
-  // CHECK:STDERR:   ^~~~~~~~~~~
+  // CHECK:STDERR:           ^~
   // CHECK:STDERR: fail_todo_import_struct_literal_call_arg.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
   // CHECK:STDERR: fail_todo_import_struct_literal_call_arg.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
   // CHECK:STDERR:   Cpp.foo({});
   // CHECK:STDERR:   Cpp.foo({});
   // CHECK:STDERR:   ^~~~~~~~~~~
   // CHECK:STDERR:   ^~~~~~~~~~~

+ 4 - 54
toolchain/check/testdata/interop/cpp/function/struct.carbon

@@ -27,7 +27,7 @@ library "[[@TEST_NAME]]";
 import Cpp library "decl_value_param_type.h";
 import Cpp library "decl_value_param_type.h";
 
 
 fn F() {
 fn F() {
-  // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE+15]]:11: error: invalid use of incomplete type `Cpp.S` [IncompleteTypeInConversion]
+  // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE+8]]:11: error: invalid use of incomplete type `Cpp.S` [IncompleteTypeInConversion]
   // CHECK:STDERR:   Cpp.foo({} as Cpp.S);
   // CHECK:STDERR:   Cpp.foo({} as Cpp.S);
   // CHECK:STDERR:           ^~~~~~~~~~~
   // CHECK:STDERR:           ^~~~~~~~~~~
   // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE-6]]:10: in file included here [InCppInclude]
   // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE-6]]:10: in file included here [InCppInclude]
@@ -35,13 +35,6 @@ fn F() {
   // CHECK:STDERR: struct S;
   // CHECK:STDERR: struct S;
   // CHECK:STDERR:        ^
   // CHECK:STDERR:        ^
   // CHECK:STDERR:
   // CHECK:STDERR:
-  // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE+7]]:3: error: call argument of type `<error>` is not supported [CppCallArgTypeNotSupported]
-  // CHECK:STDERR:   Cpp.foo({} as Cpp.S);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
-  // CHECK:STDERR:   Cpp.foo({} as Cpp.S);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
   Cpp.foo({} as Cpp.S);
   Cpp.foo({} as Cpp.S);
 }
 }
 
 
@@ -65,13 +58,6 @@ fn F() {
   // CHECK:STDERR:               ^
   // CHECK:STDERR:               ^
   // CHECK:STDERR:
   // CHECK:STDERR:
   let s: Cpp.S;
   let s: Cpp.S;
-  // CHECK:STDERR: fail_import_decl_value_param_type_previously_imported.carbon:[[@LINE+7]]:3: error: call argument of type `<error>` is not supported [CppCallArgTypeNotSupported]
-  // CHECK:STDERR:   Cpp.foo(s);
-  // CHECK:STDERR:   ^~~~~~~~~~
-  // CHECK:STDERR: fail_import_decl_value_param_type_previously_imported.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
-  // CHECK:STDERR:   Cpp.foo(s);
-  // CHECK:STDERR:   ^~~~~~~~~~
-  // CHECK:STDERR:
   Cpp.foo(s);
   Cpp.foo(s);
 }
 }
 
 
@@ -93,7 +79,7 @@ library "[[@TEST_NAME]]";
 import Cpp library "double_decl_value_param_type.h";
 import Cpp library "double_decl_value_param_type.h";
 
 
 fn F() {
 fn F() {
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+15]]:12: error: invalid use of incomplete type `Cpp.S` [IncompleteTypeInConversion]
+  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+8]]:12: error: invalid use of incomplete type `Cpp.S` [IncompleteTypeInConversion]
   // CHECK:STDERR:   Cpp.foo1({} as Cpp.S);
   // CHECK:STDERR:   Cpp.foo1({} as Cpp.S);
   // CHECK:STDERR:            ^~~~~~~~~~~
   // CHECK:STDERR:            ^~~~~~~~~~~
   // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE-6]]:10: in file included here [InCppInclude]
   // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE-6]]:10: in file included here [InCppInclude]
@@ -101,29 +87,15 @@ fn F() {
   // CHECK:STDERR: struct S;
   // CHECK:STDERR: struct S;
   // CHECK:STDERR:        ^
   // CHECK:STDERR:        ^
   // CHECK:STDERR:
   // CHECK:STDERR:
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+7]]:3: error: call argument of type `<error>` is not supported [CppCallArgTypeNotSupported]
-  // CHECK:STDERR:   Cpp.foo1({} as Cpp.S);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
-  // CHECK:STDERR:   Cpp.foo1({} as Cpp.S);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
   Cpp.foo1({} as Cpp.S);
   Cpp.foo1({} as Cpp.S);
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+15]]:12: error: invalid use of incomplete type `Cpp.S` [IncompleteTypeInConversion]
+  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+8]]:12: error: invalid use of incomplete type `Cpp.S` [IncompleteTypeInConversion]
   // CHECK:STDERR:   Cpp.foo2({} as Cpp.S);
   // CHECK:STDERR:   Cpp.foo2({} as Cpp.S);
   // CHECK:STDERR:            ^~~~~~~~~~~
   // CHECK:STDERR:            ^~~~~~~~~~~
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE-22]]:10: in file included here [InCppInclude]
+  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE-15]]:10: in file included here [InCppInclude]
   // CHECK:STDERR: ./double_decl_value_param_type.h:2:8: note: class was forward declared here [ClassForwardDeclaredHere]
   // CHECK:STDERR: ./double_decl_value_param_type.h:2:8: note: class was forward declared here [ClassForwardDeclaredHere]
   // CHECK:STDERR: struct S;
   // CHECK:STDERR: struct S;
   // CHECK:STDERR:        ^
   // CHECK:STDERR:        ^
   // CHECK:STDERR:
   // CHECK:STDERR:
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+7]]:3: error: call argument of type `<error>` is not supported [CppCallArgTypeNotSupported]
-  // CHECK:STDERR:   Cpp.foo2({} as Cpp.S);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
-  // CHECK:STDERR:   Cpp.foo2({} as Cpp.S);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
   Cpp.foo2({} as Cpp.S);
   Cpp.foo2({} as Cpp.S);
 }
 }
 
 
@@ -632,14 +604,10 @@ fn F() {
 // CHECK:STDOUT: --- fail_todo_import_definition_single_data_member_value_param_type.carbon
 // CHECK:STDOUT: --- fail_todo_import_definition_single_data_member_value_param_type.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %S: type = class_type @S [concrete]
 // CHECK:STDOUT:   %S: type = class_type @S [concrete]
 // CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @As.Convert [concrete]
 // CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @As.Convert [concrete]
 // CHECK:STDOUT:   %empty_struct: %.c5d = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct: %.c5d = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %ptr.5c7: type = ptr_type %S [concrete]
-// CHECK:STDOUT:   %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
-// CHECK:STDOUT:   %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: imports {
@@ -650,11 +618,6 @@ fn F() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %S.decl: type = class_decl @S [concrete = constants.%S] {} {}
 // CHECK:STDOUT:   %S.decl: type = class_decl @S [concrete = constants.%S] {} {}
 // CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct]
 // CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct]
-// CHECK:STDOUT:   %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] {
-// CHECK:STDOUT:     <elided>
-// CHECK:STDOUT:   } {
-// CHECK:STDOUT:     <elided>
-// CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: fn @F() {
@@ -665,22 +628,16 @@ fn F() {
 // CHECK:STDOUT:   %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S]
 // CHECK:STDOUT:   %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S]
 // CHECK:STDOUT:   %.loc15_14: %S = converted %.loc15_12, <error> [concrete = <error>]
 // CHECK:STDOUT:   %.loc15_14: %S = converted %.loc15_12, <error> [concrete = <error>]
-// CHECK:STDOUT:   %addr: %ptr.5c7 = addr_of <error> [concrete = <error>]
-// CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_todo_import_definition_multiple_data_members_value_param_type.carbon
 // CHECK:STDOUT: --- fail_todo_import_definition_multiple_data_members_value_param_type.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %S: type = class_type @S [concrete]
 // CHECK:STDOUT:   %S: type = class_type @S [concrete]
 // CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @As.Convert [concrete]
 // CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @As.Convert [concrete]
 // CHECK:STDOUT:   %empty_struct: %.c5d = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct: %.c5d = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %ptr.5c7: type = ptr_type %S [concrete]
-// CHECK:STDOUT:   %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
-// CHECK:STDOUT:   %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: imports {
@@ -691,11 +648,6 @@ fn F() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %S.decl: type = class_decl @S [concrete = constants.%S] {} {}
 // CHECK:STDOUT:   %S.decl: type = class_decl @S [concrete = constants.%S] {} {}
 // CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct]
 // CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct]
-// CHECK:STDOUT:   %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] {
-// CHECK:STDOUT:     <elided>
-// CHECK:STDOUT:   } {
-// CHECK:STDOUT:     <elided>
-// CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: fn @F() {
@@ -706,8 +658,6 @@ fn F() {
 // CHECK:STDOUT:   %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S]
 // CHECK:STDOUT:   %S.ref: type = name_ref S, imports.%S.decl [concrete = constants.%S]
 // CHECK:STDOUT:   %.loc15_14: %S = converted %.loc15_12, <error> [concrete = <error>]
 // CHECK:STDOUT:   %.loc15_14: %S = converted %.loc15_12, <error> [concrete = <error>]
-// CHECK:STDOUT:   %addr: %ptr.5c7 = addr_of <error> [concrete = <error>]
-// CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:

+ 7 - 57
toolchain/check/testdata/interop/cpp/function/union.carbon

@@ -28,7 +28,7 @@ import Cpp library "decl_value_param_type.h";
 
 
 fn F() {
 fn F() {
   //@dump-sem-ir-begin
   //@dump-sem-ir-begin
-  // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE+15]]:11: error: invalid use of incomplete type `Cpp.U` [IncompleteTypeInConversion]
+  // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE+8]]:11: error: invalid use of incomplete type `Cpp.U` [IncompleteTypeInConversion]
   // CHECK:STDERR:   Cpp.foo({} as Cpp.U);
   // CHECK:STDERR:   Cpp.foo({} as Cpp.U);
   // CHECK:STDERR:           ^~~~~~~~~~~
   // CHECK:STDERR:           ^~~~~~~~~~~
   // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE-7]]:10: in file included here [InCppInclude]
   // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE-7]]:10: in file included here [InCppInclude]
@@ -36,13 +36,6 @@ fn F() {
   // CHECK:STDERR: union U;
   // CHECK:STDERR: union U;
   // CHECK:STDERR:       ^
   // CHECK:STDERR:       ^
   // CHECK:STDERR:
   // CHECK:STDERR:
-  // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE+7]]:3: error: call argument of type `<error>` is not supported [CppCallArgTypeNotSupported]
-  // CHECK:STDERR:   Cpp.foo({} as Cpp.U);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_import_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
-  // CHECK:STDERR:   Cpp.foo({} as Cpp.U);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
   Cpp.foo({} as Cpp.U);
   Cpp.foo({} as Cpp.U);
   //@dump-sem-ir-end
   //@dump-sem-ir-end
 }
 }
@@ -67,13 +60,6 @@ fn F() {
   // CHECK:STDERR:               ^
   // CHECK:STDERR:               ^
   // CHECK:STDERR:
   // CHECK:STDERR:
   let u: Cpp.U;
   let u: Cpp.U;
-  // CHECK:STDERR: fail_import_decl_value_param_type_previously_imported.carbon:[[@LINE+7]]:3: error: call argument of type `<error>` is not supported [CppCallArgTypeNotSupported]
-  // CHECK:STDERR:   Cpp.foo(u);
-  // CHECK:STDERR:   ^~~~~~~~~~
-  // CHECK:STDERR: fail_import_decl_value_param_type_previously_imported.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
-  // CHECK:STDERR:   Cpp.foo(u);
-  // CHECK:STDERR:   ^~~~~~~~~~
-  // CHECK:STDERR:
   Cpp.foo(u);
   Cpp.foo(u);
 }
 }
 
 
@@ -95,7 +81,7 @@ library "[[@TEST_NAME]]";
 import Cpp library "double_decl_value_param_type.h";
 import Cpp library "double_decl_value_param_type.h";
 
 
 fn F() {
 fn F() {
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+15]]:12: error: invalid use of incomplete type `Cpp.U` [IncompleteTypeInConversion]
+  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+8]]:12: error: invalid use of incomplete type `Cpp.U` [IncompleteTypeInConversion]
   // CHECK:STDERR:   Cpp.foo1({} as Cpp.U);
   // CHECK:STDERR:   Cpp.foo1({} as Cpp.U);
   // CHECK:STDERR:            ^~~~~~~~~~~
   // CHECK:STDERR:            ^~~~~~~~~~~
   // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE-6]]:10: in file included here [InCppInclude]
   // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE-6]]:10: in file included here [InCppInclude]
@@ -103,29 +89,15 @@ fn F() {
   // CHECK:STDERR: union U;
   // CHECK:STDERR: union U;
   // CHECK:STDERR:       ^
   // CHECK:STDERR:       ^
   // CHECK:STDERR:
   // CHECK:STDERR:
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+7]]:3: error: call argument of type `<error>` is not supported [CppCallArgTypeNotSupported]
-  // CHECK:STDERR:   Cpp.foo1({} as Cpp.U);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
-  // CHECK:STDERR:   Cpp.foo1({} as Cpp.U);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
   Cpp.foo1({} as Cpp.U);
   Cpp.foo1({} as Cpp.U);
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+15]]:12: error: invalid use of incomplete type `Cpp.U` [IncompleteTypeInConversion]
+  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+8]]:12: error: invalid use of incomplete type `Cpp.U` [IncompleteTypeInConversion]
   // CHECK:STDERR:   Cpp.foo2({} as Cpp.U);
   // CHECK:STDERR:   Cpp.foo2({} as Cpp.U);
   // CHECK:STDERR:            ^~~~~~~~~~~
   // CHECK:STDERR:            ^~~~~~~~~~~
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE-22]]:10: in file included here [InCppInclude]
+  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE-15]]:10: in file included here [InCppInclude]
   // CHECK:STDERR: ./double_decl_value_param_type.h:2:7: note: class was forward declared here [ClassForwardDeclaredHere]
   // CHECK:STDERR: ./double_decl_value_param_type.h:2:7: note: class was forward declared here [ClassForwardDeclaredHere]
   // CHECK:STDERR: union U;
   // CHECK:STDERR: union U;
   // CHECK:STDERR:       ^
   // CHECK:STDERR:       ^
   // CHECK:STDERR:
   // CHECK:STDERR:
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+7]]:3: error: call argument of type `<error>` is not supported [CppCallArgTypeNotSupported]
-  // CHECK:STDERR:   Cpp.foo2({} as Cpp.U);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR: fail_import_double_decl_value_param_type.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
-  // CHECK:STDERR:   Cpp.foo2({} as Cpp.U);
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~
-  // CHECK:STDERR:
   Cpp.foo2({} as Cpp.U);
   Cpp.foo2({} as Cpp.U);
 }
 }
 
 
@@ -506,10 +478,10 @@ fn F() {
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: !entry:
 // CHECK:STDOUT: !entry:
-// CHECK:STDOUT:   %Cpp.ref.loc23_3: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
+// CHECK:STDOUT:   %Cpp.ref.loc16_3: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %foo.ref: %.c5d = name_ref foo, imports.%.a21 [concrete = constants.%empty_struct]
 // CHECK:STDOUT:   %foo.ref: %.c5d = name_ref foo, imports.%.a21 [concrete = constants.%empty_struct]
-// CHECK:STDOUT:   %.loc23: %empty_struct_type = struct_literal ()
-// CHECK:STDOUT:   %Cpp.ref.loc23_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
+// CHECK:STDOUT:   %.loc16: %empty_struct_type = struct_literal ()
+// CHECK:STDOUT:   %Cpp.ref.loc16_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %U.ref: type = name_ref U, imports.%U.decl [concrete = constants.%U]
 // CHECK:STDOUT:   %U.ref: type = name_ref U, imports.%U.decl [concrete = constants.%U]
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
@@ -571,14 +543,10 @@ fn F() {
 // CHECK:STDOUT: --- fail_import_definition_single_data_member_value_param_type.carbon
 // CHECK:STDOUT: --- fail_import_definition_single_data_member_value_param_type.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %U: type = class_type @U [concrete]
 // CHECK:STDOUT:   %U: type = class_type @U [concrete]
 // CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @As.Convert [concrete]
 // CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @As.Convert [concrete]
 // CHECK:STDOUT:   %empty_struct: %.c5d = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct: %.c5d = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %ptr.86f: type = ptr_type %U [concrete]
-// CHECK:STDOUT:   %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
-// CHECK:STDOUT:   %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: imports {
@@ -589,11 +557,6 @@ fn F() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %U.decl: type = class_decl @U [concrete = constants.%U] {} {}
 // CHECK:STDOUT:   %U.decl: type = class_decl @U [concrete = constants.%U] {} {}
 // CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct]
 // CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct]
-// CHECK:STDOUT:   %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] {
-// CHECK:STDOUT:     <elided>
-// CHECK:STDOUT:   } {
-// CHECK:STDOUT:     <elided>
-// CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: fn @F() {
@@ -604,22 +567,16 @@ fn F() {
 // CHECK:STDOUT:   %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %U.ref: type = name_ref U, imports.%U.decl [concrete = constants.%U]
 // CHECK:STDOUT:   %U.ref: type = name_ref U, imports.%U.decl [concrete = constants.%U]
 // CHECK:STDOUT:   %.loc15_14: %U = converted %.loc15_12, <error> [concrete = <error>]
 // CHECK:STDOUT:   %.loc15_14: %U = converted %.loc15_12, <error> [concrete = <error>]
-// CHECK:STDOUT:   %addr: %ptr.86f = addr_of <error> [concrete = <error>]
-// CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: --- fail_import_definition_multiple_data_members_value_param_type.carbon
 // CHECK:STDOUT: --- fail_import_definition_multiple_data_members_value_param_type.carbon
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: constants {
 // CHECK:STDOUT: constants {
-// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]
 // CHECK:STDOUT:   %U: type = class_type @U [concrete]
 // CHECK:STDOUT:   %U: type = class_type @U [concrete]
 // CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @As.Convert [concrete]
 // CHECK:STDOUT:   %.c5d: type = cpp_overload_set_type @As.Convert [concrete]
 // CHECK:STDOUT:   %empty_struct: %.c5d = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct: %.c5d = struct_value () [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
 // CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]
-// CHECK:STDOUT:   %ptr.86f: type = ptr_type %U [concrete]
-// CHECK:STDOUT:   %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
-// CHECK:STDOUT:   %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: imports {
 // CHECK:STDOUT: imports {
@@ -630,11 +587,6 @@ fn F() {
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   }
 // CHECK:STDOUT:   %U.decl: type = class_decl @U [concrete = constants.%U] {} {}
 // CHECK:STDOUT:   %U.decl: type = class_decl @U [concrete = constants.%U] {} {}
 // CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct]
 // CHECK:STDOUT:   %.a21: %.c5d = cpp_overload_set_value @As.Convert [concrete = constants.%empty_struct]
-// CHECK:STDOUT:   %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] {
-// CHECK:STDOUT:     <elided>
-// CHECK:STDOUT:   } {
-// CHECK:STDOUT:     <elided>
-// CHECK:STDOUT:   }
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:
 // CHECK:STDOUT: fn @F() {
 // CHECK:STDOUT: fn @F() {
@@ -645,8 +597,6 @@ fn F() {
 // CHECK:STDOUT:   %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %Cpp.ref.loc15_17: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
 // CHECK:STDOUT:   %U.ref: type = name_ref U, imports.%U.decl [concrete = constants.%U]
 // CHECK:STDOUT:   %U.ref: type = name_ref U, imports.%U.decl [concrete = constants.%U]
 // CHECK:STDOUT:   %.loc15_14: %U = converted %.loc15_12, <error> [concrete = <error>]
 // CHECK:STDOUT:   %.loc15_14: %U = converted %.loc15_12, <error> [concrete = <error>]
-// CHECK:STDOUT:   %addr: %ptr.86f = addr_of <error> [concrete = <error>]
-// CHECK:STDOUT:   %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr)
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT:   <elided>
 // CHECK:STDOUT: }
 // CHECK:STDOUT: }
 // CHECK:STDOUT:
 // CHECK:STDOUT:

+ 2 - 2
toolchain/check/testdata/interop/cpp/stdlib/string_view.carbon

@@ -46,9 +46,9 @@ import Cpp library "string_view.h";
 
 
 //@dump-sem-ir-begin
 //@dump-sem-ir-begin
 fn F() {
 fn F() {
-  // CHECK:STDERR: fail_todo_5891_import_multiple.carbon:[[@LINE+7]]:3: error: call argument of type `str` is not supported [CppCallArgTypeNotSupported]
+  // CHECK:STDERR: fail_todo_5891_import_multiple.carbon:[[@LINE+7]]:15: error: call argument of type `str` is not supported [CppCallArgTypeNotSupported]
   // CHECK:STDERR:   Cpp.Consume("hello");
   // CHECK:STDERR:   Cpp.Consume("hello");
-  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~
+  // CHECK:STDERR:               ^~~~~~~
   // CHECK:STDERR: fail_todo_5891_import_multiple.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
   // CHECK:STDERR: fail_todo_5891_import_multiple.carbon:[[@LINE+4]]:3: note: in call to Cpp function here [InCallToCppFunction]
   // CHECK:STDERR:   Cpp.Consume("hello");
   // CHECK:STDERR:   Cpp.Consume("hello");
   // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~
   // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~

+ 0 - 1
toolchain/diagnostics/diagnostic_kind.def

@@ -246,7 +246,6 @@ CARBON_DIAGNOSTIC_KIND(CppCallArgTypeNotSupported)
 CARBON_DIAGNOSTIC_KIND(CppOverloadingAmbiguousCandidatesFound)
 CARBON_DIAGNOSTIC_KIND(CppOverloadingAmbiguousCandidatesFound)
 CARBON_DIAGNOSTIC_KIND(CppOverloadingDeletedFunctionFound)
 CARBON_DIAGNOSTIC_KIND(CppOverloadingDeletedFunctionFound)
 CARBON_DIAGNOSTIC_KIND(CppOverloadingNoViableFunctionFound)
 CARBON_DIAGNOSTIC_KIND(CppOverloadingNoViableFunctionFound)
-CARBON_DIAGNOSTIC_KIND(CppTemplateFunctionNotSupported)
 CARBON_DIAGNOSTIC_KIND(GenericParamMustBeConstant)
 CARBON_DIAGNOSTIC_KIND(GenericParamMustBeConstant)
 CARBON_DIAGNOSTIC_KIND(ImplictParamMustBeConstant)
 CARBON_DIAGNOSTIC_KIND(ImplictParamMustBeConstant)
 CARBON_DIAGNOSTIC_KIND(IncompleteReturnTypeHere)
 CARBON_DIAGNOSTIC_KIND(IncompleteReturnTypeHere)