
When a specialization was ambiguous, we would mark it as invalid, even if the specialization occured in an immediate context. This would subsequently lead to scenarios where invalid specialization produced no diagnostics, causing crashes during codegen. Fixes #51866
76 lines
2.2 KiB
C++
76 lines
2.2 KiB
C++
// RUN: %clang_cc1 -std=c++26 %s -verify
|
|
|
|
namespace hana_enable_if_idiom {
|
|
template<bool> struct A {};
|
|
template<typename, typename = A<true>> struct B;
|
|
template<typename T, bool N> struct B<T, A<N>> {};
|
|
template<typename T> struct B<T, A<T::value>> {};
|
|
struct C {
|
|
static const bool value = true;
|
|
};
|
|
B<C> b;
|
|
}
|
|
|
|
namespace GH132562 {
|
|
struct I {
|
|
int v = 0;
|
|
};
|
|
|
|
namespace t1 {
|
|
template <I... X> struct A;
|
|
template <I... X>
|
|
requires ((X.v == 0) ||...)
|
|
struct A<X...>;
|
|
} // namespace t1
|
|
namespace t2 {
|
|
template <I... X> struct A; // expected-note {{template is declared here}}
|
|
template <int... X> struct A<X...>;
|
|
// expected-error@-1 {{is not more specialized than the primary template}}
|
|
// expected-note@-2 {{no viable conversion from 'int' to 'I'}}
|
|
|
|
template <int... X> struct B; // expected-note {{template is declared here}}
|
|
template <I... X> struct B<X...>;
|
|
// expected-error@-1 {{is not more specialized than the primary template}}
|
|
// expected-note@-2 {{value of type 'const I' is not implicitly convertible to 'int'}}
|
|
} // namespace t2
|
|
namespace t3 {
|
|
struct J {
|
|
int v = 0;
|
|
constexpr J(int v) : v(v) {}
|
|
};
|
|
template <J... X> struct A;
|
|
template <int... X> struct A<X...>;
|
|
|
|
template <int... X> struct B; // expected-note {{template is declared here}}
|
|
template <J... X> struct B<X...>;
|
|
// expected-error@-1 {{is not more specialized than the primary template}}
|
|
// expected-note@-2 {{value of type 'const J' is not implicitly convertible to 'int'}}
|
|
} // namespace t3
|
|
} // namespace GH132562
|
|
|
|
namespace GH51866 {
|
|
|
|
template <class> struct Trait;
|
|
template <class T>
|
|
requires T::one
|
|
struct Trait<T> {}; // #gh51866-one
|
|
template <class T>
|
|
requires T::two
|
|
struct Trait<T> {}; // #gh51866-two
|
|
|
|
struct Y {
|
|
static constexpr bool one = true;
|
|
static constexpr bool two = true;
|
|
};
|
|
|
|
template <class T>
|
|
concept C = sizeof(Trait<T>) != 0;
|
|
|
|
static_assert(!C<Y>);
|
|
|
|
Trait<Y> t;
|
|
// expected-error@-1{{ambiguous partial specializations of 'Trait<GH51866::Y>'}}
|
|
// expected-note@#gh51866-one{{partial specialization matches}}
|
|
// expected-note@#gh51866-two{{partial specialization matches}}
|
|
}
|