// Part of the Carbon Language project, under the Apache License v2.0 with LLVM // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon // // AUTOUPDATE // TIP: To test this file alone, run: // TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/function/import/overloads.carbon // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/function/import/overloads.carbon // ============================================================================ // Overloaded sets tests // ============================================================================ // --- multiple_functions_no_overloads.h auto no_overloads_foo(short a) -> void; auto no_overloads_bar(short a) -> void; // --- import_multiple_functions_no_overloads.carbon library "[[@TEST_NAME]]"; import Cpp library "multiple_functions_no_overloads.h"; fn F() { Cpp.no_overloads_bar(1 as i16); } // --- overloaded_functions.h auto overloaded_foo(short a) -> void; auto overloaded_foo(int a) -> void; // --- import_overloaded_functions.carbon library "[[@TEST_NAME]]"; import Cpp library "overloaded_functions.h"; fn F() { Cpp.overloaded_foo(1 as i32); } // --- both_overloaded_functions_called.h auto both_called_foo(short a) -> void; auto both_called_foo(int a) -> void; // --- import_both_overloaded_functions_called.carbon library "[[@TEST_NAME]]"; import Cpp library "both_overloaded_functions_called.h"; fn F() { Cpp.both_called_foo(1 as i32); Cpp.both_called_foo(1 as i16); } // --- multiple_overloaded_sets.h auto multi_set_foo(short a) -> void; auto multi_set_foo(int a) -> void; auto multi_set_bar(long a) -> void; auto multi_set_bar(int a) -> void; // --- import_multiple_overloaded_sets.carbon library "[[@TEST_NAME]]"; import Cpp library "multiple_overloaded_sets.h"; fn F() { Cpp.multi_set_foo(1 as i32); Cpp.multi_set_bar(1 as i32); } // ============================================================================ // Call args tests // ============================================================================ // --- int_literal.h auto int_literal_foo(int a) -> int; auto int_literal_foo(unsigned int a) -> unsigned int; auto int_literal_foo(long a) -> long; auto int_literal_foo(unsigned long a) -> unsigned long; auto int_literal_foo(long long a) -> long long; auto int_literal_foo(unsigned long long a) -> unsigned long long; auto int_literal_foo(__int128 a) -> __int128; auto int_literal_foo(unsigned __int128 a) -> unsigned __int128; // --- import_int_literal.carbon library "[[@TEST_NAME]]"; import Cpp library "int_literal.h"; fn F() { // i32_max let unused a: i32 = Cpp.int_literal_foo(2147483647); // i32_max + 1 // It could fit to unsigned int, but only signed integers are considered, so assigned to long. // Decimal, hexadecimal and binary integer literals are treated the same when assigning a C++ type. let unused b: i64 = Cpp.int_literal_foo(2147483648); let unused b_hexa: i64 = Cpp.int_literal_foo(0x8000_0000); let unused b_binary: i64 = Cpp.int_literal_foo(0b1000_0000_0000_0000_0000_0000_0000_0000); // i64_max let unused c: i64 = Cpp.int_literal_foo(9223372036854775807); // i64_max + 1 // Could fit to unsigned long, but only signed integers are considered, so fitted to _int128. let unused d: i128 = Cpp.int_literal_foo(9223372036854775808); // u64_max let unused e: i128 = Cpp.int_literal_foo(18446744073709551615); // u64_max + 1 let unused f: i128 = Cpp.int_literal_foo(18446744073709551616); // i128_max let unused g: i128 = Cpp.int_literal_foo(170141183460469231731687303715884105727); } // --- fail_import_large_int_literal.carbon library "[[@TEST_NAME]]"; import Cpp library "int_literal.h"; fn F() { // TODO: get rid of the second error message here. // i128_max + 1 // CHECK:STDERR: ╭─┤ fail_import_large_int_literal.carbon:[[@LINE+18]]:44 // CHECK:STDERR: -> │ ...ed h: i128 = Cpp.int_literal_foo(170141183460469231731687303715884105728); // CHECK:STDERR: · ━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━ // CHECK:STDERR: · ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ // CHECK:STDERR: · ┃ error: integer value 170141183460469231731687303715884105728 too large to fit // CHECK:STDERR: · ┃ in a signed C++ integer type; requires 129 bits, but max is 128 // CHECK:STDERR: · ┃ [IntTooLargeForCppType] // CHECK:STDERR: ╰──── // CHECK:STDERR: // CHECK:STDERR: ╭─┤ fail_import_large_int_literal.carbon:[[@LINE+9]]:44 // CHECK:STDERR: -> │ ...ed h: i128 = Cpp.int_literal_foo(170141183460469231731687303715884105728); // CHECK:STDERR: · ┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: call argument of type // CHECK:STDERR: · ┃ `Core.IntLiteral` is not // CHECK:STDERR: · ┃ supported // CHECK:STDERR: · ┃ [CppCallArgTypeNotSupported] // CHECK:STDERR: ╰──── // CHECK:STDERR: let unused h: i128 = Cpp.int_literal_foo(170141183460469231731687303715884105728); } // --- negative_int_literal.h auto neg_literal_foo(long a) -> void; auto neg_literal_foo(int a) -> void; // --- import_negative_int_literal.carbon library "[[@TEST_NAME]]"; import Cpp library "negative_int_literal.h"; fn F() { // selects `auto neg_literal_foo(int a) -> void;` Cpp.neg_literal_foo(-1); } // --- negative_literal_passed_to_unsigned.h auto neg_to_unsigned_foo(unsigned int a) -> void; // --- fail_import_negative_literal_passed_to_unsigned.carbon library "[[@TEST_NAME]]"; import Cpp library "negative_literal_passed_to_unsigned.h"; fn F() { // CHECK:STDERR: ╭─┤ fail_import_negative_literal_passed_to_unsigned.carbon:[[@LINE+14]]:27 // CHECK:STDERR: -> │ Cpp.neg_to_unsigned_foo(-1); // CHECK:STDERR: · ┳━ // CHECK:STDERR: · ┗━━┫ error: negative integer value -1 converted to // CHECK:STDERR: · ┃ unsigned type `u32` // CHECK:STDERR: · ┃ [NegativeIntInUnsignedType] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./negative_literal_passed_to_unsigned.h // CHECK:STDERR: │ auto neg_to_unsigned_foo(unsigned int a) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.neg_to_unsigned_foo(-1); } // --- floating_point_literal.h auto float_literal_foo(float a) -> float; auto float_literal_foo(double a) -> double; // --- import_floating_point_literal.carbon library "[[@TEST_NAME]]"; import Cpp library "floating_point_literal.h"; fn F() { let unused d: f64 = Cpp.float_literal_foo(1.0); } // --- fail_import_large_floating_point_literal.carbon library "[[@TEST_NAME]]"; import Cpp library "floating_point_literal.h"; fn F() { // CHECK:STDERR: ╭─┤ fail_import_large_floating_point_literal.carbon:[[@LINE+14]]:25 // CHECK:STDERR: -> │ Cpp.float_literal_foo(1.8e+308); // CHECK:STDERR: · ┳━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: value 18*10^307 too large for floating-point // CHECK:STDERR: · ┃ type `f64` // CHECK:STDERR: · ┃ [FloatLiteralTooLargeForType] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./floating_point_literal.h // CHECK:STDERR: │ auto float_literal_foo(double a) -> double; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.float_literal_foo(1.8e+308); } // --- struct_init.h struct NoFields {}; auto PassNoFields(NoFields s) -> void; struct ThreeFields { int a, b, c; }; auto PassThreeFields(ThreeFields t) -> void; // --- struct_init.carbon library "[[@TEST_NAME]]"; import Cpp library "struct_init.h"; fn MakeEmpty() -> {}; fn Empty(value: {}, ref reference: {}) { Cpp.PassNoFields({}); Cpp.PassNoFields(value); Cpp.PassNoFields(reference); Cpp.PassNoFields(MakeEmpty()); } // --- fail_todo_struct_init_nonempty.carbon library "[[@TEST_NAME]]"; import Cpp library "struct_init.h"; fn MakeThreeFields() -> {.a: i32, .b: i32, .c: i32}; fn ThreeFields(value: {.a: i32, .b: i32, .c: i32}, ref reference: {.a: i32, .b: i32, .c: i32}) { // CHECK:STDERR: ╭─┤ fail_todo_struct_init_nonempty.carbon:[[@LINE+20]]:23 // CHECK:STDERR: -> │ Cpp.PassThreeFields({.a = 1, .b = 2, .c = 3}); // CHECK:STDERR: · ━━━━━━━━━━━━┳━━━━━━━━━━━ // CHECK:STDERR: · ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ // CHECK:STDERR: · ┃ error: cannot implicitly convert expression of type // CHECK:STDERR: · ┃ `{.a: Core.IntLiteral, .b: Core.IntLiteral, .c: Core.IntLiteral}` to // CHECK:STDERR: · ┃ `Cpp.ThreeFields` // CHECK:STDERR: · ┃ [ConversionFailure] // CHECK:STDERR: · ╭─────────────────────────────────╯ // CHECK:STDERR: · │ type `{.a: Core.IntLiteral, .b: Core.IntLiteral, .c: Core.IntLiteral}` does // CHECK:STDERR: · │ not implement interface `Core.ImplicitAs(Cpp.ThreeFields)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassThreeFields(ThreeFields t) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassThreeFields({.a = 1, .b = 2, .c = 3}); // CHECK:STDERR: ╭─┤ fail_todo_struct_init_nonempty.carbon:[[@LINE+19]]:23 // CHECK:STDERR: -> │ Cpp.PassThreeFields(value); // CHECK:STDERR: · ┳━━━━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type // CHECK:STDERR: · │ ┃ `{.a: i32, .b: i32, .c: i32}` to // CHECK:STDERR: · │ ┃ `Cpp.ThreeFields` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `{.a: i32, .b: i32, .c: i32}` does not // CHECK:STDERR: · │ implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(Cpp.ThreeFields)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassThreeFields(ThreeFields t) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassThreeFields(value); // CHECK:STDERR: ╭─┤ fail_todo_struct_init_nonempty.carbon:[[@LINE+19]]:23 // CHECK:STDERR: -> │ Cpp.PassThreeFields(reference); // CHECK:STDERR: · ┳━━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type // CHECK:STDERR: · │ ┃ `{.a: i32, .b: i32, .c: i32}` to // CHECK:STDERR: · │ ┃ `Cpp.ThreeFields` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `{.a: i32, .b: i32, .c: i32}` does not // CHECK:STDERR: · │ implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(Cpp.ThreeFields)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassThreeFields(ThreeFields t) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassThreeFields(reference); // CHECK:STDERR: ╭─┤ fail_todo_struct_init_nonempty.carbon:[[@LINE+19]]:23 // CHECK:STDERR: -> │ Cpp.PassThreeFields(MakeThreeFields()); // CHECK:STDERR: · ┳━━━━━━━━━━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type // CHECK:STDERR: · │ ┃ `{.a: i32, .b: i32, .c: i32}` to // CHECK:STDERR: · │ ┃ `Cpp.ThreeFields` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `{.a: i32, .b: i32, .c: i32}` does not // CHECK:STDERR: · │ implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(Cpp.ThreeFields)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassThreeFields(ThreeFields t) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassThreeFields(MakeThreeFields()); // CHECK:STDERR: ╭─┤ fail_todo_struct_init_nonempty.carbon:[[@LINE+20]]:23 // CHECK:STDERR: -> │ Cpp.PassThreeFields({.b = 1, .c = 2, .a = 3}); // CHECK:STDERR: · ━━━━━━━━━━━━┳━━━━━━━━━━━ // CHECK:STDERR: · ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ // CHECK:STDERR: · ┃ error: cannot implicitly convert expression of type // CHECK:STDERR: · ┃ `{.b: Core.IntLiteral, .c: Core.IntLiteral, .a: Core.IntLiteral}` to // CHECK:STDERR: · ┃ `Cpp.ThreeFields` // CHECK:STDERR: · ┃ [ConversionFailure] // CHECK:STDERR: · ╭─────────────────────────────────╯ // CHECK:STDERR: · │ type `{.b: Core.IntLiteral, .c: Core.IntLiteral, .a: Core.IntLiteral}` does // CHECK:STDERR: · │ not implement interface `Core.ImplicitAs(Cpp.ThreeFields)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassThreeFields(ThreeFields t) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassThreeFields({.b = 1, .c = 2, .a = 3}); } // --- fail_struct_init_field_mismatch.carbon library "[[@TEST_NAME]]"; import Cpp library "struct_init.h"; fn F() { // CHECK:STDERR: ╭─┤ fail_struct_init_field_mismatch.carbon:[[@LINE+15]]:3 // CHECK:STDERR: -> │ Cpp.PassThreeFields({.a = 1, .b = 2, .c = 3, .d = 4}); // CHECK:STDERR: · ━━━━━━━━━┳━━━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: no matching function for call to 'PassThreeFields' // CHECK:STDERR: · ┃ [CppInteropParseError] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassThreeFields(ThreeFields t) -> void; // CHECK:STDERR: · ┬ ┬──────────── // CHECK:STDERR: · ╰──────────────────┤ candidate function not viable [CppInteropParseNote] // CHECK:STDERR: · ╰────┤ cannot convert initializer list argument to // CHECK:STDERR: · │ 'ThreeFields' // CHECK:STDERR: · │ [CppInteropParseNoteReason] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassThreeFields({.a = 1, .b = 2, .c = 3, .d = 4}); // CHECK:STDERR: ╭─┤ fail_struct_init_field_mismatch.carbon:[[@LINE+15]]:3 // CHECK:STDERR: -> │ Cpp.PassThreeFields({.a = 1, .x = 2, .c = 3}); // CHECK:STDERR: · ━━━━━━━━━┳━━━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: no matching function for call to 'PassThreeFields' // CHECK:STDERR: · ┃ [CppInteropParseError] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassThreeFields(ThreeFields t) -> void; // CHECK:STDERR: · ┬ ┬──────────── // CHECK:STDERR: · ╰──────────────────┤ candidate function not viable [CppInteropParseNote] // CHECK:STDERR: · ╰────┤ cannot convert initializer list argument to // CHECK:STDERR: · │ 'ThreeFields' // CHECK:STDERR: · │ [CppInteropParseNoteReason] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassThreeFields({.a = 1, .x = 2, .c = 3}); } // --- fail_struct_init_unsupported_field_name.carbon library "[[@TEST_NAME]]"; import Cpp library "struct_init.h"; fn F() { // CHECK:STDERR: ╭─┤ fail_struct_init_unsupported_field_name.carbon:[[@LINE+7]]:23 // CHECK:STDERR: -> │ Cpp.PassThreeFields({.base = 1}); // CHECK:STDERR: · ━━━┳━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: field name `base` cannot be mapped into C++ // CHECK:STDERR: · ┃ [CppCallFieldNameNotSupported] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassThreeFields({.base = 1}); } // --- fail_struct_init_from_tuple.carbon library "[[@TEST_NAME]]"; import Cpp library "struct_init.h"; // TODO: Struct init from an undesignated list is allowed in C++, but not in // Carbon. Should we allow it when initializing a C++ class type? fn MakeEmpty() -> (); fn Empty(value: (), ref reference: ()) { // CHECK:STDERR: ╭─┤ fail_struct_init_from_tuple.carbon:[[@LINE+17]]:20 // CHECK:STDERR: -> │ Cpp.PassNoFields(()); // CHECK:STDERR: · ┳━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type `()` // CHECK:STDERR: · │ ┃ to `Cpp.NoFields` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `()` does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(Cpp.NoFields)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassNoFields(NoFields s) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassNoFields(()); // CHECK:STDERR: ╭─┤ fail_struct_init_from_tuple.carbon:[[@LINE+17]]:20 // CHECK:STDERR: -> │ Cpp.PassNoFields(value); // CHECK:STDERR: · ┳━━━━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type `()` // CHECK:STDERR: · │ ┃ to `Cpp.NoFields` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `()` does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(Cpp.NoFields)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassNoFields(NoFields s) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassNoFields(value); // CHECK:STDERR: ╭─┤ fail_struct_init_from_tuple.carbon:[[@LINE+17]]:20 // CHECK:STDERR: -> │ Cpp.PassNoFields(reference); // CHECK:STDERR: · ┳━━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type `()` // CHECK:STDERR: · │ ┃ to `Cpp.NoFields` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `()` does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(Cpp.NoFields)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassNoFields(NoFields s) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassNoFields(reference); // CHECK:STDERR: ╭─┤ fail_struct_init_from_tuple.carbon:[[@LINE+17]]:20 // CHECK:STDERR: -> │ Cpp.PassNoFields(MakeEmpty()); // CHECK:STDERR: · ┳━━━━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type `()` // CHECK:STDERR: · │ ┃ to `Cpp.NoFields` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `()` does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(Cpp.NoFields)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassNoFields(NoFields s) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassNoFields(MakeEmpty()); } fn MakeThreeFields() -> (i32, i32, i32); fn ThreeFields(value: (i32, i32, i32), ref reference: (i32, i32, i32)) { // CHECK:STDERR: ╭─┤ fail_struct_init_from_tuple.carbon:[[@LINE+21]]:23 // CHECK:STDERR: -> │ Cpp.PassThreeFields((1, 2, 3)); // CHECK:STDERR: · ┳━━━━━━━━ // CHECK:STDERR: · ┏━━━━━━━━━━━━━━━━━━━━━┛ // CHECK:STDERR: · ┃ error: cannot implicitly convert expression of type // CHECK:STDERR: · ┃ `(Core.IntLiteral, Core.IntLiteral, Core.IntLiteral)` to // CHECK:STDERR: · ┃ `Cpp.ThreeFields` // CHECK:STDERR: · ┃ [ConversionFailure] // CHECK:STDERR: · ╰──┤ type // CHECK:STDERR: · │ `(Core.IntLiteral, Core.IntLiteral, Core.IntLiteral)` // CHECK:STDERR: · │ does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(Cpp.ThreeFields)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassThreeFields(ThreeFields t) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassThreeFields((1, 2, 3)); // CHECK:STDERR: ╭─┤ fail_struct_init_from_tuple.carbon:[[@LINE+17]]:23 // CHECK:STDERR: -> │ Cpp.PassThreeFields(value); // CHECK:STDERR: · ┳━━━━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type // CHECK:STDERR: · │ ┃ `(i32, i32, i32)` to `Cpp.ThreeFields` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `(i32, i32, i32)` does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(Cpp.ThreeFields)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassThreeFields(ThreeFields t) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassThreeFields(value); // CHECK:STDERR: ╭─┤ fail_struct_init_from_tuple.carbon:[[@LINE+17]]:23 // CHECK:STDERR: -> │ Cpp.PassThreeFields(reference); // CHECK:STDERR: · ┳━━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type // CHECK:STDERR: · │ ┃ `(i32, i32, i32)` to `Cpp.ThreeFields` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `(i32, i32, i32)` does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(Cpp.ThreeFields)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassThreeFields(ThreeFields t) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassThreeFields(reference); // CHECK:STDERR: ╭─┤ fail_struct_init_from_tuple.carbon:[[@LINE+17]]:23 // CHECK:STDERR: -> │ Cpp.PassThreeFields(MakeThreeFields()); // CHECK:STDERR: · ┳━━━━━━━━━━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type // CHECK:STDERR: · │ ┃ `(i32, i32, i32)` to `Cpp.ThreeFields` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `(i32, i32, i32)` does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(Cpp.ThreeFields)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./struct_init.h // CHECK:STDERR: │ auto PassThreeFields(ThreeFields t) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassThreeFields(MakeThreeFields()); } // --- int_from_struct.h auto PassInt(int n) -> void; struct S {}; auto PassOverloaded(int n) -> void; auto PassOverloaded(S n) -> void; // --- fail_int_from_struct.carbon library "[[@TEST_NAME]]"; import Cpp library "int_from_struct.h"; fn F() { // C++ permits `{}` to be used to initialize an int, but Carbon does not. // CHECK:STDERR: ╭─┤ fail_int_from_struct.carbon:[[@LINE+16]]:15 // CHECK:STDERR: -> │ Cpp.PassInt({}); // CHECK:STDERR: · ┳━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type `{}` to // CHECK:STDERR: · │ ┃ `i32` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `{}` does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(i32)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./int_from_struct.h // CHECK:STDERR: │ auto PassInt(int n) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassInt({}); // CHECK:STDERR: ╭─┤ fail_int_from_struct.carbon:[[@LINE+16]]:15 // CHECK:STDERR: -> │ Cpp.PassInt(()); // CHECK:STDERR: · ┳━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type `()` to // CHECK:STDERR: · │ ┃ `i32` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `()` does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(i32)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./int_from_struct.h // CHECK:STDERR: │ auto PassInt(int n) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassInt(()); } // --- fail_int_from_struct_overloaded.carbon library "[[@TEST_NAME]]"; import Cpp library "int_from_struct.h"; fn F() { // C++ overload resolution prefers to convert `{}` to `int` rather than to an // empty struct. So that's the overload we pick, even though we can't call it. // CHECK:STDERR: ╭─┤ fail_int_from_struct_overloaded.carbon:[[@LINE+17]]:22 // CHECK:STDERR: -> │ Cpp.PassOverloaded({}); // CHECK:STDERR: · ┳━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type // CHECK:STDERR: · │ ┃ `{}` to `i32` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `{}` does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(i32)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./int_from_struct.h // CHECK:STDERR: │ auto PassOverloaded(int n) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassOverloaded({}); // CHECK:STDERR: ╭─┤ fail_int_from_struct_overloaded.carbon:[[@LINE+17]]:22 // CHECK:STDERR: -> │ Cpp.PassOverloaded(()); // CHECK:STDERR: · ┳━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type // CHECK:STDERR: · │ ┃ `()` to `i32` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `()` does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(i32)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./int_from_struct.h // CHECK:STDERR: │ auto PassOverloaded(int n) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.PassOverloaded(()); } // --- nested_structs.h struct A { int x, y; }; struct B { A a; int n; }; void TakeB(B); // --- fail_pass_nested_structs_inner_field_mismatch.carbon library "[[@TEST_NAME]]"; import Cpp library "nested_structs.h"; fn F() { // CHECK:STDERR: ╭─┤ fail_pass_nested_structs_inner_field_mismatch.carbon:[[@LINE+14]]:3 // CHECK:STDERR: -> │ Cpp.TakeB({.a = {.x = 1, .z = 2}, .n = 3}); // CHECK:STDERR: · ━━━━┳━━━━ // CHECK:STDERR: · ┗━━┫ error: no matching function for call to 'TakeB' // CHECK:STDERR: · ┃ [CppInteropParseError] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./nested_structs.h // CHECK:STDERR: │ void TakeB(B); // CHECK:STDERR: · ┬ ┬ // CHECK:STDERR: · ╰────────┤ candidate function not viable [CppInteropParseNote] // CHECK:STDERR: · ╰────┤ cannot convert initializer list argument to 'B' // CHECK:STDERR: · │ [CppInteropParseNoteReason] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.TakeB({.a = {.x = 1, .z = 2}, .n = 3}); } // --- fail_todo_pass_nested_structs.carbon library "[[@TEST_NAME]]"; import Cpp library "nested_structs.h"; fn F() { // CHECK:STDERR: ╭─┤ fail_todo_pass_nested_structs.carbon:[[@LINE+19]]:13 // CHECK:STDERR: -> │ Cpp.TakeB({.a = {.x = 1, .y = 2}, .n = 3}); // CHECK:STDERR: · ━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━ // CHECK:STDERR: · ┏━━━━━━━━━━━━━━━━━━━━━━━━━━┛ // CHECK:STDERR: · ┃ error: cannot implicitly convert expression of type // CHECK:STDERR: · ┃ `{.a: {.x: Core.IntLiteral, .y: Core.IntLiteral}, .n: Core.IntLiteral}` // CHECK:STDERR: · ┃ to `Cpp.B` // CHECK:STDERR: · ┃ [ConversionFailure] // CHECK:STDERR: · ╭──────────────────────────╯ // CHECK:STDERR: · │ type `{.a: {.x: Core.IntLiteral, .y: Core.IntLiteral}, .n: Core.IntLiteral}` // CHECK:STDERR: · │ does not implement interface `Core.ImplicitAs(Cpp.B)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./nested_structs.h // CHECK:STDERR: │ void TakeB(B); // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.TakeB({.a = {.x = 1, .y = 2}, .n = 3}); } // ============================================================================ // Overload rejected on Carbon side // ============================================================================ // --- upsizing.h auto upsizing_foo(int a) -> void; // --- upsizing.carbon library "[[@TEST_NAME]]"; import Cpp library "upsizing.h"; fn F() { Cpp.upsizing_foo(1 as i16); } // --- signedness_change.h auto signedness_foo(unsigned int a) -> void; // --- fail_signedness_change_rejected.carbon library "[[@TEST_NAME]]"; import Cpp library "signedness_change.h"; fn F() { // CHECK:STDERR: ╭─┤ fail_signedness_change_rejected.carbon:[[@LINE+17]]:22 // CHECK:STDERR: -> │ Cpp.signedness_foo(1 as i32); // CHECK:STDERR: · ┳━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type // CHECK:STDERR: · │ ┃ `i32` to `u32` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `i32` does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(u32)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./signedness_change.h // CHECK:STDERR: │ auto signedness_foo(unsigned int a) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.signedness_foo(1 as i32); } // --- downsizing_rejected.h auto downsizing_foo(short a) -> void; // --- fail_import_downsizing_rejected.carbon library "[[@TEST_NAME]]"; import Cpp library "downsizing_rejected.h"; fn F() { // CHECK:STDERR: ╭─┤ fail_import_downsizing_rejected.carbon:[[@LINE+17]]:22 // CHECK:STDERR: -> │ Cpp.downsizing_foo(1 as i32); // CHECK:STDERR: · ┳━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: cannot implicitly convert expression of type // CHECK:STDERR: · │ ┃ `i32` to `i16` // CHECK:STDERR: · │ ┃ [ConversionFailure] // CHECK:STDERR: · ╰────┤ type `i32` does not implement interface // CHECK:STDERR: · │ `Core.ImplicitAs(i16)` // CHECK:STDERR: · │ [MissingImplInMemberAccessInContext] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./downsizing_rejected.h // CHECK:STDERR: │ auto downsizing_foo(short a) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ initializing function parameter // CHECK:STDERR: · │ [InCallToFunctionParam] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.downsizing_foo(1 as i32); } // ============================================================================ // No viable function found // ============================================================================ // --- no_viable_function.h auto no_viable_foo(short a, int b) -> void; // --- fail_import_no_viable_function.carbon library "[[@TEST_NAME]]"; import Cpp library "no_viable_function.h"; fn F() { // CHECK:STDERR: ╭─┤ fail_import_no_viable_function.carbon:[[@LINE+15]]:3 // CHECK:STDERR: -> │ Cpp.no_viable_foo(1 as i64); // CHECK:STDERR: · ━━━━━━━━┳━━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: no matching function for call to 'no_viable_foo' // CHECK:STDERR: · ┃ [CppInteropParseError] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./no_viable_function.h // CHECK:STDERR: │ auto no_viable_foo(short a, int b) -> void; // CHECK:STDERR: · ┬ ───────┬────── // CHECK:STDERR: · ╰───────────────────────┤ candidate function not viable // CHECK:STDERR: · │ │ [CppInteropParseNote] // CHECK:STDERR: · ╰────┤ requires 2 arguments, but 1 was provided // CHECK:STDERR: · │ [CppInteropParseNoteReason] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.no_viable_foo(1 as i64); } // ============================================================================ // Ambiguous overload found // ============================================================================ // --- ambiguous_overload.h auto ambiguous_foo(short a) -> void; auto ambiguous_foo(int a) -> void; // --- fail_import_ambiguous_overload.carbon library "[[@TEST_NAME]]"; import Cpp library "ambiguous_overload.h"; fn F() { // CHECK:STDERR: ╭─┤ fail_import_ambiguous_overload.carbon:[[@LINE+15]]:3 // CHECK:STDERR: -> │ Cpp.ambiguous_foo(1 as i64); // CHECK:STDERR: · ━━━━━━━━┳━━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: call to 'ambiguous_foo' is ambiguous // CHECK:STDERR: · ┃ [CppInteropParseError] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./ambiguous_overload.h // CHECK:STDERR: │ auto ambiguous_foo(short a) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ candidate function [CppInteropParseNote] // CHECK:STDERR: │ auto ambiguous_foo(int a) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ candidate function [CppInteropParseNote] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.ambiguous_foo(1 as i64); } // ============================================================================ // Deleted function found // ============================================================================ // --- deleted_function.h auto deleted_foo(short a) -> void; auto deleted_foo(int a) -> void = delete; // --- fail_import_deleted_function.carbon library "[[@TEST_NAME]]"; import Cpp library "deleted_function.h"; fn F() { // CHECK:STDERR: ╭─┤ fail_import_deleted_function.carbon:[[@LINE+15]]:3 // CHECK:STDERR: -> │ Cpp.deleted_foo(1 as i32); // CHECK:STDERR: · ━━━━━━━┳━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: call to deleted function 'deleted_foo' // CHECK:STDERR: · ┃ [CppInteropParseError] // CHECK:STDERR: ┆ // CHECK:STDERR: ├─┤ ./deleted_function.h // CHECK:STDERR: │ auto deleted_foo(short a) -> void; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ candidate function [CppInteropParseNote] // CHECK:STDERR: │ auto deleted_foo(int a) -> void = delete; // CHECK:STDERR: · ┬ // CHECK:STDERR: · ╰──┤ candidate function has been explicitly deleted [CppInteropParseNote] // CHECK:STDERR: ╰──── // CHECK:STDERR: Cpp.deleted_foo(1 as i32); } // --- fail_missing_impl.carbon library "[[@TEST_NAME]]"; import Cpp inline ''' void missing_impl_foo(); void missing_impl_foo(int); '''; interface I {} fn EchoValue[ValueT: I](unused generic value: ValueT) {} fn F() { // CHECK:STDERR: ╭─┤ fail_missing_impl.carbon:[[@LINE+13]]:3 // CHECK:STDERR: │ fn EchoValue[ValueT: I](unused generic value: ValueT) {} // CHECK:STDERR: · ─────────────────────────┬───────────────────────────── // CHECK:STDERR: · ╰──┤ while deducing parameters of generic declared here // CHECK:STDERR: · │ [DeductionGenericHere] // CHECK:STDERR: ┆ // CHECK:STDERR: -> │ EchoValue(Cpp.missing_impl_foo); // CHECK:STDERR: · ┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // CHECK:STDERR: · ┗━━┫ error: cannot convert type `` into type // CHECK:STDERR: · ┃ implementing `I` // CHECK:STDERR: · ┃ [ConversionFailureTypeToFacet] // CHECK:STDERR: ╰──── // CHECK:STDERR: EchoValue(Cpp.missing_impl_foo); }