Skip to content

Commit cac3578

Browse files
authored
Avoid crashing when importing a C++ struct indirectly (#6086)
Return an error constant id instead and output a TODO. Part of #6060.
1 parent 02ea39f commit cac3578

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

toolchain/check/import_ref.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,9 @@ class ImportRefResolver : public ImportContext {
447447

448448
// Step 1: check for a constant value.
449449
auto existing = FindResolvedConstId(work.inst_id);
450+
if (existing.const_id == SemIR::ErrorInst::ConstantId) {
451+
return existing.const_id;
452+
}
450453
if (existing.const_id.has_value() && !work.retry_with_constant_value) {
451454
work_stack_.pop_back();
452455
continue;
@@ -583,6 +586,11 @@ class ImportRefResolver : public ImportContext {
583586
return result;
584587
}
585588
auto ir_inst = cursor_ir->import_ir_insts().Get(import_ir_inst_id);
589+
if (ir_inst.ir_id() == SemIR::ImportIRId::Cpp) {
590+
local_context().TODO(SemIR::LocId::None,
591+
"Unsupported: Importing C++ indirectly");
592+
return {.const_id = SemIR::ErrorInst::ConstantId};
593+
}
586594

587595
const auto* prev_ir = cursor_ir;
588596
auto prev_inst_id = cursor_inst_id;

toolchain/check/testdata/interop/cpp/import.carbon

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,37 @@ fn F() {
4646
//@dump-sem-ir-end
4747
}
4848

49+
// ============================================================================
50+
// Import C++ struct indirectly
51+
// ============================================================================
52+
53+
// --- struct.h
54+
55+
struct MyStruct { void Foo(); };
56+
57+
// --- struct_api.carbon
58+
59+
library "[[@TEST_NAME]]";
60+
61+
import Cpp library "struct.h";
62+
63+
alias MyStructAlias = Cpp.MyStruct;
64+
65+
// --- fail_todo_import_struct_api.carbon
66+
// CHECK:STDERR: fail_todo_import_struct_api.carbon: error: semantics TODO: `Unsupported: Importing C++ indirectly` [SemanticsTodo]
67+
// CHECK:STDERR:
68+
69+
library "[[@TEST_NAME]]";
70+
71+
import library "struct_api";
72+
73+
fn F() {
74+
//@dump-sem-ir-begin
75+
var x: MyStructAlias;
76+
x.Foo();
77+
//@dump-sem-ir-end
78+
}
79+
4980
// ============================================================================
5081
// Import C++ function indirectly
5182
// ============================================================================
@@ -101,6 +132,29 @@ fn F() {
101132
// CHECK:STDOUT: <elided>
102133
// CHECK:STDOUT: }
103134
// CHECK:STDOUT:
135+
// CHECK:STDOUT: --- fail_todo_import_struct_api.carbon
136+
// CHECK:STDOUT:
137+
// CHECK:STDOUT: constants {
138+
// CHECK:STDOUT: }
139+
// CHECK:STDOUT:
140+
// CHECK:STDOUT: imports {
141+
// CHECK:STDOUT: %Main.MyStructAlias: type = import_ref Main//struct_api, MyStructAlias, loaded [concrete = <error>]
142+
// CHECK:STDOUT: }
143+
// CHECK:STDOUT:
144+
// CHECK:STDOUT: fn @F() {
145+
// CHECK:STDOUT: !entry:
146+
// CHECK:STDOUT: name_binding_decl {
147+
// CHECK:STDOUT: %x.patt: <error> = binding_pattern x [concrete]
148+
// CHECK:STDOUT: %x.var_patt: <error> = var_pattern %x.patt [concrete]
149+
// CHECK:STDOUT: }
150+
// CHECK:STDOUT: %x.var: ref <error> = var %x.var_patt [concrete = <error>]
151+
// CHECK:STDOUT: %MyStructAlias.ref: type = name_ref MyStructAlias, imports.%Main.MyStructAlias [concrete = <error>]
152+
// CHECK:STDOUT: %x: <error> = bind_name x, <error> [concrete = <error>]
153+
// CHECK:STDOUT: %x.ref: <error> = name_ref x, %x [concrete = <error>]
154+
// CHECK:STDOUT: %Foo.ref: <error> = name_ref Foo, <error> [concrete = <error>]
155+
// CHECK:STDOUT: <elided>
156+
// CHECK:STDOUT: }
157+
// CHECK:STDOUT:
104158
// CHECK:STDOUT: --- fail_todo_import_function_api.carbon
105159
// CHECK:STDOUT:
106160
// CHECK:STDOUT: constants {

0 commit comments

Comments
 (0)