diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8c2f737836a9d..a424554ed821d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -847,6 +847,7 @@ Bug Fixes to C++ Support - Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307), (#GH88081), (#GH89496), (#GH90669) and (#GH91633). - Fixed handling of brace ellison when building deduction guides. (#GH64625), (#GH83368). +- Clang now instantiates local constexpr functions eagerly for constant evaluators. (#GH35052), (#GH94849) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 99a8704298314..4db8b4130c3c7 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -18112,16 +18112,17 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, if (FirstInstantiation || TSK != TSK_ImplicitInstantiation || Func->isConstexpr()) { - if (isa(Func->getDeclContext()) && - cast(Func->getDeclContext())->isLocalClass() && - CodeSynthesisContexts.size()) - PendingLocalImplicitInstantiations.push_back( - std::make_pair(Func, PointOfInstantiation)); - else if (Func->isConstexpr()) + if (Func->isConstexpr()) // Do not defer instantiations of constexpr functions, to avoid the // expression evaluator needing to call back into Sema if it sees a // call to such a function. InstantiateFunctionDefinition(PointOfInstantiation, Func); + else if (isa(Func->getDeclContext()) && + cast(Func->getDeclContext()) + ->isLocalClass() && + CodeSynthesisContexts.size()) + PendingLocalImplicitInstantiations.push_back( + std::make_pair(Func, PointOfInstantiation)); else { Func->setInstantiationIsPending(true); PendingInstantiations.push_back( diff --git a/clang/test/SemaTemplate/instantiate-local-class.cpp b/clang/test/SemaTemplate/instantiate-local-class.cpp index 47591045fd26e..7eee131e28d60 100644 --- a/clang/test/SemaTemplate/instantiate-local-class.cpp +++ b/clang/test/SemaTemplate/instantiate-local-class.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -verify -std=c++11 %s // RUN: %clang_cc1 -verify -std=c++11 -fdelayed-template-parsing %s +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s template void f0() { @@ -509,3 +510,26 @@ namespace LambdaInDefaultMemberInitializer { } template void f(); } + +#if __cplusplus >= 201703L +namespace GH35052 { + +template constexpr int func(F f) { + if constexpr (f(1UL)) { + return 1; + } + return 0; +} + +int main() { + auto predicate = [](auto v) /*implicit constexpr*/ -> bool { + return v == 1; + }; + + static_assert(predicate(1)); + return func(predicate); +} + +} // namespace GH35052 + +#endif