-
Notifications
You must be signed in to change notification settings - Fork 15.3k
Open
Labels
clang:frontendLanguage frontend issues, e.g. anything involving "Sema"Language frontend issues, e.g. anything involving "Sema"diverges-from:gccDoes the clang frontend diverge from gcc on this issueDoes the clang frontend diverge from gcc on this issuediverges-from:msvcDoes the clang frontend diverge from msvc on this issueDoes the clang frontend diverge from msvc on this issuelambdaC++11 lambda expressionsC++11 lambda expressionsneeds-reductionLarge reproducer that should be reduced into a simpler formLarge reproducer that should be reduced into a simpler form
Description
Example code could be found below or on godbolt. clang 14, gcc and MSVC all compile fine. clang 15 onwards fail.
The problem is triggered only if tc_lazy is called in a template function and the lambda in tc_lazy is a generic lambda.
#include <type_traits>
#include <utility>
#define HYBRIDSTR(str) \
[](auto t) constexpr noexcept -> decltype(auto) { \
using ArgCharT = typename decltype(t)::type; \
if constexpr(std::is_same<ArgCharT, char>::value) { \
return str; \
} else if constexpr(std::is_same<ArgCharT, wchar_t>::value) { \
return L ## str; \
} else if constexpr(std::is_same<ArgCharT, char16_t>::value) { \
return u ## str; \
} else { \
static_assert(std::is_same<ArgCharT, char32_t>::value); \
return U ## str; \
} \
}
namespace tc {
template<typename T>
constexpr std::conditional_t<
std::is_rvalue_reference<T&&>::value,
std::decay_t<T>,
T
> lvalue_or_decay(T&& t) {
return std::forward<T>(t);
}
namespace make_lazy_adl {
template<typename Func>
struct make_lazy : Func {
constexpr explicit make_lazy(Func func) noexcept : Func(std::move(func)) {}
constexpr operator decltype(std::declval<Func const&>()())() const&& {
return (*this)();
}
};
}
using make_lazy_adl::make_lazy;
namespace lazy_detail {
template<bool bReference, typename T>
decltype(auto) lvalue_or_decay(T&& t) noexcept {
if constexpr (bReference) {
return tc::lvalue_or_decay(std::forward<T>(t));
}
}
}
}
#define tc_lazy( ... ) tc::make_lazy([&](auto&&...) -> decltype(auto) { \
if constexpr (std::is_reference<decltype((__VA_ARGS__))>::value) { \
return tc::lazy_detail::lvalue_or_decay<std::is_reference<decltype((__VA_ARGS__))>::value>(__VA_ARGS__); \
} else { \
return __VA_ARGS__; \
} \
})
template<typename Char>
auto foo() {
return tc_lazy(HYBRIDSTR("abc")(std::type_identity<Char>()))(); // fails in template function from clang 15 onwards
}
void bar() {
tc_lazy(0)();
tc_lazy(HYBRIDSTR("abc")(std::type_identity<char16_t>()))(); // compiles
foo<char16_t>();
}
Metadata
Metadata
Assignees
Labels
clang:frontendLanguage frontend issues, e.g. anything involving "Sema"Language frontend issues, e.g. anything involving "Sema"diverges-from:gccDoes the clang frontend diverge from gcc on this issueDoes the clang frontend diverge from gcc on this issuediverges-from:msvcDoes the clang frontend diverge from msvc on this issueDoes the clang frontend diverge from msvc on this issuelambdaC++11 lambda expressionsC++11 lambda expressionsneeds-reductionLarge reproducer that should be reduced into a simpler formLarge reproducer that should be reduced into a simpler form