diff --git a/toolchain/check/testdata/interop/cpp/enum/using.carbon b/toolchain/check/testdata/interop/cpp/enum/using.carbon new file mode 100644 index 0000000000000..9df296d2967e3 --- /dev/null +++ b/toolchain/check/testdata/interop/cpp/enum/using.carbon @@ -0,0 +1,137 @@ +// 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/uint.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/enum/using.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/enum/using.carbon + +// --- enum.h + +enum Enum { a, b, c }; +using UEnum = Enum; + +enum Other { d }; + +// --- import_enum.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "enum.h"; + +//@dump-sem-ir-begin +fn F() { + let a: Cpp.Enum = Cpp.Enum.a; + let b: Cpp.UEnum = Cpp.UEnum.b; + var c: Cpp.UEnum = Cpp.UEnum.c; + c = b; +} +//@dump-sem-ir-end + +// --- fail_wrong_enum.carbon + +library "[[@TEST_NAME]]"; + +import Cpp library "enum.h"; + +fn F() { + // CHECK:STDERR: fail_wrong_enum.carbon:[[@LINE+7]]:22: error: cannot implicitly convert expression of type `Cpp.Enum` to `Cpp.Other` [ConversionFailure] + // CHECK:STDERR: let c: Cpp.Other = Cpp.UEnum.a; + // CHECK:STDERR: ^~~~~~~~~~~ + // CHECK:STDERR: fail_wrong_enum.carbon:[[@LINE+4]]:22: note: type `Cpp.Enum` does not implement interface `Core.ImplicitAs(Cpp.Other)` [MissingImplInMemberAccessNote] + // CHECK:STDERR: let c: Cpp.Other = Cpp.UEnum.a; + // CHECK:STDERR: ^~~~~~~~~~~ + // CHECK:STDERR: + let c: Cpp.Other = Cpp.UEnum.a; + +} + +// CHECK:STDOUT: --- import_enum.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [concrete] +// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] +// CHECK:STDOUT: %F: %F.type = struct_value () [concrete] +// CHECK:STDOUT: %Enum: type = class_type @Enum [concrete] +// CHECK:STDOUT: %pattern_type.ebf: type = pattern_type %Enum [concrete] +// CHECK:STDOUT: %int_0: %Enum = int_value 0 [concrete] +// CHECK:STDOUT: %int_1: %Enum = int_value 1 [concrete] +// CHECK:STDOUT: %int_2: %Enum = int_value 2 [concrete] +// CHECK:STDOUT: %type_where: type = facet_type > [concrete] +// CHECK:STDOUT: %facet_value: %type_where = facet_value %Enum, () [concrete] +// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.cd9: type = fn_type @DestroyT.binding.as_type.as.Destroy.impl.Op, @DestroyT.binding.as_type.as.Destroy.impl(%facet_value) [concrete] +// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.0d9: %DestroyT.binding.as_type.as.Destroy.impl.Op.type.cd9 = struct_value () [concrete] +// CHECK:STDOUT: %ptr.47b: type = ptr_type %Enum [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Cpp: = namespace file.%Cpp.import_cpp, [concrete] { +// CHECK:STDOUT: .Enum = %Enum.decl +// CHECK:STDOUT: .UEnum = %Enum.decl +// CHECK:STDOUT: import Cpp//... +// CHECK:STDOUT: } +// CHECK:STDOUT: %Enum.decl: type = class_decl @Enum [concrete = constants.%Enum] {} {} +// CHECK:STDOUT: %int_0: %Enum = int_value 0 [concrete = constants.%int_0] +// CHECK:STDOUT: %int_1: %Enum = int_value 1 [concrete = constants.%int_1] +// CHECK:STDOUT: %int_2: %Enum = int_value 2 [concrete = constants.%int_2] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %a.patt: %pattern_type.ebf = binding_pattern a [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.ref.loc8_21: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Enum.ref.loc8_24: type = name_ref Enum, imports.%Enum.decl [concrete = constants.%Enum] +// CHECK:STDOUT: %a.ref: %Enum = name_ref a, imports.%int_0 [concrete = constants.%int_0] +// CHECK:STDOUT: %.loc8: type = splice_block %Enum.ref.loc8_13 [concrete = constants.%Enum] { +// CHECK:STDOUT: %Cpp.ref.loc8_10: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %Enum.ref.loc8_13: type = name_ref Enum, imports.%Enum.decl [concrete = constants.%Enum] +// CHECK:STDOUT: } +// CHECK:STDOUT: %a: %Enum = bind_name a, %a.ref +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %b.patt: %pattern_type.ebf = binding_pattern b [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %Cpp.ref.loc9_22: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %UEnum.ref.loc9_25: type = name_ref UEnum, imports.%Enum.decl [concrete = constants.%Enum] +// CHECK:STDOUT: %b.ref.loc9: %Enum = name_ref b, imports.%int_1 [concrete = constants.%int_1] +// CHECK:STDOUT: %.loc9: type = splice_block %UEnum.ref.loc9_13 [concrete = constants.%Enum] { +// CHECK:STDOUT: %Cpp.ref.loc9_10: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %UEnum.ref.loc9_13: type = name_ref UEnum, imports.%Enum.decl [concrete = constants.%Enum] +// CHECK:STDOUT: } +// CHECK:STDOUT: %b: %Enum = bind_name b, %b.ref.loc9 +// CHECK:STDOUT: name_binding_decl { +// CHECK:STDOUT: %c.patt: %pattern_type.ebf = binding_pattern c [concrete] +// CHECK:STDOUT: %c.var_patt: %pattern_type.ebf = var_pattern %c.patt [concrete] +// CHECK:STDOUT: } +// CHECK:STDOUT: %c.var: ref %Enum = var %c.var_patt +// CHECK:STDOUT: %Cpp.ref.loc10_22: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %UEnum.ref.loc10_25: type = name_ref UEnum, imports.%Enum.decl [concrete = constants.%Enum] +// CHECK:STDOUT: %c.ref.loc10: %Enum = name_ref c, imports.%int_2 [concrete = constants.%int_2] +// CHECK:STDOUT: assign %c.var, %c.ref.loc10 +// CHECK:STDOUT: %.loc10_13: type = splice_block %UEnum.ref.loc10_13 [concrete = constants.%Enum] { +// CHECK:STDOUT: %Cpp.ref.loc10_10: = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] +// CHECK:STDOUT: %UEnum.ref.loc10_13: type = name_ref UEnum, imports.%Enum.decl [concrete = constants.%Enum] +// CHECK:STDOUT: } +// CHECK:STDOUT: %c: ref %Enum = bind_name c, %c.var +// CHECK:STDOUT: %c.ref.loc11: ref %Enum = name_ref c, %c +// CHECK:STDOUT: %b.ref.loc11: %Enum = name_ref b, %b +// CHECK:STDOUT: assign %c.ref.loc11, %b.ref.loc11 +// CHECK:STDOUT: %facet_value: %type_where = facet_value constants.%Enum, () [concrete = constants.%facet_value] +// CHECK:STDOUT: %.loc10_3: %type_where = converted constants.%Enum, %facet_value [concrete = constants.%facet_value] +// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound: = bound_method %c.var, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.0d9 +// CHECK:STDOUT: +// CHECK:STDOUT: %bound_method: = bound_method %c.var, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn +// CHECK:STDOUT: %addr: %ptr.47b = addr_of %c.var +// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call: init %empty_tuple.type = call %bound_method(%addr) +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: