diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -16654,11 +16654,22 @@ /// It's OK if this fails; we'll also remove this in /// HandleImmediateInvocations, but catching it here allows us to avoid /// walking the AST looking for it in simple cases. - if (auto *Call = dyn_cast(E.get()->IgnoreImplicit())) + if (auto *Call = dyn_cast(E.get()->IgnoreImplicit())) { if (auto *DeclRef = dyn_cast(Call->getCallee()->IgnoreImplicit())) ExprEvalContexts.back().ReferenceToConsteval.erase(DeclRef); + // If any arguments are value-dependent, we will not be able to evaluate + // the function call until instantiation. + if (Call->isValueDependent()) + return E; + + for (Expr *Arg : Call->arguments()) { + if (Arg->isValueDependent()) + return E; + } + } + E = MaybeCreateExprWithCleanups(E); ConstantExpr *Res = ConstantExpr::Create( diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -61,6 +61,20 @@ struct E : C { consteval ~E() {} // expected-error {{cannot be declared consteval}} }; + +template +constexpr int callConstevalWithNameDependentArg() { + return f1(X); +} + +template +constexpr int callConstevalWithNameDependentArgAsVariable() { + constexpr int x = X; + return f1(x); +} + +auto foo = callConstevalWithNameDependentArg<42>(); + } consteval int main() { // expected-error {{'main' is not allowed to be declared consteval}}