-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang] ICE when dealing with some certain requires clauses in calculateConstraintSatisfaction
#69307
Comments
@llvm/issue-subscribers-clang-frontend Author: Runge (RungeCC)
## Descriptions
#include <concepts>
#include <type_traits>
#include <utility>
[[maybe_unused]] constexpr inline static auto lpartial =
[](auto fn, auto... t0) constexpr noexcept {
return [=](auto... rest) constexpr noexcept
requires requires { fn(t0..., rest...); }
{ return fn(t0..., rest...); };
};
[[maybe_unused]] constexpr inline static auto fix =
[](auto self) constexpr noexcept {
return [=](auto... args) constexpr noexcept
requires requires { self(self, args...); }
{ return self(self, args...); };
};
[[maybe_unused]] constexpr inline static auto currify0 =
[](auto self, auto v, auto fn) constexpr noexcept {
return [=](auto... as) constexpr noexcept
requires(
(v.value > sizeof...(as) && requires { lpartial(fn, as...); }) ||
(v.value == sizeof...(as) && requires { fn(as...); }))
{
if constexpr (v.value > sizeof...(as))
return self(self, std::integral_constant<std::size_t, v.value - sizeof...(as)>{}, lpartial(fn, as...));
else
return fn(as...);
};
};
[[maybe_unused]] constexpr static inline auto plus =
[](auto x, auto y) constexpr noexcept
requires requires { x + y; }
{ return x + y; };
#undef lambda_body
[[maybe_unused]] constexpr static inline auto plus_ =
fix(currify0)(std::integral_constant<std::size_t, 2>{}, plus);
Expected behavior: Accepts the above code, just as Actual behavior: Crash, with output: <details>
</details> Versions: trunk(Online compiler, with assertions) and:
Notes
|
@llvm/issue-subscribers-c-20 Author: Runge (RungeCC)
## Descriptions
#include <concepts>
#include <type_traits>
#include <utility>
[[maybe_unused]] constexpr inline static auto lpartial =
[](auto fn, auto... t0) constexpr noexcept {
return [=](auto... rest) constexpr noexcept
requires requires { fn(t0..., rest...); }
{ return fn(t0..., rest...); };
};
[[maybe_unused]] constexpr inline static auto fix =
[](auto self) constexpr noexcept {
return [=](auto... args) constexpr noexcept
requires requires { self(self, args...); }
{ return self(self, args...); };
};
[[maybe_unused]] constexpr inline static auto currify0 =
[](auto self, auto v, auto fn) constexpr noexcept {
return [=](auto... as) constexpr noexcept
requires(
(v.value > sizeof...(as) && requires { lpartial(fn, as...); }) ||
(v.value == sizeof...(as) && requires { fn(as...); }))
{
if constexpr (v.value > sizeof...(as))
return self(self, std::integral_constant<std::size_t, v.value - sizeof...(as)>{}, lpartial(fn, as...));
else
return fn(as...);
};
};
[[maybe_unused]] constexpr static inline auto plus =
[](auto x, auto y) constexpr noexcept
requires requires { x + y; }
{ return x + y; };
#undef lambda_body
[[maybe_unused]] constexpr static inline auto plus_ =
fix(currify0)(std::integral_constant<std::size_t, 2>{}, plus);
Expected behavior: Accepts the above code, just as Actual behavior: Crash, with output: <details>
</details> Versions: trunk(Online compiler, with assertions) and:
Notes
|
I have found a strange workaround: Convert a function call that will trigger clang ICE, like:
into an equivalent form:
Then clang could work with it, without crashing or emitting any warnings. See online compiler. |
Possibly related: #67260 |
A minimal example is: constexpr auto ICE = [](auto a) { // a dependent ParmVar
return [=]() // #1, ICE
// [&]() // #2, ICE
// [ ]() // #3, OK
// [r=a]() // #4, OK
// [a]() // #5, OK
// [&r=a]()// #6, OK with warning
// [&a]() // #7, OK with warning
requires requires { a; }
{ return 1; };
};
constexpr auto Ret = ICE(1)(); constexpr auto ICE = [](auto a) {
return [=]()
requires requires { a; }
{ return a; }; // #8, implicitly captured, OK
};
constexpr auto Ret = ICE(1)(); Note:
|
I think the following code is suspicious: llvm-project/clang/lib/Sema/SemaExpr.cpp Lines 19787 to 19792 in 4f131b0
Consider: constexpr auto ICE(auto a) { // template function, not lambda
return [=]()
requires requires { a; }
{ return 1; };
}; ICE happens when checking satisfaction of constraints of the It seems that before 3ed9e9e the above example is somehow like (ignoring incorrect syntax): constexpr auto ICE(auto a) { // template function, not lambda
return [=]()
{ requires requires { a; }; return 1; };
}; llvm-project/clang/lib/Sema/SemaExpr.cpp Lines 19779 to 19815 in 4f131b0
As at that time llvm-project/clang/lib/Sema/SemaDecl.cpp Lines 15383 to 15386 in eaf725b
CC: @cor3ntin Note: The above analysis may be completely wrong, as I've only recently started reading the clang source code. |
I think this theory makes some sense, since I notice this:
also triggers the same ICE(https://godbolt.org/z/cjc4arcTW). |
I will submit a pull request to attempt to fix this issue. |
Descriptions
Example:
Expected behavior:
Accepts the above code, just as
gcc
(13.2 and trunk),msvc
(latest) do.Actual behavior:
Crash, with output:
Click me
Versions:
trunk(Online compiler, with assertions) and:
Notes
requires requires ...
in the decl of lambdafix
, then clang-trunk will accept it.The text was updated successfully, but these errors were encountered: