File: temp_arg_template_p0522.cpp

package info (click to toggle)
llvm-toolchain-21 1%3A21.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,235,796 kB
  • sloc: cpp: 7,617,614; ansic: 1,433,901; asm: 1,058,726; python: 252,096; f90: 94,671; objc: 70,753; lisp: 42,813; pascal: 18,401; sh: 10,032; ml: 5,111; perl: 4,720; awk: 3,523; makefile: 3,401; javascript: 2,272; xml: 892; fortran: 770
file content (170 lines) | stat: -rw-r--r-- 7,577 bytes parent folder | download | duplicates (6)
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