/
githubmirror
/
carbon-lang
Обзор
Документация
Войти
/
githubmirror
/
carbon-lang
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
trunk
toolchain/check/testdata/interop/cpp/function/import/constexpr.carbon
274 строки
15 KB
Christopher Di Bella
Skip `ImplWitnessTable::elements_id` when generating fingerprints (#7629)
12 авг 2026, 01:39
Не верифицирован
12 авг 2026, 01:39
4ea5ef4
Код
Авторство
О чём код?
// 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 // EXTRA-ARGS: --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/function/import/constexpr.carbon // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/function/import/constexpr.carbon // --- basic.carbon library "[[@TEST_NAME]]"; import Cpp inline ''' constexpr int f(int a, int b) { return a + b; } '''; let a: array(i32, Cpp.f(1, 2)) = (1, 2, 3); // --- bool_param.carbon library "[[@TEST_NAME]]"; import Cpp inline ''' constexpr int f(bool b) { return b ? 3 : 0; } '''; let a: array(i32, Cpp.f(true)) = (1, 2, 3); // --- float_param.carbon library "[[@TEST_NAME]]"; import Cpp inline ''' constexpr int f(float b) { return static_cast<int>(b); } '''; let a: array(i32, Cpp.f(3.0)) = (1, 2, 3); // --- return_bool.carbon library "[[@TEST_NAME]]"; import Cpp inline ''' constexpr bool f() { return true; } '''; musteval fn F(b: bool) -> i32 { return if b then 3 else 0; } let a: array(i32, F(Cpp.f())) = (1, 2, 3); // --- fail_invalid_constant_eval.carbon library "[[@TEST_NAME]]"; import Cpp inline ''' constexpr int arr[1] = {0}; constexpr int f(int a) { return arr[a]; } '''; // CHECK:STDERR: fail_invalid_constant_eval.carbon:[[@LINE+4]]:19: error: array bound is not a constant [InvalidArrayExpr] // CHECK:STDERR: let a: array(i32, Cpp.f(5)) = (1, 2, 3); // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: let a: array(i32, Cpp.f(5)) = (1, 2, 3); // --- nonconstant_constexpr_call.carbon library "[[@TEST_NAME]]"; import Cpp; var a: i32 = 0; inline Cpp ''' constexpr int f(const int &r) { return r; } '''; // OK, runtime call. var b: i32 = Cpp.f(a); // --- fail_nonconstant_consteval_call.carbon library "[[@TEST_NAME]]"; import Cpp; var a: i32 = 0; // TODO: This is failing when building the thunk, not when calling it. inline Cpp ''' // CHECK:STDERR: fail_nonconstant_consteval_call.carbon:[[@LINE+9]]:15: error: call to consteval function 'f' is not a constant expression [CppInteropParseError] // CHECK:STDERR: 19 | consteval int f(const int &r) { return r; } // CHECK:STDERR: | ^ // CHECK:STDERR: fail_nonconstant_consteval_call.carbon:[[@LINE+6]]:15: note: function parameter 'r' with unknown value cannot be used in a constant expression [CppInteropParseNote] // CHECK:STDERR: 19 | consteval int f(const int &r) { return r; } // CHECK:STDERR: | ^ // CHECK:STDERR: fail_nonconstant_consteval_call.carbon:[[@LINE+3]]:15: note: declared here [CppInteropParseNote] // CHECK:STDERR: 19 | consteval int f(const int &r) { return r; } // CHECK:STDERR: | ^ consteval int f(const int &r) { return r; } '''; // CHECK:STDERR: fail_nonconstant_consteval_call.carbon:[[@LINE+11]]:14: note: in thunk for C++ function used here [InCppThunk] // CHECK:STDERR: var b: i32 = Cpp.f(a); // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: // CHECK:STDERR: fail_nonconstant_consteval_call.carbon:[[@LINE+7]]:14: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction] // CHECK:STDERR: var b: i32 = Cpp.f(a); // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: fail_nonconstant_consteval_call.carbon:[[@LINE-10]]:15: note: compile-time-only function declared here [CompTimeOnlyFunctionHere] // CHECK:STDERR: consteval int f(const int &r) { return r; } // CHECK:STDERR: ^ // CHECK:STDERR: var b: i32 = Cpp.f(a); // --- fail_todo_constructor.carbon library "[[@TEST_NAME]]"; import Cpp; inline Cpp ''' struct C { constexpr C(int a) : a(a) {} int a; }; '''; // TODO: This should probably be allowed. eval fn F() -> i32 { //@dump-sem-ir-begin // CHECK:STDERR: fail_todo_constructor.carbon:[[@LINE+3]]:18: error: expression is runtime; expected constant [EvalRequiresConstantValue] // CHECK:STDERR: let c: Cpp.C = 3; // CHECK:STDERR: ^ let c: Cpp.C = 3; return c.a; //@dump-sem-ir-end } // CHECK:STDERR: fail_todo_constructor.carbon:[[@LINE+4]]:19: note: in call to F here [InCallToEvalFn] // CHECK:STDERR: let a: array(i32, F()) = (1, 2, 3); // CHECK:STDERR: ^~~ // CHECK:STDERR: let a: array(i32, F()) = (1, 2, 3); // CHECK:STDOUT: --- fail_todo_constructor.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete] // CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete] // CHECK:STDOUT: %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic] // CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete] // CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %C.elem: type = unbound_element_type %C, %i32 [concrete] // CHECK:STDOUT: %pattern_type.bbc: type = pattern_type %C [concrete] // CHECK:STDOUT: %c.patt: %pattern_type.bbc = value_binding_pattern c [concrete] // CHECK:STDOUT: %int_3.1ba: Core.IntLiteral = int_value 3 [concrete] // CHECK:STDOUT: %ptr.0a2: type = ptr_type %C [concrete] // CHECK:STDOUT: %C__carbon_thunk.type: type = fn_type @C__carbon_thunk [concrete] // CHECK:STDOUT: %C__carbon_thunk: %C__carbon_thunk.type = struct_value () [concrete] // CHECK:STDOUT: %ImplicitAs.type.914: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete] // CHECK:STDOUT: %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic] // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e74: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl.0e9(%To) [symbolic] // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.845: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e74 = struct_value () [symbolic] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %ImplicitAs.impl_witness.a2a: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.1aa, @Core.IntLiteral.as.ImplicitAs.impl.0e9(%int_32) [concrete] // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.2ba: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl.0e9(%int_32) [concrete] // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.2ba = struct_value () [concrete] // CHECK:STDOUT: %ImplicitAs.facet.48f: %ImplicitAs.type.914 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.a2a) [concrete] // CHECK:STDOUT: %ImplicitAs.WithSelf.Convert.type.8eb: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet.48f) [concrete] // CHECK:STDOUT: %.b7a: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.8eb, %ImplicitAs.facet.48f [concrete] // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39 [concrete] // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.e39, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete] // CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete] // CHECK:STDOUT: %int_3.410: %i32 = int_value 3 [concrete] // CHECK:STDOUT: %Int.as.Copy.impl.Op.type.ac8: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic] // CHECK:STDOUT: %Int.as.Copy.impl.Op.5e0: %Int.as.Copy.impl.Op.type.ac8 = struct_value () [symbolic] // CHECK:STDOUT: %Copy.impl_witness.b51: <witness> = impl_witness imports.%Copy.impl_witness_table.8d2, @Int.as.Copy.impl(%int_32) [concrete] // CHECK:STDOUT: %Int.as.Copy.impl.Op.type.3f6: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete] // CHECK:STDOUT: %Int.as.Copy.impl.Op.4f6: %Int.as.Copy.impl.Op.type.3f6 = struct_value () [concrete] // CHECK:STDOUT: %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.b51) [concrete] // CHECK:STDOUT: %Copy.WithSelf.Op.type.381: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete] // CHECK:STDOUT: %.737: type = fn_type_with_self_type %Copy.WithSelf.Op.type.381, %Copy.facet [concrete] // CHECK:STDOUT: %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.4f6, @Int.as.Copy.impl.Op(%int_32) [concrete] // CHECK:STDOUT: %C.cpp_destructor.type: type = fn_type @C.cpp_destructor [concrete] // CHECK:STDOUT: %C.cpp_destructor: %C.cpp_destructor.type = struct_value () [concrete] // CHECK:STDOUT: %C.Op.type: type = fn_type @C.Op [concrete] // CHECK:STDOUT: %C.Op: %C.Op.type = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { // CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] { // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: import Cpp//... // CHECK:STDOUT: } // CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} // CHECK:STDOUT: %C__carbon_thunk.decl: %C__carbon_thunk.type = fn_decl @C__carbon_thunk [concrete = constants.%C__carbon_thunk] { // CHECK:STDOUT: <elided> // CHECK:STDOUT: } { // CHECK:STDOUT: <elided> // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import_ref.edf: @Core.IntLiteral.as.ImplicitAs.impl.0e9.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e74) = import_ref Core//prelude/types/int, loc{{\d+_\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.0e9.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.845)] // CHECK:STDOUT: %ImplicitAs.impl_witness_table.1aa = impl_witness_table (%Core.import_ref.edf), @Core.IntLiteral.as.ImplicitAs.impl.0e9 [concrete] // CHECK:STDOUT: %Core.import_ref.cd6: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.ac8) = import_ref Core//prelude/types/int, loc{{\d+_\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.5e0)] // CHECK:STDOUT: %Copy.impl_witness_table.8d2 = impl_witness_table (%Core.import_ref.cd6), @Int.as.Copy.impl [concrete] // CHECK:STDOUT: %C.cpp_destructor.decl: %C.cpp_destructor.type = fn_decl @C.cpp_destructor [concrete = constants.%C.cpp_destructor] { // CHECK:STDOUT: <elided> // CHECK:STDOUT: } { // CHECK:STDOUT: <elided> // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @F() -> out %return.param: %i32 { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba] // CHECK:STDOUT: %.loc19_18.1: ref %C = temporary_storage // CHECK:STDOUT: %impl.elem0.loc19: %.b7a = impl_witness_access constants.%ImplicitAs.impl_witness.a2a, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.e39] // CHECK:STDOUT: %bound_method.loc19_18.1: <bound method> = bound_method %int_3, %impl.elem0.loc19 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound] // CHECK:STDOUT: %specific_fn.loc19: <specific function> = specific_function %impl.elem0.loc19, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn] // CHECK:STDOUT: %bound_method.loc19_18.2: <bound method> = bound_method %int_3, %specific_fn.loc19 [concrete = constants.%bound_method] // CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc19_18.2(%int_3) [concrete = constants.%int_3.410] // CHECK:STDOUT: %.loc19_18.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_3.410] // CHECK:STDOUT: %.loc19_18.3: %i32 = converted %int_3, %.loc19_18.2 [concrete = constants.%int_3.410] // CHECK:STDOUT: %addr: %ptr.0a2 = addr_of %.loc19_18.1 // CHECK:STDOUT: %C__carbon_thunk.call: init %empty_tuple.type = call imports.%C__carbon_thunk.decl(%.loc19_18.3, %addr) // CHECK:STDOUT: %.loc19_18.4: init %C to %.loc19_18.1 = mark_in_place_init %C__carbon_thunk.call // CHECK:STDOUT: %.loc19_18.5: init %C = converted %int_3, %.loc19_18.4 // CHECK:STDOUT: %.loc19_18.6: ref %C = temporary %.loc19_18.1, %.loc19_18.5 // CHECK:STDOUT: %.loc19_18.7: %C = acquire_value %.loc19_18.6 // CHECK:STDOUT: %.loc19_13: type = splice_block %C.ref [concrete = constants.%C] { // CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp] // CHECK:STDOUT: %C.ref: type = name_ref C, imports.%C.decl [concrete = constants.%C] // CHECK:STDOUT: } // CHECK:STDOUT: %c: %C = wrapper_binding c, %.loc19_18.7 // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %c.patt: %pattern_type.bbc = value_binding_pattern c [concrete = constants.%c.patt] // CHECK:STDOUT: } // CHECK:STDOUT: %c.ref: %C = name_ref c, %c // CHECK:STDOUT: %a.ref: %C.elem = name_ref a, @C.%.1 [concrete = @C.%.1] // CHECK:STDOUT: %.loc20_11.1: ref %i32 = class_element_access %c.ref, element0 // CHECK:STDOUT: %.loc20_11.2: %i32 = acquire_value %.loc20_11.1 // CHECK:STDOUT: %impl.elem0.loc20: %.737 = impl_witness_access constants.%Copy.impl_witness.b51, element0 [concrete = constants.%Int.as.Copy.impl.Op.4f6] // CHECK:STDOUT: %bound_method.loc20_11.1: <bound method> = bound_method %.loc20_11.2, %impl.elem0.loc20 // CHECK:STDOUT: %specific_fn.loc20: <specific function> = specific_function %impl.elem0.loc20, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn] // CHECK:STDOUT: %bound_method.loc20_11.2: <bound method> = bound_method %.loc20_11.2, %specific_fn.loc20 // CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc20_11.2(%.loc20_11.2) // CHECK:STDOUT: <elided> // CHECK:STDOUT: %C.Op.bound: <bound method> = bound_method %.loc19_18.6, constants.%C.Op // CHECK:STDOUT: %Op.ref: %C.cpp_destructor.type = name_ref Op, imports.%C.cpp_destructor.decl [concrete = constants.%C.cpp_destructor] // CHECK:STDOUT: %C.cpp_destructor.bound: <bound method> = bound_method %.loc19_18.6, %Op.ref // CHECK:STDOUT: %C.cpp_destructor.call: init %empty_tuple.type = call %C.cpp_destructor.bound(%.loc19_18.6) // CHECK:STDOUT: return %Int.as.Copy.impl.Op.call // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: <elided> // CHECK:STDOUT: } // CHECK:STDOUT: