llvm-project/clang/test/SemaTemplate/partial-order.cpp
Corentin Jabot e29ac9bc2e
[Clang] Do not mark ambiguous specialization invalid. (#147275)
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
2025-07-08 17:41:11 +02:00

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}}
}