This patch will finally allow us to mark C++17 support in clang as
complete.
In order to implement this as a DR and avoid breaking reasonable code
that worked before P0522, this patch implements a provisional resolution
for CWG2398: When deducing template template parameters against each other,
and the argument side names a template specialization, instead of just
deducing A, we deduce a synthesized template template parameter based
on A, but with it's parameters using the template specialization's arguments
as defaults.
The driver flag is deprecated with a warning.
Fixes https://github.com/llvm/llvm-project/issues/36505
140 lines
5.3 KiB
C++
140 lines
5.3 KiB
C++
// RUN: %clang_cc1 %s -fsyntax-only -std=c++23 -verify=expected,new
|
|
// RUN: %clang_cc1 %s -fsyntax-only -std=c++23 -fno-relaxed-template-template-args -verify=expected,old
|
|
|
|
namespace issue1 {
|
|
template<class T, class U = T> class B {};
|
|
template<template<class> class P, class T> void f(P<T>);
|
|
// new-note@-1 {{deduced type 'B<[...], (default) int>' of 1st parameter does not match adjusted type 'B<[...], float>' of argument [with P = issue1::B, T = int]}}
|
|
// old-note@-2 2{{template template argument has different template parameters}}
|
|
|
|
void g() {
|
|
f(B<int>()); // old-error {{no matching function for call}}
|
|
f(B<int,float>()); // expected-error {{no matching function for call}}
|
|
}
|
|
} // namespace issue1
|
|
|
|
namespace issue2 {
|
|
template<typename> struct match;
|
|
|
|
template<template<typename> class t,typename T> struct match<t<T>>;
|
|
|
|
template<template<typename,typename> class t,typename T0,typename T1>
|
|
struct match<t<T0,T1>> {};
|
|
|
|
template<typename,typename = void> struct other {};
|
|
template struct match<other<void,void>>;
|
|
} // namespace issue2
|
|
|
|
namespace type {
|
|
template<class T1, class T2 = float> struct A;
|
|
|
|
template<class T3> struct B;
|
|
template<template<class T4 > class TT1, class T5 > struct B<TT1<T5 >> ;
|
|
template<template<class T6, class T7> class TT2, class T8, class T9> struct B<TT2<T8, T9>> {};
|
|
template struct B<A<int>>;
|
|
} // namespace type
|
|
|
|
namespace value {
|
|
template<class T1, int V1 = 1> struct A;
|
|
|
|
template<class T2> struct B;
|
|
template<template<class T3 > class TT1, class T4 > struct B<TT1<T4 >> ;
|
|
template<template<class T5, int V2> class TT2, class T6, int V3> struct B<TT2<T6, V3>> {};
|
|
template struct B<A<int>>;
|
|
} // namespace value
|
|
|
|
namespace templ {
|
|
template <class T1> struct A;
|
|
|
|
template<class T2, template <class T3> class T4 = A> struct B {};
|
|
|
|
template<class T5> struct C;
|
|
|
|
template<template<class T6> class TT1, class T7> struct C<TT1<T7>>;
|
|
|
|
template<template<class T8, template <class T9> class> class TT2,
|
|
class T10, template <class T11> class TT3>
|
|
struct C<TT2<T10, TT3>> {};
|
|
|
|
template struct C<B<int>>;
|
|
} // namespace templ
|
|
|
|
namespace type_pack1 {
|
|
template<class T2> struct A;
|
|
template<template<class ...T3s> class TT1, class T4> struct A<TT1<T4>> ;
|
|
// new-note@-1 {{partial specialization matches}}
|
|
template<template<class T5 > class TT2, class T6> struct A<TT2<T6>> {};
|
|
// new-note@-1 {{partial specialization matches}}
|
|
|
|
template<class T1> struct B;
|
|
template struct A<B<char>>;
|
|
// new-error@-1 {{ambiguous partial specialization}}
|
|
} // namespace type_pack1
|
|
|
|
namespace type_pack2 {
|
|
template<class T2> struct A;
|
|
template<template<class ...T3s> class TT1, class ...T4> struct A<TT1<T4...>> ;
|
|
// new-note@-1 {{partial specialization matches}}
|
|
template<template<class T5 > class TT2, class ...T6> struct A<TT2<T6...>> {};
|
|
// new-note@-1 {{partial specialization matches}}
|
|
|
|
template<class T1> struct B;
|
|
template struct A<B<char>>;
|
|
// new-error@-1 {{ambiguous partial specialization}}
|
|
} // namespace type_pack2
|
|
|
|
namespace type_pack3 {
|
|
template<class T1, class T2 = float> struct A;
|
|
|
|
template<class T3> struct B;
|
|
|
|
template<template<class T4 > class TT1, class T5 > struct B<TT1<T5 >>;
|
|
// new-note@-1 {{template is declared here}}
|
|
template<template<class T6, class ...T7s> class TT2, class T8, class ...T9s> struct B<TT2<T8, T9s...>>;
|
|
// old-note@-1 {{template is declared here}}
|
|
|
|
template struct B<A<int>>;
|
|
// expected-error@-1 {{explicit instantiation of undefined template}}
|
|
} // namespace type_pack3
|
|
|
|
namespace gcc_issue {
|
|
template<class T1, class T2> struct A;
|
|
|
|
template<template<class T1> class TT1, class T2> struct A<TT1<T2>, typename TT1<T2>::type>;
|
|
// new-note@-1 {{partial specialization matches}}
|
|
|
|
template<template<class T3, class T4> class TT2, class T5, class T6>
|
|
struct A<TT2<T5, T6>, typename TT2<T5, T5>::type>;
|
|
// new-note@-1 {{partial specialization matches}}
|
|
// old-note@-2 {{template is declared here}}
|
|
|
|
template <class T7, class T8 = T7> struct B { using type = int; };
|
|
|
|
template struct A<B<int>, int>;
|
|
// new-error@-1 {{ambiguous partial specializations}}
|
|
// old-error@-2 {{explicit instantiation of undefined template}}
|
|
} // namespace gcc_issue
|
|
|
|
namespace ttp_defaults {
|
|
template <template <class T1> class TT1> struct A {};
|
|
// old-note@-1 2{{previous template template parameter}}
|
|
|
|
template <template <class T2> class TT2> void f(A<TT2>);
|
|
// new-note@-1 {{explicit instantiation candidate}}
|
|
// old-note@-2 {{invalid explicitly-specified argument for template parameter 'TT2'}}
|
|
|
|
// FIXME: The default arguments on the TTP are not available during partial ordering.
|
|
template <template <class T3, class T4 = float> class TT3> void f(A<TT3>) {};
|
|
// new-note@-1 {{explicit instantiation candidate}}
|
|
// old-error@-2 {{template template argument has different template parameters}}
|
|
// old-note@-3 {{too many template parameters}}
|
|
|
|
template <class T5, class T6 = int> struct B;
|
|
// old-note@-1 {{too many template parameters}}
|
|
|
|
template void f<B>(A<B>);
|
|
// new-error@-1 {{partial ordering for explicit instantiation of 'f' is ambiguous}}
|
|
// old-error@-2 {{template template argument has different template parameters}}
|
|
// old-error@-3 {{explicit instantiation of 'f' does not refer to a function template}}
|
|
} // namespace ttp_defaults
|