From b2b0b4a73fffcf26cba4bef97e72878b1291d4df Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 13 Aug 2025 15:07:54 -0700 Subject: [PATCH] Improve recovery from bad type imports. (#5953) The main change here is that a bad type appearing somewhere within a field or base class of a class shouldn't cause an import of that class to fail. Instead, only that field or base class becomes inaccessible from Carbon. Also improve the way that type importing errors are diagnosed. While we lose the precision of a diagnostic saying why a type is not supported, we gain a useful source location for where the type was mentioned in C++ code. --------- Co-authored-by: Jon Ross-Perkins --- toolchain/check/import_cpp.cpp | 44 +++++---- .../testdata/interop/cpp/class/class.carbon | 42 ++++----- .../testdata/interop/cpp/class/field.carbon | 90 +++++++++++++++---- .../testdata/interop/cpp/class/method.carbon | 11 +-- .../testdata/interop/cpp/class/struct.carbon | 42 ++++----- .../testdata/interop/cpp/class/union.carbon | 42 ++++----- .../interop/cpp/function/pointer.carbon | 14 +-- .../interop/cpp/unsupported_decl_type.carbon | 13 ++- .../testdata/interop/cpp/fail_extern_c.carbon | 13 ++- 9 files changed, 165 insertions(+), 146 deletions(-) diff --git a/toolchain/check/import_cpp.cpp b/toolchain/check/import_cpp.cpp index 8874e5075f62..ce11c7eb3b3e 100644 --- a/toolchain/check/import_cpp.cpp +++ b/toolchain/check/import_cpp.cpp @@ -1125,9 +1125,8 @@ static auto MapNonWrapperType(Context& context, SemIR::LocId loc_id, } // Maps a qualified C++ type to a Carbon type. -static auto MapQualifiedType(Context& context, SemIR::LocId loc_id, - clang::QualType type, TypeExpr type_expr) - -> TypeExpr { +static auto MapQualifiedType(Context& context, clang::QualType type, + TypeExpr type_expr) -> TypeExpr { auto quals = type.getQualifiers(); if (quals.hasConst()) { @@ -1139,28 +1138,22 @@ static auto MapQualifiedType(Context& context, SemIR::LocId loc_id, // TODO: Support other qualifiers. if (!quals.empty()) { - context.TODO(loc_id, llvm::formatv("Unsupported: qualified type: {0}", - type.getAsString())); - return {.inst_id = SemIR::ErrorInst::TypeInstId, - .type_id = SemIR::ErrorInst::TypeId}; + return {.inst_id = SemIR::TypeInstId::None, .type_id = SemIR::TypeId::None}; } return type_expr; } // Maps a C++ pointer type to a Carbon pointer type. -static auto MapPointerType(Context& context, SemIR::LocId loc_id, - clang::QualType type, TypeExpr pointee_type_expr) - -> TypeExpr { +static auto MapPointerType(Context& context, clang::QualType type, + TypeExpr pointee_type_expr) -> TypeExpr { CARBON_CHECK(type->isPointerType()); if (auto nullability = type->getNullability(); !nullability.has_value() || *nullability != clang::NullabilityKind::NonNull) { - context.TODO(loc_id, llvm::formatv("Unsupported: nullable pointer: {0}", - type.getAsString())); - return {.inst_id = SemIR::ErrorInst::TypeInstId, - .type_id = SemIR::ErrorInst::TypeId}; + // TODO: Support nullable pointers. + return {.inst_id = SemIR::TypeInstId::None, .type_id = SemIR::TypeId::None}; } SemIR::TypeId pointer_type_id = @@ -1197,9 +1190,9 @@ static auto MapType(Context& context, SemIR::LocId loc_id, clang::QualType type) } if (wrapper.hasQualifiers()) { - mapped = MapQualifiedType(context, loc_id, wrapper, mapped); + mapped = MapQualifiedType(context, wrapper, mapped); } else if (wrapper->isPointerType()) { - mapped = MapPointerType(context, loc_id, wrapper, mapped); + mapped = MapPointerType(context, wrapper, mapped); } else { CARBON_FATAL("Unexpected wrapper type {0}", wrapper.getAsString()); } @@ -1656,11 +1649,12 @@ static auto ImportDeclAfterDependencies(Context& context, SemIR::LocId loc_id, return ImportNamespaceDecl(context, clang_namespace_decl); } if (auto* type_decl = dyn_cast(clang_decl)) { - auto type = type_decl->getASTContext().getTypeDeclType(type_decl); + auto type = clang_decl->getASTContext().getTypeDeclType(type_decl); auto type_inst_id = MapType(context, loc_id, type).inst_id; if (!type_inst_id.has_value()) { - context.TODO(loc_id, llvm::formatv("Unsupported: Type declaration: {0}", - type.getAsString())); + context.TODO(AddImportIRInst(context.sem_ir(), type_decl->getLocation()), + llvm::formatv("Unsupported: Type declaration: {0}", + type.getAsString())); return SemIR::ErrorInst::InstId; } return type_inst_id; @@ -1672,13 +1666,15 @@ static auto ImportDeclAfterDependencies(Context& context, SemIR::LocId loc_id, existing_inst_id.has_value()) { return existing_inst_id; } - context.TODO(loc_id, "Unsupported: Unhandled kind of field declaration"); - return SemIR::InstId::None; + context.TODO(AddImportIRInst(context.sem_ir(), clang_decl->getLocation()), + "Unsupported: field declaration has unhandled type or kind"); + return SemIR::ErrorInst::InstId; } - context.TODO(loc_id, llvm::formatv("Unsupported: Declaration type {0}", - clang_decl->getDeclKindName())); - return SemIR::InstId::None; + context.TODO(AddImportIRInst(context.sem_ir(), clang_decl->getLocation()), + llvm::formatv("Unsupported: Declaration type {0}", + clang_decl->getDeclKindName())); + return SemIR::ErrorInst::InstId; } // Imports a declaration from Clang to Carbon. If successful, returns the diff --git a/toolchain/check/testdata/interop/cpp/class/class.carbon b/toolchain/check/testdata/interop/cpp/class/class.carbon index bdcf5be49074..691e846d4778 100644 --- a/toolchain/check/testdata/interop/cpp/class/class.carbon +++ b/toolchain/check/testdata/interop/cpp/class/class.carbon @@ -121,18 +121,15 @@ class Bar { library "[[@TEST_NAME]]"; +// CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+4]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./static_data_member.h:4:15: error: semantics TODO: `Unsupported: Declaration type Var` [SemanticsTodo] +// CHECK:STDERR: static Bar* foo; +// CHECK:STDERR: ^ import Cpp library "static_data_member.h"; fn MyF() { //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+11]]:23: error: semantics TODO: `Unsupported: Declaration type Var` [SemanticsTodo] - // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); - // CHECK:STDERR: ^~~~~~~~~~~ - // CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+8]]:23: note: in `Cpp` name lookup for `foo` [InCppNameLookup] - // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); - // CHECK:STDERR: ^~~~~~~~~~~ - // CHECK:STDERR: - // CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+4]]:23: error: member name `foo` not found in `Cpp.Bar` [MemberNameNotFoundInInstScope] + // CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+4]]:23: note: in `Cpp` name lookup for `foo` [InCppNameLookup] // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); // CHECK:STDERR: ^~~~~~~~~~~ // CHECK:STDERR: @@ -224,17 +221,14 @@ class Bar {}; library "[[@TEST_NAME]]"; +// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+4]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./template.h:3:7: error: semantics TODO: `Unsupported: Declaration type ClassTemplate` [SemanticsTodo] +// CHECK:STDERR: class Bar {}; +// CHECK:STDERR: ^ import Cpp library "template.h"; //@dump-sem-ir-begin -// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+11]]:13: error: semantics TODO: `Unsupported: Declaration type ClassTemplate` [SemanticsTodo] -// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+8]]:13: note: in `Cpp` name lookup for `Bar` [InCppNameLookup] -// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: -// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+4]]:13: error: member name `Bar` not found in `Cpp` [MemberNameNotFoundInInstScope] +// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+4]]:13: note: in `Cpp` name lookup for `Bar` [InCppNameLookup] // CHECK:STDERR: fn MyF(bar: Cpp.Bar*); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: @@ -394,13 +388,13 @@ fn MyF(bar: Cpp.Bar*); // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %bar.patt: %pattern_type = binding_pattern bar [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %Cpp.ref.loc19_23: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %Bar.ref.loc19_26: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %Cpp.ref.loc16_23: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref.loc16_26: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar] // CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] -// CHECK:STDOUT: %.loc19: type = splice_block %ptr [concrete = constants.%ptr.f68] { -// CHECK:STDOUT: %Cpp.ref.loc19_12: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %Bar.ref.loc19_15: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar] -// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref.loc19_15 [concrete = constants.%ptr.f68] +// CHECK:STDOUT: %.loc16: type = splice_block %ptr [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref.loc16_12: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref.loc16_15: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref.loc16_15 [concrete = constants.%ptr.f68] // CHECK:STDOUT: } // CHECK:STDOUT: %bar: %ptr.f68 = bind_name bar, [concrete = ] // CHECK:STDOUT: @@ -584,7 +578,7 @@ fn MyF(bar: Cpp.Bar*); // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { -// CHECK:STDOUT: .Bar = +// CHECK:STDOUT: .Bar = // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: } @@ -595,7 +589,7 @@ fn MyF(bar: Cpp.Bar*); // CHECK:STDOUT: %bar.param_patt: = value_param_pattern %bar.patt, call_param0 [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %bar.param: = value_param call_param0 -// CHECK:STDOUT: %.loc18: type = splice_block %ptr [concrete = ] { +// CHECK:STDOUT: %.loc15: type = splice_block %ptr [concrete = ] { // CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %Bar.ref: = name_ref Bar, [concrete = ] // CHECK:STDOUT: %ptr: type = ptr_type [concrete = ] diff --git a/toolchain/check/testdata/interop/cpp/class/field.carbon b/toolchain/check/testdata/interop/cpp/class/field.carbon index 0e0a0f520f74..68d94bebc94e 100644 --- a/toolchain/check/testdata/interop/cpp/class/field.carbon +++ b/toolchain/check/testdata/interop/cpp/class/field.carbon @@ -123,35 +123,29 @@ fn G(s: Cpp.Union) -> i32 { library "[[@TEST_NAME]]"; +// CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+4]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./with_bitfields.h:4:7: error: semantics TODO: `Unsupported: field declaration has unhandled type or kind` [SemanticsTodo] +// CHECK:STDERR: int b : 2; +// CHECK:STDERR: ^ import Cpp library "with_bitfields.h"; fn F(s: Cpp.Struct) -> i32 { //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+11]]:10: error: semantics TODO: `Unsupported: Unhandled kind of field declaration` [SemanticsTodo] - // CHECK:STDERR: return s.b; - // CHECK:STDERR: ^~~ // CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+8]]:10: note: in `Cpp` name lookup for `b` [InCppNameLookup] // CHECK:STDERR: return s.b; // CHECK:STDERR: ^~~ // CHECK:STDERR: - // CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+4]]:10: error: member name `b` not found in `Cpp.Struct` [MemberNameNotFoundInInstScope] - // CHECK:STDERR: return s.b; - // CHECK:STDERR: ^~~ - // CHECK:STDERR: + // CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE-8]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./with_bitfields.h:9:7: error: semantics TODO: `Unsupported: field declaration has unhandled type or kind` [SemanticsTodo] + // CHECK:STDERR: int d : 3; + // CHECK:STDERR: ^ return s.b; //@dump-sem-ir-end } fn G(s: Cpp.Union) -> i32 { //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+11]]:10: error: semantics TODO: `Unsupported: Unhandled kind of field declaration` [SemanticsTodo] - // CHECK:STDERR: return s.d; - // CHECK:STDERR: ^~~ - // CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+8]]:10: note: in `Cpp` name lookup for `d` [InCppNameLookup] - // CHECK:STDERR: return s.d; - // CHECK:STDERR: ^~~ - // CHECK:STDERR: - // CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+4]]:10: error: member name `d` not found in `Cpp.Union` [MemberNameNotFoundInInstScope] + // CHECK:STDERR: fail_todo_use_bitfields.carbon:[[@LINE+4]]:10: note: in `Cpp` name lookup for `d` [InCppNameLookup] // CHECK:STDERR: return s.d; // CHECK:STDERR: ^~~ // CHECK:STDERR: @@ -159,6 +153,72 @@ fn G(s: Cpp.Union) -> i32 { //@dump-sem-ir-end } +// --- unsupported_members.h + +struct UnsupportedMembers { + // Volatile is not supported. + volatile int is_volatile; + // Nullable pointers are not supported. + int *is_nullable; + // References are not supported. + int &is_reference; + // But this should be fine. + int integer; +}; + +void Consume(UnsupportedMembers); + +// --- supported_members_in_type_with_unsupported_members.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "unsupported_members.h"; + +fn Test(m: Cpp.UnsupportedMembers*) { + // OK: Can still access supported members. + m->integer = 42; + // OK: Can still pass the class to a C++ function. + Cpp.Consume(*m); +} + +// --- fail_use_unsupported_members.carbon + +library "[[@TEST_NAME]]"; + +// CHECK:STDERR: fail_use_unsupported_members.carbon:[[@LINE+4]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./unsupported_members.h:4:16: error: semantics TODO: `Unsupported: field declaration has unhandled type or kind` [SemanticsTodo] +// CHECK:STDERR: volatile int is_volatile; +// CHECK:STDERR: ^ +import Cpp library "unsupported_members.h"; + +fn Test(m: Cpp.UnsupportedMembers*) { + // CHECK:STDERR: fail_use_unsupported_members.carbon:[[@LINE+8]]:16: note: in `Cpp` name lookup for `is_volatile` [InCppNameLookup] + // CHECK:STDERR: let a: i32 = m->is_volatile; + // CHECK:STDERR: ^~~~~~~~~~~~~~ + // CHECK:STDERR: + // CHECK:STDERR: fail_use_unsupported_members.carbon:[[@LINE-7]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./unsupported_members.h:6:8: error: semantics TODO: `Unsupported: field declaration has unhandled type or kind` [SemanticsTodo] + // CHECK:STDERR: int *is_nullable; + // CHECK:STDERR: ^ + let a: i32 = m->is_volatile; + + // CHECK:STDERR: fail_use_unsupported_members.carbon:[[@LINE+8]]:17: note: in `Cpp` name lookup for `is_nullable` [InCppNameLookup] + // CHECK:STDERR: let b: i32 = *m->is_nullable; + // CHECK:STDERR: ^~~~~~~~~~~~~~ + // CHECK:STDERR: + // CHECK:STDERR: fail_use_unsupported_members.carbon:[[@LINE-17]]:10: in file included here [InCppInclude] + // CHECK:STDERR: ./unsupported_members.h:8:8: error: semantics TODO: `Unsupported: field declaration has unhandled type or kind` [SemanticsTodo] + // CHECK:STDERR: int &is_reference; + // CHECK:STDERR: ^ + let b: i32 = *m->is_nullable; + + // CHECK:STDERR: fail_use_unsupported_members.carbon:[[@LINE+4]]:16: note: in `Cpp` name lookup for `is_reference` [InCppNameLookup] + // CHECK:STDERR: let c: i32 = m->is_reference; + // CHECK:STDERR: ^~~~~~~~~~~~~~~ + // CHECK:STDERR: + let c: i32 = m->is_reference; +} + // CHECK:STDOUT: --- use_struct_fields.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/interop/cpp/class/method.carbon b/toolchain/check/testdata/interop/cpp/class/method.carbon index 30014c4e9ee7..6a2a08c301e1 100644 --- a/toolchain/check/testdata/interop/cpp/class/method.carbon +++ b/toolchain/check/testdata/interop/cpp/class/method.carbon @@ -57,18 +57,13 @@ fn Value(v: Cpp.HasQualifiers) { v.plain(); // TODO: This should remain invalid once we support `volatile`. - // CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+12]]:3: error: semantics TODO: `Unsupported: qualified type: volatile struct HasQualifiers` [SemanticsTodo] + // CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: object parameter type: volatile struct HasQualifiers` [SemanticsTodo] // CHECK:STDERR: v.volatile_this(); // CHECK:STDERR: ^~~~~~~~~~~~~~~ - // CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+9]]:3: note: in `Cpp` name lookup for `volatile_this` [InCppNameLookup] + // CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `volatile_this` [InCppNameLookup] // CHECK:STDERR: v.volatile_this(); // CHECK:STDERR: ^~~~~~~~~~~~~~~ // CHECK:STDERR: - // 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: v.volatile_this(); - // CHECK:STDERR: ^ - // CHECK:STDERR: fail_bad_object_param_qualifiers_by_value.carbon: note: initializing function parameter [InCallToFunctionParam] - // CHECK:STDERR: 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] @@ -105,7 +100,7 @@ import Cpp library "object_param_qualifiers.h"; fn Ref(p: Cpp.HasQualifiers*) { // TODO: This should eventually be accepted if we support `volatile`. - // CHECK:STDERR: fail_todo_bad_object_param_qualifiers_by_ref.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: qualified type: volatile struct HasQualifiers` [SemanticsTodo] + // CHECK:STDERR: fail_todo_bad_object_param_qualifiers_by_ref.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: object parameter type: volatile struct HasQualifiers` [SemanticsTodo] // CHECK:STDERR: p->volatile_this(); // CHECK:STDERR: ^~~~~~~~~~~~~~~~ // CHECK:STDERR: fail_todo_bad_object_param_qualifiers_by_ref.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `volatile_this` [InCppNameLookup] diff --git a/toolchain/check/testdata/interop/cpp/class/struct.carbon b/toolchain/check/testdata/interop/cpp/class/struct.carbon index ff4bf135ff60..f7c69b2a71e9 100644 --- a/toolchain/check/testdata/interop/cpp/class/struct.carbon +++ b/toolchain/check/testdata/interop/cpp/class/struct.carbon @@ -119,18 +119,15 @@ struct Bar { library "[[@TEST_NAME]]"; +// CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+4]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./static_data_member.h:3:24: error: semantics TODO: `Unsupported: Declaration type Var` [SemanticsTodo] +// CHECK:STDERR: static Bar* _Nonnull foo; +// CHECK:STDERR: ^ import Cpp library "static_data_member.h"; fn MyF() { //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+11]]:23: error: semantics TODO: `Unsupported: Declaration type Var` [SemanticsTodo] - // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); - // CHECK:STDERR: ^~~~~~~~~~~ - // CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+8]]:23: note: in `Cpp` name lookup for `foo` [InCppNameLookup] - // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); - // CHECK:STDERR: ^~~~~~~~~~~ - // CHECK:STDERR: - // CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+4]]:23: error: member name `foo` not found in `Cpp.Bar` [MemberNameNotFoundInInstScope] + // CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+4]]:23: note: in `Cpp` name lookup for `foo` [InCppNameLookup] // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); // CHECK:STDERR: ^~~~~~~~~~~ // CHECK:STDERR: @@ -212,17 +209,14 @@ struct Bar {}; library "[[@TEST_NAME]]"; +// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+4]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./template.h:3:8: error: semantics TODO: `Unsupported: Declaration type ClassTemplate` [SemanticsTodo] +// CHECK:STDERR: struct Bar {}; +// CHECK:STDERR: ^ import Cpp library "template.h"; //@dump-sem-ir-begin -// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+11]]:13: error: semantics TODO: `Unsupported: Declaration type ClassTemplate` [SemanticsTodo] -// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+8]]:13: note: in `Cpp` name lookup for `Bar` [InCppNameLookup] -// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: -// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+4]]:13: error: member name `Bar` not found in `Cpp` [MemberNameNotFoundInInstScope] +// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+4]]:13: note: in `Cpp` name lookup for `Bar` [InCppNameLookup] // CHECK:STDERR: fn MyF(bar: Cpp.Bar*); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: @@ -382,13 +376,13 @@ fn MyF(bar: Cpp.Bar*); // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %bar.patt: %pattern_type = binding_pattern bar [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %Cpp.ref.loc19_23: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %Bar.ref.loc19_26: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %Cpp.ref.loc16_23: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref.loc16_26: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar] // CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] -// CHECK:STDOUT: %.loc19: type = splice_block %ptr [concrete = constants.%ptr.f68] { -// CHECK:STDOUT: %Cpp.ref.loc19_12: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %Bar.ref.loc19_15: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar] -// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref.loc19_15 [concrete = constants.%ptr.f68] +// CHECK:STDOUT: %.loc16: type = splice_block %ptr [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref.loc16_12: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref.loc16_15: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref.loc16_15 [concrete = constants.%ptr.f68] // CHECK:STDOUT: } // CHECK:STDOUT: %bar: %ptr.f68 = bind_name bar, [concrete = ] // CHECK:STDOUT: @@ -532,7 +526,7 @@ fn MyF(bar: Cpp.Bar*); // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { -// CHECK:STDOUT: .Bar = +// CHECK:STDOUT: .Bar = // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: } @@ -543,7 +537,7 @@ fn MyF(bar: Cpp.Bar*); // CHECK:STDOUT: %bar.param_patt: = value_param_pattern %bar.patt, call_param0 [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %bar.param: = value_param call_param0 -// CHECK:STDOUT: %.loc18: type = splice_block %ptr [concrete = ] { +// CHECK:STDOUT: %.loc15: type = splice_block %ptr [concrete = ] { // CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %Bar.ref: = name_ref Bar, [concrete = ] // CHECK:STDOUT: %ptr: type = ptr_type [concrete = ] diff --git a/toolchain/check/testdata/interop/cpp/class/union.carbon b/toolchain/check/testdata/interop/cpp/class/union.carbon index 95c0affd6698..7d9fd327b8f5 100644 --- a/toolchain/check/testdata/interop/cpp/class/union.carbon +++ b/toolchain/check/testdata/interop/cpp/class/union.carbon @@ -121,18 +121,15 @@ union Bar { library "[[@TEST_NAME]]"; +// CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+4]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./static_data_member.h:4:24: error: semantics TODO: `Unsupported: Declaration type Var` [SemanticsTodo] +// CHECK:STDERR: static Bar* _Nonnull foo; +// CHECK:STDERR: ^ import Cpp library "static_data_member.h"; fn MyF() { //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+11]]:23: error: semantics TODO: `Unsupported: Declaration type Var` [SemanticsTodo] - // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); - // CHECK:STDERR: ^~~~~~~~~~~ - // CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+8]]:23: note: in `Cpp` name lookup for `foo` [InCppNameLookup] - // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); - // CHECK:STDERR: ^~~~~~~~~~~ - // CHECK:STDERR: - // CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+4]]:23: error: member name `foo` not found in `Cpp.Bar` [MemberNameNotFoundInInstScope] + // CHECK:STDERR: fail_todo_import_static_data_member.carbon:[[@LINE+4]]:23: note: in `Cpp` name lookup for `foo` [InCppNameLookup] // CHECK:STDERR: let bar: Cpp.Bar* = Cpp.Bar.foo(); // CHECK:STDERR: ^~~~~~~~~~~ // CHECK:STDERR: @@ -176,17 +173,14 @@ union Bar {}; library "[[@TEST_NAME]]"; +// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+4]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./template.h:3:7: error: semantics TODO: `Unsupported: Declaration type ClassTemplate` [SemanticsTodo] +// CHECK:STDERR: union Bar {}; +// CHECK:STDERR: ^ import Cpp library "template.h"; //@dump-sem-ir-begin -// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+11]]:13: error: semantics TODO: `Unsupported: Declaration type ClassTemplate` [SemanticsTodo] -// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+8]]:13: note: in `Cpp` name lookup for `Bar` [InCppNameLookup] -// CHECK:STDERR: fn MyF(bar: Cpp.Bar*); -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: -// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+4]]:13: error: member name `Bar` not found in `Cpp` [MemberNameNotFoundInInstScope] +// CHECK:STDERR: fail_todo_import_template.carbon:[[@LINE+4]]:13: note: in `Cpp` name lookup for `Bar` [InCppNameLookup] // CHECK:STDERR: fn MyF(bar: Cpp.Bar*); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: @@ -346,13 +340,13 @@ fn MyF(bar: Cpp.Bar*); // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %bar.patt: %pattern_type = binding_pattern bar [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %Cpp.ref.loc19_23: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %Bar.ref.loc19_26: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %Cpp.ref.loc16_23: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref.loc16_26: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar] // CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] -// CHECK:STDOUT: %.loc19: type = splice_block %ptr [concrete = constants.%ptr.f68] { -// CHECK:STDOUT: %Cpp.ref.loc19_12: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %Bar.ref.loc19_15: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar] -// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref.loc19_15 [concrete = constants.%ptr.f68] +// CHECK:STDOUT: %.loc16: type = splice_block %ptr [concrete = constants.%ptr.f68] { +// CHECK:STDOUT: %Cpp.ref.loc16_12: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Bar.ref.loc16_15: type = name_ref Bar, imports.%Bar.decl [concrete = constants.%Bar] +// CHECK:STDOUT: %ptr: type = ptr_type %Bar.ref.loc16_15 [concrete = constants.%ptr.f68] // CHECK:STDOUT: } // CHECK:STDOUT: %bar: %ptr.f68 = bind_name bar, [concrete = ] // CHECK:STDOUT: @@ -420,7 +414,7 @@ fn MyF(bar: Cpp.Bar*); // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { -// CHECK:STDOUT: .Bar = +// CHECK:STDOUT: .Bar = // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: } @@ -431,7 +425,7 @@ fn MyF(bar: Cpp.Bar*); // CHECK:STDOUT: %bar.param_patt: = value_param_pattern %bar.patt, call_param0 [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %bar.param: = value_param call_param0 -// CHECK:STDOUT: %.loc18: type = splice_block %ptr [concrete = ] { +// CHECK:STDOUT: %.loc15: type = splice_block %ptr [concrete = ] { // CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %Bar.ref: = name_ref Bar, [concrete = ] // CHECK:STDOUT: %ptr: type = ptr_type [concrete = ] diff --git a/toolchain/check/testdata/interop/cpp/function/pointer.carbon b/toolchain/check/testdata/interop/cpp/function/pointer.carbon index 8a74192194b2..37f502dc01b5 100644 --- a/toolchain/check/testdata/interop/cpp/function/pointer.carbon +++ b/toolchain/check/testdata/interop/cpp/function/pointer.carbon @@ -176,7 +176,7 @@ import Cpp library "nullable_pointer_param.h"; fn F() { //@dump-sem-ir-begin var s: Cpp.S = {}; - // CHECK:STDERR: fail_todo_import_nullable_pointer_param.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: nullable pointer: S *` [SemanticsTodo] + // CHECK:STDERR: fail_todo_import_nullable_pointer_param.carbon:[[@LINE+7]]:3: error: semantics TODO: `Unsupported: parameter type: S *` [SemanticsTodo] // CHECK:STDERR: Cpp.foo(&s); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: fail_todo_import_nullable_pointer_param.carbon:[[@LINE+4]]:3: note: in `Cpp` name lookup for `foo` [InCppNameLookup] @@ -524,8 +524,6 @@ fn F() { // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] // CHECK:STDOUT: %pattern_type.7da: type = pattern_type %S [concrete] // CHECK:STDOUT: %S.val: %S = struct_value () [concrete] -// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] -// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] // CHECK:STDOUT: %ptr.5c7: type = ptr_type %S [concrete] // CHECK:STDOUT: %T.as.Destroy.impl.Op.type.642: type = fn_type @T.as.Destroy.impl.Op, @T.as.Destroy.impl(%S) [concrete] // CHECK:STDOUT: %T.as.Destroy.impl.Op.ab5: %T.as.Destroy.impl.Op.type.642 = struct_value () [concrete] @@ -534,15 +532,10 @@ fn F() { // CHECK:STDOUT: imports { // CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { // CHECK:STDOUT: .S = %S.decl -// CHECK:STDOUT: .foo = %foo.decl +// CHECK:STDOUT: .foo = // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: %S.decl: type = class_decl @S [concrete = constants.%S] {} {} -// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] { -// CHECK:STDOUT: -// CHECK:STDOUT: } { -// CHECK:STDOUT: -// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() { @@ -562,10 +555,9 @@ fn F() { // CHECK:STDOUT: } // CHECK:STDOUT: %s: ref %S = bind_name s, %s.var // CHECK:STDOUT: %Cpp.ref.loc16: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, imports.%foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.ref: = name_ref foo, [concrete = ] // CHECK:STDOUT: %s.ref: ref %S = name_ref s, %s // CHECK:STDOUT: %addr.loc16: %ptr.5c7 = addr_of %s.ref -// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref() // CHECK:STDOUT: %T.as.Destroy.impl.Op.bound: = bound_method %s.var, constants.%T.as.Destroy.impl.Op.ab5 // CHECK:STDOUT: // CHECK:STDOUT: %bound_method: = bound_method %s.var, %T.as.Destroy.impl.Op.specific_fn diff --git a/toolchain/check/testdata/interop/cpp/unsupported_decl_type.carbon b/toolchain/check/testdata/interop/cpp/unsupported_decl_type.carbon index 1d33b673e323..f0eb4bdd1b1e 100644 --- a/toolchain/check/testdata/interop/cpp/unsupported_decl_type.carbon +++ b/toolchain/check/testdata/interop/cpp/unsupported_decl_type.carbon @@ -18,18 +18,15 @@ template class C {}; library "[[@TEST_NAME]]"; +// CHECK:STDERR: fail_todo_use_template.carbon:[[@LINE+4]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./template.h:2:28: error: semantics TODO: `Unsupported: Declaration type ClassTemplate` [SemanticsTodo] +// CHECK:STDERR: template class C {}; +// CHECK:STDERR: ^ import Cpp library "template.h"; fn F() { //@dump-sem-ir-begin - // CHECK:STDERR: fail_todo_use_template.carbon:[[@LINE+11]]:10: error: semantics TODO: `Unsupported: Declaration type ClassTemplate` [SemanticsTodo] - // CHECK:STDERR: var c: Cpp.C({}); - // CHECK:STDERR: ^~~~~ - // CHECK:STDERR: fail_todo_use_template.carbon:[[@LINE+8]]:10: note: in `Cpp` name lookup for `C` [InCppNameLookup] - // CHECK:STDERR: var c: Cpp.C({}); - // CHECK:STDERR: ^~~~~ - // CHECK:STDERR: - // CHECK:STDERR: fail_todo_use_template.carbon:[[@LINE+4]]:10: error: member name `C` not found in `Cpp` [MemberNameNotFoundInInstScope] + // CHECK:STDERR: fail_todo_use_template.carbon:[[@LINE+4]]:10: note: in `Cpp` name lookup for `C` [InCppNameLookup] // CHECK:STDERR: var c: Cpp.C({}); // CHECK:STDERR: ^~~~~ // CHECK:STDERR: diff --git a/toolchain/lower/testdata/interop/cpp/fail_extern_c.carbon b/toolchain/lower/testdata/interop/cpp/fail_extern_c.carbon index aae1b7678003..44d769110f04 100644 --- a/toolchain/lower/testdata/interop/cpp/fail_extern_c.carbon +++ b/toolchain/lower/testdata/interop/cpp/fail_extern_c.carbon @@ -26,17 +26,14 @@ extern "C" int foo; library "[[@TEST_NAME]]"; +// CHECK:STDERR: fail_todo_import_extern_c_variable.carbon:[[@LINE+4]]:10: in file included here [InCppInclude] +// CHECK:STDERR: ./extern_c_variable.h:2:16: error: semantics TODO: `Unsupported: Declaration type Var` [SemanticsTodo] +// CHECK:STDERR: extern "C" int foo; +// CHECK:STDERR: ^ import Cpp library "extern_c_variable.h"; fn MyF() -> i32 { - // CHECK:STDERR: fail_todo_import_extern_c_variable.carbon:[[@LINE+11]]:10: error: semantics TODO: `Unsupported: Declaration type Var` [SemanticsTodo] - // CHECK:STDERR: return Cpp.foo; - // CHECK:STDERR: ^~~~~~~ - // CHECK:STDERR: fail_todo_import_extern_c_variable.carbon:[[@LINE+8]]:10: note: in `Cpp` name lookup for `foo` [InCppNameLookup] - // CHECK:STDERR: return Cpp.foo; - // CHECK:STDERR: ^~~~~~~ - // CHECK:STDERR: - // CHECK:STDERR: fail_todo_import_extern_c_variable.carbon:[[@LINE+4]]:10: error: member name `foo` not found in `Cpp` [MemberNameNotFoundInInstScope] + // CHECK:STDERR: fail_todo_import_extern_c_variable.carbon:[[@LINE+4]]:10: note: in `Cpp` name lookup for `foo` [InCppNameLookup] // CHECK:STDERR: return Cpp.foo; // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: