diff --git a/toolchain/check/testdata/interop/cpp/no_prelude/function_decl_inline.carbon b/toolchain/check/testdata/interop/cpp/no_prelude/function_decl_inline.carbon new file mode 100644 index 000000000000..2ab2a1f78c6e --- /dev/null +++ b/toolchain/check/testdata/interop/cpp/no_prelude/function_decl_inline.carbon @@ -0,0 +1,131 @@ +// 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 +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/no_prelude/function_decl_inline.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/no_prelude/function_decl_inline.carbon + +// ============================================================================ +// inline_function_decl_with_definition +// ============================================================================ + +// --- inline_function_decl_with_definition.h + +inline void foo() {} + +// --- import_inline_function_decl_with_definition.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "inline_function_decl_with_definition.h"; + +fn MyF() { + Cpp.foo(); +} + +// ============================================================================ +// inline_function_decl_without_definition +// ============================================================================ + +// --- inline_function_decl_without_definition.h + +inline void foo(); + +// --- todo_fail_import_inline_function_decl_without_definition.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "inline_function_decl_without_definition.h"; + +fn MyF() { + // TODO: Error on using an inline function without definition. + Cpp.foo(); + + // Don't error on repeated calls. + Cpp.foo(); +} + +// CHECK:STDOUT: --- import_inline_function_decl_with_definition.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .foo = @MyF.%foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "inline_function_decl_with_definition.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {} {} +// CHECK:STDOUT: %foo.ref: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call: init %empty_tuple.type = call %foo.ref() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_import_inline_function_decl_without_definition.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %MyF.type: type = fn_type @MyF [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %MyF: %MyF.type = struct_value () [concrete] +// CHECK:STDOUT: %foo.type: type = fn_type @foo [concrete] +// CHECK:STDOUT: %foo: %foo.type = struct_value () [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .foo = @MyF.%foo.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [concrete] { +// CHECK:STDOUT: .Cpp = imports.%Cpp +// CHECK:STDOUT: .MyF = %MyF.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.import_cpp = import_cpp { +// CHECK:STDOUT: import Cpp "inline_function_decl_without_definition.h" +// CHECK:STDOUT: } +// CHECK:STDOUT: %MyF.decl: %MyF.type = fn_decl @MyF [concrete = constants.%MyF] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MyF() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Cpp.ref.loc8: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %foo.decl: %foo.type = fn_decl @foo [concrete = constants.%foo] {} {} +// CHECK:STDOUT: %foo.ref.loc8: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call.loc8: init %empty_tuple.type = call %foo.ref.loc8() +// CHECK:STDOUT: %Cpp.ref.loc11: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %foo.ref.loc11: %foo.type = name_ref foo, %foo.decl [concrete = constants.%foo] +// CHECK:STDOUT: %foo.call.loc11: init %empty_tuple.type = call %foo.ref.loc11() +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @foo(); +// CHECK:STDOUT: diff --git a/toolchain/lower/testdata/interop/cpp/function_decl.carbon b/toolchain/lower/testdata/interop/cpp/function_decl.carbon index 016a1b8c091f..f8480d3d07f5 100644 --- a/toolchain/lower/testdata/interop/cpp/function_decl.carbon +++ b/toolchain/lower/testdata/interop/cpp/function_decl.carbon @@ -8,6 +8,10 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lower/testdata/interop/cpp/function_decl.carbon +// ============================================================================ +// function_decl +// ============================================================================ + // --- function_decl.h void foo(); @@ -22,6 +26,25 @@ fn MyF() { Cpp.foo(); } +// ============================================================================ +// inline_function_decl +// ============================================================================ + +// --- inline_function_decl.h + +inline void foo() {} + +// --- todo_import_inline_function_decl.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "inline_function_decl.h"; + +fn MyF() { + // TODO: This should generate the definition of the inline function `foo()`. + Cpp.foo(); +} + // CHECK:STDOUT: ; ModuleID = 'import_function_decl.carbon' // CHECK:STDOUT: source_filename = "import_function_decl.carbon" // CHECK:STDOUT: @@ -45,3 +68,26 @@ fn MyF() { // CHECK:STDOUT: !6 = !{} // CHECK:STDOUT: !7 = !DILocation(line: 7, column: 3, scope: !4) // CHECK:STDOUT: !8 = !DILocation(line: 6, column: 1, scope: !4) +// CHECK:STDOUT: ; ModuleID = 'todo_import_inline_function_decl.carbon' +// CHECK:STDOUT: source_filename = "todo_import_inline_function_decl.carbon" +// CHECK:STDOUT: +// CHECK:STDOUT: define void @_CMyF.Main() !dbg !4 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: call void @_Z3foov(), !dbg !7 +// CHECK:STDOUT: ret void, !dbg !8 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: declare void @_Z3foov() +// CHECK:STDOUT: +// CHECK:STDOUT: !llvm.module.flags = !{!0, !1} +// CHECK:STDOUT: !llvm.dbg.cu = !{!2} +// CHECK:STDOUT: +// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5} +// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3} +// CHECK:STDOUT: !2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !3 = !DIFile(filename: "todo_import_inline_function_decl.carbon", directory: "") +// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "MyF", linkageName: "_CMyF.Main", scope: null, file: !3, line: 6, type: !5, spFlags: DISPFlagDefinition, unit: !2) +// CHECK:STDOUT: !5 = !DISubroutineType(types: !6) +// CHECK:STDOUT: !6 = !{} +// CHECK:STDOUT: !7 = !DILocation(line: 8, column: 3, scope: !4) +// CHECK:STDOUT: !8 = !DILocation(line: 6, column: 1, scope: !4)