[clang] e7eec38 - [clang] Skip re-building lambda expressions in parameters to consteval fns.

Utkarsh Saxena via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 2 03:31:14 PDT 2022


Author: Utkarsh Saxena
Date: 2022-09-02T12:30:52+02:00
New Revision: e7eec38246560781e0a4020b19c7eb038a8c5655

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

LOG: [clang] Skip re-building lambda expressions in parameters to consteval fns.

As discussed in this [comment](https://github.com/llvm/llvm-project/issues/56183#issuecomment-1224331699),
we end up building the lambda twice: once while parsing the function calls and then again while handling the immediate invocation.

This happens specially during removing nested immediate invocation.
Eg: When we have another consteval function as the parameter along with this lambda expression. Eg: `foo(bar([]{}))`, `foo(bar(), []{})`

While removing such nested immediate invocations, we should not rebuild this lambda. (IIUC, rebuilding a lambda would always generate a new type which will never match the original type from parsing)

Fixes: https://github.com/llvm/llvm-project/issues/56183
Fixes: https://github.com/llvm/llvm-project/issues/51695
Fixes: https://github.com/llvm/llvm-project/issues/50455
Fixes: https://github.com/llvm/llvm-project/issues/54872
Fixes: https://github.com/llvm/llvm-project/issues/54587

Differential Revision: https://reviews.llvm.org/D132945

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaExpr.cpp
    clang/test/SemaCXX/cxx2a-consteval.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 41fb9e4035e69..2a92f65cc04fc 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -211,9 +211,16 @@ C++20 Feature Support
 - Correctly set expression evaluation context as 'immediate function context' in
   consteval functions.
   This fixes `GH51182 <https://github.com/llvm/llvm-project/issues/51182>`
+
 - Fixes an assert crash caused by looking up missing vtable information on ``consteval``
   virtual functions. Fixes `GH55065 <https://github.com/llvm/llvm-project/issues/55065>`_.
 
+- Skip rebuilding lambda expressions in arguments of immediate invocations.
+  This fixes `GH56183 <https://github.com/llvm/llvm-project/issues/56183>`_,
+  `GH51695 <https://github.com/llvm/llvm-project/issues/51695>`_,
+  `GH50455 <https://github.com/llvm/llvm-project/issues/50455>`_,
+  `GH54872 <https://github.com/llvm/llvm-project/issues/54872>`_,
+  `GH54587 <https://github.com/llvm/llvm-project/issues/54587>`_.
 
 C++2b Feature Support
 ^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 80ac6733cbef2..f124ad3bc08d0 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -17598,6 +17598,11 @@ static void RemoveNestedImmediateInvocation(
       DRSet.erase(E);
       return E;
     }
+    ExprResult TransformLambdaExpr(LambdaExpr *E) {
+      // Do not rebuild lambdas to avoid creating a new type.
+      // Lambdas have already been processed inside their eval context.
+      return E;
+    }
     bool AlwaysRebuild() { return false; }
     bool ReplacingOriginal() { return true; }
     bool AllowSkippingCXXConstructExpr() {

diff  --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index 09129a27818d3..1a8097797bc3c 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -939,3 +939,82 @@ consteval T mid(const T& a, const T& b, const T& c) {
 static_assert(max(1,2)==2);
 static_assert(mid(1,2,3)==2);
 } // namespace GH51182
+
+// https://github.com/llvm/llvm-project/issues/56183
+namespace GH56183 {
+consteval auto Foo(auto c) { return c; }
+consteval auto Bar(auto f) { return f(); }
+void test() {
+  constexpr auto x = Foo(Bar([] { return 'a'; }));
+  static_assert(x == 'a');
+}
+}  // namespace GH56183
+
+// https://github.com/llvm/llvm-project/issues/51695
+namespace GH51695 {
+// Original ========================================
+template <typename T>
+struct type_t {};
+
+template <typename...>
+struct list_t {};
+
+template <typename T, typename... Ts>
+consteval auto pop_front(list_t<T, Ts...>) -> auto {
+  return list_t<Ts...>{};
+}
+
+template <typename... Ts, typename F>
+consteval auto apply(list_t<Ts...>, F fn) -> auto {
+  return fn(type_t<Ts>{}...);
+}
+
+void test1() {
+  constexpr auto x = apply(pop_front(list_t<char, char>{}),
+                            []<typename... Us>(type_t<Us>...) { return 42; });
+  static_assert(x == 42);
+}
+// Reduced 1 ========================================
+consteval bool zero() { return false; }
+
+template <typename F>
+consteval bool foo(bool, F f) {
+  return f();
+}
+
+void test2() {
+  constexpr auto x = foo(zero(), []() { return true; });
+  static_assert(x);
+}
+
+// Reduced 2 ========================================
+template <typename F>
+consteval auto bar(F f) { return f;}
+
+void test3() {
+  constexpr auto t1 = bar(bar(bar(bar([]() { return true; }))))();
+  static_assert(t1);
+
+  int a = 1; // expected-note {{declared here}}
+  auto t2 = bar(bar(bar(bar([=]() { return a; }))))(); // expected-error-re {{call to consteval function 'GH51695::bar<(lambda at {{.*}})>' is not a constant expression}}
+  // expected-note at -1 {{read of non-const variable 'a' is not allowed in a constant expression}}
+
+  constexpr auto t3 = bar(bar([x=bar(42)]() { return x; }))();
+  static_assert(t3==42);
+  constexpr auto t4 = bar(bar([x=bar(42)]() consteval { return x; }))();
+  static_assert(t4==42);
+}
+
+}  // namespace GH51695
+
+// https://github.com/llvm/llvm-project/issues/50455
+namespace GH50455 {
+void f() {
+  []() consteval { int i{}; }();
+  []() consteval { int i{}; ++i; }();
+}
+void g() {
+  (void)[](int i) consteval { return i; }(0);
+  (void)[](int i) consteval { return i; }(0);
+}
+}  // namespace GH50455


        


More information about the cfe-commits mailing list