annotate gcc/cp/constraint.cc @ 120:f93fa5091070

fix conv1.c
author mir3636
date Thu, 08 Mar 2018 14:53:42 +0900
parents 04ced10e8804
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Processing rules for constraints.
kono
parents:
diff changeset
2 Copyright (C) 2013-2017 Free Software Foundation, Inc.
kono
parents:
diff changeset
3 Contributed by Andrew Sutton (andrew.n.sutton@gmail.com)
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify
kono
parents:
diff changeset
8 it under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
9 the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
10 any later version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful,
kono
parents:
diff changeset
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kono
parents:
diff changeset
15 GNU General Public License for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 #include "config.h"
kono
parents:
diff changeset
22 #include "system.h"
kono
parents:
diff changeset
23 #include "coretypes.h"
kono
parents:
diff changeset
24 #include "tm.h"
kono
parents:
diff changeset
25 #include "timevar.h"
kono
parents:
diff changeset
26 #include "hash-set.h"
kono
parents:
diff changeset
27 #include "machmode.h"
kono
parents:
diff changeset
28 #include "vec.h"
kono
parents:
diff changeset
29 #include "double-int.h"
kono
parents:
diff changeset
30 #include "input.h"
kono
parents:
diff changeset
31 #include "alias.h"
kono
parents:
diff changeset
32 #include "symtab.h"
kono
parents:
diff changeset
33 #include "wide-int.h"
kono
parents:
diff changeset
34 #include "inchash.h"
kono
parents:
diff changeset
35 #include "tree.h"
kono
parents:
diff changeset
36 #include "stringpool.h"
kono
parents:
diff changeset
37 #include "attribs.h"
kono
parents:
diff changeset
38 #include "intl.h"
kono
parents:
diff changeset
39 #include "flags.h"
kono
parents:
diff changeset
40 #include "cp-tree.h"
kono
parents:
diff changeset
41 #include "c-family/c-common.h"
kono
parents:
diff changeset
42 #include "c-family/c-objc.h"
kono
parents:
diff changeset
43 #include "cp-objcp-common.h"
kono
parents:
diff changeset
44 #include "tree-inline.h"
kono
parents:
diff changeset
45 #include "decl.h"
kono
parents:
diff changeset
46 #include "toplev.h"
kono
parents:
diff changeset
47 #include "type-utils.h"
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49 /*---------------------------------------------------------------------------
kono
parents:
diff changeset
50 Operations on constraints
kono
parents:
diff changeset
51 ---------------------------------------------------------------------------*/
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53 /* Returns true if C is a constraint tree code. Note that ERROR_MARK
kono
parents:
diff changeset
54 is a valid constraint. */
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 static inline bool
kono
parents:
diff changeset
57 constraint_p (tree_code c)
kono
parents:
diff changeset
58 {
kono
parents:
diff changeset
59 return ((PRED_CONSTR <= c && c <= DISJ_CONSTR)
kono
parents:
diff changeset
60 || c == EXPR_PACK_EXPANSION
kono
parents:
diff changeset
61 || c == ERROR_MARK);
kono
parents:
diff changeset
62 }
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 /* Returns true if T is a constraint. Note that error_mark_node
kono
parents:
diff changeset
65 is a valid constraint. */
kono
parents:
diff changeset
66
kono
parents:
diff changeset
67 bool
kono
parents:
diff changeset
68 constraint_p (tree t)
kono
parents:
diff changeset
69 {
kono
parents:
diff changeset
70 return constraint_p (TREE_CODE (t));
kono
parents:
diff changeset
71 }
kono
parents:
diff changeset
72
kono
parents:
diff changeset
73 /* Returns the conjunction of two constraints A and B. Note that
kono
parents:
diff changeset
74 conjoining a non-null constraint with NULL_TREE is an identity
kono
parents:
diff changeset
75 operation. That is, for non-null A,
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 conjoin_constraints(a, NULL_TREE) == a
kono
parents:
diff changeset
78
kono
parents:
diff changeset
79 and
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 conjoin_constraints (NULL_TREE, a) == a
kono
parents:
diff changeset
82
kono
parents:
diff changeset
83 If both A and B are NULL_TREE, the result is also NULL_TREE. */
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 tree
kono
parents:
diff changeset
86 conjoin_constraints (tree a, tree b)
kono
parents:
diff changeset
87 {
kono
parents:
diff changeset
88 gcc_assert (a ? constraint_p (a) : true);
kono
parents:
diff changeset
89 gcc_assert (b ? constraint_p (b) : true);
kono
parents:
diff changeset
90 if (a)
kono
parents:
diff changeset
91 return b ? build_nt (CONJ_CONSTR, a, b) : a;
kono
parents:
diff changeset
92 else if (b)
kono
parents:
diff changeset
93 return b;
kono
parents:
diff changeset
94 else
kono
parents:
diff changeset
95 return NULL_TREE;
kono
parents:
diff changeset
96 }
kono
parents:
diff changeset
97
kono
parents:
diff changeset
98 /* Transform the vector of expressions in the T into a conjunction
kono
parents:
diff changeset
99 of requirements. T must be a TREE_VEC. */
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 tree
kono
parents:
diff changeset
102 conjoin_constraints (tree t)
kono
parents:
diff changeset
103 {
kono
parents:
diff changeset
104 gcc_assert (TREE_CODE (t) == TREE_VEC);
kono
parents:
diff changeset
105 tree r = NULL_TREE;
kono
parents:
diff changeset
106 for (int i = 0; i < TREE_VEC_LENGTH (t); ++i)
kono
parents:
diff changeset
107 r = conjoin_constraints (r, TREE_VEC_ELT (t, i));
kono
parents:
diff changeset
108 return r;
kono
parents:
diff changeset
109 }
kono
parents:
diff changeset
110
kono
parents:
diff changeset
111 /* Returns true if T is a call expression to a function
kono
parents:
diff changeset
112 concept. */
kono
parents:
diff changeset
113
kono
parents:
diff changeset
114 bool
kono
parents:
diff changeset
115 function_concept_check_p (tree t)
kono
parents:
diff changeset
116 {
kono
parents:
diff changeset
117 gcc_assert (TREE_CODE (t) == CALL_EXPR);
kono
parents:
diff changeset
118 tree fn = CALL_EXPR_FN (t);
kono
parents:
diff changeset
119 if (fn != NULL_TREE
kono
parents:
diff changeset
120 && TREE_CODE (fn) == TEMPLATE_ID_EXPR)
kono
parents:
diff changeset
121 {
kono
parents:
diff changeset
122 tree f1 = OVL_FIRST (TREE_OPERAND (fn, 0));
kono
parents:
diff changeset
123 if (TREE_CODE (f1) == TEMPLATE_DECL
kono
parents:
diff changeset
124 && DECL_DECLARED_CONCEPT_P (DECL_TEMPLATE_RESULT (f1)))
kono
parents:
diff changeset
125 return true;
kono
parents:
diff changeset
126 }
kono
parents:
diff changeset
127 return false;
kono
parents:
diff changeset
128 }
kono
parents:
diff changeset
129
kono
parents:
diff changeset
130 /* Returns true if any of the arguments in the template
kono
parents:
diff changeset
131 argument list is a wildcard or wildcard pack. */
kono
parents:
diff changeset
132
kono
parents:
diff changeset
133 bool
kono
parents:
diff changeset
134 contains_wildcard_p (tree args)
kono
parents:
diff changeset
135 {
kono
parents:
diff changeset
136 for (int i = 0; i < TREE_VEC_LENGTH (args); ++i)
kono
parents:
diff changeset
137 {
kono
parents:
diff changeset
138 tree arg = TREE_VEC_ELT (args, i);
kono
parents:
diff changeset
139 if (TREE_CODE (arg) == WILDCARD_DECL)
kono
parents:
diff changeset
140 return true;
kono
parents:
diff changeset
141 }
kono
parents:
diff changeset
142 return false;
kono
parents:
diff changeset
143 }
kono
parents:
diff changeset
144
kono
parents:
diff changeset
145 /* Build a new call expression, but don't actually generate a
kono
parents:
diff changeset
146 new function call. We just want the tree, not the semantics. */
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 inline tree
kono
parents:
diff changeset
149 build_call_check (tree id)
kono
parents:
diff changeset
150 {
kono
parents:
diff changeset
151 ++processing_template_decl;
kono
parents:
diff changeset
152 vec<tree, va_gc> *fargs = make_tree_vector();
kono
parents:
diff changeset
153 tree call = finish_call_expr (id, &fargs, false, false, tf_none);
kono
parents:
diff changeset
154 release_tree_vector (fargs);
kono
parents:
diff changeset
155 --processing_template_decl;
kono
parents:
diff changeset
156 return call;
kono
parents:
diff changeset
157 }
kono
parents:
diff changeset
158
kono
parents:
diff changeset
159 /* Build an expression that will check a variable concept. If any
kono
parents:
diff changeset
160 argument contains a wildcard, don't try to finish the variable
kono
parents:
diff changeset
161 template because we can't substitute into a non-existent
kono
parents:
diff changeset
162 declaration. */
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 tree
kono
parents:
diff changeset
165 build_variable_check (tree id)
kono
parents:
diff changeset
166 {
kono
parents:
diff changeset
167 gcc_assert (TREE_CODE (id) == TEMPLATE_ID_EXPR);
kono
parents:
diff changeset
168 if (contains_wildcard_p (TREE_OPERAND (id, 1)))
kono
parents:
diff changeset
169 return id;
kono
parents:
diff changeset
170
kono
parents:
diff changeset
171 ++processing_template_decl;
kono
parents:
diff changeset
172 tree var = finish_template_variable (id);
kono
parents:
diff changeset
173 --processing_template_decl;
kono
parents:
diff changeset
174 return var;
kono
parents:
diff changeset
175 }
kono
parents:
diff changeset
176
kono
parents:
diff changeset
177 /*---------------------------------------------------------------------------
kono
parents:
diff changeset
178 Resolution of qualified concept names
kono
parents:
diff changeset
179 ---------------------------------------------------------------------------*/
kono
parents:
diff changeset
180
kono
parents:
diff changeset
181 /* This facility is used to resolve constraint checks from
kono
parents:
diff changeset
182 requirement expressions. A constraint check is a call to
kono
parents:
diff changeset
183 a function template declared with the keyword 'concept'.
kono
parents:
diff changeset
184
kono
parents:
diff changeset
185 The result of resolution is a pair (a TREE_LIST) whose value
kono
parents:
diff changeset
186 is the matched declaration, and whose purpose contains the
kono
parents:
diff changeset
187 coerced template arguments that can be substituted into the
kono
parents:
diff changeset
188 call. */
kono
parents:
diff changeset
189
kono
parents:
diff changeset
190 // Given an overload set OVL, try to find a unique definition that can be
kono
parents:
diff changeset
191 // instantiated by the template arguments ARGS.
kono
parents:
diff changeset
192 //
kono
parents:
diff changeset
193 // This function is not called for arbitrary call expressions. In particular,
kono
parents:
diff changeset
194 // the call expression must be written with explicit template arguments
kono
parents:
diff changeset
195 // and no function arguments. For example:
kono
parents:
diff changeset
196 //
kono
parents:
diff changeset
197 // f<T, U>()
kono
parents:
diff changeset
198 //
kono
parents:
diff changeset
199 // If a single match is found, this returns a TREE_LIST whose VALUE
kono
parents:
diff changeset
200 // is the constraint function (not the template), and its PURPOSE is
kono
parents:
diff changeset
201 // the complete set of arguments substituted into the parameter list.
kono
parents:
diff changeset
202 static tree
kono
parents:
diff changeset
203 resolve_constraint_check (tree ovl, tree args)
kono
parents:
diff changeset
204 {
kono
parents:
diff changeset
205 int nerrs = 0;
kono
parents:
diff changeset
206 tree cands = NULL_TREE;
kono
parents:
diff changeset
207 for (lkp_iterator iter (ovl); iter; ++iter)
kono
parents:
diff changeset
208 {
kono
parents:
diff changeset
209 // Get the next template overload.
kono
parents:
diff changeset
210 tree tmpl = *iter;
kono
parents:
diff changeset
211 if (TREE_CODE (tmpl) != TEMPLATE_DECL)
kono
parents:
diff changeset
212 continue;
kono
parents:
diff changeset
213
kono
parents:
diff changeset
214 // Don't try to deduce checks for non-concepts. We often
kono
parents:
diff changeset
215 // end up trying to resolve constraints in functional casts
kono
parents:
diff changeset
216 // as part of a postfix-expression. We can save time and
kono
parents:
diff changeset
217 // headaches by not instantiating those declarations.
kono
parents:
diff changeset
218 //
kono
parents:
diff changeset
219 // NOTE: This masks a potential error, caused by instantiating
kono
parents:
diff changeset
220 // non-deduced contexts using placeholder arguments.
kono
parents:
diff changeset
221 tree fn = DECL_TEMPLATE_RESULT (tmpl);
kono
parents:
diff changeset
222 if (DECL_ARGUMENTS (fn))
kono
parents:
diff changeset
223 continue;
kono
parents:
diff changeset
224 if (!DECL_DECLARED_CONCEPT_P (fn))
kono
parents:
diff changeset
225 continue;
kono
parents:
diff changeset
226
kono
parents:
diff changeset
227 // Remember the candidate if we can deduce a substitution.
kono
parents:
diff changeset
228 ++processing_template_decl;
kono
parents:
diff changeset
229 tree parms = TREE_VALUE (DECL_TEMPLATE_PARMS (tmpl));
kono
parents:
diff changeset
230 if (tree subst = coerce_template_parms (parms, args, tmpl))
kono
parents:
diff changeset
231 {
kono
parents:
diff changeset
232 if (subst == error_mark_node)
kono
parents:
diff changeset
233 ++nerrs;
kono
parents:
diff changeset
234 else
kono
parents:
diff changeset
235 cands = tree_cons (subst, fn, cands);
kono
parents:
diff changeset
236 }
kono
parents:
diff changeset
237 --processing_template_decl;
kono
parents:
diff changeset
238 }
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 if (!cands)
kono
parents:
diff changeset
241 /* We either had no candidates or failed deductions. */
kono
parents:
diff changeset
242 return nerrs ? error_mark_node : NULL_TREE;
kono
parents:
diff changeset
243 else if (TREE_CHAIN (cands))
kono
parents:
diff changeset
244 /* There are multiple candidates. */
kono
parents:
diff changeset
245 return error_mark_node;
kono
parents:
diff changeset
246
kono
parents:
diff changeset
247 return cands;
kono
parents:
diff changeset
248 }
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 // Determine if the the call expression CALL is a constraint check, and
kono
parents:
diff changeset
251 // return the concept declaration and arguments being checked. If CALL
kono
parents:
diff changeset
252 // does not denote a constraint check, return NULL.
kono
parents:
diff changeset
253 tree
kono
parents:
diff changeset
254 resolve_constraint_check (tree call)
kono
parents:
diff changeset
255 {
kono
parents:
diff changeset
256 gcc_assert (TREE_CODE (call) == CALL_EXPR);
kono
parents:
diff changeset
257
kono
parents:
diff changeset
258 // A constraint check must be only a template-id expression. If
kono
parents:
diff changeset
259 // it's a call to a base-link, its function(s) should be a
kono
parents:
diff changeset
260 // template-id expression. If this is not a template-id, then it
kono
parents:
diff changeset
261 // cannot be a concept-check.
kono
parents:
diff changeset
262 tree target = CALL_EXPR_FN (call);
kono
parents:
diff changeset
263 if (BASELINK_P (target))
kono
parents:
diff changeset
264 target = BASELINK_FUNCTIONS (target);
kono
parents:
diff changeset
265 if (TREE_CODE (target) != TEMPLATE_ID_EXPR)
kono
parents:
diff changeset
266 return NULL_TREE;
kono
parents:
diff changeset
267
kono
parents:
diff changeset
268 // Get the overload set and template arguments and try to
kono
parents:
diff changeset
269 // resolve the target.
kono
parents:
diff changeset
270 tree ovl = TREE_OPERAND (target, 0);
kono
parents:
diff changeset
271
kono
parents:
diff changeset
272 /* This is a function call of a variable concept... ill-formed. */
kono
parents:
diff changeset
273 if (TREE_CODE (ovl) == TEMPLATE_DECL)
kono
parents:
diff changeset
274 {
kono
parents:
diff changeset
275 error_at (location_of (call),
kono
parents:
diff changeset
276 "function call of variable concept %qE", call);
kono
parents:
diff changeset
277 return error_mark_node;
kono
parents:
diff changeset
278 }
kono
parents:
diff changeset
279
kono
parents:
diff changeset
280 tree args = TREE_OPERAND (target, 1);
kono
parents:
diff changeset
281 return resolve_constraint_check (ovl, args);
kono
parents:
diff changeset
282 }
kono
parents:
diff changeset
283
kono
parents:
diff changeset
284 /* Returns a pair containing the checked variable concept
kono
parents:
diff changeset
285 and its associated prototype parameter. The result
kono
parents:
diff changeset
286 is a TREE_LIST whose TREE_VALUE is the variable concept
kono
parents:
diff changeset
287 and whose TREE_PURPOSE is the prototype parameter. */
kono
parents:
diff changeset
288
kono
parents:
diff changeset
289 tree
kono
parents:
diff changeset
290 resolve_variable_concept_check (tree id)
kono
parents:
diff changeset
291 {
kono
parents:
diff changeset
292 tree tmpl = TREE_OPERAND (id, 0);
kono
parents:
diff changeset
293 tree args = TREE_OPERAND (id, 1);
kono
parents:
diff changeset
294
kono
parents:
diff changeset
295 if (!variable_concept_p (tmpl))
kono
parents:
diff changeset
296 return NULL_TREE;
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 /* Make sure that we have the right parameters before
kono
parents:
diff changeset
299 assuming that it works. Note that failing to deduce
kono
parents:
diff changeset
300 will result in diagnostics. */
kono
parents:
diff changeset
301 tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
kono
parents:
diff changeset
302 ++processing_template_decl;
kono
parents:
diff changeset
303 tree result = coerce_template_parms (parms, args, tmpl);
kono
parents:
diff changeset
304 --processing_template_decl;
kono
parents:
diff changeset
305 if (result != error_mark_node)
kono
parents:
diff changeset
306 {
kono
parents:
diff changeset
307 tree decl = DECL_TEMPLATE_RESULT (tmpl);
kono
parents:
diff changeset
308 return build_tree_list (result, decl);
kono
parents:
diff changeset
309 }
kono
parents:
diff changeset
310 else
kono
parents:
diff changeset
311 return error_mark_node;
kono
parents:
diff changeset
312 }
kono
parents:
diff changeset
313
kono
parents:
diff changeset
314
kono
parents:
diff changeset
315 /* Given a call expression or template-id expression to
kono
parents:
diff changeset
316 a concept EXPR possibly including a wildcard, deduce
kono
parents:
diff changeset
317 the concept being checked and the prototype parameter.
kono
parents:
diff changeset
318 Returns true if the constraint and prototype can be
kono
parents:
diff changeset
319 deduced and false otherwise. Note that the CHECK and
kono
parents:
diff changeset
320 PROTO arguments are set to NULL_TREE if this returns
kono
parents:
diff changeset
321 false. */
kono
parents:
diff changeset
322
kono
parents:
diff changeset
323 bool
kono
parents:
diff changeset
324 deduce_constrained_parameter (tree expr, tree& check, tree& proto)
kono
parents:
diff changeset
325 {
kono
parents:
diff changeset
326 tree info = NULL_TREE;
kono
parents:
diff changeset
327 if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
kono
parents:
diff changeset
328 info = resolve_variable_concept_check (expr);
kono
parents:
diff changeset
329 else if (TREE_CODE (expr) == CALL_EXPR)
kono
parents:
diff changeset
330 info = resolve_constraint_check (expr);
kono
parents:
diff changeset
331 else
kono
parents:
diff changeset
332 gcc_unreachable ();
kono
parents:
diff changeset
333
kono
parents:
diff changeset
334 if (info && info != error_mark_node)
kono
parents:
diff changeset
335 {
kono
parents:
diff changeset
336 check = TREE_VALUE (info);
kono
parents:
diff changeset
337 tree arg = TREE_VEC_ELT (TREE_PURPOSE (info), 0);
kono
parents:
diff changeset
338 if (ARGUMENT_PACK_P (arg))
kono
parents:
diff changeset
339 arg = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg), 0);
kono
parents:
diff changeset
340 proto = TREE_TYPE (arg);
kono
parents:
diff changeset
341 return true;
kono
parents:
diff changeset
342 }
kono
parents:
diff changeset
343 check = proto = NULL_TREE;
kono
parents:
diff changeset
344 return false;
kono
parents:
diff changeset
345 }
kono
parents:
diff changeset
346
kono
parents:
diff changeset
347 // Given a call expression or template-id expression to a concept, EXPR,
kono
parents:
diff changeset
348 // deduce the concept being checked and return the template arguments.
kono
parents:
diff changeset
349 // Returns NULL_TREE if deduction fails.
kono
parents:
diff changeset
350 static tree
kono
parents:
diff changeset
351 deduce_concept_introduction (tree expr)
kono
parents:
diff changeset
352 {
kono
parents:
diff changeset
353 tree info = NULL_TREE;
kono
parents:
diff changeset
354 if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
kono
parents:
diff changeset
355 info = resolve_variable_concept_check (expr);
kono
parents:
diff changeset
356 else if (TREE_CODE (expr) == CALL_EXPR)
kono
parents:
diff changeset
357 info = resolve_constraint_check (expr);
kono
parents:
diff changeset
358 else
kono
parents:
diff changeset
359 gcc_unreachable ();
kono
parents:
diff changeset
360
kono
parents:
diff changeset
361 if (info && info != error_mark_node)
kono
parents:
diff changeset
362 return TREE_PURPOSE (info);
kono
parents:
diff changeset
363 return NULL_TREE;
kono
parents:
diff changeset
364 }
kono
parents:
diff changeset
365
kono
parents:
diff changeset
366 namespace {
kono
parents:
diff changeset
367
kono
parents:
diff changeset
368 /*---------------------------------------------------------------------------
kono
parents:
diff changeset
369 Constraint implication learning
kono
parents:
diff changeset
370 ---------------------------------------------------------------------------*/
kono
parents:
diff changeset
371
kono
parents:
diff changeset
372 /* The implication context determines how we memoize concept checks.
kono
parents:
diff changeset
373 Given two checks C1 and C2, the direction of implication depends
kono
parents:
diff changeset
374 on whether we are learning implications of a conjunction or disjunction.
kono
parents:
diff changeset
375 For example:
kono
parents:
diff changeset
376
kono
parents:
diff changeset
377 template<typename T> concept bool C = ...;
kono
parents:
diff changeset
378 template<typenaem T> concept bool D = C<T> && true;
kono
parents:
diff changeset
379
kono
parents:
diff changeset
380 From this, we can learn that D<T> implies C<T>. We cannot learn,
kono
parents:
diff changeset
381 without further testing, that C<T> does not imply D<T>. If, for
kono
parents:
diff changeset
382 example, C<T> were defined as true, then these constraints would
kono
parents:
diff changeset
383 be logically equivalent.
kono
parents:
diff changeset
384
kono
parents:
diff changeset
385 In rare cases, we may start with a logical equivalence. For example:
kono
parents:
diff changeset
386
kono
parents:
diff changeset
387 template<typename T> concept bool C = ...;
kono
parents:
diff changeset
388 template<typename T> concept bool D = C<T>;
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 Here, we learn that C<T> implies D<T> and vice versa. */
kono
parents:
diff changeset
391
kono
parents:
diff changeset
392 enum implication_context
kono
parents:
diff changeset
393 {
kono
parents:
diff changeset
394 conjunction_cxt, /* C1 implies C2. */
kono
parents:
diff changeset
395 disjunction_cxt, /* C2 implies C1. */
kono
parents:
diff changeset
396 equivalence_cxt /* C1 implies C2, C2 implies C1. */
kono
parents:
diff changeset
397 };
kono
parents:
diff changeset
398
kono
parents:
diff changeset
399 void learn_implications(tree, tree, implication_context);
kono
parents:
diff changeset
400
kono
parents:
diff changeset
401 void
kono
parents:
diff changeset
402 learn_implication (tree parent, tree child, implication_context cxt)
kono
parents:
diff changeset
403 {
kono
parents:
diff changeset
404 switch (cxt)
kono
parents:
diff changeset
405 {
kono
parents:
diff changeset
406 case conjunction_cxt:
kono
parents:
diff changeset
407 save_subsumption_result (parent, child, true);
kono
parents:
diff changeset
408 break;
kono
parents:
diff changeset
409 case disjunction_cxt:
kono
parents:
diff changeset
410 save_subsumption_result (child, parent, true);
kono
parents:
diff changeset
411 break;
kono
parents:
diff changeset
412 case equivalence_cxt:
kono
parents:
diff changeset
413 save_subsumption_result (parent, child, true);
kono
parents:
diff changeset
414 save_subsumption_result (child, parent, true);
kono
parents:
diff changeset
415 break;
kono
parents:
diff changeset
416 }
kono
parents:
diff changeset
417 }
kono
parents:
diff changeset
418
kono
parents:
diff changeset
419 void
kono
parents:
diff changeset
420 learn_logical_operation (tree parent, tree constr, implication_context cxt)
kono
parents:
diff changeset
421 {
kono
parents:
diff changeset
422 learn_implications (parent, TREE_OPERAND (constr, 0), cxt);
kono
parents:
diff changeset
423 learn_implications (parent, TREE_OPERAND (constr, 1), cxt);
kono
parents:
diff changeset
424 }
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 void
kono
parents:
diff changeset
427 learn_implications (tree parent, tree constr, implication_context cxt)
kono
parents:
diff changeset
428 {
kono
parents:
diff changeset
429 switch (TREE_CODE (constr))
kono
parents:
diff changeset
430 {
kono
parents:
diff changeset
431 case CHECK_CONSTR:
kono
parents:
diff changeset
432 return learn_implication (parent, constr, cxt);
kono
parents:
diff changeset
433
kono
parents:
diff changeset
434 case CONJ_CONSTR:
kono
parents:
diff changeset
435 if (cxt == disjunction_cxt)
kono
parents:
diff changeset
436 return;
kono
parents:
diff changeset
437 return learn_logical_operation (parent, constr, cxt);
kono
parents:
diff changeset
438
kono
parents:
diff changeset
439 case DISJ_CONSTR:
kono
parents:
diff changeset
440 if (cxt == conjunction_cxt)
kono
parents:
diff changeset
441 return;
kono
parents:
diff changeset
442 return learn_logical_operation (parent, constr, cxt);
kono
parents:
diff changeset
443
kono
parents:
diff changeset
444 default:
kono
parents:
diff changeset
445 break;
kono
parents:
diff changeset
446 }
kono
parents:
diff changeset
447 }
kono
parents:
diff changeset
448
kono
parents:
diff changeset
449 /* Quickly scan the top-level constraints of CONSTR to learn and
kono
parents:
diff changeset
450 cache logical relations between concepts. The search does not
kono
parents:
diff changeset
451 include conjunctions of disjunctions or vice versa. */
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453 void
kono
parents:
diff changeset
454 learn_implications (tree tmpl, tree args, tree constr)
kono
parents:
diff changeset
455 {
kono
parents:
diff changeset
456 /* Don't memoize relations between non-dependent arguemnts. It's not
kono
parents:
diff changeset
457 helpful. */
kono
parents:
diff changeset
458 if (!uses_template_parms (args))
kono
parents:
diff changeset
459 return;
kono
parents:
diff changeset
460
kono
parents:
diff changeset
461 /* Build a check constraint for the purpose of caching. */
kono
parents:
diff changeset
462 tree parent = build_nt (CHECK_CONSTR, tmpl, args);
kono
parents:
diff changeset
463
kono
parents:
diff changeset
464 /* Start learning based on the kind of the top-level contraint. */
kono
parents:
diff changeset
465 if (TREE_CODE (constr) == CONJ_CONSTR)
kono
parents:
diff changeset
466 return learn_logical_operation (parent, constr, conjunction_cxt);
kono
parents:
diff changeset
467 else if (TREE_CODE (constr) == DISJ_CONSTR)
kono
parents:
diff changeset
468 return learn_logical_operation (parent, constr, disjunction_cxt);
kono
parents:
diff changeset
469 else if (TREE_CODE (constr) == CHECK_CONSTR)
kono
parents:
diff changeset
470 /* This is the rare concept alias case. */
kono
parents:
diff changeset
471 return learn_implication (parent, constr, equivalence_cxt);
kono
parents:
diff changeset
472 }
kono
parents:
diff changeset
473
kono
parents:
diff changeset
474 /*---------------------------------------------------------------------------
kono
parents:
diff changeset
475 Expansion of concept definitions
kono
parents:
diff changeset
476 ---------------------------------------------------------------------------*/
kono
parents:
diff changeset
477
kono
parents:
diff changeset
478 /* Returns the expression of a function concept. */
kono
parents:
diff changeset
479
kono
parents:
diff changeset
480 tree
kono
parents:
diff changeset
481 get_returned_expression (tree fn)
kono
parents:
diff changeset
482 {
kono
parents:
diff changeset
483 /* Extract the body of the function minus the return expression. */
kono
parents:
diff changeset
484 tree body = DECL_SAVED_TREE (fn);
kono
parents:
diff changeset
485 if (!body)
kono
parents:
diff changeset
486 return error_mark_node;
kono
parents:
diff changeset
487 if (TREE_CODE (body) == BIND_EXPR)
kono
parents:
diff changeset
488 body = BIND_EXPR_BODY (body);
kono
parents:
diff changeset
489 if (TREE_CODE (body) != RETURN_EXPR)
kono
parents:
diff changeset
490 return error_mark_node;
kono
parents:
diff changeset
491
kono
parents:
diff changeset
492 return TREE_OPERAND (body, 0);
kono
parents:
diff changeset
493 }
kono
parents:
diff changeset
494
kono
parents:
diff changeset
495 /* Returns the initializer of a variable concept. */
kono
parents:
diff changeset
496
kono
parents:
diff changeset
497 tree
kono
parents:
diff changeset
498 get_variable_initializer (tree var)
kono
parents:
diff changeset
499 {
kono
parents:
diff changeset
500 tree init = DECL_INITIAL (var);
kono
parents:
diff changeset
501 if (!init)
kono
parents:
diff changeset
502 return error_mark_node;
kono
parents:
diff changeset
503 return init;
kono
parents:
diff changeset
504 }
kono
parents:
diff changeset
505
kono
parents:
diff changeset
506 /* Returns the definition of a variable or function concept. */
kono
parents:
diff changeset
507
kono
parents:
diff changeset
508 tree
kono
parents:
diff changeset
509 get_concept_definition (tree decl)
kono
parents:
diff changeset
510 {
kono
parents:
diff changeset
511 if (VAR_P (decl))
kono
parents:
diff changeset
512 return get_variable_initializer (decl);
kono
parents:
diff changeset
513 else if (TREE_CODE (decl) == FUNCTION_DECL)
kono
parents:
diff changeset
514 return get_returned_expression (decl);
kono
parents:
diff changeset
515 gcc_unreachable ();
kono
parents:
diff changeset
516 }
kono
parents:
diff changeset
517
kono
parents:
diff changeset
518 int expansion_level = 0;
kono
parents:
diff changeset
519
kono
parents:
diff changeset
520 struct expanding_concept_sentinel
kono
parents:
diff changeset
521 {
kono
parents:
diff changeset
522 expanding_concept_sentinel ()
kono
parents:
diff changeset
523 {
kono
parents:
diff changeset
524 ++expansion_level;
kono
parents:
diff changeset
525 }
kono
parents:
diff changeset
526
kono
parents:
diff changeset
527 ~expanding_concept_sentinel()
kono
parents:
diff changeset
528 {
kono
parents:
diff changeset
529 --expansion_level;
kono
parents:
diff changeset
530 }
kono
parents:
diff changeset
531 };
kono
parents:
diff changeset
532
kono
parents:
diff changeset
533
kono
parents:
diff changeset
534 } /* namespace */
kono
parents:
diff changeset
535
kono
parents:
diff changeset
536 /* Returns true when a concept is being expanded. */
kono
parents:
diff changeset
537
kono
parents:
diff changeset
538 bool
kono
parents:
diff changeset
539 expanding_concept()
kono
parents:
diff changeset
540 {
kono
parents:
diff changeset
541 return expansion_level > 0;
kono
parents:
diff changeset
542 }
kono
parents:
diff changeset
543
kono
parents:
diff changeset
544 /* Expand a concept declaration (not a template) and its arguments to
kono
parents:
diff changeset
545 a constraint defined by the concept's initializer or definition. */
kono
parents:
diff changeset
546
kono
parents:
diff changeset
547 tree
kono
parents:
diff changeset
548 expand_concept (tree decl, tree args)
kono
parents:
diff changeset
549 {
kono
parents:
diff changeset
550 expanding_concept_sentinel sentinel;
kono
parents:
diff changeset
551
kono
parents:
diff changeset
552 if (TREE_CODE (decl) == TEMPLATE_DECL)
kono
parents:
diff changeset
553 decl = DECL_TEMPLATE_RESULT (decl);
kono
parents:
diff changeset
554 tree tmpl = DECL_TI_TEMPLATE (decl);
kono
parents:
diff changeset
555
kono
parents:
diff changeset
556 /* Check for a previous specialization. */
kono
parents:
diff changeset
557 if (tree spec = get_concept_expansion (tmpl, args))
kono
parents:
diff changeset
558 return spec;
kono
parents:
diff changeset
559
kono
parents:
diff changeset
560 /* Substitute the arguments to form a new definition expression. */
kono
parents:
diff changeset
561 tree def = get_concept_definition (decl);
kono
parents:
diff changeset
562
kono
parents:
diff changeset
563 ++processing_template_decl;
kono
parents:
diff changeset
564 tree result = tsubst_expr (def, args, tf_none, NULL_TREE, true);
kono
parents:
diff changeset
565 --processing_template_decl;
kono
parents:
diff changeset
566 if (result == error_mark_node)
kono
parents:
diff changeset
567 return error_mark_node;
kono
parents:
diff changeset
568
kono
parents:
diff changeset
569 /* And lastly, normalize it, check for implications, and save
kono
parents:
diff changeset
570 the specialization for later. */
kono
parents:
diff changeset
571 tree norm = normalize_expression (result);
kono
parents:
diff changeset
572 learn_implications (tmpl, args, norm);
kono
parents:
diff changeset
573 return save_concept_expansion (tmpl, args, norm);
kono
parents:
diff changeset
574 }
kono
parents:
diff changeset
575
kono
parents:
diff changeset
576
kono
parents:
diff changeset
577 /*---------------------------------------------------------------------------
kono
parents:
diff changeset
578 Stepwise normalization of expressions
kono
parents:
diff changeset
579
kono
parents:
diff changeset
580 This set of functions will transform an expression into a constraint
kono
parents:
diff changeset
581 in a sequence of steps. Normalization does not not look into concept
kono
parents:
diff changeset
582 definitions.
kono
parents:
diff changeset
583 ---------------------------------------------------------------------------*/
kono
parents:
diff changeset
584
kono
parents:
diff changeset
585 /* Transform a logical-or or logical-and expression into either
kono
parents:
diff changeset
586 a conjunction or disjunction. */
kono
parents:
diff changeset
587
kono
parents:
diff changeset
588 tree
kono
parents:
diff changeset
589 normalize_logical_operation (tree t, tree_code c)
kono
parents:
diff changeset
590 {
kono
parents:
diff changeset
591 tree t0 = normalize_expression (TREE_OPERAND (t, 0));
kono
parents:
diff changeset
592 tree t1 = normalize_expression (TREE_OPERAND (t, 1));
kono
parents:
diff changeset
593 return build_nt (c, t0, t1);
kono
parents:
diff changeset
594 }
kono
parents:
diff changeset
595
kono
parents:
diff changeset
596 /* A simple requirement T introduces an expression constraint
kono
parents:
diff changeset
597 for its expression. */
kono
parents:
diff changeset
598
kono
parents:
diff changeset
599 inline tree
kono
parents:
diff changeset
600 normalize_simple_requirement (tree t)
kono
parents:
diff changeset
601 {
kono
parents:
diff changeset
602 return build_nt (EXPR_CONSTR, TREE_OPERAND (t, 0));
kono
parents:
diff changeset
603 }
kono
parents:
diff changeset
604
kono
parents:
diff changeset
605 /* A type requirement T introduce a type constraint for its type. */
kono
parents:
diff changeset
606
kono
parents:
diff changeset
607 inline tree
kono
parents:
diff changeset
608 normalize_type_requirement (tree t)
kono
parents:
diff changeset
609 {
kono
parents:
diff changeset
610 return build_nt (TYPE_CONSTR, TREE_OPERAND (t, 0));
kono
parents:
diff changeset
611 }
kono
parents:
diff changeset
612
kono
parents:
diff changeset
613 /* A compound requirement T introduces a conjunction of constraints
kono
parents:
diff changeset
614 depending on its form. The conjunction always includes an
kono
parents:
diff changeset
615 expression constraint for the expression of the requirement.
kono
parents:
diff changeset
616 If a trailing return type was specified, the conjunction includes
kono
parents:
diff changeset
617 either an implicit conversion constraint or an argument deduction
kono
parents:
diff changeset
618 constraint. If the noexcept specifier is present, the conjunction
kono
parents:
diff changeset
619 includes an exception constraint. */
kono
parents:
diff changeset
620
kono
parents:
diff changeset
621 tree
kono
parents:
diff changeset
622 normalize_compound_requirement (tree t)
kono
parents:
diff changeset
623 {
kono
parents:
diff changeset
624 tree expr = TREE_OPERAND (t, 0);
kono
parents:
diff changeset
625 tree constr = build_nt (EXPR_CONSTR, TREE_OPERAND (t, 0));
kono
parents:
diff changeset
626
kono
parents:
diff changeset
627 /* If a type is given, append an implicit conversion or
kono
parents:
diff changeset
628 argument deduction constraint. */
kono
parents:
diff changeset
629 if (tree type = TREE_OPERAND (t, 1))
kono
parents:
diff changeset
630 {
kono
parents:
diff changeset
631 tree type_constr;
kono
parents:
diff changeset
632 /* TODO: We should be extracting a list of auto nodes
kono
parents:
diff changeset
633 from type_uses_auto, not a single node */
kono
parents:
diff changeset
634 if (tree placeholder = type_uses_auto (type))
kono
parents:
diff changeset
635 type_constr = build_nt (DEDUCT_CONSTR, expr, type, placeholder);
kono
parents:
diff changeset
636 else
kono
parents:
diff changeset
637 type_constr = build_nt (ICONV_CONSTR, expr, type);
kono
parents:
diff changeset
638 constr = conjoin_constraints (constr, type_constr);
kono
parents:
diff changeset
639 }
kono
parents:
diff changeset
640
kono
parents:
diff changeset
641 /* If noexcept is present, append an exception constraint. */
kono
parents:
diff changeset
642 if (COMPOUND_REQ_NOEXCEPT_P (t))
kono
parents:
diff changeset
643 {
kono
parents:
diff changeset
644 tree except = build_nt (EXCEPT_CONSTR, expr);
kono
parents:
diff changeset
645 constr = conjoin_constraints (constr, except);
kono
parents:
diff changeset
646 }
kono
parents:
diff changeset
647
kono
parents:
diff changeset
648 return constr;
kono
parents:
diff changeset
649 }
kono
parents:
diff changeset
650
kono
parents:
diff changeset
651 /* A nested requirement T introduces a conjunction of constraints
kono
parents:
diff changeset
652 corresponding to its constraint-expression.
kono
parents:
diff changeset
653
kono
parents:
diff changeset
654 If the result of transforming T is error_mark_node, the resulting
kono
parents:
diff changeset
655 constraint is a predicate constraint whose operand is also
kono
parents:
diff changeset
656 error_mark_node. This preserves the constraint structure, but
kono
parents:
diff changeset
657 will guarantee that the constraint is never satisfied. */
kono
parents:
diff changeset
658
kono
parents:
diff changeset
659 inline tree
kono
parents:
diff changeset
660 normalize_nested_requirement (tree t)
kono
parents:
diff changeset
661 {
kono
parents:
diff changeset
662 return normalize_expression (TREE_OPERAND (t, 0));
kono
parents:
diff changeset
663 }
kono
parents:
diff changeset
664
kono
parents:
diff changeset
665 /* Transform a requirement T into one or more constraints. */
kono
parents:
diff changeset
666
kono
parents:
diff changeset
667 tree
kono
parents:
diff changeset
668 normalize_requirement (tree t)
kono
parents:
diff changeset
669 {
kono
parents:
diff changeset
670 switch (TREE_CODE (t))
kono
parents:
diff changeset
671 {
kono
parents:
diff changeset
672 case SIMPLE_REQ:
kono
parents:
diff changeset
673 return normalize_simple_requirement (t);
kono
parents:
diff changeset
674
kono
parents:
diff changeset
675 case TYPE_REQ:
kono
parents:
diff changeset
676 return normalize_type_requirement (t);
kono
parents:
diff changeset
677
kono
parents:
diff changeset
678 case COMPOUND_REQ:
kono
parents:
diff changeset
679 return normalize_compound_requirement (t);
kono
parents:
diff changeset
680
kono
parents:
diff changeset
681 case NESTED_REQ:
kono
parents:
diff changeset
682 return normalize_nested_requirement (t);
kono
parents:
diff changeset
683
kono
parents:
diff changeset
684 default:
kono
parents:
diff changeset
685 gcc_unreachable ();
kono
parents:
diff changeset
686 }
kono
parents:
diff changeset
687 return error_mark_node;
kono
parents:
diff changeset
688 }
kono
parents:
diff changeset
689
kono
parents:
diff changeset
690 /* Transform a sequence of requirements into a conjunction of
kono
parents:
diff changeset
691 constraints. */
kono
parents:
diff changeset
692
kono
parents:
diff changeset
693 tree
kono
parents:
diff changeset
694 normalize_requirements (tree t)
kono
parents:
diff changeset
695 {
kono
parents:
diff changeset
696 tree result = NULL_TREE;
kono
parents:
diff changeset
697 for (; t; t = TREE_CHAIN (t))
kono
parents:
diff changeset
698 {
kono
parents:
diff changeset
699 tree constr = normalize_requirement (TREE_VALUE (t));
kono
parents:
diff changeset
700 result = conjoin_constraints (result, constr);
kono
parents:
diff changeset
701 }
kono
parents:
diff changeset
702 return result;
kono
parents:
diff changeset
703 }
kono
parents:
diff changeset
704
kono
parents:
diff changeset
705 /* The normal form of a requires-expression is a parameterized
kono
parents:
diff changeset
706 constraint having the same parameters and a conjunction of
kono
parents:
diff changeset
707 constraints representing the normal form of requirements. */
kono
parents:
diff changeset
708
kono
parents:
diff changeset
709 tree
kono
parents:
diff changeset
710 normalize_requires_expression (tree t)
kono
parents:
diff changeset
711 {
kono
parents:
diff changeset
712 tree operand = normalize_requirements (TREE_OPERAND (t, 1));
kono
parents:
diff changeset
713 if (tree parms = TREE_OPERAND (t, 0))
kono
parents:
diff changeset
714 return build_nt (PARM_CONSTR, parms, operand);
kono
parents:
diff changeset
715 else
kono
parents:
diff changeset
716 return operand;
kono
parents:
diff changeset
717 }
kono
parents:
diff changeset
718
kono
parents:
diff changeset
719 /* For a template-id referring to a variable concept, returns
kono
parents:
diff changeset
720 a check constraint. Otherwise, returns a predicate constraint. */
kono
parents:
diff changeset
721
kono
parents:
diff changeset
722 tree
kono
parents:
diff changeset
723 normalize_template_id_expression (tree t)
kono
parents:
diff changeset
724 {
kono
parents:
diff changeset
725 if (tree info = resolve_variable_concept_check (t))
kono
parents:
diff changeset
726 {
kono
parents:
diff changeset
727 if (info == error_mark_node)
kono
parents:
diff changeset
728 {
kono
parents:
diff changeset
729 /* We get this when the template arguments don't match
kono
parents:
diff changeset
730 the variable concept. */
kono
parents:
diff changeset
731 error ("invalid reference to concept %qE", t);
kono
parents:
diff changeset
732 return error_mark_node;
kono
parents:
diff changeset
733 }
kono
parents:
diff changeset
734
kono
parents:
diff changeset
735 tree decl = TREE_VALUE (info);
kono
parents:
diff changeset
736 tree args = TREE_PURPOSE (info);
kono
parents:
diff changeset
737 return build_nt (CHECK_CONSTR, decl, args);
kono
parents:
diff changeset
738 }
kono
parents:
diff changeset
739
kono
parents:
diff changeset
740 /* Check that we didn't refer to a function concept like a variable. */
kono
parents:
diff changeset
741 tree fn = OVL_FIRST (TREE_OPERAND (t, 0));
kono
parents:
diff changeset
742 if (TREE_CODE (fn) == TEMPLATE_DECL
kono
parents:
diff changeset
743 && DECL_DECLARED_CONCEPT_P (DECL_TEMPLATE_RESULT (fn)))
kono
parents:
diff changeset
744 {
kono
parents:
diff changeset
745 error_at (location_of (t),
kono
parents:
diff changeset
746 "invalid reference to function concept %qD", fn);
kono
parents:
diff changeset
747 return error_mark_node;
kono
parents:
diff changeset
748 }
kono
parents:
diff changeset
749
kono
parents:
diff changeset
750 return build_nt (PRED_CONSTR, t);
kono
parents:
diff changeset
751 }
kono
parents:
diff changeset
752
kono
parents:
diff changeset
753 /* For a call expression to a function concept, returns a check
kono
parents:
diff changeset
754 constraint. Otherwise, returns a predicate constraint. */
kono
parents:
diff changeset
755
kono
parents:
diff changeset
756 tree
kono
parents:
diff changeset
757 normalize_call_expression (tree t)
kono
parents:
diff changeset
758 {
kono
parents:
diff changeset
759 /* Try to resolve this function call as a concept. If not, then
kono
parents:
diff changeset
760 it can be returned as a predicate constraint. */
kono
parents:
diff changeset
761 tree check = resolve_constraint_check (t);
kono
parents:
diff changeset
762 if (!check)
kono
parents:
diff changeset
763 return build_nt (PRED_CONSTR, t);
kono
parents:
diff changeset
764 if (check == error_mark_node)
kono
parents:
diff changeset
765 {
kono
parents:
diff changeset
766 /* TODO: Improve diagnostics. We could report why the reference
kono
parents:
diff changeset
767 is invalid. */
kono
parents:
diff changeset
768 error ("invalid reference to concept %qE", t);
kono
parents:
diff changeset
769 return error_mark_node;
kono
parents:
diff changeset
770 }
kono
parents:
diff changeset
771
kono
parents:
diff changeset
772 tree fn = TREE_VALUE (check);
kono
parents:
diff changeset
773 tree args = TREE_PURPOSE (check);
kono
parents:
diff changeset
774 return build_nt (CHECK_CONSTR, fn, args);
kono
parents:
diff changeset
775 }
kono
parents:
diff changeset
776
kono
parents:
diff changeset
777 /* If T is a call to an overloaded && or || operator, diagnose that
kono
parents:
diff changeset
778 as a non-SFINAEable error. Returns true if an error is emitted.
kono
parents:
diff changeset
779
kono
parents:
diff changeset
780 TODO: It would be better to diagnose this at the point of definition,
kono
parents:
diff changeset
781 if possible. Perhaps we should immediately do a first-pass normalization
kono
parents:
diff changeset
782 of a concept definition to catch obvious non-dependent errors like
kono
parents:
diff changeset
783 this. */
kono
parents:
diff changeset
784
kono
parents:
diff changeset
785 bool
kono
parents:
diff changeset
786 check_for_logical_overloads (tree t)
kono
parents:
diff changeset
787 {
kono
parents:
diff changeset
788 if (TREE_CODE (t) != CALL_EXPR)
kono
parents:
diff changeset
789 return false;
kono
parents:
diff changeset
790
kono
parents:
diff changeset
791 tree fn = CALL_EXPR_FN (t);
kono
parents:
diff changeset
792
kono
parents:
diff changeset
793 /* For member calls, try extracting the function from the
kono
parents:
diff changeset
794 component ref. */
kono
parents:
diff changeset
795 if (TREE_CODE (fn) == COMPONENT_REF)
kono
parents:
diff changeset
796 {
kono
parents:
diff changeset
797 fn = TREE_OPERAND (fn, 1);
kono
parents:
diff changeset
798 if (TREE_CODE (fn) == BASELINK)
kono
parents:
diff changeset
799 fn = BASELINK_FUNCTIONS (fn);
kono
parents:
diff changeset
800 }
kono
parents:
diff changeset
801
kono
parents:
diff changeset
802 if (TREE_CODE (fn) != FUNCTION_DECL)
kono
parents:
diff changeset
803 return false;
kono
parents:
diff changeset
804
kono
parents:
diff changeset
805 if (DECL_OVERLOADED_OPERATOR_P (fn))
kono
parents:
diff changeset
806 {
kono
parents:
diff changeset
807 location_t loc = EXPR_LOC_OR_LOC (t, input_location);
kono
parents:
diff changeset
808 error_at (loc, "constraint %qE, uses overloaded operator", t);
kono
parents:
diff changeset
809 return true;
kono
parents:
diff changeset
810 }
kono
parents:
diff changeset
811
kono
parents:
diff changeset
812 return false;
kono
parents:
diff changeset
813 }
kono
parents:
diff changeset
814
kono
parents:
diff changeset
815 /* The normal form of an atom depends on the expression. The normal
kono
parents:
diff changeset
816 form of a function call to a function concept is a check constraint
kono
parents:
diff changeset
817 for that concept. The normal form of a reference to a variable
kono
parents:
diff changeset
818 concept is a check constraint for that concept. Otherwise, the
kono
parents:
diff changeset
819 constraint is a predicate constraint. */
kono
parents:
diff changeset
820
kono
parents:
diff changeset
821 tree
kono
parents:
diff changeset
822 normalize_atom (tree t)
kono
parents:
diff changeset
823 {
kono
parents:
diff changeset
824 /* We can get constraints pushed down through pack expansions, so
kono
parents:
diff changeset
825 just return them. */
kono
parents:
diff changeset
826 if (constraint_p (t))
kono
parents:
diff changeset
827 return t;
kono
parents:
diff changeset
828
kono
parents:
diff changeset
829 tree type = TREE_TYPE (t);
kono
parents:
diff changeset
830 if (!type || type_unknown_p (t) || TREE_CODE (type) == TEMPLATE_TYPE_PARM)
kono
parents:
diff changeset
831 ;
kono
parents:
diff changeset
832 else if (!dependent_type_p (type))
kono
parents:
diff changeset
833 {
kono
parents:
diff changeset
834 if (check_for_logical_overloads (t))
kono
parents:
diff changeset
835 return error_mark_node;
kono
parents:
diff changeset
836
kono
parents:
diff changeset
837 type = cv_unqualified (type);
kono
parents:
diff changeset
838 if (!same_type_p (type, boolean_type_node))
kono
parents:
diff changeset
839 {
kono
parents:
diff changeset
840 error ("predicate constraint %q+E does not have type %<bool%>", t);
kono
parents:
diff changeset
841 return error_mark_node;
kono
parents:
diff changeset
842 }
kono
parents:
diff changeset
843 }
kono
parents:
diff changeset
844
kono
parents:
diff changeset
845 if (TREE_CODE (t) == TEMPLATE_ID_EXPR)
kono
parents:
diff changeset
846 return normalize_template_id_expression (t);
kono
parents:
diff changeset
847 if (TREE_CODE (t) == CALL_EXPR)
kono
parents:
diff changeset
848 return normalize_call_expression (t);
kono
parents:
diff changeset
849 return build_nt (PRED_CONSTR, t);
kono
parents:
diff changeset
850 }
kono
parents:
diff changeset
851
kono
parents:
diff changeset
852 /* Push down the pack expansion EXP into the leaves of the constraint PAT. */
kono
parents:
diff changeset
853
kono
parents:
diff changeset
854 tree
kono
parents:
diff changeset
855 push_down_pack_expansion (tree exp, tree pat)
kono
parents:
diff changeset
856 {
kono
parents:
diff changeset
857 switch (TREE_CODE (pat))
kono
parents:
diff changeset
858 {
kono
parents:
diff changeset
859 case CONJ_CONSTR:
kono
parents:
diff changeset
860 case DISJ_CONSTR:
kono
parents:
diff changeset
861 {
kono
parents:
diff changeset
862 pat = copy_node (pat);
kono
parents:
diff changeset
863 TREE_OPERAND (pat, 0)
kono
parents:
diff changeset
864 = push_down_pack_expansion (exp, TREE_OPERAND (pat, 0));
kono
parents:
diff changeset
865 TREE_OPERAND (pat, 1)
kono
parents:
diff changeset
866 = push_down_pack_expansion (exp, TREE_OPERAND (pat, 1));
kono
parents:
diff changeset
867 return pat;
kono
parents:
diff changeset
868 }
kono
parents:
diff changeset
869 default:
kono
parents:
diff changeset
870 {
kono
parents:
diff changeset
871 exp = copy_node (exp);
kono
parents:
diff changeset
872 SET_PACK_EXPANSION_PATTERN (exp, pat);
kono
parents:
diff changeset
873 return exp;
kono
parents:
diff changeset
874 }
kono
parents:
diff changeset
875 }
kono
parents:
diff changeset
876 }
kono
parents:
diff changeset
877
kono
parents:
diff changeset
878 /* Transform a pack expansion into a constraint. First we transform the
kono
parents:
diff changeset
879 pattern of the pack expansion, then we push the pack expansion down into the
kono
parents:
diff changeset
880 leaves of the constraint so that partial ordering will work. */
kono
parents:
diff changeset
881
kono
parents:
diff changeset
882 tree
kono
parents:
diff changeset
883 normalize_pack_expansion (tree t)
kono
parents:
diff changeset
884 {
kono
parents:
diff changeset
885 tree pat = normalize_expression (PACK_EXPANSION_PATTERN (t));
kono
parents:
diff changeset
886 return push_down_pack_expansion (t, pat);
kono
parents:
diff changeset
887 }
kono
parents:
diff changeset
888
kono
parents:
diff changeset
889 /* Transform an expression into a constraint. */
kono
parents:
diff changeset
890
kono
parents:
diff changeset
891 tree
kono
parents:
diff changeset
892 normalize_any_expression (tree t)
kono
parents:
diff changeset
893 {
kono
parents:
diff changeset
894 switch (TREE_CODE (t))
kono
parents:
diff changeset
895 {
kono
parents:
diff changeset
896 case TRUTH_ANDIF_EXPR:
kono
parents:
diff changeset
897 return normalize_logical_operation (t, CONJ_CONSTR);
kono
parents:
diff changeset
898
kono
parents:
diff changeset
899 case TRUTH_ORIF_EXPR:
kono
parents:
diff changeset
900 return normalize_logical_operation (t, DISJ_CONSTR);
kono
parents:
diff changeset
901
kono
parents:
diff changeset
902 case REQUIRES_EXPR:
kono
parents:
diff changeset
903 return normalize_requires_expression (t);
kono
parents:
diff changeset
904
kono
parents:
diff changeset
905 case BIND_EXPR:
kono
parents:
diff changeset
906 return normalize_expression (BIND_EXPR_BODY (t));
kono
parents:
diff changeset
907
kono
parents:
diff changeset
908 case EXPR_PACK_EXPANSION:
kono
parents:
diff changeset
909 return normalize_pack_expansion (t);
kono
parents:
diff changeset
910
kono
parents:
diff changeset
911 default:
kono
parents:
diff changeset
912 /* All other constraints are atomic. */
kono
parents:
diff changeset
913 return normalize_atom (t);
kono
parents:
diff changeset
914 }
kono
parents:
diff changeset
915 }
kono
parents:
diff changeset
916
kono
parents:
diff changeset
917 /* Transform a statement into an expression. */
kono
parents:
diff changeset
918 tree
kono
parents:
diff changeset
919 normalize_any_statement (tree t)
kono
parents:
diff changeset
920 {
kono
parents:
diff changeset
921 switch (TREE_CODE (t))
kono
parents:
diff changeset
922 {
kono
parents:
diff changeset
923 case RETURN_EXPR:
kono
parents:
diff changeset
924 return normalize_expression (TREE_OPERAND (t, 0));
kono
parents:
diff changeset
925 default:
kono
parents:
diff changeset
926 gcc_unreachable ();
kono
parents:
diff changeset
927 }
kono
parents:
diff changeset
928 return error_mark_node;
kono
parents:
diff changeset
929 }
kono
parents:
diff changeset
930
kono
parents:
diff changeset
931 /* Reduction rules for the declaration T. */
kono
parents:
diff changeset
932
kono
parents:
diff changeset
933 tree
kono
parents:
diff changeset
934 normalize_any_declaration (tree t)
kono
parents:
diff changeset
935 {
kono
parents:
diff changeset
936 switch (TREE_CODE (t))
kono
parents:
diff changeset
937 {
kono
parents:
diff changeset
938 case VAR_DECL:
kono
parents:
diff changeset
939 return normalize_atom (t);
kono
parents:
diff changeset
940 default:
kono
parents:
diff changeset
941 gcc_unreachable ();
kono
parents:
diff changeset
942 }
kono
parents:
diff changeset
943 return error_mark_node;
kono
parents:
diff changeset
944 }
kono
parents:
diff changeset
945
kono
parents:
diff changeset
946 /* Returns the normal form of a constraint expression. */
kono
parents:
diff changeset
947
kono
parents:
diff changeset
948 tree
kono
parents:
diff changeset
949 normalize_expression (tree t)
kono
parents:
diff changeset
950 {
kono
parents:
diff changeset
951 if (!t)
kono
parents:
diff changeset
952 return NULL_TREE;
kono
parents:
diff changeset
953
kono
parents:
diff changeset
954 if (t == error_mark_node)
kono
parents:
diff changeset
955 return error_mark_node;
kono
parents:
diff changeset
956
kono
parents:
diff changeset
957 switch (TREE_CODE_CLASS (TREE_CODE (t)))
kono
parents:
diff changeset
958 {
kono
parents:
diff changeset
959 case tcc_unary:
kono
parents:
diff changeset
960 case tcc_binary:
kono
parents:
diff changeset
961 case tcc_expression:
kono
parents:
diff changeset
962 case tcc_vl_exp:
kono
parents:
diff changeset
963 return normalize_any_expression (t);
kono
parents:
diff changeset
964
kono
parents:
diff changeset
965 case tcc_statement:
kono
parents:
diff changeset
966 return normalize_any_statement (t);
kono
parents:
diff changeset
967
kono
parents:
diff changeset
968 case tcc_declaration:
kono
parents:
diff changeset
969 return normalize_any_declaration (t);
kono
parents:
diff changeset
970
kono
parents:
diff changeset
971 case tcc_exceptional:
kono
parents:
diff changeset
972 case tcc_constant:
kono
parents:
diff changeset
973 case tcc_reference:
kono
parents:
diff changeset
974 case tcc_comparison:
kono
parents:
diff changeset
975 /* These are all atomic predicate constraints. */
kono
parents:
diff changeset
976 return normalize_atom (t);
kono
parents:
diff changeset
977
kono
parents:
diff changeset
978 default:
kono
parents:
diff changeset
979 /* Unhandled node kind. */
kono
parents:
diff changeset
980 gcc_unreachable ();
kono
parents:
diff changeset
981 }
kono
parents:
diff changeset
982 return error_mark_node;
kono
parents:
diff changeset
983 }
kono
parents:
diff changeset
984
kono
parents:
diff changeset
985
kono
parents:
diff changeset
986 /*---------------------------------------------------------------------------
kono
parents:
diff changeset
987 Constraint normalization
kono
parents:
diff changeset
988 ---------------------------------------------------------------------------*/
kono
parents:
diff changeset
989
kono
parents:
diff changeset
990 tree normalize_constraint (tree);
kono
parents:
diff changeset
991
kono
parents:
diff changeset
992 /* The normal form of the disjunction T0 /\ T1 is the conjunction
kono
parents:
diff changeset
993 of the normal form of T0 and the normal form of T1. */
kono
parents:
diff changeset
994
kono
parents:
diff changeset
995 inline tree
kono
parents:
diff changeset
996 normalize_conjunction (tree t)
kono
parents:
diff changeset
997 {
kono
parents:
diff changeset
998 tree t0 = normalize_constraint (TREE_OPERAND (t, 0));
kono
parents:
diff changeset
999 tree t1 = normalize_constraint (TREE_OPERAND (t, 1));
kono
parents:
diff changeset
1000 return build_nt (CONJ_CONSTR, t0, t1);
kono
parents:
diff changeset
1001 }
kono
parents:
diff changeset
1002
kono
parents:
diff changeset
1003 /* The normal form of the disjunction T0 \/ T1 is the disjunction
kono
parents:
diff changeset
1004 of the normal form of T0 and the normal form of T1. */
kono
parents:
diff changeset
1005
kono
parents:
diff changeset
1006 inline tree
kono
parents:
diff changeset
1007 normalize_disjunction (tree t)
kono
parents:
diff changeset
1008 {
kono
parents:
diff changeset
1009 tree t0 = normalize_constraint (TREE_OPERAND (t, 0));
kono
parents:
diff changeset
1010 tree t1 = normalize_constraint (TREE_OPERAND (t, 1));
kono
parents:
diff changeset
1011 return build_nt (DISJ_CONSTR, t0, t1);
kono
parents:
diff changeset
1012 }
kono
parents:
diff changeset
1013
kono
parents:
diff changeset
1014 /* A predicate constraint is normalized in two stages. First all
kono
parents:
diff changeset
1015 references specializations of concepts are replaced by their
kono
parents:
diff changeset
1016 substituted definitions. Then, the resulting expression is
kono
parents:
diff changeset
1017 transformed into a constraint by transforming && expressions
kono
parents:
diff changeset
1018 into conjunctions and || into disjunctions. */
kono
parents:
diff changeset
1019
kono
parents:
diff changeset
1020 tree
kono
parents:
diff changeset
1021 normalize_predicate_constraint (tree t)
kono
parents:
diff changeset
1022 {
kono
parents:
diff changeset
1023 ++processing_template_decl;
kono
parents:
diff changeset
1024 tree expr = PRED_CONSTR_EXPR (t);
kono
parents:
diff changeset
1025 tree constr = normalize_expression (expr);
kono
parents:
diff changeset
1026 --processing_template_decl;
kono
parents:
diff changeset
1027 return constr;
kono
parents:
diff changeset
1028 }
kono
parents:
diff changeset
1029
kono
parents:
diff changeset
1030 /* The normal form of a parameterized constraint is the normal
kono
parents:
diff changeset
1031 form of its operand. */
kono
parents:
diff changeset
1032
kono
parents:
diff changeset
1033 tree
kono
parents:
diff changeset
1034 normalize_parameterized_constraint (tree t)
kono
parents:
diff changeset
1035 {
kono
parents:
diff changeset
1036 tree parms = PARM_CONSTR_PARMS (t);
kono
parents:
diff changeset
1037 tree operand = normalize_constraint (PARM_CONSTR_OPERAND (t));
kono
parents:
diff changeset
1038 return build_nt (PARM_CONSTR, parms, operand);
kono
parents:
diff changeset
1039 }
kono
parents:
diff changeset
1040
kono
parents:
diff changeset
1041 /* Normalize the constraint T by reducing it so that it is
kono
parents:
diff changeset
1042 comprised of only conjunctions and disjunctions of atomic
kono
parents:
diff changeset
1043 constraints. */
kono
parents:
diff changeset
1044
kono
parents:
diff changeset
1045 tree
kono
parents:
diff changeset
1046 normalize_constraint (tree t)
kono
parents:
diff changeset
1047 {
kono
parents:
diff changeset
1048 if (!t)
kono
parents:
diff changeset
1049 return NULL_TREE;
kono
parents:
diff changeset
1050
kono
parents:
diff changeset
1051 if (t == error_mark_node)
kono
parents:
diff changeset
1052 return t;
kono
parents:
diff changeset
1053
kono
parents:
diff changeset
1054 switch (TREE_CODE (t))
kono
parents:
diff changeset
1055 {
kono
parents:
diff changeset
1056 case CONJ_CONSTR:
kono
parents:
diff changeset
1057 return normalize_conjunction (t);
kono
parents:
diff changeset
1058
kono
parents:
diff changeset
1059 case DISJ_CONSTR:
kono
parents:
diff changeset
1060 return normalize_disjunction (t);
kono
parents:
diff changeset
1061
kono
parents:
diff changeset
1062 case PRED_CONSTR:
kono
parents:
diff changeset
1063 return normalize_predicate_constraint (t);
kono
parents:
diff changeset
1064
kono
parents:
diff changeset
1065 case PARM_CONSTR:
kono
parents:
diff changeset
1066 return normalize_parameterized_constraint (t);
kono
parents:
diff changeset
1067
kono
parents:
diff changeset
1068 case EXPR_CONSTR:
kono
parents:
diff changeset
1069 case TYPE_CONSTR:
kono
parents:
diff changeset
1070 case ICONV_CONSTR:
kono
parents:
diff changeset
1071 case DEDUCT_CONSTR:
kono
parents:
diff changeset
1072 case EXCEPT_CONSTR:
kono
parents:
diff changeset
1073 /* These constraints are defined to be atomic. */
kono
parents:
diff changeset
1074 return t;
kono
parents:
diff changeset
1075
kono
parents:
diff changeset
1076 default:
kono
parents:
diff changeset
1077 /* CONSTR was not a constraint. */
kono
parents:
diff changeset
1078 gcc_unreachable();
kono
parents:
diff changeset
1079 }
kono
parents:
diff changeset
1080 return error_mark_node;
kono
parents:
diff changeset
1081 }
kono
parents:
diff changeset
1082
kono
parents:
diff changeset
1083
kono
parents:
diff changeset
1084
kono
parents:
diff changeset
1085 // -------------------------------------------------------------------------- //
kono
parents:
diff changeset
1086 // Constraint Semantic Processing
kono
parents:
diff changeset
1087 //
kono
parents:
diff changeset
1088 // The following functions are called by the parser and substitution rules
kono
parents:
diff changeset
1089 // to create and evaluate constraint-related nodes.
kono
parents:
diff changeset
1090
kono
parents:
diff changeset
1091 // The constraints associated with the current template parameters.
kono
parents:
diff changeset
1092 tree
kono
parents:
diff changeset
1093 current_template_constraints (void)
kono
parents:
diff changeset
1094 {
kono
parents:
diff changeset
1095 if (!current_template_parms)
kono
parents:
diff changeset
1096 return NULL_TREE;
kono
parents:
diff changeset
1097 tree tmpl_constr = TEMPLATE_PARM_CONSTRAINTS (current_template_parms);
kono
parents:
diff changeset
1098 return build_constraints (tmpl_constr, NULL_TREE);
kono
parents:
diff changeset
1099 }
kono
parents:
diff changeset
1100
kono
parents:
diff changeset
1101 // If the recently parsed TYPE declares or defines a template or template
kono
parents:
diff changeset
1102 // specialization, get its corresponding constraints from the current
kono
parents:
diff changeset
1103 // template parameters and bind them to TYPE's declaration.
kono
parents:
diff changeset
1104 tree
kono
parents:
diff changeset
1105 associate_classtype_constraints (tree type)
kono
parents:
diff changeset
1106 {
kono
parents:
diff changeset
1107 if (!type || type == error_mark_node || TREE_CODE (type) != RECORD_TYPE)
kono
parents:
diff changeset
1108 return type;
kono
parents:
diff changeset
1109
kono
parents:
diff changeset
1110 // An explicit class template specialization has no template
kono
parents:
diff changeset
1111 // parameters.
kono
parents:
diff changeset
1112 if (!current_template_parms)
kono
parents:
diff changeset
1113 return type;
kono
parents:
diff changeset
1114
kono
parents:
diff changeset
1115 if (CLASSTYPE_IS_TEMPLATE (type) || CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
kono
parents:
diff changeset
1116 {
kono
parents:
diff changeset
1117 tree decl = TYPE_STUB_DECL (type);
kono
parents:
diff changeset
1118 tree ci = current_template_constraints ();
kono
parents:
diff changeset
1119
kono
parents:
diff changeset
1120 // An implicitly instantiated member template declaration already
kono
parents:
diff changeset
1121 // has associated constraints. If it is defined outside of its
kono
parents:
diff changeset
1122 // class, then we need match these constraints against those of
kono
parents:
diff changeset
1123 // original declaration.
kono
parents:
diff changeset
1124 if (tree orig_ci = get_constraints (decl))
kono
parents:
diff changeset
1125 {
kono
parents:
diff changeset
1126 if (!equivalent_constraints (ci, orig_ci))
kono
parents:
diff changeset
1127 {
kono
parents:
diff changeset
1128 // FIXME: Improve diagnostics.
kono
parents:
diff changeset
1129 error ("%qT does not match any declaration", type);
kono
parents:
diff changeset
1130 return error_mark_node;
kono
parents:
diff changeset
1131 }
kono
parents:
diff changeset
1132 return type;
kono
parents:
diff changeset
1133 }
kono
parents:
diff changeset
1134 set_constraints (decl, ci);
kono
parents:
diff changeset
1135 }
kono
parents:
diff changeset
1136 return type;
kono
parents:
diff changeset
1137 }
kono
parents:
diff changeset
1138
kono
parents:
diff changeset
1139 namespace {
kono
parents:
diff changeset
1140
kono
parents:
diff changeset
1141 // Create an empty constraint info block.
kono
parents:
diff changeset
1142 inline tree_constraint_info*
kono
parents:
diff changeset
1143 build_constraint_info ()
kono
parents:
diff changeset
1144 {
kono
parents:
diff changeset
1145 return (tree_constraint_info *)make_node (CONSTRAINT_INFO);
kono
parents:
diff changeset
1146 }
kono
parents:
diff changeset
1147
kono
parents:
diff changeset
1148 } // namespace
kono
parents:
diff changeset
1149
kono
parents:
diff changeset
1150 /* Build a constraint-info object that contains the associated constraints
kono
parents:
diff changeset
1151 of a declaration. This also includes the declaration's template
kono
parents:
diff changeset
1152 requirements (TREQS) and any trailing requirements for a function
kono
parents:
diff changeset
1153 declarator (DREQS). Note that both TREQS and DREQS must be constraints.
kono
parents:
diff changeset
1154
kono
parents:
diff changeset
1155 If the declaration has neither template nor declaration requirements
kono
parents:
diff changeset
1156 this returns NULL_TREE, indicating an unconstrained declaration. */
kono
parents:
diff changeset
1157
kono
parents:
diff changeset
1158 tree
kono
parents:
diff changeset
1159 build_constraints (tree tmpl_reqs, tree decl_reqs)
kono
parents:
diff changeset
1160 {
kono
parents:
diff changeset
1161 gcc_assert (tmpl_reqs ? constraint_p (tmpl_reqs) : true);
kono
parents:
diff changeset
1162 gcc_assert (decl_reqs ? constraint_p (decl_reqs) : true);
kono
parents:
diff changeset
1163
kono
parents:
diff changeset
1164 if (!tmpl_reqs && !decl_reqs)
kono
parents:
diff changeset
1165 return NULL_TREE;
kono
parents:
diff changeset
1166
kono
parents:
diff changeset
1167 tree_constraint_info* ci = build_constraint_info ();
kono
parents:
diff changeset
1168 ci->template_reqs = tmpl_reqs;
kono
parents:
diff changeset
1169 ci->declarator_reqs = decl_reqs;
kono
parents:
diff changeset
1170 ci->associated_constr = conjoin_constraints (tmpl_reqs, decl_reqs);
kono
parents:
diff changeset
1171
kono
parents:
diff changeset
1172 return (tree)ci;
kono
parents:
diff changeset
1173 }
kono
parents:
diff changeset
1174
kono
parents:
diff changeset
1175 namespace {
kono
parents:
diff changeset
1176
kono
parents:
diff changeset
1177 /* Construct a sequence of template arguments by prepending
kono
parents:
diff changeset
1178 ARG to REST. Either ARG or REST may be null. */
kono
parents:
diff changeset
1179 tree
kono
parents:
diff changeset
1180 build_concept_check_arguments (tree arg, tree rest)
kono
parents:
diff changeset
1181 {
kono
parents:
diff changeset
1182 gcc_assert (rest ? TREE_CODE (rest) == TREE_VEC : true);
kono
parents:
diff changeset
1183 tree args;
kono
parents:
diff changeset
1184 if (arg)
kono
parents:
diff changeset
1185 {
kono
parents:
diff changeset
1186 int n = rest ? TREE_VEC_LENGTH (rest) : 0;
kono
parents:
diff changeset
1187 args = make_tree_vec (n + 1);
kono
parents:
diff changeset
1188 TREE_VEC_ELT (args, 0) = arg;
kono
parents:
diff changeset
1189 if (rest)
kono
parents:
diff changeset
1190 for (int i = 0; i < n; ++i)
kono
parents:
diff changeset
1191 TREE_VEC_ELT (args, i + 1) = TREE_VEC_ELT (rest, i);
kono
parents:
diff changeset
1192 int def = rest ? GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (rest) : 0;
kono
parents:
diff changeset
1193 SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (args, def + 1);
kono
parents:
diff changeset
1194 }
kono
parents:
diff changeset
1195 else
kono
parents:
diff changeset
1196 {
kono
parents:
diff changeset
1197 gcc_assert (rest != NULL_TREE);
kono
parents:
diff changeset
1198 args = rest;
kono
parents:
diff changeset
1199 }
kono
parents:
diff changeset
1200 return args;
kono
parents:
diff changeset
1201 }
kono
parents:
diff changeset
1202
kono
parents:
diff changeset
1203 } // namespace
kono
parents:
diff changeset
1204
kono
parents:
diff changeset
1205 /* Construct an expression that checks the concept given by
kono
parents:
diff changeset
1206 TARGET. The TARGET must be:
kono
parents:
diff changeset
1207
kono
parents:
diff changeset
1208 - an OVERLOAD referring to one or more function concepts
kono
parents:
diff changeset
1209 - a BASELINK referring to an overload set of the above, or
kono
parents:
diff changeset
1210 - a TEMPLTATE_DECL referring to a variable concept.
kono
parents:
diff changeset
1211
kono
parents:
diff changeset
1212 ARG and REST are the explicit template arguments for the
kono
parents:
diff changeset
1213 eventual concept check. */
kono
parents:
diff changeset
1214 tree
kono
parents:
diff changeset
1215 build_concept_check (tree target, tree arg, tree rest)
kono
parents:
diff changeset
1216 {
kono
parents:
diff changeset
1217 tree args = build_concept_check_arguments (arg, rest);
kono
parents:
diff changeset
1218 if (variable_template_p (target))
kono
parents:
diff changeset
1219 return build_variable_check (lookup_template_variable (target, args));
kono
parents:
diff changeset
1220 else
kono
parents:
diff changeset
1221 return build_call_check (lookup_template_function (target, args));
kono
parents:
diff changeset
1222 }
kono
parents:
diff changeset
1223
kono
parents:
diff changeset
1224
kono
parents:
diff changeset
1225 /* Returns a TYPE_DECL that contains sufficient information to
kono
parents:
diff changeset
1226 build a template parameter of the same kind as PROTO and
kono
parents:
diff changeset
1227 constrained by the concept declaration CNC. Note that PROTO
kono
parents:
diff changeset
1228 is the first template parameter of CNC.
kono
parents:
diff changeset
1229
kono
parents:
diff changeset
1230 If specified, ARGS provides additional arguments to the
kono
parents:
diff changeset
1231 constraint check. */
kono
parents:
diff changeset
1232 tree
kono
parents:
diff changeset
1233 build_constrained_parameter (tree cnc, tree proto, tree args)
kono
parents:
diff changeset
1234 {
kono
parents:
diff changeset
1235 tree name = DECL_NAME (cnc);
kono
parents:
diff changeset
1236 tree type = TREE_TYPE (proto);
kono
parents:
diff changeset
1237 tree decl = build_decl (input_location, TYPE_DECL, name, type);
kono
parents:
diff changeset
1238 CONSTRAINED_PARM_PROTOTYPE (decl) = proto;
kono
parents:
diff changeset
1239 CONSTRAINED_PARM_CONCEPT (decl) = cnc;
kono
parents:
diff changeset
1240 CONSTRAINED_PARM_EXTRA_ARGS (decl) = args;
kono
parents:
diff changeset
1241 return decl;
kono
parents:
diff changeset
1242 }
kono
parents:
diff changeset
1243
kono
parents:
diff changeset
1244 /* Create a constraint expression for the given DECL that
kono
parents:
diff changeset
1245 evaluates the requirements specified by CONSTR, a TYPE_DECL
kono
parents:
diff changeset
1246 that contains all the information necessary to build the
kono
parents:
diff changeset
1247 requirements (see finish_concept_name for the layout of
kono
parents:
diff changeset
1248 that TYPE_DECL).
kono
parents:
diff changeset
1249
kono
parents:
diff changeset
1250 Note that the constraints are neither reduced nor decomposed.
kono
parents:
diff changeset
1251 That is done only after the requires clause has been parsed
kono
parents:
diff changeset
1252 (or not).
kono
parents:
diff changeset
1253
kono
parents:
diff changeset
1254 This will always return a CHECK_CONSTR. */
kono
parents:
diff changeset
1255 tree
kono
parents:
diff changeset
1256 finish_shorthand_constraint (tree decl, tree constr)
kono
parents:
diff changeset
1257 {
kono
parents:
diff changeset
1258 /* No requirements means no constraints. */
kono
parents:
diff changeset
1259 if (!constr)
kono
parents:
diff changeset
1260 return NULL_TREE;
kono
parents:
diff changeset
1261
kono
parents:
diff changeset
1262 tree proto = CONSTRAINED_PARM_PROTOTYPE (constr);
kono
parents:
diff changeset
1263 tree con = CONSTRAINED_PARM_CONCEPT (constr);
kono
parents:
diff changeset
1264 tree args = CONSTRAINED_PARM_EXTRA_ARGS (constr);
kono
parents:
diff changeset
1265
kono
parents:
diff changeset
1266 /* If the parameter declaration is variadic, but the concept
kono
parents:
diff changeset
1267 is not then we need to apply the concept to every element
kono
parents:
diff changeset
1268 in the pack. */
kono
parents:
diff changeset
1269 bool is_proto_pack = template_parameter_pack_p (proto);
kono
parents:
diff changeset
1270 bool is_decl_pack = template_parameter_pack_p (decl);
kono
parents:
diff changeset
1271 bool apply_to_all_p = is_decl_pack && !is_proto_pack;
kono
parents:
diff changeset
1272
kono
parents:
diff changeset
1273 /* Get the argument and overload used for the requirement
kono
parents:
diff changeset
1274 and adjust it if we're going to expand later. */
kono
parents:
diff changeset
1275 tree arg = template_parm_to_arg (build_tree_list (NULL_TREE, decl));
kono
parents:
diff changeset
1276 if (apply_to_all_p)
kono
parents:
diff changeset
1277 arg = PACK_EXPANSION_PATTERN (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg), 0));
kono
parents:
diff changeset
1278
kono
parents:
diff changeset
1279 /* Build the concept check. If it the constraint needs to be
kono
parents:
diff changeset
1280 applied to all elements of the parameter pack, then make
kono
parents:
diff changeset
1281 the constraint an expansion. */
kono
parents:
diff changeset
1282 tree tmpl = DECL_TI_TEMPLATE (con);
kono
parents:
diff changeset
1283 tree check = VAR_P (con) ? tmpl : ovl_make (tmpl);
kono
parents:
diff changeset
1284 check = build_concept_check (check, arg, args);
kono
parents:
diff changeset
1285
kono
parents:
diff changeset
1286 /* Make the check a pack expansion if needed.
kono
parents:
diff changeset
1287
kono
parents:
diff changeset
1288 FIXME: We should be making a fold expression. */
kono
parents:
diff changeset
1289 if (apply_to_all_p)
kono
parents:
diff changeset
1290 {
kono
parents:
diff changeset
1291 check = make_pack_expansion (check);
kono
parents:
diff changeset
1292 TREE_TYPE (check) = boolean_type_node;
kono
parents:
diff changeset
1293 }
kono
parents:
diff changeset
1294
kono
parents:
diff changeset
1295 return normalize_expression (check);
kono
parents:
diff changeset
1296 }
kono
parents:
diff changeset
1297
kono
parents:
diff changeset
1298 /* Returns a conjunction of shorthand requirements for the template
kono
parents:
diff changeset
1299 parameter list PARMS. Note that the requirements are stored in
kono
parents:
diff changeset
1300 the TYPE of each tree node. */
kono
parents:
diff changeset
1301 tree
kono
parents:
diff changeset
1302 get_shorthand_constraints (tree parms)
kono
parents:
diff changeset
1303 {
kono
parents:
diff changeset
1304 tree result = NULL_TREE;
kono
parents:
diff changeset
1305 parms = INNERMOST_TEMPLATE_PARMS (parms);
kono
parents:
diff changeset
1306 for (int i = 0; i < TREE_VEC_LENGTH (parms); ++i)
kono
parents:
diff changeset
1307 {
kono
parents:
diff changeset
1308 tree parm = TREE_VEC_ELT (parms, i);
kono
parents:
diff changeset
1309 tree constr = TEMPLATE_PARM_CONSTRAINTS (parm);
kono
parents:
diff changeset
1310 result = conjoin_constraints (result, constr);
kono
parents:
diff changeset
1311 }
kono
parents:
diff changeset
1312 return result;
kono
parents:
diff changeset
1313 }
kono
parents:
diff changeset
1314
kono
parents:
diff changeset
1315 // Returns and chains a new parameter for PARAMETER_LIST which will conform
kono
parents:
diff changeset
1316 // to the prototype given by SRC_PARM. The new parameter will have its
kono
parents:
diff changeset
1317 // identifier and location set according to IDENT and PARM_LOC respectively.
kono
parents:
diff changeset
1318 static tree
kono
parents:
diff changeset
1319 process_introduction_parm (tree parameter_list, tree src_parm)
kono
parents:
diff changeset
1320 {
kono
parents:
diff changeset
1321 // If we have a pack, we should have a single pack argument which is the
kono
parents:
diff changeset
1322 // placeholder we want to look at.
kono
parents:
diff changeset
1323 bool is_parameter_pack = ARGUMENT_PACK_P (src_parm);
kono
parents:
diff changeset
1324 if (is_parameter_pack)
kono
parents:
diff changeset
1325 src_parm = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (src_parm), 0);
kono
parents:
diff changeset
1326
kono
parents:
diff changeset
1327 // At this point we should have a wildcard, but we want to
kono
parents:
diff changeset
1328 // grab the associated decl from it. Also grab the stored
kono
parents:
diff changeset
1329 // identifier and location that should be chained to it in
kono
parents:
diff changeset
1330 // a PARM_DECL.
kono
parents:
diff changeset
1331 gcc_assert (TREE_CODE (src_parm) == WILDCARD_DECL);
kono
parents:
diff changeset
1332
kono
parents:
diff changeset
1333 tree ident = DECL_NAME (src_parm);
kono
parents:
diff changeset
1334 location_t parm_loc = DECL_SOURCE_LOCATION (src_parm);
kono
parents:
diff changeset
1335
kono
parents:
diff changeset
1336 // If we expect a pack and the deduced template is not a pack, or if the
kono
parents:
diff changeset
1337 // template is using a pack and we didn't declare a pack, throw an error.
kono
parents:
diff changeset
1338 if (is_parameter_pack != WILDCARD_PACK_P (src_parm))
kono
parents:
diff changeset
1339 {
kono
parents:
diff changeset
1340 error_at (parm_loc, "cannot match pack for introduced parameter");
kono
parents:
diff changeset
1341 tree err_parm = build_tree_list (error_mark_node, error_mark_node);
kono
parents:
diff changeset
1342 return chainon (parameter_list, err_parm);
kono
parents:
diff changeset
1343 }
kono
parents:
diff changeset
1344
kono
parents:
diff changeset
1345 src_parm = TREE_TYPE (src_parm);
kono
parents:
diff changeset
1346
kono
parents:
diff changeset
1347 tree parm;
kono
parents:
diff changeset
1348 bool is_non_type;
kono
parents:
diff changeset
1349 if (TREE_CODE (src_parm) == TYPE_DECL)
kono
parents:
diff changeset
1350 {
kono
parents:
diff changeset
1351 is_non_type = false;
kono
parents:
diff changeset
1352 parm = finish_template_type_parm (class_type_node, ident);
kono
parents:
diff changeset
1353 }
kono
parents:
diff changeset
1354 else if (TREE_CODE (src_parm) == TEMPLATE_DECL)
kono
parents:
diff changeset
1355 {
kono
parents:
diff changeset
1356 is_non_type = false;
kono
parents:
diff changeset
1357 begin_template_parm_list ();
kono
parents:
diff changeset
1358 current_template_parms = DECL_TEMPLATE_PARMS (src_parm);
kono
parents:
diff changeset
1359 end_template_parm_list ();
kono
parents:
diff changeset
1360 parm = finish_template_template_parm (class_type_node, ident);
kono
parents:
diff changeset
1361 }
kono
parents:
diff changeset
1362 else
kono
parents:
diff changeset
1363 {
kono
parents:
diff changeset
1364 is_non_type = true;
kono
parents:
diff changeset
1365
kono
parents:
diff changeset
1366 // Since we don't have a declarator, so we can copy the source
kono
parents:
diff changeset
1367 // parameter and change the name and eventually the location.
kono
parents:
diff changeset
1368 parm = copy_decl (src_parm);
kono
parents:
diff changeset
1369 DECL_NAME (parm) = ident;
kono
parents:
diff changeset
1370 }
kono
parents:
diff changeset
1371
kono
parents:
diff changeset
1372 // Wrap in a TREE_LIST for process_template_parm. Introductions do not
kono
parents:
diff changeset
1373 // retain the defaults from the source template.
kono
parents:
diff changeset
1374 parm = build_tree_list (NULL_TREE, parm);
kono
parents:
diff changeset
1375
kono
parents:
diff changeset
1376 return process_template_parm (parameter_list, parm_loc, parm,
kono
parents:
diff changeset
1377 is_non_type, is_parameter_pack);
kono
parents:
diff changeset
1378 }
kono
parents:
diff changeset
1379
kono
parents:
diff changeset
1380 /* Associates a constraint check to the current template based
kono
parents:
diff changeset
1381 on the introduction parameters. INTRO_LIST must be a TREE_VEC
kono
parents:
diff changeset
1382 of WILDCARD_DECLs containing a chained PARM_DECL which
kono
parents:
diff changeset
1383 contains the identifier as well as the source location.
kono
parents:
diff changeset
1384 TMPL_DECL is the decl for the concept being used. If we
kono
parents:
diff changeset
1385 take a concept, C, this will form a check in the form of
kono
parents:
diff changeset
1386 C<INTRO_LIST> filling in any extra arguments needed by the
kono
parents:
diff changeset
1387 defaults deduced.
kono
parents:
diff changeset
1388
kono
parents:
diff changeset
1389 Returns NULL_TREE if no concept could be matched and
kono
parents:
diff changeset
1390 error_mark_node if an error occurred when matching. */
kono
parents:
diff changeset
1391 tree
kono
parents:
diff changeset
1392 finish_template_introduction (tree tmpl_decl, tree intro_list)
kono
parents:
diff changeset
1393 {
kono
parents:
diff changeset
1394 /* Deduce the concept check. */
kono
parents:
diff changeset
1395 tree expr = build_concept_check (tmpl_decl, NULL_TREE, intro_list);
kono
parents:
diff changeset
1396 if (expr == error_mark_node)
kono
parents:
diff changeset
1397 return NULL_TREE;
kono
parents:
diff changeset
1398
kono
parents:
diff changeset
1399 tree parms = deduce_concept_introduction (expr);
kono
parents:
diff changeset
1400 if (!parms)
kono
parents:
diff changeset
1401 return NULL_TREE;
kono
parents:
diff changeset
1402
kono
parents:
diff changeset
1403 /* Build template parameter scope for introduction. */
kono
parents:
diff changeset
1404 tree parm_list = NULL_TREE;
kono
parents:
diff changeset
1405 begin_template_parm_list ();
kono
parents:
diff changeset
1406 int nargs = MIN (TREE_VEC_LENGTH (parms), TREE_VEC_LENGTH (intro_list));
kono
parents:
diff changeset
1407 for (int n = 0; n < nargs; ++n)
kono
parents:
diff changeset
1408 parm_list = process_introduction_parm (parm_list, TREE_VEC_ELT (parms, n));
kono
parents:
diff changeset
1409 parm_list = end_template_parm_list (parm_list);
kono
parents:
diff changeset
1410 for (int i = 0; i < TREE_VEC_LENGTH (parm_list); ++i)
kono
parents:
diff changeset
1411 if (TREE_VALUE (TREE_VEC_ELT (parm_list, i)) == error_mark_node)
kono
parents:
diff changeset
1412 {
kono
parents:
diff changeset
1413 end_template_decl ();
kono
parents:
diff changeset
1414 return error_mark_node;
kono
parents:
diff changeset
1415 }
kono
parents:
diff changeset
1416
kono
parents:
diff changeset
1417 /* Build a concept check for our constraint. */
kono
parents:
diff changeset
1418 tree check_args = make_tree_vec (TREE_VEC_LENGTH (parms));
kono
parents:
diff changeset
1419 int n = 0;
kono
parents:
diff changeset
1420 for (; n < TREE_VEC_LENGTH (parm_list); ++n)
kono
parents:
diff changeset
1421 {
kono
parents:
diff changeset
1422 tree parm = TREE_VEC_ELT (parm_list, n);
kono
parents:
diff changeset
1423 TREE_VEC_ELT (check_args, n) = template_parm_to_arg (parm);
kono
parents:
diff changeset
1424 }
kono
parents:
diff changeset
1425 SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (check_args, n);
kono
parents:
diff changeset
1426
kono
parents:
diff changeset
1427 /* If the template expects more parameters we should be able
kono
parents:
diff changeset
1428 to use the defaults from our deduced concept. */
kono
parents:
diff changeset
1429 for (; n < TREE_VEC_LENGTH (parms); ++n)
kono
parents:
diff changeset
1430 TREE_VEC_ELT (check_args, n) = TREE_VEC_ELT (parms, n);
kono
parents:
diff changeset
1431
kono
parents:
diff changeset
1432 /* Associate the constraint. */
kono
parents:
diff changeset
1433 tree check = build_concept_check (tmpl_decl, NULL_TREE, check_args);
kono
parents:
diff changeset
1434 tree constr = normalize_expression (check);
kono
parents:
diff changeset
1435 TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = constr;
kono
parents:
diff changeset
1436
kono
parents:
diff changeset
1437 return parm_list;
kono
parents:
diff changeset
1438 }
kono
parents:
diff changeset
1439
kono
parents:
diff changeset
1440
kono
parents:
diff changeset
1441 /* Given the predicate constraint T from a constrained-type-specifier, extract
kono
parents:
diff changeset
1442 its TMPL and ARGS. FIXME why do we need two different forms of
kono
parents:
diff changeset
1443 constrained-type-specifier? */
kono
parents:
diff changeset
1444
kono
parents:
diff changeset
1445 void
kono
parents:
diff changeset
1446 placeholder_extract_concept_and_args (tree t, tree &tmpl, tree &args)
kono
parents:
diff changeset
1447 {
kono
parents:
diff changeset
1448 if (TREE_CODE (t) == TYPE_DECL)
kono
parents:
diff changeset
1449 {
kono
parents:
diff changeset
1450 /* A constrained parameter. Build a constraint check
kono
parents:
diff changeset
1451 based on the prototype parameter and then extract the
kono
parents:
diff changeset
1452 arguments from that. */
kono
parents:
diff changeset
1453 tree proto = CONSTRAINED_PARM_PROTOTYPE (t);
kono
parents:
diff changeset
1454 tree check = finish_shorthand_constraint (proto, t);
kono
parents:
diff changeset
1455 placeholder_extract_concept_and_args (check, tmpl, args);
kono
parents:
diff changeset
1456 return;
kono
parents:
diff changeset
1457 }
kono
parents:
diff changeset
1458
kono
parents:
diff changeset
1459 if (TREE_CODE (t) == CHECK_CONSTR)
kono
parents:
diff changeset
1460 {
kono
parents:
diff changeset
1461 tree decl = CHECK_CONSTR_CONCEPT (t);
kono
parents:
diff changeset
1462 tmpl = DECL_TI_TEMPLATE (decl);
kono
parents:
diff changeset
1463 args = CHECK_CONSTR_ARGS (t);
kono
parents:
diff changeset
1464 return;
kono
parents:
diff changeset
1465 }
kono
parents:
diff changeset
1466
kono
parents:
diff changeset
1467 gcc_unreachable ();
kono
parents:
diff changeset
1468 }
kono
parents:
diff changeset
1469
kono
parents:
diff changeset
1470 /* Returns true iff the placeholders C1 and C2 are equivalent. C1
kono
parents:
diff changeset
1471 and C2 can be either CHECK_CONSTR or TEMPLATE_TYPE_PARM. */
kono
parents:
diff changeset
1472
kono
parents:
diff changeset
1473 bool
kono
parents:
diff changeset
1474 equivalent_placeholder_constraints (tree c1, tree c2)
kono
parents:
diff changeset
1475 {
kono
parents:
diff changeset
1476 if (c1 && TREE_CODE (c1) == TEMPLATE_TYPE_PARM)
kono
parents:
diff changeset
1477 /* A constrained auto. */
kono
parents:
diff changeset
1478 c1 = PLACEHOLDER_TYPE_CONSTRAINTS (c1);
kono
parents:
diff changeset
1479 if (c2 && TREE_CODE (c2) == TEMPLATE_TYPE_PARM)
kono
parents:
diff changeset
1480 c2 = PLACEHOLDER_TYPE_CONSTRAINTS (c2);
kono
parents:
diff changeset
1481
kono
parents:
diff changeset
1482 if (c1 == c2)
kono
parents:
diff changeset
1483 return true;
kono
parents:
diff changeset
1484 if (!c1 || !c2)
kono
parents:
diff changeset
1485 return false;
kono
parents:
diff changeset
1486 if (c1 == error_mark_node || c2 == error_mark_node)
kono
parents:
diff changeset
1487 /* We get here during satisfaction; when a deduction constraint
kono
parents:
diff changeset
1488 fails, substitution can produce an error_mark_node for the
kono
parents:
diff changeset
1489 placeholder constraints. */
kono
parents:
diff changeset
1490 return false;
kono
parents:
diff changeset
1491
kono
parents:
diff changeset
1492 tree t1, t2, a1, a2;
kono
parents:
diff changeset
1493 placeholder_extract_concept_and_args (c1, t1, a1);
kono
parents:
diff changeset
1494 placeholder_extract_concept_and_args (c2, t2, a2);
kono
parents:
diff changeset
1495
kono
parents:
diff changeset
1496 if (t1 != t2)
kono
parents:
diff changeset
1497 return false;
kono
parents:
diff changeset
1498
kono
parents:
diff changeset
1499 int len1 = TREE_VEC_LENGTH (a1);
kono
parents:
diff changeset
1500 int len2 = TREE_VEC_LENGTH (a2);
kono
parents:
diff changeset
1501 if (len1 != len2)
kono
parents:
diff changeset
1502 return false;
kono
parents:
diff changeset
1503
kono
parents:
diff changeset
1504 /* Skip the first argument so we don't infinitely recurse.
kono
parents:
diff changeset
1505 Also, they may differ in template parameter index. */
kono
parents:
diff changeset
1506 for (int i = 1; i < len1; ++i)
kono
parents:
diff changeset
1507 {
kono
parents:
diff changeset
1508 tree t1 = TREE_VEC_ELT (a1, i);
kono
parents:
diff changeset
1509 tree t2 = TREE_VEC_ELT (a2, i);
kono
parents:
diff changeset
1510 if (!template_args_equal (t1, t2))
kono
parents:
diff changeset
1511 return false;
kono
parents:
diff changeset
1512 }
kono
parents:
diff changeset
1513 return true;
kono
parents:
diff changeset
1514 }
kono
parents:
diff changeset
1515
kono
parents:
diff changeset
1516 /* Return a hash value for the placeholder PRED_CONSTR C. */
kono
parents:
diff changeset
1517
kono
parents:
diff changeset
1518 hashval_t
kono
parents:
diff changeset
1519 hash_placeholder_constraint (tree c)
kono
parents:
diff changeset
1520 {
kono
parents:
diff changeset
1521 tree t, a;
kono
parents:
diff changeset
1522 placeholder_extract_concept_and_args (c, t, a);
kono
parents:
diff changeset
1523
kono
parents:
diff changeset
1524 /* Like hash_tmpl_and_args, but skip the first argument. */
kono
parents:
diff changeset
1525 hashval_t val = iterative_hash_object (DECL_UID (t), 0);
kono
parents:
diff changeset
1526
kono
parents:
diff changeset
1527 for (int i = TREE_VEC_LENGTH (a)-1; i > 0; --i)
kono
parents:
diff changeset
1528 val = iterative_hash_template_arg (TREE_VEC_ELT (a, i), val);
kono
parents:
diff changeset
1529
kono
parents:
diff changeset
1530 return val;
kono
parents:
diff changeset
1531 }
kono
parents:
diff changeset
1532
kono
parents:
diff changeset
1533 /*---------------------------------------------------------------------------
kono
parents:
diff changeset
1534 Constraint substitution
kono
parents:
diff changeset
1535 ---------------------------------------------------------------------------*/
kono
parents:
diff changeset
1536
kono
parents:
diff changeset
1537 /* The following functions implement substitution rules for constraints.
kono
parents:
diff changeset
1538 Substitution without checking constraints happens only in the
kono
parents:
diff changeset
1539 instantiation of class templates. For example:
kono
parents:
diff changeset
1540
kono
parents:
diff changeset
1541 template<C1 T> struct S {
kono
parents:
diff changeset
1542 void f(T) requires C2<T>;
kono
parents:
diff changeset
1543 void g(T) requires T::value;
kono
parents:
diff changeset
1544 };
kono
parents:
diff changeset
1545
kono
parents:
diff changeset
1546 S<int> s; // error instantiating S<int>::g(T)
kono
parents:
diff changeset
1547
kono
parents:
diff changeset
1548 When we instantiate S, we substitute into its member declarations,
kono
parents:
diff changeset
1549 including their constraints. However, those constraints are not
kono
parents:
diff changeset
1550 checked. Substituting int into C2<T> yields C2<int>, and substituting
kono
parents:
diff changeset
1551 into T::value yields a substitution failure, making the program
kono
parents:
diff changeset
1552 ill-formed.
kono
parents:
diff changeset
1553
kono
parents:
diff changeset
1554 Note that we only ever substitute into the associated constraints
kono
parents:
diff changeset
1555 of a declaration. That is, substitution is defined only for predicate
kono
parents:
diff changeset
1556 constraints and conjunctions. */
kono
parents:
diff changeset
1557
kono
parents:
diff changeset
1558 /* Substitute into the predicate constraints. Returns error_mark_node
kono
parents:
diff changeset
1559 if the substitution into the expression fails. */
kono
parents:
diff changeset
1560 tree
kono
parents:
diff changeset
1561 tsubst_predicate_constraint (tree t, tree args,
kono
parents:
diff changeset
1562 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1563 {
kono
parents:
diff changeset
1564 tree expr = PRED_CONSTR_EXPR (t);
kono
parents:
diff changeset
1565 ++processing_template_decl;
kono
parents:
diff changeset
1566 tree result = tsubst_expr (expr, args, complain, in_decl, false);
kono
parents:
diff changeset
1567 --processing_template_decl;
kono
parents:
diff changeset
1568 return build_nt (PRED_CONSTR, result);
kono
parents:
diff changeset
1569 }
kono
parents:
diff changeset
1570
kono
parents:
diff changeset
1571 /* Substitute into a check constraint. */
kono
parents:
diff changeset
1572
kono
parents:
diff changeset
1573 tree
kono
parents:
diff changeset
1574 tsubst_check_constraint (tree t, tree args,
kono
parents:
diff changeset
1575 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1576 {
kono
parents:
diff changeset
1577 tree decl = CHECK_CONSTR_CONCEPT (t);
kono
parents:
diff changeset
1578 tree tmpl = DECL_TI_TEMPLATE (decl);
kono
parents:
diff changeset
1579 tree targs = CHECK_CONSTR_ARGS (t);
kono
parents:
diff changeset
1580
kono
parents:
diff changeset
1581 /* Substitute through by building an template-id expression
kono
parents:
diff changeset
1582 and then substituting into that. */
kono
parents:
diff changeset
1583 tree expr = build_nt (TEMPLATE_ID_EXPR, tmpl, targs);
kono
parents:
diff changeset
1584 ++processing_template_decl;
kono
parents:
diff changeset
1585 tree result = tsubst_expr (expr, args, complain, in_decl, false);
kono
parents:
diff changeset
1586 --processing_template_decl;
kono
parents:
diff changeset
1587
kono
parents:
diff changeset
1588 if (result == error_mark_node)
kono
parents:
diff changeset
1589 return error_mark_node;
kono
parents:
diff changeset
1590
kono
parents:
diff changeset
1591 /* Extract the results and rebuild the check constraint. */
kono
parents:
diff changeset
1592 decl = DECL_TEMPLATE_RESULT (TREE_OPERAND (result, 0));
kono
parents:
diff changeset
1593 args = TREE_OPERAND (result, 1);
kono
parents:
diff changeset
1594
kono
parents:
diff changeset
1595 return build_nt (CHECK_CONSTR, decl, args);
kono
parents:
diff changeset
1596 }
kono
parents:
diff changeset
1597
kono
parents:
diff changeset
1598 /* Substitute into the conjunction of constraints. Returns
kono
parents:
diff changeset
1599 error_mark_node if substitution into either operand fails. */
kono
parents:
diff changeset
1600
kono
parents:
diff changeset
1601 tree
kono
parents:
diff changeset
1602 tsubst_logical_operator (tree t, tree args,
kono
parents:
diff changeset
1603 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1604 {
kono
parents:
diff changeset
1605 tree t0 = TREE_OPERAND (t, 0);
kono
parents:
diff changeset
1606 tree r0 = tsubst_constraint (t0, args, complain, in_decl);
kono
parents:
diff changeset
1607 if (r0 == error_mark_node)
kono
parents:
diff changeset
1608 return error_mark_node;
kono
parents:
diff changeset
1609 tree t1 = TREE_OPERAND (t, 1);
kono
parents:
diff changeset
1610 tree r1 = tsubst_constraint (t1, args, complain, in_decl);
kono
parents:
diff changeset
1611 if (r1 == error_mark_node)
kono
parents:
diff changeset
1612 return error_mark_node;
kono
parents:
diff changeset
1613 return build_nt (TREE_CODE (t), r0, r1);
kono
parents:
diff changeset
1614 }
kono
parents:
diff changeset
1615
kono
parents:
diff changeset
1616 namespace {
kono
parents:
diff changeset
1617
kono
parents:
diff changeset
1618 /* Substitute ARGS into the expression constraint T. */
kono
parents:
diff changeset
1619
kono
parents:
diff changeset
1620 tree
kono
parents:
diff changeset
1621 tsubst_expr_constr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1622 {
kono
parents:
diff changeset
1623 cp_unevaluated guard;
kono
parents:
diff changeset
1624 tree expr = EXPR_CONSTR_EXPR (t);
kono
parents:
diff changeset
1625 tree ret = tsubst_expr (expr, args, complain, in_decl, false);
kono
parents:
diff changeset
1626 if (ret == error_mark_node)
kono
parents:
diff changeset
1627 return error_mark_node;
kono
parents:
diff changeset
1628 return build_nt (EXPR_CONSTR, ret);
kono
parents:
diff changeset
1629 }
kono
parents:
diff changeset
1630
kono
parents:
diff changeset
1631 /* Substitute ARGS into the type constraint T. */
kono
parents:
diff changeset
1632
kono
parents:
diff changeset
1633 tree
kono
parents:
diff changeset
1634 tsubst_type_constr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1635 {
kono
parents:
diff changeset
1636 tree type = TYPE_CONSTR_TYPE (t);
kono
parents:
diff changeset
1637 tree ret = tsubst (type, args, complain, in_decl);
kono
parents:
diff changeset
1638 if (ret == error_mark_node)
kono
parents:
diff changeset
1639 return error_mark_node;
kono
parents:
diff changeset
1640 return build_nt (TYPE_CONSTR, ret);
kono
parents:
diff changeset
1641 }
kono
parents:
diff changeset
1642
kono
parents:
diff changeset
1643 /* Substitute ARGS into the implicit conversion constraint T. */
kono
parents:
diff changeset
1644
kono
parents:
diff changeset
1645 tree
kono
parents:
diff changeset
1646 tsubst_implicit_conversion_constr (tree t, tree args, tsubst_flags_t complain,
kono
parents:
diff changeset
1647 tree in_decl)
kono
parents:
diff changeset
1648 {
kono
parents:
diff changeset
1649 cp_unevaluated guard;
kono
parents:
diff changeset
1650 tree expr = ICONV_CONSTR_EXPR (t);
kono
parents:
diff changeset
1651 tree type = ICONV_CONSTR_TYPE (t);
kono
parents:
diff changeset
1652 tree new_expr = tsubst_expr (expr, args, complain, in_decl, false);
kono
parents:
diff changeset
1653 if (new_expr == error_mark_node)
kono
parents:
diff changeset
1654 return error_mark_node;
kono
parents:
diff changeset
1655 tree new_type = tsubst (type, args, complain, in_decl);
kono
parents:
diff changeset
1656 if (new_type == error_mark_node)
kono
parents:
diff changeset
1657 return error_mark_node;
kono
parents:
diff changeset
1658 return build_nt (ICONV_CONSTR, new_expr, new_type);
kono
parents:
diff changeset
1659 }
kono
parents:
diff changeset
1660
kono
parents:
diff changeset
1661 /* Substitute ARGS into the argument deduction constraint T. */
kono
parents:
diff changeset
1662
kono
parents:
diff changeset
1663 tree
kono
parents:
diff changeset
1664 tsubst_argument_deduction_constr (tree t, tree args, tsubst_flags_t complain,
kono
parents:
diff changeset
1665 tree in_decl)
kono
parents:
diff changeset
1666 {
kono
parents:
diff changeset
1667 cp_unevaluated guard;
kono
parents:
diff changeset
1668 tree expr = DEDUCT_CONSTR_EXPR (t);
kono
parents:
diff changeset
1669 tree pattern = DEDUCT_CONSTR_PATTERN (t);
kono
parents:
diff changeset
1670 tree autos = DEDUCT_CONSTR_PLACEHOLDER(t);
kono
parents:
diff changeset
1671 tree new_expr = tsubst_expr (expr, args, complain, in_decl, false);
kono
parents:
diff changeset
1672 if (new_expr == error_mark_node)
kono
parents:
diff changeset
1673 return error_mark_node;
kono
parents:
diff changeset
1674 /* It seems like substituting through the pattern will not affect the
kono
parents:
diff changeset
1675 placeholders. We should (?) be able to reuse the existing list
kono
parents:
diff changeset
1676 without any problems. If not, then we probably want to create a
kono
parents:
diff changeset
1677 new list of placeholders and then instantiate the pattern using
kono
parents:
diff changeset
1678 those. */
kono
parents:
diff changeset
1679 tree new_pattern = tsubst (pattern, args, complain, in_decl);
kono
parents:
diff changeset
1680 if (new_pattern == error_mark_node)
kono
parents:
diff changeset
1681 return error_mark_node;
kono
parents:
diff changeset
1682 return build_nt (DEDUCT_CONSTR, new_expr, new_pattern, autos);
kono
parents:
diff changeset
1683 }
kono
parents:
diff changeset
1684
kono
parents:
diff changeset
1685 /* Substitute ARGS into the exception constraint T. */
kono
parents:
diff changeset
1686
kono
parents:
diff changeset
1687 tree
kono
parents:
diff changeset
1688 tsubst_exception_constr (tree t, tree args, tsubst_flags_t complain,
kono
parents:
diff changeset
1689 tree in_decl)
kono
parents:
diff changeset
1690 {
kono
parents:
diff changeset
1691 cp_unevaluated guard;
kono
parents:
diff changeset
1692 tree expr = EXCEPT_CONSTR_EXPR (t);
kono
parents:
diff changeset
1693 tree ret = tsubst_expr (expr, args, complain, in_decl, false);
kono
parents:
diff changeset
1694 if (ret == error_mark_node)
kono
parents:
diff changeset
1695 return error_mark_node;
kono
parents:
diff changeset
1696 return build_nt (EXCEPT_CONSTR, ret);
kono
parents:
diff changeset
1697 }
kono
parents:
diff changeset
1698
kono
parents:
diff changeset
1699 /* A subroutine of tsubst_constraint_variables. Register local
kono
parents:
diff changeset
1700 specializations for each of parameter in PARMS and its
kono
parents:
diff changeset
1701 corresponding substituted constraint variable in VARS.
kono
parents:
diff changeset
1702 Returns VARS. */
kono
parents:
diff changeset
1703
kono
parents:
diff changeset
1704 tree
kono
parents:
diff changeset
1705 declare_constraint_vars (tree parms, tree vars)
kono
parents:
diff changeset
1706 {
kono
parents:
diff changeset
1707 tree s = vars;
kono
parents:
diff changeset
1708 for (tree t = parms; t; t = DECL_CHAIN (t))
kono
parents:
diff changeset
1709 {
kono
parents:
diff changeset
1710 if (DECL_PACK_P (t))
kono
parents:
diff changeset
1711 {
kono
parents:
diff changeset
1712 tree pack = extract_fnparm_pack (t, &s);
kono
parents:
diff changeset
1713 register_local_specialization (pack, t);
kono
parents:
diff changeset
1714 }
kono
parents:
diff changeset
1715 else
kono
parents:
diff changeset
1716 {
kono
parents:
diff changeset
1717 register_local_specialization (s, t);
kono
parents:
diff changeset
1718 s = DECL_CHAIN (s);
kono
parents:
diff changeset
1719 }
kono
parents:
diff changeset
1720 }
kono
parents:
diff changeset
1721 return vars;
kono
parents:
diff changeset
1722 }
kono
parents:
diff changeset
1723
kono
parents:
diff changeset
1724 /* A subroutine of tsubst_parameterized_constraint. Substitute ARGS
kono
parents:
diff changeset
1725 into the parameter list T, producing a sequence of constraint
kono
parents:
diff changeset
1726 variables, declared in the current scope.
kono
parents:
diff changeset
1727
kono
parents:
diff changeset
1728 Note that the caller must establish a local specialization stack
kono
parents:
diff changeset
1729 prior to calling this function since this substitution will
kono
parents:
diff changeset
1730 declare the substituted parameters. */
kono
parents:
diff changeset
1731
kono
parents:
diff changeset
1732 tree
kono
parents:
diff changeset
1733 tsubst_constraint_variables (tree t, tree args,
kono
parents:
diff changeset
1734 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1735 {
kono
parents:
diff changeset
1736 /* Clear cp_unevaluated_operand across tsubst so that we get a proper chain
kono
parents:
diff changeset
1737 of PARM_DECLs. */
kono
parents:
diff changeset
1738 int saved_unevaluated_operand = cp_unevaluated_operand;
kono
parents:
diff changeset
1739 cp_unevaluated_operand = 0;
kono
parents:
diff changeset
1740 tree vars = tsubst (t, args, complain, in_decl);
kono
parents:
diff changeset
1741 cp_unevaluated_operand = saved_unevaluated_operand;
kono
parents:
diff changeset
1742 if (vars == error_mark_node)
kono
parents:
diff changeset
1743 return error_mark_node;
kono
parents:
diff changeset
1744 return declare_constraint_vars (t, vars);
kono
parents:
diff changeset
1745 }
kono
parents:
diff changeset
1746
kono
parents:
diff changeset
1747 /* Substitute ARGS into the parameterized constraint T. */
kono
parents:
diff changeset
1748
kono
parents:
diff changeset
1749 tree
kono
parents:
diff changeset
1750 tsubst_parameterized_constraint (tree t, tree args,
kono
parents:
diff changeset
1751 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1752 {
kono
parents:
diff changeset
1753 local_specialization_stack stack;
kono
parents:
diff changeset
1754 tree vars = tsubst_constraint_variables (PARM_CONSTR_PARMS (t),
kono
parents:
diff changeset
1755 args, complain, in_decl);
kono
parents:
diff changeset
1756 if (vars == error_mark_node)
kono
parents:
diff changeset
1757 return error_mark_node;
kono
parents:
diff changeset
1758 tree expr = tsubst_constraint (PARM_CONSTR_OPERAND (t), args,
kono
parents:
diff changeset
1759 complain, in_decl);
kono
parents:
diff changeset
1760 if (expr == error_mark_node)
kono
parents:
diff changeset
1761 return error_mark_node;
kono
parents:
diff changeset
1762 return build_nt (PARM_CONSTR, vars, expr);
kono
parents:
diff changeset
1763 }
kono
parents:
diff changeset
1764
kono
parents:
diff changeset
1765 /* Substitute ARGS into the simple requirement T. Note that
kono
parents:
diff changeset
1766 substitution may result in an ill-formed expression without
kono
parents:
diff changeset
1767 causing the program to be ill-formed. In such cases, the
kono
parents:
diff changeset
1768 requirement wraps an error_mark_node. */
kono
parents:
diff changeset
1769
kono
parents:
diff changeset
1770 inline tree
kono
parents:
diff changeset
1771 tsubst_simple_requirement (tree t, tree args,
kono
parents:
diff changeset
1772 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1773 {
kono
parents:
diff changeset
1774 ++processing_template_decl;
kono
parents:
diff changeset
1775 tree expr = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl, false);
kono
parents:
diff changeset
1776 --processing_template_decl;
kono
parents:
diff changeset
1777 return finish_simple_requirement (expr);
kono
parents:
diff changeset
1778 }
kono
parents:
diff changeset
1779
kono
parents:
diff changeset
1780 /* Substitute ARGS into the type requirement T. Note that
kono
parents:
diff changeset
1781 substitution may result in an ill-formed type without
kono
parents:
diff changeset
1782 causing the program to be ill-formed. In such cases, the
kono
parents:
diff changeset
1783 requirement wraps an error_mark_node. */
kono
parents:
diff changeset
1784
kono
parents:
diff changeset
1785 inline tree
kono
parents:
diff changeset
1786 tsubst_type_requirement (tree t, tree args,
kono
parents:
diff changeset
1787 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1788 {
kono
parents:
diff changeset
1789 ++processing_template_decl;
kono
parents:
diff changeset
1790 tree type = tsubst (TREE_OPERAND (t, 0), args, complain, in_decl);
kono
parents:
diff changeset
1791 --processing_template_decl;
kono
parents:
diff changeset
1792 return finish_type_requirement (type);
kono
parents:
diff changeset
1793 }
kono
parents:
diff changeset
1794
kono
parents:
diff changeset
1795 /* Substitute args into the compound requirement T. If substituting
kono
parents:
diff changeset
1796 into either the expression or the type fails, the corresponding
kono
parents:
diff changeset
1797 operands in the resulting node will be error_mark_node. This
kono
parents:
diff changeset
1798 preserves a requirement for the purpose of partial ordering, but
kono
parents:
diff changeset
1799 it will never be satisfied. */
kono
parents:
diff changeset
1800
kono
parents:
diff changeset
1801 tree
kono
parents:
diff changeset
1802 tsubst_compound_requirement (tree t, tree args,
kono
parents:
diff changeset
1803 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1804 {
kono
parents:
diff changeset
1805 ++processing_template_decl;
kono
parents:
diff changeset
1806 tree expr = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl, false);
kono
parents:
diff changeset
1807 tree type = tsubst (TREE_OPERAND (t, 1), args, complain, in_decl);
kono
parents:
diff changeset
1808 --processing_template_decl;
kono
parents:
diff changeset
1809 bool noexcept_p = COMPOUND_REQ_NOEXCEPT_P (t);
kono
parents:
diff changeset
1810 return finish_compound_requirement (expr, type, noexcept_p);
kono
parents:
diff changeset
1811 }
kono
parents:
diff changeset
1812
kono
parents:
diff changeset
1813 /* Substitute ARGS into the nested requirement T. */
kono
parents:
diff changeset
1814
kono
parents:
diff changeset
1815 tree
kono
parents:
diff changeset
1816 tsubst_nested_requirement (tree t, tree args,
kono
parents:
diff changeset
1817 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1818 {
kono
parents:
diff changeset
1819 ++processing_template_decl;
kono
parents:
diff changeset
1820 tree expr = tsubst_expr (TREE_OPERAND (t, 0), args, complain, in_decl, false);
kono
parents:
diff changeset
1821 --processing_template_decl;
kono
parents:
diff changeset
1822 return finish_nested_requirement (expr);
kono
parents:
diff changeset
1823 }
kono
parents:
diff changeset
1824
kono
parents:
diff changeset
1825 /* Substitute ARGS into the requirement T. */
kono
parents:
diff changeset
1826
kono
parents:
diff changeset
1827 inline tree
kono
parents:
diff changeset
1828 tsubst_requirement (tree t, tree args, tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1829 {
kono
parents:
diff changeset
1830 switch (TREE_CODE (t))
kono
parents:
diff changeset
1831 {
kono
parents:
diff changeset
1832 case SIMPLE_REQ:
kono
parents:
diff changeset
1833 return tsubst_simple_requirement (t, args, complain, in_decl);
kono
parents:
diff changeset
1834 case TYPE_REQ:
kono
parents:
diff changeset
1835 return tsubst_type_requirement (t, args, complain, in_decl);
kono
parents:
diff changeset
1836 case COMPOUND_REQ:
kono
parents:
diff changeset
1837 return tsubst_compound_requirement (t, args, complain, in_decl);
kono
parents:
diff changeset
1838 case NESTED_REQ:
kono
parents:
diff changeset
1839 return tsubst_nested_requirement (t, args, complain, in_decl);
kono
parents:
diff changeset
1840 default:
kono
parents:
diff changeset
1841 gcc_unreachable ();
kono
parents:
diff changeset
1842 }
kono
parents:
diff changeset
1843 return error_mark_node;
kono
parents:
diff changeset
1844 }
kono
parents:
diff changeset
1845
kono
parents:
diff changeset
1846 /* Substitute ARGS into the list of requirements T. Note that
kono
parents:
diff changeset
1847 substitution failures here result in ill-formed programs. */
kono
parents:
diff changeset
1848
kono
parents:
diff changeset
1849 tree
kono
parents:
diff changeset
1850 tsubst_requirement_body (tree t, tree args,
kono
parents:
diff changeset
1851 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1852 {
kono
parents:
diff changeset
1853 tree r = NULL_TREE;
kono
parents:
diff changeset
1854 while (t)
kono
parents:
diff changeset
1855 {
kono
parents:
diff changeset
1856 tree e = tsubst_requirement (TREE_VALUE (t), args, complain, in_decl);
kono
parents:
diff changeset
1857 if (e == error_mark_node)
kono
parents:
diff changeset
1858 return error_mark_node;
kono
parents:
diff changeset
1859 r = tree_cons (NULL_TREE, e, r);
kono
parents:
diff changeset
1860 t = TREE_CHAIN (t);
kono
parents:
diff changeset
1861 }
kono
parents:
diff changeset
1862 /* Ensure that the order of constraints is the same as the original. */
kono
parents:
diff changeset
1863 return nreverse (r);
kono
parents:
diff changeset
1864 }
kono
parents:
diff changeset
1865
kono
parents:
diff changeset
1866 } /* namespace */
kono
parents:
diff changeset
1867
kono
parents:
diff changeset
1868 /* Substitute ARGS into the requires expression T. Note that this
kono
parents:
diff changeset
1869 results in the re-declaration of local parameters when
kono
parents:
diff changeset
1870 substituting through the parameter list. If either substitution
kono
parents:
diff changeset
1871 fails, the program is ill-formed. */
kono
parents:
diff changeset
1872
kono
parents:
diff changeset
1873 tree
kono
parents:
diff changeset
1874 tsubst_requires_expr (tree t, tree args,
kono
parents:
diff changeset
1875 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1876 {
kono
parents:
diff changeset
1877 local_specialization_stack stack;
kono
parents:
diff changeset
1878
kono
parents:
diff changeset
1879 tree parms = TREE_OPERAND (t, 0);
kono
parents:
diff changeset
1880 if (parms)
kono
parents:
diff changeset
1881 {
kono
parents:
diff changeset
1882 parms = tsubst_constraint_variables (parms, args, complain, in_decl);
kono
parents:
diff changeset
1883 if (parms == error_mark_node)
kono
parents:
diff changeset
1884 return error_mark_node;
kono
parents:
diff changeset
1885 }
kono
parents:
diff changeset
1886
kono
parents:
diff changeset
1887 tree reqs = TREE_OPERAND (t, 1);
kono
parents:
diff changeset
1888 reqs = tsubst_requirement_body (reqs, args, complain, in_decl);
kono
parents:
diff changeset
1889 if (reqs == error_mark_node)
kono
parents:
diff changeset
1890 return error_mark_node;
kono
parents:
diff changeset
1891
kono
parents:
diff changeset
1892 return finish_requires_expr (parms, reqs);
kono
parents:
diff changeset
1893 }
kono
parents:
diff changeset
1894
kono
parents:
diff changeset
1895 /* Substitute ARGS into the constraint information CI, producing a new
kono
parents:
diff changeset
1896 constraint record. */
kono
parents:
diff changeset
1897
kono
parents:
diff changeset
1898 tree
kono
parents:
diff changeset
1899 tsubst_constraint_info (tree t, tree args,
kono
parents:
diff changeset
1900 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1901 {
kono
parents:
diff changeset
1902 if (!t || t == error_mark_node || !check_constraint_info (t))
kono
parents:
diff changeset
1903 return NULL_TREE;
kono
parents:
diff changeset
1904
kono
parents:
diff changeset
1905 tree tmpl_constr = NULL_TREE;
kono
parents:
diff changeset
1906 if (tree r = CI_TEMPLATE_REQS (t))
kono
parents:
diff changeset
1907 tmpl_constr = tsubst_constraint (r, args, complain, in_decl);
kono
parents:
diff changeset
1908
kono
parents:
diff changeset
1909 tree decl_constr = NULL_TREE;
kono
parents:
diff changeset
1910 if (tree r = CI_DECLARATOR_REQS (t))
kono
parents:
diff changeset
1911 decl_constr = tsubst_constraint (r, args, complain, in_decl);
kono
parents:
diff changeset
1912
kono
parents:
diff changeset
1913 return build_constraints (tmpl_constr, decl_constr);
kono
parents:
diff changeset
1914 }
kono
parents:
diff changeset
1915
kono
parents:
diff changeset
1916 /* Substitute ARGS into the constraint T. */
kono
parents:
diff changeset
1917
kono
parents:
diff changeset
1918 tree
kono
parents:
diff changeset
1919 tsubst_constraint (tree t, tree args, tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1920 {
kono
parents:
diff changeset
1921 if (t == NULL_TREE)
kono
parents:
diff changeset
1922 return t;
kono
parents:
diff changeset
1923 switch (TREE_CODE (t))
kono
parents:
diff changeset
1924 {
kono
parents:
diff changeset
1925 case PRED_CONSTR:
kono
parents:
diff changeset
1926 return tsubst_predicate_constraint (t, args, complain, in_decl);
kono
parents:
diff changeset
1927 case CHECK_CONSTR:
kono
parents:
diff changeset
1928 return tsubst_check_constraint (t, args, complain, in_decl);
kono
parents:
diff changeset
1929 case CONJ_CONSTR:
kono
parents:
diff changeset
1930 case DISJ_CONSTR:
kono
parents:
diff changeset
1931 return tsubst_logical_operator (t, args, complain, in_decl);
kono
parents:
diff changeset
1932 case PARM_CONSTR:
kono
parents:
diff changeset
1933 return tsubst_parameterized_constraint (t, args, complain, in_decl);
kono
parents:
diff changeset
1934 case EXPR_CONSTR:
kono
parents:
diff changeset
1935 return tsubst_expr_constr (t, args, complain, in_decl);
kono
parents:
diff changeset
1936 case TYPE_CONSTR:
kono
parents:
diff changeset
1937 return tsubst_type_constr (t, args, complain, in_decl);
kono
parents:
diff changeset
1938 case ICONV_CONSTR:
kono
parents:
diff changeset
1939 return tsubst_implicit_conversion_constr (t, args, complain, in_decl);
kono
parents:
diff changeset
1940 case DEDUCT_CONSTR:
kono
parents:
diff changeset
1941 return tsubst_argument_deduction_constr (t, args, complain, in_decl);
kono
parents:
diff changeset
1942 case EXCEPT_CONSTR:
kono
parents:
diff changeset
1943 return tsubst_exception_constr (t, args, complain, in_decl);
kono
parents:
diff changeset
1944 default:
kono
parents:
diff changeset
1945 gcc_unreachable ();
kono
parents:
diff changeset
1946 }
kono
parents:
diff changeset
1947 return error_mark_node;
kono
parents:
diff changeset
1948 }
kono
parents:
diff changeset
1949
kono
parents:
diff changeset
1950 /*---------------------------------------------------------------------------
kono
parents:
diff changeset
1951 Constraint satisfaction
kono
parents:
diff changeset
1952 ---------------------------------------------------------------------------*/
kono
parents:
diff changeset
1953
kono
parents:
diff changeset
1954 /* The following functions determine if a constraint, when
kono
parents:
diff changeset
1955 substituting template arguments, is satisfied. For convenience,
kono
parents:
diff changeset
1956 satisfaction reduces a constraint to either true or false (and
kono
parents:
diff changeset
1957 nothing else). */
kono
parents:
diff changeset
1958
kono
parents:
diff changeset
1959 namespace {
kono
parents:
diff changeset
1960
kono
parents:
diff changeset
1961 tree satisfy_constraint_1 (tree, tree, tsubst_flags_t, tree);
kono
parents:
diff changeset
1962
kono
parents:
diff changeset
1963 /* Check the constraint pack expansion. */
kono
parents:
diff changeset
1964
kono
parents:
diff changeset
1965 tree
kono
parents:
diff changeset
1966 satisfy_pack_expansion (tree t, tree args,
kono
parents:
diff changeset
1967 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1968 {
kono
parents:
diff changeset
1969 /* Get the vector of satisfaction results.
kono
parents:
diff changeset
1970 gen_elem_of_pack_expansion_instantiation will check that each element of
kono
parents:
diff changeset
1971 the expansion is satisfied. */
kono
parents:
diff changeset
1972 tree exprs = tsubst_pack_expansion (t, args, complain, in_decl);
kono
parents:
diff changeset
1973
kono
parents:
diff changeset
1974 if (exprs == error_mark_node)
kono
parents:
diff changeset
1975 return boolean_false_node;
kono
parents:
diff changeset
1976
kono
parents:
diff changeset
1977 /* TODO: It might be better to normalize each expanded term
kono
parents:
diff changeset
1978 and evaluate them separately. That would provide better
kono
parents:
diff changeset
1979 opportunities for diagnostics. */
kono
parents:
diff changeset
1980 for (int i = 0; i < TREE_VEC_LENGTH (exprs); ++i)
kono
parents:
diff changeset
1981 if (TREE_VEC_ELT (exprs, i) != boolean_true_node)
kono
parents:
diff changeset
1982 return boolean_false_node;
kono
parents:
diff changeset
1983 return boolean_true_node;
kono
parents:
diff changeset
1984 }
kono
parents:
diff changeset
1985
kono
parents:
diff changeset
1986 /* A predicate constraint is satisfied if its expression evaluates
kono
parents:
diff changeset
1987 to true. If substitution into that node fails, the constraint
kono
parents:
diff changeset
1988 is not satisfied ([temp.constr.pred]).
kono
parents:
diff changeset
1989
kono
parents:
diff changeset
1990 Note that a predicate constraint is a constraint expression
kono
parents:
diff changeset
1991 of type bool. If neither of those are true, the program is
kono
parents:
diff changeset
1992 ill-formed; they are not SFINAE'able errors. */
kono
parents:
diff changeset
1993
kono
parents:
diff changeset
1994 tree
kono
parents:
diff changeset
1995 satisfy_predicate_constraint (tree t, tree args,
kono
parents:
diff changeset
1996 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
1997 {
kono
parents:
diff changeset
1998 tree expr = TREE_OPERAND (t, 0);
kono
parents:
diff changeset
1999
kono
parents:
diff changeset
2000 /* We should never have a naked pack expansion in a predicate constraint. */
kono
parents:
diff changeset
2001 gcc_assert (TREE_CODE (expr) != EXPR_PACK_EXPANSION);
kono
parents:
diff changeset
2002
kono
parents:
diff changeset
2003 /* If substitution into the expression fails, the constraint
kono
parents:
diff changeset
2004 is not satisfied. */
kono
parents:
diff changeset
2005 expr = tsubst_expr (expr, args, complain, in_decl, false);
kono
parents:
diff changeset
2006 if (expr == error_mark_node)
kono
parents:
diff changeset
2007 return boolean_false_node;
kono
parents:
diff changeset
2008
kono
parents:
diff changeset
2009 /* A predicate constraint shall have type bool. In some
kono
parents:
diff changeset
2010 cases, substitution gives us const-qualified bool, which
kono
parents:
diff changeset
2011 is also acceptable. */
kono
parents:
diff changeset
2012 tree type = cv_unqualified (TREE_TYPE (expr));
kono
parents:
diff changeset
2013 if (!same_type_p (type, boolean_type_node))
kono
parents:
diff changeset
2014 {
kono
parents:
diff changeset
2015 error_at (EXPR_LOC_OR_LOC (expr, input_location),
kono
parents:
diff changeset
2016 "constraint %qE does not have type %qT",
kono
parents:
diff changeset
2017 expr, boolean_type_node);
kono
parents:
diff changeset
2018 return boolean_false_node;
kono
parents:
diff changeset
2019 }
kono
parents:
diff changeset
2020
kono
parents:
diff changeset
2021 return cxx_constant_value (expr);
kono
parents:
diff changeset
2022 }
kono
parents:
diff changeset
2023
kono
parents:
diff changeset
2024 /* A concept check constraint like C<CARGS> is satisfied if substituting ARGS
kono
parents:
diff changeset
2025 into CARGS succeeds and C is satisfied for the resulting arguments. */
kono
parents:
diff changeset
2026
kono
parents:
diff changeset
2027 tree
kono
parents:
diff changeset
2028 satisfy_check_constraint (tree t, tree args,
kono
parents:
diff changeset
2029 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
2030 {
kono
parents:
diff changeset
2031 tree decl = CHECK_CONSTR_CONCEPT (t);
kono
parents:
diff changeset
2032 tree tmpl = DECL_TI_TEMPLATE (decl);
kono
parents:
diff changeset
2033 tree cargs = CHECK_CONSTR_ARGS (t);
kono
parents:
diff changeset
2034
kono
parents:
diff changeset
2035 /* Instantiate the concept check arguments. */
kono
parents:
diff changeset
2036 tree targs = tsubst (cargs, args, tf_none, NULL_TREE);
kono
parents:
diff changeset
2037 if (targs == error_mark_node)
kono
parents:
diff changeset
2038 return boolean_false_node;
kono
parents:
diff changeset
2039
kono
parents:
diff changeset
2040 /* Search for a previous value. */
kono
parents:
diff changeset
2041 if (tree prev = lookup_concept_satisfaction (tmpl, targs))
kono
parents:
diff changeset
2042 return prev;
kono
parents:
diff changeset
2043
kono
parents:
diff changeset
2044 /* Expand the concept; failure here implies non-satisfaction. */
kono
parents:
diff changeset
2045 tree def = expand_concept (decl, targs);
kono
parents:
diff changeset
2046 if (def == error_mark_node)
kono
parents:
diff changeset
2047 return memoize_concept_satisfaction (tmpl, args, boolean_false_node);
kono
parents:
diff changeset
2048
kono
parents:
diff changeset
2049 /* Recursively satisfy the constraint. */
kono
parents:
diff changeset
2050 tree result = satisfy_constraint_1 (def, targs, complain, in_decl);
kono
parents:
diff changeset
2051 return memoize_concept_satisfaction (tmpl, targs, result);
kono
parents:
diff changeset
2052 }
kono
parents:
diff changeset
2053
kono
parents:
diff changeset
2054 /* Check an expression constraint. The constraint is satisfied if
kono
parents:
diff changeset
2055 substitution succeeds ([temp.constr.expr]).
kono
parents:
diff changeset
2056
kono
parents:
diff changeset
2057 Note that the expression is unevaluated. */
kono
parents:
diff changeset
2058
kono
parents:
diff changeset
2059 tree
kono
parents:
diff changeset
2060 satisfy_expression_constraint (tree t, tree args,
kono
parents:
diff changeset
2061 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
2062 {
kono
parents:
diff changeset
2063 cp_unevaluated guard;
kono
parents:
diff changeset
2064 deferring_access_check_sentinel deferring;
kono
parents:
diff changeset
2065
kono
parents:
diff changeset
2066 tree expr = EXPR_CONSTR_EXPR (t);
kono
parents:
diff changeset
2067 tree check = tsubst_expr (expr, args, complain, in_decl, false);
kono
parents:
diff changeset
2068 if (check == error_mark_node)
kono
parents:
diff changeset
2069 return boolean_false_node;
kono
parents:
diff changeset
2070 if (!perform_deferred_access_checks (tf_none))
kono
parents:
diff changeset
2071 return boolean_false_node;
kono
parents:
diff changeset
2072 return boolean_true_node;
kono
parents:
diff changeset
2073 }
kono
parents:
diff changeset
2074
kono
parents:
diff changeset
2075 /* Check a type constraint. The constraint is satisfied if
kono
parents:
diff changeset
2076 substitution succeeds. */
kono
parents:
diff changeset
2077
kono
parents:
diff changeset
2078 inline tree
kono
parents:
diff changeset
2079 satisfy_type_constraint (tree t, tree args,
kono
parents:
diff changeset
2080 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
2081 {
kono
parents:
diff changeset
2082 deferring_access_check_sentinel deferring;
kono
parents:
diff changeset
2083 tree type = TYPE_CONSTR_TYPE (t);
kono
parents:
diff changeset
2084 gcc_assert (TYPE_P (type) || type == error_mark_node);
kono
parents:
diff changeset
2085 tree check = tsubst (type, args, complain, in_decl);
kono
parents:
diff changeset
2086 if (error_operand_p (check))
kono
parents:
diff changeset
2087 return boolean_false_node;
kono
parents:
diff changeset
2088 if (!perform_deferred_access_checks (complain))
kono
parents:
diff changeset
2089 return boolean_false_node;
kono
parents:
diff changeset
2090 return boolean_true_node;
kono
parents:
diff changeset
2091 }
kono
parents:
diff changeset
2092
kono
parents:
diff changeset
2093 /* Check an implicit conversion constraint. */
kono
parents:
diff changeset
2094
kono
parents:
diff changeset
2095 tree
kono
parents:
diff changeset
2096 satisfy_implicit_conversion_constraint (tree t, tree args,
kono
parents:
diff changeset
2097 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
2098 {
kono
parents:
diff changeset
2099 /* Don't tsubst as if we're processing a template. If we try
kono
parents:
diff changeset
2100 to we can end up generating template-like expressions
kono
parents:
diff changeset
2101 (e.g., modop-exprs) that aren't properly typed. */
kono
parents:
diff changeset
2102 tree expr =
kono
parents:
diff changeset
2103 tsubst_expr (ICONV_CONSTR_EXPR (t), args, complain, in_decl, false);
kono
parents:
diff changeset
2104 if (expr == error_mark_node)
kono
parents:
diff changeset
2105 return boolean_false_node;
kono
parents:
diff changeset
2106
kono
parents:
diff changeset
2107 /* Get the transformed target type. */
kono
parents:
diff changeset
2108 tree type = tsubst (ICONV_CONSTR_TYPE (t), args, complain, in_decl);
kono
parents:
diff changeset
2109 if (type == error_mark_node)
kono
parents:
diff changeset
2110 return boolean_false_node;
kono
parents:
diff changeset
2111
kono
parents:
diff changeset
2112 /* Attempt the conversion as a direct initialization
kono
parents:
diff changeset
2113 of the form TYPE <unspecified> = EXPR. */
kono
parents:
diff changeset
2114 tree conv =
kono
parents:
diff changeset
2115 perform_direct_initialization_if_possible (type, expr, false, complain);
kono
parents:
diff changeset
2116 if (conv == NULL_TREE || conv == error_mark_node)
kono
parents:
diff changeset
2117 return boolean_false_node;
kono
parents:
diff changeset
2118 else
kono
parents:
diff changeset
2119 return boolean_true_node;
kono
parents:
diff changeset
2120 }
kono
parents:
diff changeset
2121
kono
parents:
diff changeset
2122 /* Check an argument deduction constraint. */
kono
parents:
diff changeset
2123
kono
parents:
diff changeset
2124 tree
kono
parents:
diff changeset
2125 satisfy_argument_deduction_constraint (tree t, tree args,
kono
parents:
diff changeset
2126 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
2127 {
kono
parents:
diff changeset
2128 /* Substitute through the expression. */
kono
parents:
diff changeset
2129 tree expr = DEDUCT_CONSTR_EXPR (t);
kono
parents:
diff changeset
2130 tree init = tsubst_expr (expr, args, complain, in_decl, false);
kono
parents:
diff changeset
2131 if (expr == error_mark_node)
kono
parents:
diff changeset
2132 return boolean_false_node;
kono
parents:
diff changeset
2133
kono
parents:
diff changeset
2134 /* Perform auto or decltype(auto) deduction to get the result. */
kono
parents:
diff changeset
2135 tree pattern = DEDUCT_CONSTR_PATTERN (t);
kono
parents:
diff changeset
2136 tree placeholder = DEDUCT_CONSTR_PLACEHOLDER (t);
kono
parents:
diff changeset
2137 tree constr = PLACEHOLDER_TYPE_CONSTRAINTS (placeholder);
kono
parents:
diff changeset
2138 tree type_canonical = TYPE_CANONICAL (placeholder);
kono
parents:
diff changeset
2139 PLACEHOLDER_TYPE_CONSTRAINTS (placeholder)
kono
parents:
diff changeset
2140 = tsubst_constraint (constr, args, complain|tf_partial, in_decl);
kono
parents:
diff changeset
2141 TYPE_CANONICAL (placeholder) = NULL_TREE;
kono
parents:
diff changeset
2142 tree type = do_auto_deduction (pattern, init, placeholder,
kono
parents:
diff changeset
2143 complain, adc_requirement);
kono
parents:
diff changeset
2144 PLACEHOLDER_TYPE_CONSTRAINTS (placeholder) = constr;
kono
parents:
diff changeset
2145 TYPE_CANONICAL (placeholder) = type_canonical;
kono
parents:
diff changeset
2146 if (type == error_mark_node)
kono
parents:
diff changeset
2147 return boolean_false_node;
kono
parents:
diff changeset
2148
kono
parents:
diff changeset
2149 return boolean_true_node;
kono
parents:
diff changeset
2150 }
kono
parents:
diff changeset
2151
kono
parents:
diff changeset
2152 /* Check an exception constraint. An exception constraint for an
kono
parents:
diff changeset
2153 expression e is satisfied when noexcept(e) is true. */
kono
parents:
diff changeset
2154
kono
parents:
diff changeset
2155 tree
kono
parents:
diff changeset
2156 satisfy_exception_constraint (tree t, tree args,
kono
parents:
diff changeset
2157 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
2158 {
kono
parents:
diff changeset
2159 tree expr = EXCEPT_CONSTR_EXPR (t);
kono
parents:
diff changeset
2160 tree check = tsubst_expr (expr, args, complain, in_decl, false);
kono
parents:
diff changeset
2161 if (check == error_mark_node)
kono
parents:
diff changeset
2162 return boolean_false_node;
kono
parents:
diff changeset
2163
kono
parents:
diff changeset
2164 if (expr_noexcept_p (check, complain))
kono
parents:
diff changeset
2165 return boolean_true_node;
kono
parents:
diff changeset
2166 else
kono
parents:
diff changeset
2167 return boolean_false_node;
kono
parents:
diff changeset
2168 }
kono
parents:
diff changeset
2169
kono
parents:
diff changeset
2170 /* Check a parameterized constraint. */
kono
parents:
diff changeset
2171
kono
parents:
diff changeset
2172 tree
kono
parents:
diff changeset
2173 satisfy_parameterized_constraint (tree t, tree args,
kono
parents:
diff changeset
2174 tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
2175 {
kono
parents:
diff changeset
2176 local_specialization_stack stack;
kono
parents:
diff changeset
2177 tree parms = PARM_CONSTR_PARMS (t);
kono
parents:
diff changeset
2178 tree vars = tsubst_constraint_variables (parms, args, complain, in_decl);
kono
parents:
diff changeset
2179 if (vars == error_mark_node)
kono
parents:
diff changeset
2180 return boolean_false_node;
kono
parents:
diff changeset
2181 tree constr = PARM_CONSTR_OPERAND (t);
kono
parents:
diff changeset
2182 return satisfy_constraint_1 (constr, args, complain, in_decl);
kono
parents:
diff changeset
2183 }
kono
parents:
diff changeset
2184
kono
parents:
diff changeset
2185 /* Check that the conjunction of constraints is satisfied. Note
kono
parents:
diff changeset
2186 that if left operand is not satisfied, the right operand
kono
parents:
diff changeset
2187 is not checked.
kono
parents:
diff changeset
2188
kono
parents:
diff changeset
2189 FIXME: Check that this wouldn't result in a user-defined
kono
parents:
diff changeset
2190 operator. Note that this error is partially diagnosed in
kono
parents:
diff changeset
2191 satisfy_predicate_constraint. It would be nice to diagnose
kono
parents:
diff changeset
2192 the overload, but I don't think it's strictly necessary. */
kono
parents:
diff changeset
2193
kono
parents:
diff changeset
2194 tree
kono
parents:
diff changeset
2195 satisfy_conjunction (tree t, tree args, tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
2196 {
kono
parents:
diff changeset
2197 tree t0 = satisfy_constraint_1 (TREE_OPERAND (t, 0), args, complain, in_decl);
kono
parents:
diff changeset
2198 if (t0 == boolean_false_node)
kono
parents:
diff changeset
2199 return boolean_false_node;
kono
parents:
diff changeset
2200 return satisfy_constraint_1 (TREE_OPERAND (t, 1), args, complain, in_decl);
kono
parents:
diff changeset
2201 }
kono
parents:
diff changeset
2202
kono
parents:
diff changeset
2203 /* Check that the disjunction of constraints is satisfied. Note
kono
parents:
diff changeset
2204 that if the left operand is satisfied, the right operand is not
kono
parents:
diff changeset
2205 checked. */
kono
parents:
diff changeset
2206
kono
parents:
diff changeset
2207 tree
kono
parents:
diff changeset
2208 satisfy_disjunction (tree t, tree args, tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
2209 {
kono
parents:
diff changeset
2210 tree t0 = satisfy_constraint_1 (TREE_OPERAND (t, 0), args, complain, in_decl);
kono
parents:
diff changeset
2211 if (t0 == boolean_true_node)
kono
parents:
diff changeset
2212 return boolean_true_node;
kono
parents:
diff changeset
2213 return satisfy_constraint_1 (TREE_OPERAND (t, 1), args, complain, in_decl);
kono
parents:
diff changeset
2214 }
kono
parents:
diff changeset
2215
kono
parents:
diff changeset
2216 /* Dispatch to an appropriate satisfaction routine depending on the
kono
parents:
diff changeset
2217 tree code of T. */
kono
parents:
diff changeset
2218
kono
parents:
diff changeset
2219 tree
kono
parents:
diff changeset
2220 satisfy_constraint_1 (tree t, tree args, tsubst_flags_t complain, tree in_decl)
kono
parents:
diff changeset
2221 {
kono
parents:
diff changeset
2222 gcc_assert (!processing_template_decl);
kono
parents:
diff changeset
2223
kono
parents:
diff changeset
2224 if (!t)
kono
parents:
diff changeset
2225 return boolean_false_node;
kono
parents:
diff changeset
2226
kono
parents:
diff changeset
2227 if (t == error_mark_node)
kono
parents:
diff changeset
2228 return boolean_false_node;
kono
parents:
diff changeset
2229
kono
parents:
diff changeset
2230 switch (TREE_CODE (t))
kono
parents:
diff changeset
2231 {
kono
parents:
diff changeset
2232 case PRED_CONSTR:
kono
parents:
diff changeset
2233 return satisfy_predicate_constraint (t, args, complain, in_decl);
kono
parents:
diff changeset
2234
kono
parents:
diff changeset
2235 case CHECK_CONSTR:
kono
parents:
diff changeset
2236 return satisfy_check_constraint (t, args, complain, in_decl);
kono
parents:
diff changeset
2237
kono
parents:
diff changeset
2238 case EXPR_CONSTR:
kono
parents:
diff changeset
2239 return satisfy_expression_constraint (t, args, complain, in_decl);
kono
parents:
diff changeset
2240
kono
parents:
diff changeset
2241 case TYPE_CONSTR:
kono
parents:
diff changeset
2242 return satisfy_type_constraint (t, args, complain, in_decl);
kono
parents:
diff changeset
2243
kono
parents:
diff changeset
2244 case ICONV_CONSTR:
kono
parents:
diff changeset
2245 return satisfy_implicit_conversion_constraint (t, args, complain, in_decl);
kono
parents:
diff changeset
2246
kono
parents:
diff changeset
2247 case DEDUCT_CONSTR:
kono
parents:
diff changeset
2248 return satisfy_argument_deduction_constraint (t, args, complain, in_decl);
kono
parents:
diff changeset
2249
kono
parents:
diff changeset
2250 case EXCEPT_CONSTR:
kono
parents:
diff changeset
2251 return satisfy_exception_constraint (t, args, complain, in_decl);
kono
parents:
diff changeset
2252
kono
parents:
diff changeset
2253 case PARM_CONSTR:
kono
parents:
diff changeset
2254 return satisfy_parameterized_constraint (t, args, complain, in_decl);
kono
parents:
diff changeset
2255
kono
parents:
diff changeset
2256 case CONJ_CONSTR:
kono
parents:
diff changeset
2257 return satisfy_conjunction (t, args, complain, in_decl);
kono
parents:
diff changeset
2258
kono
parents:
diff changeset
2259 case DISJ_CONSTR:
kono
parents:
diff changeset
2260 return satisfy_disjunction (t, args, complain, in_decl);
kono
parents:
diff changeset
2261
kono
parents:
diff changeset
2262 case EXPR_PACK_EXPANSION:
kono
parents:
diff changeset
2263 return satisfy_pack_expansion (t, args, complain, in_decl);
kono
parents:
diff changeset
2264
kono
parents:
diff changeset
2265 default:
kono
parents:
diff changeset
2266 gcc_unreachable ();
kono
parents:
diff changeset
2267 }
kono
parents:
diff changeset
2268 return boolean_false_node;
kono
parents:
diff changeset
2269 }
kono
parents:
diff changeset
2270
kono
parents:
diff changeset
2271 /* Check that the constraint is satisfied, according to the rules
kono
parents:
diff changeset
2272 for that constraint. Note that each satisfy_* function returns
kono
parents:
diff changeset
2273 true or false, depending on whether it is satisfied or not. */
kono
parents:
diff changeset
2274
kono
parents:
diff changeset
2275 tree
kono
parents:
diff changeset
2276 satisfy_constraint (tree t, tree args)
kono
parents:
diff changeset
2277 {
kono
parents:
diff changeset
2278 auto_timevar time (TV_CONSTRAINT_SAT);
kono
parents:
diff changeset
2279
kono
parents:
diff changeset
2280 /* Turn off template processing. Constraint satisfaction only applies
kono
parents:
diff changeset
2281 to non-dependent terms, so we want to ensure full checking here. */
kono
parents:
diff changeset
2282 processing_template_decl_sentinel proc (true);
kono
parents:
diff changeset
2283
kono
parents:
diff changeset
2284 /* Avoid early exit in tsubst and tsubst_copy from null args; since earlier
kono
parents:
diff changeset
2285 substitution was done with processing_template_decl forced on, there will
kono
parents:
diff changeset
2286 be expressions that still need semantic processing, possibly buried in
kono
parents:
diff changeset
2287 decltype or a template argument. */
kono
parents:
diff changeset
2288 if (args == NULL_TREE)
kono
parents:
diff changeset
2289 args = make_tree_vec (1);
kono
parents:
diff changeset
2290
kono
parents:
diff changeset
2291 return satisfy_constraint_1 (t, args, tf_none, NULL_TREE);
kono
parents:
diff changeset
2292 }
kono
parents:
diff changeset
2293
kono
parents:
diff changeset
2294 /* Check the associated constraints in CI against the given
kono
parents:
diff changeset
2295 ARGS, returning true when the constraints are satisfied
kono
parents:
diff changeset
2296 and false otherwise. */
kono
parents:
diff changeset
2297
kono
parents:
diff changeset
2298 tree
kono
parents:
diff changeset
2299 satisfy_associated_constraints (tree ci, tree args)
kono
parents:
diff changeset
2300 {
kono
parents:
diff changeset
2301 /* If there are no constraints then this is trivially satisfied. */
kono
parents:
diff changeset
2302 if (!ci)
kono
parents:
diff changeset
2303 return boolean_true_node;
kono
parents:
diff changeset
2304
kono
parents:
diff changeset
2305 /* If any arguments depend on template parameters, we can't
kono
parents:
diff changeset
2306 check constraints. */
kono
parents:
diff changeset
2307 if (args && uses_template_parms (args))
kono
parents:
diff changeset
2308 return boolean_true_node;
kono
parents:
diff changeset
2309
kono
parents:
diff changeset
2310 /* Check if we've seen a previous result. */
kono
parents:
diff changeset
2311 if (tree prev = lookup_constraint_satisfaction (ci, args))
kono
parents:
diff changeset
2312 return prev;
kono
parents:
diff changeset
2313
kono
parents:
diff changeset
2314 /* Actually test for satisfaction. */
kono
parents:
diff changeset
2315 tree result = satisfy_constraint (CI_ASSOCIATED_CONSTRAINTS (ci), args);
kono
parents:
diff changeset
2316 return memoize_constraint_satisfaction (ci, args, result);
kono
parents:
diff changeset
2317 }
kono
parents:
diff changeset
2318
kono
parents:
diff changeset
2319 } /* namespace */
kono
parents:
diff changeset
2320
kono
parents:
diff changeset
2321 /* Evaluate the given constraint, returning boolean_true_node
kono
parents:
diff changeset
2322 if the constraint is satisfied and boolean_false_node
kono
parents:
diff changeset
2323 otherwise. */
kono
parents:
diff changeset
2324
kono
parents:
diff changeset
2325 tree
kono
parents:
diff changeset
2326 evaluate_constraints (tree constr, tree args)
kono
parents:
diff changeset
2327 {
kono
parents:
diff changeset
2328 gcc_assert (constraint_p (constr));
kono
parents:
diff changeset
2329 return satisfy_constraint (constr, args);
kono
parents:
diff changeset
2330 }
kono
parents:
diff changeset
2331
kono
parents:
diff changeset
2332 /* Evaluate the function concept FN by substituting its own args
kono
parents:
diff changeset
2333 into its definition and evaluating that as the result. Returns
kono
parents:
diff changeset
2334 boolean_true_node if the constraints are satisfied and
kono
parents:
diff changeset
2335 boolean_false_node otherwise. */
kono
parents:
diff changeset
2336
kono
parents:
diff changeset
2337 tree
kono
parents:
diff changeset
2338 evaluate_function_concept (tree fn, tree args)
kono
parents:
diff changeset
2339 {
kono
parents:
diff changeset
2340 tree constr = build_nt (CHECK_CONSTR, fn, args);
kono
parents:
diff changeset
2341 return satisfy_constraint (constr, args);
kono
parents:
diff changeset
2342 }
kono
parents:
diff changeset
2343
kono
parents:
diff changeset
2344 /* Evaluate the variable concept VAR by substituting its own args into
kono
parents:
diff changeset
2345 its initializer and checking the resulting constraint. Returns
kono
parents:
diff changeset
2346 boolean_true_node if the constraints are satisfied and
kono
parents:
diff changeset
2347 boolean_false_node otherwise. */
kono
parents:
diff changeset
2348
kono
parents:
diff changeset
2349 tree
kono
parents:
diff changeset
2350 evaluate_variable_concept (tree var, tree args)
kono
parents:
diff changeset
2351 {
kono
parents:
diff changeset
2352 tree constr = build_nt (CHECK_CONSTR, var, args);
kono
parents:
diff changeset
2353 return satisfy_constraint (constr, args);
kono
parents:
diff changeset
2354 }
kono
parents:
diff changeset
2355
kono
parents:
diff changeset
2356 /* Evaluate the given expression as if it were a predicate
kono
parents:
diff changeset
2357 constraint. Returns boolean_true_node if the constraint
kono
parents:
diff changeset
2358 is satisfied and boolean_false_node otherwise. */
kono
parents:
diff changeset
2359
kono
parents:
diff changeset
2360 tree
kono
parents:
diff changeset
2361 evaluate_constraint_expression (tree expr, tree args)
kono
parents:
diff changeset
2362 {
kono
parents:
diff changeset
2363 tree constr = normalize_expression (expr);
kono
parents:
diff changeset
2364 return satisfy_constraint (constr, args);
kono
parents:
diff changeset
2365 }
kono
parents:
diff changeset
2366
kono
parents:
diff changeset
2367 /* Returns true if the DECL's constraints are satisfied.
kono
parents:
diff changeset
2368 This is used in cases where a declaration is formed but
kono
parents:
diff changeset
2369 before it is used (e.g., overload resolution). */
kono
parents:
diff changeset
2370
kono
parents:
diff changeset
2371 bool
kono
parents:
diff changeset
2372 constraints_satisfied_p (tree decl)
kono
parents:
diff changeset
2373 {
kono
parents:
diff changeset
2374 /* Get the constraints to check for satisfaction. This depends
kono
parents:
diff changeset
2375 on whether we're looking at a template specialization or not. */
kono
parents:
diff changeset
2376 tree ci;
kono
parents:
diff changeset
2377 tree args = NULL_TREE;
kono
parents:
diff changeset
2378 if (tree ti = DECL_TEMPLATE_INFO (decl))
kono
parents:
diff changeset
2379 {
kono
parents:
diff changeset
2380 tree tmpl = TI_TEMPLATE (ti);
kono
parents:
diff changeset
2381 ci = get_constraints (tmpl);
kono
parents:
diff changeset
2382 int depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
kono
parents:
diff changeset
2383 args = get_innermost_template_args (TI_ARGS (ti), depth);
kono
parents:
diff changeset
2384 }
kono
parents:
diff changeset
2385 else
kono
parents:
diff changeset
2386 {
kono
parents:
diff changeset
2387 ci = get_constraints (decl);
kono
parents:
diff changeset
2388 }
kono
parents:
diff changeset
2389
kono
parents:
diff changeset
2390 tree eval = satisfy_associated_constraints (ci, args);
kono
parents:
diff changeset
2391 return eval == boolean_true_node;
kono
parents:
diff changeset
2392 }
kono
parents:
diff changeset
2393
kono
parents:
diff changeset
2394 /* Returns true if the constraints are satisfied by ARGS.
kono
parents:
diff changeset
2395 Here, T can be either a constraint or a constrained
kono
parents:
diff changeset
2396 declaration. */
kono
parents:
diff changeset
2397
kono
parents:
diff changeset
2398 bool
kono
parents:
diff changeset
2399 constraints_satisfied_p (tree t, tree args)
kono
parents:
diff changeset
2400 {
kono
parents:
diff changeset
2401 tree eval;
kono
parents:
diff changeset
2402 if (constraint_p (t))
kono
parents:
diff changeset
2403 eval = evaluate_constraints (t, args);
kono
parents:
diff changeset
2404 else
kono
parents:
diff changeset
2405 eval = satisfy_associated_constraints (get_constraints (t), args);
kono
parents:
diff changeset
2406 return eval == boolean_true_node;
kono
parents:
diff changeset
2407 }
kono
parents:
diff changeset
2408
kono
parents:
diff changeset
2409 namespace
kono
parents:
diff changeset
2410 {
kono
parents:
diff changeset
2411
kono
parents:
diff changeset
2412 /* Normalize EXPR and determine if the resulting constraint is
kono
parents:
diff changeset
2413 satisfied by ARGS. Returns true if and only if the constraint
kono
parents:
diff changeset
2414 is satisfied. This is used extensively by diagnostics to
kono
parents:
diff changeset
2415 determine causes for failure. */
kono
parents:
diff changeset
2416
kono
parents:
diff changeset
2417 inline bool
kono
parents:
diff changeset
2418 constraint_expression_satisfied_p (tree expr, tree args)
kono
parents:
diff changeset
2419 {
kono
parents:
diff changeset
2420 return evaluate_constraint_expression (expr, args) == boolean_true_node;
kono
parents:
diff changeset
2421 }
kono
parents:
diff changeset
2422
kono
parents:
diff changeset
2423 } /* namespace */
kono
parents:
diff changeset
2424
kono
parents:
diff changeset
2425 /*---------------------------------------------------------------------------
kono
parents:
diff changeset
2426 Semantic analysis of requires-expressions
kono
parents:
diff changeset
2427 ---------------------------------------------------------------------------*/
kono
parents:
diff changeset
2428
kono
parents:
diff changeset
2429 /* Finish a requires expression for the given PARMS (possibly
kono
parents:
diff changeset
2430 null) and the non-empty sequence of requirements. */
kono
parents:
diff changeset
2431 tree
kono
parents:
diff changeset
2432 finish_requires_expr (tree parms, tree reqs)
kono
parents:
diff changeset
2433 {
kono
parents:
diff changeset
2434 /* Modify the declared parameters by removing their context
kono
parents:
diff changeset
2435 so they don't refer to the enclosing scope and explicitly
kono
parents:
diff changeset
2436 indicating that they are constraint variables. */
kono
parents:
diff changeset
2437 for (tree parm = parms; parm; parm = DECL_CHAIN (parm))
kono
parents:
diff changeset
2438 {
kono
parents:
diff changeset
2439 DECL_CONTEXT (parm) = NULL_TREE;
kono
parents:
diff changeset
2440 CONSTRAINT_VAR_P (parm) = true;
kono
parents:
diff changeset
2441 }
kono
parents:
diff changeset
2442
kono
parents:
diff changeset
2443 /* Build the node. */
kono
parents:
diff changeset
2444 tree r = build_min (REQUIRES_EXPR, boolean_type_node, parms, reqs);
kono
parents:
diff changeset
2445 TREE_SIDE_EFFECTS (r) = false;
kono
parents:
diff changeset
2446 TREE_CONSTANT (r) = true;
kono
parents:
diff changeset
2447 return r;
kono
parents:
diff changeset
2448 }
kono
parents:
diff changeset
2449
kono
parents:
diff changeset
2450 /* Construct a requirement for the validity of EXPR. */
kono
parents:
diff changeset
2451 tree
kono
parents:
diff changeset
2452 finish_simple_requirement (tree expr)
kono
parents:
diff changeset
2453 {
kono
parents:
diff changeset
2454 return build_nt (SIMPLE_REQ, expr);
kono
parents:
diff changeset
2455 }
kono
parents:
diff changeset
2456
kono
parents:
diff changeset
2457 /* Construct a requirement for the validity of TYPE. */
kono
parents:
diff changeset
2458 tree
kono
parents:
diff changeset
2459 finish_type_requirement (tree type)
kono
parents:
diff changeset
2460 {
kono
parents:
diff changeset
2461 return build_nt (TYPE_REQ, type);
kono
parents:
diff changeset
2462 }
kono
parents:
diff changeset
2463
kono
parents:
diff changeset
2464 /* Construct a requirement for the validity of EXPR, along with
kono
parents:
diff changeset
2465 its properties. if TYPE is non-null, then it specifies either
kono
parents:
diff changeset
2466 an implicit conversion or argument deduction constraint,
kono
parents:
diff changeset
2467 depending on whether any placeholders occur in the type name.
kono
parents:
diff changeset
2468 NOEXCEPT_P is true iff the noexcept keyword was specified. */
kono
parents:
diff changeset
2469 tree
kono
parents:
diff changeset
2470 finish_compound_requirement (tree expr, tree type, bool noexcept_p)
kono
parents:
diff changeset
2471 {
kono
parents:
diff changeset
2472 tree req = build_nt (COMPOUND_REQ, expr, type);
kono
parents:
diff changeset
2473 COMPOUND_REQ_NOEXCEPT_P (req) = noexcept_p;
kono
parents:
diff changeset
2474 return req;
kono
parents:
diff changeset
2475 }
kono
parents:
diff changeset
2476
kono
parents:
diff changeset
2477 /* Finish a nested requirement. */
kono
parents:
diff changeset
2478 tree
kono
parents:
diff changeset
2479 finish_nested_requirement (tree expr)
kono
parents:
diff changeset
2480 {
kono
parents:
diff changeset
2481 return build_nt (NESTED_REQ, expr);
kono
parents:
diff changeset
2482 }
kono
parents:
diff changeset
2483
kono
parents:
diff changeset
2484 // Check that FN satisfies the structural requirements of a
kono
parents:
diff changeset
2485 // function concept definition.
kono
parents:
diff changeset
2486 tree
kono
parents:
diff changeset
2487 check_function_concept (tree fn)
kono
parents:
diff changeset
2488 {
kono
parents:
diff changeset
2489 // Check that the function is comprised of only a single
kono
parents:
diff changeset
2490 // return statement.
kono
parents:
diff changeset
2491 tree body = DECL_SAVED_TREE (fn);
kono
parents:
diff changeset
2492 if (TREE_CODE (body) == BIND_EXPR)
kono
parents:
diff changeset
2493 body = BIND_EXPR_BODY (body);
kono
parents:
diff changeset
2494
kono
parents:
diff changeset
2495 // Sometimes a function call results in the creation of clean up
kono
parents:
diff changeset
2496 // points. Allow these to be preserved in the body of the
kono
parents:
diff changeset
2497 // constraint, as we might actually need them for some constexpr
kono
parents:
diff changeset
2498 // evaluations.
kono
parents:
diff changeset
2499 if (TREE_CODE (body) == CLEANUP_POINT_EXPR)
kono
parents:
diff changeset
2500 body = TREE_OPERAND (body, 0);
kono
parents:
diff changeset
2501
kono
parents:
diff changeset
2502 /* Check that the definition is written correctly. */
kono
parents:
diff changeset
2503 if (TREE_CODE (body) != RETURN_EXPR)
kono
parents:
diff changeset
2504 {
kono
parents:
diff changeset
2505 location_t loc = DECL_SOURCE_LOCATION (fn);
kono
parents:
diff changeset
2506 if (TREE_CODE (body) == STATEMENT_LIST && !STATEMENT_LIST_HEAD (body))
kono
parents:
diff changeset
2507 {
kono
parents:
diff changeset
2508 if (seen_error ())
kono
parents:
diff changeset
2509 /* The definition was probably erroneous, not empty. */;
kono
parents:
diff changeset
2510 else
kono
parents:
diff changeset
2511 error_at (loc, "definition of concept %qD is empty", fn);
kono
parents:
diff changeset
2512 }
kono
parents:
diff changeset
2513 else
kono
parents:
diff changeset
2514 error_at (loc, "definition of concept %qD has multiple statements", fn);
kono
parents:
diff changeset
2515 }
kono
parents:
diff changeset
2516
kono
parents:
diff changeset
2517 return NULL_TREE;
kono
parents:
diff changeset
2518 }
kono
parents:
diff changeset
2519
kono
parents:
diff changeset
2520
kono
parents:
diff changeset
2521 // Check that a constrained friend declaration function declaration,
kono
parents:
diff changeset
2522 // FN, is admissible. This is the case only when the declaration depends
kono
parents:
diff changeset
2523 // on template parameters and does not declare a specialization.
kono
parents:
diff changeset
2524 void
kono
parents:
diff changeset
2525 check_constrained_friend (tree fn, tree reqs)
kono
parents:
diff changeset
2526 {
kono
parents:
diff changeset
2527 if (fn == error_mark_node)
kono
parents:
diff changeset
2528 return;
kono
parents:
diff changeset
2529 gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
kono
parents:
diff changeset
2530
kono
parents:
diff changeset
2531 // If there are not constraints, this cannot be an error.
kono
parents:
diff changeset
2532 if (!reqs)
kono
parents:
diff changeset
2533 return;
kono
parents:
diff changeset
2534
kono
parents:
diff changeset
2535 // Constrained friend functions that don't depend on template
kono
parents:
diff changeset
2536 // arguments are effectively meaningless.
kono
parents:
diff changeset
2537 if (!uses_template_parms (TREE_TYPE (fn)))
kono
parents:
diff changeset
2538 {
kono
parents:
diff changeset
2539 error_at (location_of (fn),
kono
parents:
diff changeset
2540 "constrained friend does not depend on template parameters");
kono
parents:
diff changeset
2541 return;
kono
parents:
diff changeset
2542 }
kono
parents:
diff changeset
2543 }
kono
parents:
diff changeset
2544
kono
parents:
diff changeset
2545 /*---------------------------------------------------------------------------
kono
parents:
diff changeset
2546 Equivalence of constraints
kono
parents:
diff changeset
2547 ---------------------------------------------------------------------------*/
kono
parents:
diff changeset
2548
kono
parents:
diff changeset
2549 /* Returns true when A and B are equivalent constraints. */
kono
parents:
diff changeset
2550 bool
kono
parents:
diff changeset
2551 equivalent_constraints (tree a, tree b)
kono
parents:
diff changeset
2552 {
kono
parents:
diff changeset
2553 gcc_assert (!a || TREE_CODE (a) == CONSTRAINT_INFO);
kono
parents:
diff changeset
2554 gcc_assert (!b || TREE_CODE (b) == CONSTRAINT_INFO);
kono
parents:
diff changeset
2555 return cp_tree_equal (a, b);
kono
parents:
diff changeset
2556 }
kono
parents:
diff changeset
2557
kono
parents:
diff changeset
2558 /* Returns true if the template declarations A and B have equivalent
kono
parents:
diff changeset
2559 constraints. This is the case when A's constraints subsume B's and
kono
parents:
diff changeset
2560 when B's also constrain A's. */
kono
parents:
diff changeset
2561 bool
kono
parents:
diff changeset
2562 equivalently_constrained (tree d1, tree d2)
kono
parents:
diff changeset
2563 {
kono
parents:
diff changeset
2564 gcc_assert (TREE_CODE (d1) == TREE_CODE (d2));
kono
parents:
diff changeset
2565 return equivalent_constraints (get_constraints (d1), get_constraints (d2));
kono
parents:
diff changeset
2566 }
kono
parents:
diff changeset
2567
kono
parents:
diff changeset
2568 /*---------------------------------------------------------------------------
kono
parents:
diff changeset
2569 Partial ordering of constraints
kono
parents:
diff changeset
2570 ---------------------------------------------------------------------------*/
kono
parents:
diff changeset
2571
kono
parents:
diff changeset
2572 /* Returns true when the the constraints in A subsume those in B. */
kono
parents:
diff changeset
2573
kono
parents:
diff changeset
2574 bool
kono
parents:
diff changeset
2575 subsumes_constraints (tree a, tree b)
kono
parents:
diff changeset
2576 {
kono
parents:
diff changeset
2577 gcc_assert (!a || TREE_CODE (a) == CONSTRAINT_INFO);
kono
parents:
diff changeset
2578 gcc_assert (!b || TREE_CODE (b) == CONSTRAINT_INFO);
kono
parents:
diff changeset
2579 return subsumes (a, b);
kono
parents:
diff changeset
2580 }
kono
parents:
diff changeset
2581
kono
parents:
diff changeset
2582 /* Returns true when the the constraints in A subsume those in B, but
kono
parents:
diff changeset
2583 the constraints in B do not subsume the constraints in A. */
kono
parents:
diff changeset
2584
kono
parents:
diff changeset
2585 bool
kono
parents:
diff changeset
2586 strictly_subsumes (tree a, tree b)
kono
parents:
diff changeset
2587 {
kono
parents:
diff changeset
2588 return subsumes (a, b) && !subsumes (b, a);
kono
parents:
diff changeset
2589 }
kono
parents:
diff changeset
2590
kono
parents:
diff changeset
2591 /* Determines which of the declarations, A or B, is more constrained.
kono
parents:
diff changeset
2592 That is, which declaration's constraints subsume but are not subsumed
kono
parents:
diff changeset
2593 by the other's?
kono
parents:
diff changeset
2594
kono
parents:
diff changeset
2595 Returns 1 if A is more constrained than B, -1 if B is more constrained
kono
parents:
diff changeset
2596 than A, and 0 otherwise. */
kono
parents:
diff changeset
2597
kono
parents:
diff changeset
2598 int
kono
parents:
diff changeset
2599 more_constrained (tree d1, tree d2)
kono
parents:
diff changeset
2600 {
kono
parents:
diff changeset
2601 tree c1 = get_constraints (d1);
kono
parents:
diff changeset
2602 tree c2 = get_constraints (d2);
kono
parents:
diff changeset
2603 int winner = 0;
kono
parents:
diff changeset
2604 if (subsumes_constraints (c1, c2))
kono
parents:
diff changeset
2605 ++winner;
kono
parents:
diff changeset
2606 if (subsumes_constraints (c2, c1))
kono
parents:
diff changeset
2607 --winner;
kono
parents:
diff changeset
2608 return winner;
kono
parents:
diff changeset
2609 }
kono
parents:
diff changeset
2610
kono
parents:
diff changeset
2611 /* Returns true if D1 is at least as constrained as D2. That is, the
kono
parents:
diff changeset
2612 associated constraints of D1 subsume those of D2, or both declarations
kono
parents:
diff changeset
2613 are unconstrained. */
kono
parents:
diff changeset
2614
kono
parents:
diff changeset
2615 bool
kono
parents:
diff changeset
2616 at_least_as_constrained (tree d1, tree d2)
kono
parents:
diff changeset
2617 {
kono
parents:
diff changeset
2618 tree c1 = get_constraints (d1);
kono
parents:
diff changeset
2619 tree c2 = get_constraints (d2);
kono
parents:
diff changeset
2620 return subsumes_constraints (c1, c2);
kono
parents:
diff changeset
2621 }
kono
parents:
diff changeset
2622
kono
parents:
diff changeset
2623
kono
parents:
diff changeset
2624 /*---------------------------------------------------------------------------
kono
parents:
diff changeset
2625 Constraint diagnostics
kono
parents:
diff changeset
2626
kono
parents:
diff changeset
2627 FIXME: Normalize expressions into constraints before evaluating them.
kono
parents:
diff changeset
2628 This should be the general pattern for all such diagnostics.
kono
parents:
diff changeset
2629 ---------------------------------------------------------------------------*/
kono
parents:
diff changeset
2630
kono
parents:
diff changeset
2631 /* The number of detailed constraint failures. */
kono
parents:
diff changeset
2632
kono
parents:
diff changeset
2633 int constraint_errors = 0;
kono
parents:
diff changeset
2634
kono
parents:
diff changeset
2635 /* Do not generate errors after diagnosing this number of constraint
kono
parents:
diff changeset
2636 failures.
kono
parents:
diff changeset
2637
kono
parents:
diff changeset
2638 FIXME: This is a really arbitrary number. Provide better control of
kono
parents:
diff changeset
2639 constraint diagnostics with a command line option. */
kono
parents:
diff changeset
2640
kono
parents:
diff changeset
2641 int constraint_thresh = 20;
kono
parents:
diff changeset
2642
kono
parents:
diff changeset
2643
kono
parents:
diff changeset
2644 /* Returns true if we should elide the diagnostic for a constraint failure.
kono
parents:
diff changeset
2645 This is the case when the number of errors has exceeded the pre-configured
kono
parents:
diff changeset
2646 threshold. */
kono
parents:
diff changeset
2647
kono
parents:
diff changeset
2648 inline bool
kono
parents:
diff changeset
2649 elide_constraint_failure_p ()
kono
parents:
diff changeset
2650 {
kono
parents:
diff changeset
2651 bool ret = constraint_thresh <= constraint_errors;
kono
parents:
diff changeset
2652 ++constraint_errors;
kono
parents:
diff changeset
2653 return ret;
kono
parents:
diff changeset
2654 }
kono
parents:
diff changeset
2655
kono
parents:
diff changeset
2656 /* Returns the number of undiagnosed errors. */
kono
parents:
diff changeset
2657
kono
parents:
diff changeset
2658 inline int
kono
parents:
diff changeset
2659 undiagnosed_constraint_failures ()
kono
parents:
diff changeset
2660 {
kono
parents:
diff changeset
2661 return constraint_errors - constraint_thresh;
kono
parents:
diff changeset
2662 }
kono
parents:
diff changeset
2663
kono
parents:
diff changeset
2664 /* The diagnosis of constraints performs a combination of normalization
kono
parents:
diff changeset
2665 and satisfaction testing. We recursively walk through the conjunction or
kono
parents:
diff changeset
2666 disjunction of associated constraints, testing each sub-constraint in
kono
parents:
diff changeset
2667 turn. */
kono
parents:
diff changeset
2668
kono
parents:
diff changeset
2669 namespace {
kono
parents:
diff changeset
2670
kono
parents:
diff changeset
2671 void diagnose_constraint (location_t, tree, tree, tree);
kono
parents:
diff changeset
2672
kono
parents:
diff changeset
2673 /* Emit a specific diagnostics for a failed trait. */
kono
parents:
diff changeset
2674
kono
parents:
diff changeset
2675 void
kono
parents:
diff changeset
2676 diagnose_trait_expression (location_t loc, tree, tree cur, tree args)
kono
parents:
diff changeset
2677 {
kono
parents:
diff changeset
2678 if (constraint_expression_satisfied_p (cur, args))
kono
parents:
diff changeset
2679 return;
kono
parents:
diff changeset
2680 if (elide_constraint_failure_p())
kono
parents:
diff changeset
2681 return;
kono
parents:
diff changeset
2682
kono
parents:
diff changeset
2683 tree expr = PRED_CONSTR_EXPR (cur);
kono
parents:
diff changeset
2684 ++processing_template_decl;
kono
parents:
diff changeset
2685 expr = tsubst_expr (expr, args, tf_none, NULL_TREE, false);
kono
parents:
diff changeset
2686 --processing_template_decl;
kono
parents:
diff changeset
2687
kono
parents:
diff changeset
2688 tree t1 = TRAIT_EXPR_TYPE1 (expr);
kono
parents:
diff changeset
2689 tree t2 = TRAIT_EXPR_TYPE2 (expr);
kono
parents:
diff changeset
2690 switch (TRAIT_EXPR_KIND (expr))
kono
parents:
diff changeset
2691 {
kono
parents:
diff changeset
2692 case CPTK_HAS_NOTHROW_ASSIGN:
kono
parents:
diff changeset
2693 inform (loc, " %qT is not nothrow copy assignable", t1);
kono
parents:
diff changeset
2694 break;
kono
parents:
diff changeset
2695 case CPTK_HAS_NOTHROW_CONSTRUCTOR:
kono
parents:
diff changeset
2696 inform (loc, " %qT is not nothrow default constructible", t1);
kono
parents:
diff changeset
2697 break;
kono
parents:
diff changeset
2698 case CPTK_HAS_NOTHROW_COPY:
kono
parents:
diff changeset
2699 inform (loc, " %qT is not nothrow copy constructible", t1);
kono
parents:
diff changeset
2700 break;
kono
parents:
diff changeset
2701 case CPTK_HAS_TRIVIAL_ASSIGN:
kono
parents:
diff changeset
2702 inform (loc, " %qT is not trivially copy assignable", t1);
kono
parents:
diff changeset
2703 break;
kono
parents:
diff changeset
2704 case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
kono
parents:
diff changeset
2705 inform (loc, " %qT is not trivially default constructible", t1);
kono
parents:
diff changeset
2706 break;
kono
parents:
diff changeset
2707 case CPTK_HAS_TRIVIAL_COPY:
kono
parents:
diff changeset
2708 inform (loc, " %qT is not trivially copy constructible", t1);
kono
parents:
diff changeset
2709 break;
kono
parents:
diff changeset
2710 case CPTK_HAS_TRIVIAL_DESTRUCTOR:
kono
parents:
diff changeset
2711 inform (loc, " %qT is not trivially destructible", t1);
kono
parents:
diff changeset
2712 break;
kono
parents:
diff changeset
2713 case CPTK_HAS_VIRTUAL_DESTRUCTOR:
kono
parents:
diff changeset
2714 inform (loc, " %qT does not have a virtual destructor", t1);
kono
parents:
diff changeset
2715 break;
kono
parents:
diff changeset
2716 case CPTK_IS_ABSTRACT:
kono
parents:
diff changeset
2717 inform (loc, " %qT is not an abstract class", t1);
kono
parents:
diff changeset
2718 break;
kono
parents:
diff changeset
2719 case CPTK_IS_BASE_OF:
kono
parents:
diff changeset
2720 inform (loc, " %qT is not a base of %qT", t1, t2);
kono
parents:
diff changeset
2721 break;
kono
parents:
diff changeset
2722 case CPTK_IS_CLASS:
kono
parents:
diff changeset
2723 inform (loc, " %qT is not a class", t1);
kono
parents:
diff changeset
2724 break;
kono
parents:
diff changeset
2725 case CPTK_IS_EMPTY:
kono
parents:
diff changeset
2726 inform (loc, " %qT is not an empty class", t1);
kono
parents:
diff changeset
2727 break;
kono
parents:
diff changeset
2728 case CPTK_IS_ENUM:
kono
parents:
diff changeset
2729 inform (loc, " %qT is not an enum", t1);
kono
parents:
diff changeset
2730 break;
kono
parents:
diff changeset
2731 case CPTK_IS_FINAL:
kono
parents:
diff changeset
2732 inform (loc, " %qT is not a final class", t1);
kono
parents:
diff changeset
2733 break;
kono
parents:
diff changeset
2734 case CPTK_IS_LITERAL_TYPE:
kono
parents:
diff changeset
2735 inform (loc, " %qT is not a literal type", t1);
kono
parents:
diff changeset
2736 break;
kono
parents:
diff changeset
2737 case CPTK_IS_POD:
kono
parents:
diff changeset
2738 inform (loc, " %qT is not a POD type", t1);
kono
parents:
diff changeset
2739 break;
kono
parents:
diff changeset
2740 case CPTK_IS_POLYMORPHIC:
kono
parents:
diff changeset
2741 inform (loc, " %qT is not a polymorphic type", t1);
kono
parents:
diff changeset
2742 break;
kono
parents:
diff changeset
2743 case CPTK_IS_SAME_AS:
kono
parents:
diff changeset
2744 inform (loc, " %qT is not the same as %qT", t1, t2);
kono
parents:
diff changeset
2745 break;
kono
parents:
diff changeset
2746 case CPTK_IS_STD_LAYOUT:
kono
parents:
diff changeset
2747 inform (loc, " %qT is not an standard layout type", t1);
kono
parents:
diff changeset
2748 break;
kono
parents:
diff changeset
2749 case CPTK_IS_TRIVIAL:
kono
parents:
diff changeset
2750 inform (loc, " %qT is not a trivial type", t1);
kono
parents:
diff changeset
2751 break;
kono
parents:
diff changeset
2752 case CPTK_IS_UNION:
kono
parents:
diff changeset
2753 inform (loc, " %qT is not a union", t1);
kono
parents:
diff changeset
2754 break;
kono
parents:
diff changeset
2755 default:
kono
parents:
diff changeset
2756 gcc_unreachable ();
kono
parents:
diff changeset
2757 }
kono
parents:
diff changeset
2758 }
kono
parents:
diff changeset
2759
kono
parents:
diff changeset
2760 /* Diagnose the expression of a predicate constraint. */
kono
parents:
diff changeset
2761
kono
parents:
diff changeset
2762 void
kono
parents:
diff changeset
2763 diagnose_other_expression (location_t loc, tree, tree cur, tree args)
kono
parents:
diff changeset
2764 {
kono
parents:
diff changeset
2765 if (constraint_expression_satisfied_p (cur, args))
kono
parents:
diff changeset
2766 return;
kono
parents:
diff changeset
2767 if (elide_constraint_failure_p())
kono
parents:
diff changeset
2768 return;
kono
parents:
diff changeset
2769 inform (loc, "%qE evaluated to false", cur);
kono
parents:
diff changeset
2770 }
kono
parents:
diff changeset
2771
kono
parents:
diff changeset
2772 /* Do our best to infer meaning from predicates. */
kono
parents:
diff changeset
2773
kono
parents:
diff changeset
2774 inline void
kono
parents:
diff changeset
2775 diagnose_predicate_constraint (location_t loc, tree orig, tree cur, tree args)
kono
parents:
diff changeset
2776 {
kono
parents:
diff changeset
2777 if (TREE_CODE (PRED_CONSTR_EXPR (cur)) == TRAIT_EXPR)
kono
parents:
diff changeset
2778 diagnose_trait_expression (loc, orig, cur, args);
kono
parents:
diff changeset
2779 else
kono
parents:
diff changeset
2780 diagnose_other_expression (loc, orig, cur, args);
kono
parents:
diff changeset
2781 }
kono
parents:
diff changeset
2782
kono
parents:
diff changeset
2783 /* Diagnose a failed pack expansion, possibly containing constraints. */
kono
parents:
diff changeset
2784
kono
parents:
diff changeset
2785 void
kono
parents:
diff changeset
2786 diagnose_pack_expansion (location_t loc, tree, tree cur, tree args)
kono
parents:
diff changeset
2787 {
kono
parents:
diff changeset
2788 if (constraint_expression_satisfied_p (cur, args))
kono
parents:
diff changeset
2789 return;
kono
parents:
diff changeset
2790 if (elide_constraint_failure_p())
kono
parents:
diff changeset
2791 return;
kono
parents:
diff changeset
2792
kono
parents:
diff changeset
2793 /* Make sure that we don't have naked packs that we don't expect. */
kono
parents:
diff changeset
2794 if (!same_type_p (TREE_TYPE (cur), boolean_type_node))
kono
parents:
diff changeset
2795 {
kono
parents:
diff changeset
2796 inform (loc, "invalid pack expansion in constraint %qE", cur);
kono
parents:
diff changeset
2797 return;
kono
parents:
diff changeset
2798 }
kono
parents:
diff changeset
2799
kono
parents:
diff changeset
2800 inform (loc, "in the expansion of %qE", cur);
kono
parents:
diff changeset
2801
kono
parents:
diff changeset
2802 /* Get the vector of expanded arguments. Note that n must not
kono
parents:
diff changeset
2803 be 0 since this constraint is not satisfied. */
kono
parents:
diff changeset
2804 ++processing_template_decl;
kono
parents:
diff changeset
2805 tree exprs = tsubst_pack_expansion (cur, args, tf_none, NULL_TREE);
kono
parents:
diff changeset
2806 --processing_template_decl;
kono
parents:
diff changeset
2807 if (exprs == error_mark_node)
kono
parents:
diff changeset
2808 {
kono
parents:
diff changeset
2809 /* TODO: This error message could be better. */
kono
parents:
diff changeset
2810 inform (loc, " substitution failure occurred during expansion");
kono
parents:
diff changeset
2811 return;
kono
parents:
diff changeset
2812 }
kono
parents:
diff changeset
2813
kono
parents:
diff changeset
2814 /* Check each expanded constraint separately. */
kono
parents:
diff changeset
2815 int n = TREE_VEC_LENGTH (exprs);
kono
parents:
diff changeset
2816 for (int i = 0; i < n; ++i)
kono
parents:
diff changeset
2817 {
kono
parents:
diff changeset
2818 tree expr = TREE_VEC_ELT (exprs, i);
kono
parents:
diff changeset
2819 if (!constraint_expression_satisfied_p (expr, args))
kono
parents:
diff changeset
2820 inform (loc, " %qE was not satisfied", expr);
kono
parents:
diff changeset
2821 }
kono
parents:
diff changeset
2822 }
kono
parents:
diff changeset
2823
kono
parents:
diff changeset
2824 /* Diagnose a potentially unsatisfied concept check constraint DECL<CARGS>.
kono
parents:
diff changeset
2825 Parameters are as for diagnose_constraint. */
kono
parents:
diff changeset
2826
kono
parents:
diff changeset
2827 void
kono
parents:
diff changeset
2828 diagnose_check_constraint (location_t loc, tree orig, tree cur, tree args)
kono
parents:
diff changeset
2829 {
kono
parents:
diff changeset
2830 if (constraints_satisfied_p (cur, args))
kono
parents:
diff changeset
2831 return;
kono
parents:
diff changeset
2832
kono
parents:
diff changeset
2833 tree decl = CHECK_CONSTR_CONCEPT (cur);
kono
parents:
diff changeset
2834 tree cargs = CHECK_CONSTR_ARGS (cur);
kono
parents:
diff changeset
2835 tree tmpl = DECL_TI_TEMPLATE (decl);
kono
parents:
diff changeset
2836 tree check = build_nt (CHECK_CONSTR, decl, cargs);
kono
parents:
diff changeset
2837
kono
parents:
diff changeset
2838 /* Instantiate the concept check arguments. */
kono
parents:
diff changeset
2839 tree targs = tsubst (cargs, args, tf_none, NULL_TREE);
kono
parents:
diff changeset
2840 if (targs == error_mark_node)
kono
parents:
diff changeset
2841 {
kono
parents:
diff changeset
2842 if (elide_constraint_failure_p ())
kono
parents:
diff changeset
2843 return;
kono
parents:
diff changeset
2844 inform (loc, "invalid use of the concept %qE", check);
kono
parents:
diff changeset
2845 tsubst (cargs, args, tf_warning_or_error, NULL_TREE);
kono
parents:
diff changeset
2846 return;
kono
parents:
diff changeset
2847 }
kono
parents:
diff changeset
2848
kono
parents:
diff changeset
2849 tree sub = build_tree_list (tmpl, targs);
kono
parents:
diff changeset
2850 /* Update to the expanded definitions. */
kono
parents:
diff changeset
2851 cur = expand_concept (decl, targs);
kono
parents:
diff changeset
2852 if (cur == error_mark_node)
kono
parents:
diff changeset
2853 {
kono
parents:
diff changeset
2854 if (elide_constraint_failure_p ())
kono
parents:
diff changeset
2855 return;
kono
parents:
diff changeset
2856 inform (loc, "in the expansion of concept %<%E %S%>", check, sub);
kono
parents:
diff changeset
2857 cur = get_concept_definition (decl);
kono
parents:
diff changeset
2858 tsubst_expr (cur, targs, tf_warning_or_error, NULL_TREE, false);
kono
parents:
diff changeset
2859 return;
kono
parents:
diff changeset
2860 }
kono
parents:
diff changeset
2861
kono
parents:
diff changeset
2862 orig = get_concept_definition (CHECK_CONSTR_CONCEPT (orig));
kono
parents:
diff changeset
2863 orig = normalize_expression (orig);
kono
parents:
diff changeset
2864
kono
parents:
diff changeset
2865 location_t dloc = DECL_SOURCE_LOCATION (decl);
kono
parents:
diff changeset
2866 inform (dloc, "within %qS", sub);
kono
parents:
diff changeset
2867 diagnose_constraint (dloc, orig, cur, targs);
kono
parents:
diff changeset
2868 }
kono
parents:
diff changeset
2869
kono
parents:
diff changeset
2870 /* Diagnose a potentially unsatisfied conjunction or disjunction. Parameters
kono
parents:
diff changeset
2871 are as for diagnose_constraint. */
kono
parents:
diff changeset
2872
kono
parents:
diff changeset
2873 void
kono
parents:
diff changeset
2874 diagnose_logical_constraint (location_t loc, tree orig, tree cur, tree args)
kono
parents:
diff changeset
2875 {
kono
parents:
diff changeset
2876 tree t0 = TREE_OPERAND (cur, 0);
kono
parents:
diff changeset
2877 tree t1 = TREE_OPERAND (cur, 1);
kono
parents:
diff changeset
2878 if (!constraints_satisfied_p (t0, args))
kono
parents:
diff changeset
2879 diagnose_constraint (loc, TREE_OPERAND (orig, 0), t0, args);
kono
parents:
diff changeset
2880 else if (TREE_CODE (orig) == TRUTH_ORIF_EXPR)
kono
parents:
diff changeset
2881 return;
kono
parents:
diff changeset
2882 if (!constraints_satisfied_p (t1, args))
kono
parents:
diff changeset
2883 diagnose_constraint (loc, TREE_OPERAND (orig, 1), t1, args);
kono
parents:
diff changeset
2884 }
kono
parents:
diff changeset
2885
kono
parents:
diff changeset
2886 /* Diagnose a potential expression constraint failure. */
kono
parents:
diff changeset
2887
kono
parents:
diff changeset
2888 void
kono
parents:
diff changeset
2889 diagnose_expression_constraint (location_t loc, tree orig, tree cur, tree args)
kono
parents:
diff changeset
2890 {
kono
parents:
diff changeset
2891 if (constraints_satisfied_p (cur, args))
kono
parents:
diff changeset
2892 return;
kono
parents:
diff changeset
2893 if (elide_constraint_failure_p())
kono
parents:
diff changeset
2894 return;
kono
parents:
diff changeset
2895
kono
parents:
diff changeset
2896 tree expr = EXPR_CONSTR_EXPR (orig);
kono
parents:
diff changeset
2897 inform (loc, "the required expression %qE would be ill-formed", expr);
kono
parents:
diff changeset
2898
kono
parents:
diff changeset
2899 // TODO: We should have a flag that controls this substitution.
kono
parents:
diff changeset
2900 // I'm finding it very useful for resolving concept check errors.
kono
parents:
diff changeset
2901
kono
parents:
diff changeset
2902 // inform (input_location, "==== BEGIN DUMP ====");
kono
parents:
diff changeset
2903 // tsubst_expr (EXPR_CONSTR_EXPR (orig), args, tf_warning_or_error, NULL_TREE, false);
kono
parents:
diff changeset
2904 // inform (input_location, "==== END DUMP ====");
kono
parents:
diff changeset
2905 }
kono
parents:
diff changeset
2906
kono
parents:
diff changeset
2907 /* Diagnose a potentially failed type constraint. */
kono
parents:
diff changeset
2908
kono
parents:
diff changeset
2909 void
kono
parents:
diff changeset
2910 diagnose_type_constraint (location_t loc, tree orig, tree cur, tree args)
kono
parents:
diff changeset
2911 {
kono
parents:
diff changeset
2912 if (constraints_satisfied_p (cur, args))
kono
parents:
diff changeset
2913 return;
kono
parents:
diff changeset
2914 if (elide_constraint_failure_p())
kono
parents:
diff changeset
2915 return;
kono
parents:
diff changeset
2916
kono
parents:
diff changeset
2917 tree type = TYPE_CONSTR_TYPE (orig);
kono
parents:
diff changeset
2918 inform (loc, "the required type %qT would be ill-formed", type);
kono
parents:
diff changeset
2919 }
kono
parents:
diff changeset
2920
kono
parents:
diff changeset
2921 /* Diagnose a potentially unsatisfied conversion constraint. */
kono
parents:
diff changeset
2922
kono
parents:
diff changeset
2923 void
kono
parents:
diff changeset
2924 diagnose_implicit_conversion_constraint (location_t loc, tree orig, tree cur,
kono
parents:
diff changeset
2925 tree args)
kono
parents:
diff changeset
2926 {
kono
parents:
diff changeset
2927 if (constraints_satisfied_p (cur, args))
kono
parents:
diff changeset
2928 return;
kono
parents:
diff changeset
2929
kono
parents:
diff changeset
2930 /* The expression and type will previously have been substituted into,
kono
parents:
diff changeset
2931 and therefore may already be an error. Also, we will have already
kono
parents:
diff changeset
2932 diagnosed substitution failures into an expression since this must be
kono
parents:
diff changeset
2933 part of a compound requirement. */
kono
parents:
diff changeset
2934 tree expr = ICONV_CONSTR_EXPR (cur);
kono
parents:
diff changeset
2935 if (error_operand_p (expr))
kono
parents:
diff changeset
2936 return;
kono
parents:
diff changeset
2937
kono
parents:
diff changeset
2938 /* Don't elide a previously diagnosed failure. */
kono
parents:
diff changeset
2939 if (elide_constraint_failure_p())
kono
parents:
diff changeset
2940 return;
kono
parents:
diff changeset
2941
kono
parents:
diff changeset
2942 tree type = ICONV_CONSTR_TYPE (cur);
kono
parents:
diff changeset
2943 if (error_operand_p (type))
kono
parents:
diff changeset
2944 {
kono
parents:
diff changeset
2945 inform (loc, "substitution into type %qT failed",
kono
parents:
diff changeset
2946 ICONV_CONSTR_TYPE (orig));
kono
parents:
diff changeset
2947 return;
kono
parents:
diff changeset
2948 }
kono
parents:
diff changeset
2949
kono
parents:
diff changeset
2950 inform(loc, "%qE is not implicitly convertible to %qT", expr, type);
kono
parents:
diff changeset
2951 }
kono
parents:
diff changeset
2952
kono
parents:
diff changeset
2953 /* Diagnose an argument deduction constraint. */
kono
parents:
diff changeset
2954
kono
parents:
diff changeset
2955 void
kono
parents:
diff changeset
2956 diagnose_argument_deduction_constraint (location_t loc, tree orig, tree cur,
kono
parents:
diff changeset
2957 tree args)
kono
parents:
diff changeset
2958 {
kono
parents:
diff changeset
2959 if (constraints_satisfied_p (cur, args))
kono
parents:
diff changeset
2960 return;
kono
parents:
diff changeset
2961
kono
parents:
diff changeset
2962 /* The expression and type will previously have been substituted into,
kono
parents:
diff changeset
2963 and therefore may already be an error. Also, we will have already
kono
parents:
diff changeset
2964 diagnosed substution failures into an expression since this must be
kono
parents:
diff changeset
2965 part of a compound requirement. */
kono
parents:
diff changeset
2966 tree expr = DEDUCT_CONSTR_EXPR (cur);
kono
parents:
diff changeset
2967 if (error_operand_p (expr))
kono
parents:
diff changeset
2968 return;
kono
parents:
diff changeset
2969
kono
parents:
diff changeset
2970 /* Don't elide a previously diagnosed failure. */
kono
parents:
diff changeset
2971 if (elide_constraint_failure_p ())
kono
parents:
diff changeset
2972 return;
kono
parents:
diff changeset
2973
kono
parents:
diff changeset
2974 tree pattern = DEDUCT_CONSTR_PATTERN (cur);
kono
parents:
diff changeset
2975 if (error_operand_p (pattern))
kono
parents:
diff changeset
2976 {
kono
parents:
diff changeset
2977 inform (loc, "substitution into type %qT failed",
kono
parents:
diff changeset
2978 DEDUCT_CONSTR_PATTERN (orig));
kono
parents:
diff changeset
2979 return;
kono
parents:
diff changeset
2980 }
kono
parents:
diff changeset
2981
kono
parents:
diff changeset
2982 inform (loc, "unable to deduce placeholder type %qT from %qE",
kono
parents:
diff changeset
2983 pattern, expr);
kono
parents:
diff changeset
2984 }
kono
parents:
diff changeset
2985
kono
parents:
diff changeset
2986 /* Diagnose an exception constraint. */
kono
parents:
diff changeset
2987
kono
parents:
diff changeset
2988 void
kono
parents:
diff changeset
2989 diagnose_exception_constraint (location_t loc, tree orig, tree cur, tree args)
kono
parents:
diff changeset
2990 {
kono
parents:
diff changeset
2991 if (constraints_satisfied_p (cur, args))
kono
parents:
diff changeset
2992 return;
kono
parents:
diff changeset
2993 if (elide_constraint_failure_p ())
kono
parents:
diff changeset
2994 return;
kono
parents:
diff changeset
2995
kono
parents:
diff changeset
2996 /* Rebuild a noexcept expression. */
kono
parents:
diff changeset
2997 tree expr = EXCEPT_CONSTR_EXPR (cur);
kono
parents:
diff changeset
2998 if (error_operand_p (expr))
kono
parents:
diff changeset
2999 return;
kono
parents:
diff changeset
3000
kono
parents:
diff changeset
3001 inform (loc, "%qE evaluated to false", EXCEPT_CONSTR_EXPR (orig));
kono
parents:
diff changeset
3002 }
kono
parents:
diff changeset
3003
kono
parents:
diff changeset
3004 /* Diagnose a potentially unsatisfied parameterized constraint. */
kono
parents:
diff changeset
3005
kono
parents:
diff changeset
3006 void
kono
parents:
diff changeset
3007 diagnose_parameterized_constraint (location_t loc, tree orig, tree cur,
kono
parents:
diff changeset
3008 tree args)
kono
parents:
diff changeset
3009 {
kono
parents:
diff changeset
3010 if (constraints_satisfied_p (cur, args))
kono
parents:
diff changeset
3011 return;
kono
parents:
diff changeset
3012
kono
parents:
diff changeset
3013 local_specialization_stack stack;
kono
parents:
diff changeset
3014 tree parms = PARM_CONSTR_PARMS (cur);
kono
parents:
diff changeset
3015 tree vars = tsubst_constraint_variables (parms, args, tf_warning_or_error,
kono
parents:
diff changeset
3016 NULL_TREE);
kono
parents:
diff changeset
3017 if (vars == error_mark_node)
kono
parents:
diff changeset
3018 {
kono
parents:
diff changeset
3019 if (elide_constraint_failure_p ())
kono
parents:
diff changeset
3020 return;
kono
parents:
diff changeset
3021
kono
parents:
diff changeset
3022 /* TODO: Check which variable failed and use orig to diagnose
kono
parents:
diff changeset
3023 that substitution error. */
kono
parents:
diff changeset
3024 inform (loc, "failed to instantiate constraint variables");
kono
parents:
diff changeset
3025 return;
kono
parents:
diff changeset
3026 }
kono
parents:
diff changeset
3027
kono
parents:
diff changeset
3028 /* TODO: It would be better write these in a list. */
kono
parents:
diff changeset
3029 while (vars)
kono
parents:
diff changeset
3030 {
kono
parents:
diff changeset
3031 inform (loc, " with %q#D", vars);
kono
parents:
diff changeset
3032 vars = TREE_CHAIN (vars);
kono
parents:
diff changeset
3033 }
kono
parents:
diff changeset
3034 orig = PARM_CONSTR_OPERAND (orig);
kono
parents:
diff changeset
3035 cur = PARM_CONSTR_OPERAND (cur);
kono
parents:
diff changeset
3036 return diagnose_constraint (loc, orig, cur, args);
kono
parents:
diff changeset
3037 }
kono
parents:
diff changeset
3038
kono
parents:
diff changeset
3039 /* Diagnose the constraint CUR for the given ARGS. This is only ever invoked
kono
parents:
diff changeset
3040 on the associated constraints, so we can only have conjunctions of
kono
parents:
diff changeset
3041 predicate constraints. The ORIGinal (dependent) constructs follow
kono
parents:
diff changeset
3042 the current constraints to enable better diagnostics. Note that ORIG
kono
parents:
diff changeset
3043 and CUR must be the same kinds of node, except when CUR is an error. */
kono
parents:
diff changeset
3044
kono
parents:
diff changeset
3045 void
kono
parents:
diff changeset
3046 diagnose_constraint (location_t loc, tree orig, tree cur, tree args)
kono
parents:
diff changeset
3047 {
kono
parents:
diff changeset
3048 switch (TREE_CODE (cur))
kono
parents:
diff changeset
3049 {
kono
parents:
diff changeset
3050 case EXPR_CONSTR:
kono
parents:
diff changeset
3051 diagnose_expression_constraint (loc, orig, cur, args);
kono
parents:
diff changeset
3052 break;
kono
parents:
diff changeset
3053
kono
parents:
diff changeset
3054 case TYPE_CONSTR:
kono
parents:
diff changeset
3055 diagnose_type_constraint (loc, orig, cur, args);
kono
parents:
diff changeset
3056 break;
kono
parents:
diff changeset
3057
kono
parents:
diff changeset
3058 case ICONV_CONSTR:
kono
parents:
diff changeset
3059 diagnose_implicit_conversion_constraint (loc, orig, cur, args);
kono
parents:
diff changeset
3060 break;
kono
parents:
diff changeset
3061
kono
parents:
diff changeset
3062 case DEDUCT_CONSTR:
kono
parents:
diff changeset
3063 diagnose_argument_deduction_constraint (loc, orig, cur, args);
kono
parents:
diff changeset
3064 break;
kono
parents:
diff changeset
3065
kono
parents:
diff changeset
3066 case EXCEPT_CONSTR:
kono
parents:
diff changeset
3067 diagnose_exception_constraint (loc, orig, cur, args);
kono
parents:
diff changeset
3068 break;
kono
parents:
diff changeset
3069
kono
parents:
diff changeset
3070 case CONJ_CONSTR:
kono
parents:
diff changeset
3071 case DISJ_CONSTR:
kono
parents:
diff changeset
3072 diagnose_logical_constraint (loc, orig, cur, args);
kono
parents:
diff changeset
3073 break;
kono
parents:
diff changeset
3074
kono
parents:
diff changeset
3075 case PRED_CONSTR:
kono
parents:
diff changeset
3076 diagnose_predicate_constraint (loc, orig, cur, args);
kono
parents:
diff changeset
3077 break;
kono
parents:
diff changeset
3078
kono
parents:
diff changeset
3079 case PARM_CONSTR:
kono
parents:
diff changeset
3080 diagnose_parameterized_constraint (loc, orig, cur, args);
kono
parents:
diff changeset
3081 break;
kono
parents:
diff changeset
3082
kono
parents:
diff changeset
3083 case CHECK_CONSTR:
kono
parents:
diff changeset
3084 diagnose_check_constraint (loc, orig, cur, args);
kono
parents:
diff changeset
3085 break;
kono
parents:
diff changeset
3086
kono
parents:
diff changeset
3087 case EXPR_PACK_EXPANSION:
kono
parents:
diff changeset
3088 diagnose_pack_expansion (loc, orig, cur, args);
kono
parents:
diff changeset
3089 break;
kono
parents:
diff changeset
3090
kono
parents:
diff changeset
3091 case ERROR_MARK:
kono
parents:
diff changeset
3092 /* TODO: Can we improve the diagnostic with the original? */
kono
parents:
diff changeset
3093 inform (input_location, "ill-formed constraint");
kono
parents:
diff changeset
3094 break;
kono
parents:
diff changeset
3095
kono
parents:
diff changeset
3096 default:
kono
parents:
diff changeset
3097 gcc_unreachable ();
kono
parents:
diff changeset
3098 break;
kono
parents:
diff changeset
3099 }
kono
parents:
diff changeset
3100 }
kono
parents:
diff changeset
3101
kono
parents:
diff changeset
3102 /* Diagnose the reason(s) why ARGS do not satisfy the constraints
kono
parents:
diff changeset
3103 of declaration DECL. */
kono
parents:
diff changeset
3104
kono
parents:
diff changeset
3105 void
kono
parents:
diff changeset
3106 diagnose_declaration_constraints (location_t loc, tree decl, tree args)
kono
parents:
diff changeset
3107 {
kono
parents:
diff changeset
3108 inform (loc, " constraints not satisfied");
kono
parents:
diff changeset
3109
kono
parents:
diff changeset
3110 /* Constraints are attached to the template. */
kono
parents:
diff changeset
3111 if (tree ti = DECL_TEMPLATE_INFO (decl))
kono
parents:
diff changeset
3112 {
kono
parents:
diff changeset
3113 decl = TI_TEMPLATE (ti);
kono
parents:
diff changeset
3114 if (!args)
kono
parents:
diff changeset
3115 args = TI_ARGS (ti);
kono
parents:
diff changeset
3116 }
kono
parents:
diff changeset
3117
kono
parents:
diff changeset
3118 /* Recursively diagnose the associated constraints. */
kono
parents:
diff changeset
3119 tree ci = get_constraints (decl);
kono
parents:
diff changeset
3120 tree t = CI_ASSOCIATED_CONSTRAINTS (ci);
kono
parents:
diff changeset
3121 diagnose_constraint (loc, t, t, args);
kono
parents:
diff changeset
3122 }
kono
parents:
diff changeset
3123
kono
parents:
diff changeset
3124 } // namespace
kono
parents:
diff changeset
3125
kono
parents:
diff changeset
3126 /* Emit diagnostics detailing the failure ARGS to satisfy the
kono
parents:
diff changeset
3127 constraints of T. Here, T can be either a constraint
kono
parents:
diff changeset
3128 or a declaration. */
kono
parents:
diff changeset
3129
kono
parents:
diff changeset
3130 void
kono
parents:
diff changeset
3131 diagnose_constraints (location_t loc, tree t, tree args)
kono
parents:
diff changeset
3132 {
kono
parents:
diff changeset
3133 constraint_errors = 0;
kono
parents:
diff changeset
3134
kono
parents:
diff changeset
3135 if (constraint_p (t))
kono
parents:
diff changeset
3136 diagnose_constraint (loc, t, t, args);
kono
parents:
diff changeset
3137 else if (DECL_P (t))
kono
parents:
diff changeset
3138 diagnose_declaration_constraints (loc, t, args);
kono
parents:
diff changeset
3139 else
kono
parents:
diff changeset
3140 gcc_unreachable ();
kono
parents:
diff changeset
3141
kono
parents:
diff changeset
3142 /* Note the number of elided failures. */
kono
parents:
diff changeset
3143 int n = undiagnosed_constraint_failures ();
kono
parents:
diff changeset
3144 if (n > 0)
kono
parents:
diff changeset
3145 inform (loc, "... and %d more constraint errors not shown", n);
kono
parents:
diff changeset
3146 }