aboutsummaryrefslogtreecommitdiff
path: root/clang/test/SemaTemplate/concepts-recovery-expr.cpp
blob: 6bed1790051f38f708fdfea2f55e24116d5a00c5 (plain)
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
// RUN: %clang_cc1 -std=c++20 -verify %s

// expected-error@+1 {{invalid operands to binary expression ('const char[5]' and 'float')}}
constexpr bool CausesRecoveryExpr = "test" + 1.0f;

template<typename T>
concept ReferencesCRE = CausesRecoveryExpr;

template<typename T> requires CausesRecoveryExpr // #NVC1REQ
void NoViableCands1(){} // #NVC1

template<typename T> requires ReferencesCRE<T> // #NVC2REQ
void NoViableCands2(){} // #NVC2

template<ReferencesCRE T> // #NVC3REQ
void NoViableCands3(){} // #NVC3

void NVCUse() {
  NoViableCands1<int>();
  // expected-error@-1 {{no matching function for call to 'NoViableCands1'}}
  // expected-note@#NVC1{{candidate template ignored: constraints not satisfied}}
  // expected-note@#NVC1REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}

  NoViableCands2<int>();
  // expected-error@-1 {{no matching function for call to 'NoViableCands2'}}
  // expected-note@#NVC2{{candidate template ignored: constraints not satisfied}}
  // expected-note@#NVC2REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
  NoViableCands3<int>();
  // expected-error@-1 {{no matching function for call to 'NoViableCands3'}}
  // expected-note@#NVC3{{candidate template ignored: constraints not satisfied}}
  // expected-note@#NVC3REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
}

template<typename T> requires CausesRecoveryExpr // #OVC1REQ
void OtherViableCands1(){} // #OVC1

template<typename T>
void OtherViableCands1(){} // #OVC1_ALT

template<typename T> requires ReferencesCRE<T> // #OVC2REQ
void OtherViableCands2(){} // #OVC2

template<typename T>
void OtherViableCands2(){} // #OVC2_ALT

template<ReferencesCRE T> // #OVC3REQ
void OtherViableCands3(){} // #OVC3
template<typename T>
void OtherViableCands3(){} // #OVC3_ALT

void OVCUse() {
  OtherViableCands1<int>();
  // expected-error@-1 {{no matching function for call to 'OtherViableCands1'}}
  // expected-note@#OVC1_ALT {{candidate function}}
  // expected-note@#OVC1 {{candidate template ignored: constraints not satisfied}}
  // expected-note@#OVC1REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
  OtherViableCands2<int>();
  // expected-error@-1 {{no matching function for call to 'OtherViableCands2'}}
  // expected-note@#OVC2_ALT {{candidate function}}
  // expected-note@#OVC2 {{candidate template ignored: constraints not satisfied}}
  // expected-note@#OVC2REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
  OtherViableCands3<int>();
  // expected-error@-1 {{no matching function for call to 'OtherViableCands3'}}
  // expected-note@#OVC3_ALT {{candidate function}}
  // expected-note@#OVC3 {{candidate template ignored: constraints not satisfied}}
  // expected-note@#OVC3REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
}

template<typename T> requires CausesRecoveryExpr // #OBNVC1REQ
void OtherBadNoViableCands1(){} // #OBNVC1

template<typename T> requires false // #OBNVC1REQ_ALT
void OtherBadNoViableCands1(){} // #OBNVC1_ALT

template<typename T> requires ReferencesCRE<T> // #OBNVC2REQ
void OtherBadNoViableCands2(){} // #OBNVC2

template<typename T> requires false// #OBNVC2REQ_ALT
void OtherBadNoViableCands2(){} // #OBNVC2_ALT

template<ReferencesCRE T> // #OBNVC3REQ
void OtherBadNoViableCands3(){} // #OBNVC3
template<typename T> requires false // #OBNVC3REQ_ALT
void OtherBadNoViableCands3(){} // #OBNVC3_ALT

void OBNVCUse() {
  OtherBadNoViableCands1<int>();
  // expected-error@-1 {{no matching function for call to 'OtherBadNoViableCands1'}}
  // expected-note@#OBNVC1_ALT {{candidate template ignored: constraints not satisfied}}
  // expected-note@#OBNVC1REQ_ALT {{because 'false' evaluated to false}}
  // expected-note@#OBNVC1 {{candidate template ignored: constraints not satisfied}}
  // expected-note@#OBNVC1REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
  OtherBadNoViableCands2<int>();
  // expected-error@-1 {{no matching function for call to 'OtherBadNoViableCands2'}}
  // expected-note@#OBNVC2_ALT {{candidate template ignored: constraints not satisfied}}
  // expected-note@#OBNVC2REQ_ALT {{because 'false' evaluated to false}}
  // expected-note@#OBNVC2 {{candidate template ignored: constraints not satisfied}}
  // expected-note@#OBNVC2REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
  OtherBadNoViableCands3<int>();
  // expected-error@-1 {{no matching function for call to 'OtherBadNoViableCands3'}}
  // expected-note@#OBNVC3_ALT {{candidate template ignored: constraints not satisfied}}
  // expected-note@#OBNVC3REQ_ALT {{because 'false' evaluated to false}}
  // expected-note@#OBNVC3 {{candidate template ignored: constraints not satisfied}}
  // expected-note@#OBNVC3REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
}


// Same tests with member functions.
struct OVC {
template<typename T> requires CausesRecoveryExpr // #MEMOVC1REQ
void OtherViableCands1(){} // #MEMOVC1

template<typename T>
void OtherViableCands1(){} // #MEMOVC1_ALT

template<typename T> requires ReferencesCRE<T> // #MEMOVC2REQ
void OtherViableCands2(){} // #MEMOVC2

template<typename T>
void OtherViableCands2(){} // #MEMOVC2_ALT

template<ReferencesCRE T> // #MEMOVC3REQ
void OtherViableCands3(){} // #MEMOVC3
template<typename T>
void OtherViableCands3(){} // #MEMOVC3_ALT
};

void MemOVCUse() {
  OVC S;
  S.OtherViableCands1<int>();
  // expected-error@-1 {{no matching member function for call to 'OtherViableCands1'}}
  // expected-note@#MEMOVC1_ALT {{candidate function}}
  // expected-note@#MEMOVC1 {{candidate template ignored: constraints not satisfied}}
  // expected-note@#MEMOVC1REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
  S.OtherViableCands2<int>();
  // expected-error@-1 {{no matching member function for call to 'OtherViableCands2'}}
  // expected-note@#MEMOVC2_ALT {{candidate function}}
  // expected-note@#MEMOVC2 {{candidate template ignored: constraints not satisfied}}
  // expected-note@#MEMOVC2REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
  S.OtherViableCands3<int>();
  // expected-error@-1 {{no matching member function for call to 'OtherViableCands3'}}
  // expected-note@#MEMOVC3_ALT {{candidate function}}
  // expected-note@#MEMOVC3 {{candidate template ignored: constraints not satisfied}}
  // expected-note@#MEMOVC3REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
}

struct StaticOVC {
template<typename T> requires CausesRecoveryExpr // #SMEMOVC1REQ
static void OtherViableCands1(){} // #SMEMOVC1

template<typename T>
static void OtherViableCands1(){} // #SMEMOVC1_ALT

template<typename T> requires ReferencesCRE<T> // #SMEMOVC2REQ
static void OtherViableCands2(){} // #SMEMOVC2

template<typename T>
static void OtherViableCands2(){} // #SMEMOVC2_ALT

template<ReferencesCRE T> // #SMEMOVC3REQ
static void OtherViableCands3(){} // #SMEMOVC3
template<typename T>
static void OtherViableCands3(){} // #SMEMOVC3_ALT
};

void StaticMemOVCUse() {
  StaticOVC::OtherViableCands1<int>();
  // expected-error@-1 {{no matching function for call to 'OtherViableCands1'}}
  // expected-note@#SMEMOVC1_ALT {{candidate function}}
  // expected-note@#SMEMOVC1 {{candidate template ignored: constraints not satisfied}}
  // expected-note@#SMEMOVC1REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
  StaticOVC::OtherViableCands2<int>();
  // expected-error@-1 {{no matching function for call to 'OtherViableCands2'}}
  // expected-note@#SMEMOVC2_ALT {{candidate function}}
  // expected-note@#SMEMOVC2 {{candidate template ignored: constraints not satisfied}}
  // expected-note@#SMEMOVC2REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
  StaticOVC::OtherViableCands3<int>();
  // expected-error@-1 {{no matching function for call to 'OtherViableCands3'}}
  // expected-note@#SMEMOVC3_ALT {{candidate function}}
  // expected-note@#SMEMOVC3 {{candidate template ignored: constraints not satisfied}}
  // expected-note@#SMEMOVC3REQ{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
}

namespace GH58548 {

template <class, class> struct formatter; // #primary-template
template <class, class> struct basic_format_context {};

template <typename CharType>
concept has_format_function =
    format(basic_format_context<CharType, CharType>());

template <typename ValueType, typename CharType>
  requires has_format_function<CharType>
struct formatter<ValueType, CharType> {
  template <typename OutputIt>
  CharType format(basic_format_context<OutputIt, CharType>);
};

template <class Ctx> int handle_replacement_field(Ctx arg) {
  formatter<decltype(arg), int> ctx; // expected-error {{implicit instantiation of undefined template}}
  return 0;
}

int x = handle_replacement_field(0);
// expected-note@-1 {{template specialization 'GH58548::handle_replacement_field<int>' requested here}}
// expected-note@#primary-template {{is declared here}}

} // GH58548