From 8edd5eb9a15798c9c0f632132e8571916c450eeb Mon Sep 17 00:00:00 2001 From: little Kitchen <55852668+littleKitchen@users.noreply.github.com> Date: Tue, 24 Feb 2026 10:19:50 -0800 Subject: [PATCH] fix: reject {} initialization for non-aggregate C++ classes (#6675) ## Summary Fixes the toolchain incorrectly allowing `{}` initialization for non-aggregate C++ classes. ## Problem When importing an empty C++ class, the toolchain was treating it as a Carbon empty struct, which allowed initialization from `{}`. This is incorrect for non-aggregate classes (e.g., those with user-declared constructors). ```carbon import Cpp inline ''' struct X { X(); }; // non-aggregate (has user-declared constructor) '''; fn Make() { var x: Cpp.X = {}; // incorrectly accepted, should be rejected } ``` ## Solution Added a check for `clang_def->isAggregate()` in `ImportClassObjectRepr` so that only aggregate classes get the empty struct representation. **Before:** ```cpp if (clang_def->isEmpty() && !clang_def->getNumBases()) { ``` **After:** ```cpp if (clang_def->isEmpty() && !clang_def->getNumBases() && clang_def->isAggregate()) { ``` ## Testing Added test file `toolchain/check/testdata/interop/cpp/class/non_aggregate_init.carbon` with: - Non-aggregate class (`struct X { X(); }`) - should reject `{}` initialization - Aggregate class (`struct Y {}`) - should accept `{}` initialization Note: I couldn't run tests locally due to clang version requirements (needs >= 19, have 17). The CI should validate the changes. Closes #6669 --------- Co-authored-by: Richard Smith --- toolchain/check/cpp/import.cpp | 11 +- .../cpp/class/non_aggregate_init.carbon | 60 ++++++ .../interop/cpp/impls/implicit_as.carbon | 179 +++++------------- .../testdata/interop/cpp/constructor.carbon | 125 ++++++------ .../interop/cpp/std_initializer_list.carbon | 22 +-- 5 files changed, 181 insertions(+), 216 deletions(-) create mode 100644 toolchain/check/testdata/interop/cpp/class/non_aggregate_init.carbon diff --git a/toolchain/check/cpp/import.cpp b/toolchain/check/cpp/import.cpp index 4adfb0169b54..11161d84a9b1 100644 --- a/toolchain/check/cpp/import.cpp +++ b/toolchain/check/cpp/import.cpp @@ -429,11 +429,14 @@ static auto ImportClassObjectRepr(Context& context, SemIR::ClassId class_id, return SemIR::ErrorInst::TypeInstId; } - // For now, if the class is empty, produce an empty struct as the object - // representation. This allows our tests to continue to pass while we don't - // properly support initializing imported C++ classes. + // For now, if the class is empty and an aggregate, produce an empty struct as + // the object representation. This allows our tests to continue to pass while + // we don't properly support initializing imported C++ classes. We only do + // this for aggregates so that non-aggregate classes are not incorrectly + // initializable from `{}`. // TODO: Remove this. - if (clang_def->isEmpty() && !clang_def->getNumBases()) { + if (clang_def->isEmpty() && !clang_def->getNumBases() && + clang_def->isAggregate()) { return context.types().GetAsTypeInstId(AddInst( context, MakeImportedLocIdAndInst( diff --git a/toolchain/check/testdata/interop/cpp/class/non_aggregate_init.carbon b/toolchain/check/testdata/interop/cpp/class/non_aggregate_init.carbon new file mode 100644 index 000000000000..7e86fd80f8ce --- /dev/null +++ b/toolchain/check/testdata/interop/cpp/class/non_aggregate_init.carbon @@ -0,0 +1,60 @@ +// 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/primitives.carbon +// EXTRA-ARGS: --target=x86_64-linux-gnu --clang-arg=-std=c++20 +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/class/non_aggregate_init.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/class/non_aggregate_init.carbon + +// ============================================================================ +// Non-aggregate class should not be initializable from {} +// ============================================================================ + +// --- non_aggregate.h + +// A class with a user-declared constructor is not an aggregate. +struct X { + X(); +}; + +// --- fail_non_aggregate_init.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "non_aggregate.h"; + +fn Make() { + // CHECK:STDERR: fail_non_aggregate_init.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `{}` to `Cpp.X` [ConversionFailure] + // CHECK:STDERR: var _: Cpp.X = {}; + // CHECK:STDERR: ^~~~~~~~~~~~ + // CHECK:STDERR: fail_non_aggregate_init.carbon:[[@LINE+4]]:3: note: type `{}` does not implement interface `Core.ImplicitAs(Cpp.X)` [MissingImplInMemberAccessNote] + // CHECK:STDERR: var _: Cpp.X = {}; + // CHECK:STDERR: ^~~~~~~~~~~~ + // CHECK:STDERR: + var _: Cpp.X = {}; +} + +// ============================================================================ +// Aggregate class should be initializable from {} +// ============================================================================ + +// --- aggregate.h + +// A class with no user-declared constructors is an aggregate. +struct Y {}; + +// --- aggregate_init.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "aggregate.h"; + +fn Make() { + // This should succeed because Y is an aggregate. + var _: Cpp.Y = {}; +} diff --git a/toolchain/check/testdata/interop/cpp/impls/implicit_as.carbon b/toolchain/check/testdata/interop/cpp/impls/implicit_as.carbon index 90b79289a490..640597763506 100644 --- a/toolchain/check/testdata/interop/cpp/impls/implicit_as.carbon +++ b/toolchain/check/testdata/interop/cpp/impls/implicit_as.carbon @@ -252,10 +252,6 @@ fn DefaultConstructorTest() { //@dump-sem-ir-begin // OK, empty tuple maps to `{}` initializer list. let _: Cpp.DefaultConstructor = (); - - // OK: empty struct maps to `{}` initializer list, which is an acceptable - // constructor call, even though a non-empty struct would not be. - let _: Cpp.DefaultConstructor = {}; //@dump-sem-ir-end } @@ -380,21 +376,6 @@ fn InitFromStruct() { //@dump-sem-ir-end } -// --- todo_fail_non_aggregate_from_empty_struct.carbon - -library "[[@TEST_NAME]]"; - -import Cpp library "aggregate.h"; - -// TODO: This should be rejected; we should only support initialization from a -// struct for an aggregate class. - -fn InitFromStruct() { - //@dump-sem-ir-begin - let _: Cpp.NonAggregate = {}; - //@dump-sem-ir-end -} - // --- fail_non_aggregate_from_struct.carbon library "[[@TEST_NAME]]"; @@ -403,13 +384,26 @@ import Cpp library "aggregate.h"; fn InitFromStruct() { //@dump-sem-ir-begin + // CHECK:STDERR: fail_non_aggregate_from_struct.carbon:[[@LINE+7]]:29: error: cannot implicitly convert expression of type `{}` to `Cpp.NonAggregate` [ConversionFailure] + // CHECK:STDERR: let _: Cpp.NonAggregate = {}; + // CHECK:STDERR: ^~ + // CHECK:STDERR: fail_non_aggregate_from_struct.carbon:[[@LINE+4]]:29: note: type `{}` does not implement interface `Core.ImplicitAs(Cpp.NonAggregate)` [MissingImplInMemberAccessNote] + // CHECK:STDERR: let _: Cpp.NonAggregate = {}; + // CHECK:STDERR: ^~ + // CHECK:STDERR: let _: Cpp.NonAggregate = {}; - // CHECK:STDERR: fail_non_aggregate_from_struct.carbon:[[@LINE+4]]:29: error: cannot initialize class with 0 fields from struct with 1 field [StructInitElementCountMismatch] + // CHECK:STDERR: fail_non_aggregate_from_struct.carbon:[[@LINE+7]]:29: error: cannot implicitly convert expression of type `{.x: Core.IntLiteral}` to `Cpp.NonAggregate` [ConversionFailure] + // CHECK:STDERR: let _: Cpp.NonAggregate = {.x = 1}; + // CHECK:STDERR: ^~~~~~~~ + // CHECK:STDERR: fail_non_aggregate_from_struct.carbon:[[@LINE+4]]:29: note: type `{.x: Core.IntLiteral}` does not implement interface `Core.ImplicitAs(Cpp.NonAggregate)` [MissingImplInMemberAccessNote] // CHECK:STDERR: let _: Cpp.NonAggregate = {.x = 1}; // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: let _: Cpp.NonAggregate = {.x = 1}; - // CHECK:STDERR: fail_non_aggregate_from_struct.carbon:[[@LINE+4]]:29: error: cannot initialize class with 0 fields from struct with 2 fields [StructInitElementCountMismatch] + // CHECK:STDERR: fail_non_aggregate_from_struct.carbon:[[@LINE+7]]:29: error: cannot implicitly convert expression of type `{.x: Core.IntLiteral, .y: Core.IntLiteral}` to `Cpp.NonAggregate` [ConversionFailure] + // CHECK:STDERR: let _: Cpp.NonAggregate = {.x = 1, .y = 2}; + // CHECK:STDERR: ^~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_non_aggregate_from_struct.carbon:[[@LINE+4]]:29: note: type `{.x: Core.IntLiteral, .y: Core.IntLiteral}` does not implement interface `Core.ImplicitAs(Cpp.NonAggregate)` [MissingImplInMemberAccessNote] // CHECK:STDERR: let _: Cpp.NonAggregate = {.x = 1, .y = 2}; // CHECK:STDERR: ^~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -963,14 +957,11 @@ fn InitFromStruct() { // CHECK:STDOUT: constants { // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %DefaultConstructor: type = class_type @DefaultConstructor [concrete] -// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] // CHECK:STDOUT: %pattern_type.b66: type = pattern_type %DefaultConstructor [concrete] // CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete] // CHECK:STDOUT: %ptr.3f7: type = ptr_type %DefaultConstructor [concrete] // CHECK:STDOUT: %DefaultConstructor__carbon_thunk.type: type = fn_type @DefaultConstructor__carbon_thunk [concrete] // CHECK:STDOUT: %DefaultConstructor__carbon_thunk: %DefaultConstructor__carbon_thunk.type = struct_value () [concrete] -// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete] -// CHECK:STDOUT: %DefaultConstructor.val: %DefaultConstructor = struct_value () [concrete] // CHECK:STDOUT: %DefaultConstructor.cpp_destructor.type: type = fn_type @DefaultConstructor.cpp_destructor [concrete] // CHECK:STDOUT: %DefaultConstructor.cpp_destructor: %DefaultConstructor.cpp_destructor.type = struct_value () [concrete] // CHECK:STDOUT: } @@ -991,12 +982,12 @@ fn InitFromStruct() { // CHECK:STDOUT: fn @DefaultConstructorTest() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: name_binding_decl { -// CHECK:STDOUT: %_.patt.loc9: %pattern_type.b66 = value_binding_pattern _ [concrete] +// CHECK:STDOUT: %_.patt: %pattern_type.b66 = value_binding_pattern _ [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: %.loc9_36.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple] -// CHECK:STDOUT: %.loc9_13: type = splice_block %DefaultConstructor.ref.loc9 [concrete = constants.%DefaultConstructor] { -// CHECK:STDOUT: %Cpp.ref.loc9: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %DefaultConstructor.ref.loc9: type = name_ref DefaultConstructor, imports.%DefaultConstructor.decl [concrete = constants.%DefaultConstructor] +// CHECK:STDOUT: %.loc9_13: type = splice_block %DefaultConstructor.ref [concrete = constants.%DefaultConstructor] { +// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %DefaultConstructor.ref: type = name_ref DefaultConstructor, imports.%DefaultConstructor.decl [concrete = constants.%DefaultConstructor] // CHECK:STDOUT: } // CHECK:STDOUT: %.loc9_36.2: ref %DefaultConstructor = temporary_storage // CHECK:STDOUT: %addr: %ptr.3f7 = addr_of %.loc9_36.2 @@ -1005,25 +996,9 @@ fn InitFromStruct() { // CHECK:STDOUT: %.loc9_36.4: init %DefaultConstructor = converted %.loc9_36.1, %.loc9_36.3 // CHECK:STDOUT: %.loc9_36.5: ref %DefaultConstructor = temporary %.loc9_36.2, %.loc9_36.4 // CHECK:STDOUT: %.loc9_36.6: %DefaultConstructor = acquire_value %.loc9_36.5 -// CHECK:STDOUT: %_.loc9: %DefaultConstructor = value_binding _, %.loc9_36.6 -// CHECK:STDOUT: name_binding_decl { -// CHECK:STDOUT: %_.patt.loc13: %pattern_type.b66 = value_binding_pattern _ [concrete] -// CHECK:STDOUT: } -// CHECK:STDOUT: %.loc13_36.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] -// CHECK:STDOUT: %.loc13_13: type = splice_block %DefaultConstructor.ref.loc13 [concrete = constants.%DefaultConstructor] { -// CHECK:STDOUT: %Cpp.ref.loc13: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %DefaultConstructor.ref.loc13: type = name_ref DefaultConstructor, imports.%DefaultConstructor.decl [concrete = constants.%DefaultConstructor] -// CHECK:STDOUT: } -// CHECK:STDOUT: %.loc13_36.2: ref %DefaultConstructor = temporary_storage -// CHECK:STDOUT: %.loc13_36.3: init %DefaultConstructor to %.loc13_36.2 = class_init () [concrete = constants.%DefaultConstructor.val] -// CHECK:STDOUT: %.loc13_36.4: ref %DefaultConstructor = temporary %.loc13_36.2, %.loc13_36.3 -// CHECK:STDOUT: %.loc13_36.5: ref %DefaultConstructor = converted %.loc13_36.1, %.loc13_36.4 -// CHECK:STDOUT: %.loc13_36.6: %DefaultConstructor = acquire_value %.loc13_36.5 -// CHECK:STDOUT: %_.loc13: %DefaultConstructor = value_binding _, %.loc13_36.6 -// CHECK:STDOUT: %DefaultConstructor.cpp_destructor.bound.loc13: = bound_method %.loc13_36.4, constants.%DefaultConstructor.cpp_destructor -// CHECK:STDOUT: %DefaultConstructor.cpp_destructor.call.loc13: init %empty_tuple.type = call %DefaultConstructor.cpp_destructor.bound.loc13(%.loc13_36.4) -// CHECK:STDOUT: %DefaultConstructor.cpp_destructor.bound.loc9: = bound_method %.loc9_36.5, constants.%DefaultConstructor.cpp_destructor -// CHECK:STDOUT: %DefaultConstructor.cpp_destructor.call.loc9: init %empty_tuple.type = call %DefaultConstructor.cpp_destructor.bound.loc9(%.loc9_36.5) +// CHECK:STDOUT: %_: %DefaultConstructor = value_binding _, %.loc9_36.6 +// CHECK:STDOUT: %DefaultConstructor.cpp_destructor.bound: = bound_method %.loc9_36.5, constants.%DefaultConstructor.cpp_destructor +// CHECK:STDOUT: %DefaultConstructor.cpp_destructor.call: init %empty_tuple.type = call %DefaultConstructor.cpp_destructor.bound(%.loc9_36.5) // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: @@ -1493,65 +1468,19 @@ fn InitFromStruct() { // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- todo_fail_non_aggregate_from_empty_struct.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] -// CHECK:STDOUT: %NonAggregate: type = class_type @NonAggregate [concrete] -// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] -// CHECK:STDOUT: %pattern_type.eac: type = pattern_type %NonAggregate [concrete] -// CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete] -// CHECK:STDOUT: %NonAggregate.val: %NonAggregate = struct_value () [concrete] -// CHECK:STDOUT: %NonAggregate.cpp_destructor.type: type = fn_type @NonAggregate.cpp_destructor [concrete] -// CHECK:STDOUT: %NonAggregate.cpp_destructor: %NonAggregate.cpp_destructor.type = struct_value () [concrete] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { -// CHECK:STDOUT: .NonAggregate = %NonAggregate.decl -// CHECK:STDOUT: import Cpp//... -// CHECK:STDOUT: } -// CHECK:STDOUT: %NonAggregate.decl: type = class_decl @NonAggregate [concrete = constants.%NonAggregate] {} {} -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @InitFromStruct() { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: name_binding_decl { -// CHECK:STDOUT: %_.patt: %pattern_type.eac = value_binding_pattern _ [concrete] -// CHECK:STDOUT: } -// CHECK:STDOUT: %.loc11_30.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] -// CHECK:STDOUT: %.loc11_13: type = splice_block %NonAggregate.ref [concrete = constants.%NonAggregate] { -// CHECK:STDOUT: %Cpp.ref: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %NonAggregate.ref: type = name_ref NonAggregate, imports.%NonAggregate.decl [concrete = constants.%NonAggregate] -// CHECK:STDOUT: } -// CHECK:STDOUT: %.loc11_30.2: ref %NonAggregate = temporary_storage -// CHECK:STDOUT: %.loc11_30.3: init %NonAggregate to %.loc11_30.2 = class_init () [concrete = constants.%NonAggregate.val] -// CHECK:STDOUT: %.loc11_30.4: ref %NonAggregate = temporary %.loc11_30.2, %.loc11_30.3 -// CHECK:STDOUT: %.loc11_30.5: ref %NonAggregate = converted %.loc11_30.1, %.loc11_30.4 -// CHECK:STDOUT: %.loc11_30.6: %NonAggregate = acquire_value %.loc11_30.5 -// CHECK:STDOUT: %_: %NonAggregate = value_binding _, %.loc11_30.6 -// CHECK:STDOUT: %NonAggregate.cpp_destructor.bound: = bound_method %.loc11_30.4, constants.%NonAggregate.cpp_destructor -// CHECK:STDOUT: %NonAggregate.cpp_destructor.call: init %empty_tuple.type = call %NonAggregate.cpp_destructor.bound(%.loc11_30.4) -// CHECK:STDOUT: -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: --- fail_non_aggregate_from_struct.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %NonAggregate: type = class_type @NonAggregate [concrete] -// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] // CHECK:STDOUT: %pattern_type.eac: type = pattern_type %NonAggregate [concrete] +// CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] // CHECK:STDOUT: %empty_struct: %empty_struct_type = struct_value () [concrete] -// CHECK:STDOUT: %NonAggregate.val: %NonAggregate = struct_value () [concrete] // CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete] // CHECK:STDOUT: %struct_type.x: type = struct_type {.x: Core.IntLiteral} [concrete] // CHECK:STDOUT: %struct.147: %struct_type.x = struct_value (%int_1) [concrete] // CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete] // CHECK:STDOUT: %struct_type.x.y: type = struct_type {.x: Core.IntLiteral, .y: Core.IntLiteral} [concrete] // CHECK:STDOUT: %struct.004: %struct_type.x.y = struct_value (%int_1, %int_2) [concrete] -// CHECK:STDOUT: %NonAggregate.cpp_destructor.type: type = fn_type @NonAggregate.cpp_destructor [concrete] -// CHECK:STDOUT: %NonAggregate.cpp_destructor: %NonAggregate.cpp_destructor.type = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -1565,54 +1494,38 @@ fn InitFromStruct() { // CHECK:STDOUT: fn @InitFromStruct() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: name_binding_decl { -// CHECK:STDOUT: %_.patt.loc8: %pattern_type.eac = value_binding_pattern _ [concrete] +// CHECK:STDOUT: %_.patt.loc15: %pattern_type.eac = value_binding_pattern _ [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc8_30.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] -// CHECK:STDOUT: %.loc8_13: type = splice_block %NonAggregate.ref.loc8 [concrete = constants.%NonAggregate] { -// CHECK:STDOUT: %Cpp.ref.loc8: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %NonAggregate.ref.loc8: type = name_ref NonAggregate, imports.%NonAggregate.decl [concrete = constants.%NonAggregate] +// CHECK:STDOUT: %.loc15_30.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] +// CHECK:STDOUT: %.loc15_13: type = splice_block %NonAggregate.ref.loc15 [concrete = constants.%NonAggregate] { +// CHECK:STDOUT: %Cpp.ref.loc15: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %NonAggregate.ref.loc15: type = name_ref NonAggregate, imports.%NonAggregate.decl [concrete = constants.%NonAggregate] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc8_30.2: ref %NonAggregate = temporary_storage -// CHECK:STDOUT: %.loc8_30.3: init %NonAggregate to %.loc8_30.2 = class_init () [concrete = constants.%NonAggregate.val] -// CHECK:STDOUT: %.loc8_30.4: ref %NonAggregate = temporary %.loc8_30.2, %.loc8_30.3 -// CHECK:STDOUT: %.loc8_30.5: ref %NonAggregate = converted %.loc8_30.1, %.loc8_30.4 -// CHECK:STDOUT: %.loc8_30.6: %NonAggregate = acquire_value %.loc8_30.5 -// CHECK:STDOUT: %_.loc8: %NonAggregate = value_binding _, %.loc8_30.6 +// CHECK:STDOUT: %.loc15_30.2: %NonAggregate = converted %.loc15_30.1, [concrete = ] +// CHECK:STDOUT: %_.loc15: %NonAggregate = value_binding _, [concrete = ] // CHECK:STDOUT: name_binding_decl { -// CHECK:STDOUT: %_.patt.loc13: %pattern_type.eac = value_binding_pattern _ [concrete] +// CHECK:STDOUT: %_.patt.loc23: %pattern_type.eac = value_binding_pattern _ [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %int_1.loc13: Core.IntLiteral = int_value 1 [concrete = constants.%int_1] -// CHECK:STDOUT: %.loc13_36.1: %struct_type.x = struct_literal (%int_1.loc13) [concrete = constants.%struct.147] -// CHECK:STDOUT: %.loc13_13: type = splice_block %NonAggregate.ref.loc13 [concrete = constants.%NonAggregate] { -// CHECK:STDOUT: %Cpp.ref.loc13: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %NonAggregate.ref.loc13: type = name_ref NonAggregate, imports.%NonAggregate.decl [concrete = constants.%NonAggregate] +// CHECK:STDOUT: %int_1.loc23: Core.IntLiteral = int_value 1 [concrete = constants.%int_1] +// CHECK:STDOUT: %.loc23_36.1: %struct_type.x = struct_literal (%int_1.loc23) [concrete = constants.%struct.147] +// CHECK:STDOUT: %.loc23_13: type = splice_block %NonAggregate.ref.loc23 [concrete = constants.%NonAggregate] { +// CHECK:STDOUT: %Cpp.ref.loc23: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %NonAggregate.ref.loc23: type = name_ref NonAggregate, imports.%NonAggregate.decl [concrete = constants.%NonAggregate] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc13_36.2: ref %NonAggregate = temporary_storage -// CHECK:STDOUT: %.loc13_36.3: ref %NonAggregate = temporary %.loc13_36.2, -// CHECK:STDOUT: %.loc13_36.4: ref %NonAggregate = converted %.loc13_36.1, %.loc13_36.3 -// CHECK:STDOUT: %.loc13_36.5: %NonAggregate = acquire_value %.loc13_36.4 -// CHECK:STDOUT: %_.loc13: %NonAggregate = value_binding _, %.loc13_36.5 +// CHECK:STDOUT: %.loc23_36.2: %NonAggregate = converted %.loc23_36.1, [concrete = ] +// CHECK:STDOUT: %_.loc23: %NonAggregate = value_binding _, [concrete = ] // CHECK:STDOUT: name_binding_decl { -// CHECK:STDOUT: %_.patt.loc18: %pattern_type.eac = value_binding_pattern _ [concrete] +// CHECK:STDOUT: %_.patt.loc31: %pattern_type.eac = value_binding_pattern _ [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %int_1.loc18: Core.IntLiteral = int_value 1 [concrete = constants.%int_1] +// CHECK:STDOUT: %int_1.loc31: Core.IntLiteral = int_value 1 [concrete = constants.%int_1] // CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2] -// CHECK:STDOUT: %.loc18_44.1: %struct_type.x.y = struct_literal (%int_1.loc18, %int_2) [concrete = constants.%struct.004] -// CHECK:STDOUT: %.loc18_13: type = splice_block %NonAggregate.ref.loc18 [concrete = constants.%NonAggregate] { -// CHECK:STDOUT: %Cpp.ref.loc18: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] -// CHECK:STDOUT: %NonAggregate.ref.loc18: type = name_ref NonAggregate, imports.%NonAggregate.decl [concrete = constants.%NonAggregate] +// CHECK:STDOUT: %.loc31_44.1: %struct_type.x.y = struct_literal (%int_1.loc31, %int_2) [concrete = constants.%struct.004] +// CHECK:STDOUT: %.loc31_13: type = splice_block %NonAggregate.ref.loc31 [concrete = constants.%NonAggregate] { +// CHECK:STDOUT: %Cpp.ref.loc31: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %NonAggregate.ref.loc31: type = name_ref NonAggregate, imports.%NonAggregate.decl [concrete = constants.%NonAggregate] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc18_44.2: ref %NonAggregate = temporary_storage -// CHECK:STDOUT: %.loc18_44.3: ref %NonAggregate = temporary %.loc18_44.2, -// CHECK:STDOUT: %.loc18_44.4: ref %NonAggregate = converted %.loc18_44.1, %.loc18_44.3 -// CHECK:STDOUT: %.loc18_44.5: %NonAggregate = acquire_value %.loc18_44.4 -// CHECK:STDOUT: %_.loc18: %NonAggregate = value_binding _, %.loc18_44.5 -// CHECK:STDOUT: %NonAggregate.cpp_destructor.bound.loc18: = bound_method %.loc18_44.3, constants.%NonAggregate.cpp_destructor -// CHECK:STDOUT: %NonAggregate.cpp_destructor.call.loc18: init %empty_tuple.type = call %NonAggregate.cpp_destructor.bound.loc18(%.loc18_44.3) -// CHECK:STDOUT: %NonAggregate.cpp_destructor.bound.loc13: = bound_method %.loc13_36.3, constants.%NonAggregate.cpp_destructor -// CHECK:STDOUT: %NonAggregate.cpp_destructor.call.loc13: init %empty_tuple.type = call %NonAggregate.cpp_destructor.bound.loc13(%.loc13_36.3) -// CHECK:STDOUT: %NonAggregate.cpp_destructor.bound.loc8: = bound_method %.loc8_30.4, constants.%NonAggregate.cpp_destructor -// CHECK:STDOUT: %NonAggregate.cpp_destructor.call.loc8: init %empty_tuple.type = call %NonAggregate.cpp_destructor.bound.loc8(%.loc8_30.4) +// CHECK:STDOUT: %.loc31_44.2: %NonAggregate = converted %.loc31_44.1, [concrete = ] +// CHECK:STDOUT: %_.loc31: %NonAggregate = value_binding _, [concrete = ] // CHECK:STDOUT: // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/lower/testdata/interop/cpp/constructor.carbon b/toolchain/lower/testdata/interop/cpp/constructor.carbon index 583df15b0e84..625b66e030f1 100644 --- a/toolchain/lower/testdata/interop/cpp/constructor.carbon +++ b/toolchain/lower/testdata/interop/cpp/constructor.carbon @@ -107,7 +107,6 @@ import Cpp library "multi_argument.h"; fn Zero() { let _: Cpp.C = Cpp.C.C(); let _: Cpp.C = (); - let _: Cpp.C = {}; } fn One() { @@ -417,8 +416,6 @@ fn Four() { // CHECK:STDOUT: // CHECK:STDOUT: $_ZN1CC2Eiiii = comdat any // CHECK:STDOUT: -// CHECK:STDOUT: @C.val.loc9_19.3 = internal constant {} zeroinitializer -// CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable // CHECK:STDOUT: define dso_local void @_ZN1CC1Ev.carbon_thunk(ptr noundef %return) #0 { // CHECK:STDOUT: entry: @@ -632,87 +629,80 @@ fn Four() { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CZero.Main() #2 !dbg !15 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %.loc7_26.1.temp = alloca {}, align 8, !dbg !18 -// CHECK:STDOUT: %.loc8_19.2.temp = alloca {}, align 8, !dbg !19 -// CHECK:STDOUT: %.loc9_19.2.temp = alloca {}, align 8, !dbg !20 +// CHECK:STDOUT: %.loc7_26.1.temp = alloca [1 x i8], align 1, !dbg !18 +// CHECK:STDOUT: %.loc8_19.2.temp = alloca [1 x i8], align 1, !dbg !19 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_26.1.temp), !dbg !18 // CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk(ptr %.loc7_26.1.temp), !dbg !18 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc8_19.2.temp), !dbg !19 // CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk_tuple(ptr %.loc8_19.2.temp), !dbg !19 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc9_19.2.temp), !dbg !20 -// CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %.loc9_19.2.temp, ptr align 1 @C.val.loc9_19.3, i64 0, i1 false), !dbg !20 -// CHECK:STDOUT: ret void, !dbg !21 +// CHECK:STDOUT: ret void, !dbg !20 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define void @_COne.Main() #2 !dbg !22 { +// CHECK:STDOUT: define void @_COne.Main() #2 !dbg !21 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %.loc13_27.1.temp = alloca {}, align 8, !dbg !23 -// CHECK:STDOUT: %.loc14_18.1.temp = alloca {}, align 8, !dbg !24 -// CHECK:STDOUT: %.loc15_21.2.temp = alloca {}, align 8, !dbg !25 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc13_27.1.temp), !dbg !23 -// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk(i32 1, ptr %.loc13_27.1.temp), !dbg !23 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc14_18.1.temp), !dbg !24 -// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk(i32 2, ptr %.loc14_18.1.temp), !dbg !24 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc15_21.2.temp), !dbg !25 -// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk_tuple(i32 3, ptr %.loc15_21.2.temp), !dbg !25 -// CHECK:STDOUT: ret void, !dbg !26 +// CHECK:STDOUT: %.loc12_27.1.temp = alloca [1 x i8], align 1, !dbg !22 +// CHECK:STDOUT: %.loc13_18.1.temp = alloca [1 x i8], align 1, !dbg !23 +// CHECK:STDOUT: %.loc14_21.2.temp = alloca [1 x i8], align 1, !dbg !24 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc12_27.1.temp), !dbg !22 +// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk(i32 1, ptr %.loc12_27.1.temp), !dbg !22 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc13_18.1.temp), !dbg !23 +// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk(i32 2, ptr %.loc13_18.1.temp), !dbg !23 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc14_21.2.temp), !dbg !24 +// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk_tuple(i32 3, ptr %.loc14_21.2.temp), !dbg !24 +// CHECK:STDOUT: ret void, !dbg !25 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define void @_CTwo.Main() #2 !dbg !27 { +// CHECK:STDOUT: define void @_CTwo.Main() #2 !dbg !26 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %.loc19_30.1.temp = alloca {}, align 8, !dbg !28 -// CHECK:STDOUT: %.loc20_23.2.temp = alloca {}, align 8, !dbg !29 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc19_30.1.temp), !dbg !28 -// CHECK:STDOUT: call void @_ZN1CC1Eii.carbon_thunk(i32 1, i32 2, ptr %.loc19_30.1.temp), !dbg !28 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc20_23.2.temp), !dbg !29 -// CHECK:STDOUT: call void @_ZN1CC1Eii.carbon_thunk_tuple(i32 3, i32 4, ptr %.loc20_23.2.temp), !dbg !29 -// CHECK:STDOUT: ret void, !dbg !30 +// CHECK:STDOUT: %.loc18_30.1.temp = alloca [1 x i8], align 1, !dbg !27 +// CHECK:STDOUT: %.loc19_23.2.temp = alloca [1 x i8], align 1, !dbg !28 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc18_30.1.temp), !dbg !27 +// CHECK:STDOUT: call void @_ZN1CC1Eii.carbon_thunk(i32 1, i32 2, ptr %.loc18_30.1.temp), !dbg !27 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc19_23.2.temp), !dbg !28 +// CHECK:STDOUT: call void @_ZN1CC1Eii.carbon_thunk_tuple(i32 3, i32 4, ptr %.loc19_23.2.temp), !dbg !28 +// CHECK:STDOUT: ret void, !dbg !29 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define void @_CThree.Main() #2 !dbg !31 { +// CHECK:STDOUT: define void @_CThree.Main() #2 !dbg !30 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %.loc24_33.1.temp = alloca {}, align 8, !dbg !32 -// CHECK:STDOUT: %.loc25_26.2.temp = alloca {}, align 8, !dbg !33 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc24_33.1.temp), !dbg !32 -// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk3(i32 1, i32 2, i32 3, ptr %.loc24_33.1.temp), !dbg !32 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc25_26.2.temp), !dbg !33 -// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk_tuple3(i32 4, i32 5, i32 6, ptr %.loc25_26.2.temp), !dbg !33 -// CHECK:STDOUT: ret void, !dbg !34 +// CHECK:STDOUT: %.loc23_33.1.temp = alloca [1 x i8], align 1, !dbg !31 +// CHECK:STDOUT: %.loc24_26.2.temp = alloca [1 x i8], align 1, !dbg !32 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc23_33.1.temp), !dbg !31 +// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk3(i32 1, i32 2, i32 3, ptr %.loc23_33.1.temp), !dbg !31 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc24_26.2.temp), !dbg !32 +// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk_tuple3(i32 4, i32 5, i32 6, ptr %.loc24_26.2.temp), !dbg !32 +// CHECK:STDOUT: ret void, !dbg !33 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define void @_CFour.Main() #2 !dbg !35 { +// CHECK:STDOUT: define void @_CFour.Main() #2 !dbg !34 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %.loc29_36.1.temp = alloca {}, align 8, !dbg !36 -// CHECK:STDOUT: %.loc30_29.2.temp = alloca {}, align 8, !dbg !37 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc29_36.1.temp), !dbg !36 -// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk(i32 1, i32 2, i32 3, i32 4, ptr %.loc29_36.1.temp), !dbg !36 -// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc30_29.2.temp), !dbg !37 -// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk_tuple(i32 5, i32 6, i32 7, i32 8, ptr %.loc30_29.2.temp), !dbg !37 -// CHECK:STDOUT: ret void, !dbg !38 +// CHECK:STDOUT: %.loc28_36.1.temp = alloca [1 x i8], align 1, !dbg !35 +// CHECK:STDOUT: %.loc29_29.2.temp = alloca [1 x i8], align 1, !dbg !36 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc28_36.1.temp), !dbg !35 +// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk(i32 1, i32 2, i32 3, i32 4, ptr %.loc28_36.1.temp), !dbg !35 +// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc29_29.2.temp), !dbg !36 +// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk_tuple(i32 5, i32 6, i32 7, i32 8, ptr %.loc29_29.2.temp), !dbg !36 +// CHECK:STDOUT: ret void, !dbg !37 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) // CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #3 // CHECK:STDOUT: -// CHECK:STDOUT: ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite) -// CHECK:STDOUT: declare void @llvm.memcpy.p0.p0.i64(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i64, i1 immarg) #4 -// CHECK:STDOUT: // CHECK:STDOUT: ; uselistorder directives // CHECK:STDOUT: uselistorder ptr @_ZN1CC2Ev, { 1, 0 } // CHECK:STDOUT: uselistorder ptr @_ZN1CC2Ei, { 1, 0 } // CHECK:STDOUT: uselistorder ptr @_ZN1CC2Eii, { 1, 0 } // CHECK:STDOUT: uselistorder ptr @_ZN1CC2Eiiii, { 3, 2, 1, 0 } -// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 } +// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 } // CHECK:STDOUT: // CHECK:STDOUT: attributes #0 = { alwaysinline mustprogress uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: attributes #1 = { mustprogress nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } // CHECK:STDOUT: attributes #2 = { nounwind } // CHECK:STDOUT: attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } -// CHECK:STDOUT: attributes #4 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } // CHECK:STDOUT: // CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4, !5} // CHECK:STDOUT: !llvm.dbg.cu = !{!6} @@ -738,22 +728,21 @@ fn Four() { // CHECK:STDOUT: !17 = !{null} // CHECK:STDOUT: !18 = !DILocation(line: 7, column: 18, scope: !15) // CHECK:STDOUT: !19 = !DILocation(line: 8, column: 18, scope: !15) -// CHECK:STDOUT: !20 = !DILocation(line: 9, column: 18, scope: !15) -// CHECK:STDOUT: !21 = !DILocation(line: 6, column: 1, scope: !15) -// CHECK:STDOUT: !22 = distinct !DISubprogram(name: "One", linkageName: "_COne.Main", scope: null, file: !7, line: 12, type: !16, spFlags: DISPFlagDefinition, unit: !6) -// CHECK:STDOUT: !23 = !DILocation(line: 13, column: 18, scope: !22) -// CHECK:STDOUT: !24 = !DILocation(line: 14, column: 18, scope: !22) -// CHECK:STDOUT: !25 = !DILocation(line: 15, column: 18, scope: !22) -// CHECK:STDOUT: !26 = !DILocation(line: 12, column: 1, scope: !22) -// CHECK:STDOUT: !27 = distinct !DISubprogram(name: "Two", linkageName: "_CTwo.Main", scope: null, file: !7, line: 18, type: !16, spFlags: DISPFlagDefinition, unit: !6) -// CHECK:STDOUT: !28 = !DILocation(line: 19, column: 18, scope: !27) -// CHECK:STDOUT: !29 = !DILocation(line: 20, column: 18, scope: !27) -// CHECK:STDOUT: !30 = !DILocation(line: 18, column: 1, scope: !27) -// CHECK:STDOUT: !31 = distinct !DISubprogram(name: "Three", linkageName: "_CThree.Main", scope: null, file: !7, line: 23, type: !16, spFlags: DISPFlagDefinition, unit: !6) -// CHECK:STDOUT: !32 = !DILocation(line: 24, column: 18, scope: !31) -// CHECK:STDOUT: !33 = !DILocation(line: 25, column: 18, scope: !31) -// CHECK:STDOUT: !34 = !DILocation(line: 23, column: 1, scope: !31) -// CHECK:STDOUT: !35 = distinct !DISubprogram(name: "Four", linkageName: "_CFour.Main", scope: null, file: !7, line: 28, type: !16, spFlags: DISPFlagDefinition, unit: !6) -// CHECK:STDOUT: !36 = !DILocation(line: 29, column: 18, scope: !35) -// CHECK:STDOUT: !37 = !DILocation(line: 30, column: 18, scope: !35) -// CHECK:STDOUT: !38 = !DILocation(line: 28, column: 1, scope: !35) +// CHECK:STDOUT: !20 = !DILocation(line: 6, column: 1, scope: !15) +// CHECK:STDOUT: !21 = distinct !DISubprogram(name: "One", linkageName: "_COne.Main", scope: null, file: !7, line: 11, type: !16, spFlags: DISPFlagDefinition, unit: !6) +// CHECK:STDOUT: !22 = !DILocation(line: 12, column: 18, scope: !21) +// CHECK:STDOUT: !23 = !DILocation(line: 13, column: 18, scope: !21) +// CHECK:STDOUT: !24 = !DILocation(line: 14, column: 18, scope: !21) +// CHECK:STDOUT: !25 = !DILocation(line: 11, column: 1, scope: !21) +// CHECK:STDOUT: !26 = distinct !DISubprogram(name: "Two", linkageName: "_CTwo.Main", scope: null, file: !7, line: 17, type: !16, spFlags: DISPFlagDefinition, unit: !6) +// CHECK:STDOUT: !27 = !DILocation(line: 18, column: 18, scope: !26) +// CHECK:STDOUT: !28 = !DILocation(line: 19, column: 18, scope: !26) +// CHECK:STDOUT: !29 = !DILocation(line: 17, column: 1, scope: !26) +// CHECK:STDOUT: !30 = distinct !DISubprogram(name: "Three", linkageName: "_CThree.Main", scope: null, file: !7, line: 22, type: !16, spFlags: DISPFlagDefinition, unit: !6) +// CHECK:STDOUT: !31 = !DILocation(line: 23, column: 18, scope: !30) +// CHECK:STDOUT: !32 = !DILocation(line: 24, column: 18, scope: !30) +// CHECK:STDOUT: !33 = !DILocation(line: 22, column: 1, scope: !30) +// CHECK:STDOUT: !34 = distinct !DISubprogram(name: "Four", linkageName: "_CFour.Main", scope: null, file: !7, line: 27, type: !16, spFlags: DISPFlagDefinition, unit: !6) +// CHECK:STDOUT: !35 = !DILocation(line: 28, column: 18, scope: !34) +// CHECK:STDOUT: !36 = !DILocation(line: 29, column: 18, scope: !34) +// CHECK:STDOUT: !37 = !DILocation(line: 27, column: 1, scope: !34) diff --git a/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon b/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon index b983c0e1e621..f97447f623df 100644 --- a/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon +++ b/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon @@ -206,7 +206,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CInitVectorLike.Main() #3 !dbg !29 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %_.var = alloca {}, align 8, !dbg !30 +// CHECK:STDOUT: %_.var = alloca [1 x i8], align 1, !dbg !30 // CHECK:STDOUT: %.loc18_36.2.temp = alloca [16 x i8], align 1, !dbg !31 // CHECK:STDOUT: %.loc18_36.4.temp = alloca [3 x i32], align 4, !dbg !31 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !30 @@ -240,19 +240,19 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: define void @_CInitNontrivialDtor.Main() #3 !dbg !34 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %_.var = alloca [16 x i8], align 1, !dbg !35 -// CHECK:STDOUT: %.loc23_69.17.temp = alloca [3 x {}], align 8, !dbg !36 +// CHECK:STDOUT: %.loc23_69.17.temp = alloca [3 x [1 x i8]], align 1, !dbg !36 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !35 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc23_69.17.temp), !dbg !36 -// CHECK:STDOUT: %.loc23_69.18.array.index = getelementptr inbounds [3 x {}], ptr %.loc23_69.17.temp, i32 0, i64 0, !dbg !36 +// CHECK:STDOUT: %.loc23_69.18.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 0, !dbg !36 // CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.18.array.index), !dbg !36 -// CHECK:STDOUT: %.loc23_69.16.array.index = getelementptr inbounds [3 x {}], ptr %.loc23_69.17.temp, i32 0, i64 1, !dbg !36 +// CHECK:STDOUT: %.loc23_69.16.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 1, !dbg !36 // CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.16.array.index), !dbg !36 -// CHECK:STDOUT: %.loc23_69.15.array.index = getelementptr inbounds [3 x {}], ptr %.loc23_69.17.temp, i32 0, i64 2, !dbg !36 +// CHECK:STDOUT: %.loc23_69.15.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 2, !dbg !36 // CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.15.array.index), !dbg !36 // CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.begin = getelementptr inbounds nuw [16 x i8], ptr %_.var, i32 0, i32 0, !dbg !35 // CHECK:STDOUT: store ptr %.loc23_69.17.temp, ptr %initializer_list.initializer_list.call.init_list.begin, align 8, !dbg !35 // CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.end = getelementptr inbounds nuw [16 x i8], ptr %_.var, i32 0, i32 8, !dbg !35 -// CHECK:STDOUT: %initializer_list.initializer_list.call.array.end = getelementptr inbounds [3 x {}], ptr %.loc23_69.17.temp, i32 1, !dbg !35 +// CHECK:STDOUT: %initializer_list.initializer_list.call.array.end = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 1, !dbg !35 // CHECK:STDOUT: store ptr %initializer_list.initializer_list.call.array.end, ptr %initializer_list.initializer_list.call.init_list.end, align 8, !dbg !35 // CHECK:STDOUT: call void @_CWithinLifetime.Main(), !dbg !37 // CHECK:STDOUT: ret void, !dbg !38 @@ -407,7 +407,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CInitVectorLike.Main() #3 !dbg !31 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %_.var = alloca {}, align 8, !dbg !32 +// CHECK:STDOUT: %_.var = alloca [1 x i8], align 1, !dbg !32 // CHECK:STDOUT: %.loc18_36.2.temp = alloca [16 x i8], align 1, !dbg !33 // CHECK:STDOUT: %.loc18_36.4.temp = alloca [3 x i32], align 4, !dbg !33 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !32 @@ -440,14 +440,14 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: define void @_CInitNontrivialDtor.Main() #3 !dbg !36 { // CHECK:STDOUT: entry: // CHECK:STDOUT: %_.var = alloca [16 x i8], align 1, !dbg !37 -// CHECK:STDOUT: %.loc23_69.17.temp = alloca [3 x {}], align 8, !dbg !38 +// CHECK:STDOUT: %.loc23_69.17.temp = alloca [3 x [1 x i8]], align 1, !dbg !38 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !37 // CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc23_69.17.temp), !dbg !38 -// CHECK:STDOUT: %.loc23_69.18.array.index = getelementptr inbounds [3 x {}], ptr %.loc23_69.17.temp, i32 0, i64 0, !dbg !38 +// CHECK:STDOUT: %.loc23_69.18.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 0, !dbg !38 // CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.18.array.index), !dbg !38 -// CHECK:STDOUT: %.loc23_69.16.array.index = getelementptr inbounds [3 x {}], ptr %.loc23_69.17.temp, i32 0, i64 1, !dbg !38 +// CHECK:STDOUT: %.loc23_69.16.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 1, !dbg !38 // CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.16.array.index), !dbg !38 -// CHECK:STDOUT: %.loc23_69.15.array.index = getelementptr inbounds [3 x {}], ptr %.loc23_69.17.temp, i32 0, i64 2, !dbg !38 +// CHECK:STDOUT: %.loc23_69.15.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 2, !dbg !38 // CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.15.array.index), !dbg !38 // CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.begin = getelementptr inbounds nuw [16 x i8], ptr %_.var, i32 0, i32 0, !dbg !37 // CHECK:STDOUT: store ptr %.loc23_69.17.temp, ptr %initializer_list.initializer_list.call.init_list.begin, align 8, !dbg !37