[clang] [Clang] Instantiate local constexpr functions eagerly (PR #95660)

Younan Zhang via cfe-commits cfe-commits at lists.llvm.org
Sat Jun 15 05:55:49 PDT 2024


https://github.com/zyn0217 created https://github.com/llvm/llvm-project/pull/95660

We had a code path in `Sema::MarkFunctionReferenced()` that deferred local lambda instantiation even for constexprs. This resulted in any calls to them referring to function decls that lack bodies and hence failures at constant evaluation.

The issue doesn't occur when the lambda has no explicit return type because the return type deduction requires instantiation.

Fixes https://github.com/llvm/llvm-project/issues/35052
Fixes https://github.com/llvm/llvm-project/issues/94849


>From c288190c313d6990580048368c60a846919f98ae Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Sat, 15 Jun 2024 20:29:24 +0800
Subject: [PATCH] [Clang] Instantiate local constexpr functions eagerly

---
 clang/docs/ReleaseNotes.rst                   |  1 +
 clang/lib/Sema/SemaExpr.cpp                   |  3 ++-
 .../SemaTemplate/instantiate-local-class.cpp  | 24 +++++++++++++++++++
 3 files changed, 27 insertions(+), 1 deletion(-)

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..88e9b2b00f84d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -18112,7 +18112,8 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
 
         if (FirstInstantiation || TSK != TSK_ImplicitInstantiation ||
             Func->isConstexpr()) {
-          if (isa<CXXRecordDecl>(Func->getDeclContext()) &&
+          if (!Func->isConstexpr() &&
+              isa<CXXRecordDecl>(Func->getDeclContext()) &&
               cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass() &&
               CodeSynthesisContexts.size())
             PendingLocalImplicitInstantiations.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<typename T>
 void f0() {
@@ -509,3 +510,26 @@ namespace LambdaInDefaultMemberInitializer {
   }
   template void f<int>();
 }
+
+#if __cplusplus >= 201703L
+namespace GH35052 {
+
+template <typename F> 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



More information about the cfe-commits mailing list