
In the last patch #82310, we used template depths to tell if such alias decls contain lambdas, which is wrong because the lambda can also appear as a part of the default argument, and that would make `getTemplateInstantiationArgs` provide extra template arguments in undesired contexts. This leads to issue #89853. Moreover, our approach for https://github.com/llvm/llvm-project/issues/82104 was sadly wrong. We tried to teach `DeduceReturnType` to consider alias template arguments; however, giving these arguments in the context where they should have been substituted in a `TransformCallExpr` call is never correct. This patch addresses such problems by using a `RecursiveASTVisitor` to check if the lambda is contained by an alias `Decl`, as well as twiddling the lambda dependencies - we should also build a dependent lambda expression if the surrounding alias template arguments were dependent. Fixes #89853 Fixes #102760 Fixes #105885
175 lines
5.3 KiB
C++
175 lines
5.3 KiB
C++
// RUN: %clang_cc1 -std=c++2c -fsyntax-only -verify %s
|
|
namespace lambda_calls {
|
|
|
|
template <class>
|
|
concept True = true;
|
|
|
|
template <class>
|
|
concept False = false; // #False
|
|
|
|
template <class T> struct S {
|
|
template <class... U> using type = decltype([](U...) {}(U()...));
|
|
template <class U> using type2 = decltype([](auto) {}(1));
|
|
template <class U> using type3 = decltype([](True auto) {}(1));
|
|
template <class>
|
|
using type4 = decltype([](auto... pack) { return sizeof...(pack); }(1, 2));
|
|
|
|
template <class U> using type5 = decltype([](False auto...) {}(1)); // #Type5
|
|
|
|
template <class U>
|
|
using type6 = decltype([]<True> {}.template operator()<char>());
|
|
template <class U>
|
|
using type7 = decltype([]<False> {}.template operator()<char>()); // #Type7
|
|
|
|
template <class U>
|
|
using type8 = decltype([]() // #Type8
|
|
requires(sizeof(U) == 32) // #Type8-requirement
|
|
{}());
|
|
|
|
template <class... U>
|
|
using type9 = decltype([]<True>(U...) {}.template operator()<char>(U()...));
|
|
// https://github.com/llvm/llvm-project/issues/76674
|
|
template <class U>
|
|
using type10 = decltype([]<class V> { return V(); }.template operator()<U>());
|
|
|
|
template <class U> using type11 = decltype([] { return U{}; });
|
|
};
|
|
|
|
template <class> using Meow = decltype([]<True> {}.template operator()<int>());
|
|
|
|
template <class... U>
|
|
using MeowMeow = decltype([]<True>(U...) {}.template operator()<char>(U()...));
|
|
|
|
// https://github.com/llvm/llvm-project/issues/70601
|
|
template <class> using U = decltype([]<True> {}.template operator()<int>());
|
|
|
|
U<int> foo();
|
|
|
|
void bar() {
|
|
using T = S<int>::type<int, int, int>;
|
|
using T2 = S<int>::type2<int>;
|
|
using T3 = S<int>::type3<char>;
|
|
using T4 = S<int>::type4<void>;
|
|
using T5 = S<int>::type5<void>; // #T5
|
|
// expected-error@#Type5 {{no matching function for call}}
|
|
// expected-note@#T5 {{type alias 'type5' requested here}}
|
|
// expected-note@#Type5 {{constraints not satisfied [with auto:1 = <int>]}}
|
|
// expected-note@#Type5 {{because 'int' does not satisfy 'False'}}
|
|
// expected-note@#False {{because 'false' evaluated to false}}
|
|
|
|
using T6 = S<int>::type6<void>;
|
|
using T7 = S<int>::type7<void>; // #T7
|
|
// expected-error@#Type7 {{no matching member function for call}}
|
|
// expected-note@#T7 {{type alias 'type7' requested here}}
|
|
// expected-note@#Type7 {{constraints not satisfied [with $0 = char]}}
|
|
// expected-note@#Type7 {{because 'char' does not satisfy 'False'}}
|
|
// expected-note@#False {{because 'false' evaluated to false}}
|
|
|
|
using T8 = S<int>::type8<char>; // #T8
|
|
// expected-error@#Type8 {{no matching function for call}}
|
|
// expected-note@#T8 {{type alias 'type8' requested here}}
|
|
// expected-note@#Type8 {{constraints not satisfied}}
|
|
// expected-note@#Type8-requirement {{because 'sizeof(char) == 32' (1 == 32) evaluated to false}}
|
|
|
|
using T9 = S<int>::type9<long, long, char>;
|
|
using T10 = S<int>::type10<int>;
|
|
using T11 = S<int>::type11<int>;
|
|
int x = T11()();
|
|
using T12 = Meow<int>;
|
|
using T13 = MeowMeow<char, int, long, unsigned>;
|
|
|
|
static_assert(__is_same(T, void));
|
|
static_assert(__is_same(T2, void));
|
|
static_assert(__is_same(T3, void));
|
|
static_assert(__is_same(T4, decltype(sizeof(0))));
|
|
static_assert(__is_same(T6, void));
|
|
static_assert(__is_same(T9, void));
|
|
static_assert(__is_same(T10, int));
|
|
static_assert(__is_same(T12, void));
|
|
static_assert(__is_same(T13, void));
|
|
}
|
|
|
|
namespace GH82104 {
|
|
|
|
template <typename, typename... D> constexpr int Value = sizeof...(D);
|
|
|
|
template <typename T, typename... U>
|
|
using T14 = decltype([]<int V = 0>(auto Param) {
|
|
return Value<T, U...> + V + (int)sizeof(Param);
|
|
}("hello"));
|
|
|
|
template <typename T> using T15 = T14<T, T>;
|
|
|
|
static_assert(__is_same(T15<char>, int));
|
|
|
|
// FIXME: This still crashes because we can't extract template arguments T and U
|
|
// outside of the instantiation context of T16.
|
|
#if 0
|
|
template <typename T, typename... U>
|
|
using T16 = decltype([](auto Param) requires (sizeof(Param) != 1 && sizeof...(U) > 0) {
|
|
return Value<T, U...> + sizeof(Param);
|
|
});
|
|
static_assert(T16<int, char, float>()(42) == 2 + sizeof(42));
|
|
#endif
|
|
} // namespace GH82104
|
|
|
|
namespace GH89853 {
|
|
|
|
template <typename = void>
|
|
static constexpr auto innocuous = []<int m> { return m; };
|
|
|
|
template <auto Pred = innocuous<>>
|
|
using broken = decltype(Pred.template operator()<42>());
|
|
|
|
broken<> *boom;
|
|
|
|
template <auto Pred =
|
|
[]<char c> {
|
|
(void)static_cast<char>(c);
|
|
}>
|
|
using broken2 = decltype(Pred.template operator()<42>());
|
|
|
|
broken2<> *boom2;
|
|
|
|
template <auto Pred = []<char m> { return m; }>
|
|
using broken3 = decltype(Pred.template operator()<42>());
|
|
|
|
broken3<> *boom3;
|
|
|
|
static constexpr auto non_default = []<char c>(True auto) {
|
|
(void) static_cast<char>(c);
|
|
};
|
|
|
|
template<True auto Pred>
|
|
using broken4 = decltype(Pred.template operator()<42>(Pred));
|
|
|
|
broken4<non_default>* boom4;
|
|
|
|
} // namespace GH89853
|
|
|
|
namespace GH105885 {
|
|
|
|
template<int>
|
|
using test = decltype([](auto...) {
|
|
}());
|
|
|
|
static_assert(__is_same(test<0>, void));
|
|
|
|
} // namespace GH105885
|
|
|
|
namespace GH102760 {
|
|
|
|
auto make_tuple = []< class Tag, class... Captures>(Tag, Captures...) {
|
|
return []< class _Fun >( _Fun) -> void requires requires { 0; }
|
|
{};
|
|
};
|
|
|
|
template < class, class... _As >
|
|
using Result = decltype(make_tuple(0)(_As{}...));
|
|
|
|
using T = Result<int, int>;
|
|
|
|
} // namespace GH102760
|
|
|
|
} // namespace lambda_calls
|