File: | build/gcc/vec.h |
Warning: | line 815, column 10 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Processing rules for constraints. | |||
2 | Copyright (C) 2013-2021 Free Software Foundation, Inc. | |||
3 | Contributed by Andrew Sutton (andrew.n.sutton@gmail.com) | |||
4 | ||||
5 | This file is part of GCC. | |||
6 | ||||
7 | GCC is free software; you can redistribute it and/or modify | |||
8 | it under the terms of the GNU General Public License as published by | |||
9 | the Free Software Foundation; either version 3, or (at your option) | |||
10 | any later version. | |||
11 | ||||
12 | GCC is distributed in the hope that it will be useful, | |||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
15 | GNU General Public License for more details. | |||
16 | ||||
17 | You should have received a copy of the GNU General Public License | |||
18 | along with GCC; see the file COPYING3. If not see | |||
19 | <http://www.gnu.org/licenses/>. */ | |||
20 | ||||
21 | #include "config.h" | |||
22 | #include "system.h" | |||
23 | #include "coretypes.h" | |||
24 | #include "tm.h" | |||
25 | #include "timevar.h" | |||
26 | #include "hash-set.h" | |||
27 | #include "machmode.h" | |||
28 | #include "vec.h" | |||
29 | #include "double-int.h" | |||
30 | #include "input.h" | |||
31 | #include "alias.h" | |||
32 | #include "symtab.h" | |||
33 | #include "wide-int.h" | |||
34 | #include "inchash.h" | |||
35 | #include "tree.h" | |||
36 | #include "stringpool.h" | |||
37 | #include "attribs.h" | |||
38 | #include "intl.h" | |||
39 | #include "flags.h" | |||
40 | #include "cp-tree.h" | |||
41 | #include "c-family/c-common.h" | |||
42 | #include "c-family/c-objc.h" | |||
43 | #include "cp-objcp-common.h" | |||
44 | #include "tree-inline.h" | |||
45 | #include "decl.h" | |||
46 | #include "toplev.h" | |||
47 | #include "type-utils.h" | |||
48 | ||||
49 | static tree satisfaction_value (tree t); | |||
50 | ||||
51 | /* When we're parsing or substuting a constraint expression, we have slightly | |||
52 | different expression semantics. In particular, we don't want to reduce a | |||
53 | concept-id to a satisfaction value. */ | |||
54 | ||||
55 | processing_constraint_expression_sentinel:: | |||
56 | processing_constraint_expression_sentinel () | |||
57 | { | |||
58 | ++scope_chain->x_processing_constraint; | |||
59 | } | |||
60 | ||||
61 | processing_constraint_expression_sentinel:: | |||
62 | ~processing_constraint_expression_sentinel () | |||
63 | { | |||
64 | --scope_chain->x_processing_constraint; | |||
65 | } | |||
66 | ||||
67 | bool | |||
68 | processing_constraint_expression_p () | |||
69 | { | |||
70 | return scope_chain->x_processing_constraint != 0; | |||
71 | } | |||
72 | ||||
73 | /*--------------------------------------------------------------------------- | |||
74 | Constraint expressions | |||
75 | ---------------------------------------------------------------------------*/ | |||
76 | ||||
77 | /* Information provided to substitution. */ | |||
78 | ||||
79 | struct subst_info | |||
80 | { | |||
81 | subst_info (tsubst_flags_t cmp, tree in) | |||
82 | : complain (cmp), in_decl (in) | |||
83 | { } | |||
84 | ||||
85 | /* True if we should not diagnose errors. */ | |||
86 | bool quiet() const | |||
87 | { | |||
88 | return complain == tf_none; | |||
89 | } | |||
90 | ||||
91 | /* True if we should diagnose errors. */ | |||
92 | bool noisy() const | |||
93 | { | |||
94 | return !quiet (); | |||
95 | } | |||
96 | ||||
97 | tsubst_flags_t complain; | |||
98 | tree in_decl; | |||
99 | }; | |||
100 | ||||
101 | /* Provides additional context for satisfaction. | |||
102 | ||||
103 | The flag noisy() controls whether to diagnose ill-formed satisfaction, | |||
104 | such as the satisfaction value of an atom being non-bool or non-constant. | |||
105 | ||||
106 | The flag diagnose_unsatisfaction_p() controls whether to explain why | |||
107 | a constraint is not satisfied. | |||
108 | ||||
109 | The entrypoints to satisfaction for which we set noisy+unsat are | |||
110 | diagnose_constraints and diagnose_nested_requirement. The entrypoints for | |||
111 | which we set noisy-unsat are the replays inside constraint_satisfaction_value, | |||
112 | evaluate_concept_check and tsubst_nested_requirement. In other entrypoints, | |||
113 | e.g. constraints_satisfied_p, we enter satisfaction quietly (both flags | |||
114 | cleared). */ | |||
115 | ||||
116 | struct sat_info : subst_info | |||
117 | { | |||
118 | sat_info (tsubst_flags_t cmp, tree in, bool diag_unsat = false) | |||
119 | : subst_info (cmp, in), diagnose_unsatisfaction (diag_unsat) | |||
120 | { | |||
121 | if (diagnose_unsatisfaction_p ()) | |||
122 | gcc_checking_assert (noisy ())((void)(!(noisy ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 122, __FUNCTION__), 0 : 0)); | |||
123 | } | |||
124 | ||||
125 | /* True if we should diagnose the cause of satisfaction failure. | |||
126 | Implies noisy(). */ | |||
127 | bool | |||
128 | diagnose_unsatisfaction_p () const | |||
129 | { | |||
130 | return diagnose_unsatisfaction; | |||
131 | } | |||
132 | ||||
133 | bool diagnose_unsatisfaction; | |||
134 | }; | |||
135 | ||||
136 | static tree satisfy_constraint (tree, tree, sat_info); | |||
137 | ||||
138 | /* True if T is known to be some type other than bool. Note that this | |||
139 | is false for dependent types and errors. */ | |||
140 | ||||
141 | static inline bool | |||
142 | known_non_bool_p (tree t) | |||
143 | { | |||
144 | return (t && !WILDCARD_TYPE_P (t)(((enum tree_code) (t)->base.code) == TEMPLATE_TYPE_PARM || ((enum tree_code) (t)->base.code) == TYPENAME_TYPE || ((enum tree_code) (t)->base.code) == TYPEOF_TYPE || ((enum tree_code ) (t)->base.code) == BOUND_TEMPLATE_TEMPLATE_PARM || ((enum tree_code) (t)->base.code) == DECLTYPE_TYPE) && TREE_CODE (t)((enum tree_code) (t)->base.code) != BOOLEAN_TYPE); | |||
145 | } | |||
146 | ||||
147 | static bool | |||
148 | check_constraint_atom (cp_expr expr) | |||
149 | { | |||
150 | if (known_non_bool_p (TREE_TYPE (expr)((contains_struct_check ((expr), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 150, __FUNCTION__))->typed.type))) | |||
151 | { | |||
152 | error_at (expr.get_location (), | |||
153 | "constraint expression does not have type %<bool%>"); | |||
154 | return false; | |||
155 | } | |||
156 | ||||
157 | /* Check that we're using function concepts correctly. */ | |||
158 | if (concept_check_p (expr)) | |||
159 | { | |||
160 | tree id = unpack_concept_check (expr); | |||
161 | tree tmpl = TREE_OPERAND (id, 0)(*((const_cast<tree*> (tree_operand_check ((id), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 161, __FUNCTION__))))); | |||
162 | if (OVL_P (tmpl)(((enum tree_code) (tmpl)->base.code) == FUNCTION_DECL || ( (enum tree_code) (tmpl)->base.code) == OVERLOAD) && TREE_CODE (expr)((enum tree_code) (expr)->base.code) == TEMPLATE_ID_EXPR) | |||
163 | { | |||
164 | error_at (EXPR_LOC_OR_LOC (expr, input_location)((((IS_ADHOC_LOC (((((expr)) && ((tree_code_type[(int ) (((enum tree_code) ((expr))->base.code))]) >= tcc_reference && (tree_code_type[(int) (((enum tree_code) ((expr)) ->base.code))]) <= tcc_expression)) ? (expr)->exp.locus : ((location_t) 0)))) ? get_location_from_adhoc_loc (line_table , ((((expr)) && ((tree_code_type[(int) (((enum tree_code ) ((expr))->base.code))]) >= tcc_reference && ( tree_code_type[(int) (((enum tree_code) ((expr))->base.code ))]) <= tcc_expression)) ? (expr)->exp.locus : ((location_t ) 0))) : (((((expr)) && ((tree_code_type[(int) (((enum tree_code) ((expr))->base.code))]) >= tcc_reference && (tree_code_type[(int) (((enum tree_code) ((expr))->base.code ))]) <= tcc_expression)) ? (expr)->exp.locus : ((location_t ) 0)))) != ((location_t) 0)) ? (expr)->exp.locus : (input_location )), | |||
165 | "function concept must be called"); | |||
166 | return false; | |||
167 | } | |||
168 | } | |||
169 | ||||
170 | return true; | |||
171 | } | |||
172 | ||||
173 | static bool | |||
174 | check_constraint_operands (location_t, cp_expr lhs, cp_expr rhs) | |||
175 | { | |||
176 | return check_constraint_atom (lhs) && check_constraint_atom (rhs); | |||
177 | } | |||
178 | ||||
179 | /* Validate the semantic properties of the constraint expression. */ | |||
180 | ||||
181 | static cp_expr | |||
182 | finish_constraint_binary_op (location_t loc, | |||
183 | tree_code code, | |||
184 | cp_expr lhs, | |||
185 | cp_expr rhs) | |||
186 | { | |||
187 | gcc_assert (processing_constraint_expression_p ())((void)(!(processing_constraint_expression_p ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 187, __FUNCTION__), 0 : 0)); | |||
188 | if (lhs == error_mark_nodeglobal_trees[TI_ERROR_MARK] || rhs == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
189 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
190 | if (!check_constraint_operands (loc, lhs, rhs)) | |||
191 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
192 | tree overload; | |||
193 | cp_expr expr = build_x_binary_op (loc, code, | |||
194 | lhs, TREE_CODE (lhs)((enum tree_code) (lhs)->base.code), | |||
195 | rhs, TREE_CODE (rhs)((enum tree_code) (rhs)->base.code), | |||
196 | &overload, tf_none); | |||
197 | /* When either operand is dependent, the overload set may be non-empty. */ | |||
198 | if (expr == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
199 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
200 | expr.set_location (loc); | |||
201 | expr.set_range (lhs.get_start (), rhs.get_finish ()); | |||
202 | return expr; | |||
203 | } | |||
204 | ||||
205 | cp_expr | |||
206 | finish_constraint_or_expr (location_t loc, cp_expr lhs, cp_expr rhs) | |||
207 | { | |||
208 | return finish_constraint_binary_op (loc, TRUTH_ORIF_EXPR, lhs, rhs); | |||
209 | } | |||
210 | ||||
211 | cp_expr | |||
212 | finish_constraint_and_expr (location_t loc, cp_expr lhs, cp_expr rhs) | |||
213 | { | |||
214 | return finish_constraint_binary_op (loc, TRUTH_ANDIF_EXPR, lhs, rhs); | |||
215 | } | |||
216 | ||||
217 | cp_expr | |||
218 | finish_constraint_primary_expr (cp_expr expr) | |||
219 | { | |||
220 | if (expr == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
221 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
222 | if (!check_constraint_atom (expr)) | |||
223 | return cp_expr (error_mark_nodeglobal_trees[TI_ERROR_MARK], expr.get_location ()); | |||
224 | return expr; | |||
225 | } | |||
226 | ||||
227 | /* Combine two constraint-expressions with a logical-and. */ | |||
228 | ||||
229 | tree | |||
230 | combine_constraint_expressions (tree lhs, tree rhs) | |||
231 | { | |||
232 | processing_constraint_expression_sentinel pce; | |||
233 | if (!lhs) | |||
234 | return rhs; | |||
235 | if (!rhs) | |||
236 | return lhs; | |||
237 | return finish_constraint_and_expr (input_location, lhs, rhs); | |||
238 | } | |||
239 | ||||
240 | /* Extract the template-id from a concept check. For standard and variable | |||
241 | checks, this is simply T. For function concept checks, this is the | |||
242 | called function. */ | |||
243 | ||||
244 | tree | |||
245 | unpack_concept_check (tree t) | |||
246 | { | |||
247 | gcc_assert (concept_check_p (t))((void)(!(concept_check_p (t)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 247, __FUNCTION__), 0 : 0)); | |||
248 | ||||
249 | if (TREE_CODE (t)((enum tree_code) (t)->base.code) == CALL_EXPR) | |||
250 | t = CALL_EXPR_FN (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 250, __FUNCTION__, (CALL_EXPR)))), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 250, __FUNCTION__))))); | |||
251 | ||||
252 | gcc_assert (TREE_CODE (t) == TEMPLATE_ID_EXPR)((void)(!(((enum tree_code) (t)->base.code) == TEMPLATE_ID_EXPR ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 252, __FUNCTION__), 0 : 0)); | |||
253 | return t; | |||
254 | } | |||
255 | ||||
256 | /* Extract the TEMPLATE_DECL from a concept check. */ | |||
257 | ||||
258 | tree | |||
259 | get_concept_check_template (tree t) | |||
260 | { | |||
261 | tree id = unpack_concept_check (t); | |||
262 | tree tmpl = TREE_OPERAND (id, 0)(*((const_cast<tree*> (tree_operand_check ((id), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 262, __FUNCTION__))))); | |||
263 | if (OVL_P (tmpl)(((enum tree_code) (tmpl)->base.code) == FUNCTION_DECL || ( (enum tree_code) (tmpl)->base.code) == OVERLOAD)) | |||
264 | tmpl = OVL_FIRST (tmpl)ovl_first (tmpl); | |||
265 | return tmpl; | |||
266 | } | |||
267 | ||||
268 | /* Returns true if any of the arguments in the template argument list is | |||
269 | a wildcard or wildcard pack. */ | |||
270 | ||||
271 | bool | |||
272 | contains_wildcard_p (tree args) | |||
273 | { | |||
274 | for (int i = 0; i < TREE_VEC_LENGTH (args)((tree_check ((args), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 274, __FUNCTION__, (TREE_VEC)))->base.u.length); ++i) | |||
275 | { | |||
276 | tree arg = TREE_VEC_ELT (args, i)(*((const_cast<tree *> (tree_vec_elt_check ((args), (i) , "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 276, __FUNCTION__))))); | |||
277 | if (TREE_CODE (arg)((enum tree_code) (arg)->base.code) == WILDCARD_DECL) | |||
278 | return true; | |||
279 | } | |||
280 | return false; | |||
281 | } | |||
282 | ||||
283 | /*--------------------------------------------------------------------------- | |||
284 | Resolution of qualified concept names | |||
285 | ---------------------------------------------------------------------------*/ | |||
286 | ||||
287 | /* This facility is used to resolve constraint checks from requirement | |||
288 | expressions. A constraint check is a call to a function template declared | |||
289 | with the keyword 'concept'. | |||
290 | ||||
291 | The result of resolution is a pair (a TREE_LIST) whose value is the | |||
292 | matched declaration, and whose purpose contains the coerced template | |||
293 | arguments that can be substituted into the call. */ | |||
294 | ||||
295 | /* Given an overload set OVL, try to find a unique definition that can be | |||
296 | instantiated by the template arguments ARGS. | |||
297 | ||||
298 | This function is not called for arbitrary call expressions. In particular, | |||
299 | the call expression must be written with explicit template arguments | |||
300 | and no function arguments. For example: | |||
301 | ||||
302 | f<T, U>() | |||
303 | ||||
304 | If a single match is found, this returns a TREE_LIST whose VALUE | |||
305 | is the constraint function (not the template), and its PURPOSE is | |||
306 | the complete set of arguments substituted into the parameter list. */ | |||
307 | ||||
308 | static tree | |||
309 | resolve_function_concept_overload (tree ovl, tree args) | |||
310 | { | |||
311 | int nerrs = 0; | |||
312 | tree cands = NULL_TREE(tree) __null; | |||
313 | for (lkp_iterator iter (ovl); iter; ++iter) | |||
314 | { | |||
315 | tree tmpl = *iter; | |||
316 | if (TREE_CODE (tmpl)((enum tree_code) (tmpl)->base.code) != TEMPLATE_DECL) | |||
317 | continue; | |||
318 | ||||
319 | /* Don't try to deduce checks for non-concepts. We often end up trying | |||
320 | to resolve constraints in functional casts as part of a | |||
321 | postfix-expression. We can save time and headaches by not | |||
322 | instantiating those declarations. | |||
323 | ||||
324 | NOTE: This masks a potential error, caused by instantiating | |||
325 | non-deduced contexts using placeholder arguments. */ | |||
326 | tree fn = DECL_TEMPLATE_RESULT (tmpl)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((tmpl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 326, __FUNCTION__, (TEMPLATE_DECL))))))))->result; | |||
327 | if (DECL_ARGUMENTS (fn)((tree_check ((fn), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 327, __FUNCTION__, (FUNCTION_DECL)))->function_decl.arguments )) | |||
328 | continue; | |||
329 | if (!DECL_DECLARED_CONCEPT_P (fn)(((contains_struct_check ((fn), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 329, __FUNCTION__))->decl_common.lang_specific)->u.base .concept_p)) | |||
330 | continue; | |||
331 | ||||
332 | /* Remember the candidate if we can deduce a substitution. */ | |||
333 | ++processing_template_declscope_chain->x_processing_template_decl; | |||
334 | tree parms = TREE_VALUE (DECL_TEMPLATE_PARMS (tmpl))((tree_check ((((struct tree_template_decl *)(const_cast<union tree_node *> ((((tree_check ((tmpl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 334, __FUNCTION__, (TEMPLATE_DECL))))))))->arguments), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 334, __FUNCTION__, (TREE_LIST)))->list.value); | |||
335 | if (tree subst = coerce_template_parms (parms, args, tmpl)) | |||
336 | { | |||
337 | if (subst == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
338 | ++nerrs; | |||
339 | else | |||
340 | cands = tree_cons (subst, fn, cands); | |||
341 | } | |||
342 | --processing_template_declscope_chain->x_processing_template_decl; | |||
343 | } | |||
344 | ||||
345 | if (!cands) | |||
346 | /* We either had no candidates or failed deductions. */ | |||
347 | return nerrs ? error_mark_nodeglobal_trees[TI_ERROR_MARK] : NULL_TREE(tree) __null; | |||
348 | else if (TREE_CHAIN (cands)((contains_struct_check ((cands), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 348, __FUNCTION__))->common.chain)) | |||
349 | /* There are multiple candidates. */ | |||
350 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
351 | ||||
352 | return cands; | |||
353 | } | |||
354 | ||||
355 | /* Determine if the call expression CALL is a constraint check, and | |||
356 | return the concept declaration and arguments being checked. If CALL | |||
357 | does not denote a constraint check, return NULL. */ | |||
358 | ||||
359 | tree | |||
360 | resolve_function_concept_check (tree call) | |||
361 | { | |||
362 | gcc_assert (TREE_CODE (call) == CALL_EXPR)((void)(!(((enum tree_code) (call)->base.code) == CALL_EXPR ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 362, __FUNCTION__), 0 : 0)); | |||
363 | ||||
364 | /* A constraint check must be only a template-id expression. | |||
365 | If it's a call to a base-link, its function(s) should be a | |||
366 | template-id expression. If this is not a template-id, then | |||
367 | it cannot be a concept-check. */ | |||
368 | tree target = CALL_EXPR_FN (call)(*((const_cast<tree*> (tree_operand_check (((tree_check ((call), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 368, __FUNCTION__, (CALL_EXPR)))), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 368, __FUNCTION__))))); | |||
369 | if (BASELINK_P (target)(((enum tree_code) (target)->base.code) == BASELINK)) | |||
370 | target = BASELINK_FUNCTIONS (target)(((struct tree_baselink*) (tree_check ((target), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 370, __FUNCTION__, (BASELINK))))->functions); | |||
371 | if (TREE_CODE (target)((enum tree_code) (target)->base.code) != TEMPLATE_ID_EXPR) | |||
372 | return NULL_TREE(tree) __null; | |||
373 | ||||
374 | /* Get the overload set and template arguments and try to | |||
375 | resolve the target. */ | |||
376 | tree ovl = TREE_OPERAND (target, 0)(*((const_cast<tree*> (tree_operand_check ((target), (0 ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 376, __FUNCTION__))))); | |||
377 | ||||
378 | /* This is a function call of a variable concept... ill-formed. */ | |||
379 | if (TREE_CODE (ovl)((enum tree_code) (ovl)->base.code) == TEMPLATE_DECL) | |||
380 | { | |||
381 | error_at (location_of (call), | |||
382 | "function call of variable concept %qE", call); | |||
383 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
384 | } | |||
385 | ||||
386 | tree args = TREE_OPERAND (target, 1)(*((const_cast<tree*> (tree_operand_check ((target), (1 ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 386, __FUNCTION__))))); | |||
387 | return resolve_function_concept_overload (ovl, args); | |||
388 | } | |||
389 | ||||
390 | /* Returns a pair containing the checked concept and its associated | |||
391 | prototype parameter. The result is a TREE_LIST whose TREE_VALUE | |||
392 | is the concept (non-template) and whose TREE_PURPOSE contains | |||
393 | the converted template arguments, including the deduced prototype | |||
394 | parameter (in position 0). */ | |||
395 | ||||
396 | tree | |||
397 | resolve_concept_check (tree check) | |||
398 | { | |||
399 | gcc_assert (concept_check_p (check))((void)(!(concept_check_p (check)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 399, __FUNCTION__), 0 : 0)); | |||
400 | tree id = unpack_concept_check (check); | |||
401 | tree tmpl = TREE_OPERAND (id, 0)(*((const_cast<tree*> (tree_operand_check ((id), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 401, __FUNCTION__))))); | |||
402 | ||||
403 | /* If this is an overloaded function concept, perform overload | |||
404 | resolution (this only happens when deducing prototype parameters | |||
405 | and template introductions). */ | |||
406 | if (TREE_CODE (tmpl)((enum tree_code) (tmpl)->base.code) == OVERLOAD) | |||
407 | { | |||
408 | if (OVL_CHAIN (tmpl)(((struct tree_overload*)(tree_check ((tmpl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 408, __FUNCTION__, (OVERLOAD))))->common.chain)) | |||
409 | return resolve_function_concept_check (check); | |||
410 | tmpl = OVL_FIRST (tmpl)ovl_first (tmpl); | |||
411 | } | |||
412 | ||||
413 | tree args = TREE_OPERAND (id, 1)(*((const_cast<tree*> (tree_operand_check ((id), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 413, __FUNCTION__))))); | |||
414 | tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl))((tree_check ((((struct tree_template_decl *)(const_cast<union tree_node *> ((((tree_check ((tmpl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 414, __FUNCTION__, (TEMPLATE_DECL))))))))->arguments), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 414, __FUNCTION__, (TREE_LIST)))->list.value); | |||
415 | ++processing_template_declscope_chain->x_processing_template_decl; | |||
416 | tree result = coerce_template_parms (parms, args, tmpl); | |||
417 | --processing_template_declscope_chain->x_processing_template_decl; | |||
418 | if (result == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
419 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
420 | return build_tree_list (result, DECL_TEMPLATE_RESULT (tmpl)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((tmpl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 420, __FUNCTION__, (TEMPLATE_DECL))))))))->result); | |||
421 | } | |||
422 | ||||
423 | /* Given a call expression or template-id expression to a concept EXPR | |||
424 | possibly including a wildcard, deduce the concept being checked and | |||
425 | the prototype parameter. Returns true if the constraint and prototype | |||
426 | can be deduced and false otherwise. Note that the CHECK and PROTO | |||
427 | arguments are set to NULL_TREE if this returns false. */ | |||
428 | ||||
429 | bool | |||
430 | deduce_constrained_parameter (tree expr, tree& check, tree& proto) | |||
431 | { | |||
432 | tree info = resolve_concept_check (expr); | |||
433 | if (info && info != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
434 | { | |||
435 | check = TREE_VALUE (info)((tree_check ((info), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 435, __FUNCTION__, (TREE_LIST)))->list.value); | |||
436 | tree arg = TREE_VEC_ELT (TREE_PURPOSE (info), 0)(*((const_cast<tree *> (tree_vec_elt_check ((((tree_check ((info), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 436, __FUNCTION__, (TREE_LIST)))->list.purpose)), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 436, __FUNCTION__))))); | |||
437 | if (ARGUMENT_PACK_P (arg)(((enum tree_code) (arg)->base.code) == TYPE_ARGUMENT_PACK || ((enum tree_code) (arg)->base.code) == NONTYPE_ARGUMENT_PACK )) | |||
438 | arg = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg), 0)(*((const_cast<tree *> (tree_vec_elt_check (((((enum tree_code ) (arg)->base.code) == TYPE_ARGUMENT_PACK? ((contains_struct_check ((arg), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 438, __FUNCTION__))->typed.type) : (*((const_cast<tree *> (tree_operand_check ((arg), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 438, __FUNCTION__))))))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 438, __FUNCTION__))))); | |||
439 | proto = TREE_TYPE (arg)((contains_struct_check ((arg), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 439, __FUNCTION__))->typed.type); | |||
440 | return true; | |||
441 | } | |||
442 | ||||
443 | check = proto = NULL_TREE(tree) __null; | |||
444 | return false; | |||
445 | } | |||
446 | ||||
447 | /* Given a call expression or template-id expression to a concept, EXPR, | |||
448 | deduce the concept being checked and return the template arguments. | |||
449 | Returns NULL_TREE if deduction fails. */ | |||
450 | static tree | |||
451 | deduce_concept_introduction (tree check) | |||
452 | { | |||
453 | tree info = resolve_concept_check (check); | |||
454 | if (info && info != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
455 | return TREE_PURPOSE (info)((tree_check ((info), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 455, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
456 | return NULL_TREE(tree) __null; | |||
457 | } | |||
458 | ||||
459 | /* Build a constrained placeholder type where SPEC is a type-constraint. | |||
460 | SPEC can be anything were concept_definition_p is true. | |||
461 | ||||
462 | If DECLTYPE_P is true, then the placeholder is decltype(auto). | |||
463 | ||||
464 | Returns a pair whose FIRST is the concept being checked and whose | |||
465 | SECOND is the prototype parameter. */ | |||
466 | ||||
467 | tree_pair | |||
468 | finish_type_constraints (tree spec, tree args, tsubst_flags_t complain) | |||
469 | { | |||
470 | gcc_assert (concept_definition_p (spec))((void)(!(concept_definition_p (spec)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 470, __FUNCTION__), 0 : 0)); | |||
471 | ||||
472 | /* Build an initial concept check. */ | |||
473 | tree check = build_type_constraint (spec, args, complain); | |||
474 | if (check == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
475 | return std::make_pair (error_mark_nodeglobal_trees[TI_ERROR_MARK], NULL_TREE(tree) __null); | |||
476 | ||||
477 | /* Extract the concept and prototype parameter from the check. */ | |||
478 | tree con; | |||
479 | tree proto; | |||
480 | if (!deduce_constrained_parameter (check, con, proto)) | |||
481 | return std::make_pair (error_mark_nodeglobal_trees[TI_ERROR_MARK], NULL_TREE(tree) __null); | |||
482 | ||||
483 | return std::make_pair (con, proto); | |||
484 | } | |||
485 | ||||
486 | /*--------------------------------------------------------------------------- | |||
487 | Expansion of concept definitions | |||
488 | ---------------------------------------------------------------------------*/ | |||
489 | ||||
490 | /* Returns the expression of a function concept. */ | |||
491 | ||||
492 | static tree | |||
493 | get_returned_expression (tree fn) | |||
494 | { | |||
495 | /* Extract the body of the function minus the return expression. */ | |||
496 | tree body = DECL_SAVED_TREE (fn)((tree_check ((fn), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 496, __FUNCTION__, (FUNCTION_DECL)))->function_decl.saved_tree ); | |||
497 | if (!body) | |||
498 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
499 | if (TREE_CODE (body)((enum tree_code) (body)->base.code) == BIND_EXPR) | |||
500 | body = BIND_EXPR_BODY (body)((*((const_cast<tree*> (tree_operand_check (((tree_check ((body), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 500, __FUNCTION__, (BIND_EXPR)))), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 500, __FUNCTION__)))))); | |||
501 | if (TREE_CODE (body)((enum tree_code) (body)->base.code) != RETURN_EXPR) | |||
502 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
503 | ||||
504 | return TREE_OPERAND (body, 0)(*((const_cast<tree*> (tree_operand_check ((body), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 504, __FUNCTION__))))); | |||
505 | } | |||
506 | ||||
507 | /* Returns the initializer of a variable concept. */ | |||
508 | ||||
509 | static tree | |||
510 | get_variable_initializer (tree var) | |||
511 | { | |||
512 | tree init = DECL_INITIAL (var)((contains_struct_check ((var), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 512, __FUNCTION__))->decl_common.initial); | |||
513 | if (!init) | |||
514 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
515 | if (BRACE_ENCLOSED_INITIALIZER_P (init)(((enum tree_code) (init)->base.code) == CONSTRUCTOR && ((contains_struct_check ((init), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 515, __FUNCTION__))->typed.type) == cp_global_trees[CPTI_INIT_LIST_TYPE ]) | |||
516 | && CONSTRUCTOR_NELTS (init)(vec_safe_length (((tree_check ((init), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 516, __FUNCTION__, (CONSTRUCTOR)))->constructor.elts))) == 1) | |||
517 | init = CONSTRUCTOR_ELT (init, 0)(&(*((tree_check ((init), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 517, __FUNCTION__, (CONSTRUCTOR)))->constructor.elts))[0 ])->value; | |||
518 | return init; | |||
519 | } | |||
520 | ||||
521 | /* Returns the definition of a variable or function concept. */ | |||
522 | ||||
523 | static tree | |||
524 | get_concept_definition (tree decl) | |||
525 | { | |||
526 | if (TREE_CODE (decl)((enum tree_code) (decl)->base.code) == OVERLOAD) | |||
527 | decl = OVL_FIRST (decl)ovl_first (decl); | |||
528 | ||||
529 | if (TREE_CODE (decl)((enum tree_code) (decl)->base.code) == TEMPLATE_DECL) | |||
530 | decl = DECL_TEMPLATE_RESULT (decl)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((decl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 530, __FUNCTION__, (TEMPLATE_DECL))))))))->result; | |||
531 | ||||
532 | if (TREE_CODE (decl)((enum tree_code) (decl)->base.code) == CONCEPT_DECL) | |||
533 | return DECL_INITIAL (decl)((contains_struct_check ((decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 533, __FUNCTION__))->decl_common.initial); | |||
534 | if (VAR_P (decl)(((enum tree_code) (decl)->base.code) == VAR_DECL)) | |||
535 | return get_variable_initializer (decl); | |||
536 | if (TREE_CODE (decl)((enum tree_code) (decl)->base.code) == FUNCTION_DECL) | |||
537 | return get_returned_expression (decl); | |||
538 | gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 538, __FUNCTION__)); | |||
539 | } | |||
540 | ||||
541 | /*--------------------------------------------------------------------------- | |||
542 | Normalization of expressions | |||
543 | ||||
544 | This set of functions will transform an expression into a constraint | |||
545 | in a sequence of steps. | |||
546 | ---------------------------------------------------------------------------*/ | |||
547 | ||||
548 | void | |||
549 | debug_parameter_mapping (tree map) | |||
550 | { | |||
551 | for (tree p = map; p; p = TREE_CHAIN (p)((contains_struct_check ((p), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 551, __FUNCTION__))->common.chain)) | |||
552 | { | |||
553 | tree parm = TREE_VALUE (p)((tree_check ((p), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 553, __FUNCTION__, (TREE_LIST)))->list.value); | |||
554 | tree arg = TREE_PURPOSE (p)((tree_check ((p), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 554, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
555 | if (TYPE_P (parm)(tree_code_type[(int) (((enum tree_code) (parm)->base.code ))] == tcc_type)) | |||
556 | verbatim ("MAP %qD TO %qT", TEMPLATE_TYPE_DECL (parm)((((template_parm_index*)(tree_check (((((tree_class_check (( (tree_check3 (((parm)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 556, __FUNCTION__, (TEMPLATE_TYPE_PARM), (TEMPLATE_TEMPLATE_PARM ), (BOUND_TEMPLATE_TEMPLATE_PARM)))), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 556, __FUNCTION__))->type_non_common.values))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 556, __FUNCTION__, (TEMPLATE_PARM_INDEX))))->decl)), arg); | |||
557 | else | |||
558 | verbatim ("MAP %qD TO %qE", TEMPLATE_PARM_DECL (parm)(((template_parm_index*)(tree_check ((parm), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 558, __FUNCTION__, (TEMPLATE_PARM_INDEX))))->decl), arg); | |||
559 | // debug_tree (parm); | |||
560 | // debug_tree (arg); | |||
561 | } | |||
562 | } | |||
563 | ||||
564 | void | |||
565 | debug_argument_list (tree args) | |||
566 | { | |||
567 | for (int i = 0; i < TREE_VEC_LENGTH (args)((tree_check ((args), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 567, __FUNCTION__, (TREE_VEC)))->base.u.length); ++i) | |||
568 | { | |||
569 | tree arg = TREE_VEC_ELT (args, i)(*((const_cast<tree *> (tree_vec_elt_check ((args), (i) , "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 569, __FUNCTION__))))); | |||
570 | if (TYPE_P (arg)(tree_code_type[(int) (((enum tree_code) (arg)->base.code) )] == tcc_type)) | |||
571 | verbatim ("argument %qT", arg); | |||
572 | else | |||
573 | verbatim ("argument %qE", arg); | |||
574 | } | |||
575 | } | |||
576 | ||||
577 | /* Associate each parameter in PARMS with its corresponding template | |||
578 | argument in ARGS. */ | |||
579 | ||||
580 | static tree | |||
581 | map_arguments (tree parms, tree args) | |||
582 | { | |||
583 | for (tree p = parms; p; p = TREE_CHAIN (p)((contains_struct_check ((p), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 583, __FUNCTION__))->common.chain)) | |||
584 | if (args) | |||
585 | { | |||
586 | int level; | |||
587 | int index; | |||
588 | template_parm_level_and_index (TREE_VALUE (p)((tree_check ((p), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 588, __FUNCTION__, (TREE_LIST)))->list.value), &level, &index); | |||
589 | TREE_PURPOSE (p)((tree_check ((p), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 589, __FUNCTION__, (TREE_LIST)))->list.purpose) = TMPL_ARG (args, level, index)((*((const_cast<tree *> (tree_vec_elt_check ((((args && ((tree_check ((args), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 589, __FUNCTION__, (TREE_VEC)))->base.u.length) && (*((const_cast<tree *> (tree_vec_elt_check ((args), (0 ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 589, __FUNCTION__))))) && ((enum tree_code) ((*((const_cast <tree *> (tree_vec_elt_check ((args), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 589, __FUNCTION__))))))->base.code) == TREE_VEC) ? (*((const_cast <tree *> (tree_vec_elt_check ((args), ((level) - 1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 589, __FUNCTION__))))) : (args))), (index), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 589, __FUNCTION__)))))); | |||
590 | } | |||
591 | else | |||
592 | TREE_PURPOSE (p)((tree_check ((p), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 592, __FUNCTION__, (TREE_LIST)))->list.purpose) = template_parm_to_arg (p); | |||
593 | ||||
594 | return parms; | |||
595 | } | |||
596 | ||||
597 | /* Build the parameter mapping for EXPR using ARGS. */ | |||
598 | ||||
599 | static tree | |||
600 | build_parameter_mapping (tree expr, tree args, tree decl) | |||
601 | { | |||
602 | tree ctx_parms = NULL_TREE(tree) __null; | |||
603 | if (decl) | |||
604 | { | |||
605 | gcc_assert (TREE_CODE (decl) == TEMPLATE_DECL)((void)(!(((enum tree_code) (decl)->base.code) == TEMPLATE_DECL ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 605, __FUNCTION__), 0 : 0)); | |||
606 | ctx_parms = DECL_TEMPLATE_PARMS (decl)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((decl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 606, __FUNCTION__, (TEMPLATE_DECL))))))))->arguments; | |||
607 | } | |||
608 | else if (current_template_parmsscope_chain->template_parms) | |||
609 | { | |||
610 | /* TODO: This should probably be the only case, but because the | |||
611 | point of declaration of concepts is currently set after the | |||
612 | initializer, the template parameter lists are not available | |||
613 | when normalizing concept definitions, hence the case above. */ | |||
614 | ctx_parms = current_template_parmsscope_chain->template_parms; | |||
615 | } | |||
616 | ||||
617 | tree parms = find_template_parameters (expr, ctx_parms); | |||
618 | tree map = map_arguments (parms, args); | |||
619 | return map; | |||
620 | } | |||
621 | ||||
622 | /* True if the parameter mappings of two atomic constraints formed | |||
623 | from the same expression are equivalent. */ | |||
624 | ||||
625 | static bool | |||
626 | parameter_mapping_equivalent_p (tree t1, tree t2) | |||
627 | { | |||
628 | tree map1 = ATOMIC_CONSTR_MAP (t1)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 628, __FUNCTION__, (ATOMIC_CONSTR)))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 628, __FUNCTION__))))); | |||
629 | tree map2 = ATOMIC_CONSTR_MAP (t2)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t2), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 629, __FUNCTION__, (ATOMIC_CONSTR)))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 629, __FUNCTION__))))); | |||
630 | while (map1 && map2) | |||
631 | { | |||
632 | gcc_checking_assert (TREE_VALUE (map1) == TREE_VALUE (map2))((void)(!(((tree_check ((map1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 632, __FUNCTION__, (TREE_LIST)))->list.value) == ((tree_check ((map2), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 632, __FUNCTION__, (TREE_LIST)))->list.value)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 632, __FUNCTION__), 0 : 0)); | |||
633 | tree arg1 = TREE_PURPOSE (map1)((tree_check ((map1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 633, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
634 | tree arg2 = TREE_PURPOSE (map2)((tree_check ((map2), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 634, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
635 | if (!template_args_equal (arg1, arg2)) | |||
636 | return false; | |||
637 | map1 = TREE_CHAIN (map1)((contains_struct_check ((map1), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 637, __FUNCTION__))->common.chain); | |||
638 | map2 = TREE_CHAIN (map2)((contains_struct_check ((map2), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 638, __FUNCTION__))->common.chain); | |||
639 | } | |||
640 | gcc_checking_assert (!map1 && !map2)((void)(!(!map1 && !map2) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 640, __FUNCTION__), 0 : 0)); | |||
641 | return true; | |||
642 | } | |||
643 | ||||
644 | /* Provides additional context for normalization. */ | |||
645 | ||||
646 | struct norm_info : subst_info | |||
647 | { | |||
648 | explicit norm_info (tsubst_flags_t complain) | |||
649 | : subst_info (tf_warning_or_error | complain, NULL_TREE(tree) __null), | |||
650 | context() | |||
651 | {} | |||
652 | ||||
653 | /* Construct a top-level context for DECL. */ | |||
654 | ||||
655 | norm_info (tree in_decl, tsubst_flags_t complain) | |||
656 | : subst_info (tf_warning_or_error | complain, in_decl), | |||
657 | context (make_context (in_decl)), | |||
658 | orig_decl (in_decl) | |||
659 | {} | |||
660 | ||||
661 | bool generate_diagnostics() const | |||
662 | { | |||
663 | return complain & tf_norm; | |||
664 | } | |||
665 | ||||
666 | tree make_context(tree in_decl) | |||
667 | { | |||
668 | if (generate_diagnostics ()) | |||
669 | return build_tree_list (NULL_TREE(tree) __null, in_decl); | |||
670 | return NULL_TREE(tree) __null; | |||
671 | } | |||
672 | ||||
673 | void update_context(tree expr, tree args) | |||
674 | { | |||
675 | if (generate_diagnostics ()) | |||
676 | { | |||
677 | tree map = build_parameter_mapping (expr, args, in_decl); | |||
678 | context = tree_cons (map, expr, context); | |||
679 | } | |||
680 | in_decl = get_concept_check_template (expr); | |||
681 | } | |||
682 | ||||
683 | /* Provides information about the source of a constraint. This is a | |||
684 | TREE_LIST whose VALUE is either a concept check or a constrained | |||
685 | declaration. The PURPOSE, for concept checks is a parameter mapping | |||
686 | for that check. */ | |||
687 | ||||
688 | tree context; | |||
689 | ||||
690 | /* The declaration whose constraints we're normalizing. The targets | |||
691 | of the parameter mapping of each atom will be in terms of the | |||
692 | template parameters of ORIG_DECL. */ | |||
693 | ||||
694 | tree orig_decl = NULL_TREE(tree) __null; | |||
695 | }; | |||
696 | ||||
697 | static tree normalize_expression (tree, tree, norm_info); | |||
698 | ||||
699 | /* Transform a logical-or or logical-and expression into either | |||
700 | a conjunction or disjunction. */ | |||
701 | ||||
702 | static tree | |||
703 | normalize_logical_operation (tree t, tree args, tree_code c, norm_info info) | |||
704 | { | |||
705 | tree t0 = normalize_expression (TREE_OPERAND (t, 0)(*((const_cast<tree*> (tree_operand_check ((t), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 705, __FUNCTION__))))), args, info); | |||
706 | tree t1 = normalize_expression (TREE_OPERAND (t, 1)(*((const_cast<tree*> (tree_operand_check ((t), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 706, __FUNCTION__))))), args, info); | |||
707 | ||||
708 | /* Build a new info object for the constraint. */ | |||
709 | tree ci = info.generate_diagnostics() | |||
710 | ? build_tree_list (t, info.context) | |||
711 | : NULL_TREE(tree) __null; | |||
712 | ||||
713 | return build2 (c, ci, t0, t1); | |||
714 | } | |||
715 | ||||
716 | static tree | |||
717 | normalize_concept_check (tree check, tree args, norm_info info) | |||
718 | { | |||
719 | tree id = unpack_concept_check (check); | |||
720 | tree tmpl = TREE_OPERAND (id, 0)(*((const_cast<tree*> (tree_operand_check ((id), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 720, __FUNCTION__))))); | |||
721 | tree targs = TREE_OPERAND (id, 1)(*((const_cast<tree*> (tree_operand_check ((id), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 721, __FUNCTION__))))); | |||
722 | ||||
723 | /* A function concept is wrapped in an overload. */ | |||
724 | if (TREE_CODE (tmpl)((enum tree_code) (tmpl)->base.code) == OVERLOAD) | |||
725 | { | |||
726 | /* TODO: Can we diagnose this error during parsing? */ | |||
727 | if (TREE_CODE (check)((enum tree_code) (check)->base.code) == TEMPLATE_ID_EXPR) | |||
728 | error_at (EXPR_LOC_OR_LOC (check, input_location)((((IS_ADHOC_LOC (((((check)) && ((tree_code_type[(int ) (((enum tree_code) ((check))->base.code))]) >= tcc_reference && (tree_code_type[(int) (((enum tree_code) ((check) )->base.code))]) <= tcc_expression)) ? (check)->exp. locus : ((location_t) 0)))) ? get_location_from_adhoc_loc (line_table , ((((check)) && ((tree_code_type[(int) (((enum tree_code ) ((check))->base.code))]) >= tcc_reference && ( tree_code_type[(int) (((enum tree_code) ((check))->base.code ))]) <= tcc_expression)) ? (check)->exp.locus : ((location_t ) 0))) : (((((check)) && ((tree_code_type[(int) (((enum tree_code) ((check))->base.code))]) >= tcc_reference && (tree_code_type[(int) (((enum tree_code) ((check))->base. code))]) <= tcc_expression)) ? (check)->exp.locus : ((location_t ) 0)))) != ((location_t) 0)) ? (check)->exp.locus : (input_location )), | |||
729 | "function concept must be called"); | |||
730 | tmpl = OVL_FIRST (tmpl)ovl_first (tmpl); | |||
731 | } | |||
732 | ||||
733 | /* Substitute through the arguments of the concept check. */ | |||
734 | if (args) | |||
735 | targs = tsubst_template_args (targs, args, info.complain, info.in_decl); | |||
736 | if (targs == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
737 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
738 | ||||
739 | /* Build the substitution for the concept definition. */ | |||
740 | tree parms = TREE_VALUE (DECL_TEMPLATE_PARMS (tmpl))((tree_check ((((struct tree_template_decl *)(const_cast<union tree_node *> ((((tree_check ((tmpl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 740, __FUNCTION__, (TEMPLATE_DECL))))))))->arguments), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 740, __FUNCTION__, (TREE_LIST)))->list.value); | |||
741 | /* Turn on template processing; coercing non-type template arguments | |||
742 | will automatically assume they're non-dependent. */ | |||
743 | ++processing_template_declscope_chain->x_processing_template_decl; | |||
744 | tree subst = coerce_template_parms (parms, targs, tmpl); | |||
745 | --processing_template_declscope_chain->x_processing_template_decl; | |||
746 | if (subst == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
747 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
748 | ||||
749 | /* The concept may have been ill-formed. */ | |||
750 | tree def = get_concept_definition (DECL_TEMPLATE_RESULT (tmpl)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((tmpl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 750, __FUNCTION__, (TEMPLATE_DECL))))))))->result); | |||
751 | if (def == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
752 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
753 | ||||
754 | info.update_context (check, args); | |||
755 | return normalize_expression (def, subst, info); | |||
756 | } | |||
757 | ||||
758 | /* Used by normalize_atom to cache ATOMIC_CONSTRs. */ | |||
759 | ||||
760 | static GTY((deletable)) hash_table<atom_hasher> *atom_cache; | |||
761 | ||||
762 | /* The normal form of an atom depends on the expression. The normal | |||
763 | form of a function call to a function concept is a check constraint | |||
764 | for that concept. The normal form of a reference to a variable | |||
765 | concept is a check constraint for that concept. Otherwise, the | |||
766 | constraint is a predicate constraint. */ | |||
767 | ||||
768 | static tree | |||
769 | normalize_atom (tree t, tree args, norm_info info) | |||
770 | { | |||
771 | /* Concept checks are not atomic. */ | |||
772 | if (concept_check_p (t)) | |||
773 | return normalize_concept_check (t, args, info); | |||
774 | ||||
775 | /* Build the parameter mapping for the atom. */ | |||
776 | tree map = build_parameter_mapping (t, args, info.in_decl); | |||
777 | ||||
778 | /* Build a new info object for the atom. */ | |||
779 | tree ci = build_tree_list (t, info.context); | |||
780 | ||||
781 | tree atom = build1 (ATOMIC_CONSTR, ci, map); | |||
782 | if (!info.generate_diagnostics ()) | |||
783 | { | |||
784 | /* Cache the ATOMIC_CONSTRs that we return, so that sat_hasher::equal | |||
785 | later can cheaply compare two atoms using just pointer equality. */ | |||
786 | if (!atom_cache) | |||
787 | atom_cache = hash_table<atom_hasher>::create_ggc (31); | |||
788 | tree *slot = atom_cache->find_slot (atom, INSERT); | |||
789 | if (*slot) | |||
790 | return *slot; | |||
791 | ||||
792 | /* Find all template parameters used in the targets of the parameter | |||
793 | mapping, and store a list of them in the TREE_TYPE of the mapping. | |||
794 | This list will be used by sat_hasher to determine the subset of | |||
795 | supplied template arguments that the satisfaction value of the atom | |||
796 | depends on. */ | |||
797 | if (map) | |||
798 | { | |||
799 | tree targets = make_tree_vec (list_length (map)); | |||
800 | int i = 0; | |||
801 | for (tree node = map; node; node = TREE_CHAIN (node)((contains_struct_check ((node), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 801, __FUNCTION__))->common.chain)) | |||
802 | { | |||
803 | tree target = TREE_PURPOSE (node)((tree_check ((node), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 803, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
804 | TREE_VEC_ELT (targets, i++)(*((const_cast<tree *> (tree_vec_elt_check ((targets), ( i++), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 804, __FUNCTION__))))) = target; | |||
805 | } | |||
806 | tree ctx_parms = (info.orig_decl | |||
807 | ? DECL_TEMPLATE_PARMS (info.orig_decl)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((info.orig_decl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 807, __FUNCTION__, (TEMPLATE_DECL))))))))->arguments | |||
808 | : current_template_parmsscope_chain->template_parms); | |||
809 | tree target_parms = find_template_parameters (targets, ctx_parms); | |||
810 | TREE_TYPE (map)((contains_struct_check ((map), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 810, __FUNCTION__))->typed.type) = target_parms; | |||
811 | } | |||
812 | ||||
813 | *slot = atom; | |||
814 | } | |||
815 | return atom; | |||
816 | } | |||
817 | ||||
818 | /* Returns the normal form of an expression. */ | |||
819 | ||||
820 | static tree | |||
821 | normalize_expression (tree t, tree args, norm_info info) | |||
822 | { | |||
823 | if (!t) | |||
824 | return NULL_TREE(tree) __null; | |||
825 | ||||
826 | if (t == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
827 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
828 | ||||
829 | switch (TREE_CODE (t)((enum tree_code) (t)->base.code)) | |||
830 | { | |||
831 | case TRUTH_ANDIF_EXPR: | |||
832 | return normalize_logical_operation (t, args, CONJ_CONSTR, info); | |||
833 | case TRUTH_ORIF_EXPR: | |||
834 | return normalize_logical_operation (t, args, DISJ_CONSTR, info); | |||
835 | default: | |||
836 | return normalize_atom (t, args, info); | |||
837 | } | |||
838 | } | |||
839 | ||||
840 | /* Cache of the normalized form of constraints. Marked as deletable because it | |||
841 | can all be recalculated. */ | |||
842 | static GTY((deletable)) hash_map<tree,tree> *normalized_map; | |||
843 | ||||
844 | static tree | |||
845 | get_normalized_constraints (tree t, norm_info info) | |||
846 | { | |||
847 | auto_timevar time (TV_CONSTRAINT_NORM); | |||
848 | return normalize_expression (t, NULL_TREE(tree) __null, info); | |||
849 | } | |||
850 | ||||
851 | /* Returns the normalized constraints from a constraint-info object | |||
852 | or NULL_TREE if the constraints are null. IN_DECL provides the | |||
853 | declaration to which the constraints belong. */ | |||
854 | ||||
855 | static tree | |||
856 | get_normalized_constraints_from_info (tree ci, tree in_decl, bool diag = false) | |||
857 | { | |||
858 | if (ci == NULL_TREE(tree) __null) | |||
859 | return NULL_TREE(tree) __null; | |||
860 | ||||
861 | /* Substitution errors during normalization are fatal. */ | |||
862 | ++processing_template_declscope_chain->x_processing_template_decl; | |||
863 | norm_info info (in_decl, diag ? tf_norm : tf_none); | |||
864 | tree t = get_normalized_constraints (CI_ASSOCIATED_CONSTRAINTS (ci)check_constraint_info (check_nonnull (ci))->associated_constr, info); | |||
865 | --processing_template_declscope_chain->x_processing_template_decl; | |||
866 | ||||
867 | return t; | |||
868 | } | |||
869 | ||||
870 | /* Returns the normalized constraints for the declaration D. */ | |||
871 | ||||
872 | static tree | |||
873 | get_normalized_constraints_from_decl (tree d, bool diag = false) | |||
874 | { | |||
875 | tree tmpl; | |||
876 | tree decl; | |||
877 | ||||
878 | /* For inherited constructors, consider the original declaration; | |||
879 | it has the correct template information attached. */ | |||
880 | d = strip_inheriting_ctors (d); | |||
881 | ||||
882 | if (TREE_CODE (d)((enum tree_code) (d)->base.code) == TEMPLATE_DECL) | |||
883 | { | |||
884 | tmpl = d; | |||
885 | decl = DECL_TEMPLATE_RESULT (tmpl)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((tmpl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 885, __FUNCTION__, (TEMPLATE_DECL))))))))->result; | |||
886 | } | |||
887 | else | |||
888 | { | |||
889 | if (tree ti = DECL_TEMPLATE_INFO (d)(((contains_struct_check ((template_info_decl_check ((d), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 889, __FUNCTION__)), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 889, __FUNCTION__))->decl_common.lang_specific) ->u.min .template_info)) | |||
890 | tmpl = TI_TEMPLATE (ti)((struct tree_template_info*)(tree_check ((ti), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 890, __FUNCTION__, (TEMPLATE_INFO))))->tmpl; | |||
891 | else | |||
892 | tmpl = NULL_TREE(tree) __null; | |||
893 | decl = d; | |||
894 | } | |||
895 | ||||
896 | /* Get the most general template for the declaration, and compute | |||
897 | arguments from that. This ensures that the arguments used for | |||
898 | normalization are always template parameters and not arguments | |||
899 | used for outer specializations. For example: | |||
900 | ||||
901 | template<typename T> | |||
902 | struct S { | |||
903 | template<typename U> requires C<T, U> void f(U); | |||
904 | }; | |||
905 | ||||
906 | S<int>::f(0); | |||
907 | ||||
908 | When we normalize the requirements for S<int>::f, we want the | |||
909 | arguments to be {T, U}, not {int, U}. One reason for this is that | |||
910 | accepting the latter causes the template parameter level of U | |||
911 | to be reduced in a way that makes it overly difficult substitute | |||
912 | concrete arguments (i.e., eventually {int, int} during satisfaction. */ | |||
913 | if (tmpl) | |||
914 | { | |||
915 | if (DECL_LANG_SPECIFIC(tmpl)((contains_struct_check ((tmpl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 915, __FUNCTION__))->decl_common.lang_specific) && !DECL_TEMPLATE_SPECIALIZATION (tmpl)((((contains_struct_check ((tmpl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 915, __FUNCTION__))->decl_common.lang_specific)->u.base .use_template) == 2)) | |||
916 | tmpl = most_general_template (tmpl); | |||
917 | } | |||
918 | ||||
919 | /* If we're not diagnosing errors, use cached constraints, if any. */ | |||
920 | if (!diag) | |||
921 | if (tree *p = hash_map_safe_get (normalized_map, tmpl)) | |||
922 | return *p; | |||
923 | ||||
924 | tree norm = NULL_TREE(tree) __null; | |||
925 | if (tree ci = get_constraints (decl)) | |||
926 | { | |||
927 | push_nested_class_guard pncs (DECL_CONTEXT (d)((contains_struct_check ((d), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 927, __FUNCTION__))->decl_minimal.context)); | |||
928 | ||||
929 | temp_override<tree> ovr (current_function_decl); | |||
930 | if (TREE_CODE (decl)((enum tree_code) (decl)->base.code) == FUNCTION_DECL) | |||
931 | current_function_decl = decl; | |||
932 | ||||
933 | norm = get_normalized_constraints_from_info (ci, tmpl, diag); | |||
934 | } | |||
935 | ||||
936 | if (!diag) | |||
937 | hash_map_safe_put<hm_ggc> (normalized_map, tmpl, norm); | |||
938 | ||||
939 | return norm; | |||
940 | } | |||
941 | ||||
942 | /* Returns the normal form of TMPL's definition. */ | |||
943 | ||||
944 | static tree | |||
945 | normalize_concept_definition (tree tmpl, bool diag = false) | |||
946 | { | |||
947 | if (!diag) | |||
948 | if (tree *p = hash_map_safe_get (normalized_map, tmpl)) | |||
949 | return *p; | |||
950 | ||||
951 | gcc_assert (concept_definition_p (tmpl))((void)(!(concept_definition_p (tmpl)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 951, __FUNCTION__), 0 : 0)); | |||
952 | if (OVL_P (tmpl)(((enum tree_code) (tmpl)->base.code) == FUNCTION_DECL || ( (enum tree_code) (tmpl)->base.code) == OVERLOAD)) | |||
953 | tmpl = OVL_FIRST (tmpl)ovl_first (tmpl); | |||
954 | gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL)((void)(!(((enum tree_code) (tmpl)->base.code) == TEMPLATE_DECL ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 954, __FUNCTION__), 0 : 0)); | |||
955 | tree def = get_concept_definition (DECL_TEMPLATE_RESULT (tmpl)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((tmpl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 955, __FUNCTION__, (TEMPLATE_DECL))))))))->result); | |||
956 | ++processing_template_declscope_chain->x_processing_template_decl; | |||
957 | norm_info info (tmpl, diag ? tf_norm : tf_none); | |||
958 | tree norm = get_normalized_constraints (def, info); | |||
959 | --processing_template_declscope_chain->x_processing_template_decl; | |||
960 | ||||
961 | if (!diag) | |||
962 | hash_map_safe_put<hm_ggc> (normalized_map, tmpl, norm); | |||
963 | ||||
964 | return norm; | |||
965 | } | |||
966 | ||||
967 | /* Returns the normal form of TMPL's requirements. */ | |||
968 | ||||
969 | static tree | |||
970 | normalize_template_requirements (tree tmpl, bool diag = false) | |||
971 | { | |||
972 | return get_normalized_constraints_from_decl (tmpl, diag); | |||
973 | } | |||
974 | ||||
975 | /* Returns the normal form of TMPL's requirements. */ | |||
976 | ||||
977 | static tree | |||
978 | normalize_nontemplate_requirements (tree decl, bool diag = false) | |||
979 | { | |||
980 | return get_normalized_constraints_from_decl (decl, diag); | |||
981 | } | |||
982 | ||||
983 | /* Normalize an EXPR as a constraint. */ | |||
984 | ||||
985 | static tree | |||
986 | normalize_constraint_expression (tree expr, bool diag) | |||
987 | { | |||
988 | if (!expr || expr == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
989 | return expr; | |||
990 | ++processing_template_declscope_chain->x_processing_template_decl; | |||
991 | norm_info info (diag ? tf_norm : tf_none); | |||
992 | tree norm = get_normalized_constraints (expr, info); | |||
993 | --processing_template_declscope_chain->x_processing_template_decl; | |||
994 | return norm; | |||
995 | } | |||
996 | ||||
997 | /* 17.4.1.2p2. Two constraints are identical if they are formed | |||
998 | from the same expression and the targets of the parameter mapping | |||
999 | are equivalent. */ | |||
1000 | ||||
1001 | bool | |||
1002 | atomic_constraints_identical_p (tree t1, tree t2) | |||
1003 | { | |||
1004 | gcc_assert (TREE_CODE (t1) == ATOMIC_CONSTR)((void)(!(((enum tree_code) (t1)->base.code) == ATOMIC_CONSTR ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1004, __FUNCTION__), 0 : 0)); | |||
1005 | gcc_assert (TREE_CODE (t2) == ATOMIC_CONSTR)((void)(!(((enum tree_code) (t2)->base.code) == ATOMIC_CONSTR ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1005, __FUNCTION__), 0 : 0)); | |||
1006 | ||||
1007 | if (ATOMIC_CONSTR_EXPR (t1)((tree_check ((((contains_struct_check (((tree_check3 (((tree_check ((t1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1007, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1007, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1007, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1007, __FUNCTION__, (TREE_LIST)))->list.purpose) != ATOMIC_CONSTR_EXPR (t2)((tree_check ((((contains_struct_check (((tree_check3 (((tree_check ((t2), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1007, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1007, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1007, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1007, __FUNCTION__, (TREE_LIST)))->list.purpose)) | |||
1008 | return false; | |||
1009 | ||||
1010 | if (!parameter_mapping_equivalent_p (t1, t2)) | |||
1011 | return false; | |||
1012 | ||||
1013 | return true; | |||
1014 | } | |||
1015 | ||||
1016 | /* True if T1 and T2 are equivalent, meaning they have the same syntactic | |||
1017 | structure and all corresponding constraints are identical. */ | |||
1018 | ||||
1019 | bool | |||
1020 | constraints_equivalent_p (tree t1, tree t2) | |||
1021 | { | |||
1022 | gcc_assert (CONSTR_P (t1))((void)(!((((enum tree_code) (t1)->base.code) == ATOMIC_CONSTR || ((enum tree_code) (t1)->base.code) == CONJ_CONSTR || ( (enum tree_code) (t1)->base.code) == DISJ_CONSTR)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1022, __FUNCTION__), 0 : 0)); | |||
1023 | gcc_assert (CONSTR_P (t2))((void)(!((((enum tree_code) (t2)->base.code) == ATOMIC_CONSTR || ((enum tree_code) (t2)->base.code) == CONJ_CONSTR || ( (enum tree_code) (t2)->base.code) == DISJ_CONSTR)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1023, __FUNCTION__), 0 : 0)); | |||
1024 | ||||
1025 | if (TREE_CODE (t1)((enum tree_code) (t1)->base.code) != TREE_CODE (t2)((enum tree_code) (t2)->base.code)) | |||
1026 | return false; | |||
1027 | ||||
1028 | switch (TREE_CODE (t1)((enum tree_code) (t1)->base.code)) | |||
1029 | { | |||
1030 | case CONJ_CONSTR: | |||
1031 | case DISJ_CONSTR: | |||
1032 | if (!constraints_equivalent_p (TREE_OPERAND (t1, 0)(*((const_cast<tree*> (tree_operand_check ((t1), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1032, __FUNCTION__))))), TREE_OPERAND (t2, 0)(*((const_cast<tree*> (tree_operand_check ((t2), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1032, __FUNCTION__))))))) | |||
1033 | return false; | |||
1034 | if (!constraints_equivalent_p (TREE_OPERAND (t1, 1)(*((const_cast<tree*> (tree_operand_check ((t1), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1034, __FUNCTION__))))), TREE_OPERAND (t2, 1)(*((const_cast<tree*> (tree_operand_check ((t2), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1034, __FUNCTION__))))))) | |||
1035 | return false; | |||
1036 | break; | |||
1037 | case ATOMIC_CONSTR: | |||
1038 | if (!atomic_constraints_identical_p(t1, t2)) | |||
1039 | return false; | |||
1040 | break; | |||
1041 | default: | |||
1042 | gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1042, __FUNCTION__)); | |||
1043 | } | |||
1044 | return true; | |||
1045 | } | |||
1046 | ||||
1047 | /* Compute the hash value for T. */ | |||
1048 | ||||
1049 | hashval_t | |||
1050 | hash_atomic_constraint (tree t) | |||
1051 | { | |||
1052 | gcc_assert (TREE_CODE (t) == ATOMIC_CONSTR)((void)(!(((enum tree_code) (t)->base.code) == ATOMIC_CONSTR ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1052, __FUNCTION__), 0 : 0)); | |||
1053 | ||||
1054 | /* Hash the identity of the expression. */ | |||
1055 | hashval_t val = htab_hash_pointer (ATOMIC_CONSTR_EXPR (t)((tree_check ((((contains_struct_check (((tree_check3 (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1055, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1055, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1055, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1055, __FUNCTION__, (TREE_LIST)))->list.purpose)); | |||
1056 | ||||
1057 | /* Hash the targets of the parameter map. */ | |||
1058 | tree p = ATOMIC_CONSTR_MAP (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1058, __FUNCTION__, (ATOMIC_CONSTR)))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1058, __FUNCTION__))))); | |||
1059 | while (p) | |||
1060 | { | |||
1061 | val = iterative_hash_template_arg (TREE_PURPOSE (p)((tree_check ((p), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1061, __FUNCTION__, (TREE_LIST)))->list.purpose), val); | |||
1062 | p = TREE_CHAIN (p)((contains_struct_check ((p), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1062, __FUNCTION__))->common.chain); | |||
1063 | } | |||
1064 | ||||
1065 | return val; | |||
1066 | } | |||
1067 | ||||
1068 | namespace inchash | |||
1069 | { | |||
1070 | ||||
1071 | static void | |||
1072 | add_constraint (tree t, hash& h) | |||
1073 | { | |||
1074 | h.add_int(TREE_CODE (t)((enum tree_code) (t)->base.code)); | |||
1075 | switch (TREE_CODE (t)((enum tree_code) (t)->base.code)) | |||
1076 | { | |||
1077 | case CONJ_CONSTR: | |||
1078 | case DISJ_CONSTR: | |||
1079 | add_constraint (TREE_OPERAND (t, 0)(*((const_cast<tree*> (tree_operand_check ((t), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1079, __FUNCTION__))))), h); | |||
1080 | add_constraint (TREE_OPERAND (t, 1)(*((const_cast<tree*> (tree_operand_check ((t), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1080, __FUNCTION__))))), h); | |||
1081 | break; | |||
1082 | case ATOMIC_CONSTR: | |||
1083 | h.merge_hash (hash_atomic_constraint (t)); | |||
1084 | break; | |||
1085 | default: | |||
1086 | gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1086, __FUNCTION__)); | |||
1087 | } | |||
1088 | } | |||
1089 | ||||
1090 | } | |||
1091 | ||||
1092 | /* Computes a hash code for the constraint T. */ | |||
1093 | ||||
1094 | hashval_t | |||
1095 | iterative_hash_constraint (tree t, hashval_t val) | |||
1096 | { | |||
1097 | gcc_assert (CONSTR_P (t))((void)(!((((enum tree_code) (t)->base.code) == ATOMIC_CONSTR || ((enum tree_code) (t)->base.code) == CONJ_CONSTR || (( enum tree_code) (t)->base.code) == DISJ_CONSTR)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1097, __FUNCTION__), 0 : 0)); | |||
1098 | inchash::hash h (val); | |||
1099 | inchash::add_constraint (t, h); | |||
1100 | return h.end (); | |||
1101 | } | |||
1102 | ||||
1103 | // -------------------------------------------------------------------------- // | |||
1104 | // Constraint Semantic Processing | |||
1105 | // | |||
1106 | // The following functions are called by the parser and substitution rules | |||
1107 | // to create and evaluate constraint-related nodes. | |||
1108 | ||||
1109 | // The constraints associated with the current template parameters. | |||
1110 | tree | |||
1111 | current_template_constraints (void) | |||
1112 | { | |||
1113 | if (!current_template_parmsscope_chain->template_parms) | |||
1114 | return NULL_TREE(tree) __null; | |||
1115 | tree tmpl_constr = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms)((contains_struct_check (((tree_check ((scope_chain->template_parms ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1115, __FUNCTION__, (TREE_LIST)))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1115, __FUNCTION__))->typed.type); | |||
1116 | return build_constraints (tmpl_constr, NULL_TREE(tree) __null); | |||
1117 | } | |||
1118 | ||||
1119 | /* If the recently parsed TYPE declares or defines a template or | |||
1120 | template specialization, get its corresponding constraints from the | |||
1121 | current template parameters and bind them to TYPE's declaration. */ | |||
1122 | ||||
1123 | tree | |||
1124 | associate_classtype_constraints (tree type) | |||
1125 | { | |||
1126 | if (!type || type == error_mark_nodeglobal_trees[TI_ERROR_MARK] || !CLASS_TYPE_P (type)(((((enum tree_code) (type)->base.code)) == RECORD_TYPE || (((enum tree_code) (type)->base.code)) == UNION_TYPE) && ((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1126, __FUNCTION__))->type_common.lang_flag_5))) | |||
1127 | return type; | |||
1128 | ||||
1129 | /* An explicit class template specialization has no template parameters. */ | |||
1130 | if (!current_template_parmsscope_chain->template_parms) | |||
1131 | return type; | |||
1132 | ||||
1133 | if (CLASSTYPE_IS_TEMPLATE (type)((((tree_class_check (((tree_check3 ((type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1133, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE )))), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1133, __FUNCTION__))->type_non_common.lang_1)) && !((((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1133, __FUNCTION__))->type_with_lang_specific.lang_specific ))->use_template) && (((((contains_struct_check (( ((tree_check ((((struct tree_template_decl *)(const_cast<union tree_node *> ((((tree_check ((((struct tree_template_info *)(tree_check (((((tree_class_check (((tree_check3 ((type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1133, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE )))), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1133, __FUNCTION__))->type_non_common.lang_1))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1133, __FUNCTION__, (TEMPLATE_INFO))))->tmpl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1133, __FUNCTION__, (TEMPLATE_DECL))))))))->arguments), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1133, __FUNCTION__, (TREE_LIST)))->list.value)), (TS_TYPED ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1133, __FUNCTION__))->typed.type))) == (((struct tree_template_info *)(tree_check (((((tree_class_check (((tree_check3 ((type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1133, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE )))), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1133, __FUNCTION__))->type_non_common.lang_1))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1133, __FUNCTION__, (TEMPLATE_INFO))))->tmpl))) || CLASSTYPE_TEMPLATE_SPECIALIZATION (type)(((((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1133, __FUNCTION__))->type_with_lang_specific.lang_specific ))->use_template) == 2)) | |||
1134 | { | |||
1135 | tree decl = TYPE_STUB_DECL (type)(((contains_struct_check (((tree_class_check ((type), (tcc_type ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1135, __FUNCTION__))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1135, __FUNCTION__))->common.chain)); | |||
1136 | tree ci = current_template_constraints (); | |||
1137 | ||||
1138 | /* An implicitly instantiated member template declaration already | |||
1139 | has associated constraints. If it is defined outside of its | |||
1140 | class, then we need match these constraints against those of | |||
1141 | original declaration. */ | |||
1142 | if (tree orig_ci = get_constraints (decl)) | |||
1143 | { | |||
1144 | if (int extra_levels = (TMPL_PARMS_DEPTH (current_template_parms)((long) ((unsigned long) (*tree_int_cst_elt_check ((((tree_check ((scope_chain->template_parms), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1144, __FUNCTION__, (TREE_LIST)))->list.purpose)), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1144, __FUNCTION__)))) | |||
1145 | - TMPL_ARGS_DEPTH (TYPE_TI_ARGS (type))(((((struct tree_template_info*)(tree_check (((((enum tree_code ) (type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (type)->base.code) == BOUND_TEMPLATE_TEMPLATE_PARM || ((( enum tree_code) (type)->base.code) == RECORD_TYPE || ((enum tree_code) (type)->base.code) == UNION_TYPE || ((enum tree_code ) (type)->base.code) == QUAL_UNION_TYPE) ? ((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__))->type_non_common.lang_1) : (tree) __null )), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__, (TEMPLATE_INFO))))->args) && ((tree_check (((((struct tree_template_info*)(tree_check ((( ((enum tree_code) (type)->base.code) == ENUMERAL_TYPE || ( (enum tree_code) (type)->base.code) == BOUND_TEMPLATE_TEMPLATE_PARM || (((enum tree_code) (type)->base.code) == RECORD_TYPE || ((enum tree_code) (type)->base.code) == UNION_TYPE || ((enum tree_code) (type)->base.code) == QUAL_UNION_TYPE) ? ((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__))->type_non_common.lang_1) : (tree) __null )), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__, (TEMPLATE_INFO))))->args)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__, (TREE_VEC)))->base.u.length) && (*((const_cast<tree *> (tree_vec_elt_check (((((struct tree_template_info*)(tree_check (((((enum tree_code) (type)-> base.code) == ENUMERAL_TYPE || ((enum tree_code) (type)->base .code) == BOUND_TEMPLATE_TEMPLATE_PARM || (((enum tree_code) ( type)->base.code) == RECORD_TYPE || ((enum tree_code) (type )->base.code) == UNION_TYPE || ((enum tree_code) (type)-> base.code) == QUAL_UNION_TYPE) ? ((tree_class_check ((type), ( tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__))->type_non_common.lang_1) : (tree) __null )), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__, (TEMPLATE_INFO))))->args)), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__))))) && ((enum tree_code) ((*((const_cast <tree *> (tree_vec_elt_check (((((struct tree_template_info *)(tree_check (((((enum tree_code) (type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (type)->base.code) == BOUND_TEMPLATE_TEMPLATE_PARM || (((enum tree_code) (type)->base.code) == RECORD_TYPE || ((enum tree_code) (type)->base.code) == UNION_TYPE || ((enum tree_code) (type)->base.code) == QUAL_UNION_TYPE) ? ((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__))->type_non_common.lang_1) : (tree) __null )), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__, (TEMPLATE_INFO))))->args)), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__))))))->base.code) == TREE_VEC) ? ((tree_check (((((struct tree_template_info*)(tree_check (((((enum tree_code ) (type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (type)->base.code) == BOUND_TEMPLATE_TEMPLATE_PARM || ((( enum tree_code) (type)->base.code) == RECORD_TYPE || ((enum tree_code) (type)->base.code) == UNION_TYPE || ((enum tree_code ) (type)->base.code) == QUAL_UNION_TYPE) ? ((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__))->type_non_common.lang_1) : (tree) __null )), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__, (TEMPLATE_INFO))))->args)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1145, __FUNCTION__, (TREE_VEC)))->base.u.length) : 1))) | |||
1146 | { | |||
1147 | /* If there is a discrepancy between the current template depth | |||
1148 | and the template depth of the original declaration, then we | |||
1149 | must be redeclaring a class template as part of a friend | |||
1150 | declaration within another class template. Before matching | |||
1151 | constraints, we need to reduce the template parameter level | |||
1152 | within the current constraints via substitution. */ | |||
1153 | tree outer_gtargs = template_parms_to_args (current_template_parmsscope_chain->template_parms); | |||
1154 | TREE_VEC_LENGTH (outer_gtargs)((tree_check ((outer_gtargs), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1154, __FUNCTION__, (TREE_VEC)))->base.u.length) = extra_levels; | |||
1155 | ci = tsubst_constraint_info (ci, outer_gtargs, tf_none, NULL_TREE(tree) __null); | |||
1156 | } | |||
1157 | if (!equivalent_constraints (ci, orig_ci)) | |||
1158 | { | |||
1159 | error ("%qT does not match original declaration", type); | |||
1160 | tree tmpl = CLASSTYPE_TI_TEMPLATE (type)((struct tree_template_info*)(tree_check (((((tree_class_check (((tree_check3 ((type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1160, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE )))), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1160, __FUNCTION__))->type_non_common.lang_1))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1160, __FUNCTION__, (TEMPLATE_INFO))))->tmpl; | |||
1161 | location_t loc = DECL_SOURCE_LOCATION (tmpl)((contains_struct_check ((tmpl), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1161, __FUNCTION__))->decl_minimal.locus); | |||
1162 | inform (loc, "original template declaration here"); | |||
1163 | /* Fall through, so that we define the type anyway. */ | |||
1164 | } | |||
1165 | return type; | |||
1166 | } | |||
1167 | set_constraints (decl, ci); | |||
1168 | } | |||
1169 | return type; | |||
1170 | } | |||
1171 | ||||
1172 | /* Create an empty constraint info block. */ | |||
1173 | ||||
1174 | static inline tree_constraint_info* | |||
1175 | build_constraint_info () | |||
1176 | { | |||
1177 | return (tree_constraint_info *)make_node (CONSTRAINT_INFO); | |||
1178 | } | |||
1179 | ||||
1180 | /* Build a constraint-info object that contains the associated constraints | |||
1181 | of a declaration. This also includes the declaration's template | |||
1182 | requirements (TREQS) and any trailing requirements for a function | |||
1183 | declarator (DREQS). Note that both TREQS and DREQS must be constraints. | |||
1184 | ||||
1185 | If the declaration has neither template nor declaration requirements | |||
1186 | this returns NULL_TREE, indicating an unconstrained declaration. */ | |||
1187 | ||||
1188 | tree | |||
1189 | build_constraints (tree tr, tree dr) | |||
1190 | { | |||
1191 | if (!tr && !dr) | |||
1192 | return NULL_TREE(tree) __null; | |||
1193 | ||||
1194 | tree_constraint_info* ci = build_constraint_info (); | |||
1195 | ci->template_reqs = tr; | |||
1196 | ci->declarator_reqs = dr; | |||
1197 | ci->associated_constr = combine_constraint_expressions (tr, dr); | |||
1198 | ||||
1199 | return (tree)ci; | |||
1200 | } | |||
1201 | ||||
1202 | /* Add constraint RHS to the end of CONSTRAINT_INFO ci. */ | |||
1203 | ||||
1204 | tree | |||
1205 | append_constraint (tree ci, tree rhs) | |||
1206 | { | |||
1207 | tree tr = ci ? CI_TEMPLATE_REQS (ci)check_constraint_info (check_nonnull (ci))->template_reqs : NULL_TREE(tree) __null; | |||
1208 | tree dr = ci ? CI_DECLARATOR_REQS (ci)check_constraint_info (check_nonnull (ci))->declarator_reqs : NULL_TREE(tree) __null; | |||
1209 | dr = combine_constraint_expressions (dr, rhs); | |||
1210 | if (ci) | |||
1211 | { | |||
1212 | CI_DECLARATOR_REQS (ci)check_constraint_info (check_nonnull (ci))->declarator_reqs = dr; | |||
1213 | tree ac = combine_constraint_expressions (tr, dr); | |||
1214 | CI_ASSOCIATED_CONSTRAINTS (ci)check_constraint_info (check_nonnull (ci))->associated_constr = ac; | |||
1215 | } | |||
1216 | else | |||
1217 | ci = build_constraints (tr, dr); | |||
1218 | return ci; | |||
1219 | } | |||
1220 | ||||
1221 | /* A mapping from declarations to constraint information. */ | |||
1222 | ||||
1223 | static GTY ((cache)) decl_tree_cache_map *decl_constraints; | |||
1224 | ||||
1225 | /* Returns the template constraints of declaration T. If T is not | |||
1226 | constrained, return NULL_TREE. Note that T must be non-null. */ | |||
1227 | ||||
1228 | tree | |||
1229 | get_constraints (const_tree t) | |||
1230 | { | |||
1231 | if (!flag_conceptsglobal_options.x_flag_concepts) | |||
1232 | return NULL_TREE(tree) __null; | |||
1233 | if (!decl_constraints) | |||
1234 | return NULL_TREE(tree) __null; | |||
1235 | ||||
1236 | gcc_assert (DECL_P (t))((void)(!((tree_code_type[(int) (((enum tree_code) (t)->base .code))] == tcc_declaration)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1236, __FUNCTION__), 0 : 0)); | |||
1237 | if (TREE_CODE (t)((enum tree_code) (t)->base.code) == TEMPLATE_DECL) | |||
1238 | t = DECL_TEMPLATE_RESULT (t)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1238, __FUNCTION__, (TEMPLATE_DECL))))))))->result; | |||
1239 | tree* found = decl_constraints->get (CONST_CAST_TREE (t)(const_cast<union tree_node *> (((t))))); | |||
1240 | if (found) | |||
1241 | return *found; | |||
1242 | else | |||
1243 | return NULL_TREE(tree) __null; | |||
1244 | } | |||
1245 | ||||
1246 | /* Associate the given constraint information CI with the declaration | |||
1247 | T. If T is a template, then the constraints are associated with | |||
1248 | its underlying declaration. Don't build associations if CI is | |||
1249 | NULL_TREE. */ | |||
1250 | ||||
1251 | void | |||
1252 | set_constraints (tree t, tree ci) | |||
1253 | { | |||
1254 | if (!ci) | |||
1255 | return; | |||
1256 | gcc_assert (t && flag_concepts)((void)(!(t && global_options.x_flag_concepts) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1256, __FUNCTION__), 0 : 0)); | |||
1257 | if (TREE_CODE (t)((enum tree_code) (t)->base.code) == TEMPLATE_DECL) | |||
1258 | t = DECL_TEMPLATE_RESULT (t)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1258, __FUNCTION__, (TEMPLATE_DECL))))))))->result; | |||
1259 | bool found = hash_map_safe_put<hm_ggc> (decl_constraints, t, ci); | |||
1260 | gcc_assert (!found)((void)(!(!found) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1260, __FUNCTION__), 0 : 0)); | |||
1261 | } | |||
1262 | ||||
1263 | /* Remove the associated constraints of the declaration T. */ | |||
1264 | ||||
1265 | void | |||
1266 | remove_constraints (tree t) | |||
1267 | { | |||
1268 | gcc_checking_assert (DECL_P (t))((void)(!((tree_code_type[(int) (((enum tree_code) (t)->base .code))] == tcc_declaration)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1268, __FUNCTION__), 0 : 0)); | |||
1269 | if (TREE_CODE (t)((enum tree_code) (t)->base.code) == TEMPLATE_DECL) | |||
1270 | t = DECL_TEMPLATE_RESULT (t)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1270, __FUNCTION__, (TEMPLATE_DECL))))))))->result; | |||
1271 | ||||
1272 | if (decl_constraints) | |||
1273 | decl_constraints->remove (t); | |||
1274 | } | |||
1275 | ||||
1276 | /* If DECL is a friend, substitute into REQS to produce requirements suitable | |||
1277 | for declaration matching. */ | |||
1278 | ||||
1279 | tree | |||
1280 | maybe_substitute_reqs_for (tree reqs, const_tree decl_) | |||
1281 | { | |||
1282 | if (reqs == NULL_TREE(tree) __null) | |||
1283 | return NULL_TREE(tree) __null; | |||
1284 | ||||
1285 | tree decl = CONST_CAST_TREE (decl_)(const_cast<union tree_node *> (((decl_)))); | |||
1286 | tree result = STRIP_TEMPLATE (decl)(((enum tree_code) (decl)->base.code) == TEMPLATE_DECL ? ( (struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((decl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1286, __FUNCTION__, (TEMPLATE_DECL))))))))->result : decl ); | |||
1287 | ||||
1288 | if (DECL_UNIQUE_FRIEND_P (result)(((contains_struct_check (((tree_check ((result), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1288, __FUNCTION__, (FUNCTION_DECL)))), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1288, __FUNCTION__))->decl_common.lang_specific) ->u. base.friend_or_tls)) | |||
1289 | { | |||
1290 | tree tmpl = decl; | |||
1291 | if (TREE_CODE (decl)((enum tree_code) (decl)->base.code) != TEMPLATE_DECL) | |||
1292 | tmpl = DECL_TI_TEMPLATE (result)((struct tree_template_info*)(tree_check (((((contains_struct_check ((template_info_decl_check ((result), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1292, __FUNCTION__)), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1292, __FUNCTION__))->decl_common.lang_specific) ->u. min.template_info)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1292, __FUNCTION__, (TEMPLATE_INFO))))->tmpl; | |||
1293 | ||||
1294 | tree gargs = generic_targs_for (tmpl); | |||
1295 | processing_template_decl_sentinel s; | |||
1296 | if (uses_template_parms (gargs)) | |||
1297 | ++processing_template_declscope_chain->x_processing_template_decl; | |||
1298 | reqs = tsubst_constraint (reqs, gargs, | |||
1299 | tf_warning_or_error, NULL_TREE(tree) __null); | |||
1300 | } | |||
1301 | return reqs; | |||
1302 | } | |||
1303 | ||||
1304 | /* Returns the template-head requires clause for the template | |||
1305 | declaration T or NULL_TREE if none. */ | |||
1306 | ||||
1307 | tree | |||
1308 | get_template_head_requirements (tree t) | |||
1309 | { | |||
1310 | tree ci = get_constraints (t); | |||
1311 | if (!ci) | |||
1312 | return NULL_TREE(tree) __null; | |||
1313 | return CI_TEMPLATE_REQS (ci)check_constraint_info (check_nonnull (ci))->template_reqs; | |||
1314 | } | |||
1315 | ||||
1316 | /* Returns the trailing requires clause of the declarator of | |||
1317 | a template declaration T or NULL_TREE if none. */ | |||
1318 | ||||
1319 | tree | |||
1320 | get_trailing_function_requirements (tree t) | |||
1321 | { | |||
1322 | tree ci = get_constraints (t); | |||
1323 | if (!ci) | |||
1324 | return NULL_TREE(tree) __null; | |||
1325 | return CI_DECLARATOR_REQS (ci)check_constraint_info (check_nonnull (ci))->declarator_reqs; | |||
1326 | } | |||
1327 | ||||
1328 | /* Construct a sequence of template arguments by prepending | |||
1329 | ARG to REST. Either ARG or REST may be null. */ | |||
1330 | static tree | |||
1331 | build_concept_check_arguments (tree arg, tree rest) | |||
1332 | { | |||
1333 | gcc_assert (rest ? TREE_CODE (rest) == TREE_VEC : true)((void)(!(rest ? ((enum tree_code) (rest)->base.code) == TREE_VEC : true) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1333, __FUNCTION__), 0 : 0)); | |||
1334 | tree args; | |||
1335 | if (arg) | |||
1336 | { | |||
1337 | int n = rest ? TREE_VEC_LENGTH (rest)((tree_check ((rest), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1337, __FUNCTION__, (TREE_VEC)))->base.u.length) : 0; | |||
1338 | args = make_tree_vec (n + 1); | |||
1339 | TREE_VEC_ELT (args, 0)(*((const_cast<tree *> (tree_vec_elt_check ((args), (0) , "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1339, __FUNCTION__))))) = arg; | |||
1340 | if (rest) | |||
1341 | for (int i = 0; i < n; ++i) | |||
1342 | TREE_VEC_ELT (args, i + 1)(*((const_cast<tree *> (tree_vec_elt_check ((args), (i + 1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1342, __FUNCTION__))))) = TREE_VEC_ELT (rest, i)(*((const_cast<tree *> (tree_vec_elt_check ((rest), (i) , "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1342, __FUNCTION__))))); | |||
1343 | int def = rest ? GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (rest)int_cst_value (((contains_struct_check (((tree_check ((rest), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1343, __FUNCTION__, (TREE_VEC)))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1343, __FUNCTION__))->common.chain)) : 0; | |||
1344 | SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (args, def + 1)((contains_struct_check (((tree_check ((args), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1344, __FUNCTION__, (TREE_VEC)))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1344, __FUNCTION__))->common.chain) = build_int_cst ((tree ) __null, def + 1); | |||
1345 | } | |||
1346 | else | |||
1347 | { | |||
1348 | gcc_assert (rest != NULL_TREE)((void)(!(rest != (tree) __null) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1348, __FUNCTION__), 0 : 0)); | |||
1349 | args = rest; | |||
1350 | } | |||
1351 | return args; | |||
1352 | } | |||
1353 | ||||
1354 | /* Builds an id-expression of the form `C<Args...>()` where C is a function | |||
1355 | concept. */ | |||
1356 | ||||
1357 | static tree | |||
1358 | build_function_check (tree tmpl, tree args, tsubst_flags_t /*complain*/) | |||
1359 | { | |||
1360 | if (TREE_CODE (tmpl)((enum tree_code) (tmpl)->base.code) == TEMPLATE_DECL) | |||
1361 | { | |||
1362 | /* If we just got a template, wrap it in an overload so it looks like any | |||
1363 | other template-id. */ | |||
1364 | tmpl = ovl_make (tmpl); | |||
1365 | TREE_TYPE (tmpl)((contains_struct_check ((tmpl), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1365, __FUNCTION__))->typed.type) = boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE]; | |||
1366 | } | |||
1367 | ||||
1368 | /* Perform function concept resolution now so we always have a single | |||
1369 | function of the overload set (even if we started with only one; the | |||
1370 | resolution function converts template arguments). Note that we still | |||
1371 | wrap this in an overload set so we don't upset other parts of the | |||
1372 | compiler that expect template-ids referring to function concepts | |||
1373 | to have an overload set. */ | |||
1374 | tree info = resolve_function_concept_overload (tmpl, args); | |||
1375 | if (info == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1376 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1377 | if (!info) | |||
1378 | { | |||
1379 | error ("no matching concepts for %qE", tmpl); | |||
1380 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1381 | } | |||
1382 | args = TREE_PURPOSE (info)((tree_check ((info), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1382, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
1383 | tmpl = DECL_TI_TEMPLATE (TREE_VALUE (info))((struct tree_template_info*)(tree_check (((((contains_struct_check ((template_info_decl_check ((((tree_check ((info), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1383, __FUNCTION__, (TREE_LIST)))->list.value)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1383, __FUNCTION__)), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1383, __FUNCTION__))->decl_common.lang_specific) ->u. min.template_info)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1383, __FUNCTION__, (TEMPLATE_INFO))))->tmpl; | |||
1384 | ||||
1385 | /* Rebuild the singleton overload set; mark the type bool. */ | |||
1386 | tmpl = ovl_make (tmpl, NULL_TREE(tree) __null); | |||
1387 | TREE_TYPE (tmpl)((contains_struct_check ((tmpl), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1387, __FUNCTION__))->typed.type) = boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE]; | |||
1388 | ||||
1389 | /* Build the id-expression around the overload set. */ | |||
1390 | tree id = build2 (TEMPLATE_ID_EXPR, boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE], tmpl, args); | |||
1391 | ||||
1392 | /* Finally, build the call expression around the overload. */ | |||
1393 | ++processing_template_declscope_chain->x_processing_template_decl; | |||
1394 | vec<tree, va_gc> *fargs = make_tree_vector (); | |||
1395 | tree call = build_min_nt_call_vec (id, fargs); | |||
1396 | TREE_TYPE (call)((contains_struct_check ((call), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1396, __FUNCTION__))->typed.type) = boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE]; | |||
1397 | release_tree_vector (fargs); | |||
1398 | --processing_template_declscope_chain->x_processing_template_decl; | |||
1399 | ||||
1400 | return call; | |||
1401 | } | |||
1402 | ||||
1403 | /* Builds an id-expression of the form `C<Args...>` where C is a variable | |||
1404 | concept. */ | |||
1405 | ||||
1406 | static tree | |||
1407 | build_variable_check (tree tmpl, tree args, tsubst_flags_t complain) | |||
1408 | { | |||
1409 | gcc_assert (variable_concept_p (tmpl))((void)(!(variable_concept_p (tmpl)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1409, __FUNCTION__), 0 : 0)); | |||
1410 | gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL)((void)(!(((enum tree_code) (tmpl)->base.code) == TEMPLATE_DECL ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1410, __FUNCTION__), 0 : 0)); | |||
1411 | tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl))((tree_check ((((struct tree_template_decl *)(const_cast<union tree_node *> ((((tree_check ((tmpl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1411, __FUNCTION__, (TEMPLATE_DECL))))))))->arguments), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1411, __FUNCTION__, (TREE_LIST)))->list.value); | |||
1412 | args = coerce_template_parms (parms, args, tmpl, complain); | |||
1413 | if (args == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1414 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1415 | return build2 (TEMPLATE_ID_EXPR, boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE], tmpl, args); | |||
1416 | } | |||
1417 | ||||
1418 | /* Builds an id-expression of the form `C<Args...>` where C is a standard | |||
1419 | concept. */ | |||
1420 | ||||
1421 | static tree | |||
1422 | build_standard_check (tree tmpl, tree args, tsubst_flags_t complain) | |||
1423 | { | |||
1424 | gcc_assert (standard_concept_p (tmpl))((void)(!(standard_concept_p (tmpl)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1424, __FUNCTION__), 0 : 0)); | |||
1425 | gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL)((void)(!(((enum tree_code) (tmpl)->base.code) == TEMPLATE_DECL ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1425, __FUNCTION__), 0 : 0)); | |||
1426 | tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl))((tree_check ((((struct tree_template_decl *)(const_cast<union tree_node *> ((((tree_check ((tmpl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1426, __FUNCTION__, (TEMPLATE_DECL))))))))->arguments), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1426, __FUNCTION__, (TREE_LIST)))->list.value); | |||
1427 | args = coerce_template_parms (parms, args, tmpl, complain); | |||
1428 | if (args == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1429 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1430 | return build2 (TEMPLATE_ID_EXPR, boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE], tmpl, args); | |||
1431 | } | |||
1432 | ||||
1433 | /* Construct an expression that checks TARGET using ARGS. */ | |||
1434 | ||||
1435 | tree | |||
1436 | build_concept_check (tree target, tree args, tsubst_flags_t complain) | |||
1437 | { | |||
1438 | return build_concept_check (target, NULL_TREE(tree) __null, args, complain); | |||
1439 | } | |||
1440 | ||||
1441 | /* Construct an expression that checks the concept given by DECL. If | |||
1442 | concept_definition_p (DECL) is false, this returns null. */ | |||
1443 | ||||
1444 | tree | |||
1445 | build_concept_check (tree decl, tree arg, tree rest, tsubst_flags_t complain) | |||
1446 | { | |||
1447 | if (arg == NULL_TREE(tree) __null && rest == NULL_TREE(tree) __null) | |||
1448 | { | |||
1449 | tree id = build_nt (TEMPLATE_ID_EXPR, decl, rest); | |||
1450 | error ("invalid use concept %qE", id); | |||
1451 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1452 | } | |||
1453 | ||||
1454 | tree args = build_concept_check_arguments (arg, rest); | |||
1455 | ||||
1456 | if (standard_concept_p (decl)) | |||
1457 | return build_standard_check (decl, args, complain); | |||
1458 | if (variable_concept_p (decl)) | |||
1459 | return build_variable_check (decl, args, complain); | |||
1460 | if (function_concept_p (decl)) | |||
1461 | return build_function_check (decl, args, complain); | |||
1462 | ||||
1463 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1464 | } | |||
1465 | ||||
1466 | /* Build a template-id that can participate in a concept check. */ | |||
1467 | ||||
1468 | static tree | |||
1469 | build_concept_id (tree decl, tree args) | |||
1470 | { | |||
1471 | tree check = build_concept_check (decl, args, tf_warning_or_error); | |||
1472 | if (check == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1473 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1474 | return unpack_concept_check (check); | |||
1475 | } | |||
1476 | ||||
1477 | /* Build a template-id that can participate in a concept check, preserving | |||
1478 | the source location of the original template-id. */ | |||
1479 | ||||
1480 | tree | |||
1481 | build_concept_id (tree expr) | |||
1482 | { | |||
1483 | gcc_assert (TREE_CODE (expr) == TEMPLATE_ID_EXPR)((void)(!(((enum tree_code) (expr)->base.code) == TEMPLATE_ID_EXPR ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1483, __FUNCTION__), 0 : 0)); | |||
1484 | tree id = build_concept_id (TREE_OPERAND (expr, 0)(*((const_cast<tree*> (tree_operand_check ((expr), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1484, __FUNCTION__))))), TREE_OPERAND (expr, 1)(*((const_cast<tree*> (tree_operand_check ((expr), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1484, __FUNCTION__)))))); | |||
1485 | protected_set_expr_location (id, cp_expr_location (expr)); | |||
1486 | return id; | |||
1487 | } | |||
1488 | ||||
1489 | /* Build as template-id with a placeholder that can be used as a | |||
1490 | type constraint. | |||
1491 | ||||
1492 | Note that this will diagnose errors if the initial concept check | |||
1493 | cannot be built. */ | |||
1494 | ||||
1495 | tree | |||
1496 | build_type_constraint (tree decl, tree args, tsubst_flags_t complain) | |||
1497 | { | |||
1498 | tree wildcard = build_nt (WILDCARD_DECL); | |||
1499 | ++processing_template_declscope_chain->x_processing_template_decl; | |||
1500 | tree check = build_concept_check (decl, wildcard, args, complain); | |||
1501 | --processing_template_declscope_chain->x_processing_template_decl; | |||
1502 | if (check == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1503 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1504 | return unpack_concept_check (check); | |||
1505 | } | |||
1506 | ||||
1507 | /* Returns a TYPE_DECL that contains sufficient information to | |||
1508 | build a template parameter of the same kind as PROTO and | |||
1509 | constrained by the concept declaration CNC. Note that PROTO | |||
1510 | is the first template parameter of CNC. | |||
1511 | ||||
1512 | If specified, ARGS provides additional arguments to the | |||
1513 | constraint check. */ | |||
1514 | tree | |||
1515 | build_constrained_parameter (tree cnc, tree proto, tree args) | |||
1516 | { | |||
1517 | tree name = DECL_NAME (cnc)((contains_struct_check ((cnc), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1517, __FUNCTION__))->decl_minimal.name); | |||
1518 | tree type = TREE_TYPE (proto)((contains_struct_check ((proto), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1518, __FUNCTION__))->typed.type); | |||
1519 | tree decl = build_decl (input_location, TYPE_DECL, name, type); | |||
1520 | CONSTRAINED_PARM_PROTOTYPE (decl)((contains_struct_check (((tree_check ((decl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1520, __FUNCTION__, (TYPE_DECL)))), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1520, __FUNCTION__))->decl_common.initial) = proto; | |||
1521 | CONSTRAINED_PARM_CONCEPT (decl)((contains_struct_check (((tree_check ((decl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1521, __FUNCTION__, (TYPE_DECL)))), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1521, __FUNCTION__))->decl_common.size_unit) = cnc; | |||
1522 | CONSTRAINED_PARM_EXTRA_ARGS (decl)((contains_struct_check (((tree_check ((decl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1522, __FUNCTION__, (TYPE_DECL)))), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1522, __FUNCTION__))->decl_common.size) = args; | |||
1523 | return decl; | |||
1524 | } | |||
1525 | ||||
1526 | /* Create a constraint expression for the given DECL that evaluates the | |||
1527 | requirements specified by CONSTR, a TYPE_DECL that contains all the | |||
1528 | information necessary to build the requirements (see finish_concept_name | |||
1529 | for the layout of that TYPE_DECL). | |||
1530 | ||||
1531 | Note that the constraints are neither reduced nor decomposed. That is | |||
1532 | done only after the requires clause has been parsed (or not). */ | |||
1533 | ||||
1534 | tree | |||
1535 | finish_shorthand_constraint (tree decl, tree constr) | |||
1536 | { | |||
1537 | /* No requirements means no constraints. */ | |||
1538 | if (!constr) | |||
1539 | return NULL_TREE(tree) __null; | |||
1540 | ||||
1541 | if (error_operand_p (constr)((constr) == global_trees[TI_ERROR_MARK] || ((constr) && ((contains_struct_check (((constr)), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1541, __FUNCTION__))->typed.type) == global_trees[TI_ERROR_MARK ]))) | |||
1542 | return NULL_TREE(tree) __null; | |||
1543 | ||||
1544 | tree proto = CONSTRAINED_PARM_PROTOTYPE (constr)((contains_struct_check (((tree_check ((constr), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1544, __FUNCTION__, (TYPE_DECL)))), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1544, __FUNCTION__))->decl_common.initial); | |||
1545 | tree con = CONSTRAINED_PARM_CONCEPT (constr)((contains_struct_check (((tree_check ((constr), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1545, __FUNCTION__, (TYPE_DECL)))), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1545, __FUNCTION__))->decl_common.size_unit); | |||
1546 | tree args = CONSTRAINED_PARM_EXTRA_ARGS (constr)((contains_struct_check (((tree_check ((constr), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1546, __FUNCTION__, (TYPE_DECL)))), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1546, __FUNCTION__))->decl_common.size); | |||
1547 | ||||
1548 | /* The TS lets use shorthand to constrain a pack of arguments, but the | |||
1549 | standard does not. | |||
1550 | ||||
1551 | For the TS, consider: | |||
1552 | ||||
1553 | template<C... Ts> struct s; | |||
1554 | ||||
1555 | If C is variadic (and because Ts is a pack), we associate the | |||
1556 | constraint C<Ts...>. In all other cases, we associate | |||
1557 | the constraint (C<Ts> && ...). | |||
1558 | ||||
1559 | The standard behavior cannot be overridden by -fconcepts-ts. */ | |||
1560 | bool variadic_concept_p = template_parameter_pack_p (proto); | |||
1561 | bool declared_pack_p = template_parameter_pack_p (decl); | |||
1562 | bool apply_to_each_p = (cxx_dialect >= cxx20) ? true : !variadic_concept_p; | |||
1563 | ||||
1564 | /* Get the argument and overload used for the requirement | |||
1565 | and adjust it if we're going to expand later. */ | |||
1566 | tree arg = template_parm_to_arg (decl); | |||
1567 | if (apply_to_each_p && declared_pack_p) | |||
1568 | arg = PACK_EXPANSION_PATTERN (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg), 0))(((enum tree_code) ((*((const_cast<tree *> (tree_vec_elt_check (((((enum tree_code) (arg)->base.code) == TYPE_ARGUMENT_PACK ? ((contains_struct_check ((arg), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1568, __FUNCTION__))->typed.type) : (*((const_cast<tree *> (tree_operand_check ((arg), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1568, __FUNCTION__))))))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1568, __FUNCTION__))))))->base.code) == TYPE_PACK_EXPANSION ? ((contains_struct_check (((*((const_cast<tree *> (tree_vec_elt_check (((((enum tree_code) (arg)->base.code) == TYPE_ARGUMENT_PACK ? ((contains_struct_check ((arg), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1568, __FUNCTION__))->typed.type) : (*((const_cast<tree *> (tree_operand_check ((arg), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1568, __FUNCTION__))))))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1568, __FUNCTION__)))))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1568, __FUNCTION__))->typed.type) : (*((const_cast<tree *> (tree_operand_check (((*((const_cast<tree *> (tree_vec_elt_check (((((enum tree_code) (arg)->base.code) == TYPE_ARGUMENT_PACK ? ((contains_struct_check ((arg), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1568, __FUNCTION__))->typed.type) : (*((const_cast<tree *> (tree_operand_check ((arg), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1568, __FUNCTION__))))))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1568, __FUNCTION__)))))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1568, __FUNCTION__)))))); | |||
1569 | ||||
1570 | /* Build the concept constraint-expression. */ | |||
1571 | tree tmpl = DECL_TI_TEMPLATE (con)((struct tree_template_info*)(tree_check (((((contains_struct_check ((template_info_decl_check ((con), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1571, __FUNCTION__)), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1571, __FUNCTION__))->decl_common.lang_specific) ->u. min.template_info)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1571, __FUNCTION__, (TEMPLATE_INFO))))->tmpl; | |||
1572 | tree check = tmpl; | |||
1573 | if (TREE_CODE (con)((enum tree_code) (con)->base.code) == FUNCTION_DECL) | |||
1574 | check = ovl_make (tmpl); | |||
1575 | check = build_concept_check (check, arg, args, tf_warning_or_error); | |||
1576 | ||||
1577 | /* Make the check a fold-expression if needed. */ | |||
1578 | if (apply_to_each_p && declared_pack_p) | |||
1579 | check = finish_left_unary_fold_expr (check, TRUTH_ANDIF_EXPR); | |||
1580 | ||||
1581 | return check; | |||
1582 | } | |||
1583 | ||||
1584 | /* Returns a conjunction of shorthand requirements for the template | |||
1585 | parameter list PARMS. Note that the requirements are stored in | |||
1586 | the TYPE of each tree node. */ | |||
1587 | ||||
1588 | tree | |||
1589 | get_shorthand_constraints (tree parms) | |||
1590 | { | |||
1591 | tree result = NULL_TREE(tree) __null; | |||
1592 | parms = INNERMOST_TEMPLATE_PARMS (parms)((tree_check ((parms), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1592, __FUNCTION__, (TREE_LIST)))->list.value); | |||
1593 | for (int i = 0; i < TREE_VEC_LENGTH (parms)((tree_check ((parms), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1593, __FUNCTION__, (TREE_VEC)))->base.u.length); ++i) | |||
1594 | { | |||
1595 | tree parm = TREE_VEC_ELT (parms, i)(*((const_cast<tree *> (tree_vec_elt_check ((parms), (i ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1595, __FUNCTION__))))); | |||
1596 | tree constr = TEMPLATE_PARM_CONSTRAINTS (parm)((contains_struct_check (((tree_check ((parm), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1596, __FUNCTION__, (TREE_LIST)))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1596, __FUNCTION__))->typed.type); | |||
1597 | result = combine_constraint_expressions (result, constr); | |||
1598 | } | |||
1599 | return result; | |||
1600 | } | |||
1601 | ||||
1602 | /* Get the deduced wildcard from a DEDUCED placeholder. If the deduced | |||
1603 | wildcard is a pack, return the first argument of that pack. */ | |||
1604 | ||||
1605 | static tree | |||
1606 | get_deduced_wildcard (tree wildcard) | |||
1607 | { | |||
1608 | if (ARGUMENT_PACK_P (wildcard)(((enum tree_code) (wildcard)->base.code) == TYPE_ARGUMENT_PACK || ((enum tree_code) (wildcard)->base.code) == NONTYPE_ARGUMENT_PACK )) | |||
1609 | wildcard = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (wildcard), 0)(*((const_cast<tree *> (tree_vec_elt_check (((((enum tree_code ) (wildcard)->base.code) == TYPE_ARGUMENT_PACK? ((contains_struct_check ((wildcard), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1609, __FUNCTION__))->typed.type) : (*((const_cast<tree *> (tree_operand_check ((wildcard), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1609, __FUNCTION__))))))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1609, __FUNCTION__))))); | |||
1610 | gcc_assert (TREE_CODE (wildcard) == WILDCARD_DECL)((void)(!(((enum tree_code) (wildcard)->base.code) == WILDCARD_DECL ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1610, __FUNCTION__), 0 : 0)); | |||
1611 | return wildcard; | |||
1612 | } | |||
1613 | ||||
1614 | /* Returns the prototype parameter for the nth deduced wildcard. */ | |||
1615 | ||||
1616 | static tree | |||
1617 | get_introduction_prototype (tree wildcards, int index) | |||
1618 | { | |||
1619 | return TREE_TYPE (get_deduced_wildcard (TREE_VEC_ELT (wildcards, index)))((contains_struct_check ((get_deduced_wildcard ((*((const_cast <tree *> (tree_vec_elt_check ((wildcards), (index), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1619, __FUNCTION__))))))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1619, __FUNCTION__))->typed.type); | |||
1620 | } | |||
1621 | ||||
1622 | /* Introduce a type template parameter. */ | |||
1623 | ||||
1624 | static tree | |||
1625 | introduce_type_template_parameter (tree wildcard, bool& non_type_p) | |||
1626 | { | |||
1627 | non_type_p = false; | |||
1628 | return finish_template_type_parm (class_type_nodecp_global_trees[CPTI_CLASS_TYPE], DECL_NAME (wildcard)((contains_struct_check ((wildcard), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1628, __FUNCTION__))->decl_minimal.name)); | |||
1629 | } | |||
1630 | ||||
1631 | /* Introduce a template template parameter. */ | |||
1632 | ||||
1633 | static tree | |||
1634 | introduce_template_template_parameter (tree wildcard, bool& non_type_p) | |||
1635 | { | |||
1636 | non_type_p = false; | |||
1637 | begin_template_parm_list (); | |||
1638 | current_template_parmsscope_chain->template_parms = DECL_TEMPLATE_PARMS (TREE_TYPE (wildcard))((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((((contains_struct_check ((wildcard), (TS_TYPED ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1638, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1638, __FUNCTION__, (TEMPLATE_DECL))))))))->arguments; | |||
1639 | end_template_parm_list (); | |||
1640 | return finish_template_template_parm (class_type_nodecp_global_trees[CPTI_CLASS_TYPE], DECL_NAME (wildcard)((contains_struct_check ((wildcard), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1640, __FUNCTION__))->decl_minimal.name)); | |||
1641 | } | |||
1642 | ||||
1643 | /* Introduce a template non-type parameter. */ | |||
1644 | ||||
1645 | static tree | |||
1646 | introduce_nontype_template_parameter (tree wildcard, bool& non_type_p) | |||
1647 | { | |||
1648 | non_type_p = true; | |||
1649 | tree parm = copy_decl (TREE_TYPE (wildcard)((contains_struct_check ((wildcard), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1649, __FUNCTION__))->typed.type)); | |||
1650 | DECL_NAME (parm)((contains_struct_check ((parm), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1650, __FUNCTION__))->decl_minimal.name) = DECL_NAME (wildcard)((contains_struct_check ((wildcard), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1650, __FUNCTION__))->decl_minimal.name); | |||
1651 | return parm; | |||
1652 | } | |||
1653 | ||||
1654 | /* Introduce a single template parameter. */ | |||
1655 | ||||
1656 | static tree | |||
1657 | build_introduced_template_parameter (tree wildcard, bool& non_type_p) | |||
1658 | { | |||
1659 | tree proto = TREE_TYPE (wildcard)((contains_struct_check ((wildcard), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1659, __FUNCTION__))->typed.type); | |||
1660 | ||||
1661 | tree parm; | |||
1662 | if (TREE_CODE (proto)((enum tree_code) (proto)->base.code) == TYPE_DECL) | |||
1663 | parm = introduce_type_template_parameter (wildcard, non_type_p); | |||
1664 | else if (TREE_CODE (proto)((enum tree_code) (proto)->base.code) == TEMPLATE_DECL) | |||
1665 | parm = introduce_template_template_parameter (wildcard, non_type_p); | |||
1666 | else | |||
1667 | parm = introduce_nontype_template_parameter (wildcard, non_type_p); | |||
1668 | ||||
1669 | /* Wrap in a TREE_LIST for process_template_parm. Note that introduced | |||
1670 | parameters do not retain the defaults from the source parameter. */ | |||
1671 | return build_tree_list (NULL_TREE(tree) __null, parm); | |||
1672 | } | |||
1673 | ||||
1674 | /* Introduce a single template parameter. */ | |||
1675 | ||||
1676 | static tree | |||
1677 | introduce_template_parameter (tree parms, tree wildcard) | |||
1678 | { | |||
1679 | gcc_assert (!ARGUMENT_PACK_P (wildcard))((void)(!(!(((enum tree_code) (wildcard)->base.code) == TYPE_ARGUMENT_PACK || ((enum tree_code) (wildcard)->base.code) == NONTYPE_ARGUMENT_PACK )) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1679, __FUNCTION__), 0 : 0)); | |||
1680 | tree proto = TREE_TYPE (wildcard)((contains_struct_check ((wildcard), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1680, __FUNCTION__))->typed.type); | |||
1681 | location_t loc = DECL_SOURCE_LOCATION (wildcard)((contains_struct_check ((wildcard), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1681, __FUNCTION__))->decl_minimal.locus); | |||
1682 | ||||
1683 | /* Diagnose the case where we have C{...Args}. */ | |||
1684 | if (WILDCARD_PACK_P (wildcard)((tree_not_check2 ((wildcard), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1684, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_0)) | |||
1685 | { | |||
1686 | tree id = DECL_NAME (wildcard)((contains_struct_check ((wildcard), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1686, __FUNCTION__))->decl_minimal.name); | |||
1687 | error_at (loc, "%qE cannot be introduced with an ellipsis %<...%>", id); | |||
1688 | inform (DECL_SOURCE_LOCATION (proto)((contains_struct_check ((proto), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1688, __FUNCTION__))->decl_minimal.locus), "prototype declared here"); | |||
1689 | } | |||
1690 | ||||
1691 | bool non_type_p; | |||
1692 | tree parm = build_introduced_template_parameter (wildcard, non_type_p); | |||
1693 | return process_template_parm (parms, loc, parm, non_type_p, false); | |||
1694 | } | |||
1695 | ||||
1696 | /* Introduce a template parameter pack. */ | |||
1697 | ||||
1698 | static tree | |||
1699 | introduce_template_parameter_pack (tree parms, tree wildcard) | |||
1700 | { | |||
1701 | bool non_type_p; | |||
1702 | tree parm = build_introduced_template_parameter (wildcard, non_type_p); | |||
1703 | location_t loc = DECL_SOURCE_LOCATION (wildcard)((contains_struct_check ((wildcard), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1703, __FUNCTION__))->decl_minimal.locus); | |||
1704 | return process_template_parm (parms, loc, parm, non_type_p, true); | |||
1705 | } | |||
1706 | ||||
1707 | /* Introduce the nth template parameter. */ | |||
1708 | ||||
1709 | static tree | |||
1710 | introduce_template_parameter (tree parms, tree wildcards, int& index) | |||
1711 | { | |||
1712 | tree deduced = TREE_VEC_ELT (wildcards, index++)(*((const_cast<tree *> (tree_vec_elt_check ((wildcards) , (index++), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1712, __FUNCTION__))))); | |||
1713 | return introduce_template_parameter (parms, deduced); | |||
1714 | } | |||
1715 | ||||
1716 | /* Introduce either a template parameter pack or a list of template | |||
1717 | parameters. */ | |||
1718 | ||||
1719 | static tree | |||
1720 | introduce_template_parameters (tree parms, tree wildcards, int& index) | |||
1721 | { | |||
1722 | /* If the prototype was a parameter, we better have deduced an | |||
1723 | argument pack, and that argument must be the last deduced value | |||
1724 | in the wildcard vector. */ | |||
1725 | tree deduced = TREE_VEC_ELT (wildcards, index++)(*((const_cast<tree *> (tree_vec_elt_check ((wildcards) , (index++), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1725, __FUNCTION__))))); | |||
1726 | gcc_assert (ARGUMENT_PACK_P (deduced))((void)(!((((enum tree_code) (deduced)->base.code) == TYPE_ARGUMENT_PACK || ((enum tree_code) (deduced)->base.code) == NONTYPE_ARGUMENT_PACK )) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1726, __FUNCTION__), 0 : 0)); | |||
1727 | gcc_assert (index == TREE_VEC_LENGTH (wildcards))((void)(!(index == ((tree_check ((wildcards), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1727, __FUNCTION__, (TREE_VEC)))->base.u.length)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1727, __FUNCTION__), 0 : 0)); | |||
1728 | ||||
1729 | /* Introduce each element in the pack. */ | |||
1730 | tree args = ARGUMENT_PACK_ARGS (deduced)(((enum tree_code) (deduced)->base.code) == TYPE_ARGUMENT_PACK ? ((contains_struct_check ((deduced), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1730, __FUNCTION__))->typed.type) : (*((const_cast<tree *> (tree_operand_check ((deduced), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1730, __FUNCTION__)))))); | |||
1731 | for (int i = 0; i < TREE_VEC_LENGTH (args)((tree_check ((args), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1731, __FUNCTION__, (TREE_VEC)))->base.u.length); ++i) | |||
1732 | { | |||
1733 | tree arg = TREE_VEC_ELT (args, i)(*((const_cast<tree *> (tree_vec_elt_check ((args), (i) , "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1733, __FUNCTION__))))); | |||
1734 | if (WILDCARD_PACK_P (arg)((tree_not_check2 ((arg), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1734, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_0)) | |||
1735 | parms = introduce_template_parameter_pack (parms, arg); | |||
1736 | else | |||
1737 | parms = introduce_template_parameter (parms, arg); | |||
1738 | } | |||
1739 | ||||
1740 | return parms; | |||
1741 | } | |||
1742 | ||||
1743 | /* Builds the template parameter list PARMS by chaining introduced | |||
1744 | parameters from the WILDCARD vector. INDEX is the position of | |||
1745 | the current parameter. */ | |||
1746 | ||||
1747 | static tree | |||
1748 | process_introduction_parms (tree parms, tree wildcards, int& index) | |||
1749 | { | |||
1750 | tree proto = get_introduction_prototype (wildcards, index); | |||
1751 | if (template_parameter_pack_p (proto)) | |||
1752 | return introduce_template_parameters (parms, wildcards, index); | |||
1753 | else | |||
1754 | return introduce_template_parameter (parms, wildcards, index); | |||
1755 | } | |||
1756 | ||||
1757 | /* Ensure that all template parameters have been introduced for the concept | |||
1758 | named in CHECK. If not, emit a diagnostic. | |||
1759 | ||||
1760 | Note that implicitly introducing a parameter with a default argument | |||
1761 | creates a case where a parameter is declared, but unnamed, making | |||
1762 | it unusable in the definition. */ | |||
1763 | ||||
1764 | static bool | |||
1765 | check_introduction_list (tree intros, tree check) | |||
1766 | { | |||
1767 | check = unpack_concept_check (check); | |||
1768 | tree tmpl = TREE_OPERAND (check, 0)(*((const_cast<tree*> (tree_operand_check ((check), (0) , "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1768, __FUNCTION__))))); | |||
1769 | if (OVL_P (tmpl)(((enum tree_code) (tmpl)->base.code) == FUNCTION_DECL || ( (enum tree_code) (tmpl)->base.code) == OVERLOAD)) | |||
1770 | tmpl = OVL_FIRST (tmpl)ovl_first (tmpl); | |||
1771 | ||||
1772 | tree parms = DECL_INNERMOST_TEMPLATE_PARMS (tmpl)((tree_check ((((struct tree_template_decl *)(const_cast<union tree_node *> ((((tree_check ((tmpl), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1772, __FUNCTION__, (TEMPLATE_DECL))))))))->arguments), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1772, __FUNCTION__, (TREE_LIST)))->list.value); | |||
1773 | if (TREE_VEC_LENGTH (intros)((tree_check ((intros), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1773, __FUNCTION__, (TREE_VEC)))->base.u.length) < TREE_VEC_LENGTH (parms)((tree_check ((parms), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1773, __FUNCTION__, (TREE_VEC)))->base.u.length)) | |||
1774 | { | |||
1775 | error_at (input_location, "all template parameters of %qD must " | |||
1776 | "be introduced", tmpl); | |||
1777 | return false; | |||
1778 | } | |||
1779 | ||||
1780 | return true; | |||
1781 | } | |||
1782 | ||||
1783 | /* Associates a constraint check to the current template based on the | |||
1784 | introduction parameters. INTRO_LIST must be a TREE_VEC of WILDCARD_DECLs | |||
1785 | containing a chained PARM_DECL which contains the identifier as well as | |||
1786 | the source location. TMPL_DECL is the decl for the concept being used. | |||
1787 | If we take a concept, C, this will form a check in the form of | |||
1788 | C<INTRO_LIST> filling in any extra arguments needed by the defaults | |||
1789 | deduced. | |||
1790 | ||||
1791 | Returns NULL_TREE if no concept could be matched and error_mark_node if | |||
1792 | an error occurred when matching. */ | |||
1793 | ||||
1794 | tree | |||
1795 | finish_template_introduction (tree tmpl_decl, | |||
1796 | tree intro_list, | |||
1797 | location_t intro_loc) | |||
1798 | { | |||
1799 | /* Build a concept check to deduce the actual parameters. */ | |||
1800 | tree expr = build_concept_check (tmpl_decl, intro_list, tf_none); | |||
1801 | if (expr == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1802 | { | |||
1803 | error_at (intro_loc, "cannot deduce template parameters from " | |||
1804 | "introduction list"); | |||
1805 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1806 | } | |||
1807 | ||||
1808 | if (!check_introduction_list (intro_list, expr)) | |||
1809 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1810 | ||||
1811 | tree parms = deduce_concept_introduction (expr); | |||
1812 | if (!parms) | |||
1813 | return NULL_TREE(tree) __null; | |||
1814 | ||||
1815 | /* Build template parameter scope for introduction. */ | |||
1816 | tree parm_list = NULL_TREE(tree) __null; | |||
1817 | begin_template_parm_list (); | |||
1818 | int nargs = MIN (TREE_VEC_LENGTH (parms), TREE_VEC_LENGTH (intro_list))((((tree_check ((parms), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1818, __FUNCTION__, (TREE_VEC)))->base.u.length)) < ( ((tree_check ((intro_list), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1818, __FUNCTION__, (TREE_VEC)))->base.u.length)) ? (((tree_check ((parms), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1818, __FUNCTION__, (TREE_VEC)))->base.u.length)) : (((tree_check ((intro_list), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1818, __FUNCTION__, (TREE_VEC)))->base.u.length))); | |||
1819 | for (int n = 0; n < nargs; ) | |||
1820 | parm_list = process_introduction_parms (parm_list, parms, n); | |||
1821 | parm_list = end_template_parm_list (parm_list); | |||
1822 | ||||
1823 | /* Update the number of arguments to reflect the number of deduced | |||
1824 | template parameter introductions. */ | |||
1825 | nargs = TREE_VEC_LENGTH (parm_list)((tree_check ((parm_list), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1825, __FUNCTION__, (TREE_VEC)))->base.u.length); | |||
1826 | ||||
1827 | /* Determine if any errors occurred during matching. */ | |||
1828 | for (int i = 0; i < TREE_VEC_LENGTH (parm_list)((tree_check ((parm_list), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1828, __FUNCTION__, (TREE_VEC)))->base.u.length); ++i) | |||
1829 | if (TREE_VALUE (TREE_VEC_ELT (parm_list, i))((tree_check (((*((const_cast<tree *> (tree_vec_elt_check ((parm_list), (i), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1829, __FUNCTION__)))))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1829, __FUNCTION__, (TREE_LIST)))->list.value) == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1830 | { | |||
1831 | end_template_decl (); | |||
1832 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1833 | } | |||
1834 | ||||
1835 | /* Build a concept check for our constraint. */ | |||
1836 | tree check_args = make_tree_vec (nargs); | |||
1837 | int n = 0; | |||
1838 | for (; n < TREE_VEC_LENGTH (parm_list)((tree_check ((parm_list), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1838, __FUNCTION__, (TREE_VEC)))->base.u.length); ++n) | |||
1839 | { | |||
1840 | tree parm = TREE_VEC_ELT (parm_list, n)(*((const_cast<tree *> (tree_vec_elt_check ((parm_list) , (n), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1840, __FUNCTION__))))); | |||
1841 | TREE_VEC_ELT (check_args, n)(*((const_cast<tree *> (tree_vec_elt_check ((check_args ), (n), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1841, __FUNCTION__))))) = template_parm_to_arg (parm); | |||
1842 | } | |||
1843 | SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (check_args, n)((contains_struct_check (((tree_check ((check_args), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1843, __FUNCTION__, (TREE_VEC)))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1843, __FUNCTION__))->common.chain) = build_int_cst ((tree ) __null, n); | |||
1844 | ||||
1845 | /* If the template expects more parameters we should be able | |||
1846 | to use the defaults from our deduced concept. */ | |||
1847 | for (; n < TREE_VEC_LENGTH (parms)((tree_check ((parms), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1847, __FUNCTION__, (TREE_VEC)))->base.u.length); ++n) | |||
1848 | TREE_VEC_ELT (check_args, n)(*((const_cast<tree *> (tree_vec_elt_check ((check_args ), (n), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1848, __FUNCTION__))))) = TREE_VEC_ELT (parms, n)(*((const_cast<tree *> (tree_vec_elt_check ((parms), (n ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1848, __FUNCTION__))))); | |||
1849 | ||||
1850 | /* Associate the constraint. */ | |||
1851 | tree check = build_concept_check (tmpl_decl, | |||
1852 | check_args, | |||
1853 | tf_warning_or_error); | |||
1854 | TEMPLATE_PARMS_CONSTRAINTS (current_template_parms)((contains_struct_check (((tree_check ((scope_chain->template_parms ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1854, __FUNCTION__, (TREE_LIST)))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1854, __FUNCTION__))->typed.type) = check; | |||
1855 | ||||
1856 | return parm_list; | |||
1857 | } | |||
1858 | ||||
1859 | ||||
1860 | /* Given the concept check T from a constrained-type-specifier, extract | |||
1861 | its TMPL and ARGS. FIXME why do we need two different forms of | |||
1862 | constrained-type-specifier? */ | |||
1863 | ||||
1864 | void | |||
1865 | placeholder_extract_concept_and_args (tree t, tree &tmpl, tree &args) | |||
1866 | { | |||
1867 | if (concept_check_p (t)) | |||
1868 | { | |||
1869 | t = unpack_concept_check (t); | |||
1870 | tmpl = TREE_OPERAND (t, 0)(*((const_cast<tree*> (tree_operand_check ((t), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1870, __FUNCTION__))))); | |||
1871 | if (TREE_CODE (tmpl)((enum tree_code) (tmpl)->base.code) == OVERLOAD) | |||
1872 | tmpl = OVL_FIRST (tmpl)ovl_first (tmpl); | |||
1873 | args = TREE_OPERAND (t, 1)(*((const_cast<tree*> (tree_operand_check ((t), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1873, __FUNCTION__))))); | |||
1874 | return; | |||
1875 | } | |||
1876 | ||||
1877 | if (TREE_CODE (t)((enum tree_code) (t)->base.code) == TYPE_DECL) | |||
1878 | { | |||
1879 | /* A constrained parameter. Build a constraint check | |||
1880 | based on the prototype parameter and then extract the | |||
1881 | arguments from that. */ | |||
1882 | tree proto = CONSTRAINED_PARM_PROTOTYPE (t)((contains_struct_check (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1882, __FUNCTION__, (TYPE_DECL)))), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1882, __FUNCTION__))->decl_common.initial); | |||
1883 | tree check = finish_shorthand_constraint (proto, t); | |||
1884 | placeholder_extract_concept_and_args (check, tmpl, args); | |||
1885 | return; | |||
1886 | } | |||
1887 | } | |||
1888 | ||||
1889 | /* Returns true iff the placeholders C1 and C2 are equivalent. C1 | |||
1890 | and C2 can be either TEMPLATE_TYPE_PARM or template-ids. */ | |||
1891 | ||||
1892 | bool | |||
1893 | equivalent_placeholder_constraints (tree c1, tree c2) | |||
1894 | { | |||
1895 | if (c1 && TREE_CODE (c1)((enum tree_code) (c1)->base.code) == TEMPLATE_TYPE_PARM) | |||
1896 | /* A constrained auto. */ | |||
1897 | c1 = PLACEHOLDER_TYPE_CONSTRAINTS (c1)((contains_struct_check ((((tree_class_check ((c1), (tcc_type ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1897, __FUNCTION__))->type_common.name)), (TS_DECL_COMMON ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1897, __FUNCTION__))->decl_common.size_unit); | |||
1898 | if (c2 && TREE_CODE (c2)((enum tree_code) (c2)->base.code) == TEMPLATE_TYPE_PARM) | |||
1899 | c2 = PLACEHOLDER_TYPE_CONSTRAINTS (c2)((contains_struct_check ((((tree_class_check ((c2), (tcc_type ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1899, __FUNCTION__))->type_common.name)), (TS_DECL_COMMON ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1899, __FUNCTION__))->decl_common.size_unit); | |||
1900 | ||||
1901 | if (c1 == c2) | |||
1902 | return true; | |||
1903 | if (!c1 || !c2) | |||
1904 | return false; | |||
1905 | if (c1 == error_mark_nodeglobal_trees[TI_ERROR_MARK] || c2 == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1906 | /* We get here during satisfaction; when a deduction constraint | |||
1907 | fails, substitution can produce an error_mark_node for the | |||
1908 | placeholder constraints. */ | |||
1909 | return false; | |||
1910 | ||||
1911 | tree t1, t2, a1, a2; | |||
1912 | placeholder_extract_concept_and_args (c1, t1, a1); | |||
1913 | placeholder_extract_concept_and_args (c2, t2, a2); | |||
1914 | ||||
1915 | if (t1 != t2) | |||
1916 | return false; | |||
1917 | ||||
1918 | int len1 = TREE_VEC_LENGTH (a1)((tree_check ((a1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1918, __FUNCTION__, (TREE_VEC)))->base.u.length); | |||
1919 | int len2 = TREE_VEC_LENGTH (a2)((tree_check ((a2), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1919, __FUNCTION__, (TREE_VEC)))->base.u.length); | |||
1920 | if (len1 != len2) | |||
1921 | return false; | |||
1922 | ||||
1923 | /* Skip the first argument so we don't infinitely recurse. | |||
1924 | Also, they may differ in template parameter index. */ | |||
1925 | for (int i = 1; i < len1; ++i) | |||
1926 | { | |||
1927 | tree t1 = TREE_VEC_ELT (a1, i)(*((const_cast<tree *> (tree_vec_elt_check ((a1), (i), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1927, __FUNCTION__))))); | |||
1928 | tree t2 = TREE_VEC_ELT (a2, i)(*((const_cast<tree *> (tree_vec_elt_check ((a2), (i), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1928, __FUNCTION__))))); | |||
1929 | if (!template_args_equal (t1, t2)) | |||
1930 | return false; | |||
1931 | } | |||
1932 | return true; | |||
1933 | } | |||
1934 | ||||
1935 | /* Return a hash value for the placeholder ATOMIC_CONSTR C. */ | |||
1936 | ||||
1937 | hashval_t | |||
1938 | hash_placeholder_constraint (tree c) | |||
1939 | { | |||
1940 | tree t, a; | |||
1941 | placeholder_extract_concept_and_args (c, t, a); | |||
1942 | ||||
1943 | /* Like hash_tmpl_and_args, but skip the first argument. */ | |||
1944 | hashval_t val = iterative_hash_object (DECL_UID (t), 0)iterative_hash (&((contains_struct_check ((t), (TS_DECL_MINIMAL ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1944, __FUNCTION__))->decl_minimal.uid), sizeof (((contains_struct_check ((t), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1944, __FUNCTION__))->decl_minimal.uid)), 0); | |||
1945 | ||||
1946 | for (int i = TREE_VEC_LENGTH (a)((tree_check ((a), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1946, __FUNCTION__, (TREE_VEC)))->base.u.length)-1; i > 0; --i) | |||
1947 | val = iterative_hash_template_arg (TREE_VEC_ELT (a, i)(*((const_cast<tree *> (tree_vec_elt_check ((a), (i), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1947, __FUNCTION__))))), val); | |||
1948 | ||||
1949 | return val; | |||
1950 | } | |||
1951 | ||||
1952 | /* Substitute through the simple requirement. */ | |||
1953 | ||||
1954 | static tree | |||
1955 | tsubst_valid_expression_requirement (tree t, tree args, subst_info info) | |||
1956 | { | |||
1957 | tree r = tsubst_expr (t, args, info.complain, info.in_decl, false); | |||
1958 | if (convert_to_void (r, ICV_STATEMENT, info.complain) == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1959 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1960 | return r; | |||
1961 | } | |||
1962 | ||||
1963 | ||||
1964 | /* Substitute through the simple requirement. */ | |||
1965 | ||||
1966 | static tree | |||
1967 | tsubst_simple_requirement (tree t, tree args, subst_info info) | |||
1968 | { | |||
1969 | tree t0 = TREE_OPERAND (t, 0)(*((const_cast<tree*> (tree_operand_check ((t), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1969, __FUNCTION__))))); | |||
1970 | tree expr = tsubst_valid_expression_requirement (t0, args, info); | |||
1971 | if (expr == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1972 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1973 | return finish_simple_requirement (EXPR_LOCATION (t)((((t)) && ((tree_code_type[(int) (((enum tree_code) ( (t))->base.code))]) >= tcc_reference && (tree_code_type [(int) (((enum tree_code) ((t))->base.code))]) <= tcc_expression )) ? (t)->exp.locus : ((location_t) 0)), expr); | |||
1974 | } | |||
1975 | ||||
1976 | /* Substitute through the type requirement. */ | |||
1977 | ||||
1978 | static tree | |||
1979 | tsubst_type_requirement (tree t, tree args, subst_info info) | |||
1980 | { | |||
1981 | tree t0 = TREE_OPERAND (t, 0)(*((const_cast<tree*> (tree_operand_check ((t), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 1981, __FUNCTION__))))); | |||
1982 | tree type = tsubst (t0, args, info.complain, info.in_decl); | |||
1983 | if (type == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1984 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1985 | return finish_type_requirement (EXPR_LOCATION (t)((((t)) && ((tree_code_type[(int) (((enum tree_code) ( (t))->base.code))]) >= tcc_reference && (tree_code_type [(int) (((enum tree_code) ((t))->base.code))]) <= tcc_expression )) ? (t)->exp.locus : ((location_t) 0)), type); | |||
1986 | } | |||
1987 | ||||
1988 | /* True if TYPE can be deduced from EXPR. */ | |||
1989 | ||||
1990 | static bool | |||
1991 | type_deducible_p (tree expr, tree type, tree placeholder, tree args, | |||
1992 | subst_info info) | |||
1993 | { | |||
1994 | /* Make sure deduction is performed against ( EXPR ), so that | |||
1995 | references are preserved in the result. */ | |||
1996 | expr = force_paren_expr_uneval (expr); | |||
1997 | ||||
1998 | /* Replace the constraints with the instantiated constraints. This | |||
1999 | substitutes args into any template parameters in the trailing | |||
2000 | result type. */ | |||
2001 | tree saved_constr = PLACEHOLDER_TYPE_CONSTRAINTS (placeholder)((contains_struct_check ((((tree_class_check ((placeholder), ( tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2001, __FUNCTION__))->type_common.name)), (TS_DECL_COMMON ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2001, __FUNCTION__))->decl_common.size_unit); | |||
2002 | tree subst_constr | |||
2003 | = tsubst_constraint (saved_constr, | |||
2004 | args, | |||
2005 | info.complain | tf_partial, | |||
2006 | info.in_decl); | |||
2007 | ||||
2008 | if (subst_constr == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2009 | return false; | |||
2010 | ||||
2011 | PLACEHOLDER_TYPE_CONSTRAINTS (placeholder)((contains_struct_check ((((tree_class_check ((placeholder), ( tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2011, __FUNCTION__))->type_common.name)), (TS_DECL_COMMON ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2011, __FUNCTION__))->decl_common.size_unit) = subst_constr; | |||
2012 | ||||
2013 | /* Temporarily unlink the canonical type. */ | |||
2014 | tree saved_type = TYPE_CANONICAL (placeholder)((tree_class_check ((placeholder), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2014, __FUNCTION__))->type_common.canonical); | |||
2015 | TYPE_CANONICAL (placeholder)((tree_class_check ((placeholder), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2015, __FUNCTION__))->type_common.canonical) = NULL_TREE(tree) __null; | |||
2016 | ||||
2017 | tree deduced_type | |||
2018 | = do_auto_deduction (type, | |||
2019 | expr, | |||
2020 | placeholder, | |||
2021 | info.complain, | |||
2022 | adc_requirement); | |||
2023 | ||||
2024 | PLACEHOLDER_TYPE_CONSTRAINTS (placeholder)((contains_struct_check ((((tree_class_check ((placeholder), ( tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2024, __FUNCTION__))->type_common.name)), (TS_DECL_COMMON ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2024, __FUNCTION__))->decl_common.size_unit) = saved_constr; | |||
2025 | TYPE_CANONICAL (placeholder)((tree_class_check ((placeholder), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2025, __FUNCTION__))->type_common.canonical) = saved_type; | |||
2026 | ||||
2027 | if (deduced_type == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2028 | return false; | |||
2029 | ||||
2030 | return true; | |||
2031 | } | |||
2032 | ||||
2033 | /* True if EXPR can not be converted to TYPE. */ | |||
2034 | ||||
2035 | static bool | |||
2036 | expression_convertible_p (tree expr, tree type, subst_info info) | |||
2037 | { | |||
2038 | tree conv = | |||
2039 | perform_direct_initialization_if_possible (type, expr, false, | |||
2040 | info.complain); | |||
2041 | if (conv == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2042 | return false; | |||
2043 | if (conv == NULL_TREE(tree) __null) | |||
2044 | { | |||
2045 | if (info.complain & tf_error) | |||
2046 | { | |||
2047 | location_t loc = EXPR_LOC_OR_LOC (expr, input_location)((((IS_ADHOC_LOC (((((expr)) && ((tree_code_type[(int ) (((enum tree_code) ((expr))->base.code))]) >= tcc_reference && (tree_code_type[(int) (((enum tree_code) ((expr)) ->base.code))]) <= tcc_expression)) ? (expr)->exp.locus : ((location_t) 0)))) ? get_location_from_adhoc_loc (line_table , ((((expr)) && ((tree_code_type[(int) (((enum tree_code ) ((expr))->base.code))]) >= tcc_reference && ( tree_code_type[(int) (((enum tree_code) ((expr))->base.code ))]) <= tcc_expression)) ? (expr)->exp.locus : ((location_t ) 0))) : (((((expr)) && ((tree_code_type[(int) (((enum tree_code) ((expr))->base.code))]) >= tcc_reference && (tree_code_type[(int) (((enum tree_code) ((expr))->base.code ))]) <= tcc_expression)) ? (expr)->exp.locus : ((location_t ) 0)))) != ((location_t) 0)) ? (expr)->exp.locus : (input_location )); | |||
2048 | error_at (loc, "cannot convert %qE to %qT", expr, type); | |||
2049 | } | |||
2050 | return false; | |||
2051 | } | |||
2052 | return true; | |||
2053 | } | |||
2054 | ||||
2055 | ||||
2056 | /* Substitute through the compound requirement. */ | |||
2057 | ||||
2058 | static tree | |||
2059 | tsubst_compound_requirement (tree t, tree args, subst_info info) | |||
2060 | { | |||
2061 | tree t0 = TREE_OPERAND (t, 0)(*((const_cast<tree*> (tree_operand_check ((t), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2061, __FUNCTION__))))); | |||
2062 | tree t1 = TREE_OPERAND (t, 1)(*((const_cast<tree*> (tree_operand_check ((t), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2062, __FUNCTION__))))); | |||
2063 | tree expr = tsubst_valid_expression_requirement (t0, args, info); | |||
2064 | if (expr == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2065 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2066 | ||||
2067 | /* Check the noexcept condition. */ | |||
2068 | bool noexcept_p = COMPOUND_REQ_NOEXCEPT_P (t)((tree_not_check2 (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2068, __FUNCTION__, (COMPOUND_REQ)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2068, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_0); | |||
2069 | if (noexcept_p && !expr_noexcept_p (expr, tf_none)) | |||
2070 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2071 | ||||
2072 | /* Substitute through the type expression, if any. */ | |||
2073 | tree type = tsubst (t1, args, info.complain, info.in_decl); | |||
2074 | if (type == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2075 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2076 | ||||
2077 | subst_info quiet (tf_none, info.in_decl); | |||
2078 | ||||
2079 | /* Check expression against the result type. */ | |||
2080 | if (type) | |||
2081 | { | |||
2082 | if (tree placeholder = type_uses_auto (type)) | |||
2083 | { | |||
2084 | if (!type_deducible_p (expr, type, placeholder, args, quiet)) | |||
2085 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2086 | } | |||
2087 | else if (!expression_convertible_p (expr, type, quiet)) | |||
2088 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2089 | } | |||
2090 | ||||
2091 | return finish_compound_requirement (EXPR_LOCATION (t)((((t)) && ((tree_code_type[(int) (((enum tree_code) ( (t))->base.code))]) >= tcc_reference && (tree_code_type [(int) (((enum tree_code) ((t))->base.code))]) <= tcc_expression )) ? (t)->exp.locus : ((location_t) 0)), | |||
2092 | expr, type, noexcept_p); | |||
2093 | } | |||
2094 | ||||
2095 | static tree | |||
2096 | tsubst_nested_requirement (tree t, tree args, subst_info info) | |||
2097 | { | |||
2098 | /* Perform satisfaction quietly with the regular normal form. */ | |||
2099 | sat_info quiet (tf_none, info.in_decl); | |||
2100 | tree norm = TREE_VALUE (TREE_TYPE (t))((tree_check ((((contains_struct_check ((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2100, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2100, __FUNCTION__, (TREE_LIST)))->list.value); | |||
2101 | tree diag_norm = TREE_PURPOSE (TREE_TYPE (t))((tree_check ((((contains_struct_check ((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2101, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2101, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
2102 | tree result = satisfy_constraint (norm, args, quiet); | |||
2103 | if (result == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2104 | { | |||
2105 | /* Replay the error using the diagnostic normal form. */ | |||
2106 | sat_info noisy (tf_warning_or_error, info.in_decl); | |||
2107 | satisfy_constraint (diag_norm, args, noisy); | |||
2108 | } | |||
2109 | if (result != boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]) | |||
2110 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2111 | return result; | |||
2112 | } | |||
2113 | ||||
2114 | /* Substitute ARGS into the requirement T. */ | |||
2115 | ||||
2116 | static tree | |||
2117 | tsubst_requirement (tree t, tree args, subst_info info) | |||
2118 | { | |||
2119 | iloc_sentinel loc_s (cp_expr_location (t)); | |||
2120 | switch (TREE_CODE (t)((enum tree_code) (t)->base.code)) | |||
2121 | { | |||
2122 | case SIMPLE_REQ: | |||
2123 | return tsubst_simple_requirement (t, args, info); | |||
2124 | case TYPE_REQ: | |||
2125 | return tsubst_type_requirement (t, args, info); | |||
2126 | case COMPOUND_REQ: | |||
2127 | return tsubst_compound_requirement (t, args, info); | |||
2128 | case NESTED_REQ: | |||
2129 | return tsubst_nested_requirement (t, args, info); | |||
2130 | default: | |||
2131 | break; | |||
2132 | } | |||
2133 | gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2133, __FUNCTION__)); | |||
2134 | } | |||
2135 | ||||
2136 | /* Substitute ARGS into the list of requirements T. Note that | |||
2137 | substitution failures here result in ill-formed programs. */ | |||
2138 | ||||
2139 | static tree | |||
2140 | tsubst_requirement_body (tree t, tree args, subst_info info) | |||
2141 | { | |||
2142 | tree result = NULL_TREE(tree) __null; | |||
2143 | while (t) | |||
2144 | { | |||
2145 | tree req = tsubst_requirement (TREE_VALUE (t)((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2145, __FUNCTION__, (TREE_LIST)))->list.value), args, info); | |||
2146 | if (req == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2147 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2148 | result = tree_cons (NULL_TREE(tree) __null, req, result); | |||
2149 | t = TREE_CHAIN (t)((contains_struct_check ((t), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2149, __FUNCTION__))->common.chain); | |||
2150 | } | |||
2151 | return nreverse (result); | |||
2152 | } | |||
2153 | ||||
2154 | static tree | |||
2155 | declare_constraint_vars (tree parms, tree vars) | |||
2156 | { | |||
2157 | tree s = vars; | |||
2158 | for (tree t = parms; t; t = DECL_CHAIN (t)(((contains_struct_check (((contains_struct_check ((t), (TS_DECL_MINIMAL ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2158, __FUNCTION__))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2158, __FUNCTION__))->common.chain))) | |||
2159 | { | |||
2160 | if (DECL_PACK_P (t)((tree_code_type[(int) (((enum tree_code) (t)->base.code)) ] == tcc_declaration) && (((enum tree_code) (((contains_struct_check ((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2160, __FUNCTION__))->typed.type))->base.code) == TYPE_PACK_EXPANSION || ((enum tree_code) (((contains_struct_check ((t), (TS_TYPED ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2160, __FUNCTION__))->typed.type))->base.code) == EXPR_PACK_EXPANSION ))) | |||
2161 | { | |||
2162 | tree pack = extract_fnparm_pack (t, &s); | |||
2163 | register_local_specialization (pack, t); | |||
2164 | } | |||
2165 | else | |||
2166 | { | |||
2167 | register_local_specialization (s, t); | |||
2168 | s = DECL_CHAIN (s)(((contains_struct_check (((contains_struct_check ((s), (TS_DECL_MINIMAL ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2168, __FUNCTION__))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2168, __FUNCTION__))->common.chain)); | |||
2169 | } | |||
2170 | } | |||
2171 | return vars; | |||
2172 | } | |||
2173 | ||||
2174 | /* Substitute through as if checking function parameter types. This | |||
2175 | will diagnose common parameter type errors. Returns error_mark_node | |||
2176 | if an error occurred. */ | |||
2177 | ||||
2178 | static tree | |||
2179 | check_constaint_variables (tree t, tree args, subst_info info) | |||
2180 | { | |||
2181 | tree types = NULL_TREE(tree) __null; | |||
2182 | tree p = t; | |||
2183 | while (p && !VOID_TYPE_P (p)(((enum tree_code) (p)->base.code) == VOID_TYPE)) | |||
2184 | { | |||
2185 | types = tree_cons (NULL_TREE(tree) __null, TREE_TYPE (p)((contains_struct_check ((p), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2185, __FUNCTION__))->typed.type), types); | |||
2186 | p = TREE_CHAIN (p)((contains_struct_check ((p), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2186, __FUNCTION__))->common.chain); | |||
2187 | } | |||
2188 | types = chainon (nreverse (types), void_list_nodeglobal_trees[TI_VOID_LIST_NODE]); | |||
2189 | return tsubst_function_parms (types, args, info.complain, info.in_decl); | |||
2190 | } | |||
2191 | ||||
2192 | /* A subroutine of tsubst_parameterized_constraint. Substitute ARGS | |||
2193 | into the parameter list T, producing a sequence of constraint | |||
2194 | variables, declared in the current scope. | |||
2195 | ||||
2196 | Note that the caller must establish a local specialization stack | |||
2197 | prior to calling this function since this substitution will | |||
2198 | declare the substituted parameters. */ | |||
2199 | ||||
2200 | static tree | |||
2201 | tsubst_constraint_variables (tree t, tree args, subst_info info) | |||
2202 | { | |||
2203 | /* Perform a trial substitution to check for type errors. */ | |||
2204 | tree parms = check_constaint_variables (t, args, info); | |||
2205 | if (parms == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2206 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2207 | ||||
2208 | /* Clear cp_unevaluated_operand across tsubst so that we get a proper chain | |||
2209 | of PARM_DECLs. */ | |||
2210 | int saved_unevaluated_operand = cp_unevaluated_operand; | |||
2211 | cp_unevaluated_operand = 0; | |||
2212 | tree vars = tsubst (t, args, info.complain, info.in_decl); | |||
2213 | cp_unevaluated_operand = saved_unevaluated_operand; | |||
2214 | if (vars == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2215 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2216 | return declare_constraint_vars (t, vars); | |||
2217 | } | |||
2218 | ||||
2219 | /* Substitute ARGS into the requires-expression T. [8.4.7]p6. The | |||
2220 | substitution of template arguments into a requires-expression | |||
2221 | may result in the formation of invalid types or expressions | |||
2222 | in its requirements ... In such cases, the expression evaluates | |||
2223 | to false; it does not cause the program to be ill-formed. | |||
2224 | ||||
2225 | However, there are cases where substitution must produce a | |||
2226 | new requires-expression, that is not a template constraint. | |||
2227 | For example: | |||
2228 | ||||
2229 | template<typename T> | |||
2230 | class X { | |||
2231 | template<typename U> | |||
2232 | static constexpr bool var = requires (U u) { T::fn(u); }; | |||
2233 | }; | |||
2234 | ||||
2235 | In the instantiation of X<Y> (assuming Y defines fn), then the | |||
2236 | instantiated requires-expression would include Y::fn(u). If any | |||
2237 | substitution in the requires-expression fails, we can immediately | |||
2238 | fold the expression to false, as would be the case e.g., when | |||
2239 | instantiation X<int>. */ | |||
2240 | ||||
2241 | tree | |||
2242 | tsubst_requires_expr (tree t, tree args, | |||
2243 | tsubst_flags_t complain, tree in_decl) | |||
2244 | { | |||
2245 | local_specialization_stack stack (lss_copy); | |||
2246 | ||||
2247 | subst_info info (complain, in_decl); | |||
2248 | ||||
2249 | /* A requires-expression is an unevaluated context. */ | |||
2250 | cp_unevaluated u; | |||
2251 | ||||
2252 | args = add_extra_args (REQUIRES_EXPR_EXTRA_ARGS (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2252, __FUNCTION__, (REQUIRES_EXPR)))), (2), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2252, __FUNCTION__))))), args); | |||
2253 | if (processing_template_declscope_chain->x_processing_template_decl) | |||
2254 | { | |||
2255 | /* We're partially instantiating a generic lambda. Substituting into | |||
2256 | this requires-expression now may cause its requirements to get | |||
2257 | checked out of order, so instead just remember the template | |||
2258 | arguments and wait until we can substitute them all at once. */ | |||
2259 | t = copy_node (t); | |||
2260 | REQUIRES_EXPR_EXTRA_ARGS (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2260, __FUNCTION__, (REQUIRES_EXPR)))), (2), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2260, __FUNCTION__))))) = build_extra_args (t, args, complain); | |||
2261 | return t; | |||
2262 | } | |||
2263 | ||||
2264 | tree parms = REQUIRES_EXPR_PARMS (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2264, __FUNCTION__, (REQUIRES_EXPR)))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2264, __FUNCTION__))))); | |||
2265 | if (parms) | |||
2266 | { | |||
2267 | parms = tsubst_constraint_variables (parms, args, info); | |||
2268 | if (parms == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2269 | return boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]; | |||
2270 | } | |||
2271 | ||||
2272 | tree reqs = REQUIRES_EXPR_REQS (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2272, __FUNCTION__, (REQUIRES_EXPR)))), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2272, __FUNCTION__))))); | |||
2273 | reqs = tsubst_requirement_body (reqs, args, info); | |||
2274 | if (reqs == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2275 | return boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]; | |||
2276 | ||||
2277 | return boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]; | |||
2278 | } | |||
2279 | ||||
2280 | /* Substitute ARGS into the constraint information CI, producing a new | |||
2281 | constraint record. */ | |||
2282 | ||||
2283 | tree | |||
2284 | tsubst_constraint_info (tree t, tree args, | |||
2285 | tsubst_flags_t complain, tree in_decl) | |||
2286 | { | |||
2287 | if (!t || t == error_mark_nodeglobal_trees[TI_ERROR_MARK] || !check_constraint_info (t)) | |||
2288 | return NULL_TREE(tree) __null; | |||
2289 | ||||
2290 | tree tr = tsubst_constraint (CI_TEMPLATE_REQS (t)check_constraint_info (check_nonnull (t))->template_reqs, args, complain, in_decl); | |||
2291 | tree dr = tsubst_constraint (CI_DECLARATOR_REQS (t)check_constraint_info (check_nonnull (t))->declarator_reqs, args, complain, in_decl); | |||
2292 | return build_constraints (tr, dr); | |||
2293 | } | |||
2294 | ||||
2295 | /* Substitute through a parameter mapping, in order to get the actual | |||
2296 | arguments used to instantiate an atomic constraint. This may fail | |||
2297 | if the substitution into arguments produces something ill-formed. */ | |||
2298 | ||||
2299 | static tree | |||
2300 | tsubst_parameter_mapping (tree map, tree args, subst_info info) | |||
2301 | { | |||
2302 | if (!map) | |||
2303 | return NULL_TREE(tree) __null; | |||
2304 | ||||
2305 | tsubst_flags_t complain = info.complain; | |||
2306 | tree in_decl = info.in_decl; | |||
2307 | ||||
2308 | tree result = NULL_TREE(tree) __null; | |||
2309 | for (tree p = map; p; p = TREE_CHAIN (p)((contains_struct_check ((p), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2309, __FUNCTION__))->common.chain)) | |||
2310 | { | |||
2311 | if (p == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2312 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2313 | tree parm = TREE_VALUE (p)((tree_check ((p), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2313, __FUNCTION__, (TREE_LIST)))->list.value); | |||
2314 | tree arg = TREE_PURPOSE (p)((tree_check ((p), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2314, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
2315 | tree new_arg = NULL_TREE(tree) __null; | |||
2316 | if (TYPE_P (arg)(tree_code_type[(int) (((enum tree_code) (arg)->base.code) )] == tcc_type)) | |||
2317 | { | |||
2318 | /* If a template parameter is declared with a placeholder, we can | |||
2319 | get those in the argument list if decltype is applied to the | |||
2320 | placeholder. For example: | |||
2321 | ||||
2322 | template<auto T> | |||
2323 | requires C<decltype(T)> | |||
2324 | void f() { } | |||
2325 | ||||
2326 | The normalized argument for C will be an auto type, so we'll | |||
2327 | need to deduce the actual argument from the corresponding | |||
2328 | initializer (whatever argument is provided for T), and use | |||
2329 | that result in the instantiated parameter mapping. */ | |||
2330 | if (tree auto_node = type_uses_auto (arg)) | |||
2331 | { | |||
2332 | int level; | |||
2333 | int index; | |||
2334 | template_parm_level_and_index (parm, &level, &index); | |||
2335 | tree init = TMPL_ARG (args, level, index)((*((const_cast<tree *> (tree_vec_elt_check ((((args && ((tree_check ((args), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2335, __FUNCTION__, (TREE_VEC)))->base.u.length) && (*((const_cast<tree *> (tree_vec_elt_check ((args), (0 ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2335, __FUNCTION__))))) && ((enum tree_code) ((*((const_cast <tree *> (tree_vec_elt_check ((args), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2335, __FUNCTION__))))))->base.code) == TREE_VEC) ? (*(( const_cast<tree *> (tree_vec_elt_check ((args), ((level ) - 1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2335, __FUNCTION__))))) : (args))), (index), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2335, __FUNCTION__)))))); | |||
2336 | new_arg = do_auto_deduction (arg, init, auto_node, | |||
2337 | complain, adc_variable_type, | |||
2338 | make_tree_vec (0)); | |||
2339 | } | |||
2340 | } | |||
2341 | else if (ARGUMENT_PACK_P (arg)(((enum tree_code) (arg)->base.code) == TYPE_ARGUMENT_PACK || ((enum tree_code) (arg)->base.code) == NONTYPE_ARGUMENT_PACK )) | |||
2342 | new_arg = tsubst_argument_pack (arg, args, complain, in_decl); | |||
2343 | if (!new_arg) | |||
2344 | { | |||
2345 | new_arg = tsubst_template_arg (arg, args, complain, in_decl); | |||
2346 | if (TYPE_P (new_arg)(tree_code_type[(int) (((enum tree_code) (new_arg)->base.code ))] == tcc_type)) | |||
2347 | new_arg = canonicalize_type_argument (new_arg, complain); | |||
2348 | if (TREE_CODE (new_arg)((enum tree_code) (new_arg)->base.code) == TYPE_ARGUMENT_PACK) | |||
2349 | { | |||
2350 | tree pack_args = ARGUMENT_PACK_ARGS (new_arg)(((enum tree_code) (new_arg)->base.code) == TYPE_ARGUMENT_PACK ? ((contains_struct_check ((new_arg), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2350, __FUNCTION__))->typed.type) : (*((const_cast<tree *> (tree_operand_check ((new_arg), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2350, __FUNCTION__)))))); | |||
2351 | for (int i = 0; i < TREE_VEC_LENGTH (pack_args)((tree_check ((pack_args), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2351, __FUNCTION__, (TREE_VEC)))->base.u.length); i++) | |||
2352 | { | |||
2353 | tree& pack_arg = TREE_VEC_ELT (pack_args, i)(*((const_cast<tree *> (tree_vec_elt_check ((pack_args) , (i), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2353, __FUNCTION__))))); | |||
2354 | if (TYPE_P (pack_arg)(tree_code_type[(int) (((enum tree_code) (pack_arg)->base. code))] == tcc_type)) | |||
2355 | pack_arg = canonicalize_type_argument (pack_arg, complain); | |||
2356 | } | |||
2357 | } | |||
2358 | } | |||
2359 | if (new_arg == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2360 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2361 | ||||
2362 | result = tree_cons (new_arg, parm, result); | |||
2363 | } | |||
2364 | return nreverse (result); | |||
2365 | } | |||
2366 | ||||
2367 | tree | |||
2368 | tsubst_parameter_mapping (tree map, tree args, tsubst_flags_t complain, tree in_decl) | |||
2369 | { | |||
2370 | return tsubst_parameter_mapping (map, args, subst_info (complain, in_decl)); | |||
2371 | } | |||
2372 | ||||
2373 | /*--------------------------------------------------------------------------- | |||
2374 | Constraint satisfaction | |||
2375 | ---------------------------------------------------------------------------*/ | |||
2376 | ||||
2377 | /* True if we are currently satisfying a constraint. */ | |||
2378 | ||||
2379 | static bool satisfying_constraint; | |||
2380 | ||||
2381 | /* A vector of incomplete types (and of declarations with undeduced return type), | |||
2382 | appended to by note_failed_type_completion_for_satisfaction. The | |||
2383 | satisfaction caches use this in order to keep track of "potentially unstable" | |||
2384 | satisfaction results. | |||
2385 | ||||
2386 | Since references to entries in this vector are stored only in the | |||
2387 | GC-deletable sat_cache, it's safe to make this deletable as well. */ | |||
2388 | ||||
2389 | static GTY((deletable)) vec<tree, va_gc> *failed_type_completions; | |||
2390 | ||||
2391 | /* Called whenever a type completion (or return type deduction) failure occurs | |||
2392 | that definitely affects the meaning of the program, by e.g. inducing | |||
2393 | substitution failure. */ | |||
2394 | ||||
2395 | void | |||
2396 | note_failed_type_completion_for_satisfaction (tree t) | |||
2397 | { | |||
2398 | if (satisfying_constraint) | |||
| ||||
2399 | { | |||
2400 | gcc_checking_assert ((TYPE_P (t) && !COMPLETE_TYPE_P (t))((void)(!(((tree_code_type[(int) (((enum tree_code) (t)->base .code))] == tcc_type) && !(((tree_class_check ((t), ( tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2400, __FUNCTION__))->type_common.size) != (tree) __null )) || ((tree_code_type[(int) (((enum tree_code) (t)->base. code))] == tcc_declaration) && undeduced_auto_decl (t ))) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2401, __FUNCTION__), 0 : 0)) | |||
2401 | || (DECL_P (t) && undeduced_auto_decl (t)))((void)(!(((tree_code_type[(int) (((enum tree_code) (t)->base .code))] == tcc_type) && !(((tree_class_check ((t), ( tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2400, __FUNCTION__))->type_common.size) != (tree) __null )) || ((tree_code_type[(int) (((enum tree_code) (t)->base. code))] == tcc_declaration) && undeduced_auto_decl (t ))) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2401, __FUNCTION__), 0 : 0)); | |||
2402 | vec_safe_push (failed_type_completions, t); | |||
2403 | } | |||
2404 | } | |||
2405 | ||||
2406 | /* Returns true if the range [BEGIN, END) of elements within the | |||
2407 | failed_type_completions vector contains a complete type (or a | |||
2408 | declaration with a non-placeholder return type). */ | |||
2409 | ||||
2410 | static bool | |||
2411 | some_type_complete_p (int begin, int end) | |||
2412 | { | |||
2413 | for (int i = begin; i < end; i++) | |||
2414 | { | |||
2415 | tree t = (*failed_type_completions)[i]; | |||
2416 | if (TYPE_P (t)(tree_code_type[(int) (((enum tree_code) (t)->base.code))] == tcc_type) && COMPLETE_TYPE_P (t)(((tree_class_check ((t), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2416, __FUNCTION__))->type_common.size) != (tree) __null )) | |||
2417 | return true; | |||
2418 | if (DECL_P (t)(tree_code_type[(int) (((enum tree_code) (t)->base.code))] == tcc_declaration) && !undeduced_auto_decl (t)) | |||
2419 | return true; | |||
2420 | } | |||
2421 | return false; | |||
2422 | } | |||
2423 | ||||
2424 | /* Hash functions and data types for satisfaction cache entries. */ | |||
2425 | ||||
2426 | struct GTY((for_user)) sat_entry | |||
2427 | { | |||
2428 | /* The relevant ATOMIC_CONSTR. */ | |||
2429 | tree atom; | |||
2430 | ||||
2431 | /* The relevant template arguments. */ | |||
2432 | tree args; | |||
2433 | ||||
2434 | /* The result of satisfaction of ATOM+ARGS. | |||
2435 | This is either boolean_true_node, boolean_false_node or error_mark_node, | |||
2436 | where error_mark_node indicates ill-formed satisfaction. | |||
2437 | It's set to NULL_TREE while computing satisfaction of ATOM+ARGS for | |||
2438 | the first time. */ | |||
2439 | tree result; | |||
2440 | ||||
2441 | /* The value of input_location when satisfaction of ATOM+ARGS was first | |||
2442 | performed. */ | |||
2443 | location_t location; | |||
2444 | ||||
2445 | /* The range of elements appended to the failed_type_completions vector | |||
2446 | during computation of this satisfaction result, encoded as a begin/end | |||
2447 | pair of offsets. */ | |||
2448 | int ftc_begin, ftc_end; | |||
2449 | ||||
2450 | /* True if we want to diagnose the above instability when it's detected. | |||
2451 | We don't always want to do so, in order to avoid emitting duplicate | |||
2452 | diagnostics in some cases. */ | |||
2453 | bool diagnose_instability; | |||
2454 | ||||
2455 | /* True if we're in the middle of computing this satisfaction result. | |||
2456 | Used during both quiet and noisy satisfaction to detect self-recursive | |||
2457 | satisfaction. */ | |||
2458 | bool evaluating; | |||
2459 | }; | |||
2460 | ||||
2461 | struct sat_hasher : ggc_ptr_hash<sat_entry> | |||
2462 | { | |||
2463 | static hashval_t hash (sat_entry *e) | |||
2464 | { | |||
2465 | if (ATOMIC_CONSTR_MAP_INSTANTIATED_P (e->atom)((tree_not_check2 (((tree_check ((e->atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2465, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2465, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_0)) | |||
2466 | { | |||
2467 | /* Atoms with instantiated mappings are built during satisfaction. | |||
2468 | They live only inside the sat_cache, and we build one to query | |||
2469 | the cache with each time we instantiate a mapping. */ | |||
2470 | gcc_assert (!e->args)((void)(!(!e->args) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2470, __FUNCTION__), 0 : 0)); | |||
2471 | return hash_atomic_constraint (e->atom); | |||
2472 | } | |||
2473 | ||||
2474 | /* Atoms with uninstantiated mappings are built during normalization. | |||
2475 | Since normalize_atom caches the atoms it returns, we can assume | |||
2476 | pointer-based identity for fast hashing and comparison. Even if this | |||
2477 | assumption is violated, that's okay, we'll just get a cache miss. */ | |||
2478 | hashval_t value = htab_hash_pointer (e->atom); | |||
2479 | ||||
2480 | if (tree map = ATOMIC_CONSTR_MAP (e->atom)(*((const_cast<tree*> (tree_operand_check (((tree_check ((e->atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2480, __FUNCTION__, (ATOMIC_CONSTR)))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2480, __FUNCTION__)))))) | |||
2481 | /* Only the parameters that are used in the targets of the mapping | |||
2482 | affect the satisfaction value of the atom. So we consider only | |||
2483 | the arguments for these parameters, and ignore the rest. */ | |||
2484 | for (tree target_parms = TREE_TYPE (map)((contains_struct_check ((map), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2484, __FUNCTION__))->typed.type); | |||
2485 | target_parms; | |||
2486 | target_parms = TREE_CHAIN (target_parms)((contains_struct_check ((target_parms), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2486, __FUNCTION__))->common.chain)) | |||
2487 | { | |||
2488 | int level, index; | |||
2489 | tree parm = TREE_VALUE (target_parms)((tree_check ((target_parms), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2489, __FUNCTION__, (TREE_LIST)))->list.value); | |||
2490 | template_parm_level_and_index (parm, &level, &index); | |||
2491 | tree arg = TMPL_ARG (e->args, level, index)((*((const_cast<tree *> (tree_vec_elt_check ((((e->args && ((tree_check ((e->args), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2491, __FUNCTION__, (TREE_VEC)))->base.u.length) && (*((const_cast<tree *> (tree_vec_elt_check ((e->args ), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2491, __FUNCTION__))))) && ((enum tree_code) ((*((const_cast <tree *> (tree_vec_elt_check ((e->args), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2491, __FUNCTION__))))))->base.code) == TREE_VEC) ? (*(( const_cast<tree *> (tree_vec_elt_check ((e->args), ( (level) - 1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2491, __FUNCTION__))))) : (e->args))), (index), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2491, __FUNCTION__)))))); | |||
2492 | value = iterative_hash_template_arg (arg, value); | |||
2493 | } | |||
2494 | return value; | |||
2495 | } | |||
2496 | ||||
2497 | static bool equal (sat_entry *e1, sat_entry *e2) | |||
2498 | { | |||
2499 | if (ATOMIC_CONSTR_MAP_INSTANTIATED_P (e1->atom)((tree_not_check2 (((tree_check ((e1->atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2499, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2499, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_0) | |||
2500 | != ATOMIC_CONSTR_MAP_INSTANTIATED_P (e2->atom)((tree_not_check2 (((tree_check ((e2->atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2500, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2500, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_0)) | |||
2501 | return false; | |||
2502 | ||||
2503 | /* See sat_hasher::hash. */ | |||
2504 | if (ATOMIC_CONSTR_MAP_INSTANTIATED_P (e1->atom)((tree_not_check2 (((tree_check ((e1->atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2504, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2504, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_0)) | |||
2505 | { | |||
2506 | gcc_assert (!e1->args && !e2->args)((void)(!(!e1->args && !e2->args) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2506, __FUNCTION__), 0 : 0)); | |||
2507 | return atomic_constraints_identical_p (e1->atom, e2->atom); | |||
2508 | } | |||
2509 | ||||
2510 | if (e1->atom != e2->atom) | |||
2511 | return false; | |||
2512 | ||||
2513 | if (tree map = ATOMIC_CONSTR_MAP (e1->atom)(*((const_cast<tree*> (tree_operand_check (((tree_check ((e1->atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2513, __FUNCTION__, (ATOMIC_CONSTR)))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2513, __FUNCTION__)))))) | |||
2514 | for (tree target_parms = TREE_TYPE (map)((contains_struct_check ((map), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2514, __FUNCTION__))->typed.type); | |||
2515 | target_parms; | |||
2516 | target_parms = TREE_CHAIN (target_parms)((contains_struct_check ((target_parms), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2516, __FUNCTION__))->common.chain)) | |||
2517 | { | |||
2518 | int level, index; | |||
2519 | tree parm = TREE_VALUE (target_parms)((tree_check ((target_parms), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2519, __FUNCTION__, (TREE_LIST)))->list.value); | |||
2520 | template_parm_level_and_index (parm, &level, &index); | |||
2521 | tree arg1 = TMPL_ARG (e1->args, level, index)((*((const_cast<tree *> (tree_vec_elt_check ((((e1-> args && ((tree_check ((e1->args), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2521, __FUNCTION__, (TREE_VEC)))->base.u.length) && (*((const_cast<tree *> (tree_vec_elt_check ((e1->args ), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2521, __FUNCTION__))))) && ((enum tree_code) ((*((const_cast <tree *> (tree_vec_elt_check ((e1->args), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2521, __FUNCTION__))))))->base.code) == TREE_VEC) ? (*(( const_cast<tree *> (tree_vec_elt_check ((e1->args), ( (level) - 1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2521, __FUNCTION__))))) : (e1->args))), (index), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2521, __FUNCTION__)))))); | |||
2522 | tree arg2 = TMPL_ARG (e2->args, level, index)((*((const_cast<tree *> (tree_vec_elt_check ((((e2-> args && ((tree_check ((e2->args), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2522, __FUNCTION__, (TREE_VEC)))->base.u.length) && (*((const_cast<tree *> (tree_vec_elt_check ((e2->args ), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2522, __FUNCTION__))))) && ((enum tree_code) ((*((const_cast <tree *> (tree_vec_elt_check ((e2->args), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2522, __FUNCTION__))))))->base.code) == TREE_VEC) ? (*(( const_cast<tree *> (tree_vec_elt_check ((e2->args), ( (level) - 1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2522, __FUNCTION__))))) : (e2->args))), (index), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2522, __FUNCTION__)))))); | |||
2523 | if (!template_args_equal (arg1, arg2)) | |||
2524 | return false; | |||
2525 | } | |||
2526 | return true; | |||
2527 | } | |||
2528 | }; | |||
2529 | ||||
2530 | /* Cache the result of satisfy_atom. */ | |||
2531 | static GTY((deletable)) hash_table<sat_hasher> *sat_cache; | |||
2532 | ||||
2533 | /* Cache the result of constraint_satisfaction_value. */ | |||
2534 | static GTY((deletable)) hash_map<tree, tree> *decl_satisfied_cache; | |||
2535 | ||||
2536 | /* A tool used by satisfy_atom to help manage satisfaction caching and to | |||
2537 | diagnose "unstable" satisfaction values. We insert into the cache only | |||
2538 | when performing satisfaction quietly. */ | |||
2539 | ||||
2540 | struct satisfaction_cache | |||
2541 | { | |||
2542 | satisfaction_cache (tree, tree, sat_info); | |||
2543 | tree get (); | |||
2544 | tree save (tree); | |||
2545 | ||||
2546 | sat_entry *entry; | |||
2547 | sat_info info; | |||
2548 | int ftc_begin; | |||
2549 | }; | |||
2550 | ||||
2551 | /* Constructor for the satisfaction_cache class. We're performing satisfaction | |||
2552 | of ATOM+ARGS according to INFO. */ | |||
2553 | ||||
2554 | satisfaction_cache | |||
2555 | ::satisfaction_cache (tree atom, tree args, sat_info info) | |||
2556 | : entry(nullptr), info(info), ftc_begin(-1) | |||
2557 | { | |||
2558 | if (!sat_cache) | |||
2559 | sat_cache = hash_table<sat_hasher>::create_ggc (31); | |||
2560 | ||||
2561 | /* When noisy, we query the satisfaction cache in order to diagnose | |||
2562 | "unstable" satisfaction values. */ | |||
2563 | if (info.noisy ()) | |||
2564 | { | |||
2565 | /* When noisy, constraints have been re-normalized, and that breaks the | |||
2566 | pointer-based identity assumption of sat_cache (for atoms with | |||
2567 | uninstantiated mappings). So undo this re-normalization by looking in | |||
2568 | the atom_cache for the corresponding atom that was used during quiet | |||
2569 | satisfaction. */ | |||
2570 | if (!ATOMIC_CONSTR_MAP_INSTANTIATED_P (atom)((tree_not_check2 (((tree_check ((atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2570, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2570, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_0)) | |||
2571 | { | |||
2572 | if (tree found = atom_cache->find (atom)) | |||
2573 | atom = found; | |||
2574 | else | |||
2575 | /* The lookup should always succeed, but if it fails then let's | |||
2576 | just leave 'entry' empty, effectively disabling the cache. */ | |||
2577 | return; | |||
2578 | } | |||
2579 | } | |||
2580 | ||||
2581 | /* Look up or create the corresponding satisfaction entry. */ | |||
2582 | sat_entry elt; | |||
2583 | elt.atom = atom; | |||
2584 | elt.args = args; | |||
2585 | sat_entry **slot = sat_cache->find_slot (&elt, INSERT); | |||
2586 | if (*slot) | |||
2587 | entry = *slot; | |||
2588 | else if (info.quiet ()) | |||
2589 | { | |||
2590 | entry = ggc_alloc<sat_entry> (); | |||
2591 | entry->atom = atom; | |||
2592 | entry->args = args; | |||
2593 | entry->result = NULL_TREE(tree) __null; | |||
2594 | entry->location = input_location; | |||
2595 | entry->ftc_begin = entry->ftc_end = -1; | |||
2596 | entry->diagnose_instability = false; | |||
2597 | if (ATOMIC_CONSTR_MAP_INSTANTIATED_P (atom)((tree_not_check2 (((tree_check ((atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2597, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2597, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_0)) | |||
2598 | /* We always want to diagnose instability of an atom with an | |||
2599 | instantiated parameter mapping. For atoms with an uninstantiated | |||
2600 | mapping, we set this flag (in satisfy_atom) only if substitution | |||
2601 | into its mapping previously failed. */ | |||
2602 | entry->diagnose_instability = true; | |||
2603 | entry->evaluating = false; | |||
2604 | *slot = entry; | |||
2605 | } | |||
2606 | else | |||
2607 | /* We shouldn't get here, but if we do, let's just leave 'entry' | |||
2608 | empty, effectively disabling the cache. */ | |||
2609 | return; | |||
2610 | } | |||
2611 | ||||
2612 | /* Returns the cached satisfaction result if we have one and we're not | |||
2613 | recomputing the satisfaction result from scratch. Otherwise returns | |||
2614 | NULL_TREE. */ | |||
2615 | ||||
2616 | tree | |||
2617 | satisfaction_cache::get () | |||
2618 | { | |||
2619 | if (!entry) | |||
2620 | return NULL_TREE(tree) __null; | |||
2621 | ||||
2622 | if (entry->evaluating) | |||
2623 | { | |||
2624 | /* If we get here, it means satisfaction is self-recursive. */ | |||
2625 | gcc_checking_assert (!entry->result)((void)(!(!entry->result) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2625, __FUNCTION__), 0 : 0)); | |||
2626 | if (info.noisy ()) | |||
2627 | error_at (EXPR_LOCATION (ATOMIC_CONSTR_EXPR (entry->atom))((((((tree_check ((((contains_struct_check (((tree_check3 ((( tree_check ((entry->atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__, (TREE_LIST)))->list.purpose))) && ((tree_code_type[(int) (((enum tree_code) ((((tree_check ((( (contains_struct_check (((tree_check3 (((tree_check ((entry-> atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__, (TREE_LIST)))->list.purpose)))->base .code))]) >= tcc_reference && (tree_code_type[(int ) (((enum tree_code) ((((tree_check ((((contains_struct_check (((tree_check3 (((tree_check ((entry->atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__, (TREE_LIST)))->list.purpose)))->base .code))]) <= tcc_expression)) ? (((tree_check ((((contains_struct_check (((tree_check3 (((tree_check ((entry->atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2627, __FUNCTION__, (TREE_LIST)))->list.purpose))->exp .locus : ((location_t) 0)), | |||
2628 | "satisfaction of atomic constraint %qE depends on itself", | |||
2629 | entry->atom); | |||
2630 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2631 | } | |||
2632 | ||||
2633 | /* This satisfaction result is "potentially unstable" if a type for which | |||
2634 | type completion failed during its earlier computation is now complete. */ | |||
2635 | bool maybe_unstable = some_type_complete_p (entry->ftc_begin, | |||
2636 | entry->ftc_end); | |||
2637 | ||||
2638 | if (info.noisy () || maybe_unstable || !entry->result) | |||
2639 | { | |||
2640 | /* We're computing the satisfaction result from scratch. */ | |||
2641 | entry->evaluating = true; | |||
2642 | ftc_begin = vec_safe_length (failed_type_completions); | |||
2643 | return NULL_TREE(tree) __null; | |||
2644 | } | |||
2645 | else | |||
2646 | return entry->result; | |||
2647 | } | |||
2648 | ||||
2649 | /* RESULT is the computed satisfaction result. If RESULT differs from the | |||
2650 | previously cached result, this routine issues an appropriate error. | |||
2651 | Otherwise, when evaluating quietly, updates the cache appropriately. */ | |||
2652 | ||||
2653 | tree | |||
2654 | satisfaction_cache::save (tree result) | |||
2655 | { | |||
2656 | if (!entry) | |||
2657 | return result; | |||
2658 | ||||
2659 | gcc_checking_assert (entry->evaluating)((void)(!(entry->evaluating) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2659, __FUNCTION__), 0 : 0)); | |||
2660 | entry->evaluating = false; | |||
2661 | ||||
2662 | if (entry->result && result != entry->result) | |||
2663 | { | |||
2664 | if (info.quiet ()) | |||
2665 | /* Return error_mark_node to force satisfaction to get replayed | |||
2666 | noisily. */ | |||
2667 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2668 | else | |||
2669 | { | |||
2670 | if (entry->diagnose_instability) | |||
2671 | { | |||
2672 | auto_diagnostic_group d; | |||
2673 | error_at (EXPR_LOCATION (ATOMIC_CONSTR_EXPR (entry->atom))((((((tree_check ((((contains_struct_check (((tree_check3 ((( tree_check ((entry->atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__, (TREE_LIST)))->list.purpose))) && ((tree_code_type[(int) (((enum tree_code) ((((tree_check ((( (contains_struct_check (((tree_check3 (((tree_check ((entry-> atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__, (TREE_LIST)))->list.purpose)))->base .code))]) >= tcc_reference && (tree_code_type[(int ) (((enum tree_code) ((((tree_check ((((contains_struct_check (((tree_check3 (((tree_check ((entry->atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__, (TREE_LIST)))->list.purpose)))->base .code))]) <= tcc_expression)) ? (((tree_check ((((contains_struct_check (((tree_check3 (((tree_check ((entry->atom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2673, __FUNCTION__, (TREE_LIST)))->list.purpose))->exp .locus : ((location_t) 0)), | |||
2674 | "satisfaction value of atomic constraint %qE changed " | |||
2675 | "from %qE to %qE", entry->atom, entry->result, result); | |||
2676 | inform (entry->location, | |||
2677 | "satisfaction value first evaluated to %qE from here", | |||
2678 | entry->result); | |||
2679 | } | |||
2680 | /* For sake of error recovery, allow this latest satisfaction result | |||
2681 | to prevail. */ | |||
2682 | entry->result = result; | |||
2683 | return result; | |||
2684 | } | |||
2685 | } | |||
2686 | ||||
2687 | if (info.quiet ()) | |||
2688 | { | |||
2689 | entry->result = result; | |||
2690 | /* Store into this entry the list of relevant failed type completions | |||
2691 | that occurred during (re)computation of the satisfaction result. */ | |||
2692 | gcc_checking_assert (ftc_begin != -1)((void)(!(ftc_begin != -1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2692, __FUNCTION__), 0 : 0)); | |||
2693 | entry->ftc_begin = ftc_begin; | |||
2694 | entry->ftc_end = vec_safe_length (failed_type_completions); | |||
2695 | } | |||
2696 | ||||
2697 | return result; | |||
2698 | } | |||
2699 | ||||
2700 | /* Substitute ARGS into constraint-expression T during instantiation of | |||
2701 | a member of a class template. */ | |||
2702 | ||||
2703 | tree | |||
2704 | tsubst_constraint (tree t, tree args, tsubst_flags_t complain, tree in_decl) | |||
2705 | { | |||
2706 | /* We also don't want to evaluate concept-checks when substituting the | |||
2707 | constraint-expressions of a declaration. */ | |||
2708 | processing_constraint_expression_sentinel s; | |||
2709 | tree expr = tsubst_expr (t, args, complain, in_decl, false); | |||
2710 | return expr; | |||
2711 | } | |||
2712 | ||||
2713 | static tree satisfy_constraint_r (tree, tree, sat_info info); | |||
2714 | ||||
2715 | /* Compute the satisfaction of a conjunction. */ | |||
2716 | ||||
2717 | static tree | |||
2718 | satisfy_conjunction (tree t, tree args, sat_info info) | |||
2719 | { | |||
2720 | tree lhs = satisfy_constraint_r (TREE_OPERAND (t, 0)(*((const_cast<tree*> (tree_operand_check ((t), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2720, __FUNCTION__))))), args, info); | |||
2721 | if (lhs == error_mark_nodeglobal_trees[TI_ERROR_MARK] || lhs == boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]) | |||
2722 | return lhs; | |||
2723 | return satisfy_constraint_r (TREE_OPERAND (t, 1)(*((const_cast<tree*> (tree_operand_check ((t), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2723, __FUNCTION__))))), args, info); | |||
2724 | } | |||
2725 | ||||
2726 | /* The current depth at which we're replaying an error during recursive | |||
2727 | diagnosis of a constraint satisfaction failure. */ | |||
2728 | ||||
2729 | static int current_constraint_diagnosis_depth; | |||
2730 | ||||
2731 | /* Whether CURRENT_CONSTRAINT_DIAGNOSIS_DEPTH has ever exceeded | |||
2732 | CONCEPTS_DIAGNOSTICS_MAX_DEPTH during recursive diagnosis of a constraint | |||
2733 | satisfaction error. */ | |||
2734 | ||||
2735 | static bool concepts_diagnostics_max_depth_exceeded_p; | |||
2736 | ||||
2737 | /* Recursive subroutine of collect_operands_of_disjunction. T is a normalized | |||
2738 | subexpression of a constraint (composed of CONJ_CONSTRs and DISJ_CONSTRs) | |||
2739 | and E is the corresponding unnormalized subexpression (composed of | |||
2740 | TRUTH_ANDIF_EXPRs and TRUTH_ORIF_EXPRs). */ | |||
2741 | ||||
2742 | static void | |||
2743 | collect_operands_of_disjunction_r (tree t, tree e, | |||
2744 | auto_vec<tree_pair> *operands) | |||
2745 | { | |||
2746 | if (TREE_CODE (e)((enum tree_code) (e)->base.code) == TRUTH_ORIF_EXPR) | |||
2747 | { | |||
2748 | collect_operands_of_disjunction_r (TREE_OPERAND (t, 0)(*((const_cast<tree*> (tree_operand_check ((t), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2748, __FUNCTION__))))), | |||
2749 | TREE_OPERAND (e, 0)(*((const_cast<tree*> (tree_operand_check ((e), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2749, __FUNCTION__))))), operands); | |||
2750 | collect_operands_of_disjunction_r (TREE_OPERAND (t, 1)(*((const_cast<tree*> (tree_operand_check ((t), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2750, __FUNCTION__))))), | |||
2751 | TREE_OPERAND (e, 1)(*((const_cast<tree*> (tree_operand_check ((e), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2751, __FUNCTION__))))), operands); | |||
2752 | } | |||
2753 | else | |||
2754 | { | |||
2755 | tree_pair p = std::make_pair (t, e); | |||
2756 | operands->safe_push (p); | |||
2757 | } | |||
2758 | } | |||
2759 | ||||
2760 | /* Recursively collect the normalized and unnormalized operands of the | |||
2761 | disjunction T and append them to OPERANDS in order. */ | |||
2762 | ||||
2763 | static void | |||
2764 | collect_operands_of_disjunction (tree t, auto_vec<tree_pair> *operands) | |||
2765 | { | |||
2766 | collect_operands_of_disjunction_r (t, CONSTR_EXPR (t)((tree_check ((((contains_struct_check (((tree_check3 ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2766, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2766, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2766, __FUNCTION__, (TREE_LIST)))->list.purpose), operands); | |||
2767 | } | |||
2768 | ||||
2769 | /* Compute the satisfaction of a disjunction. */ | |||
2770 | ||||
2771 | static tree | |||
2772 | satisfy_disjunction (tree t, tree args, sat_info info) | |||
2773 | { | |||
2774 | /* Evaluate each operand with unsatisfaction diagnostics disabled. */ | |||
2775 | sat_info sub = info; | |||
2776 | sub.diagnose_unsatisfaction = false; | |||
2777 | ||||
2778 | tree lhs = satisfy_constraint_r (TREE_OPERAND (t, 0)(*((const_cast<tree*> (tree_operand_check ((t), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2778, __FUNCTION__))))), args, sub); | |||
2779 | if (lhs == boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE] || lhs == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2780 | return lhs; | |||
2781 | ||||
2782 | tree rhs = satisfy_constraint_r (TREE_OPERAND (t, 1)(*((const_cast<tree*> (tree_operand_check ((t), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2782, __FUNCTION__))))), args, sub); | |||
2783 | if (rhs == boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE] || rhs == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2784 | return rhs; | |||
2785 | ||||
2786 | /* Both branches evaluated to false. Explain the satisfaction failure in | |||
2787 | each branch. */ | |||
2788 | if (info.diagnose_unsatisfaction_p ()) | |||
2789 | { | |||
2790 | diagnosing_failed_constraint failure (t, args, info.noisy ()); | |||
2791 | cp_expr disj_expr = CONSTR_EXPR (t)((tree_check ((((contains_struct_check (((tree_check3 ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2791, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2791, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2791, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
2792 | inform (disj_expr.get_location (), | |||
2793 | "no operand of the disjunction is satisfied"); | |||
2794 | if (diagnosing_failed_constraint::replay_errors_p ()) | |||
2795 | { | |||
2796 | /* Replay the error in each branch of the disjunction. */ | |||
2797 | auto_vec<tree_pair> operands; | |||
2798 | collect_operands_of_disjunction (t, &operands); | |||
2799 | for (unsigned i = 0; i < operands.length (); i++) | |||
2800 | { | |||
2801 | tree norm_op = operands[i].first; | |||
2802 | tree op = operands[i].second; | |||
2803 | location_t loc = make_location (cp_expr_location (op), | |||
2804 | disj_expr.get_start (), | |||
2805 | disj_expr.get_finish ()); | |||
2806 | inform (loc, "the operand %qE is unsatisfied because", op); | |||
2807 | satisfy_constraint_r (norm_op, args, info); | |||
2808 | } | |||
2809 | } | |||
2810 | } | |||
2811 | ||||
2812 | return boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]; | |||
2813 | } | |||
2814 | ||||
2815 | /* Ensures that T is a truth value and not (accidentally, as sometimes | |||
2816 | happens) an integer value. */ | |||
2817 | ||||
2818 | tree | |||
2819 | satisfaction_value (tree t) | |||
2820 | { | |||
2821 | if (t == error_mark_nodeglobal_trees[TI_ERROR_MARK] || t == boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE] || t == boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]) | |||
2822 | return t; | |||
2823 | ||||
2824 | gcc_assert (TREE_CODE (t) == INTEGER_CST((void)(!(((enum tree_code) (t)->base.code) == INTEGER_CST && comptypes ((((contains_struct_check ((t), (TS_TYPED ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2825, __FUNCTION__))->typed.type)), (global_trees[TI_BOOLEAN_TYPE ]), 0)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2825, __FUNCTION__), 0 : 0)) | |||
2825 | && same_type_p (TREE_TYPE (t), boolean_type_node))((void)(!(((enum tree_code) (t)->base.code) == INTEGER_CST && comptypes ((((contains_struct_check ((t), (TS_TYPED ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2825, __FUNCTION__))->typed.type)), (global_trees[TI_BOOLEAN_TYPE ]), 0)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2825, __FUNCTION__), 0 : 0)); | |||
2826 | if (integer_zerop (t)) | |||
2827 | return boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]; | |||
2828 | else | |||
2829 | return boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]; | |||
2830 | } | |||
2831 | ||||
2832 | /* Build a new template argument list with template arguments corresponding | |||
2833 | to the parameters used in an atomic constraint. */ | |||
2834 | ||||
2835 | tree | |||
2836 | get_mapped_args (tree map) | |||
2837 | { | |||
2838 | /* No map, no arguments. */ | |||
2839 | if (!map) | |||
2840 | return NULL_TREE(tree) __null; | |||
2841 | ||||
2842 | /* Find the mapped parameter with the highest level. */ | |||
2843 | int count = 0; | |||
2844 | for (tree p = map; p; p = TREE_CHAIN (p)((contains_struct_check ((p), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2844, __FUNCTION__))->common.chain)) | |||
2845 | { | |||
2846 | int level; | |||
2847 | int index; | |||
2848 | template_parm_level_and_index (TREE_VALUE (p)((tree_check ((p), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2848, __FUNCTION__, (TREE_LIST)))->list.value), &level, &index); | |||
2849 | if (level > count) | |||
2850 | count = level; | |||
2851 | } | |||
2852 | ||||
2853 | /* Place each argument at its corresponding position in the argument | |||
2854 | list. Note that the list will be sparse (not all arguments supplied), | |||
2855 | but instantiation is guaranteed to only use the parameters in the | |||
2856 | mapping, so null arguments would never be used. */ | |||
2857 | auto_vec< vec<tree> > lists (count); | |||
2858 | lists.quick_grow_cleared (count); | |||
2859 | for (tree p = map; p; p = TREE_CHAIN (p)((contains_struct_check ((p), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2859, __FUNCTION__))->common.chain)) | |||
2860 | { | |||
2861 | int level; | |||
2862 | int index; | |||
2863 | template_parm_level_and_index (TREE_VALUE (p)((tree_check ((p), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2863, __FUNCTION__, (TREE_LIST)))->list.value), &level, &index); | |||
2864 | ||||
2865 | /* Insert the argument into its corresponding position. */ | |||
2866 | vec<tree> &list = lists[level - 1]; | |||
2867 | if (index >= (int)list.length ()) | |||
2868 | list.safe_grow_cleared (index + 1, true); | |||
2869 | list[index] = TREE_PURPOSE (p)((tree_check ((p), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2869, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
2870 | } | |||
2871 | ||||
2872 | /* Build the new argument list. */ | |||
2873 | tree args = make_tree_vec (lists.length ()); | |||
2874 | for (unsigned i = 0; i != lists.length (); ++i) | |||
2875 | { | |||
2876 | vec<tree> &list = lists[i]; | |||
2877 | tree level = make_tree_vec (list.length ()); | |||
2878 | for (unsigned j = 0; j < list.length(); ++j) | |||
2879 | TREE_VEC_ELT (level, j)(*((const_cast<tree *> (tree_vec_elt_check ((level), (j ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2879, __FUNCTION__))))) = list[j]; | |||
2880 | SET_TMPL_ARGS_LEVEL (args, i + 1, level)((*((const_cast<tree *> (tree_vec_elt_check ((args), (( i + 1) - 1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2880, __FUNCTION__))))) = (level)); | |||
2881 | list.release (); | |||
2882 | } | |||
2883 | SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (args, 0)((contains_struct_check (((tree_check ((args), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2883, __FUNCTION__, (TREE_VEC)))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2883, __FUNCTION__))->common.chain) = build_int_cst ((tree ) __null, 0); | |||
2884 | ||||
2885 | return args; | |||
2886 | } | |||
2887 | ||||
2888 | static void diagnose_atomic_constraint (tree, tree, tree, subst_info); | |||
2889 | ||||
2890 | /* Compute the satisfaction of an atomic constraint. */ | |||
2891 | ||||
2892 | static tree | |||
2893 | satisfy_atom (tree t, tree args, sat_info info) | |||
2894 | { | |||
2895 | /* In case there is a diagnostic, we want to establish the context | |||
2896 | prior to printing errors. If no errors occur, this context is | |||
2897 | removed before returning. */ | |||
2898 | diagnosing_failed_constraint failure (t, args, info.noisy ()); | |||
2899 | ||||
2900 | satisfaction_cache cache (t, args, info); | |||
2901 | if (tree r = cache.get ()) | |||
2902 | return r; | |||
2903 | ||||
2904 | /* Perform substitution quietly. */ | |||
2905 | subst_info quiet (tf_none, NULL_TREE(tree) __null); | |||
2906 | ||||
2907 | /* Instantiate the parameter mapping. */ | |||
2908 | tree map = tsubst_parameter_mapping (ATOMIC_CONSTR_MAP (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2908, __FUNCTION__, (ATOMIC_CONSTR)))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2908, __FUNCTION__))))), args, quiet); | |||
2909 | if (map == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2910 | { | |||
2911 | /* If instantiation of the parameter mapping fails, the constraint is | |||
2912 | not satisfied. Replay the substitution. */ | |||
2913 | if (info.diagnose_unsatisfaction_p ()) | |||
2914 | tsubst_parameter_mapping (ATOMIC_CONSTR_MAP (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2914, __FUNCTION__, (ATOMIC_CONSTR)))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2914, __FUNCTION__))))), args, info); | |||
2915 | if (info.quiet ()) | |||
2916 | /* Since instantiation of the parameter mapping failed, we | |||
2917 | want to diagnose potential instability of this satisfaction | |||
2918 | result. */ | |||
2919 | cache.entry->diagnose_instability = true; | |||
2920 | return cache.save (boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]); | |||
2921 | } | |||
2922 | ||||
2923 | /* Now build a new atom using the instantiated mapping. We use | |||
2924 | this atom as a second key to the satisfaction cache, and we | |||
2925 | also pass it to diagnose_atomic_constraint so that diagnostics | |||
2926 | which refer to the atom display the instantiated mapping. */ | |||
2927 | t = copy_node (t); | |||
2928 | ATOMIC_CONSTR_MAP (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2928, __FUNCTION__, (ATOMIC_CONSTR)))), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2928, __FUNCTION__))))) = map; | |||
2929 | gcc_assert (!ATOMIC_CONSTR_MAP_INSTANTIATED_P (t))((void)(!(!((tree_not_check2 (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2929, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2929, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_0)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2929, __FUNCTION__), 0 : 0)); | |||
2930 | ATOMIC_CONSTR_MAP_INSTANTIATED_P (t)((tree_not_check2 (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2930, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2930, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_0) = true; | |||
2931 | satisfaction_cache inst_cache (t, /*args=*/NULL_TREE(tree) __null, info); | |||
2932 | if (tree r = inst_cache.get ()) | |||
2933 | { | |||
2934 | cache.entry->location = inst_cache.entry->location; | |||
2935 | return cache.save (r); | |||
2936 | } | |||
2937 | ||||
2938 | /* Rebuild the argument vector from the parameter mapping. */ | |||
2939 | args = get_mapped_args (map); | |||
2940 | ||||
2941 | /* Apply the parameter mapping (i.e., just substitute). */ | |||
2942 | tree expr = ATOMIC_CONSTR_EXPR (t)((tree_check ((((contains_struct_check (((tree_check3 (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2942, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2942, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2942, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2942, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
2943 | tree result = tsubst_expr (expr, args, quiet.complain, quiet.in_decl, false); | |||
2944 | if (result == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2945 | { | |||
2946 | /* If substitution results in an invalid type or expression, the constraint | |||
2947 | is not satisfied. Replay the substitution. */ | |||
2948 | if (info.diagnose_unsatisfaction_p ()) | |||
2949 | tsubst_expr (expr, args, info.complain, info.in_decl, false); | |||
2950 | return cache.save (inst_cache.save (boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE])); | |||
2951 | } | |||
2952 | ||||
2953 | /* [17.4.1.2] ... lvalue-to-rvalue conversion is performed as necessary, | |||
2954 | and EXPR shall be a constant expression of type bool. */ | |||
2955 | result = force_rvalue (result, info.complain); | |||
2956 | if (result == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2957 | return cache.save (inst_cache.save (error_mark_nodeglobal_trees[TI_ERROR_MARK])); | |||
2958 | if (!same_type_p (TREE_TYPE (result), boolean_type_node)comptypes ((((contains_struct_check ((result), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2958, __FUNCTION__))->typed.type)), (global_trees[TI_BOOLEAN_TYPE ]), 0)) | |||
2959 | { | |||
2960 | if (info.noisy ()) | |||
2961 | diagnose_atomic_constraint (t, map, result, info); | |||
2962 | return cache.save (inst_cache.save (error_mark_nodeglobal_trees[TI_ERROR_MARK])); | |||
2963 | } | |||
2964 | ||||
2965 | /* Compute the value of the constraint. */ | |||
2966 | if (info.noisy ()) | |||
2967 | result = cxx_constant_value (result); | |||
2968 | else | |||
2969 | { | |||
2970 | result = maybe_constant_value (result, NULL_TREE(tree) __null, | |||
2971 | /*manifestly_const_eval=*/true); | |||
2972 | if (!TREE_CONSTANT (result)((non_type_check ((result), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 2972, __FUNCTION__))->base.constant_flag)) | |||
2973 | result = error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2974 | } | |||
2975 | result = satisfaction_value (result); | |||
2976 | if (result == boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE] && info.diagnose_unsatisfaction_p ()) | |||
2977 | diagnose_atomic_constraint (t, map, result, info); | |||
2978 | ||||
2979 | return cache.save (inst_cache.save (result)); | |||
2980 | } | |||
2981 | ||||
2982 | /* Determine if the normalized constraint T is satisfied. | |||
2983 | Returns boolean_true_node if the expression/constraint is | |||
2984 | satisfied, boolean_false_node if not, and error_mark_node | |||
2985 | if the there was an error evaluating the constraint. | |||
2986 | ||||
2987 | The parameter mapping of atomic constraints is simply the | |||
2988 | set of template arguments that will be substituted into | |||
2989 | the expression, regardless of template parameters appearing | |||
2990 | withing. Whether a template argument is used in the atomic | |||
2991 | constraint only matters for subsumption. */ | |||
2992 | ||||
2993 | static tree | |||
2994 | satisfy_constraint_r (tree t, tree args, sat_info info) | |||
2995 | { | |||
2996 | if (t == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2997 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2998 | ||||
2999 | switch (TREE_CODE (t)((enum tree_code) (t)->base.code)) | |||
3000 | { | |||
3001 | case CONJ_CONSTR: | |||
3002 | return satisfy_conjunction (t, args, info); | |||
3003 | case DISJ_CONSTR: | |||
3004 | return satisfy_disjunction (t, args, info); | |||
3005 | case ATOMIC_CONSTR: | |||
3006 | return satisfy_atom (t, args, info); | |||
3007 | default: | |||
3008 | gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3008, __FUNCTION__)); | |||
3009 | } | |||
3010 | } | |||
3011 | ||||
3012 | /* Check that the normalized constraint T is satisfied for ARGS. */ | |||
3013 | ||||
3014 | static tree | |||
3015 | satisfy_constraint (tree t, tree args, sat_info info) | |||
3016 | { | |||
3017 | auto_timevar time (TV_CONSTRAINT_SAT); | |||
3018 | ||||
3019 | auto ovr = make_temp_override (satisfying_constraint, true); | |||
3020 | ||||
3021 | /* Turn off template processing. Constraint satisfaction only applies | |||
3022 | to non-dependent terms, so we want to ensure full checking here. */ | |||
3023 | processing_template_decl_sentinel proc (true); | |||
3024 | ||||
3025 | /* We need to check access during satisfaction. */ | |||
3026 | deferring_access_check_sentinel acs (dk_no_deferred); | |||
3027 | ||||
3028 | return satisfy_constraint_r (t, args, info); | |||
3029 | } | |||
3030 | ||||
3031 | /* Check the normalized constraints T against ARGS, returning a satisfaction | |||
3032 | value (either true, false, or error). */ | |||
3033 | ||||
3034 | static tree | |||
3035 | satisfy_associated_constraints (tree t, tree args, sat_info info) | |||
3036 | { | |||
3037 | /* If there are no constraints then this is trivially satisfied. */ | |||
3038 | if (!t) | |||
3039 | return boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]; | |||
3040 | ||||
3041 | /* If any arguments depend on template parameters, we can't | |||
3042 | check constraints. Pretend they're satisfied for now. */ | |||
3043 | if (args && uses_template_parms (args)) | |||
3044 | return boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]; | |||
3045 | ||||
3046 | return satisfy_constraint (t, args, info); | |||
3047 | } | |||
3048 | ||||
3049 | /* Evaluate EXPR as a constraint expression using ARGS, returning a | |||
3050 | satisfaction value. */ | |||
3051 | ||||
3052 | static tree | |||
3053 | satisfy_constraint_expression (tree t, tree args, sat_info info) | |||
3054 | { | |||
3055 | if (t == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
3056 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
3057 | ||||
3058 | gcc_assert (EXPR_P (t))((void)(!(((tree_code_type[(int) (((enum tree_code) (t)->base .code))]) >= tcc_reference && (tree_code_type[(int ) (((enum tree_code) (t)->base.code))]) <= tcc_expression )) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3058, __FUNCTION__), 0 : 0)); | |||
3059 | ||||
3060 | /* Get the normalized constraints. */ | |||
3061 | tree norm; | |||
3062 | if (args == NULL_TREE(tree) __null && concept_check_p (t)) | |||
3063 | { | |||
3064 | tree id = unpack_concept_check (t); | |||
3065 | args = TREE_OPERAND (id, 1)(*((const_cast<tree*> (tree_operand_check ((id), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3065, __FUNCTION__))))); | |||
3066 | tree tmpl = get_concept_check_template (id); | |||
3067 | norm = normalize_concept_definition (tmpl, info.noisy ()); | |||
3068 | } | |||
3069 | else | |||
3070 | norm = normalize_constraint_expression (t, info.noisy ()); | |||
3071 | ||||
3072 | /* Perform satisfaction. */ | |||
3073 | return satisfy_constraint (norm, args, info); | |||
3074 | } | |||
3075 | ||||
3076 | /* Used only to evaluate requires-expressions during constant expression | |||
3077 | evaluation. */ | |||
3078 | ||||
3079 | tree | |||
3080 | satisfy_constraint_expression (tree expr) | |||
3081 | { | |||
3082 | sat_info info (tf_none, NULL_TREE(tree) __null); | |||
3083 | return satisfy_constraint_expression (expr, NULL_TREE(tree) __null, info); | |||
3084 | } | |||
3085 | ||||
3086 | static tree | |||
3087 | satisfy_declaration_constraints (tree t, sat_info info) | |||
3088 | { | |||
3089 | gcc_assert (DECL_P (t))((void)(!((tree_code_type[(int) (((enum tree_code) (t)->base .code))] == tcc_declaration)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3089, __FUNCTION__), 0 : 0)); | |||
3090 | const tree saved_t = t; | |||
3091 | ||||
3092 | /* For inherited constructors, consider the original declaration; | |||
3093 | it has the correct template information attached. */ | |||
3094 | t = strip_inheriting_ctors (t); | |||
3095 | tree inh_ctor_targs = NULL_TREE(tree) __null; | |||
3096 | if (t != saved_t) | |||
3097 | if (tree ti = DECL_TEMPLATE_INFO (saved_t)(((contains_struct_check ((template_info_decl_check ((saved_t ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3097, __FUNCTION__)), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3097, __FUNCTION__))->decl_common.lang_specific) ->u. min.template_info)) | |||
3098 | /* The inherited constructor points to an instantiation of a constructor | |||
3099 | template; remember its template arguments. */ | |||
3100 | inh_ctor_targs = TI_ARGS (ti)((struct tree_template_info*)(tree_check ((ti), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3100, __FUNCTION__, (TEMPLATE_INFO))))->args; | |||
3101 | ||||
3102 | /* Update the declaration for diagnostics. */ | |||
3103 | info.in_decl = t; | |||
3104 | ||||
3105 | if (info.quiet ()) | |||
3106 | if (tree *result = hash_map_safe_get (decl_satisfied_cache, saved_t)) | |||
3107 | return *result; | |||
3108 | ||||
3109 | /* Get the normalized constraints. */ | |||
3110 | tree norm = NULL_TREE(tree) __null; | |||
3111 | tree args = NULL_TREE(tree) __null; | |||
3112 | if (tree ti = DECL_TEMPLATE_INFO (t)(((contains_struct_check ((template_info_decl_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3112, __FUNCTION__)), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3112, __FUNCTION__))->decl_common.lang_specific) ->u. min.template_info)) | |||
3113 | { | |||
3114 | tree tmpl = TI_TEMPLATE (ti)((struct tree_template_info*)(tree_check ((ti), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3114, __FUNCTION__, (TEMPLATE_INFO))))->tmpl; | |||
3115 | norm = normalize_template_requirements (tmpl, info.noisy ()); | |||
3116 | ||||
3117 | /* The initial parameter mapping is the complete set of | |||
3118 | template arguments substituted into the declaration. */ | |||
3119 | args = TI_ARGS (ti)((struct tree_template_info*)(tree_check ((ti), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3119, __FUNCTION__, (TEMPLATE_INFO))))->args; | |||
3120 | if (inh_ctor_targs) | |||
3121 | args = add_outermost_template_args (args, inh_ctor_targs); | |||
3122 | } | |||
3123 | else | |||
3124 | { | |||
3125 | /* These should be empty until we allow constraints on non-templates. */ | |||
3126 | norm = normalize_nontemplate_requirements (t, info.noisy ()); | |||
3127 | } | |||
3128 | ||||
3129 | unsigned ftc_count = vec_safe_length (failed_type_completions); | |||
3130 | ||||
3131 | tree result = boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]; | |||
3132 | if (norm) | |||
3133 | { | |||
3134 | if (!push_tinst_level (t)) | |||
3135 | return result; | |||
3136 | push_access_scope (t); | |||
3137 | result = satisfy_associated_constraints (norm, args, info); | |||
3138 | pop_access_scope (t); | |||
3139 | pop_tinst_level (); | |||
3140 | } | |||
3141 | ||||
3142 | /* True if this satisfaction is (heuristically) potentially unstable, i.e. | |||
3143 | if its result may depend on where in the program it was performed. */ | |||
3144 | bool maybe_unstable_satisfaction = false; | |||
3145 | if (ftc_count != vec_safe_length (failed_type_completions)) | |||
3146 | /* Type completion failure occurred during satisfaction. The satisfaction | |||
3147 | result may (or may not) materially depend on the completeness of a type, | |||
3148 | so we consider it potentially unstable. */ | |||
3149 | maybe_unstable_satisfaction = true; | |||
3150 | ||||
3151 | if (maybe_unstable_satisfaction) | |||
3152 | /* Don't cache potentially unstable satisfaction, to allow satisfy_atom | |||
3153 | to check the stability the next time around. */; | |||
3154 | else if (info.quiet ()) | |||
3155 | hash_map_safe_put<hm_ggc> (decl_satisfied_cache, saved_t, result); | |||
3156 | ||||
3157 | return result; | |||
3158 | } | |||
3159 | ||||
3160 | static tree | |||
3161 | satisfy_declaration_constraints (tree t, tree args, sat_info info) | |||
3162 | { | |||
3163 | /* Update the declaration for diagnostics. */ | |||
3164 | info.in_decl = t; | |||
3165 | ||||
3166 | gcc_assert (TREE_CODE (t) == TEMPLATE_DECL)((void)(!(((enum tree_code) (t)->base.code) == TEMPLATE_DECL ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3166, __FUNCTION__), 0 : 0)); | |||
3167 | ||||
3168 | args = add_outermost_template_args (t, args); | |||
3169 | ||||
3170 | tree result = boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]; | |||
3171 | if (tree norm = normalize_template_requirements (t, info.noisy ())) | |||
3172 | { | |||
3173 | if (!push_tinst_level (t, args)) | |||
3174 | return result; | |||
3175 | tree pattern = DECL_TEMPLATE_RESULT (t)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3175, __FUNCTION__, (TEMPLATE_DECL))))))))->result; | |||
3176 | push_access_scope (pattern); | |||
3177 | result = satisfy_associated_constraints (norm, args, info); | |||
3178 | pop_access_scope (pattern); | |||
3179 | pop_tinst_level (); | |||
3180 | } | |||
3181 | ||||
3182 | return result; | |||
3183 | } | |||
3184 | ||||
3185 | static tree | |||
3186 | constraint_satisfaction_value (tree t, sat_info info) | |||
3187 | { | |||
3188 | tree r; | |||
3189 | if (DECL_P (t)(tree_code_type[(int) (((enum tree_code) (t)->base.code))] == tcc_declaration)) | |||
3190 | r = satisfy_declaration_constraints (t, info); | |||
3191 | else | |||
3192 | r = satisfy_constraint_expression (t, NULL_TREE(tree) __null, info); | |||
3193 | if (r == error_mark_nodeglobal_trees[TI_ERROR_MARK] && info.quiet () | |||
3194 | && !(DECL_P (t)(tree_code_type[(int) (((enum tree_code) (t)->base.code))] == tcc_declaration) && TREE_NO_WARNING (t)((t)->base.nowarning_flag))) | |||
3195 | { | |||
3196 | /* Replay the error with re-normalized requirements. */ | |||
3197 | sat_info noisy (tf_warning_or_error, info.in_decl); | |||
3198 | constraint_satisfaction_value (t, noisy); | |||
3199 | if (DECL_P (t)(tree_code_type[(int) (((enum tree_code) (t)->base.code))] == tcc_declaration)) | |||
3200 | /* Avoid giving these errors again. */ | |||
3201 | TREE_NO_WARNING (t)((t)->base.nowarning_flag) = true; | |||
3202 | } | |||
3203 | return r; | |||
3204 | } | |||
3205 | ||||
3206 | static tree | |||
3207 | constraint_satisfaction_value (tree t, tree args, sat_info info) | |||
3208 | { | |||
3209 | tree r; | |||
3210 | if (DECL_P (t)(tree_code_type[(int) (((enum tree_code) (t)->base.code))] == tcc_declaration)) | |||
3211 | r = satisfy_declaration_constraints (t, args, info); | |||
3212 | else | |||
3213 | r = satisfy_constraint_expression (t, args, info); | |||
3214 | if (r == error_mark_nodeglobal_trees[TI_ERROR_MARK] && info.quiet ()) | |||
3215 | { | |||
3216 | /* Replay the error with re-normalized requirements. */ | |||
3217 | sat_info noisy (tf_warning_or_error, info.in_decl); | |||
3218 | constraint_satisfaction_value (t, args, noisy); | |||
3219 | } | |||
3220 | return r; | |||
3221 | } | |||
3222 | ||||
3223 | /* True iff the result of satisfying T is BOOLEAN_TRUE_NODE and false | |||
3224 | otherwise, even in the case of errors. */ | |||
3225 | ||||
3226 | bool | |||
3227 | constraints_satisfied_p (tree t) | |||
3228 | { | |||
3229 | if (!flag_conceptsglobal_options.x_flag_concepts) | |||
3230 | return true; | |||
3231 | ||||
3232 | sat_info quiet (tf_none, NULL_TREE(tree) __null); | |||
3233 | return constraint_satisfaction_value (t, quiet) == boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]; | |||
3234 | } | |||
3235 | ||||
3236 | /* True iff the result of satisfying T with ARGS is BOOLEAN_TRUE_NODE | |||
3237 | and false otherwise, even in the case of errors. */ | |||
3238 | ||||
3239 | bool | |||
3240 | constraints_satisfied_p (tree t, tree args) | |||
3241 | { | |||
3242 | if (!flag_conceptsglobal_options.x_flag_concepts) | |||
3243 | return true; | |||
3244 | ||||
3245 | sat_info quiet (tf_none, NULL_TREE(tree) __null); | |||
3246 | return constraint_satisfaction_value (t, args, quiet) == boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]; | |||
3247 | } | |||
3248 | ||||
3249 | /* Evaluate a concept check of the form C<ARGS>. This is only used for the | |||
3250 | evaluation of template-ids as id-expressions. */ | |||
3251 | ||||
3252 | tree | |||
3253 | evaluate_concept_check (tree check, tsubst_flags_t complain) | |||
3254 | { | |||
3255 | if (check == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
3256 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
3257 | ||||
3258 | gcc_assert (concept_check_p (check))((void)(!(concept_check_p (check)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3258, __FUNCTION__), 0 : 0)); | |||
3259 | ||||
3260 | /* Check for satisfaction without diagnostics. */ | |||
3261 | sat_info quiet (tf_none, NULL_TREE(tree) __null); | |||
3262 | tree result = satisfy_constraint_expression (check, NULL_TREE(tree) __null, quiet); | |||
3263 | if (result == error_mark_nodeglobal_trees[TI_ERROR_MARK] && (complain & tf_error)) | |||
3264 | { | |||
3265 | /* Replay the error with re-normalized requirements. */ | |||
3266 | sat_info noisy (tf_warning_or_error, NULL_TREE(tree) __null); | |||
3267 | satisfy_constraint_expression (check, NULL_TREE(tree) __null, noisy); | |||
3268 | } | |||
3269 | return result; | |||
3270 | } | |||
3271 | ||||
3272 | /*--------------------------------------------------------------------------- | |||
3273 | Semantic analysis of requires-expressions | |||
3274 | ---------------------------------------------------------------------------*/ | |||
3275 | ||||
3276 | /* Finish a requires expression for the given PARMS (possibly | |||
3277 | null) and the non-empty sequence of requirements. */ | |||
3278 | ||||
3279 | tree | |||
3280 | finish_requires_expr (location_t loc, tree parms, tree reqs) | |||
3281 | { | |||
3282 | /* Modify the declared parameters by removing their context | |||
3283 | so they don't refer to the enclosing scope and explicitly | |||
3284 | indicating that they are constraint variables. */ | |||
3285 | for (tree parm = parms; parm; parm = DECL_CHAIN (parm)(((contains_struct_check (((contains_struct_check ((parm), (TS_DECL_MINIMAL ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3285, __FUNCTION__))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3285, __FUNCTION__))->common.chain))) | |||
3286 | { | |||
3287 | DECL_CONTEXT (parm)((contains_struct_check ((parm), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3287, __FUNCTION__))->decl_minimal.context) = NULL_TREE(tree) __null; | |||
3288 | CONSTRAINT_VAR_P (parm)((contains_struct_check (((tree_check ((parm), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3288, __FUNCTION__, (PARM_DECL)))), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3288, __FUNCTION__))->decl_common.lang_flag_2) = true; | |||
3289 | } | |||
3290 | ||||
3291 | /* Build the node. */ | |||
3292 | tree r = build_min (REQUIRES_EXPR, boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE], parms, reqs, NULL_TREE(tree) __null); | |||
3293 | TREE_SIDE_EFFECTS (r)((non_type_check ((r), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3293, __FUNCTION__))->base.side_effects_flag) = false; | |||
3294 | TREE_CONSTANT (r)((non_type_check ((r), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3294, __FUNCTION__))->base.constant_flag) = true; | |||
3295 | SET_EXPR_LOCATION (r, loc)(expr_check (((r)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3295, __FUNCTION__))->exp.locus = (loc); | |||
3296 | return r; | |||
3297 | } | |||
3298 | ||||
3299 | /* Construct a requirement for the validity of EXPR. */ | |||
3300 | ||||
3301 | tree | |||
3302 | finish_simple_requirement (location_t loc, tree expr) | |||
3303 | { | |||
3304 | tree r = build_nt (SIMPLE_REQ, expr); | |||
3305 | SET_EXPR_LOCATION (r, loc)(expr_check (((r)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3305, __FUNCTION__))->exp.locus = (loc); | |||
3306 | return r; | |||
3307 | } | |||
3308 | ||||
3309 | /* Construct a requirement for the validity of TYPE. */ | |||
3310 | ||||
3311 | tree | |||
3312 | finish_type_requirement (location_t loc, tree type) | |||
3313 | { | |||
3314 | tree r = build_nt (TYPE_REQ, type); | |||
3315 | SET_EXPR_LOCATION (r, loc)(expr_check (((r)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3315, __FUNCTION__))->exp.locus = (loc); | |||
3316 | return r; | |||
3317 | } | |||
3318 | ||||
3319 | /* Construct a requirement for the validity of EXPR, along with | |||
3320 | its properties. if TYPE is non-null, then it specifies either | |||
3321 | an implicit conversion or argument deduction constraint, | |||
3322 | depending on whether any placeholders occur in the type name. | |||
3323 | NOEXCEPT_P is true iff the noexcept keyword was specified. */ | |||
3324 | ||||
3325 | tree | |||
3326 | finish_compound_requirement (location_t loc, tree expr, tree type, bool noexcept_p) | |||
3327 | { | |||
3328 | tree req = build_nt (COMPOUND_REQ, expr, type); | |||
3329 | SET_EXPR_LOCATION (req, loc)(expr_check (((req)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3329, __FUNCTION__))->exp.locus = (loc); | |||
3330 | COMPOUND_REQ_NOEXCEPT_P (req)((tree_not_check2 (((tree_check ((req), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3330, __FUNCTION__, (COMPOUND_REQ)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3330, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_0) = noexcept_p; | |||
3331 | return req; | |||
3332 | } | |||
3333 | ||||
3334 | /* Finish a nested requirement. */ | |||
3335 | ||||
3336 | tree | |||
3337 | finish_nested_requirement (location_t loc, tree expr) | |||
3338 | { | |||
3339 | /* We need to normalize the constraints now, at parse time, while | |||
3340 | we have the necessary template context. We normalize twice, | |||
3341 | once without diagnostic information and once with, which we'll | |||
3342 | later use for quiet and noisy satisfaction respectively. */ | |||
3343 | tree norm = normalize_constraint_expression (expr, /*diag=*/false); | |||
3344 | tree diag_norm = normalize_constraint_expression (expr, /*diag=*/true); | |||
3345 | ||||
3346 | /* Build the constraint, saving its two normalizations as its type. */ | |||
3347 | tree r = build1 (NESTED_REQ, build_tree_list (diag_norm, norm), expr); | |||
3348 | SET_EXPR_LOCATION (r, loc)(expr_check (((r)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3348, __FUNCTION__))->exp.locus = (loc); | |||
3349 | return r; | |||
3350 | } | |||
3351 | ||||
3352 | /* Check that FN satisfies the structural requirements of a | |||
3353 | function concept definition. */ | |||
3354 | tree | |||
3355 | check_function_concept (tree fn) | |||
3356 | { | |||
3357 | /* Check that the function is comprised of only a return statement. */ | |||
3358 | tree body = DECL_SAVED_TREE (fn)((tree_check ((fn), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3358, __FUNCTION__, (FUNCTION_DECL)))->function_decl.saved_tree ); | |||
3359 | if (TREE_CODE (body)((enum tree_code) (body)->base.code) == BIND_EXPR) | |||
3360 | body = BIND_EXPR_BODY (body)((*((const_cast<tree*> (tree_operand_check (((tree_check ((body), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3360, __FUNCTION__, (BIND_EXPR)))), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3360, __FUNCTION__)))))); | |||
3361 | ||||
3362 | /* Sometimes a function call results in the creation of clean up | |||
3363 | points. Allow these to be preserved in the body of the | |||
3364 | constraint, as we might actually need them for some constexpr | |||
3365 | evaluations. */ | |||
3366 | if (TREE_CODE (body)((enum tree_code) (body)->base.code) == CLEANUP_POINT_EXPR) | |||
3367 | body = TREE_OPERAND (body, 0)(*((const_cast<tree*> (tree_operand_check ((body), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3367, __FUNCTION__))))); | |||
3368 | ||||
3369 | /* Check that the definition is written correctly. */ | |||
3370 | if (TREE_CODE (body)((enum tree_code) (body)->base.code) != RETURN_EXPR) | |||
3371 | { | |||
3372 | location_t loc = DECL_SOURCE_LOCATION (fn)((contains_struct_check ((fn), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3372, __FUNCTION__))->decl_minimal.locus); | |||
3373 | if (TREE_CODE (body)((enum tree_code) (body)->base.code) == STATEMENT_LIST && !STATEMENT_LIST_HEAD (body)((tree_check ((body), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3373, __FUNCTION__, (STATEMENT_LIST)))->stmt_list.head)) | |||
3374 | { | |||
3375 | if (seen_error ()) | |||
3376 | /* The definition was probably erroneous, not empty. */; | |||
3377 | else | |||
3378 | error_at (loc, "definition of concept %qD is empty", fn); | |||
3379 | } | |||
3380 | else | |||
3381 | error_at (loc, "definition of concept %qD has multiple statements", fn); | |||
3382 | } | |||
3383 | ||||
3384 | return NULL_TREE(tree) __null; | |||
3385 | } | |||
3386 | ||||
3387 | ||||
3388 | // Check that a constrained friend declaration function declaration, | |||
3389 | // FN, is admissible. This is the case only when the declaration depends | |||
3390 | // on template parameters and does not declare a specialization. | |||
3391 | void | |||
3392 | check_constrained_friend (tree fn, tree reqs) | |||
3393 | { | |||
3394 | if (fn == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
3395 | return; | |||
3396 | gcc_assert (TREE_CODE (fn) == FUNCTION_DECL)((void)(!(((enum tree_code) (fn)->base.code) == FUNCTION_DECL ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3396, __FUNCTION__), 0 : 0)); | |||
3397 | ||||
3398 | // If there are not constraints, this cannot be an error. | |||
3399 | if (!reqs) | |||
3400 | return; | |||
3401 | ||||
3402 | // Constrained friend functions that don't depend on template | |||
3403 | // arguments are effectively meaningless. | |||
3404 | if (!uses_template_parms (TREE_TYPE (fn)((contains_struct_check ((fn), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3404, __FUNCTION__))->typed.type))) | |||
3405 | { | |||
3406 | error_at (location_of (fn), | |||
3407 | "constrained friend does not depend on template parameters"); | |||
3408 | return; | |||
3409 | } | |||
3410 | } | |||
3411 | ||||
3412 | /*--------------------------------------------------------------------------- | |||
3413 | Equivalence of constraints | |||
3414 | ---------------------------------------------------------------------------*/ | |||
3415 | ||||
3416 | /* Returns true when A and B are equivalent constraints. */ | |||
3417 | bool | |||
3418 | equivalent_constraints (tree a, tree b) | |||
3419 | { | |||
3420 | gcc_assert (!a || TREE_CODE (a) == CONSTRAINT_INFO)((void)(!(!a || ((enum tree_code) (a)->base.code) == CONSTRAINT_INFO ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3420, __FUNCTION__), 0 : 0)); | |||
3421 | gcc_assert (!b || TREE_CODE (b) == CONSTRAINT_INFO)((void)(!(!b || ((enum tree_code) (b)->base.code) == CONSTRAINT_INFO ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3421, __FUNCTION__), 0 : 0)); | |||
3422 | return cp_tree_equal (a, b); | |||
3423 | } | |||
3424 | ||||
3425 | /* Returns true if the template declarations A and B have equivalent | |||
3426 | constraints. This is the case when A's constraints subsume B's and | |||
3427 | when B's also constrain A's. */ | |||
3428 | bool | |||
3429 | equivalently_constrained (tree d1, tree d2) | |||
3430 | { | |||
3431 | gcc_assert (TREE_CODE (d1) == TREE_CODE (d2))((void)(!(((enum tree_code) (d1)->base.code) == ((enum tree_code ) (d2)->base.code)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3431, __FUNCTION__), 0 : 0)); | |||
3432 | return equivalent_constraints (get_constraints (d1), get_constraints (d2)); | |||
3433 | } | |||
3434 | ||||
3435 | /*--------------------------------------------------------------------------- | |||
3436 | Partial ordering of constraints | |||
3437 | ---------------------------------------------------------------------------*/ | |||
3438 | ||||
3439 | /* Returns true when the constraints in A subsume those in B. */ | |||
3440 | ||||
3441 | bool | |||
3442 | subsumes_constraints (tree a, tree b) | |||
3443 | { | |||
3444 | gcc_assert (!a || TREE_CODE (a) == CONSTRAINT_INFO)((void)(!(!a || ((enum tree_code) (a)->base.code) == CONSTRAINT_INFO ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3444, __FUNCTION__), 0 : 0)); | |||
3445 | gcc_assert (!b || TREE_CODE (b) == CONSTRAINT_INFO)((void)(!(!b || ((enum tree_code) (b)->base.code) == CONSTRAINT_INFO ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3445, __FUNCTION__), 0 : 0)); | |||
3446 | return subsumes (a, b); | |||
3447 | } | |||
3448 | ||||
3449 | /* Returns true when the constraints in CI strictly subsume | |||
3450 | the associated constraints of TMPL. */ | |||
3451 | ||||
3452 | bool | |||
3453 | strictly_subsumes (tree ci, tree tmpl) | |||
3454 | { | |||
3455 | tree n1 = get_normalized_constraints_from_info (ci, NULL_TREE(tree) __null); | |||
3456 | tree n2 = get_normalized_constraints_from_decl (tmpl); | |||
3457 | ||||
3458 | return subsumes (n1, n2) && !subsumes (n2, n1); | |||
3459 | } | |||
3460 | ||||
3461 | /* Returns true when the constraints in CI subsume the | |||
3462 | associated constraints of TMPL. */ | |||
3463 | ||||
3464 | bool | |||
3465 | weakly_subsumes (tree ci, tree tmpl) | |||
3466 | { | |||
3467 | tree n1 = get_normalized_constraints_from_info (ci, NULL_TREE(tree) __null); | |||
3468 | tree n2 = get_normalized_constraints_from_decl (tmpl); | |||
3469 | ||||
3470 | return subsumes (n1, n2); | |||
3471 | } | |||
3472 | ||||
3473 | /* Determines which of the declarations, A or B, is more constrained. | |||
3474 | That is, which declaration's constraints subsume but are not subsumed | |||
3475 | by the other's? | |||
3476 | ||||
3477 | Returns 1 if D1 is more constrained than D2, -1 if D2 is more constrained | |||
3478 | than D1, and 0 otherwise. */ | |||
3479 | ||||
3480 | int | |||
3481 | more_constrained (tree d1, tree d2) | |||
3482 | { | |||
3483 | tree n1 = get_normalized_constraints_from_decl (d1); | |||
3484 | tree n2 = get_normalized_constraints_from_decl (d2); | |||
3485 | ||||
3486 | int winner = 0; | |||
3487 | if (subsumes (n1, n2)) | |||
3488 | ++winner; | |||
3489 | if (subsumes (n2, n1)) | |||
3490 | --winner; | |||
3491 | return winner; | |||
3492 | } | |||
3493 | ||||
3494 | /* Return whether D1 is at least as constrained as D2. */ | |||
3495 | ||||
3496 | bool | |||
3497 | at_least_as_constrained (tree d1, tree d2) | |||
3498 | { | |||
3499 | tree n1 = get_normalized_constraints_from_decl (d1); | |||
3500 | tree n2 = get_normalized_constraints_from_decl (d2); | |||
3501 | ||||
3502 | return subsumes (n1, n2); | |||
3503 | } | |||
3504 | ||||
3505 | /*--------------------------------------------------------------------------- | |||
3506 | Constraint diagnostics | |||
3507 | ---------------------------------------------------------------------------*/ | |||
3508 | ||||
3509 | /* Returns the best location to diagnose a constraint error. */ | |||
3510 | ||||
3511 | static location_t | |||
3512 | get_constraint_error_location (tree t) | |||
3513 | { | |||
3514 | if (location_t loc = cp_expr_location (t)) | |||
3515 | return loc; | |||
3516 | ||||
3517 | /* If we have a specific location give it. */ | |||
3518 | tree expr = CONSTR_EXPR (t)((tree_check ((((contains_struct_check (((tree_check3 ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3518, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3518, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3518, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
3519 | if (location_t loc = cp_expr_location (expr)) | |||
3520 | return loc; | |||
3521 | ||||
3522 | /* If the constraint is normalized from a requires-clause, give | |||
3523 | the location as that of the constrained declaration. */ | |||
3524 | tree cxt = CONSTR_CONTEXT (t)((tree_check ((((contains_struct_check (((tree_check3 ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3524, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3524, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3524, __FUNCTION__, (TREE_LIST)))->list.value); | |||
3525 | tree src = cxt ? TREE_VALUE (cxt)((tree_check ((cxt), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3525, __FUNCTION__, (TREE_LIST)))->list.value) : NULL_TREE(tree) __null; | |||
3526 | if (!src) | |||
3527 | /* TODO: This only happens for constrained non-template declarations. */ | |||
3528 | ; | |||
3529 | else if (DECL_P (src)(tree_code_type[(int) (((enum tree_code) (src)->base.code) )] == tcc_declaration)) | |||
3530 | return DECL_SOURCE_LOCATION (src)((contains_struct_check ((src), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3530, __FUNCTION__))->decl_minimal.locus); | |||
3531 | /* Otherwise, give the location as the defining concept. */ | |||
3532 | else if (concept_check_p (src)) | |||
3533 | { | |||
3534 | tree id = unpack_concept_check (src); | |||
3535 | tree tmpl = TREE_OPERAND (id, 0)(*((const_cast<tree*> (tree_operand_check ((id), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3535, __FUNCTION__))))); | |||
3536 | if (OVL_P (tmpl)(((enum tree_code) (tmpl)->base.code) == FUNCTION_DECL || ( (enum tree_code) (tmpl)->base.code) == OVERLOAD)) | |||
3537 | tmpl = OVL_FIRST (tmpl)ovl_first (tmpl); | |||
3538 | return DECL_SOURCE_LOCATION (tmpl)((contains_struct_check ((tmpl), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3538, __FUNCTION__))->decl_minimal.locus); | |||
3539 | } | |||
3540 | ||||
3541 | return input_location; | |||
3542 | } | |||
3543 | ||||
3544 | /* Emit a diagnostic for a failed trait. */ | |||
3545 | ||||
3546 | void | |||
3547 | diagnose_trait_expr (tree expr, tree map) | |||
3548 | { | |||
3549 | location_t loc = cp_expr_location (expr); | |||
3550 | tree args = get_mapped_args (map); | |||
3551 | ||||
3552 | /* Build a "fake" version of the instantiated trait, so we can | |||
3553 | get the instantiated types from result. */ | |||
3554 | ++processing_template_declscope_chain->x_processing_template_decl; | |||
3555 | expr = tsubst_expr (expr, args, tf_none, NULL_TREE(tree) __null, false); | |||
3556 | --processing_template_declscope_chain->x_processing_template_decl; | |||
3557 | ||||
3558 | tree t1 = TRAIT_EXPR_TYPE1 (expr)(((struct tree_trait_expr *)(tree_check ((expr), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3558, __FUNCTION__, (TRAIT_EXPR))))->type1); | |||
3559 | tree t2 = TRAIT_EXPR_TYPE2 (expr)(((struct tree_trait_expr *)(tree_check ((expr), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3559, __FUNCTION__, (TRAIT_EXPR))))->type2); | |||
3560 | switch (TRAIT_EXPR_KIND (expr)(((struct tree_trait_expr *)(tree_check ((expr), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3560, __FUNCTION__, (TRAIT_EXPR))))->kind)) | |||
3561 | { | |||
3562 | case CPTK_HAS_NOTHROW_ASSIGN: | |||
3563 | inform (loc, " %qT is not %<nothrow%> copy assignable", t1); | |||
3564 | break; | |||
3565 | case CPTK_HAS_NOTHROW_CONSTRUCTOR: | |||
3566 | inform (loc, " %qT is not %<nothrow%> default constructible", t1); | |||
3567 | break; | |||
3568 | case CPTK_HAS_NOTHROW_COPY: | |||
3569 | inform (loc, " %qT is not %<nothrow%> copy constructible", t1); | |||
3570 | break; | |||
3571 | case CPTK_HAS_TRIVIAL_ASSIGN: | |||
3572 | inform (loc, " %qT is not trivially copy assignable", t1); | |||
3573 | break; | |||
3574 | case CPTK_HAS_TRIVIAL_CONSTRUCTOR: | |||
3575 | inform (loc, " %qT is not trivially default constructible", t1); | |||
3576 | break; | |||
3577 | case CPTK_HAS_TRIVIAL_COPY: | |||
3578 | inform (loc, " %qT is not trivially copy constructible", t1); | |||
3579 | break; | |||
3580 | case CPTK_HAS_TRIVIAL_DESTRUCTOR: | |||
3581 | inform (loc, " %qT is not trivially destructible", t1); | |||
3582 | break; | |||
3583 | case CPTK_HAS_VIRTUAL_DESTRUCTOR: | |||
3584 | inform (loc, " %qT does not have a virtual destructor", t1); | |||
3585 | break; | |||
3586 | case CPTK_IS_ABSTRACT: | |||
3587 | inform (loc, " %qT is not an abstract class", t1); | |||
3588 | break; | |||
3589 | case CPTK_IS_BASE_OF: | |||
3590 | inform (loc, " %qT is not a base of %qT", t1, t2); | |||
3591 | break; | |||
3592 | case CPTK_IS_CLASS: | |||
3593 | inform (loc, " %qT is not a class", t1); | |||
3594 | break; | |||
3595 | case CPTK_IS_EMPTY: | |||
3596 | inform (loc, " %qT is not an empty class", t1); | |||
3597 | break; | |||
3598 | case CPTK_IS_ENUM: | |||
3599 | inform (loc, " %qT is not an enum", t1); | |||
3600 | break; | |||
3601 | case CPTK_IS_FINAL: | |||
3602 | inform (loc, " %qT is not a final class", t1); | |||
3603 | break; | |||
3604 | case CPTK_IS_LITERAL_TYPE: | |||
3605 | inform (loc, " %qT is not a literal type", t1); | |||
3606 | break; | |||
3607 | case CPTK_IS_POD: | |||
3608 | inform (loc, " %qT is not a POD type", t1); | |||
3609 | break; | |||
3610 | case CPTK_IS_POLYMORPHIC: | |||
3611 | inform (loc, " %qT is not a polymorphic type", t1); | |||
3612 | break; | |||
3613 | case CPTK_IS_SAME_AS: | |||
3614 | inform (loc, " %qT is not the same as %qT", t1, t2); | |||
3615 | break; | |||
3616 | case CPTK_IS_STD_LAYOUT: | |||
3617 | inform (loc, " %qT is not an standard layout type", t1); | |||
3618 | break; | |||
3619 | case CPTK_IS_TRIVIAL: | |||
3620 | inform (loc, " %qT is not a trivial type", t1); | |||
3621 | break; | |||
3622 | case CPTK_IS_UNION: | |||
3623 | inform (loc, " %qT is not a union", t1); | |||
3624 | break; | |||
3625 | default: | |||
3626 | gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3626, __FUNCTION__)); | |||
3627 | } | |||
3628 | } | |||
3629 | ||||
3630 | static tree | |||
3631 | diagnose_valid_expression (tree expr, tree args, tree in_decl) | |||
3632 | { | |||
3633 | tree result = tsubst_expr (expr, args, tf_none, in_decl, false); | |||
3634 | if (result != error_mark_nodeglobal_trees[TI_ERROR_MARK] | |||
3635 | && convert_to_void (result, ICV_STATEMENT, tf_none) != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
3636 | return result; | |||
3637 | ||||
3638 | location_t loc = cp_expr_loc_or_input_loc (expr); | |||
3639 | if (diagnosing_failed_constraint::replay_errors_p ()) | |||
3640 | { | |||
3641 | /* Replay the substitution error. */ | |||
3642 | inform (loc, "the required expression %qE is invalid, because", expr); | |||
3643 | if (result == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
3644 | tsubst_expr (expr, args, tf_error, in_decl, false); | |||
3645 | else | |||
3646 | convert_to_void (result, ICV_STATEMENT, tf_error); | |||
3647 | } | |||
3648 | else | |||
3649 | inform (loc, "the required expression %qE is invalid", expr); | |||
3650 | ||||
3651 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
3652 | } | |||
3653 | ||||
3654 | static tree | |||
3655 | diagnose_valid_type (tree type, tree args, tree in_decl) | |||
3656 | { | |||
3657 | tree result = tsubst (type, args, tf_none, in_decl); | |||
3658 | if (result != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
3659 | return result; | |||
3660 | ||||
3661 | location_t loc = cp_expr_loc_or_input_loc (type); | |||
3662 | if (diagnosing_failed_constraint::replay_errors_p ()) | |||
3663 | { | |||
3664 | /* Replay the substitution error. */ | |||
3665 | inform (loc, "the required type %qT is invalid, because", type); | |||
3666 | tsubst (type, args, tf_error, in_decl); | |||
3667 | } | |||
3668 | else | |||
3669 | inform (loc, "the required type %qT is invalid", type); | |||
3670 | ||||
3671 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
3672 | } | |||
3673 | ||||
3674 | static void | |||
3675 | diagnose_simple_requirement (tree req, tree args, tree in_decl) | |||
3676 | { | |||
3677 | diagnose_valid_expression (TREE_OPERAND (req, 0)(*((const_cast<tree*> (tree_operand_check ((req), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3677, __FUNCTION__))))), args, in_decl); | |||
3678 | } | |||
3679 | ||||
3680 | static void | |||
3681 | diagnose_compound_requirement (tree req, tree args, tree in_decl) | |||
3682 | { | |||
3683 | tree expr = TREE_OPERAND (req, 0)(*((const_cast<tree*> (tree_operand_check ((req), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3683, __FUNCTION__))))); | |||
3684 | expr = diagnose_valid_expression (expr, args, in_decl); | |||
3685 | if (expr == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
3686 | return; | |||
3687 | ||||
3688 | location_t loc = cp_expr_loc_or_input_loc (expr); | |||
3689 | ||||
3690 | /* Check the noexcept condition. */ | |||
3691 | if (COMPOUND_REQ_NOEXCEPT_P (req)((tree_not_check2 (((tree_check ((req), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3691, __FUNCTION__, (COMPOUND_REQ)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3691, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_0) && !expr_noexcept_p (expr, tf_none)) | |||
3692 | inform (loc, "%qE is not %<noexcept%>", expr); | |||
3693 | ||||
3694 | tree type = TREE_OPERAND (req, 1)(*((const_cast<tree*> (tree_operand_check ((req), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3694, __FUNCTION__))))); | |||
3695 | type = diagnose_valid_type (type, args, in_decl); | |||
3696 | if (type == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
3697 | return; | |||
3698 | ||||
3699 | if (type) | |||
3700 | { | |||
3701 | subst_info quiet (tf_none, in_decl); | |||
3702 | subst_info noisy (tf_error, in_decl); | |||
3703 | ||||
3704 | /* Check the expression against the result type. */ | |||
3705 | if (tree placeholder = type_uses_auto (type)) | |||
3706 | { | |||
3707 | if (!type_deducible_p (expr, type, placeholder, args, quiet)) | |||
3708 | { | |||
3709 | tree orig_expr = TREE_OPERAND (req, 0)(*((const_cast<tree*> (tree_operand_check ((req), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3709, __FUNCTION__))))); | |||
3710 | if (diagnosing_failed_constraint::replay_errors_p ()) | |||
3711 | { | |||
3712 | inform (loc, | |||
3713 | "%qE does not satisfy return-type-requirement, " | |||
3714 | "because", orig_expr); | |||
3715 | /* Further explain the reason for the error. */ | |||
3716 | type_deducible_p (expr, type, placeholder, args, noisy); | |||
3717 | } | |||
3718 | else | |||
3719 | inform (loc, "%qE does not satisfy return-type-requirement", | |||
3720 | orig_expr); | |||
3721 | } | |||
3722 | } | |||
3723 | else if (!expression_convertible_p (expr, type, quiet)) | |||
3724 | { | |||
3725 | tree orig_expr = TREE_OPERAND (req, 0)(*((const_cast<tree*> (tree_operand_check ((req), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3725, __FUNCTION__))))); | |||
3726 | if (diagnosing_failed_constraint::replay_errors_p ()) | |||
3727 | { | |||
3728 | inform (loc, "cannot convert %qE to %qT because", orig_expr, type); | |||
3729 | /* Further explain the reason for the error. */ | |||
3730 | expression_convertible_p (expr, type, noisy); | |||
3731 | } | |||
3732 | else | |||
3733 | inform (loc, "cannot convert %qE to %qT", orig_expr, type); | |||
3734 | } | |||
3735 | } | |||
3736 | } | |||
3737 | ||||
3738 | static void | |||
3739 | diagnose_type_requirement (tree req, tree args, tree in_decl) | |||
3740 | { | |||
3741 | tree type = TREE_OPERAND (req, 0)(*((const_cast<tree*> (tree_operand_check ((req), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3741, __FUNCTION__))))); | |||
3742 | diagnose_valid_type (type, args, in_decl); | |||
3743 | } | |||
3744 | ||||
3745 | static void | |||
3746 | diagnose_nested_requirement (tree req, tree args) | |||
3747 | { | |||
3748 | /* Quietly check for satisfaction first using the regular normal form. | |||
3749 | We can elaborate details later if needed. */ | |||
3750 | tree norm = TREE_VALUE (TREE_TYPE (req))((tree_check ((((contains_struct_check ((req), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3750, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3750, __FUNCTION__, (TREE_LIST)))->list.value); | |||
3751 | tree diag_norm = TREE_PURPOSE (TREE_TYPE (req))((tree_check ((((contains_struct_check ((req), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3751, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3751, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
3752 | sat_info info (tf_none, NULL_TREE(tree) __null); | |||
3753 | tree result = satisfy_constraint (norm, args, info); | |||
3754 | if (result == boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]) | |||
3755 | return; | |||
3756 | ||||
3757 | tree expr = TREE_OPERAND (req, 0)(*((const_cast<tree*> (tree_operand_check ((req), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3757, __FUNCTION__))))); | |||
3758 | location_t loc = cp_expr_location (expr); | |||
3759 | if (diagnosing_failed_constraint::replay_errors_p ()) | |||
3760 | { | |||
3761 | /* Replay the substitution error using the diagnostic normal form. */ | |||
3762 | inform (loc, "nested requirement %qE is not satisfied, because", expr); | |||
3763 | sat_info noisy (tf_warning_or_error, NULL_TREE(tree) __null, /*diag_unsat=*/true); | |||
3764 | satisfy_constraint (diag_norm, args, noisy); | |||
3765 | } | |||
3766 | else | |||
3767 | inform (loc, "nested requirement %qE is not satisfied", expr); | |||
3768 | ||||
3769 | } | |||
3770 | ||||
3771 | static void | |||
3772 | diagnose_requirement (tree req, tree args, tree in_decl) | |||
3773 | { | |||
3774 | iloc_sentinel loc_s (cp_expr_location (req)); | |||
3775 | switch (TREE_CODE (req)((enum tree_code) (req)->base.code)) | |||
3776 | { | |||
3777 | case SIMPLE_REQ: | |||
3778 | return diagnose_simple_requirement (req, args, in_decl); | |||
3779 | case COMPOUND_REQ: | |||
3780 | return diagnose_compound_requirement (req, args, in_decl); | |||
3781 | case TYPE_REQ: | |||
3782 | return diagnose_type_requirement (req, args, in_decl); | |||
3783 | case NESTED_REQ: | |||
3784 | return diagnose_nested_requirement (req, args); | |||
3785 | default: | |||
3786 | gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3786, __FUNCTION__)); | |||
3787 | } | |||
3788 | } | |||
3789 | ||||
3790 | static void | |||
3791 | diagnose_requires_expr (tree expr, tree map, tree in_decl) | |||
3792 | { | |||
3793 | local_specialization_stack stack (lss_copy); | |||
3794 | tree parms = TREE_OPERAND (expr, 0)(*((const_cast<tree*> (tree_operand_check ((expr), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3794, __FUNCTION__))))); | |||
3795 | tree body = TREE_OPERAND (expr, 1)(*((const_cast<tree*> (tree_operand_check ((expr), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3795, __FUNCTION__))))); | |||
3796 | tree args = get_mapped_args (map); | |||
3797 | ||||
3798 | cp_unevaluated u; | |||
3799 | subst_info info (tf_warning_or_error, NULL_TREE(tree) __null); | |||
3800 | tree vars = tsubst_constraint_variables (parms, args, info); | |||
3801 | if (vars == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
3802 | return; | |||
3803 | ||||
3804 | tree p = body; | |||
3805 | while (p) | |||
3806 | { | |||
3807 | tree req = TREE_VALUE (p)((tree_check ((p), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3807, __FUNCTION__, (TREE_LIST)))->list.value); | |||
3808 | diagnose_requirement (req, args, in_decl); | |||
3809 | p = TREE_CHAIN (p)((contains_struct_check ((p), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3809, __FUNCTION__))->common.chain); | |||
3810 | } | |||
3811 | } | |||
3812 | ||||
3813 | /* Diagnose a substitution failure in the atomic constraint T when applied | |||
3814 | with the instantiated parameter mapping MAP. */ | |||
3815 | ||||
3816 | static void | |||
3817 | diagnose_atomic_constraint (tree t, tree map, tree result, subst_info info) | |||
3818 | { | |||
3819 | /* If the constraint is already ill-formed, we've previously diagnosed | |||
3820 | the reason. We should still say why the constraints aren't satisfied. */ | |||
3821 | if (t == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
3822 | { | |||
3823 | location_t loc; | |||
3824 | if (info.in_decl) | |||
3825 | loc = DECL_SOURCE_LOCATION (info.in_decl)((contains_struct_check ((info.in_decl), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3825, __FUNCTION__))->decl_minimal.locus); | |||
3826 | else | |||
3827 | loc = input_location; | |||
3828 | inform (loc, "invalid constraints"); | |||
3829 | return; | |||
3830 | } | |||
3831 | ||||
3832 | location_t loc = get_constraint_error_location (t); | |||
3833 | iloc_sentinel loc_s (loc); | |||
3834 | ||||
3835 | /* Generate better diagnostics for certain kinds of expressions. */ | |||
3836 | tree expr = ATOMIC_CONSTR_EXPR (t)((tree_check ((((contains_struct_check (((tree_check3 (((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3836, __FUNCTION__, (ATOMIC_CONSTR)))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3836, __FUNCTION__, (ATOMIC_CONSTR), (CONJ_CONSTR), (DISJ_CONSTR )))), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3836, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3836, __FUNCTION__, (TREE_LIST)))->list.purpose); | |||
3837 | STRIP_ANY_LOCATION_WRAPPER (expr)(expr) = tree_strip_any_location_wrapper ((const_cast<union tree_node *> (((expr))))); | |||
3838 | switch (TREE_CODE (expr)((enum tree_code) (expr)->base.code)) | |||
3839 | { | |||
3840 | case TRAIT_EXPR: | |||
3841 | diagnose_trait_expr (expr, map); | |||
3842 | break; | |||
3843 | case REQUIRES_EXPR: | |||
3844 | diagnose_requires_expr (expr, map, info.in_decl); | |||
3845 | break; | |||
3846 | default: | |||
3847 | if (!same_type_p (TREE_TYPE (result), boolean_type_node)comptypes ((((contains_struct_check ((result), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3847, __FUNCTION__))->typed.type)), (global_trees[TI_BOOLEAN_TYPE ]), 0)) | |||
3848 | error_at (loc, "constraint %qE has type %qT, not %<bool%>", | |||
3849 | t, TREE_TYPE (result)((contains_struct_check ((result), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3849, __FUNCTION__))->typed.type)); | |||
3850 | else | |||
3851 | inform (loc, "the expression %qE evaluated to %<false%>", t); | |||
3852 | } | |||
3853 | } | |||
3854 | ||||
3855 | GTY(()) tree current_failed_constraint; | |||
3856 | ||||
3857 | diagnosing_failed_constraint:: | |||
3858 | diagnosing_failed_constraint (tree t, tree args, bool diag) | |||
3859 | : diagnosing_error (diag) | |||
3860 | { | |||
3861 | if (diagnosing_error) | |||
3862 | { | |||
3863 | current_failed_constraint | |||
3864 | = tree_cons (args, t, current_failed_constraint); | |||
3865 | ++current_constraint_diagnosis_depth; | |||
3866 | } | |||
3867 | } | |||
3868 | ||||
3869 | diagnosing_failed_constraint:: | |||
3870 | ~diagnosing_failed_constraint () | |||
3871 | { | |||
3872 | if (diagnosing_error) | |||
3873 | { | |||
3874 | --current_constraint_diagnosis_depth; | |||
3875 | if (current_failed_constraint) | |||
3876 | current_failed_constraint = TREE_CHAIN (current_failed_constraint)((contains_struct_check ((current_failed_constraint), (TS_COMMON ), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/constraint.cc" , 3876, __FUNCTION__))->common.chain); | |||
3877 | } | |||
3878 | ||||
3879 | } | |||
3880 | ||||
3881 | /* Whether we are allowed to replay an error that underlies a constraint failure | |||
3882 | at the current diagnosis depth. */ | |||
3883 | ||||
3884 | bool | |||
3885 | diagnosing_failed_constraint::replay_errors_p () | |||
3886 | { | |||
3887 | if (current_constraint_diagnosis_depth >= concepts_diagnostics_max_depthglobal_options.x_concepts_diagnostics_max_depth) | |||
3888 | { | |||
3889 | concepts_diagnostics_max_depth_exceeded_p = true; | |||
3890 | return false; | |||
3891 | } | |||
3892 | else | |||
3893 | return true; | |||
3894 | } | |||
3895 | ||||
3896 | /* Emit diagnostics detailing the failure ARGS to satisfy the constraints | |||
3897 | of T. Here, T can be either a constraint or a declaration. */ | |||
3898 | ||||
3899 | void | |||
3900 | diagnose_constraints (location_t loc, tree t, tree args) | |||
3901 | { | |||
3902 | inform (loc, "constraints not satisfied"); | |||
3903 | ||||
3904 | if (concepts_diagnostics_max_depthglobal_options.x_concepts_diagnostics_max_depth == 0) | |||
3905 | return; | |||
3906 | ||||
3907 | /* Replay satisfaction, but diagnose unsatisfaction. */ | |||
3908 | sat_info noisy (tf_warning_or_error, NULL_TREE(tree) __null, /*diag_unsat=*/true); | |||
3909 | if (!args) | |||
3910 | constraint_satisfaction_value (t, noisy); | |||
3911 | else | |||
3912 | constraint_satisfaction_value (t, args, noisy); | |||
3913 | ||||
3914 | static bool suggested_p; | |||
3915 | if (concepts_diagnostics_max_depth_exceeded_p | |||
3916 | && current_constraint_diagnosis_depth == 0 | |||
3917 | && !suggested_p) | |||
3918 | { | |||
3919 | inform (UNKNOWN_LOCATION((location_t) 0), | |||
3920 | "set %qs to at least %d for more detail", | |||
3921 | "-fconcepts-diagnostics-depth=", | |||
3922 | concepts_diagnostics_max_depthglobal_options.x_concepts_diagnostics_max_depth + 1); | |||
3923 | suggested_p = true; | |||
3924 | } | |||
3925 | } | |||
3926 | ||||
3927 | #include "gt-cp-constraint.h" |
1 | /* Vector API for GNU compiler. | ||||
2 | Copyright (C) 2004-2021 Free Software Foundation, Inc. | ||||
3 | Contributed by Nathan Sidwell <nathan@codesourcery.com> | ||||
4 | Re-implemented in C++ by Diego Novillo <dnovillo@google.com> | ||||
5 | |||||
6 | This file is part of GCC. | ||||
7 | |||||
8 | GCC is free software; you can redistribute it and/or modify it under | ||||
9 | the terms of the GNU General Public License as published by the Free | ||||
10 | Software Foundation; either version 3, or (at your option) any later | ||||
11 | version. | ||||
12 | |||||
13 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | ||||
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||||
16 | for more details. | ||||
17 | |||||
18 | You should have received a copy of the GNU General Public License | ||||
19 | along with GCC; see the file COPYING3. If not see | ||||
20 | <http://www.gnu.org/licenses/>. */ | ||||
21 | |||||
22 | #ifndef GCC_VEC_H | ||||
23 | #define GCC_VEC_H | ||||
24 | |||||
25 | /* Some gen* file have no ggc support as the header file gtype-desc.h is | ||||
26 | missing. Provide these definitions in case ggc.h has not been included. | ||||
27 | This is not a problem because any code that runs before gengtype is built | ||||
28 | will never need to use GC vectors.*/ | ||||
29 | |||||
30 | extern void ggc_free (void *); | ||||
31 | extern size_t ggc_round_alloc_size (size_t requested_size); | ||||
32 | extern void *ggc_realloc (void *, size_t MEM_STAT_DECL); | ||||
33 | |||||
34 | /* Templated vector type and associated interfaces. | ||||
35 | |||||
36 | The interface functions are typesafe and use inline functions, | ||||
37 | sometimes backed by out-of-line generic functions. The vectors are | ||||
38 | designed to interoperate with the GTY machinery. | ||||
39 | |||||
40 | There are both 'index' and 'iterate' accessors. The index accessor | ||||
41 | is implemented by operator[]. The iterator returns a boolean | ||||
42 | iteration condition and updates the iteration variable passed by | ||||
43 | reference. Because the iterator will be inlined, the address-of | ||||
44 | can be optimized away. | ||||
45 | |||||
46 | Each operation that increases the number of active elements is | ||||
47 | available in 'quick' and 'safe' variants. The former presumes that | ||||
48 | there is sufficient allocated space for the operation to succeed | ||||
49 | (it dies if there is not). The latter will reallocate the | ||||
50 | vector, if needed. Reallocation causes an exponential increase in | ||||
51 | vector size. If you know you will be adding N elements, it would | ||||
52 | be more efficient to use the reserve operation before adding the | ||||
53 | elements with the 'quick' operation. This will ensure there are at | ||||
54 | least as many elements as you ask for, it will exponentially | ||||
55 | increase if there are too few spare slots. If you want reserve a | ||||
56 | specific number of slots, but do not want the exponential increase | ||||
57 | (for instance, you know this is the last allocation), use the | ||||
58 | reserve_exact operation. You can also create a vector of a | ||||
59 | specific size from the get go. | ||||
60 | |||||
61 | You should prefer the push and pop operations, as they append and | ||||
62 | remove from the end of the vector. If you need to remove several | ||||
63 | items in one go, use the truncate operation. The insert and remove | ||||
64 | operations allow you to change elements in the middle of the | ||||
65 | vector. There are two remove operations, one which preserves the | ||||
66 | element ordering 'ordered_remove', and one which does not | ||||
67 | 'unordered_remove'. The latter function copies the end element | ||||
68 | into the removed slot, rather than invoke a memmove operation. The | ||||
69 | 'lower_bound' function will determine where to place an item in the | ||||
70 | array using insert that will maintain sorted order. | ||||
71 | |||||
72 | Vectors are template types with three arguments: the type of the | ||||
73 | elements in the vector, the allocation strategy, and the physical | ||||
74 | layout to use | ||||
75 | |||||
76 | Four allocation strategies are supported: | ||||
77 | |||||
78 | - Heap: allocation is done using malloc/free. This is the | ||||
79 | default allocation strategy. | ||||
80 | |||||
81 | - GC: allocation is done using ggc_alloc/ggc_free. | ||||
82 | |||||
83 | - GC atomic: same as GC with the exception that the elements | ||||
84 | themselves are assumed to be of an atomic type that does | ||||
85 | not need to be garbage collected. This means that marking | ||||
86 | routines do not need to traverse the array marking the | ||||
87 | individual elements. This increases the performance of | ||||
88 | GC activities. | ||||
89 | |||||
90 | Two physical layouts are supported: | ||||
91 | |||||
92 | - Embedded: The vector is structured using the trailing array | ||||
93 | idiom. The last member of the structure is an array of size | ||||
94 | 1. When the vector is initially allocated, a single memory | ||||
95 | block is created to hold the vector's control data and the | ||||
96 | array of elements. These vectors cannot grow without | ||||
97 | reallocation (see discussion on embeddable vectors below). | ||||
98 | |||||
99 | - Space efficient: The vector is structured as a pointer to an | ||||
100 | embedded vector. This is the default layout. It means that | ||||
101 | vectors occupy a single word of storage before initial | ||||
102 | allocation. Vectors are allowed to grow (the internal | ||||
103 | pointer is reallocated but the main vector instance does not | ||||
104 | need to relocate). | ||||
105 | |||||
106 | The type, allocation and layout are specified when the vector is | ||||
107 | declared. | ||||
108 | |||||
109 | If you need to directly manipulate a vector, then the 'address' | ||||
110 | accessor will return the address of the start of the vector. Also | ||||
111 | the 'space' predicate will tell you whether there is spare capacity | ||||
112 | in the vector. You will not normally need to use these two functions. | ||||
113 | |||||
114 | Notes on the different layout strategies | ||||
115 | |||||
116 | * Embeddable vectors (vec<T, A, vl_embed>) | ||||
117 | |||||
118 | These vectors are suitable to be embedded in other data | ||||
119 | structures so that they can be pre-allocated in a contiguous | ||||
120 | memory block. | ||||
121 | |||||
122 | Embeddable vectors are implemented using the trailing array | ||||
123 | idiom, thus they are not resizeable without changing the address | ||||
124 | of the vector object itself. This means you cannot have | ||||
125 | variables or fields of embeddable vector type -- always use a | ||||
126 | pointer to a vector. The one exception is the final field of a | ||||
127 | structure, which could be a vector type. | ||||
128 | |||||
129 | You will have to use the embedded_size & embedded_init calls to | ||||
130 | create such objects, and they will not be resizeable (so the | ||||
131 | 'safe' allocation variants are not available). | ||||
132 | |||||
133 | Properties of embeddable vectors: | ||||
134 | |||||
135 | - The whole vector and control data are allocated in a single | ||||
136 | contiguous block. It uses the trailing-vector idiom, so | ||||
137 | allocation must reserve enough space for all the elements | ||||
138 | in the vector plus its control data. | ||||
139 | - The vector cannot be re-allocated. | ||||
140 | - The vector cannot grow nor shrink. | ||||
141 | - No indirections needed for access/manipulation. | ||||
142 | - It requires 2 words of storage (prior to vector allocation). | ||||
143 | |||||
144 | |||||
145 | * Space efficient vector (vec<T, A, vl_ptr>) | ||||
146 | |||||
147 | These vectors can grow dynamically and are allocated together | ||||
148 | with their control data. They are suited to be included in data | ||||
149 | structures. Prior to initial allocation, they only take a single | ||||
150 | word of storage. | ||||
151 | |||||
152 | These vectors are implemented as a pointer to embeddable vectors. | ||||
153 | The semantics allow for this pointer to be NULL to represent | ||||
154 | empty vectors. This way, empty vectors occupy minimal space in | ||||
155 | the structure containing them. | ||||
156 | |||||
157 | Properties: | ||||
158 | |||||
159 | - The whole vector and control data are allocated in a single | ||||
160 | contiguous block. | ||||
161 | - The whole vector may be re-allocated. | ||||
162 | - Vector data may grow and shrink. | ||||
163 | - Access and manipulation requires a pointer test and | ||||
164 | indirection. | ||||
165 | - It requires 1 word of storage (prior to vector allocation). | ||||
166 | |||||
167 | An example of their use would be, | ||||
168 | |||||
169 | struct my_struct { | ||||
170 | // A space-efficient vector of tree pointers in GC memory. | ||||
171 | vec<tree, va_gc, vl_ptr> v; | ||||
172 | }; | ||||
173 | |||||
174 | struct my_struct *s; | ||||
175 | |||||
176 | if (s->v.length ()) { we have some contents } | ||||
177 | s->v.safe_push (decl); // append some decl onto the end | ||||
178 | for (ix = 0; s->v.iterate (ix, &elt); ix++) | ||||
179 | { do something with elt } | ||||
180 | */ | ||||
181 | |||||
182 | /* Support function for statistics. */ | ||||
183 | extern void dump_vec_loc_statistics (void); | ||||
184 | |||||
185 | /* Hashtable mapping vec addresses to descriptors. */ | ||||
186 | extern htab_t vec_mem_usage_hash; | ||||
187 | |||||
188 | /* Control data for vectors. This contains the number of allocated | ||||
189 | and used slots inside a vector. */ | ||||
190 | |||||
191 | struct vec_prefix | ||||
192 | { | ||||
193 | /* FIXME - These fields should be private, but we need to cater to | ||||
194 | compilers that have stricter notions of PODness for types. */ | ||||
195 | |||||
196 | /* Memory allocation support routines in vec.c. */ | ||||
197 | void register_overhead (void *, size_t, size_t CXX_MEM_STAT_INFO); | ||||
198 | void release_overhead (void *, size_t, size_t, bool CXX_MEM_STAT_INFO); | ||||
199 | static unsigned calculate_allocation (vec_prefix *, unsigned, bool); | ||||
200 | static unsigned calculate_allocation_1 (unsigned, unsigned); | ||||
201 | |||||
202 | /* Note that vec_prefix should be a base class for vec, but we use | ||||
203 | offsetof() on vector fields of tree structures (e.g., | ||||
204 | tree_binfo::base_binfos), and offsetof only supports base types. | ||||
205 | |||||
206 | To compensate, we make vec_prefix a field inside vec and make | ||||
207 | vec a friend class of vec_prefix so it can access its fields. */ | ||||
208 | template <typename, typename, typename> friend struct vec; | ||||
209 | |||||
210 | /* The allocator types also need access to our internals. */ | ||||
211 | friend struct va_gc; | ||||
212 | friend struct va_gc_atomic; | ||||
213 | friend struct va_heap; | ||||
214 | |||||
215 | unsigned m_alloc : 31; | ||||
216 | unsigned m_using_auto_storage : 1; | ||||
217 | unsigned m_num; | ||||
218 | }; | ||||
219 | |||||
220 | /* Calculate the number of slots to reserve a vector, making sure that | ||||
221 | RESERVE slots are free. If EXACT grow exactly, otherwise grow | ||||
222 | exponentially. PFX is the control data for the vector. */ | ||||
223 | |||||
224 | inline unsigned | ||||
225 | vec_prefix::calculate_allocation (vec_prefix *pfx, unsigned reserve, | ||||
226 | bool exact) | ||||
227 | { | ||||
228 | if (exact) | ||||
229 | return (pfx ? pfx->m_num : 0) + reserve; | ||||
230 | else if (!pfx) | ||||
231 | return MAX (4, reserve)((4) > (reserve) ? (4) : (reserve)); | ||||
232 | return calculate_allocation_1 (pfx->m_alloc, pfx->m_num + reserve); | ||||
233 | } | ||||
234 | |||||
235 | template<typename, typename, typename> struct vec; | ||||
236 | |||||
237 | /* Valid vector layouts | ||||
238 | |||||
239 | vl_embed - Embeddable vector that uses the trailing array idiom. | ||||
240 | vl_ptr - Space efficient vector that uses a pointer to an | ||||
241 | embeddable vector. */ | ||||
242 | struct vl_embed { }; | ||||
243 | struct vl_ptr { }; | ||||
244 | |||||
245 | |||||
246 | /* Types of supported allocations | ||||
247 | |||||
248 | va_heap - Allocation uses malloc/free. | ||||
249 | va_gc - Allocation uses ggc_alloc. | ||||
250 | va_gc_atomic - Same as GC, but individual elements of the array | ||||
251 | do not need to be marked during collection. */ | ||||
252 | |||||
253 | /* Allocator type for heap vectors. */ | ||||
254 | struct va_heap | ||||
255 | { | ||||
256 | /* Heap vectors are frequently regular instances, so use the vl_ptr | ||||
257 | layout for them. */ | ||||
258 | typedef vl_ptr default_layout; | ||||
259 | |||||
260 | template<typename T> | ||||
261 | static void reserve (vec<T, va_heap, vl_embed> *&, unsigned, bool | ||||
262 | CXX_MEM_STAT_INFO); | ||||
263 | |||||
264 | template<typename T> | ||||
265 | static void release (vec<T, va_heap, vl_embed> *&); | ||||
266 | }; | ||||
267 | |||||
268 | |||||
269 | /* Allocator for heap memory. Ensure there are at least RESERVE free | ||||
270 | slots in V. If EXACT is true, grow exactly, else grow | ||||
271 | exponentially. As a special case, if the vector had not been | ||||
272 | allocated and RESERVE is 0, no vector will be created. */ | ||||
273 | |||||
274 | template<typename T> | ||||
275 | inline void | ||||
276 | va_heap::reserve (vec<T, va_heap, vl_embed> *&v, unsigned reserve, bool exact | ||||
277 | MEM_STAT_DECL) | ||||
278 | { | ||||
279 | size_t elt_size = sizeof (T); | ||||
280 | unsigned alloc | ||||
281 | = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact); | ||||
282 | gcc_checking_assert (alloc)((void)(!(alloc) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 282, __FUNCTION__), 0 : 0)); | ||||
283 | |||||
284 | if (GATHER_STATISTICS0 && v) | ||||
285 | v->m_vecpfx.release_overhead (v, elt_size * v->allocated (), | ||||
286 | v->allocated (), false); | ||||
287 | |||||
288 | size_t size = vec<T, va_heap, vl_embed>::embedded_size (alloc); | ||||
289 | unsigned nelem = v ? v->length () : 0; | ||||
290 | v = static_cast <vec<T, va_heap, vl_embed> *> (xrealloc (v, size)); | ||||
291 | v->embedded_init (alloc, nelem); | ||||
292 | |||||
293 | if (GATHER_STATISTICS0) | ||||
294 | v->m_vecpfx.register_overhead (v, alloc, elt_size PASS_MEM_STAT); | ||||
295 | } | ||||
296 | |||||
297 | |||||
298 | #if GCC_VERSION(4 * 1000 + 2) >= 4007 | ||||
299 | #pragma GCC diagnostic push | ||||
300 | #pragma GCC diagnostic ignored "-Wfree-nonheap-object" | ||||
301 | #endif | ||||
302 | |||||
303 | /* Free the heap space allocated for vector V. */ | ||||
304 | |||||
305 | template<typename T> | ||||
306 | void | ||||
307 | va_heap::release (vec<T, va_heap, vl_embed> *&v) | ||||
308 | { | ||||
309 | size_t elt_size = sizeof (T); | ||||
310 | if (v == NULL__null) | ||||
311 | return; | ||||
312 | |||||
313 | if (GATHER_STATISTICS0) | ||||
314 | v->m_vecpfx.release_overhead (v, elt_size * v->allocated (), | ||||
315 | v->allocated (), true); | ||||
316 | ::free (v); | ||||
317 | v = NULL__null; | ||||
318 | } | ||||
319 | |||||
320 | #if GCC_VERSION(4 * 1000 + 2) >= 4007 | ||||
321 | #pragma GCC diagnostic pop | ||||
322 | #endif | ||||
323 | |||||
324 | /* Allocator type for GC vectors. Notice that we need the structure | ||||
325 | declaration even if GC is not enabled. */ | ||||
326 | |||||
327 | struct va_gc | ||||
328 | { | ||||
329 | /* Use vl_embed as the default layout for GC vectors. Due to GTY | ||||
330 | limitations, GC vectors must always be pointers, so it is more | ||||
331 | efficient to use a pointer to the vl_embed layout, rather than | ||||
332 | using a pointer to a pointer as would be the case with vl_ptr. */ | ||||
333 | typedef vl_embed default_layout; | ||||
334 | |||||
335 | template<typename T, typename A> | ||||
336 | static void reserve (vec<T, A, vl_embed> *&, unsigned, bool | ||||
337 | CXX_MEM_STAT_INFO); | ||||
338 | |||||
339 | template<typename T, typename A> | ||||
340 | static void release (vec<T, A, vl_embed> *&v); | ||||
341 | }; | ||||
342 | |||||
343 | |||||
344 | /* Free GC memory used by V and reset V to NULL. */ | ||||
345 | |||||
346 | template<typename T, typename A> | ||||
347 | inline void | ||||
348 | va_gc::release (vec<T, A, vl_embed> *&v) | ||||
349 | { | ||||
350 | if (v) | ||||
351 | ::ggc_free (v); | ||||
352 | v = NULL__null; | ||||
353 | } | ||||
354 | |||||
355 | |||||
356 | /* Allocator for GC memory. Ensure there are at least RESERVE free | ||||
357 | slots in V. If EXACT is true, grow exactly, else grow | ||||
358 | exponentially. As a special case, if the vector had not been | ||||
359 | allocated and RESERVE is 0, no vector will be created. */ | ||||
360 | |||||
361 | template<typename T, typename A> | ||||
362 | void | ||||
363 | va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact | ||||
364 | MEM_STAT_DECL) | ||||
365 | { | ||||
366 | unsigned alloc | ||||
367 | = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact); | ||||
368 | if (!alloc) | ||||
369 | { | ||||
370 | ::ggc_free (v); | ||||
371 | v = NULL__null; | ||||
372 | return; | ||||
373 | } | ||||
374 | |||||
375 | /* Calculate the amount of space we want. */ | ||||
376 | size_t size = vec<T, A, vl_embed>::embedded_size (alloc); | ||||
377 | |||||
378 | /* Ask the allocator how much space it will really give us. */ | ||||
379 | size = ::ggc_round_alloc_size (size); | ||||
380 | |||||
381 | /* Adjust the number of slots accordingly. */ | ||||
382 | size_t vec_offset = sizeof (vec_prefix); | ||||
383 | size_t elt_size = sizeof (T); | ||||
384 | alloc = (size - vec_offset) / elt_size; | ||||
385 | |||||
386 | /* And finally, recalculate the amount of space we ask for. */ | ||||
387 | size = vec_offset + alloc * elt_size; | ||||
388 | |||||
389 | unsigned nelem = v ? v->length () : 0; | ||||
390 | v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc (v, size | ||||
391 | PASS_MEM_STAT)); | ||||
392 | v->embedded_init (alloc, nelem); | ||||
393 | } | ||||
394 | |||||
395 | |||||
396 | /* Allocator type for GC vectors. This is for vectors of types | ||||
397 | atomics w.r.t. collection, so allocation and deallocation is | ||||
398 | completely inherited from va_gc. */ | ||||
399 | struct va_gc_atomic : va_gc | ||||
400 | { | ||||
401 | }; | ||||
402 | |||||
403 | |||||
404 | /* Generic vector template. Default values for A and L indicate the | ||||
405 | most commonly used strategies. | ||||
406 | |||||
407 | FIXME - Ideally, they would all be vl_ptr to encourage using regular | ||||
408 | instances for vectors, but the existing GTY machinery is limited | ||||
409 | in that it can only deal with GC objects that are pointers | ||||
410 | themselves. | ||||
411 | |||||
412 | This means that vector operations that need to deal with | ||||
413 | potentially NULL pointers, must be provided as free | ||||
414 | functions (see the vec_safe_* functions above). */ | ||||
415 | template<typename T, | ||||
416 | typename A = va_heap, | ||||
417 | typename L = typename A::default_layout> | ||||
418 | struct GTY((user)) vec | ||||
419 | { | ||||
420 | }; | ||||
421 | |||||
422 | /* Allow C++11 range-based 'for' to work directly on vec<T>*. */ | ||||
423 | template<typename T, typename A, typename L> | ||||
424 | T* begin (vec<T,A,L> *v) { return v ? v->begin () : nullptr; } | ||||
425 | template<typename T, typename A, typename L> | ||||
426 | T* end (vec<T,A,L> *v) { return v ? v->end () : nullptr; } | ||||
427 | template<typename T, typename A, typename L> | ||||
428 | const T* begin (const vec<T,A,L> *v) { return v ? v->begin () : nullptr; } | ||||
429 | template<typename T, typename A, typename L> | ||||
430 | const T* end (const vec<T,A,L> *v) { return v ? v->end () : nullptr; } | ||||
431 | |||||
432 | /* Generic vec<> debug helpers. | ||||
433 | |||||
434 | These need to be instantiated for each vec<TYPE> used throughout | ||||
435 | the compiler like this: | ||||
436 | |||||
437 | DEFINE_DEBUG_VEC (TYPE) | ||||
438 | |||||
439 | The reason we have a debug_helper() is because GDB can't | ||||
440 | disambiguate a plain call to debug(some_vec), and it must be called | ||||
441 | like debug<TYPE>(some_vec). */ | ||||
442 | |||||
443 | template<typename T> | ||||
444 | void | ||||
445 | debug_helper (vec<T> &ref) | ||||
446 | { | ||||
447 | unsigned i; | ||||
448 | for (i = 0; i < ref.length (); ++i) | ||||
449 | { | ||||
450 | fprintf (stderrstderr, "[%d] = ", i); | ||||
451 | debug_slim (ref[i]); | ||||
452 | fputc ('\n', stderrstderr); | ||||
453 | } | ||||
454 | } | ||||
455 | |||||
456 | /* We need a separate va_gc variant here because default template | ||||
457 | argument for functions cannot be used in c++-98. Once this | ||||
458 | restriction is removed, those variant should be folded with the | ||||
459 | above debug_helper. */ | ||||
460 | |||||
461 | template<typename T> | ||||
462 | void | ||||
463 | debug_helper (vec<T, va_gc> &ref) | ||||
464 | { | ||||
465 | unsigned i; | ||||
466 | for (i = 0; i < ref.length (); ++i) | ||||
467 | { | ||||
468 | fprintf (stderrstderr, "[%d] = ", i); | ||||
469 | debug_slim (ref[i]); | ||||
470 | fputc ('\n', stderrstderr); | ||||
471 | } | ||||
472 | } | ||||
473 | |||||
474 | /* Macro to define debug(vec<T>) and debug(vec<T, va_gc>) helper | ||||
475 | functions for a type T. */ | ||||
476 | |||||
477 | #define DEFINE_DEBUG_VEC(T)template void debug_helper (vec<T> &); template void debug_helper (vec<T, va_gc> &); __attribute__ ((__used__ )) void debug (vec<T> &ref) { debug_helper <T> (ref); } __attribute__ ((__used__)) void debug (vec<T> *ptr) { if (ptr) debug (*ptr); else fprintf (stderr, "<nil>\n" ); } __attribute__ ((__used__)) void debug (vec<T, va_gc> &ref) { debug_helper <T> (ref); } __attribute__ (( __used__)) void debug (vec<T, va_gc> *ptr) { if (ptr) debug (*ptr); else fprintf (stderr, "<nil>\n"); } \ | ||||
478 | template void debug_helper (vec<T> &); \ | ||||
479 | template void debug_helper (vec<T, va_gc> &); \ | ||||
480 | /* Define the vec<T> debug functions. */ \ | ||||
481 | DEBUG_FUNCTION__attribute__ ((__used__)) void \ | ||||
482 | debug (vec<T> &ref) \ | ||||
483 | { \ | ||||
484 | debug_helper <T> (ref); \ | ||||
485 | } \ | ||||
486 | DEBUG_FUNCTION__attribute__ ((__used__)) void \ | ||||
487 | debug (vec<T> *ptr) \ | ||||
488 | { \ | ||||
489 | if (ptr) \ | ||||
490 | debug (*ptr); \ | ||||
491 | else \ | ||||
492 | fprintf (stderrstderr, "<nil>\n"); \ | ||||
493 | } \ | ||||
494 | /* Define the vec<T, va_gc> debug functions. */ \ | ||||
495 | DEBUG_FUNCTION__attribute__ ((__used__)) void \ | ||||
496 | debug (vec<T, va_gc> &ref) \ | ||||
497 | { \ | ||||
498 | debug_helper <T> (ref); \ | ||||
499 | } \ | ||||
500 | DEBUG_FUNCTION__attribute__ ((__used__)) void \ | ||||
501 | debug (vec<T, va_gc> *ptr) \ | ||||
502 | { \ | ||||
503 | if (ptr) \ | ||||
504 | debug (*ptr); \ | ||||
505 | else \ | ||||
506 | fprintf (stderrstderr, "<nil>\n"); \ | ||||
507 | } | ||||
508 | |||||
509 | /* Default-construct N elements in DST. */ | ||||
510 | |||||
511 | template <typename T> | ||||
512 | inline void | ||||
513 | vec_default_construct (T *dst, unsigned n) | ||||
514 | { | ||||
515 | #ifdef BROKEN_VALUE_INITIALIZATION | ||||
516 | /* Versions of GCC before 4.4 sometimes leave certain objects | ||||
517 | uninitialized when value initialized, though if the type has | ||||
518 | user defined default ctor, that ctor is invoked. As a workaround | ||||
519 | perform clearing first and then the value initialization, which | ||||
520 | fixes the case when value initialization doesn't initialize due to | ||||
521 | the bugs and should initialize to all zeros, but still allows | ||||
522 | vectors for types with user defined default ctor that initializes | ||||
523 | some or all elements to non-zero. If T has no user defined | ||||
524 | default ctor and some non-static data members have user defined | ||||
525 | default ctors that initialize to non-zero the workaround will | ||||
526 | still not work properly; in that case we just need to provide | ||||
527 | user defined default ctor. */ | ||||
528 | memset (dst, '\0', sizeof (T) * n); | ||||
529 | #endif | ||||
530 | for ( ; n; ++dst, --n) | ||||
531 | ::new (static_cast<void*>(dst)) T (); | ||||
532 | } | ||||
533 | |||||
534 | /* Copy-construct N elements in DST from *SRC. */ | ||||
535 | |||||
536 | template <typename T> | ||||
537 | inline void | ||||
538 | vec_copy_construct (T *dst, const T *src, unsigned n) | ||||
539 | { | ||||
540 | for ( ; n; ++dst, ++src, --n) | ||||
541 | ::new (static_cast<void*>(dst)) T (*src); | ||||
542 | } | ||||
543 | |||||
544 | /* Type to provide NULL values for vec<T, A, L>. This is used to | ||||
545 | provide nil initializers for vec instances. Since vec must be | ||||
546 | a POD, we cannot have proper ctor/dtor for it. To initialize | ||||
547 | a vec instance, you can assign it the value vNULL. This isn't | ||||
548 | needed for file-scope and function-local static vectors, which | ||||
549 | are zero-initialized by default. */ | ||||
550 | struct vnull | ||||
551 | { | ||||
552 | template <typename T, typename A, typename L> | ||||
553 | CONSTEXPRconstexpr operator vec<T, A, L> () const { return vec<T, A, L>(); } | ||||
554 | }; | ||||
555 | extern vnull vNULL; | ||||
556 | |||||
557 | |||||
558 | /* Embeddable vector. These vectors are suitable to be embedded | ||||
559 | in other data structures so that they can be pre-allocated in a | ||||
560 | contiguous memory block. | ||||
561 | |||||
562 | Embeddable vectors are implemented using the trailing array idiom, | ||||
563 | thus they are not resizeable without changing the address of the | ||||
564 | vector object itself. This means you cannot have variables or | ||||
565 | fields of embeddable vector type -- always use a pointer to a | ||||
566 | vector. The one exception is the final field of a structure, which | ||||
567 | could be a vector type. | ||||
568 | |||||
569 | You will have to use the embedded_size & embedded_init calls to | ||||
570 | create such objects, and they will not be resizeable (so the 'safe' | ||||
571 | allocation variants are not available). | ||||
572 | |||||
573 | Properties: | ||||
574 | |||||
575 | - The whole vector and control data are allocated in a single | ||||
576 | contiguous block. It uses the trailing-vector idiom, so | ||||
577 | allocation must reserve enough space for all the elements | ||||
578 | in the vector plus its control data. | ||||
579 | - The vector cannot be re-allocated. | ||||
580 | - The vector cannot grow nor shrink. | ||||
581 | - No indirections needed for access/manipulation. | ||||
582 | - It requires 2 words of storage (prior to vector allocation). */ | ||||
583 | |||||
584 | template<typename T, typename A> | ||||
585 | struct GTY((user)) vec<T, A, vl_embed> | ||||
586 | { | ||||
587 | public: | ||||
588 | unsigned allocated (void) const { return m_vecpfx.m_alloc; } | ||||
589 | unsigned length (void) const { return m_vecpfx.m_num; } | ||||
590 | bool is_empty (void) const { return m_vecpfx.m_num == 0; } | ||||
591 | T *address (void) { return m_vecdata; } | ||||
592 | const T *address (void) const { return m_vecdata; } | ||||
593 | T *begin () { return address (); } | ||||
594 | const T *begin () const { return address (); } | ||||
595 | T *end () { return address () + length (); } | ||||
596 | const T *end () const { return address () + length (); } | ||||
597 | const T &operator[] (unsigned) const; | ||||
598 | T &operator[] (unsigned); | ||||
599 | T &last (void); | ||||
600 | bool space (unsigned) const; | ||||
601 | bool iterate (unsigned, T *) const; | ||||
602 | bool iterate (unsigned, T **) const; | ||||
603 | vec *copy (ALONE_CXX_MEM_STAT_INFO) const; | ||||
604 | void splice (const vec &); | ||||
605 | void splice (const vec *src); | ||||
606 | T *quick_push (const T &); | ||||
607 | T &pop (void); | ||||
608 | void truncate (unsigned); | ||||
609 | void quick_insert (unsigned, const T &); | ||||
610 | void ordered_remove (unsigned); | ||||
611 | void unordered_remove (unsigned); | ||||
612 | void block_remove (unsigned, unsigned); | ||||
613 | void qsort (int (*) (const void *, const void *))qsort (int (*) (const void *, const void *)); | ||||
614 | void sort (int (*) (const void *, const void *, void *), void *); | ||||
615 | T *bsearch (const void *key, int (*compar)(const void *, const void *)); | ||||
616 | T *bsearch (const void *key, | ||||
617 | int (*compar)(const void *, const void *, void *), void *); | ||||
618 | unsigned lower_bound (T, bool (*)(const T &, const T &)) const; | ||||
619 | bool contains (const T &search) const; | ||||
620 | static size_t embedded_size (unsigned); | ||||
621 | void embedded_init (unsigned, unsigned = 0, unsigned = 0); | ||||
622 | void quick_grow (unsigned len); | ||||
623 | void quick_grow_cleared (unsigned len); | ||||
624 | |||||
625 | /* vec class can access our internal data and functions. */ | ||||
626 | template <typename, typename, typename> friend struct vec; | ||||
627 | |||||
628 | /* The allocator types also need access to our internals. */ | ||||
629 | friend struct va_gc; | ||||
630 | friend struct va_gc_atomic; | ||||
631 | friend struct va_heap; | ||||
632 | |||||
633 | /* FIXME - These fields should be private, but we need to cater to | ||||
634 | compilers that have stricter notions of PODness for types. */ | ||||
635 | vec_prefix m_vecpfx; | ||||
636 | T m_vecdata[1]; | ||||
637 | }; | ||||
638 | |||||
639 | |||||
640 | /* Convenience wrapper functions to use when dealing with pointers to | ||||
641 | embedded vectors. Some functionality for these vectors must be | ||||
642 | provided via free functions for these reasons: | ||||
643 | |||||
644 | 1- The pointer may be NULL (e.g., before initial allocation). | ||||
645 | |||||
646 | 2- When the vector needs to grow, it must be reallocated, so | ||||
647 | the pointer will change its value. | ||||
648 | |||||
649 | Because of limitations with the current GC machinery, all vectors | ||||
650 | in GC memory *must* be pointers. */ | ||||
651 | |||||
652 | |||||
653 | /* If V contains no room for NELEMS elements, return false. Otherwise, | ||||
654 | return true. */ | ||||
655 | template<typename T, typename A> | ||||
656 | inline bool | ||||
657 | vec_safe_space (const vec<T, A, vl_embed> *v, unsigned nelems) | ||||
658 | { | ||||
659 | return v ? v->space (nelems) : nelems == 0; | ||||
660 | } | ||||
661 | |||||
662 | |||||
663 | /* If V is NULL, return 0. Otherwise, return V->length(). */ | ||||
664 | template<typename T, typename A> | ||||
665 | inline unsigned | ||||
666 | vec_safe_length (const vec<T, A, vl_embed> *v) | ||||
667 | { | ||||
668 | return v ? v->length () : 0; | ||||
669 | } | ||||
670 | |||||
671 | |||||
672 | /* If V is NULL, return NULL. Otherwise, return V->address(). */ | ||||
673 | template<typename T, typename A> | ||||
674 | inline T * | ||||
675 | vec_safe_address (vec<T, A, vl_embed> *v) | ||||
676 | { | ||||
677 | return v ? v->address () : NULL__null; | ||||
678 | } | ||||
679 | |||||
680 | |||||
681 | /* If V is NULL, return true. Otherwise, return V->is_empty(). */ | ||||
682 | template<typename T, typename A> | ||||
683 | inline bool | ||||
684 | vec_safe_is_empty (vec<T, A, vl_embed> *v) | ||||
685 | { | ||||
686 | return v ? v->is_empty () : true; | ||||
687 | } | ||||
688 | |||||
689 | /* If V does not have space for NELEMS elements, call | ||||
690 | V->reserve(NELEMS, EXACT). */ | ||||
691 | template<typename T, typename A> | ||||
692 | inline bool | ||||
693 | vec_safe_reserve (vec<T, A, vl_embed> *&v, unsigned nelems, bool exact = false | ||||
694 | CXX_MEM_STAT_INFO) | ||||
695 | { | ||||
696 | bool extend = nelems
| ||||
697 | if (extend
| ||||
698 | A::reserve (v, nelems, exact PASS_MEM_STAT); | ||||
699 | return extend; | ||||
700 | } | ||||
701 | |||||
702 | template<typename T, typename A> | ||||
703 | inline bool | ||||
704 | vec_safe_reserve_exact (vec<T, A, vl_embed> *&v, unsigned nelems | ||||
705 | CXX_MEM_STAT_INFO) | ||||
706 | { | ||||
707 | return vec_safe_reserve (v, nelems, true PASS_MEM_STAT); | ||||
708 | } | ||||
709 | |||||
710 | |||||
711 | /* Allocate GC memory for V with space for NELEMS slots. If NELEMS | ||||
712 | is 0, V is initialized to NULL. */ | ||||
713 | |||||
714 | template<typename T, typename A> | ||||
715 | inline void | ||||
716 | vec_alloc (vec<T, A, vl_embed> *&v, unsigned nelems CXX_MEM_STAT_INFO) | ||||
717 | { | ||||
718 | v = NULL__null; | ||||
719 | vec_safe_reserve (v, nelems, false PASS_MEM_STAT); | ||||
720 | } | ||||
721 | |||||
722 | |||||
723 | /* Free the GC memory allocated by vector V and set it to NULL. */ | ||||
724 | |||||
725 | template<typename T, typename A> | ||||
726 | inline void | ||||
727 | vec_free (vec<T, A, vl_embed> *&v) | ||||
728 | { | ||||
729 | A::release (v); | ||||
730 | } | ||||
731 | |||||
732 | |||||
733 | /* Grow V to length LEN. Allocate it, if necessary. */ | ||||
734 | template<typename T, typename A> | ||||
735 | inline void | ||||
736 | vec_safe_grow (vec<T, A, vl_embed> *&v, unsigned len, | ||||
737 | bool exact = false CXX_MEM_STAT_INFO) | ||||
738 | { | ||||
739 | unsigned oldlen = vec_safe_length (v); | ||||
740 | gcc_checking_assert (len >= oldlen)((void)(!(len >= oldlen) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 740, __FUNCTION__), 0 : 0)); | ||||
741 | vec_safe_reserve (v, len - oldlen, exact PASS_MEM_STAT); | ||||
742 | v->quick_grow (len); | ||||
743 | } | ||||
744 | |||||
745 | |||||
746 | /* If V is NULL, allocate it. Call V->safe_grow_cleared(LEN). */ | ||||
747 | template<typename T, typename A> | ||||
748 | inline void | ||||
749 | vec_safe_grow_cleared (vec<T, A, vl_embed> *&v, unsigned len, | ||||
750 | bool exact = false CXX_MEM_STAT_INFO) | ||||
751 | { | ||||
752 | unsigned oldlen = vec_safe_length (v); | ||||
753 | vec_safe_grow (v, len, exact PASS_MEM_STAT); | ||||
754 | vec_default_construct (v->address () + oldlen, len - oldlen); | ||||
755 | } | ||||
756 | |||||
757 | |||||
758 | /* Assume V is not NULL. */ | ||||
759 | |||||
760 | template<typename T> | ||||
761 | inline void | ||||
762 | vec_safe_grow_cleared (vec<T, va_heap, vl_ptr> *&v, | ||||
763 | unsigned len, bool exact = false CXX_MEM_STAT_INFO) | ||||
764 | { | ||||
765 | v->safe_grow_cleared (len, exact PASS_MEM_STAT); | ||||
766 | } | ||||
767 | |||||
768 | /* If V does not have space for NELEMS elements, call | ||||
769 | V->reserve(NELEMS, EXACT). */ | ||||
770 | |||||
771 | template<typename T> | ||||
772 | inline bool | ||||
773 | vec_safe_reserve (vec<T, va_heap, vl_ptr> *&v, unsigned nelems, bool exact = false | ||||
774 | CXX_MEM_STAT_INFO) | ||||
775 | { | ||||
776 | return v->reserve (nelems, exact); | ||||
777 | } | ||||
778 | |||||
779 | |||||
780 | /* If V is NULL return false, otherwise return V->iterate(IX, PTR). */ | ||||
781 | template<typename T, typename A> | ||||
782 | inline bool | ||||
783 | vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T **ptr) | ||||
784 | { | ||||
785 | if (v) | ||||
786 | return v->iterate (ix, ptr); | ||||
787 | else | ||||
788 | { | ||||
789 | *ptr = 0; | ||||
790 | return false; | ||||
791 | } | ||||
792 | } | ||||
793 | |||||
794 | template<typename T, typename A> | ||||
795 | inline bool | ||||
796 | vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T *ptr) | ||||
797 | { | ||||
798 | if (v) | ||||
799 | return v->iterate (ix, ptr); | ||||
800 | else | ||||
801 | { | ||||
802 | *ptr = 0; | ||||
803 | return false; | ||||
804 | } | ||||
805 | } | ||||
806 | |||||
807 | |||||
808 | /* If V has no room for one more element, reallocate it. Then call | ||||
809 | V->quick_push(OBJ). */ | ||||
810 | template<typename T, typename A> | ||||
811 | inline T * | ||||
812 | vec_safe_push (vec<T, A, vl_embed> *&v, const T &obj CXX_MEM_STAT_INFO) | ||||
813 | { | ||||
814 | vec_safe_reserve (v, 1, false PASS_MEM_STAT); | ||||
815 | return v->quick_push (obj); | ||||
| |||||
816 | } | ||||
817 | |||||
818 | |||||
819 | /* if V has no room for one more element, reallocate it. Then call | ||||
820 | V->quick_insert(IX, OBJ). */ | ||||
821 | template<typename T, typename A> | ||||
822 | inline void | ||||
823 | vec_safe_insert (vec<T, A, vl_embed> *&v, unsigned ix, const T &obj | ||||
824 | CXX_MEM_STAT_INFO) | ||||
825 | { | ||||
826 | vec_safe_reserve (v, 1, false PASS_MEM_STAT); | ||||
827 | v->quick_insert (ix, obj); | ||||
828 | } | ||||
829 | |||||
830 | |||||
831 | /* If V is NULL, do nothing. Otherwise, call V->truncate(SIZE). */ | ||||
832 | template<typename T, typename A> | ||||
833 | inline void | ||||
834 | vec_safe_truncate (vec<T, A, vl_embed> *v, unsigned size) | ||||
835 | { | ||||
836 | if (v) | ||||
837 | v->truncate (size); | ||||
838 | } | ||||
839 | |||||
840 | |||||
841 | /* If SRC is not NULL, return a pointer to a copy of it. */ | ||||
842 | template<typename T, typename A> | ||||
843 | inline vec<T, A, vl_embed> * | ||||
844 | vec_safe_copy (vec<T, A, vl_embed> *src CXX_MEM_STAT_INFO) | ||||
845 | { | ||||
846 | return src ? src->copy (ALONE_PASS_MEM_STAT) : NULL__null; | ||||
847 | } | ||||
848 | |||||
849 | /* Copy the elements from SRC to the end of DST as if by memcpy. | ||||
850 | Reallocate DST, if necessary. */ | ||||
851 | template<typename T, typename A> | ||||
852 | inline void | ||||
853 | vec_safe_splice (vec<T, A, vl_embed> *&dst, const vec<T, A, vl_embed> *src | ||||
854 | CXX_MEM_STAT_INFO) | ||||
855 | { | ||||
856 | unsigned src_len = vec_safe_length (src); | ||||
857 | if (src_len) | ||||
858 | { | ||||
859 | vec_safe_reserve_exact (dst, vec_safe_length (dst) + src_len | ||||
860 | PASS_MEM_STAT); | ||||
861 | dst->splice (*src); | ||||
862 | } | ||||
863 | } | ||||
864 | |||||
865 | /* Return true if SEARCH is an element of V. Note that this is O(N) in the | ||||
866 | size of the vector and so should be used with care. */ | ||||
867 | |||||
868 | template<typename T, typename A> | ||||
869 | inline bool | ||||
870 | vec_safe_contains (vec<T, A, vl_embed> *v, const T &search) | ||||
871 | { | ||||
872 | return v ? v->contains (search) : false; | ||||
873 | } | ||||
874 | |||||
875 | /* Index into vector. Return the IX'th element. IX must be in the | ||||
876 | domain of the vector. */ | ||||
877 | |||||
878 | template<typename T, typename A> | ||||
879 | inline const T & | ||||
880 | vec<T, A, vl_embed>::operator[] (unsigned ix) const | ||||
881 | { | ||||
882 | gcc_checking_assert (ix < m_vecpfx.m_num)((void)(!(ix < m_vecpfx.m_num) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 882, __FUNCTION__), 0 : 0)); | ||||
883 | return m_vecdata[ix]; | ||||
884 | } | ||||
885 | |||||
886 | template<typename T, typename A> | ||||
887 | inline T & | ||||
888 | vec<T, A, vl_embed>::operator[] (unsigned ix) | ||||
889 | { | ||||
890 | gcc_checking_assert (ix < m_vecpfx.m_num)((void)(!(ix < m_vecpfx.m_num) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 890, __FUNCTION__), 0 : 0)); | ||||
891 | return m_vecdata[ix]; | ||||
892 | } | ||||
893 | |||||
894 | |||||
895 | /* Get the final element of the vector, which must not be empty. */ | ||||
896 | |||||
897 | template<typename T, typename A> | ||||
898 | inline T & | ||||
899 | vec<T, A, vl_embed>::last (void) | ||||
900 | { | ||||
901 | gcc_checking_assert (m_vecpfx.m_num > 0)((void)(!(m_vecpfx.m_num > 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 901, __FUNCTION__), 0 : 0)); | ||||
902 | return (*this)[m_vecpfx.m_num - 1]; | ||||
903 | } | ||||
904 | |||||
905 | |||||
906 | /* If this vector has space for NELEMS additional entries, return | ||||
907 | true. You usually only need to use this if you are doing your | ||||
908 | own vector reallocation, for instance on an embedded vector. This | ||||
909 | returns true in exactly the same circumstances that vec::reserve | ||||
910 | will. */ | ||||
911 | |||||
912 | template<typename T, typename A> | ||||
913 | inline bool | ||||
914 | vec<T, A, vl_embed>::space (unsigned nelems) const | ||||
915 | { | ||||
916 | return m_vecpfx.m_alloc - m_vecpfx.m_num >= nelems; | ||||
917 | } | ||||
918 | |||||
919 | |||||
920 | /* Return iteration condition and update PTR to point to the IX'th | ||||
921 | element of this vector. Use this to iterate over the elements of a | ||||
922 | vector as follows, | ||||
923 | |||||
924 | for (ix = 0; vec<T, A>::iterate (v, ix, &ptr); ix++) | ||||
925 | continue; */ | ||||
926 | |||||
927 | template<typename T, typename A> | ||||
928 | inline bool | ||||
929 | vec<T, A, vl_embed>::iterate (unsigned ix, T *ptr) const | ||||
930 | { | ||||
931 | if (ix < m_vecpfx.m_num) | ||||
932 | { | ||||
933 | *ptr = m_vecdata[ix]; | ||||
934 | return true; | ||||
935 | } | ||||
936 | else | ||||
937 | { | ||||
938 | *ptr = 0; | ||||
939 | return false; | ||||
940 | } | ||||
941 | } | ||||
942 | |||||
943 | |||||
944 | /* Return iteration condition and update *PTR to point to the | ||||
945 | IX'th element of this vector. Use this to iterate over the | ||||
946 | elements of a vector as follows, | ||||
947 | |||||
948 | for (ix = 0; v->iterate (ix, &ptr); ix++) | ||||
949 | continue; | ||||
950 | |||||
951 | This variant is for vectors of objects. */ | ||||
952 | |||||
953 | template<typename T, typename A> | ||||
954 | inline bool | ||||
955 | vec<T, A, vl_embed>::iterate (unsigned ix, T **ptr) const | ||||
956 | { | ||||
957 | if (ix < m_vecpfx.m_num) | ||||
958 | { | ||||
959 | *ptr = CONST_CAST (T *, &m_vecdata[ix])(const_cast<T *> ((&m_vecdata[ix]))); | ||||
960 | return true; | ||||
961 | } | ||||
962 | else | ||||
963 | { | ||||
964 | *ptr = 0; | ||||
965 | return false; | ||||
966 | } | ||||
967 | } | ||||
968 | |||||
969 | |||||
970 | /* Return a pointer to a copy of this vector. */ | ||||
971 | |||||
972 | template<typename T, typename A> | ||||
973 | inline vec<T, A, vl_embed> * | ||||
974 | vec<T, A, vl_embed>::copy (ALONE_MEM_STAT_DECLvoid) const | ||||
975 | { | ||||
976 | vec<T, A, vl_embed> *new_vec = NULL__null; | ||||
977 | unsigned len = length (); | ||||
978 | if (len) | ||||
979 | { | ||||
980 | vec_alloc (new_vec, len PASS_MEM_STAT); | ||||
981 | new_vec->embedded_init (len, len); | ||||
982 | vec_copy_construct (new_vec->address (), m_vecdata, len); | ||||
983 | } | ||||
984 | return new_vec; | ||||
985 | } | ||||
986 | |||||
987 | |||||
988 | /* Copy the elements from SRC to the end of this vector as if by memcpy. | ||||
989 | The vector must have sufficient headroom available. */ | ||||
990 | |||||
991 | template<typename T, typename A> | ||||
992 | inline void | ||||
993 | vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> &src) | ||||
994 | { | ||||
995 | unsigned len = src.length (); | ||||
996 | if (len) | ||||
997 | { | ||||
998 | gcc_checking_assert (space (len))((void)(!(space (len)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 998, __FUNCTION__), 0 : 0)); | ||||
999 | vec_copy_construct (end (), src.address (), len); | ||||
1000 | m_vecpfx.m_num += len; | ||||
1001 | } | ||||
1002 | } | ||||
1003 | |||||
1004 | template<typename T, typename A> | ||||
1005 | inline void | ||||
1006 | vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> *src) | ||||
1007 | { | ||||
1008 | if (src) | ||||
1009 | splice (*src); | ||||
1010 | } | ||||
1011 | |||||
1012 | |||||
1013 | /* Push OBJ (a new element) onto the end of the vector. There must be | ||||
1014 | sufficient space in the vector. Return a pointer to the slot | ||||
1015 | where OBJ was inserted. */ | ||||
1016 | |||||
1017 | template<typename T, typename A> | ||||
1018 | inline T * | ||||
1019 | vec<T, A, vl_embed>::quick_push (const T &obj) | ||||
1020 | { | ||||
1021 | gcc_checking_assert (space (1))((void)(!(space (1)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1021, __FUNCTION__), 0 : 0)); | ||||
1022 | T *slot = &m_vecdata[m_vecpfx.m_num++]; | ||||
1023 | *slot = obj; | ||||
1024 | return slot; | ||||
1025 | } | ||||
1026 | |||||
1027 | |||||
1028 | /* Pop and return the last element off the end of the vector. */ | ||||
1029 | |||||
1030 | template<typename T, typename A> | ||||
1031 | inline T & | ||||
1032 | vec<T, A, vl_embed>::pop (void) | ||||
1033 | { | ||||
1034 | gcc_checking_assert (length () > 0)((void)(!(length () > 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1034, __FUNCTION__), 0 : 0)); | ||||
1035 | return m_vecdata[--m_vecpfx.m_num]; | ||||
1036 | } | ||||
1037 | |||||
1038 | |||||
1039 | /* Set the length of the vector to SIZE. The new length must be less | ||||
1040 | than or equal to the current length. This is an O(1) operation. */ | ||||
1041 | |||||
1042 | template<typename T, typename A> | ||||
1043 | inline void | ||||
1044 | vec<T, A, vl_embed>::truncate (unsigned size) | ||||
1045 | { | ||||
1046 | gcc_checking_assert (length () >= size)((void)(!(length () >= size) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1046, __FUNCTION__), 0 : 0)); | ||||
1047 | m_vecpfx.m_num = size; | ||||
1048 | } | ||||
1049 | |||||
1050 | |||||
1051 | /* Insert an element, OBJ, at the IXth position of this vector. There | ||||
1052 | must be sufficient space. */ | ||||
1053 | |||||
1054 | template<typename T, typename A> | ||||
1055 | inline void | ||||
1056 | vec<T, A, vl_embed>::quick_insert (unsigned ix, const T &obj) | ||||
1057 | { | ||||
1058 | gcc_checking_assert (length () < allocated ())((void)(!(length () < allocated ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1058, __FUNCTION__), 0 : 0)); | ||||
1059 | gcc_checking_assert (ix <= length ())((void)(!(ix <= length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1059, __FUNCTION__), 0 : 0)); | ||||
1060 | T *slot = &m_vecdata[ix]; | ||||
1061 | memmove (slot + 1, slot, (m_vecpfx.m_num++ - ix) * sizeof (T)); | ||||
1062 | *slot = obj; | ||||
1063 | } | ||||
1064 | |||||
1065 | |||||
1066 | /* Remove an element from the IXth position of this vector. Ordering of | ||||
1067 | remaining elements is preserved. This is an O(N) operation due to | ||||
1068 | memmove. */ | ||||
1069 | |||||
1070 | template<typename T, typename A> | ||||
1071 | inline void | ||||
1072 | vec<T, A, vl_embed>::ordered_remove (unsigned ix) | ||||
1073 | { | ||||
1074 | gcc_checking_assert (ix < length ())((void)(!(ix < length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1074, __FUNCTION__), 0 : 0)); | ||||
1075 | T *slot = &m_vecdata[ix]; | ||||
1076 | memmove (slot, slot + 1, (--m_vecpfx.m_num - ix) * sizeof (T)); | ||||
1077 | } | ||||
1078 | |||||
1079 | |||||
1080 | /* Remove elements in [START, END) from VEC for which COND holds. Ordering of | ||||
1081 | remaining elements is preserved. This is an O(N) operation. */ | ||||
1082 | |||||
1083 | #define VEC_ORDERED_REMOVE_IF_FROM_TO(vec, read_index, write_index, \{ ((void)(!((end) <= (vec).length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1084, __FUNCTION__), 0 : 0)); for (read_index = write_index = (start); read_index < (end); ++read_index) { elem_ptr = &(vec)[read_index]; bool remove_p = (cond); if (remove_p ) continue; if (read_index != write_index) (vec)[write_index] = (vec)[read_index]; write_index++; } if (read_index - write_index > 0) (vec).block_remove (write_index, read_index - write_index ); } | ||||
1084 | elem_ptr, start, end, cond){ ((void)(!((end) <= (vec).length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1084, __FUNCTION__), 0 : 0)); for (read_index = write_index = (start); read_index < (end); ++read_index) { elem_ptr = &(vec)[read_index]; bool remove_p = (cond); if (remove_p ) continue; if (read_index != write_index) (vec)[write_index] = (vec)[read_index]; write_index++; } if (read_index - write_index > 0) (vec).block_remove (write_index, read_index - write_index ); } \ | ||||
1085 | { \ | ||||
1086 | gcc_assert ((end) <= (vec).length ())((void)(!((end) <= (vec).length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1086, __FUNCTION__), 0 : 0)); \ | ||||
1087 | for (read_index = write_index = (start); read_index < (end); \ | ||||
1088 | ++read_index) \ | ||||
1089 | { \ | ||||
1090 | elem_ptr = &(vec)[read_index]; \ | ||||
1091 | bool remove_p = (cond); \ | ||||
1092 | if (remove_p) \ | ||||
1093 | continue; \ | ||||
1094 | \ | ||||
1095 | if (read_index != write_index) \ | ||||
1096 | (vec)[write_index] = (vec)[read_index]; \ | ||||
1097 | \ | ||||
1098 | write_index++; \ | ||||
1099 | } \ | ||||
1100 | \ | ||||
1101 | if (read_index - write_index > 0) \ | ||||
1102 | (vec).block_remove (write_index, read_index - write_index); \ | ||||
1103 | } | ||||
1104 | |||||
1105 | |||||
1106 | /* Remove elements from VEC for which COND holds. Ordering of remaining | ||||
1107 | elements is preserved. This is an O(N) operation. */ | ||||
1108 | |||||
1109 | #define VEC_ORDERED_REMOVE_IF(vec, read_index, write_index, elem_ptr, \{ ((void)(!(((vec).length ()) <= ((vec)).length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1110, __FUNCTION__), 0 : 0)); for (read_index = write_index = (0); read_index < ((vec).length ()); ++read_index) { elem_ptr = &((vec))[read_index]; bool remove_p = ((cond)); if (remove_p ) continue; if (read_index != write_index) ((vec))[write_index ] = ((vec))[read_index]; write_index++; } if (read_index - write_index > 0) ((vec)).block_remove (write_index, read_index - write_index ); } | ||||
1110 | cond){ ((void)(!(((vec).length ()) <= ((vec)).length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1110, __FUNCTION__), 0 : 0)); for (read_index = write_index = (0); read_index < ((vec).length ()); ++read_index) { elem_ptr = &((vec))[read_index]; bool remove_p = ((cond)); if (remove_p ) continue; if (read_index != write_index) ((vec))[write_index ] = ((vec))[read_index]; write_index++; } if (read_index - write_index > 0) ((vec)).block_remove (write_index, read_index - write_index ); } \ | ||||
1111 | VEC_ORDERED_REMOVE_IF_FROM_TO ((vec), read_index, write_index, \{ ((void)(!(((vec).length ()) <= ((vec)).length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1112, __FUNCTION__), 0 : 0)); for (read_index = write_index = (0); read_index < ((vec).length ()); ++read_index) { elem_ptr = &((vec))[read_index]; bool remove_p = ((cond)); if (remove_p ) continue; if (read_index != write_index) ((vec))[write_index ] = ((vec))[read_index]; write_index++; } if (read_index - write_index > 0) ((vec)).block_remove (write_index, read_index - write_index ); } | ||||
1112 | elem_ptr, 0, (vec).length (), (cond)){ ((void)(!(((vec).length ()) <= ((vec)).length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1112, __FUNCTION__), 0 : 0)); for (read_index = write_index = (0); read_index < ((vec).length ()); ++read_index) { elem_ptr = &((vec))[read_index]; bool remove_p = ((cond)); if (remove_p ) continue; if (read_index != write_index) ((vec))[write_index ] = ((vec))[read_index]; write_index++; } if (read_index - write_index > 0) ((vec)).block_remove (write_index, read_index - write_index ); } | ||||
1113 | |||||
1114 | /* Remove an element from the IXth position of this vector. Ordering of | ||||
1115 | remaining elements is destroyed. This is an O(1) operation. */ | ||||
1116 | |||||
1117 | template<typename T, typename A> | ||||
1118 | inline void | ||||
1119 | vec<T, A, vl_embed>::unordered_remove (unsigned ix) | ||||
1120 | { | ||||
1121 | gcc_checking_assert (ix < length ())((void)(!(ix < length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1121, __FUNCTION__), 0 : 0)); | ||||
1122 | m_vecdata[ix] = m_vecdata[--m_vecpfx.m_num]; | ||||
1123 | } | ||||
1124 | |||||
1125 | |||||
1126 | /* Remove LEN elements starting at the IXth. Ordering is retained. | ||||
1127 | This is an O(N) operation due to memmove. */ | ||||
1128 | |||||
1129 | template<typename T, typename A> | ||||
1130 | inline void | ||||
1131 | vec<T, A, vl_embed>::block_remove (unsigned ix, unsigned len) | ||||
1132 | { | ||||
1133 | gcc_checking_assert (ix + len <= length ())((void)(!(ix + len <= length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1133, __FUNCTION__), 0 : 0)); | ||||
1134 | T *slot = &m_vecdata[ix]; | ||||
1135 | m_vecpfx.m_num -= len; | ||||
1136 | memmove (slot, slot + len, (m_vecpfx.m_num - ix) * sizeof (T)); | ||||
1137 | } | ||||
1138 | |||||
1139 | |||||
1140 | /* Sort the contents of this vector with qsort. CMP is the comparison | ||||
1141 | function to pass to qsort. */ | ||||
1142 | |||||
1143 | template<typename T, typename A> | ||||
1144 | inline void | ||||
1145 | vec<T, A, vl_embed>::qsort (int (*cmp) (const void *, const void *))qsort (int (*cmp) (const void *, const void *)) | ||||
1146 | { | ||||
1147 | if (length () > 1) | ||||
1148 | gcc_qsort (address (), length (), sizeof (T), cmp); | ||||
1149 | } | ||||
1150 | |||||
1151 | /* Sort the contents of this vector with qsort. CMP is the comparison | ||||
1152 | function to pass to qsort. */ | ||||
1153 | |||||
1154 | template<typename T, typename A> | ||||
1155 | inline void | ||||
1156 | vec<T, A, vl_embed>::sort (int (*cmp) (const void *, const void *, void *), | ||||
1157 | void *data) | ||||
1158 | { | ||||
1159 | if (length () > 1) | ||||
1160 | gcc_sort_r (address (), length (), sizeof (T), cmp, data); | ||||
1161 | } | ||||
1162 | |||||
1163 | |||||
1164 | /* Search the contents of the sorted vector with a binary search. | ||||
1165 | CMP is the comparison function to pass to bsearch. */ | ||||
1166 | |||||
1167 | template<typename T, typename A> | ||||
1168 | inline T * | ||||
1169 | vec<T, A, vl_embed>::bsearch (const void *key, | ||||
1170 | int (*compar) (const void *, const void *)) | ||||
1171 | { | ||||
1172 | const void *base = this->address (); | ||||
1173 | size_t nmemb = this->length (); | ||||
1174 | size_t size = sizeof (T); | ||||
1175 | /* The following is a copy of glibc stdlib-bsearch.h. */ | ||||
1176 | size_t l, u, idx; | ||||
1177 | const void *p; | ||||
1178 | int comparison; | ||||
1179 | |||||
1180 | l = 0; | ||||
1181 | u = nmemb; | ||||
1182 | while (l < u) | ||||
1183 | { | ||||
1184 | idx = (l + u) / 2; | ||||
1185 | p = (const void *) (((const char *) base) + (idx * size)); | ||||
1186 | comparison = (*compar) (key, p); | ||||
1187 | if (comparison < 0) | ||||
1188 | u = idx; | ||||
1189 | else if (comparison > 0) | ||||
1190 | l = idx + 1; | ||||
1191 | else | ||||
1192 | return (T *)const_cast<void *>(p); | ||||
1193 | } | ||||
1194 | |||||
1195 | return NULL__null; | ||||
1196 | } | ||||
1197 | |||||
1198 | /* Search the contents of the sorted vector with a binary search. | ||||
1199 | CMP is the comparison function to pass to bsearch. */ | ||||
1200 | |||||
1201 | template<typename T, typename A> | ||||
1202 | inline T * | ||||
1203 | vec<T, A, vl_embed>::bsearch (const void *key, | ||||
1204 | int (*compar) (const void *, const void *, | ||||
1205 | void *), void *data) | ||||
1206 | { | ||||
1207 | const void *base = this->address (); | ||||
1208 | size_t nmemb = this->length (); | ||||
1209 | size_t size = sizeof (T); | ||||
1210 | /* The following is a copy of glibc stdlib-bsearch.h. */ | ||||
1211 | size_t l, u, idx; | ||||
1212 | const void *p; | ||||
1213 | int comparison; | ||||
1214 | |||||
1215 | l = 0; | ||||
1216 | u = nmemb; | ||||
1217 | while (l < u) | ||||
1218 | { | ||||
1219 | idx = (l + u) / 2; | ||||
1220 | p = (const void *) (((const char *) base) + (idx * size)); | ||||
1221 | comparison = (*compar) (key, p, data); | ||||
1222 | if (comparison < 0) | ||||
1223 | u = idx; | ||||
1224 | else if (comparison > 0) | ||||
1225 | l = idx + 1; | ||||
1226 | else | ||||
1227 | return (T *)const_cast<void *>(p); | ||||
1228 | } | ||||
1229 | |||||
1230 | return NULL__null; | ||||
1231 | } | ||||
1232 | |||||
1233 | /* Return true if SEARCH is an element of V. Note that this is O(N) in the | ||||
1234 | size of the vector and so should be used with care. */ | ||||
1235 | |||||
1236 | template<typename T, typename A> | ||||
1237 | inline bool | ||||
1238 | vec<T, A, vl_embed>::contains (const T &search) const | ||||
1239 | { | ||||
1240 | unsigned int len = length (); | ||||
1241 | for (unsigned int i = 0; i < len; i++) | ||||
1242 | if ((*this)[i] == search) | ||||
1243 | return true; | ||||
1244 | |||||
1245 | return false; | ||||
1246 | } | ||||
1247 | |||||
1248 | /* Find and return the first position in which OBJ could be inserted | ||||
1249 | without changing the ordering of this vector. LESSTHAN is a | ||||
1250 | function that returns true if the first argument is strictly less | ||||
1251 | than the second. */ | ||||
1252 | |||||
1253 | template<typename T, typename A> | ||||
1254 | unsigned | ||||
1255 | vec<T, A, vl_embed>::lower_bound (T obj, bool (*lessthan)(const T &, const T &)) | ||||
1256 | const | ||||
1257 | { | ||||
1258 | unsigned int len = length (); | ||||
1259 | unsigned int half, middle; | ||||
1260 | unsigned int first = 0; | ||||
1261 | while (len > 0) | ||||
1262 | { | ||||
1263 | half = len / 2; | ||||
1264 | middle = first; | ||||
1265 | middle += half; | ||||
1266 | T middle_elem = (*this)[middle]; | ||||
1267 | if (lessthan (middle_elem, obj)) | ||||
1268 | { | ||||
1269 | first = middle; | ||||
1270 | ++first; | ||||
1271 | len = len - half - 1; | ||||
1272 | } | ||||
1273 | else | ||||
1274 | len = half; | ||||
1275 | } | ||||
1276 | return first; | ||||
1277 | } | ||||
1278 | |||||
1279 | |||||
1280 | /* Return the number of bytes needed to embed an instance of an | ||||
1281 | embeddable vec inside another data structure. | ||||
1282 | |||||
1283 | Use these methods to determine the required size and initialization | ||||
1284 | of a vector V of type T embedded within another structure (as the | ||||
1285 | final member): | ||||
1286 | |||||
1287 | size_t vec<T, A, vl_embed>::embedded_size (unsigned alloc); | ||||
1288 | void v->embedded_init (unsigned alloc, unsigned num); | ||||
1289 | |||||
1290 | These allow the caller to perform the memory allocation. */ | ||||
1291 | |||||
1292 | template<typename T, typename A> | ||||
1293 | inline size_t | ||||
1294 | vec<T, A, vl_embed>::embedded_size (unsigned alloc) | ||||
1295 | { | ||||
1296 | struct alignas (T) U { char data[sizeof (T)]; }; | ||||
1297 | typedef vec<U, A, vl_embed> vec_embedded; | ||||
1298 | typedef typename std::conditional<std::is_standard_layout<T>::value, | ||||
1299 | vec, vec_embedded>::type vec_stdlayout; | ||||
1300 | static_assert (sizeof (vec_stdlayout) == sizeof (vec), ""); | ||||
1301 | static_assert (alignof (vec_stdlayout) == alignof (vec), ""); | ||||
1302 | return offsetof (vec_stdlayout, m_vecdata)__builtin_offsetof(vec_stdlayout, m_vecdata) + alloc * sizeof (T); | ||||
1303 | } | ||||
1304 | |||||
1305 | |||||
1306 | /* Initialize the vector to contain room for ALLOC elements and | ||||
1307 | NUM active elements. */ | ||||
1308 | |||||
1309 | template<typename T, typename A> | ||||
1310 | inline void | ||||
1311 | vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num, unsigned aut) | ||||
1312 | { | ||||
1313 | m_vecpfx.m_alloc = alloc; | ||||
1314 | m_vecpfx.m_using_auto_storage = aut; | ||||
1315 | m_vecpfx.m_num = num; | ||||
1316 | } | ||||
1317 | |||||
1318 | |||||
1319 | /* Grow the vector to a specific length. LEN must be as long or longer than | ||||
1320 | the current length. The new elements are uninitialized. */ | ||||
1321 | |||||
1322 | template<typename T, typename A> | ||||
1323 | inline void | ||||
1324 | vec<T, A, vl_embed>::quick_grow (unsigned len) | ||||
1325 | { | ||||
1326 | gcc_checking_assert (length () <= len && len <= m_vecpfx.m_alloc)((void)(!(length () <= len && len <= m_vecpfx.m_alloc ) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1326, __FUNCTION__), 0 : 0)); | ||||
1327 | m_vecpfx.m_num = len; | ||||
1328 | } | ||||
1329 | |||||
1330 | |||||
1331 | /* Grow the vector to a specific length. LEN must be as long or longer than | ||||
1332 | the current length. The new elements are initialized to zero. */ | ||||
1333 | |||||
1334 | template<typename T, typename A> | ||||
1335 | inline void | ||||
1336 | vec<T, A, vl_embed>::quick_grow_cleared (unsigned len) | ||||
1337 | { | ||||
1338 | unsigned oldlen = length (); | ||||
1339 | size_t growby = len - oldlen; | ||||
1340 | quick_grow (len); | ||||
1341 | if (growby != 0) | ||||
1342 | vec_default_construct (address () + oldlen, growby); | ||||
1343 | } | ||||
1344 | |||||
1345 | /* Garbage collection support for vec<T, A, vl_embed>. */ | ||||
1346 | |||||
1347 | template<typename T> | ||||
1348 | void | ||||
1349 | gt_ggc_mx (vec<T, va_gc> *v) | ||||
1350 | { | ||||
1351 | extern void gt_ggc_mx (T &); | ||||
1352 | for (unsigned i = 0; i < v->length (); i++) | ||||
1353 | gt_ggc_mx ((*v)[i]); | ||||
1354 | } | ||||
1355 | |||||
1356 | template<typename T> | ||||
1357 | void | ||||
1358 | gt_ggc_mx (vec<T, va_gc_atomic, vl_embed> *v ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | ||||
1359 | { | ||||
1360 | /* Nothing to do. Vectors of atomic types wrt GC do not need to | ||||
1361 | be traversed. */ | ||||
1362 | } | ||||
1363 | |||||
1364 | |||||
1365 | /* PCH support for vec<T, A, vl_embed>. */ | ||||
1366 | |||||
1367 | template<typename T, typename A> | ||||
1368 | void | ||||
1369 | gt_pch_nx (vec<T, A, vl_embed> *v) | ||||
1370 | { | ||||
1371 | extern void gt_pch_nx (T &); | ||||
1372 | for (unsigned i = 0; i < v->length (); i++) | ||||
1373 | gt_pch_nx ((*v)[i]); | ||||
1374 | } | ||||
1375 | |||||
1376 | template<typename T, typename A> | ||||
1377 | void | ||||
1378 | gt_pch_nx (vec<T *, A, vl_embed> *v, gt_pointer_operator op, void *cookie) | ||||
1379 | { | ||||
1380 | for (unsigned i = 0; i < v->length (); i++) | ||||
1381 | op (&((*v)[i]), cookie); | ||||
1382 | } | ||||
1383 | |||||
1384 | template<typename T, typename A> | ||||
1385 | void | ||||
1386 | gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie) | ||||
1387 | { | ||||
1388 | extern void gt_pch_nx (T *, gt_pointer_operator, void *); | ||||
1389 | for (unsigned i = 0; i < v->length (); i++) | ||||
1390 | gt_pch_nx (&((*v)[i]), op, cookie); | ||||
1391 | } | ||||
1392 | |||||
1393 | |||||
1394 | /* Space efficient vector. These vectors can grow dynamically and are | ||||
1395 | allocated together with their control data. They are suited to be | ||||
1396 | included in data structures. Prior to initial allocation, they | ||||
1397 | only take a single word of storage. | ||||
1398 | |||||
1399 | These vectors are implemented as a pointer to an embeddable vector. | ||||
1400 | The semantics allow for this pointer to be NULL to represent empty | ||||
1401 | vectors. This way, empty vectors occupy minimal space in the | ||||
1402 | structure containing them. | ||||
1403 | |||||
1404 | Properties: | ||||
1405 | |||||
1406 | - The whole vector and control data are allocated in a single | ||||
1407 | contiguous block. | ||||
1408 | - The whole vector may be re-allocated. | ||||
1409 | - Vector data may grow and shrink. | ||||
1410 | - Access and manipulation requires a pointer test and | ||||
1411 | indirection. | ||||
1412 | - It requires 1 word of storage (prior to vector allocation). | ||||
1413 | |||||
1414 | |||||
1415 | Limitations: | ||||
1416 | |||||
1417 | These vectors must be PODs because they are stored in unions. | ||||
1418 | (http://en.wikipedia.org/wiki/Plain_old_data_structures). | ||||
1419 | As long as we use C++03, we cannot have constructors nor | ||||
1420 | destructors in classes that are stored in unions. */ | ||||
1421 | |||||
1422 | template<typename T> | ||||
1423 | struct vec<T, va_heap, vl_ptr> | ||||
1424 | { | ||||
1425 | public: | ||||
1426 | /* Memory allocation and deallocation for the embedded vector. | ||||
1427 | Needed because we cannot have proper ctors/dtors defined. */ | ||||
1428 | void create (unsigned nelems CXX_MEM_STAT_INFO); | ||||
1429 | void release (void); | ||||
1430 | |||||
1431 | /* Vector operations. */ | ||||
1432 | bool exists (void) const | ||||
1433 | { return m_vec != NULL__null; } | ||||
1434 | |||||
1435 | bool is_empty (void) const | ||||
1436 | { return m_vec ? m_vec->is_empty () : true; } | ||||
1437 | |||||
1438 | unsigned length (void) const | ||||
1439 | { return m_vec ? m_vec->length () : 0; } | ||||
1440 | |||||
1441 | T *address (void) | ||||
1442 | { return m_vec ? m_vec->m_vecdata : NULL__null; } | ||||
1443 | |||||
1444 | const T *address (void) const | ||||
1445 | { return m_vec ? m_vec->m_vecdata : NULL__null; } | ||||
1446 | |||||
1447 | T *begin () { return address (); } | ||||
1448 | const T *begin () const { return address (); } | ||||
1449 | T *end () { return begin () + length (); } | ||||
1450 | const T *end () const { return begin () + length (); } | ||||
1451 | const T &operator[] (unsigned ix) const | ||||
1452 | { return (*m_vec)[ix]; } | ||||
1453 | |||||
1454 | bool operator!=(const vec &other) const | ||||
1455 | { return !(*this == other); } | ||||
1456 | |||||
1457 | bool operator==(const vec &other) const | ||||
1458 | { return address () == other.address (); } | ||||
1459 | |||||
1460 | T &operator[] (unsigned ix) | ||||
1461 | { return (*m_vec)[ix]; } | ||||
1462 | |||||
1463 | T &last (void) | ||||
1464 | { return m_vec->last (); } | ||||
1465 | |||||
1466 | bool space (int nelems) const | ||||