1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
// expected-note@temp_arg_template_p0522.cpp:* 1+{{template is declared here}}
// expected-note@temp_arg_template_p0522.cpp:* 1+{{template parameter is declared here}}
// expected-note@temp_arg_template_p0522.cpp:* 1+{{previous template template parameter is here}}
template<template<int> typename> struct Ti; // #Ti
template<template<int...> typename> struct TPi; // #TPi
template<template<int, int...> typename> struct TiPi;
template<template<int..., int...> typename> struct TPiPi;
// expected-error@-1 {{template parameter pack must be the last template parameter}}
template<typename T, template<T> typename> struct tT0; // #tT0
template<template<typename T, T> typename> struct Tt0; // #Tt0
template<template<typename> typename> struct Tt;
template<template<typename, typename...> typename> struct TtPt;
template<int> struct i;
template<int, int = 0> struct iDi;
template<int, int> struct ii;
template<int...> struct Pi;
template<int, int, int...> struct iiPi;
template<int, typename = int> struct iDt; // #iDt
template<int, typename> struct it; // #it
template<typename T, T v> struct t0;
template<typename...> struct Pt;
namespace IntParam {
using ok = Pt<Ti<i>,
Ti<iDi>,
Ti<Pi>,
Ti<iDt>>;
using err1 = Ti<ii>; // expected-error {{too few template arguments for class template 'ii'}}
// expected-note@-1 {{different template parameters}}
using err2 = Ti<iiPi>; // expected-error {{too few template arguments for class template 'iiPi'}}
// expected-note@-1 {{different template parameters}}
using err3 = Ti<t0>; // expected-error@#Ti {{template argument for template type parameter must be a type}}
// expected-note@-1 {{different template parameters}}
using err4 = Ti<it>; // expected-error {{too few template arguments for class template 'it'}}
// expected-note@-1 {{different template parameters}}
}
// These are accepted by the backwards-compatibility "parameter pack in
// parameter matches any number of parameters in arguments" rule.
namespace IntPackParam {
using ok = TPi<Pi>;
using ok_compat = Pt<TPi<i>, TPi<iDi>, TPi<ii>, TPi<iiPi>>;
using err1 = TPi<t0>; // expected-error@#TPi {{template argument for template type parameter must be a type}}
// expected-note@-1 {{different template parameters}}
using err2 = TPi<iDt>; // expected-error@#TPi {{template argument for template type parameter must be a type}}
// expected-note@-1 {{different template parameters}}
using err3 = TPi<it>; // expected-error@#TPi {{template argument for template type parameter must be a type}}
// expected-note@-1 {{different template parameters}}
}
namespace IntAndPackParam {
using ok = TiPi<Pi>;
using ok_compat = Pt<TiPi<ii>, TiPi<iDi>, TiPi<iiPi>>;
using err = TiPi<iDi>;
}
namespace DependentType {
using ok = Pt<tT0<int, i>, tT0<int, iDi>>;
using err1 = tT0<int, ii>; // expected-error {{too few template arguments for class template 'ii'}}
// expected-note@-1 {{different template parameters}}
using err2 = tT0<short, i>;
using err2a = tT0<long long, i>; // expected-error@#tT0 {{cannot be narrowed from type 'long long' to 'int'}}
// expected-note@-1 {{different template parameters}}
using err2b = tT0<void*, i>; // expected-error@#tT0 {{value of type 'void *' is not implicitly convertible to 'int'}}
// expected-note@-1 {{different template parameters}}
using err3 = tT0<short, t0>; // expected-error@#tT0 {{template argument for template type parameter must be a type}}
// expected-note@-1 {{different template parameters}}
using ok2 = Tt0<t0>;
using err4 = Tt0<it>; // expected-error@#Tt0 {{template argument for non-type template parameter must be an expression}}
// expected-note@-1 {{different template parameters}}
}
namespace Auto {
template<template<int> typename T> struct TInt {}; // #TInt
template<template<int*> typename T> struct TIntPtr {}; // #TIntPtr
template<template<auto> typename T> struct TAuto {};
template<template<auto*> typename T> struct TAutoPtr {};
template<template<decltype(auto)> typename T> struct TDecltypeAuto {};
template<auto> struct Auto;
template<auto*> struct AutoPtr; // #AutoPtr
template<decltype(auto)> struct DecltypeAuto;
template<int> struct Int;
template<int*> struct IntPtr;
TInt<Auto> ia;
TInt<AutoPtr> iap; // expected-error@#TInt {{non-type template parameter '' with type 'auto *' has incompatible initializer of type 'int'}}
// expected-note@-1 {{different template parameters}}
TInt<DecltypeAuto> ida;
TInt<Int> ii;
TInt<IntPtr> iip; // expected-error@#TInt {{conversion from 'int' to 'int *' is not allowed in a converted constant expression}}
// expected-note@-1 {{different template parameters}}
TIntPtr<Auto> ipa;
TIntPtr<AutoPtr> ipap;
TIntPtr<DecltypeAuto> ipda;
TIntPtr<Int> ipi; // expected-error@#TIntPtr {{value of type 'int *' is not implicitly convertible to 'int'}}
// expected-note@-1 {{different template parameters}}
TIntPtr<IntPtr> ipip;
TAuto<Auto> aa;
TAuto<AutoPtr> aap; // expected-error@#AutoPtr {{could not match 'auto *' against 'auto'}}
// expected-note@-1 {{different template parameters}}
TAuto<Int> ai; // FIXME: ill-formed (?)
TAuto<IntPtr> aip; // FIXME: ill-formed (?)
TAutoPtr<Auto> apa;
TAutoPtr<AutoPtr> apap;
TAutoPtr<Int> api; // FIXME: ill-formed (?)
TAutoPtr<IntPtr> apip; // FIXME: ill-formed (?)
TDecltypeAuto<DecltypeAuto> dada;
TDecltypeAuto<Int> dai; // FIXME: ill-formed (?)
TDecltypeAuto<IntPtr> daip; // FIXME: ill-formed (?)
// FIXME: It's completely unclear what should happen here, but these results
// seem at least plausible:
TAuto<DecltypeAuto> ada;
TAutoPtr<DecltypeAuto> apda;
// Perhaps this case should be invalid, as there are valid 'decltype(auto)'
// parameters (such as 'user-defined-type &') that are not valid 'auto'
// parameters.
TDecltypeAuto<Auto> daa;
TDecltypeAuto<AutoPtr> daap; // expected-error@#AutoPtr {{could not match 'auto *' against 'decltype(auto)'}}
// expected-note@-1 {{different template parameters}}
int n;
template<auto A, decltype(A) B = &n> struct SubstFailure;
TInt<SubstFailure> isf; // FIXME: this should be ill-formed
TIntPtr<SubstFailure> ipsf;
}
namespace GH62529 {
// Note: the constraint here is just for bypassing a fast-path.
template<class T1> requires(true) using A = int;
template<template<class ...T2s> class TT1, class T3> struct B {};
template<class T4> B<A, T4> f();
auto t = f<int>();
} // namespace GH62529
namespace GH101394 {
struct X {}; // #X
struct Y {
constexpr Y(const X &) {}
};
namespace t1 {
template<template<X> class> struct A {};
template<Y> struct B;
template struct A<B>;
} // namespace t1
namespace t2 {
template<template<Y> class> struct A {}; // #A
template<X> struct B; // #B
template struct A<B>;
// expected-error@#A {{no viable conversion from 'const Y' to 'X'}}
// expected-note@-2 {{different template parameters}}
// expected-note@#X 2{{not viable}}
// expected-note@#B {{passing argument to parameter here}}
} // namespace t2
} // namespace GH101394
|