diff --git a/toolchain/check/cpp/impl_lookup.cpp b/toolchain/check/cpp/impl_lookup.cpp index 05249902c9e0..cf077a94d81b 100644 --- a/toolchain/check/cpp/impl_lookup.cpp +++ b/toolchain/check/cpp/impl_lookup.cpp @@ -15,6 +15,7 @@ #include "toolchain/check/import_ref.h" #include "toolchain/check/inst.h" #include "toolchain/check/type.h" +#include "toolchain/check/type_completion.h" #include "toolchain/sem_ir/builtin_function_kind.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/typed_insts.h" @@ -113,6 +114,17 @@ static auto BuildCopyWitness( return SemIR::InstId::None; } if (auto* class_decl = dyn_cast(tag_decl)) { + auto class_type_id = SemIR::TypeId::ForTypeConstant(query_self_const_id); + if (!Check::RequireCompleteType( + context, class_type_id, SemIR::LocId::None, [&](auto& builder) { + CARBON_DIAGNOSTIC(IncompleteTypeInCopyWitness, Context, + "argument to C++ call has incomplete type {0}", + SemIR::TypeId); + builder.Context(loc_id, IncompleteTypeInCopyWitness, + class_type_id); + })) { + return SemIR::ErrorInst::InstId; + } auto decl_info = DeclInfo{.decl = clang_sema.LookupCopyingConstructor( class_decl, clang::Qualifiers::Const), .signature = {.num_params = 1}}; diff --git a/toolchain/check/testdata/interop/cpp/class/import/class.carbon b/toolchain/check/testdata/interop/cpp/class/import/class.carbon index 213b3d18976e..70d4b5ca136c 100644 --- a/toolchain/check/testdata/interop/cpp/class/import/class.carbon +++ b/toolchain/check/testdata/interop/cpp/class/import/class.carbon @@ -224,6 +224,34 @@ import Cpp library "template.h"; fn MyF(bar: Cpp.Bar(Cpp.X)*); //@dump-sem-ir-end +// --- fail_copy_witness_of_incomplete_class.carbon + +library "[[@TEST_NAME]]"; + +import Cpp inline ''' +class Class1; +'''; + +class Generic(x:! Core.Copy) { +} + +// CHECK:STDERR: fail_copy_witness_of_incomplete_class.carbon:[[@LINE+14]]:19: error: argument to C++ call has incomplete type `Cpp.Class1` [IncompleteTypeInCopyWitness] +// CHECK:STDERR: fn GenericUse(p2: Generic(Cpp.Class1)) { +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_copy_witness_of_incomplete_class.carbon:[[@LINE-9]]:7: note: class was forward declared here [ClassForwardDeclaredHere] +// CHECK:STDERR: class Class1; +// CHECK:STDERR: ^ +// CHECK:STDERR: fail_copy_witness_of_incomplete_class.carbon:[[@LINE-9]]:15: note: initializing generic parameter `x` declared here [InitializingGenericParam] +// CHECK:STDERR: class Generic(x:! Core.Copy) { +// CHECK:STDERR: ^~~~~~~~~~~~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_copy_witness_of_incomplete_class.carbon:[[@LINE+4]]:15: warning: binding `p2` unused [UnusedBinding] +// CHECK:STDERR: fn GenericUse(p2: Generic(Cpp.Class1)) { +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +fn GenericUse(p2: Generic(Cpp.Class1)) { +} + // CHECK:STDOUT: --- import_declaration.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/diagnostics/kind.def b/toolchain/diagnostics/kind.def index a2c3f7afd750..b84348090e32 100644 --- a/toolchain/diagnostics/kind.def +++ b/toolchain/diagnostics/kind.def @@ -454,6 +454,7 @@ CARBON_DIAGNOSTIC_KIND(IncompleteTypeInAdaptDecl) CARBON_DIAGNOSTIC_KIND(IncompleteTypeInBaseDecl) CARBON_DIAGNOSTIC_KIND(IncompleteTypeInBindingDecl) CARBON_DIAGNOSTIC_KIND(IncompleteTypeInConversion) +CARBON_DIAGNOSTIC_KIND(IncompleteTypeInCopyWitness) CARBON_DIAGNOSTIC_KIND(IncompleteTypeInFieldDecl) CARBON_DIAGNOSTIC_KIND(IncompleteTypeInFunctionParam) CARBON_DIAGNOSTIC_KIND(IncompleteTypeInFunctionReturnType)