diff --git a/toolchain/check/cpp/constant.cpp b/toolchain/check/cpp/constant.cpp index 248304b09bbd..626d24e1fa15 100644 --- a/toolchain/check/cpp/constant.cpp +++ b/toolchain/check/cpp/constant.cpp @@ -267,9 +267,12 @@ auto EvalCppCall(Context& context, SemIR::LocId loc_id, clang::Expr::EvalResult eval_result; eval_result.Diag = ¬es; if (!call_expr->EvaluateAsConstantExpr(eval_result, context.ast_context())) { + if (!function_decl->isConsteval()) { + return SemIR::ConstantId::NotConstant; + } context.clang_sema().Diag(call_expr->getBeginLoc(), clang::diag::err_invalid_consteval_call) - << function_decl << function_decl->isConsteval(); + << function_decl << /*is consteval*/ true; for (const auto& note : notes) { context.clang_sema().Diag(note.first, note.second); } diff --git a/toolchain/check/testdata/interop/cpp/constexpr.carbon b/toolchain/check/testdata/interop/cpp/constexpr.carbon index 9966c0fb552f..4e317d92e756 100644 --- a/toolchain/check/testdata/interop/cpp/constexpr.carbon +++ b/toolchain/check/testdata/interop/cpp/constexpr.carbon @@ -3,6 +3,7 @@ // 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: @@ -120,14 +121,58 @@ constexpr int f(int a) { } '''; -// CHECK:STDERR: fail_invalid_constant_eval.carbon:[[@LINE+10]]:26: error: call to immediate function 'f' is not a constant expression [CppInteropParseError] -// CHECK:STDERR: 21 | let a: array(i32, Cpp.f(5)) = (1, 2, 3); -// CHECK:STDERR: | ^ -// CHECK:STDERR: fail_invalid_constant_eval.carbon:[[@LINE-7]]:10: note: cannot refer to element 5 of array of 1 element in a constant expression [CppInteropParseNote] -// CHECK:STDERR: 7 | return arr[a]; -// CHECK:STDERR: | ^ -// CHECK:STDERR: fail_invalid_constant_eval.carbon:[[@LINE+4]]:26: note: in call to 'f(5)' [CppInteropParseNote] -// CHECK:STDERR: 21 | let a: array(i32, Cpp.f(5)) = (1, 2, 3); -// CHECK:STDERR: | ^ +// 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);