-
Notifications
You must be signed in to change notification settings - Fork 12.1k
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
[libc++] std::invoke() substitution failure when using function object with default argument #106428
Comments
It seems like std::invoke() in libc++18 (but not previous versions) doesn't like default function parameters in certain contexts. Reported as llvm/llvm-project#106428
This appears to be a Clang regression in Clang 18, not in libc++. Reduced: https://godbolt.org/z/TMc3Wqjb8 template <class _Fp, class... _Args>
decltype(_Fp{}(0, 0))
__invoke(_Fp&& __f);
template<typename T>
struct type_identity { using type = T; };
template<class Fn>
struct invoke_result : type_identity<decltype(__invoke(Fn{}))> {};
namespace std {
struct source_location {
struct __impl {
const char *_M_file_name;
const char *_M_function_name;
unsigned _M_line;
unsigned _M_column;
};
};
}
struct add_fn {
template <typename T>
constexpr auto operator()(T lhs, T rhs,
const std::source_location::__impl* = __builtin_source_location())
const -> T
{
return lhs + rhs;
}
};
using i = invoke_result<add_fn>::type;
static_assert(__is_same(i, int));
|
In llvm#78436 we made some SourceLocExpr dependent to deal with the fact that their value should reflect the name of specialized function - rather than the rtemplate in which they are first used. However SourceLocExpr are unusual in two ways - They don't depend on template argumente - They morally depend on the context in which they are used (rather than called from). It's fair to say that this is quite novels and confuses clang. In particular, in some cases, we used to create dependent SourceLocExpr and never subsequently transform them, leaving dependent objects in instantiated functions types. To work around that we avoid replacing SourceLocExpr when we think they could remain dependent. It's certainly not perfect but it fixes a number of reported bugs, and seem to only affect scenarios in which the value of the SourceLocExpr does not matter (overload resolution). Fixes llvm#106428 Fixes llvm#81155
In llvm#78436 we made some SourceLocExpr dependent to deal with the fact that their value should reflect the name of specialized function - rather than the rtemplate in which they are first used. However SourceLocExpr are unusual in two ways - They don't depend on template argumente - They morally depend on the context in which they are used (rather than called from). It's fair to say that this is quite novels and confuses clang. In particular, in some cases, we used to create dependent SourceLocExpr and never subsequently transform them, leaving dependent objects in instantiated functions types. To work around that we avoid replacing SourceLocExpr when we think they could remain dependent. It's certainly not perfect but it fixes a number of reported bugs, and seem to only affect scenarios in which the value of the SourceLocExpr does not matter (overload resolution). Fixes llvm#106428 Fixes llvm#81155
In llvm#78436 we made some SourceLocExpr dependent to deal with the fact that their value should reflect the name of specialized function - rather than the rtemplate in which they are first used. However SourceLocExpr are unusual in two ways - They don't depend on template argumente - They morally depend on the context in which they are used (rather than called from). It's fair to say that this is quite novels and confuses clang. In particular, in some cases, we used to create dependent SourceLocExpr and never subsequently transform them, leaving dependent objects in instantiated functions types. To work around that we avoid replacing SourceLocExpr when we think they could remain dependent. It's certainly not perfect but it fixes a number of reported bugs, and seem to only affect scenarios in which the value of the SourceLocExpr does not matter (overload resolution). Fixes llvm#106428 Fixes llvm#81155
In llvm#78436 we made some SourceLocExpr dependent to deal with the fact that their value should reflect the name of specialized function - rather than the rtemplate in which they are first used. However SourceLocExpr are unusual in two ways - They don't depend on template arguments - They morally depend on the context in which they are used (rather than called from). It's fair to say that this is quite novels and confuses clang. In particular, in some cases, we used to create dependent SourceLocExpr and never subsequently transform them, leaving dependent objects in instantiated functions types. To work around that we avoid replacing SourceLocExpr when we think they could remain dependent. It's certainly not perfect but it fixes a number of reported bugs, and seem to only affect scenarios in which the value of the SourceLocExpr does not matter (overload resolution). Fixes llvm#106428 Fixes llvm#81155 Fixes llvm#80210 Fixes llvm#85373 --------- Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
@llvm/issue-subscribers-clang-frontend Author: Tristan Brindle (tcbrindle)
The following test program compiles with libc++17 and libstdc++, but fails with libc++18:
#include <concepts>
#include <functional>
#include <ranges>
#include <source_location>
#define FWD(x) static_cast<decltype(x)&&>(x)
struct add_fn {
template <std::integral T>
constexpr auto operator()(T lhs, T rhs,
std::source_location loc = std::source_location::current())
const -> T
{
return lhs + rhs;
}
};
inline constexpr auto add = add_fn{};
struct fold_op {
template <typename Rng, typename Func, typename Init>
constexpr auto operator()(Rng&& rng, Func func, Init init) const
{
auto init_ = std::ranges::range_value_t<Rng>(std::move(init));
for (auto&& elem : rng) {
init_ = std::invoke(func, std::move(init_), FWD(elem));
}
return init_;
}
};
inline constexpr auto fold = fold_op{};
auto sum(std::span<int const> arr) -> int
{
return fold(arr, add, 0);
} https://godbolt.org/z/h47dnM3eP The error is:
Removing the |
In llvm#78436 we made some SourceLocExpr dependent to deal with the fact that their value should reflect the name of specialized function - rather than the rtemplate in which they are first used. However SourceLocExpr are unusual in two ways - They don't depend on template arguments - They morally depend on the context in which they are used (rather than called from). It's fair to say that this is quite novels and confuses clang. In particular, in some cases, we used to create dependent SourceLocExpr and never subsequently transform them, leaving dependent objects in instantiated functions types. To work around that we avoid replacing SourceLocExpr when we think they could remain dependent. It's certainly not perfect but it fixes a number of reported bugs, and seem to only affect scenarios in which the value of the SourceLocExpr does not matter (overload resolution). Fixes llvm#106428 Fixes llvm#81155 Fixes llvm#80210 Fixes llvm#85373 --------- Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
Will there ever be a patch for clang-18? Or will this be broken for ever for this whole major version? |
@DNKpp We're in the LLVM 20 release cycle now, so fixes will only be back-ported to LLVM 19. |
The following test program compiles with libc++17 and libstdc++, but fails with libc++18:
https://godbolt.org/z/h47dnM3eP
The error is:
Removing the
source_location
default argument fromadd_fn::operator()
allows the code to compile as expected.The text was updated successfully, but these errors were encountered: