Author: Utkarsh Saxena Date: 2022-09-08T08:49:36+02:00 New Revision: 1c73596d345481de957e5ccc0bedf1fb9d9f643a
URL: https://github.com/llvm/llvm-project/commit/1c73596d345481de957e5ccc0bedf1fb9d9f643a DIFF: https://github.com/llvm/llvm-project/commit/1c73596d345481de957e5ccc0bedf1fb9d9f643a.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 (cherry picked from commit e7eec38246560781e0a4020b19c7eb038a8c5655) 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 5620cb3b64004..96c4120ea522d 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 0e24237faae5b..83081bbf0aa0c 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 df2a9925c0154..c6f3e27346a10 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 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits