aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/docs/ReleaseNotes.rst6
-rw-r--r--clang/lib/Sema/SemaExpr.cpp5
-rw-r--r--clang/test/SemaCXX/cxx2a-consteval.cpp69
3 files changed, 80 insertions, 0 deletions
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5620cb3..96c4120 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -542,6 +542,12 @@ C++20 Feature Support
- As per "Conditionally Trivial Special Member Functions" (P0848), it is
now possible to overload destructors using concepts. Note that the rest
of the paper about other special member functions is not yet implemented.
+- 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 0e24237..83081bb 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -17600,6 +17600,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 df2a992..c6f3e273 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -766,3 +766,72 @@ void test() {
static_assert(c == 8);
}
}
+
+// 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@-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