瀏覽代碼

Require imported C++ types to be complete before creating a Core.Copy witness (#7112)

Fixes a crash that would occur due to `scope_id` of the class being
unset.

Relands #7106 that was reverted by #7103 due to a github infrastructure
bug.

Co-authored-by: David Blaikie <dblaikie@gmail.com>
Richard Smith 1 周之前
父節點
當前提交
2a059366a7

+ 12 - 0
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<clang::CXXRecordDecl>(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}};

+ 28 - 0
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 {

+ 1 - 0
toolchain/diagnostics/kind.def

@@ -455,6 +455,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)