diff --git a/toolchain/check/cpp/constant.cpp b/toolchain/check/cpp/constant.cpp index 2eddb00d8bc3..6f91ae32ae28 100644 --- a/toolchain/check/cpp/constant.cpp +++ b/toolchain/check/cpp/constant.cpp @@ -5,6 +5,7 @@ #include "toolchain/check/cpp/constant.h" #include "toolchain/check/cpp/import.h" +#include "toolchain/check/cpp/location.h" #include "toolchain/check/cpp/type_mapping.h" #include "toolchain/check/eval.h" #include "toolchain/check/member_access.h" @@ -226,7 +227,7 @@ auto EvalCppCall(Context& context, SemIR::LocId loc_id, context.ast_context(), /*QualifierLoc=*/clang::NestedNameSpecifierLoc(), /*TemplateKWLoc=*/clang::SourceLocation(), function_decl, /*RefersToEnclosingVariableOrCapture=*/false, - /*NameLoc=*/clang::SourceLocation(), function_decl->getType(), + /*NameLoc=*/GetCppLocation(context, loc_id), function_decl->getType(), clang::VK_LValue); // Cast to a function pointer type. @@ -253,18 +254,20 @@ auto EvalCppCall(Context& context, SemIR::LocId loc_id, auto* call_expr = clang::CallExpr::Create( context.ast_context(), implicit_cast_expr, arg_exprs, function_decl->getCallResultType(), clang::VK_PRValue, - /*RParenLoc=*/clang::SourceLocation(), clang::FPOptionsOverride()); + /*RParenLoc=*/GetCppLocation(context, loc_id), + clang::FPOptionsOverride()); // Evaluate the expr as a constant and map that to Carbon constant. + clang::SmallVector notes; clang::Expr::EvalResult eval_result; + eval_result.Diag = ¬es; if (!call_expr->EvaluateAsConstantExpr(eval_result, context.ast_context())) { - // TODO: improve this diagnostic with information from `eval_result`. - CARBON_DIAGNOSTIC(CppConstexprEval, Error, - "failed to evaluate {0:consteval|constexpr} function " - "call as a constant", - Diagnostics::BoolAsSelect); - context.emitter().Emit(loc_id, CppConstexprEval, - function_decl->isConsteval()); + context.clang_sema().Diag(call_expr->getBeginLoc(), + clang::diag::err_invalid_consteval_call) + << function_decl << function_decl->isConsteval(); + for (const auto& note : notes) { + context.clang_sema().Diag(note.first, note.second); + } return SemIR::ErrorInst::ConstantId; } diff --git a/toolchain/check/testdata/interop/cpp/constexpr.carbon b/toolchain/check/testdata/interop/cpp/constexpr.carbon index cfa3d7ed78a9..124c480b366d 100644 --- a/toolchain/check/testdata/interop/cpp/constexpr.carbon +++ b/toolchain/check/testdata/interop/cpp/constexpr.carbon @@ -80,8 +80,14 @@ constexpr int f(int a) { } '''; -// CHECK:STDERR: fail_invalid_constant_eval.carbon:[[@LINE+4]]:19: error: failed to evaluate constexpr function call as a constant [CppConstexprEval] -// CHECK:STDERR: let a: array(i32, Cpp.f(5)) = (1, 2, 3); -// CHECK:STDERR: ^~~~~~~~ +// 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: let a: array(i32, Cpp.f(5)) = (1, 2, 3); diff --git a/toolchain/diagnostics/kind.def b/toolchain/diagnostics/kind.def index 2e74aa6730b9..591b6e51a7ee 100644 --- a/toolchain/diagnostics/kind.def +++ b/toolchain/diagnostics/kind.def @@ -270,7 +270,6 @@ CARBON_DIAGNOSTIC_KIND(RefTagNoRefParam) CARBON_DIAGNOSTIC_KIND(RefTagNotDurableRef) CARBON_DIAGNOSTIC_KIND(SelfParameterNotAllowed) CARBON_DIAGNOSTIC_KIND(ValueForRefParam) -CARBON_DIAGNOSTIC_KIND(CppConstexprEval) // Function declaration checking. CARBON_DIAGNOSTIC_KIND(DefinedAbstractFunction)