[clang] 5548ea3 - [Clang] Instantiate local constexpr functions eagerly (#95660)

via cfe-commits cfe-commits at lists.llvm.org
Sun Jun 16 06:54:23 PDT 2024


Author: Younan Zhang
Date: 2024-06-16T21:54:19+08:00
New Revision: 5548ea34341e9d0ae645719c34b466ca3b9eaa5a

URL: https://github.com/llvm/llvm-project/commit/5548ea34341e9d0ae645719c34b466ca3b9eaa5a
DIFF: https://github.com/llvm/llvm-project/commit/5548ea34341e9d0ae645719c34b466ca3b9eaa5a.diff

LOG: [Clang] Instantiate local constexpr functions eagerly (#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

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaExpr.cpp
    clang/test/SemaTemplate/instantiate-local-class.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 36efeb8c70cca..69aea6c21ad39 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -858,6 +858,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<CXXRecordDecl>(Func->getDeclContext()) &&
-              cast<CXXRecordDecl>(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<CXXRecordDecl>(Func->getDeclContext()) &&
+                   cast<CXXRecordDecl>(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<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