File: | build/gcc/vec.h |
Warning: | line 742, column 3 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Parser for GIMPLE. | |||
2 | Copyright (C) 2016-2023 Free Software Foundation, Inc. | |||
3 | ||||
4 | This file is part of GCC. | |||
5 | ||||
6 | GCC is free software; you can redistribute it and/or modify it under | |||
7 | the terms of the GNU General Public License as published by the Free | |||
8 | Software Foundation; either version 3, or (at your option) any later | |||
9 | version. | |||
10 | ||||
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |||
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |||
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |||
14 | for more details. | |||
15 | ||||
16 | You should have received a copy of the GNU General Public License | |||
17 | along with GCC; see the file COPYING3. If not see | |||
18 | <http://www.gnu.org/licenses/>. */ | |||
19 | ||||
20 | #include "config.h" | |||
21 | #include "system.h" | |||
22 | #include "coretypes.h" | |||
23 | #include "target.h" | |||
24 | #include "function.h" | |||
25 | #include "c-tree.h" | |||
26 | #include "timevar.h" | |||
27 | #include "stringpool.h" | |||
28 | #include "cgraph.h" | |||
29 | #include "attribs.h" | |||
30 | #include "stor-layout.h" | |||
31 | #include "varasm.h" | |||
32 | #include "trans-mem.h" | |||
33 | #include "c-family/c-pragma.h" | |||
34 | #include "c-lang.h" | |||
35 | #include "c-family/c-objc.h" | |||
36 | #include "plugin.h" | |||
37 | #include "builtins.h" | |||
38 | #include "gomp-constants.h" | |||
39 | #include "c-family/c-indentation.h" | |||
40 | #include "gimple-expr.h" | |||
41 | #include "context.h" | |||
42 | #include "gcc-rich-location.h" | |||
43 | #include "c-parser.h" | |||
44 | #include "tree-vrp.h" | |||
45 | #include "tree-pass.h" | |||
46 | #include "tree-pretty-print.h" | |||
47 | #include "tree.h" | |||
48 | #include "basic-block.h" | |||
49 | #include "gimple.h" | |||
50 | #include "gimple-pretty-print.h" | |||
51 | #include "tree-ssa.h" | |||
52 | #include "pass_manager.h" | |||
53 | #include "tree-ssanames.h" | |||
54 | #include "gimple-ssa.h" | |||
55 | #include "tree-dfa.h" | |||
56 | #include "internal-fn.h" | |||
57 | #include "cfg.h" | |||
58 | #include "cfghooks.h" | |||
59 | #include "bitmap.h" | |||
60 | #include "cfganal.h" | |||
61 | #include "tree-cfg.h" | |||
62 | #include "gimple-iterator.h" | |||
63 | #include "cfgloop.h" | |||
64 | #include "tree-phinodes.h" | |||
65 | #include "tree-into-ssa.h" | |||
66 | ||||
67 | ||||
68 | /* GIMPLE parser state. */ | |||
69 | ||||
70 | class gimple_parser | |||
71 | { | |||
72 | public: | |||
73 | gimple_parser (c_parser *p) : parser (p), edges(), current_bb(NULLnullptr) {} | |||
74 | /* c_parser is not visible here, use composition and fake inheritance | |||
75 | via a conversion operator. */ | |||
76 | operator c_parser *() { return parser; } | |||
77 | c_parser *parser; | |||
78 | ||||
79 | /* CFG build state. */ | |||
80 | class gimple_parser_edge | |||
81 | { | |||
82 | public: | |||
83 | int src; | |||
84 | int dest; | |||
85 | int flags; | |||
86 | profile_probability probability; | |||
87 | }; | |||
88 | auto_vec<gimple_parser_edge> edges; | |||
89 | basic_block current_bb; | |||
90 | ||||
91 | void push_edge (int, int, int, profile_probability); | |||
92 | }; | |||
93 | ||||
94 | void | |||
95 | gimple_parser::push_edge (int src, int dest, int flags, | |||
96 | profile_probability prob) | |||
97 | { | |||
98 | gimple_parser_edge e; | |||
99 | e.src = src; | |||
100 | e.dest = dest; | |||
101 | e.flags = flags; | |||
102 | e.probability = prob; | |||
103 | edges.safe_push (e); | |||
104 | } | |||
105 | ||||
106 | ||||
107 | /* Gimple parsing functions. */ | |||
108 | static bool c_parser_gimple_compound_statement (gimple_parser &, gimple_seq *); | |||
109 | static void c_parser_gimple_label (gimple_parser &, gimple_seq *); | |||
110 | static void c_parser_gimple_statement (gimple_parser &, gimple_seq *); | |||
111 | static struct c_expr c_parser_gimple_binary_expression (gimple_parser &); | |||
112 | static struct c_expr c_parser_gimple_unary_expression (gimple_parser &); | |||
113 | static struct c_expr c_parser_gimple_postfix_expression (gimple_parser &); | |||
114 | static struct c_expr c_parser_gimple_postfix_expression_after_primary | |||
115 | (gimple_parser &, location_t, struct c_expr); | |||
116 | static void c_parser_gimple_declaration (gimple_parser &); | |||
117 | static void c_parser_gimple_goto_stmt (gimple_parser &, location_t, | |||
118 | tree, gimple_seq *); | |||
119 | static void c_parser_gimple_try_stmt (gimple_parser &, gimple_seq *); | |||
120 | static void c_parser_gimple_if_stmt (gimple_parser &, gimple_seq *); | |||
121 | static void c_parser_gimple_switch_stmt (gimple_parser &, gimple_seq *); | |||
122 | static void c_parser_gimple_return_stmt (gimple_parser &, gimple_seq *); | |||
123 | static void c_finish_gimple_return (location_t, tree); | |||
124 | static tree c_parser_gimple_paren_condition (gimple_parser &); | |||
125 | static void c_parser_gimple_expr_list (gimple_parser &, vec<tree> *); | |||
126 | ||||
127 | ||||
128 | /* See if VAL is an identifier matching __BB<num> and return <num> | |||
129 | in *INDEX. */ | |||
130 | ||||
131 | static bool | |||
132 | c_parser_gimple_parse_bb_spec (tree val, int *index) | |||
133 | { | |||
134 | if (!startswith (IDENTIFIER_POINTER (val)((const char *) (tree_check ((val), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 134, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__BB")) | |||
135 | return false; | |||
136 | for (const char *p = IDENTIFIER_POINTER (val)((const char *) (tree_check ((val), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 136, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ) + 4; *p; ++p) | |||
137 | if (!ISDIGIT (*p)(_sch_istable[(*p) & 0xff] & (unsigned short)(_sch_isdigit ))) | |||
138 | return false; | |||
139 | *index = atoi (IDENTIFIER_POINTER (val)((const char *) (tree_check ((val), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 139, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ) + 4); | |||
140 | return *index > 0; | |||
141 | } | |||
142 | ||||
143 | /* See if VAL is an identifier matching __BB<num> and return <num> | |||
144 | in *INDEX. Return true if so and parse also FREQUENCY of | |||
145 | the edge. */ | |||
146 | ||||
147 | ||||
148 | static bool | |||
149 | c_parser_gimple_parse_bb_spec_edge_probability (tree val, | |||
150 | gimple_parser &parser, | |||
151 | int *index, | |||
152 | profile_probability | |||
153 | *probability) | |||
154 | { | |||
155 | bool return_p = c_parser_gimple_parse_bb_spec (val, index); | |||
156 | if (return_p) | |||
157 | { | |||
158 | *probability = profile_probability::uninitialized (); | |||
159 | /* Parse frequency if provided. */ | |||
160 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |||
161 | { | |||
162 | tree f; | |||
163 | c_parser_consume_token (parser); | |||
164 | if (!c_parser_next_token_is (parser, CPP_NAME)) | |||
165 | { | |||
166 | c_parser_error (parser, "expected frequency quality"); | |||
167 | return false; | |||
168 | } | |||
169 | ||||
170 | profile_quality quality; | |||
171 | const char *v | |||
172 | = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value)((const char *) (tree_check ((c_parser_peek_token (parser)-> value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 172, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ); | |||
173 | if (!parse_profile_quality (v, &quality)) | |||
174 | { | |||
175 | c_parser_error (parser, "unknown profile quality"); | |||
176 | return false; | |||
177 | } | |||
178 | ||||
179 | c_parser_consume_token (parser); | |||
180 | if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
181 | return false; | |||
182 | ||||
183 | if (!c_parser_next_token_is (parser, CPP_NUMBER) | |||
184 | || (TREE_CODE (f = c_parser_peek_token (parser)->value)((enum tree_code) (f = c_parser_peek_token (parser)->value )->base.code) | |||
185 | != INTEGER_CST)) | |||
186 | { | |||
187 | c_parser_error (parser, "expected frequency value"); | |||
188 | return false; | |||
189 | } | |||
190 | ||||
191 | unsigned int value = TREE_INT_CST_LOW (f)((unsigned long) (*tree_int_cst_elt_check ((f), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 191, __FUNCTION__))); | |||
192 | *probability = profile_probability (value, quality); | |||
193 | ||||
194 | c_parser_consume_token (parser); | |||
195 | if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) | |||
196 | return false; | |||
197 | ||||
198 | if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) | |||
199 | return false; | |||
200 | } | |||
201 | ||||
202 | return true; | |||
203 | } | |||
204 | ||||
205 | return false; | |||
206 | ||||
207 | } | |||
208 | ||||
209 | /* Parse the body of a function declaration marked with "__GIMPLE". */ | |||
210 | ||||
211 | void | |||
212 | c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass, | |||
213 | enum c_declspec_il cdil, | |||
214 | profile_count entry_bb_count) | |||
215 | { | |||
216 | gimple_parser parser (cparser); | |||
217 | gimple_seq seq = NULLnullptr; | |||
218 | gimple_seq body = NULLnullptr; | |||
219 | tree stmt = push_stmt_list (); | |||
220 | push_scope (); | |||
221 | location_t loc1 = c_parser_peek_token (parser)->location; | |||
222 | ||||
223 | cfun(cfun + 0)->pass_startwith = gimple_pass; | |||
224 | init_tree_ssa (cfun(cfun + 0)); | |||
225 | ||||
226 | if (cdil == cdil_gimple) | |||
227 | /* While we have SSA names in the IL we do not have a CFG built yet | |||
228 | and PHIs are represented using a PHI internal function. We do | |||
229 | have lowered control flow and exception handling (well, we do not | |||
230 | have parser support for EH yet). But as we still have BINDs | |||
231 | we have to go through lowering again. */ | |||
232 | cfun(cfun + 0)->curr_properties = PROP_gimple_any(1 << 0); | |||
233 | else | |||
234 | { | |||
235 | /* We have at least cdil_gimple_cfg. */ | |||
236 | gimple_register_cfg_hooks (); | |||
237 | init_empty_tree_cfg (); | |||
238 | parser.current_bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_entry_block_ptr); | |||
239 | /* Initialize the bare loop structure - we are going to only | |||
240 | mark headers and leave the rest to fixup. */ | |||
241 | set_loops_for_fn (cfun(cfun + 0), ggc_cleared_alloc<struct loops> ()); | |||
242 | init_loops_structure (cfun(cfun + 0), loops_for_fn (cfun(cfun + 0)), 1); | |||
243 | loops_state_set (cfun(cfun + 0), LOOPS_NEED_FIXUP|LOOPS_MAY_HAVE_MULTIPLE_LATCHES); | |||
244 | cfun(cfun + 0)->curr_properties | |||
245 | |= PROP_gimple_lcf(1 << 1) | PROP_gimple_leh(1 << 2) | PROP_cfg(1 << 3) | PROP_loops(1 << 11); | |||
246 | if (cdil == cdil_gimple_ssa) | |||
247 | { | |||
248 | init_ssa_operands (cfun(cfun + 0)); | |||
249 | cfun(cfun + 0)->curr_properties |= PROP_ssa(1 << 5); | |||
250 | } | |||
251 | } | |||
252 | ||||
253 | if (! c_parser_gimple_compound_statement (parser, &seq) | |||
254 | && cdil == cdil_gimple) | |||
255 | { | |||
256 | gimple *ret = gimple_build_return (NULLnullptr); | |||
257 | gimple_seq_add_stmt_without_update (&seq, ret); | |||
258 | } | |||
259 | ||||
260 | tree block = pop_scope (); | |||
261 | stmt = pop_stmt_list (stmt); | |||
262 | stmt = c_build_bind_expr (loc1, block, stmt); | |||
263 | ||||
264 | block = DECL_INITIAL (current_function_decl)((contains_struct_check ((current_function_decl), (TS_DECL_COMMON ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 264, __FUNCTION__))->decl_common.initial); | |||
265 | BLOCK_SUBBLOCKS (block)((tree_check ((block), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 265, __FUNCTION__, (BLOCK)))->block.subblocks) = NULL_TREE(tree) nullptr; | |||
266 | BLOCK_CHAIN (block)((tree_check ((block), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 266, __FUNCTION__, (BLOCK)))->block.chain) = NULL_TREE(tree) nullptr; | |||
267 | TREE_ASM_WRITTEN (block)((block)->base.asm_written_flag) = 1; | |||
268 | ||||
269 | if (cdil == cdil_gimple) | |||
270 | { | |||
271 | gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt)((*((const_cast<tree*> (tree_operand_check (((tree_check ((stmt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 271, __FUNCTION__, (BIND_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 271, __FUNCTION__)))))), NULLnullptr, | |||
272 | BIND_EXPR_BLOCK (stmt)((*((const_cast<tree*> (tree_operand_check (((tree_check ((stmt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 272, __FUNCTION__, (BIND_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 272, __FUNCTION__))))))); | |||
273 | gimple_bind_set_body (bind_stmt, seq); | |||
274 | gimple_seq_add_stmt_without_update (&body, bind_stmt); | |||
275 | gimple_set_body (current_function_decl, body); | |||
276 | } | |||
277 | else | |||
278 | { | |||
279 | /* Control-flow and binds are lowered, record local decls. */ | |||
280 | for (tree var = BIND_EXPR_VARS (stmt)((*((const_cast<tree*> (tree_operand_check (((tree_check ((stmt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 280, __FUNCTION__, (BIND_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 280, __FUNCTION__)))))); var; var = DECL_CHAIN (var)(((contains_struct_check (((contains_struct_check ((var), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 280, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 280, __FUNCTION__))->common.chain))) | |||
281 | if (VAR_P (var)(((enum tree_code) (var)->base.code) == VAR_DECL) | |||
282 | && !DECL_EXTERNAL (var)((contains_struct_check ((var), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 282, __FUNCTION__))->decl_common.decl_flag_1)) | |||
283 | add_local_decl (cfun(cfun + 0), var); | |||
284 | /* We have a CFG. Build the edges. */ | |||
285 | for (unsigned i = 0; i < parser.edges.length (); ++i) | |||
286 | { | |||
287 | edge e = make_edge (BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].src)((*(((cfun + 0))->cfg->x_basic_block_info))[(parser.edges [i].src)]), | |||
288 | BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].dest)((*(((cfun + 0))->cfg->x_basic_block_info))[(parser.edges [i].dest)]), | |||
289 | parser.edges[i].flags); | |||
290 | e->probability = parser.edges[i].probability; | |||
291 | } | |||
292 | /* Add edges for case labels. */ | |||
293 | basic_block bb; | |||
294 | FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb ; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb-> next_bb) | |||
295 | if (EDGE_COUNT (bb->succs)vec_safe_length (bb->succs) == 0) | |||
296 | { | |||
297 | gimple *last = last_stmt (bb); | |||
298 | if (gswitch *sw = safe_dyn_cast <gswitch *> (last)) | |||
299 | for (unsigned i = 0; i < gimple_switch_num_labels (sw); ++i) | |||
300 | { | |||
301 | basic_block label_bb = gimple_switch_label_bb (cfun(cfun + 0), sw, i); | |||
302 | make_edge (bb, label_bb, 0); | |||
303 | } | |||
304 | } | |||
305 | /* Need those for loop fixup. */ | |||
306 | calculate_dominance_info (CDI_DOMINATORS); | |||
307 | /* With SSA lower PHIs parsed as internal function calls and | |||
308 | update stmts. */ | |||
309 | if (cdil == cdil_gimple_ssa) | |||
310 | { | |||
311 | /* Create PHI nodes, they are parsed into __PHI internal calls. */ | |||
312 | FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb ; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb-> next_bb) | |||
313 | for (gimple_stmt_iterator gsi = gsi_start_bb (bb); | |||
314 | !gsi_end_p (gsi);) | |||
315 | { | |||
316 | gimple *stmt = gsi_stmt (gsi); | |||
317 | if (!gimple_call_internal_p (stmt, IFN_PHI)) | |||
318 | break; | |||
319 | ||||
320 | gphi *phi = create_phi_node (gimple_call_lhs (stmt), bb); | |||
321 | for (unsigned i = 0; i < gimple_call_num_args (stmt); i += 2) | |||
322 | { | |||
323 | int srcidx = TREE_INT_CST_LOW (gimple_call_arg (stmt, i))((unsigned long) (*tree_int_cst_elt_check ((gimple_call_arg ( stmt, i)), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 323, __FUNCTION__))); | |||
324 | edge e = find_edge (BASIC_BLOCK_FOR_FN (cfun, srcidx)((*(((cfun + 0))->cfg->x_basic_block_info))[(srcidx)]), bb); | |||
325 | if (!e) | |||
326 | c_parser_error (parser, "edge not found"); | |||
327 | else | |||
328 | add_phi_arg (phi, gimple_call_arg (stmt, i + 1), e, | |||
329 | UNKNOWN_LOCATION((location_t) 0)); | |||
330 | } | |||
331 | gsi_remove (&gsi, true); | |||
332 | } | |||
333 | /* Fill SSA name gaps, putting them on the freelist and diagnose | |||
334 | SSA names without definition. */ | |||
335 | for (unsigned i = 1; i < num_ssa_names(vec_safe_length ((cfun + 0)->gimple_df->ssa_names)); ++i) | |||
336 | if (!ssa_name (i)((*(cfun + 0)->gimple_df->ssa_names)[(i)])) | |||
337 | { | |||
338 | tree name = make_ssa_name_fn (cfun(cfun + 0), integer_type_nodeinteger_types[itk_int], NULLnullptr, i); | |||
339 | release_ssa_name_fn (cfun(cfun + 0), name); | |||
340 | } | |||
341 | else if (!SSA_NAME_DEF_STMT (ssa_name (i))(tree_check ((((*(cfun + 0)->gimple_df->ssa_names)[(i)] )), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 341, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt) | |||
342 | error ("SSA name %qE with version %d has no definition", | |||
343 | ssa_name (i)((*(cfun + 0)->gimple_df->ssa_names)[(i)]), i); | |||
344 | /* No explicit virtual operands (yet). */ | |||
345 | bitmap_obstack_initialize (NULLnullptr); | |||
346 | update_ssa (TODO_update_ssa_only_virtuals(1 << 14)); | |||
347 | bitmap_obstack_release (NULLnullptr); | |||
348 | /* ??? By flushing the freelist after virtual operand SSA rewrite | |||
349 | we keep the gaps available for re-use like needed for the | |||
350 | PR89595 testcase but then usually virtual operands would have | |||
351 | taken most of them. The fix is obviously to make virtual | |||
352 | operands explicit in the SSA IL. */ | |||
353 | flush_ssaname_freelist (); | |||
354 | } | |||
355 | fix_loop_structure (NULLnullptr); | |||
356 | } | |||
357 | ||||
358 | if (cfun(cfun + 0)->curr_properties & PROP_cfg(1 << 3)) | |||
359 | { | |||
360 | ENTRY_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_entry_block_ptr)->count = entry_bb_count; | |||
361 | gcov_type t = param_gimple_fe_computed_hot_bb_thresholdglobal_options.x_param_gimple_fe_computed_hot_bb_threshold; | |||
362 | set_hot_bb_threshold (t); | |||
363 | update_max_bb_count (); | |||
364 | cgraph_node::get_create (cfun(cfun + 0)->decl); | |||
365 | cgraph_edge::rebuild_edges (); | |||
366 | } | |||
367 | ||||
368 | /* Perform IL validation and if any error is found abort compilation | |||
369 | of this function by zapping its body. */ | |||
370 | if ((cfun(cfun + 0)->curr_properties & PROP_cfg(1 << 3)) | |||
371 | && verify_gimple_in_cfg (cfun(cfun + 0), false, false)) | |||
372 | init_empty_tree_cfg (); | |||
373 | else if (!(cfun(cfun + 0)->curr_properties & PROP_cfg(1 << 3)) | |||
374 | && verify_gimple_in_seq (gimple_body (current_function_decl), false)) | |||
375 | gimple_set_body (current_function_decl, NULLnullptr); | |||
376 | ||||
377 | dump_function (TDI_gimple, current_function_decl); | |||
378 | } | |||
379 | ||||
380 | /* Parse a compound statement in gimple function body. | |||
381 | ||||
382 | gimple-statement: | |||
383 | gimple-statement | |||
384 | gimple-declaration-statement | |||
385 | gimple-if-statement | |||
386 | gimple-switch-statement | |||
387 | gimple-labeled-statement | |||
388 | gimple-expression-statement | |||
389 | gimple-goto-statement | |||
390 | gimple-phi-statement | |||
391 | gimple-return-statement | |||
392 | */ | |||
393 | ||||
394 | static bool | |||
395 | c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq) | |||
396 | { | |||
397 | bool return_p = false; | |||
398 | ||||
399 | if (! c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) | |||
| ||||
400 | return false; | |||
401 | ||||
402 | /* A compund statement starts with optional declarations. */ | |||
403 | while (c_parser_next_tokens_start_declaration (parser)) | |||
404 | { | |||
405 | c_parser_gimple_declaration (parser); | |||
406 | if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) | |||
407 | return false; | |||
408 | } | |||
409 | ||||
410 | while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) | |||
411 | { | |||
412 | if (c_parser_error (parser)) | |||
413 | { | |||
414 | c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULLnullptr); | |||
415 | return return_p; | |||
416 | } | |||
417 | else if (c_parser_next_token_is (parser, CPP_EOF)) | |||
418 | { | |||
419 | c_parser_error (parser, "expected declaration or statement"); | |||
420 | return return_p; | |||
421 | } | |||
422 | ||||
423 | switch (c_parser_peek_token (parser)->type) | |||
424 | { | |||
425 | case CPP_KEYWORD: | |||
426 | switch (c_parser_peek_token (parser)->keyword) | |||
427 | { | |||
428 | case RID_AT_TRY: | |||
429 | c_parser_gimple_try_stmt (parser, seq); | |||
430 | break; | |||
431 | case RID_IF: | |||
432 | c_parser_gimple_if_stmt (parser, seq); | |||
433 | break; | |||
434 | case RID_SWITCH: | |||
435 | c_parser_gimple_switch_stmt (parser, seq); | |||
436 | break; | |||
437 | case RID_GOTO: | |||
438 | { | |||
439 | location_t loc = c_parser_peek_token (parser)->location; | |||
440 | c_parser_consume_token (parser); | |||
441 | if (c_parser_next_token_is (parser, CPP_NAME)) | |||
442 | { | |||
443 | tree label = c_parser_peek_token (parser)->value; | |||
444 | c_parser_consume_token (parser); | |||
445 | c_parser_gimple_goto_stmt (parser, loc, label, seq); | |||
446 | if (! c_parser_require (parser, CPP_SEMICOLON, | |||
447 | "expected %<;%>")) | |||
448 | return return_p; | |||
449 | } | |||
450 | } | |||
451 | break; | |||
452 | case RID_RETURN: | |||
453 | return_p = true; | |||
454 | c_parser_gimple_return_stmt (parser, seq); | |||
455 | if (! c_parser_require (parser, CPP_SEMICOLON, | |||
456 | "expected %<;%>")) | |||
457 | return return_p; | |||
458 | if (cfun(cfun + 0)->curr_properties & PROP_cfg(1 << 3)) | |||
459 | parser.push_edge (parser.current_bb->index, EXIT_BLOCK(1), 0, | |||
460 | profile_probability::uninitialized ()); | |||
461 | break; | |||
462 | default: | |||
463 | goto expr_stmt; | |||
464 | } | |||
465 | break; | |||
466 | case CPP_NAME: | |||
467 | if (c_parser_peek_2nd_token (parser)->type == CPP_COLON) | |||
468 | { | |||
469 | c_parser_gimple_label (parser, seq); | |||
470 | break; | |||
471 | } | |||
472 | if (c_parser_next_token_is (parser, CPP_NAME) | |||
473 | && c_parser_peek_token (parser)->id_kind == C_ID_ID | |||
474 | && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value)((const char *) (tree_check ((c_parser_peek_token (parser)-> value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 474, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), | |||
475 | "try") == 0) | |||
476 | { | |||
477 | c_parser_gimple_try_stmt (parser, seq); | |||
478 | break; | |||
479 | } | |||
480 | /* Basic block specification. | |||
481 | __BB (index, ...) */ | |||
482 | if ((cfun(cfun + 0)->curr_properties & PROP_cfg(1 << 3)) | |||
483 | && !strcmp (IDENTIFIER_POINTER((const char *) (tree_check ((c_parser_peek_token (parser)-> value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 484, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ) | |||
484 | (c_parser_peek_token (parser)->value)((const char *) (tree_check ((c_parser_peek_token (parser)-> value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 484, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__BB")) | |||
485 | { | |||
486 | c_parser_consume_token (parser); | |||
487 | if (! c_parser_require (parser, CPP_OPEN_PAREN, | |||
488 | "expected %<(%>")) | |||
489 | return return_p; | |||
490 | if (c_parser_next_token_is_not (parser, CPP_NUMBER)) | |||
491 | { | |||
492 | c_parser_error (parser, "expected block index"); | |||
493 | return return_p; | |||
494 | } | |||
495 | tree tnum = c_parser_peek_token (parser)->value; | |||
496 | if (TREE_CODE (tnum)((enum tree_code) (tnum)->base.code) != INTEGER_CST) | |||
497 | { | |||
498 | c_parser_error (parser, "expected block index"); | |||
499 | return return_p; | |||
500 | } | |||
501 | int index = TREE_INT_CST_LOW (tnum)((unsigned long) (*tree_int_cst_elt_check ((tnum), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 501, __FUNCTION__))); | |||
502 | if (index < NUM_FIXED_BLOCKS(2) | |||
503 | || (index < last_basic_block_for_fn (cfun)(((cfun + 0))->cfg->x_last_basic_block) | |||
504 | && BASIC_BLOCK_FOR_FN (cfun, index)((*(((cfun + 0))->cfg->x_basic_block_info))[(index)]) != NULLnullptr)) | |||
505 | { | |||
506 | c_parser_error (parser, "invalid block index"); | |||
507 | return return_p; | |||
508 | } | |||
509 | int is_loop_header_of = -1; | |||
510 | profile_count bb_count = profile_count::uninitialized (); | |||
511 | c_parser_consume_token (parser); | |||
512 | while (c_parser_next_token_is (parser, CPP_COMMA)) | |||
513 | { | |||
514 | c_parser_consume_token (parser); | |||
515 | if (! c_parser_next_token_is (parser, CPP_NAME)) | |||
516 | { | |||
517 | c_parser_error (parser, "expected block specifier"); | |||
518 | return return_p; | |||
519 | } | |||
520 | /* loop_header (NUM) */ | |||
521 | if (!strcmp (IDENTIFIER_POINTER((const char *) (tree_check ((c_parser_peek_token (parser)-> value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 522, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ) | |||
522 | (c_parser_peek_token (parser)->value)((const char *) (tree_check ((c_parser_peek_token (parser)-> value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 522, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), | |||
523 | "loop_header")) | |||
524 | { | |||
525 | c_parser_consume_token (parser); | |||
526 | if (! c_parser_require (parser, CPP_OPEN_PAREN, | |||
527 | "expected %<(%>")) | |||
528 | return return_p; | |||
529 | tree loop_num; | |||
530 | if (! c_parser_next_token_is (parser, CPP_NUMBER) | |||
531 | || TREE_CODE (loop_num((enum tree_code) (loop_num = c_parser_peek_token (parser)-> value)->base.code) | |||
532 | = c_parser_peek_token (parser)->value)((enum tree_code) (loop_num = c_parser_peek_token (parser)-> value)->base.code) | |||
533 | != INTEGER_CST) | |||
534 | { | |||
535 | c_parser_error (parser, "expected loop number"); | |||
536 | return return_p; | |||
537 | } | |||
538 | c_parser_consume_token (parser); | |||
539 | is_loop_header_of = TREE_INT_CST_LOW (loop_num)((unsigned long) (*tree_int_cst_elt_check ((loop_num), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 539, __FUNCTION__))); | |||
540 | if (! c_parser_require (parser, CPP_CLOSE_PAREN, | |||
541 | "expected %<)%>")) | |||
542 | return return_p; | |||
543 | } | |||
544 | /* Parse profile: quality(value) */ | |||
545 | else | |||
546 | { | |||
547 | tree q; | |||
548 | profile_quality quality; | |||
549 | tree v = c_parser_peek_token (parser)->value; | |||
550 | if (!parse_profile_quality (IDENTIFIER_POINTER (v)((const char *) (tree_check ((v), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 550, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), | |||
551 | &quality)) | |||
552 | { | |||
553 | c_parser_error (parser, "unknown block specifier"); | |||
554 | return false; | |||
555 | } | |||
556 | ||||
557 | c_parser_consume_token (parser); | |||
558 | if (!c_parser_require (parser, CPP_OPEN_PAREN, | |||
559 | "expected %<(%>")) | |||
560 | return false; | |||
561 | ||||
562 | if (!c_parser_next_token_is (parser, CPP_NUMBER) | |||
563 | || (TREE_CODE (q = c_parser_peek_token (parser)->value)((enum tree_code) (q = c_parser_peek_token (parser)->value )->base.code) | |||
564 | != INTEGER_CST)) | |||
565 | { | |||
566 | c_parser_error (parser, "expected count value"); | |||
567 | return false; | |||
568 | } | |||
569 | ||||
570 | bb_count | |||
571 | = profile_count::from_gcov_type (TREE_INT_CST_LOW (q)((unsigned long) (*tree_int_cst_elt_check ((q), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 571, __FUNCTION__))), | |||
572 | quality); | |||
573 | c_parser_consume_token (parser); | |||
574 | if (! c_parser_require (parser, CPP_CLOSE_PAREN, | |||
575 | "expected %<)%>")) | |||
576 | return return_p; | |||
577 | } | |||
578 | } | |||
579 | if (! c_parser_require (parser, CPP_CLOSE_PAREN, | |||
580 | "expected %<)%>") | |||
581 | || ! c_parser_require (parser, CPP_COLON, | |||
582 | "expected %<:%>")) | |||
583 | return return_p; | |||
584 | ||||
585 | /* Put stmts parsed in the current block. */ | |||
586 | if (!gimple_seq_empty_p (*seq)) | |||
587 | { | |||
588 | if (!parser.current_bb) | |||
589 | c_parser_error (parser, "stmts without block"); | |||
590 | else | |||
591 | { | |||
592 | gimple_stmt_iterator gsi | |||
593 | = gsi_start_bb (parser.current_bb); | |||
594 | gsi_insert_seq_after (&gsi, *seq, GSI_CONTINUE_LINKING); | |||
595 | } | |||
596 | *seq = NULLnullptr; | |||
597 | } | |||
598 | ||||
599 | /* Build an empty block with specified index, linking them | |||
600 | in source order. */ | |||
601 | basic_block bb = alloc_block (); | |||
602 | bb->index = index; | |||
603 | link_block (bb, (parser.current_bb ? parser.current_bb | |||
604 | : ENTRY_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_entry_block_ptr))); | |||
605 | if (basic_block_info_for_fn (cfun)(((cfun + 0))->cfg->x_basic_block_info)->length () <= (size_t)index) | |||
606 | vec_safe_grow_cleared (basic_block_info_for_fn (cfun)(((cfun + 0))->cfg->x_basic_block_info), | |||
607 | index + 1, true); | |||
608 | SET_BASIC_BLOCK_FOR_FN (cfun, index, bb)((*(((cfun + 0))->cfg->x_basic_block_info))[(index)] = ( bb)); | |||
609 | if (last_basic_block_for_fn (cfun)(((cfun + 0))->cfg->x_last_basic_block) <= index) | |||
610 | last_basic_block_for_fn (cfun)(((cfun + 0))->cfg->x_last_basic_block) = index + 1; | |||
611 | n_basic_blocks_for_fn (cfun)(((cfun + 0))->cfg->x_n_basic_blocks)++; | |||
612 | if (parser.current_bb->index == ENTRY_BLOCK(0)) | |||
613 | parser.push_edge (ENTRY_BLOCK(0), bb->index, EDGE_FALLTHRU, | |||
614 | profile_probability::always ()); | |||
615 | ||||
616 | /* We leave the proper setting to fixup. */ | |||
617 | class loop *loop_father = loops_for_fn (cfun(cfun + 0))->tree_root; | |||
618 | /* If the new block is a loop header, allocate a loop | |||
619 | struct. Fixup will take care of proper placement within | |||
620 | the loop tree. */ | |||
621 | if (is_loop_header_of != -1) | |||
622 | { | |||
623 | if (number_of_loops (cfun(cfun + 0)) > (unsigned)is_loop_header_of | |||
624 | && get_loop (cfun(cfun + 0), is_loop_header_of) != NULLnullptr) | |||
625 | { | |||
626 | c_parser_error (parser, "duplicate loop header"); | |||
627 | } | |||
628 | else | |||
629 | { | |||
630 | class loop *loop = alloc_loop (); | |||
631 | loop->num = is_loop_header_of; | |||
632 | loop->header = bb; | |||
633 | if (number_of_loops (cfun(cfun + 0)) <= (unsigned)is_loop_header_of) | |||
634 | vec_safe_grow_cleared (loops_for_fn (cfun(cfun + 0))->larray, | |||
635 | is_loop_header_of + 1, true); | |||
636 | (*loops_for_fn (cfun(cfun + 0))->larray)[is_loop_header_of] = loop; | |||
637 | flow_loop_tree_node_add (loops_for_fn (cfun(cfun + 0))->tree_root, | |||
638 | loop); | |||
639 | } | |||
640 | loop_father = get_loop (cfun(cfun + 0), is_loop_header_of); | |||
641 | } | |||
642 | bb->loop_father = loop_father; | |||
643 | bb->count = bb_count; | |||
644 | ||||
645 | /* Stmts now go to the new block. */ | |||
646 | parser.current_bb = bb; | |||
647 | break; | |||
648 | } | |||
649 | goto expr_stmt; | |||
650 | ||||
651 | case CPP_SEMICOLON: | |||
652 | { | |||
653 | /* Empty stmt. */ | |||
654 | location_t loc = c_parser_peek_token (parser)->location; | |||
655 | c_parser_consume_token (parser); | |||
656 | gimple *nop = gimple_build_nop (); | |||
657 | gimple_set_location (nop, loc); | |||
658 | gimple_seq_add_stmt_without_update (seq, nop); | |||
659 | break; | |||
660 | } | |||
661 | ||||
662 | default: | |||
663 | expr_stmt: | |||
664 | c_parser_gimple_statement (parser, seq); | |||
665 | if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) | |||
666 | c_parser_skip_until_found (parser, CPP_SEMICOLON, NULLnullptr); | |||
667 | } | |||
668 | } | |||
669 | c_parser_consume_token (parser); | |||
670 | ||||
671 | /* Put stmts parsed in the current block. */ | |||
672 | if ((cfun(cfun + 0)->curr_properties & PROP_cfg(1 << 3)) | |||
673 | && !gimple_seq_empty_p (*seq)) | |||
674 | { | |||
675 | if (!parser.current_bb) | |||
676 | c_parser_error (parser, "stmts without block"); | |||
677 | else | |||
678 | { | |||
679 | gimple_stmt_iterator gsi = gsi_start_bb (parser.current_bb); | |||
680 | gsi_insert_seq_after (&gsi, *seq, GSI_CONTINUE_LINKING); | |||
681 | } | |||
682 | *seq = NULLnullptr; | |||
683 | } | |||
684 | ||||
685 | return return_p; | |||
686 | } | |||
687 | ||||
688 | /* Parse a gimple statement. | |||
689 | ||||
690 | gimple-statement: | |||
691 | gimple-call-expression | |||
692 | gimple-assign-statement | |||
693 | gimple-phi-statement | |||
694 | ||||
695 | gimple-assign-statement: | |||
696 | gimple-unary-expression = gimple-assign-rhs | |||
697 | ||||
698 | gimple-assign-rhs: | |||
699 | gimple-cast-expression | |||
700 | gimple-unary-expression | |||
701 | gimple-binary-expression | |||
702 | gimple-call-expression | |||
703 | ||||
704 | gimple-phi-statement: | |||
705 | identifier = __PHI ( label : gimple_primary-expression, ... ) | |||
706 | ||||
707 | gimple-call-expr: | |||
708 | gimple-primary-expression ( argument-list ) | |||
709 | ||||
710 | gimple-cast-expression: | |||
711 | ( type-name ) gimple-primary-expression | |||
712 | ||||
713 | */ | |||
714 | ||||
715 | static void | |||
716 | c_parser_gimple_statement (gimple_parser &parser, gimple_seq *seq) | |||
717 | { | |||
718 | struct c_expr lhs, rhs; | |||
719 | gimple *assign = NULLnullptr; | |||
720 | location_t loc; | |||
721 | tree arg = NULL_TREE(tree) nullptr; | |||
722 | auto_vec<tree> vargs; | |||
723 | ||||
724 | lhs = c_parser_gimple_unary_expression (parser); | |||
725 | loc = EXPR_LOCATION (lhs.value)((((lhs.value)) && ((tree_code_type_tmpl <0>::tree_code_type [(int) (((enum tree_code) ((lhs.value))->base.code))]) >= tcc_reference && (tree_code_type_tmpl <0>::tree_code_type [(int) (((enum tree_code) ((lhs.value))->base.code))]) <= tcc_expression)) ? (lhs.value)->exp.locus : ((location_t) 0)); | |||
726 | rhs.set_error (); | |||
727 | ||||
728 | /* GIMPLE call statement without LHS. */ | |||
729 | if (c_parser_next_token_is (parser, CPP_SEMICOLON) | |||
730 | && TREE_CODE (lhs.value)((enum tree_code) (lhs.value)->base.code) == CALL_EXPR) | |||
731 | { | |||
732 | gimple *call; | |||
733 | call = gimple_build_call_from_tree (lhs.value, NULLnullptr); | |||
734 | gimple_seq_add_stmt_without_update (seq, call); | |||
735 | gimple_set_location (call, loc); | |||
736 | return; | |||
737 | } | |||
738 | ||||
739 | /* All following cases are statements with LHS. */ | |||
740 | if (! c_parser_require (parser, CPP_EQ, "expected %<=%>")) | |||
741 | return; | |||
742 | ||||
743 | /* Cast expression. */ | |||
744 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) | |||
745 | && c_token_starts_typename (c_parser_peek_2nd_token (parser))) | |||
746 | { | |||
747 | c_parser_consume_token (parser); | |||
748 | struct c_type_name *type_name = c_parser_type_name (parser); | |||
749 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); | |||
750 | if (type_name == NULLnullptr) | |||
751 | return; | |||
752 | /* ??? The actual type used in the cast expression is ignored as | |||
753 | in GIMPLE it is encoded by the type of the LHS. */ | |||
754 | rhs = c_parser_gimple_postfix_expression (parser); | |||
755 | if (lhs.value != error_mark_nodeglobal_trees[TI_ERROR_MARK] | |||
756 | && rhs.value != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
757 | { | |||
758 | enum tree_code code = NOP_EXPR; | |||
759 | if (FLOAT_TYPE_P (TREE_TYPE (lhs.value))((((enum tree_code) (((contains_struct_check ((lhs.value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 759, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE ) || ((((enum tree_code) (((contains_struct_check ((lhs.value ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 759, __FUNCTION__))->typed.type))->base.code) == COMPLEX_TYPE || (((enum tree_code) (((contains_struct_check ((lhs.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 759, __FUNCTION__))->typed.type))->base.code) == VECTOR_TYPE )) && (((enum tree_code) (((contains_struct_check ((( (contains_struct_check ((lhs.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 759, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 759, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE ))) | |||
760 | && ! FLOAT_TYPE_P (TREE_TYPE (rhs.value))((((enum tree_code) (((contains_struct_check ((rhs.value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 760, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE ) || ((((enum tree_code) (((contains_struct_check ((rhs.value ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 760, __FUNCTION__))->typed.type))->base.code) == COMPLEX_TYPE || (((enum tree_code) (((contains_struct_check ((rhs.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 760, __FUNCTION__))->typed.type))->base.code) == VECTOR_TYPE )) && (((enum tree_code) (((contains_struct_check ((( (contains_struct_check ((rhs.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 760, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 760, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE )))) | |||
761 | code = FLOAT_EXPR; | |||
762 | else if (! FLOAT_TYPE_P (TREE_TYPE (lhs.value))((((enum tree_code) (((contains_struct_check ((lhs.value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 762, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE ) || ((((enum tree_code) (((contains_struct_check ((lhs.value ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 762, __FUNCTION__))->typed.type))->base.code) == COMPLEX_TYPE || (((enum tree_code) (((contains_struct_check ((lhs.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 762, __FUNCTION__))->typed.type))->base.code) == VECTOR_TYPE )) && (((enum tree_code) (((contains_struct_check ((( (contains_struct_check ((lhs.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 762, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 762, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE ))) | |||
763 | && FLOAT_TYPE_P (TREE_TYPE (rhs.value))((((enum tree_code) (((contains_struct_check ((rhs.value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 763, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE ) || ((((enum tree_code) (((contains_struct_check ((rhs.value ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 763, __FUNCTION__))->typed.type))->base.code) == COMPLEX_TYPE || (((enum tree_code) (((contains_struct_check ((rhs.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 763, __FUNCTION__))->typed.type))->base.code) == VECTOR_TYPE )) && (((enum tree_code) (((contains_struct_check ((( (contains_struct_check ((rhs.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 763, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 763, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE )))) | |||
764 | code = FIX_TRUNC_EXPR; | |||
765 | assign = gimple_build_assign (lhs.value, code, rhs.value); | |||
766 | gimple_seq_add_stmt_without_update (seq, assign); | |||
767 | gimple_set_location (assign, loc); | |||
768 | return; | |||
769 | } | |||
770 | } | |||
771 | ||||
772 | /* Unary expression. */ | |||
773 | switch (c_parser_peek_token (parser)->type) | |||
774 | { | |||
775 | case CPP_NAME: | |||
776 | { | |||
777 | tree id = c_parser_peek_token (parser)->value; | |||
778 | if (strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 778, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__ABS") == 0 | |||
779 | || strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 779, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__ABSU") == 0 | |||
780 | || strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 780, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__MIN") == 0 | |||
781 | || strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 781, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__MAX") == 0 | |||
782 | || strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 782, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__BIT_INSERT") == 0 | |||
783 | || strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 783, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__VEC_PERM") == 0) | |||
784 | goto build_unary_expr; | |||
785 | break; | |||
786 | } | |||
787 | case CPP_KEYWORD: | |||
788 | if (c_parser_peek_token (parser)->keyword != RID_REALPART | |||
789 | && c_parser_peek_token (parser)->keyword != RID_IMAGPART) | |||
790 | break; | |||
791 | /* Fallthru. */ | |||
792 | case CPP_AND: | |||
793 | case CPP_PLUS: | |||
794 | case CPP_MINUS: | |||
795 | case CPP_COMPL: | |||
796 | case CPP_NOT: | |||
797 | case CPP_MULT: /* pointer deref */ | |||
798 | build_unary_expr: | |||
799 | rhs = c_parser_gimple_unary_expression (parser); | |||
800 | if (rhs.value != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
801 | { | |||
802 | assign = gimple_build_assign (lhs.value, rhs.value); | |||
803 | gimple_set_location (assign, loc); | |||
804 | gimple_seq_add_stmt_without_update (seq, assign); | |||
805 | } | |||
806 | return; | |||
807 | ||||
808 | default:; | |||
809 | } | |||
810 | ||||
811 | /* GIMPLE PHI statement. */ | |||
812 | if (c_parser_next_token_is_keyword (parser, RID_PHI)) | |||
813 | { | |||
814 | c_parser_consume_token (parser); | |||
815 | ||||
816 | if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
817 | return; | |||
818 | ||||
819 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |||
820 | c_parser_consume_token (parser); | |||
821 | ||||
822 | while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) | |||
823 | { | |||
824 | if (c_parser_next_token_is (parser, CPP_NAME) | |||
825 | && c_parser_peek_2nd_token (parser)->type == CPP_COLON) | |||
826 | { | |||
827 | arg = c_parser_peek_token (parser)->value; | |||
828 | c_parser_consume_token (parser); | |||
829 | if (c_parser_next_token_is (parser, CPP_COLON)) | |||
830 | c_parser_consume_token (parser); | |||
831 | int src_index = -1; | |||
832 | if (!c_parser_gimple_parse_bb_spec (arg, &src_index)) | |||
833 | c_parser_error (parser, "invalid source block specification"); | |||
834 | vargs.safe_push (size_int (src_index)size_int_kind (src_index, stk_sizetype)); | |||
835 | } | |||
836 | else if (c_parser_next_token_is (parser, CPP_COMMA)) | |||
837 | c_parser_consume_token (parser); | |||
838 | else | |||
839 | { | |||
840 | arg = c_parser_gimple_unary_expression (parser).value; | |||
841 | vargs.safe_push (arg); | |||
842 | } | |||
843 | } | |||
844 | ||||
845 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |||
846 | "expected %<)%>"); | |||
847 | ||||
848 | /* Build internal function for PHI. */ | |||
849 | gcall *call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs); | |||
850 | gimple_call_set_lhs (call_stmt, lhs.value); | |||
851 | gimple_set_location (call_stmt, UNKNOWN_LOCATION((location_t) 0)); | |||
852 | gimple_seq_add_stmt_without_update (seq, call_stmt); | |||
853 | return; | |||
854 | } | |||
855 | ||||
856 | /* GIMPLE call with lhs. */ | |||
857 | if (c_parser_next_token_is (parser, CPP_DOT) | |||
858 | || (c_parser_next_token_is (parser, CPP_NAME) | |||
859 | && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN | |||
860 | && lookup_name (c_parser_peek_token (parser)->value))) | |||
861 | { | |||
862 | rhs = c_parser_gimple_unary_expression (parser); | |||
863 | if (rhs.value != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
864 | { | |||
865 | gimple *call = gimple_build_call_from_tree (rhs.value, NULLnullptr); | |||
866 | gimple_call_set_lhs (call, lhs.value); | |||
867 | gimple_seq_add_stmt_without_update (seq, call); | |||
868 | gimple_set_location (call, loc); | |||
869 | } | |||
870 | return; | |||
871 | } | |||
872 | ||||
873 | rhs = c_parser_gimple_binary_expression (parser); | |||
874 | if (lhs.value != error_mark_nodeglobal_trees[TI_ERROR_MARK] | |||
875 | && rhs.value != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
876 | { | |||
877 | /* If we parsed a comparison or an identifier and the next token | |||
878 | is a '?' then parse a conditional expression. */ | |||
879 | if ((COMPARISON_CLASS_P (rhs.value)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (rhs.value)->base.code))] == tcc_comparison) | |||
880 | || SSA_VAR_P (rhs.value)(((enum tree_code) (rhs.value)->base.code) == VAR_DECL || ( (enum tree_code) (rhs.value)->base.code) == PARM_DECL || ( (enum tree_code) (rhs.value)->base.code) == RESULT_DECL || ((enum tree_code) (rhs.value)->base.code) == SSA_NAME)) | |||
881 | && c_parser_next_token_is (parser, CPP_QUERY)) | |||
882 | { | |||
883 | struct c_expr trueval, falseval; | |||
884 | c_parser_consume_token (parser); | |||
885 | trueval = c_parser_gimple_postfix_expression (parser); | |||
886 | falseval.set_error (); | |||
887 | if (c_parser_require (parser, CPP_COLON, "expected %<:%>")) | |||
888 | falseval = c_parser_gimple_postfix_expression (parser); | |||
889 | if (trueval.value == error_mark_nodeglobal_trees[TI_ERROR_MARK] | |||
890 | || falseval.value == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
891 | return; | |||
892 | rhs.value = build3_loc (loc, | |||
893 | VECTOR_TYPE_P (TREE_TYPE (rhs.value))(((enum tree_code) (((contains_struct_check ((rhs.value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 893, __FUNCTION__))->typed.type))->base.code) == VECTOR_TYPE ) | |||
894 | ? VEC_COND_EXPR : COND_EXPR, | |||
895 | TREE_TYPE (trueval.value)((contains_struct_check ((trueval.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 895, __FUNCTION__))->typed.type), | |||
896 | rhs.value, trueval.value, falseval.value); | |||
897 | } | |||
898 | if (get_gimple_rhs_class (TREE_CODE (rhs.value)((enum tree_code) (rhs.value)->base.code)) == GIMPLE_INVALID_RHS) | |||
899 | { | |||
900 | c_parser_error (parser, "unexpected RHS for assignment"); | |||
901 | return; | |||
902 | } | |||
903 | assign = gimple_build_assign (lhs.value, rhs.value); | |||
904 | gimple_seq_add_stmt_without_update (seq, assign); | |||
905 | gimple_set_location (assign, loc); | |||
906 | } | |||
907 | return; | |||
908 | } | |||
909 | ||||
910 | /* Parse gimple binary expr. | |||
911 | ||||
912 | gimple-binary-expression: | |||
913 | gimple-unary-expression * gimple-unary-expression | |||
914 | gimple-unary-expression __MULT_HIGHPART gimple-unary-expression | |||
915 | gimple-unary-expression / gimple-unary-expression | |||
916 | gimple-unary-expression % gimple-unary-expression | |||
917 | gimple-unary-expression + gimple-unary-expression | |||
918 | gimple-unary-expression - gimple-unary-expression | |||
919 | gimple-unary-expression << gimple-unary-expression | |||
920 | gimple-unary-expression >> gimple-unary-expression | |||
921 | gimple-unary-expression < gimple-unary-expression | |||
922 | gimple-unary-expression > gimple-unary-expression | |||
923 | gimple-unary-expression <= gimple-unary-expression | |||
924 | gimple-unary-expression >= gimple-unary-expression | |||
925 | gimple-unary-expression == gimple-unary-expression | |||
926 | gimple-unary-expression != gimple-unary-expression | |||
927 | gimple-unary-expression & gimple-unary-expression | |||
928 | gimple-unary-expression ^ gimple-unary-expression | |||
929 | gimple-unary-expression | gimple-unary-expression | |||
930 | ||||
931 | */ | |||
932 | ||||
933 | static c_expr | |||
934 | c_parser_gimple_binary_expression (gimple_parser &parser) | |||
935 | { | |||
936 | /* Location of the binary operator. */ | |||
937 | struct c_expr ret, lhs, rhs; | |||
938 | enum tree_code code = ERROR_MARK; | |||
939 | ret.set_error (); | |||
940 | lhs = c_parser_gimple_postfix_expression (parser); | |||
941 | if (c_parser_error (parser)) | |||
942 | return ret; | |||
943 | tree ret_type = TREE_TYPE (lhs.value)((contains_struct_check ((lhs.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 943, __FUNCTION__))->typed.type); | |||
944 | switch (c_parser_peek_token (parser)->type) | |||
945 | { | |||
946 | case CPP_MULT: | |||
947 | code = MULT_EXPR; | |||
948 | break; | |||
949 | case CPP_DIV: | |||
950 | code = TRUNC_DIV_EXPR; | |||
951 | break; | |||
952 | case CPP_MOD: | |||
953 | code = TRUNC_MOD_EXPR; | |||
954 | break; | |||
955 | case CPP_PLUS: | |||
956 | if (POINTER_TYPE_P (TREE_TYPE (lhs.value))(((enum tree_code) (((contains_struct_check ((lhs.value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 956, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((lhs.value), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 956, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE )) | |||
957 | code = POINTER_PLUS_EXPR; | |||
958 | else | |||
959 | code = PLUS_EXPR; | |||
960 | break; | |||
961 | case CPP_MINUS: | |||
962 | code = MINUS_EXPR; | |||
963 | break; | |||
964 | case CPP_LSHIFT: | |||
965 | code = LSHIFT_EXPR; | |||
966 | break; | |||
967 | case CPP_RSHIFT: | |||
968 | code = RSHIFT_EXPR; | |||
969 | break; | |||
970 | case CPP_LESS: | |||
971 | code = LT_EXPR; | |||
972 | ret_type = boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE]; | |||
973 | break; | |||
974 | case CPP_GREATER: | |||
975 | code = GT_EXPR; | |||
976 | ret_type = boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE]; | |||
977 | break; | |||
978 | case CPP_LESS_EQ: | |||
979 | code = LE_EXPR; | |||
980 | ret_type = boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE]; | |||
981 | break; | |||
982 | case CPP_GREATER_EQ: | |||
983 | code = GE_EXPR; | |||
984 | ret_type = boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE]; | |||
985 | break; | |||
986 | case CPP_EQ_EQ: | |||
987 | code = EQ_EXPR; | |||
988 | ret_type = boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE]; | |||
989 | break; | |||
990 | case CPP_NOT_EQ: | |||
991 | code = NE_EXPR; | |||
992 | ret_type = boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE]; | |||
993 | break; | |||
994 | case CPP_AND: | |||
995 | code = BIT_AND_EXPR; | |||
996 | break; | |||
997 | case CPP_XOR: | |||
998 | code = BIT_XOR_EXPR; | |||
999 | break; | |||
1000 | case CPP_OR: | |||
1001 | code = BIT_IOR_EXPR; | |||
1002 | break; | |||
1003 | case CPP_AND_AND: | |||
1004 | c_parser_error (parser, "%<&&%> not valid in GIMPLE"); | |||
1005 | return ret; | |||
1006 | case CPP_OR_OR: | |||
1007 | c_parser_error (parser, "%<||%> not valid in GIMPLE"); | |||
1008 | return ret; | |||
1009 | case CPP_NAME: | |||
1010 | { | |||
1011 | tree id = c_parser_peek_token (parser)->value; | |||
1012 | if (strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1012, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__MULT_HIGHPART") == 0) | |||
1013 | { | |||
1014 | code = MULT_HIGHPART_EXPR; | |||
1015 | break; | |||
1016 | } | |||
1017 | } | |||
1018 | /* Fallthru. */ | |||
1019 | default: | |||
1020 | /* Not a binary expression. */ | |||
1021 | return lhs; | |||
1022 | } | |||
1023 | location_t ret_loc = c_parser_peek_token (parser)->location; | |||
1024 | c_parser_consume_token (parser); | |||
1025 | rhs = c_parser_gimple_postfix_expression (parser); | |||
1026 | if (lhs.value != error_mark_nodeglobal_trees[TI_ERROR_MARK] && rhs.value != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1027 | ret.value = build2_loc (ret_loc, code, ret_type, lhs.value, rhs.value); | |||
1028 | return ret; | |||
1029 | } | |||
1030 | ||||
1031 | /* Parse a gimple parentized binary expression. */ | |||
1032 | ||||
1033 | static c_expr | |||
1034 | c_parser_gimple_parentized_binary_expression (gimple_parser &parser, | |||
1035 | location_t op_loc, | |||
1036 | tree_code code) | |||
1037 | { | |||
1038 | struct c_expr ret; | |||
1039 | ret.set_error (); | |||
1040 | ||||
1041 | c_parser_consume_token (parser); | |||
1042 | if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
1043 | return ret; | |||
1044 | c_expr op1 = c_parser_gimple_postfix_expression (parser); | |||
1045 | if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) | |||
1046 | return ret; | |||
1047 | c_expr op2 = c_parser_gimple_postfix_expression (parser); | |||
1048 | if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) | |||
1049 | return ret; | |||
1050 | ||||
1051 | if (op1.value != error_mark_nodeglobal_trees[TI_ERROR_MARK] && op2.value != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1052 | ret.value = build2_loc (op_loc, | |||
1053 | code, TREE_TYPE (op1.value)((contains_struct_check ((op1.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1053, __FUNCTION__))->typed.type), op1.value, op2.value); | |||
1054 | return ret; | |||
1055 | } | |||
1056 | ||||
1057 | /* Parse a gimple parentized binary expression. */ | |||
1058 | ||||
1059 | static c_expr | |||
1060 | c_parser_gimple_parentized_ternary_expression (gimple_parser &parser, | |||
1061 | location_t op_loc, | |||
1062 | tree_code code) | |||
1063 | { | |||
1064 | struct c_expr ret; | |||
1065 | ret.set_error (); | |||
1066 | ||||
1067 | c_parser_consume_token (parser); | |||
1068 | if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
1069 | return ret; | |||
1070 | c_expr op1 = c_parser_gimple_postfix_expression (parser); | |||
1071 | if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) | |||
1072 | return ret; | |||
1073 | c_expr op2 = c_parser_gimple_postfix_expression (parser); | |||
1074 | if (!c_parser_require (parser, CPP_COMMA, "expected %<)%>")) | |||
1075 | return ret; | |||
1076 | c_expr op3 = c_parser_gimple_postfix_expression (parser); | |||
1077 | if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) | |||
1078 | return ret; | |||
1079 | ||||
1080 | if (op1.value != error_mark_nodeglobal_trees[TI_ERROR_MARK] | |||
1081 | && op2.value != error_mark_nodeglobal_trees[TI_ERROR_MARK] | |||
1082 | && op3.value != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1083 | ret.value = build3_loc (op_loc, | |||
1084 | code, TREE_TYPE (op1.value)((contains_struct_check ((op1.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1084, __FUNCTION__))->typed.type), | |||
1085 | op1.value, op2.value, op3.value); | |||
1086 | return ret; | |||
1087 | } | |||
1088 | ||||
1089 | /* Parse gimple unary expression. | |||
1090 | ||||
1091 | gimple-unary-expression: | |||
1092 | gimple-postfix-expression | |||
1093 | unary-operator gimple-postfix-expression | |||
1094 | ||||
1095 | unary-operator: one of | |||
1096 | & * + - ~ abs_expr | |||
1097 | */ | |||
1098 | ||||
1099 | static c_expr | |||
1100 | c_parser_gimple_unary_expression (gimple_parser &parser) | |||
1101 | { | |||
1102 | struct c_expr ret, op; | |||
1103 | location_t op_loc = c_parser_peek_token (parser)->location; | |||
1104 | location_t finish; | |||
1105 | ret.set_error (); | |||
1106 | switch (c_parser_peek_token (parser)->type) | |||
1107 | { | |||
1108 | case CPP_AND: | |||
1109 | c_parser_consume_token (parser); | |||
1110 | op = c_parser_gimple_postfix_expression (parser); | |||
1111 | mark_exp_read (op.value); | |||
1112 | return parser_build_unary_op (op_loc, ADDR_EXPR, op); | |||
1113 | case CPP_MULT: | |||
1114 | { | |||
1115 | c_parser_consume_token (parser); | |||
1116 | op = c_parser_gimple_postfix_expression (parser); | |||
1117 | if (op.value == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1118 | return ret; | |||
1119 | if (! POINTER_TYPE_P (TREE_TYPE (op.value))(((enum tree_code) (((contains_struct_check ((op.value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1119, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((op.value), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1119, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE )) | |||
1120 | { | |||
1121 | error_at (op_loc, "expected pointer as argument of unary %<*%>"); | |||
1122 | return ret; | |||
1123 | } | |||
1124 | finish = op.get_finish (); | |||
1125 | location_t combined_loc = make_location (op_loc, op_loc, finish); | |||
1126 | ret.value = build_simple_mem_ref_loc (combined_loc, op.value); | |||
1127 | TREE_SIDE_EFFECTS (ret.value)((non_type_check ((ret.value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1127, __FUNCTION__))->base.side_effects_flag) | |||
1128 | = TREE_THIS_VOLATILE (ret.value)((ret.value)->base.volatile_flag) | |||
1129 | = TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (op.value)))((tree_class_check ((((contains_struct_check ((((contains_struct_check ((op.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1129, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1129, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1129, __FUNCTION__))->base.volatile_flag); | |||
1130 | ret.src_range.m_start = op_loc; | |||
1131 | ret.src_range.m_finish = finish; | |||
1132 | return ret; | |||
1133 | } | |||
1134 | case CPP_PLUS: | |||
1135 | c_parser_consume_token (parser); | |||
1136 | op = c_parser_gimple_postfix_expression (parser); | |||
1137 | return parser_build_unary_op (op_loc, CONVERT_EXPR, op); | |||
1138 | case CPP_MINUS: | |||
1139 | c_parser_consume_token (parser); | |||
1140 | op = c_parser_gimple_postfix_expression (parser); | |||
1141 | return parser_build_unary_op (op_loc, NEGATE_EXPR, op); | |||
1142 | case CPP_COMPL: | |||
1143 | c_parser_consume_token (parser); | |||
1144 | op = c_parser_gimple_postfix_expression (parser); | |||
1145 | return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op); | |||
1146 | case CPP_NOT: | |||
1147 | c_parser_error (parser, "%<!%> not valid in GIMPLE"); | |||
1148 | return ret; | |||
1149 | case CPP_KEYWORD: | |||
1150 | switch (c_parser_peek_token (parser)->keyword) | |||
1151 | { | |||
1152 | case RID_REALPART: | |||
1153 | c_parser_consume_token (parser); | |||
1154 | op = c_parser_gimple_postfix_expression (parser); | |||
1155 | return parser_build_unary_op (op_loc, REALPART_EXPR, op); | |||
1156 | case RID_IMAGPART: | |||
1157 | c_parser_consume_token (parser); | |||
1158 | op = c_parser_gimple_postfix_expression (parser); | |||
1159 | return parser_build_unary_op (op_loc, IMAGPART_EXPR, op); | |||
1160 | default: | |||
1161 | return c_parser_gimple_postfix_expression (parser); | |||
1162 | } | |||
1163 | case CPP_NAME: | |||
1164 | { | |||
1165 | tree id = c_parser_peek_token (parser)->value; | |||
1166 | if (strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1166, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__ABS") == 0) | |||
1167 | { | |||
1168 | c_parser_consume_token (parser); | |||
1169 | op = c_parser_gimple_postfix_expression (parser); | |||
1170 | return parser_build_unary_op (op_loc, ABS_EXPR, op); | |||
1171 | } | |||
1172 | else if (strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1172, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__ABSU") == 0) | |||
1173 | { | |||
1174 | c_parser_consume_token (parser); | |||
1175 | op = c_parser_gimple_postfix_expression (parser); | |||
1176 | return parser_build_unary_op (op_loc, ABSU_EXPR, op); | |||
1177 | } | |||
1178 | else if (strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1178, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__MIN") == 0) | |||
1179 | return c_parser_gimple_parentized_binary_expression (parser, | |||
1180 | op_loc, | |||
1181 | MIN_EXPR); | |||
1182 | else if (strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1182, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__MAX") == 0) | |||
1183 | return c_parser_gimple_parentized_binary_expression (parser, | |||
1184 | op_loc, | |||
1185 | MAX_EXPR); | |||
1186 | else if (strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1186, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__VEC_PERM") == 0) | |||
1187 | return c_parser_gimple_parentized_ternary_expression | |||
1188 | (parser, op_loc, VEC_PERM_EXPR); | |||
1189 | else if (strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1189, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__BIT_INSERT") == 0) | |||
1190 | { | |||
1191 | /* __BIT_INSERT '(' postfix-expression, postfix-expression, | |||
1192 | integer ')' */ | |||
1193 | location_t loc = c_parser_peek_token (parser)->location; | |||
1194 | c_parser_consume_token (parser); | |||
1195 | if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
1196 | { | |||
1197 | c_expr op0 = c_parser_gimple_postfix_expression (parser); | |||
1198 | c_parser_skip_until_found (parser, CPP_COMMA, | |||
1199 | "expected %<,%>"); | |||
1200 | c_expr op1 = c_parser_gimple_postfix_expression (parser); | |||
1201 | c_parser_skip_until_found (parser, CPP_COMMA, | |||
1202 | "expected %<,%>"); | |||
1203 | c_expr op2 = c_parser_gimple_postfix_expression (parser); | |||
1204 | if (TREE_CODE (op2.value)((enum tree_code) (op2.value)->base.code) != INTEGER_CST | |||
1205 | || !int_fits_type_p (op2.value, bitsizetypesizetype_tab[(int) stk_bitsizetype])) | |||
1206 | c_parser_error (parser, "expected constant offset"); | |||
1207 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |||
1208 | "expected %<)%>"); | |||
1209 | if (op0.value != error_mark_nodeglobal_trees[TI_ERROR_MARK] | |||
1210 | && op1.value != error_mark_nodeglobal_trees[TI_ERROR_MARK] | |||
1211 | && TREE_CODE (op2.value)((enum tree_code) (op2.value)->base.code) == INTEGER_CST) | |||
1212 | ret.value = build3_loc (loc, BIT_INSERT_EXPR, | |||
1213 | TREE_TYPE (op0.value)((contains_struct_check ((op0.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1213, __FUNCTION__))->typed.type), | |||
1214 | op0.value, op1.value, | |||
1215 | fold_convert (bitsizetype,fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_bitsizetype ], op2.value) | |||
1216 | op2.value)fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_bitsizetype ], op2.value)); | |||
1217 | } | |||
1218 | return ret; | |||
1219 | } | |||
1220 | else | |||
1221 | return c_parser_gimple_postfix_expression (parser); | |||
1222 | } | |||
1223 | default: | |||
1224 | return c_parser_gimple_postfix_expression (parser); | |||
1225 | } | |||
1226 | } | |||
1227 | ||||
1228 | /* Decompose ID into base name (ID until ver_offset) and VERSION. Return | |||
1229 | true if ID matches a SSA name. */ | |||
1230 | ||||
1231 | static bool | |||
1232 | c_parser_parse_ssa_name_id (tree id, unsigned *version, unsigned *ver_offset) | |||
1233 | { | |||
1234 | const char *token = IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1234, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ); | |||
1235 | const char *var_version = strrchr (token, '_'); | |||
1236 | if (! var_version) | |||
1237 | return false; | |||
1238 | ||||
1239 | *ver_offset = var_version - token; | |||
1240 | for (const char *p = var_version + 1; *p; ++p) | |||
1241 | if (! ISDIGIT (*p)(_sch_istable[(*p) & 0xff] & (unsigned short)(_sch_isdigit ))) | |||
1242 | return false; | |||
1243 | *version = atoi (var_version + 1); | |||
1244 | return *version > 0; | |||
1245 | } | |||
1246 | ||||
1247 | /* Get at the actual SSA name ID with VERSION starting at VER_OFFSET. | |||
1248 | TYPE is the type if the SSA name is being declared. */ | |||
1249 | ||||
1250 | static tree | |||
1251 | c_parser_parse_ssa_name (gimple_parser &parser, | |||
1252 | tree id, tree type, unsigned version, | |||
1253 | unsigned ver_offset) | |||
1254 | { | |||
1255 | tree name = NULL_TREE(tree) nullptr; | |||
1256 | const char *token = IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1256, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ); | |||
1257 | ||||
1258 | if (ver_offset == 0) | |||
1259 | { | |||
1260 | /* Anonymous unnamed SSA name. */ | |||
1261 | if (version < num_ssa_names(vec_safe_length ((cfun + 0)->gimple_df->ssa_names))) | |||
1262 | name = ssa_name (version)((*(cfun + 0)->gimple_df->ssa_names)[(version)]); | |||
1263 | if (! name) | |||
1264 | { | |||
1265 | if (! type) | |||
1266 | { | |||
1267 | c_parser_error (parser, "SSA name undeclared"); | |||
1268 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1269 | } | |||
1270 | name = make_ssa_name_fn (cfun(cfun + 0), type, NULLnullptr, version); | |||
1271 | } | |||
1272 | } | |||
1273 | else | |||
1274 | { | |||
1275 | if (version < num_ssa_names(vec_safe_length ((cfun + 0)->gimple_df->ssa_names))) | |||
1276 | name = ssa_name (version)((*(cfun + 0)->gimple_df->ssa_names)[(version)]); | |||
1277 | if (! name) | |||
1278 | { | |||
1279 | /* Separate var name from version. */ | |||
1280 | char *var_name = XNEWVEC (char, ver_offset + 1)((char *) xmalloc (sizeof (char) * (ver_offset + 1))); | |||
1281 | memcpy (var_name, token, ver_offset); | |||
1282 | var_name[ver_offset] = '\0'; | |||
1283 | /* lookup for parent decl. */ | |||
1284 | id = get_identifier (var_name)(__builtin_constant_p (var_name) ? get_identifier_with_length ((var_name), strlen (var_name)) : get_identifier (var_name)); | |||
1285 | tree parent = lookup_name (id); | |||
1286 | XDELETEVEC (var_name)free ((void*) (var_name)); | |||
1287 | if (! parent || parent == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1288 | { | |||
1289 | c_parser_error (parser, "base variable or SSA name undeclared"); | |||
1290 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1291 | } | |||
1292 | if (!(VAR_P (parent)(((enum tree_code) (parent)->base.code) == VAR_DECL) | |||
1293 | || TREE_CODE (parent)((enum tree_code) (parent)->base.code) == PARM_DECL | |||
1294 | || TREE_CODE (parent)((enum tree_code) (parent)->base.code) == RESULT_DECL)) | |||
1295 | { | |||
1296 | error ("invalid base %qE for SSA name", parent); | |||
1297 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1298 | } | |||
1299 | name = make_ssa_name_fn (cfun(cfun + 0), parent, | |||
1300 | gimple_build_nop (), version); | |||
1301 | } | |||
1302 | } | |||
1303 | ||||
1304 | return name; | |||
1305 | } | |||
1306 | ||||
1307 | /* Parse a gimple call to an internal function. | |||
1308 | ||||
1309 | gimple-call-internal: | |||
1310 | . identifier ( gimple-argument-expression-list[opt] ) */ | |||
1311 | ||||
1312 | static struct c_expr | |||
1313 | c_parser_gimple_call_internal (gimple_parser &parser) | |||
1314 | { | |||
1315 | struct c_expr expr; | |||
1316 | expr.set_error (); | |||
1317 | ||||
1318 | gcc_assert (c_parser_next_token_is (parser, CPP_DOT))((void)(!(c_parser_next_token_is (parser, CPP_DOT)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1318, __FUNCTION__), 0 : 0)); | |||
1319 | c_parser_consume_token (parser); | |||
1320 | location_t loc = c_parser_peek_token (parser)->location; | |||
1321 | if (!c_parser_next_token_is (parser, CPP_NAME) | |||
1322 | || c_parser_peek_token (parser)->id_kind != C_ID_ID) | |||
1323 | { | |||
1324 | c_parser_error (parser, "expecting internal function name"); | |||
1325 | return expr; | |||
1326 | } | |||
1327 | tree id = c_parser_peek_token (parser)->value; | |||
1328 | internal_fn ifn = lookup_internal_fn (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1328, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )); | |||
1329 | c_parser_consume_token (parser); | |||
1330 | if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
1331 | { | |||
1332 | auto_vec<tree> exprlist; | |||
1333 | if (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |||
1334 | c_parser_gimple_expr_list (parser, &exprlist); | |||
1335 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); | |||
1336 | if (ifn == IFN_LAST) | |||
1337 | error_at (loc, "unknown internal function %qE", id); | |||
1338 | else | |||
1339 | { | |||
1340 | expr.value = build_call_expr_internal_loc_array | |||
1341 | (loc, ifn, void_type_nodeglobal_trees[TI_VOID_TYPE], exprlist.length (), | |||
1342 | exprlist.address ()); | |||
1343 | expr.original_code = ERROR_MARK; | |||
1344 | expr.original_type = NULLnullptr; | |||
1345 | expr.m_decimal = 0; | |||
1346 | } | |||
1347 | } | |||
1348 | return expr; | |||
1349 | } | |||
1350 | ||||
1351 | /* Parse '<' type [',' alignment] '>' and return a type on success | |||
1352 | and NULL_TREE on error. */ | |||
1353 | ||||
1354 | static tree | |||
1355 | c_parser_gimple_typespec (gimple_parser &parser) | |||
1356 | { | |||
1357 | struct c_type_name *type_name = NULLnullptr; | |||
1358 | tree alignment = NULL_TREE(tree) nullptr; | |||
1359 | if (c_parser_require (parser, CPP_LESS, "expected %<<%>")) | |||
1360 | { | |||
1361 | type_name = c_parser_type_name (parser); | |||
1362 | /* Optional alignment. */ | |||
1363 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |||
1364 | { | |||
1365 | c_parser_consume_token (parser); | |||
1366 | alignment | |||
1367 | = c_parser_gimple_postfix_expression (parser).value; | |||
1368 | } | |||
1369 | c_parser_skip_until_found (parser, | |||
1370 | CPP_GREATER, "expected %<>%>"); | |||
1371 | } | |||
1372 | if (!type_name) | |||
1373 | return NULL_TREE(tree) nullptr; | |||
1374 | tree tem; | |||
1375 | tree type = groktypename (type_name, &tem, NULLnullptr); | |||
1376 | if (alignment) | |||
1377 | type = build_aligned_type (type, tree_to_uhwi (alignment)); | |||
1378 | return type; | |||
1379 | } | |||
1380 | ||||
1381 | /* Parse gimple postfix expression. | |||
1382 | ||||
1383 | gimple-postfix-expression: | |||
1384 | gimple-primary-expression | |||
1385 | gimple-primary-expression [ gimple-primary-expression ] | |||
1386 | gimple-primary-expression ( gimple-argument-expression-list[opt] ) | |||
1387 | gimple-postfix-expression . identifier | |||
1388 | gimple-postfix-expression -> identifier | |||
1389 | ||||
1390 | gimple-argument-expression-list: | |||
1391 | gimple-unary-expression | |||
1392 | gimple-argument-expression-list , gimple-unary-expression | |||
1393 | ||||
1394 | gimple-primary-expression: | |||
1395 | identifier | |||
1396 | constant | |||
1397 | string-literal | |||
1398 | constructor | |||
1399 | gimple-call-internal | |||
1400 | ||||
1401 | */ | |||
1402 | ||||
1403 | static struct c_expr | |||
1404 | c_parser_gimple_postfix_expression (gimple_parser &parser) | |||
1405 | { | |||
1406 | location_t loc = c_parser_peek_token (parser)->location; | |||
1407 | source_range tok_range = c_parser_peek_token (parser)->get_range (); | |||
1408 | struct c_expr expr; | |||
1409 | expr.set_error (); | |||
1410 | switch (c_parser_peek_token (parser)->type) | |||
1411 | { | |||
1412 | case CPP_NUMBER: | |||
1413 | expr.value = c_parser_peek_token (parser)->value; | |||
1414 | set_c_expr_source_range (&expr, tok_range); | |||
1415 | loc = c_parser_peek_token (parser)->location; | |||
1416 | c_parser_consume_token (parser); | |||
1417 | break; | |||
1418 | case CPP_CHAR: | |||
1419 | case CPP_CHAR16: | |||
1420 | case CPP_CHAR32: | |||
1421 | case CPP_UTF8CHAR: | |||
1422 | case CPP_WCHAR: | |||
1423 | expr.value = c_parser_peek_token (parser)->value; | |||
1424 | set_c_expr_source_range (&expr, tok_range); | |||
1425 | c_parser_consume_token (parser); | |||
1426 | break; | |||
1427 | case CPP_STRING: | |||
1428 | case CPP_STRING16: | |||
1429 | case CPP_STRING32: | |||
1430 | case CPP_WSTRING: | |||
1431 | case CPP_UTF8STRING: | |||
1432 | expr = c_parser_string_literal (parser, false, true); | |||
1433 | break; | |||
1434 | case CPP_DOT: | |||
1435 | expr = c_parser_gimple_call_internal (parser); | |||
1436 | break; | |||
1437 | case CPP_NAME: | |||
1438 | if (c_parser_peek_token (parser)->id_kind == C_ID_ID) | |||
1439 | { | |||
1440 | tree id = c_parser_peek_token (parser)->value; | |||
1441 | if (strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1441, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__MEM") == 0) | |||
1442 | { | |||
1443 | /* __MEM '<' type-name [ ',' number ] '>' | |||
1444 | '(' [ '(' type-name ')' ] unary-expression | |||
1445 | [ '+' number ] ')' */ | |||
1446 | location_t loc = c_parser_peek_token (parser)->location; | |||
1447 | c_parser_consume_token (parser); | |||
1448 | tree type = c_parser_gimple_typespec (parser); | |||
1449 | struct c_expr ptr; | |||
1450 | ptr.value = error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1451 | tree alias_off = NULL_TREE(tree) nullptr; | |||
1452 | if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
1453 | { | |||
1454 | tree alias_type = NULL_TREE(tree) nullptr; | |||
1455 | /* Optional alias-type cast. */ | |||
1456 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) | |||
1457 | { | |||
1458 | c_parser_consume_token (parser); | |||
1459 | struct c_type_name *alias_type_name | |||
1460 | = c_parser_type_name (parser); | |||
1461 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |||
1462 | "expected %<)%>"); | |||
1463 | if (alias_type_name) | |||
1464 | { | |||
1465 | tree tem; | |||
1466 | alias_type = groktypename (alias_type_name, | |||
1467 | &tem, NULLnullptr); | |||
1468 | } | |||
1469 | } | |||
1470 | ptr = c_parser_gimple_unary_expression (parser); | |||
1471 | if (ptr.value == error_mark_nodeglobal_trees[TI_ERROR_MARK] | |||
1472 | || ! POINTER_TYPE_P (TREE_TYPE (ptr.value))(((enum tree_code) (((contains_struct_check ((ptr.value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1472, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((ptr.value), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1472, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE )) | |||
1473 | { | |||
1474 | if (ptr.value != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1475 | error_at (ptr.get_start (), | |||
1476 | "invalid type of %<__MEM%> operand"); | |||
1477 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |||
1478 | "expected %<)%>"); | |||
1479 | return expr; | |||
1480 | } | |||
1481 | if (! alias_type) | |||
1482 | alias_type = TREE_TYPE (ptr.value)((contains_struct_check ((ptr.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1482, __FUNCTION__))->typed.type); | |||
1483 | /* Optional constant offset. */ | |||
1484 | if (c_parser_next_token_is (parser, CPP_PLUS)) | |||
1485 | { | |||
1486 | c_parser_consume_token (parser); | |||
1487 | alias_off | |||
1488 | = c_parser_gimple_postfix_expression (parser).value; | |||
1489 | alias_off = fold_convert (alias_type, alias_off)fold_convert_loc (((location_t) 0), alias_type, alias_off); | |||
1490 | } | |||
1491 | if (! alias_off) | |||
1492 | alias_off = build_int_cst (alias_type, 0); | |||
1493 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |||
1494 | "expected %<)%>"); | |||
1495 | } | |||
1496 | if (! type || c_parser_error (parser)) | |||
1497 | { | |||
1498 | c_parser_set_error (parser, false); | |||
1499 | return expr; | |||
1500 | } | |||
1501 | expr.value = build2_loc (loc, MEM_REF, | |||
1502 | type, ptr.value, alias_off); | |||
1503 | break; | |||
1504 | } | |||
1505 | else if (strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1505, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__VIEW_CONVERT") == 0) | |||
1506 | { | |||
1507 | /* __VIEW_CONVERT '<' type-name [ ',' number ] '>' | |||
1508 | '(' postfix-expression ')' */ | |||
1509 | location_t loc = c_parser_peek_token (parser)->location; | |||
1510 | c_parser_consume_token (parser); | |||
1511 | tree type = c_parser_gimple_typespec (parser); | |||
1512 | if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
1513 | { | |||
1514 | c_expr op = c_parser_gimple_postfix_expression (parser); | |||
1515 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |||
1516 | "expected %<)%>"); | |||
1517 | if (type && op.value != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1518 | expr.value = build1_loc (loc, VIEW_CONVERT_EXPR, | |||
1519 | type, op.value); | |||
1520 | } | |||
1521 | break; | |||
1522 | } | |||
1523 | else if (strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1523, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "__BIT_FIELD_REF") == 0) | |||
1524 | { | |||
1525 | /* __BIT_FIELD_REF '<' type-name [ ',' number ] '>' | |||
1526 | '(' postfix-expression, integer, integer ')' */ | |||
1527 | location_t loc = c_parser_peek_token (parser)->location; | |||
1528 | c_parser_consume_token (parser); | |||
1529 | tree type = c_parser_gimple_typespec (parser); | |||
1530 | if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
1531 | { | |||
1532 | c_expr op0 = c_parser_gimple_postfix_expression (parser); | |||
1533 | c_parser_skip_until_found (parser, CPP_COMMA, | |||
1534 | "expected %<,%>"); | |||
1535 | c_expr op1 = c_parser_gimple_postfix_expression (parser); | |||
1536 | if (TREE_CODE (op1.value)((enum tree_code) (op1.value)->base.code) != INTEGER_CST | |||
1537 | || !int_fits_type_p (op1.value, bitsizetypesizetype_tab[(int) stk_bitsizetype])) | |||
1538 | c_parser_error (parser, "expected constant size"); | |||
1539 | c_parser_skip_until_found (parser, CPP_COMMA, | |||
1540 | "expected %<,%>"); | |||
1541 | c_expr op2 = c_parser_gimple_postfix_expression (parser); | |||
1542 | if (TREE_CODE (op2.value)((enum tree_code) (op2.value)->base.code) != INTEGER_CST | |||
1543 | || !int_fits_type_p (op2.value, bitsizetypesizetype_tab[(int) stk_bitsizetype])) | |||
1544 | c_parser_error (parser, "expected constant offset"); | |||
1545 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |||
1546 | "expected %<)%>"); | |||
1547 | if (type | |||
1548 | && op0.value != error_mark_nodeglobal_trees[TI_ERROR_MARK] | |||
1549 | && TREE_CODE (op1.value)((enum tree_code) (op1.value)->base.code) == INTEGER_CST | |||
1550 | && TREE_CODE (op2.value)((enum tree_code) (op2.value)->base.code) == INTEGER_CST) | |||
1551 | expr.value = build3_loc (loc, BIT_FIELD_REF, type, | |||
1552 | op0.value, | |||
1553 | fold_convert (bitsizetype,fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_bitsizetype ], op1.value) | |||
1554 | op1.value)fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_bitsizetype ], op1.value), | |||
1555 | fold_convert (bitsizetype,fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_bitsizetype ], op2.value) | |||
1556 | op2.value)fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_bitsizetype ], op2.value)); | |||
1557 | } | |||
1558 | break; | |||
1559 | } | |||
1560 | else if (strcmp (IDENTIFIER_POINTER (id)((const char *) (tree_check ((id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1560, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), "_Literal") == 0) | |||
1561 | { | |||
1562 | /* _Literal '(' type-name ')' ( [ '-' ] constant | constructor ) */ | |||
1563 | c_parser_consume_token (parser); | |||
1564 | tree type = NULL_TREE(tree) nullptr; | |||
1565 | if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
1566 | { | |||
1567 | struct c_type_name *type_name = c_parser_type_name (parser); | |||
1568 | tree tem; | |||
1569 | if (type_name) | |||
1570 | type = groktypename (type_name, &tem, NULLnullptr); | |||
1571 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |||
1572 | "expected %<)%>"); | |||
1573 | } | |||
1574 | if (! type) | |||
1575 | { | |||
1576 | c_parser_error (parser, "invalid _Literal"); | |||
1577 | return expr; | |||
1578 | } | |||
1579 | if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) | |||
1580 | { | |||
1581 | c_parser_consume_token (parser); | |||
1582 | if (!AGGREGATE_TYPE_P (type)(((enum tree_code) (type)->base.code) == ARRAY_TYPE || ((( 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)) | |||
1583 | && !VECTOR_TYPE_P (type)(((enum tree_code) (type)->base.code) == VECTOR_TYPE)) | |||
1584 | { | |||
1585 | c_parser_error (parser, "invalid type for _Literal with " | |||
1586 | "constructor"); | |||
1587 | c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, | |||
1588 | "expected %<}%>"); | |||
1589 | return expr; | |||
1590 | } | |||
1591 | vec<constructor_elt, va_gc> *v = NULLnullptr; | |||
1592 | bool constant_p = true; | |||
1593 | if (VECTOR_TYPE_P (type)(((enum tree_code) (type)->base.code) == VECTOR_TYPE) | |||
1594 | && !c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) | |||
1595 | { | |||
1596 | vec_alloc (v, TYPE_VECTOR_SUBPARTS (type).to_constant ()); | |||
1597 | do | |||
1598 | { | |||
1599 | tree val | |||
1600 | = c_parser_gimple_postfix_expression (parser).value; | |||
1601 | if (! val | |||
1602 | || val == error_mark_nodeglobal_trees[TI_ERROR_MARK] | |||
1603 | || (! CONSTANT_CLASS_P (val)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (val)->base.code))] == tcc_constant) | |||
1604 | && ! SSA_VAR_P (val)(((enum tree_code) (val)->base.code) == VAR_DECL || ((enum tree_code) (val)->base.code) == PARM_DECL || ((enum tree_code ) (val)->base.code) == RESULT_DECL || ((enum tree_code) (val )->base.code) == SSA_NAME))) | |||
1605 | { | |||
1606 | c_parser_error (parser, "invalid _Literal"); | |||
1607 | return expr; | |||
1608 | } | |||
1609 | CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, val)do { constructor_elt _ce___ = {(tree) nullptr, val}; vec_safe_push ((v), _ce___); } while (0); | |||
1610 | if (! CONSTANT_CLASS_P (val)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (val)->base.code))] == tcc_constant)) | |||
1611 | constant_p = false; | |||
1612 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |||
1613 | c_parser_consume_token (parser); | |||
1614 | else | |||
1615 | break; | |||
1616 | } | |||
1617 | while (1); | |||
1618 | } | |||
1619 | if (c_parser_require (parser, CPP_CLOSE_BRACE, | |||
1620 | "expected %<}%>")) | |||
1621 | { | |||
1622 | if (v && constant_p) | |||
1623 | expr.value = build_vector_from_ctor (type, v); | |||
1624 | else | |||
1625 | expr.value = build_constructor (type, v); | |||
1626 | } | |||
1627 | else | |||
1628 | { | |||
1629 | c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, | |||
1630 | "expected %<}%>"); | |||
1631 | return expr; | |||
1632 | } | |||
1633 | } | |||
1634 | else | |||
1635 | { | |||
1636 | bool neg_p, addr_p; | |||
1637 | if ((neg_p = c_parser_next_token_is (parser, CPP_MINUS))) | |||
1638 | c_parser_consume_token (parser); | |||
1639 | if ((addr_p = c_parser_next_token_is (parser, CPP_AND))) | |||
1640 | c_parser_consume_token (parser); | |||
1641 | tree val = c_parser_gimple_postfix_expression (parser).value; | |||
1642 | if (! val | |||
1643 | || val == error_mark_nodeglobal_trees[TI_ERROR_MARK] | |||
1644 | || (!CONSTANT_CLASS_P (val)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (val)->base.code))] == tcc_constant) && !addr_p)) | |||
1645 | { | |||
1646 | c_parser_error (parser, "invalid _Literal"); | |||
1647 | return expr; | |||
1648 | } | |||
1649 | if (addr_p) | |||
1650 | { | |||
1651 | val = build1 (ADDR_EXPR, type, val); | |||
1652 | if (!is_gimple_invariant_address (val)) | |||
1653 | { | |||
1654 | c_parser_error (parser, "invalid _Literal"); | |||
1655 | return expr; | |||
1656 | } | |||
1657 | } | |||
1658 | if (neg_p) | |||
1659 | { | |||
1660 | val = const_unop (NEGATE_EXPR, TREE_TYPE (val)((contains_struct_check ((val), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1660, __FUNCTION__))->typed.type), val); | |||
1661 | if (! val) | |||
1662 | { | |||
1663 | c_parser_error (parser, "invalid _Literal"); | |||
1664 | return expr; | |||
1665 | } | |||
1666 | } | |||
1667 | expr.value = fold_convert (type, val)fold_convert_loc (((location_t) 0), type, val); | |||
1668 | } | |||
1669 | return expr; | |||
1670 | } | |||
1671 | ||||
1672 | /* SSA name. */ | |||
1673 | unsigned version, ver_offset; | |||
1674 | if (! lookup_name (id) | |||
1675 | && c_parser_parse_ssa_name_id (id, &version, &ver_offset)) | |||
1676 | { | |||
1677 | c_parser_consume_token (parser); | |||
1678 | expr.value = c_parser_parse_ssa_name (parser, id, NULL_TREE(tree) nullptr, | |||
1679 | version, ver_offset); | |||
1680 | if (expr.value == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1681 | return expr; | |||
1682 | set_c_expr_source_range (&expr, tok_range); | |||
1683 | /* For default definition SSA names. */ | |||
1684 | if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) | |||
1685 | && c_parser_peek_2nd_token (parser)->type == CPP_NAME | |||
1686 | && strcmp ("D", | |||
1687 | IDENTIFIER_POINTER((const char *) (tree_check ((c_parser_peek_2nd_token (parser )->value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1688, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ) | |||
1688 | (c_parser_peek_2nd_token (parser)->value)((const char *) (tree_check ((c_parser_peek_2nd_token (parser )->value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1688, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str )) == 0 | |||
1689 | && c_parser_peek_nth_token (parser, 3)->type == CPP_CLOSE_PAREN) | |||
1690 | { | |||
1691 | c_parser_consume_token (parser); | |||
1692 | c_parser_consume_token (parser); | |||
1693 | c_parser_consume_token (parser); | |||
1694 | if (! SSA_NAME_IS_DEFAULT_DEF (expr.value)(tree_check ((expr.value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1694, __FUNCTION__, (SSA_NAME)))->base.default_def_flag) | |||
1695 | { | |||
1696 | if (!SSA_NAME_VAR (expr.value)((tree_check ((expr.value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1696, __FUNCTION__, (SSA_NAME)))->ssa_name.var == (tree) nullptr || ((enum tree_code) ((expr.value)->ssa_name.var) ->base.code) == IDENTIFIER_NODE ? (tree) nullptr : (expr.value )->ssa_name.var)) | |||
1697 | { | |||
1698 | error_at (loc, "anonymous SSA name cannot have" | |||
1699 | " default definition"); | |||
1700 | expr.value = error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
1701 | return expr; | |||
1702 | } | |||
1703 | set_ssa_default_def (cfun(cfun + 0), SSA_NAME_VAR (expr.value)((tree_check ((expr.value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1703, __FUNCTION__, (SSA_NAME)))->ssa_name.var == (tree) nullptr || ((enum tree_code) ((expr.value)->ssa_name.var) ->base.code) == IDENTIFIER_NODE ? (tree) nullptr : (expr.value )->ssa_name.var), | |||
1704 | expr.value); | |||
1705 | SSA_NAME_DEF_STMT (expr.value)(tree_check ((expr.value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1705, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt = gimple_build_nop (); | |||
1706 | } | |||
1707 | } | |||
1708 | } | |||
1709 | else | |||
1710 | { | |||
1711 | c_parser_consume_token (parser); | |||
1712 | expr.value | |||
1713 | = build_external_ref (loc, id, | |||
1714 | (c_parser_peek_token (parser)->type | |||
1715 | == CPP_OPEN_PAREN), &expr.original_type); | |||
1716 | set_c_expr_source_range (&expr, tok_range); | |||
1717 | } | |||
1718 | break; | |||
1719 | } | |||
1720 | /* Fallthru. */ | |||
1721 | default: | |||
1722 | c_parser_error (parser, "expected expression"); | |||
1723 | expr.set_error (); | |||
1724 | break; | |||
1725 | } | |||
1726 | if (expr.value == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
1727 | return expr; | |||
1728 | return c_parser_gimple_postfix_expression_after_primary | |||
1729 | (parser, EXPR_LOC_OR_LOC (expr.value, loc)((((IS_ADHOC_LOC (((((expr.value)) && ((tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) ((expr.value ))->base.code))]) >= tcc_reference && (tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) ((expr.value ))->base.code))]) <= tcc_expression)) ? (expr.value)-> exp.locus : ((location_t) 0)))) ? get_location_from_adhoc_loc (line_table, ((((expr.value)) && ((tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) ((expr.value ))->base.code))]) >= tcc_reference && (tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) ((expr.value ))->base.code))]) <= tcc_expression)) ? (expr.value)-> exp.locus : ((location_t) 0))) : (((((expr.value)) && ((tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) ((expr.value))->base.code))]) >= tcc_reference && (tree_code_type_tmpl <0>::tree_code_type[(int ) (((enum tree_code) ((expr.value))->base.code))]) <= tcc_expression )) ? (expr.value)->exp.locus : ((location_t) 0)))) != ((location_t ) 0)) ? (expr.value)->exp.locus : (loc)), expr); | |||
1730 | } | |||
1731 | ||||
1732 | /* Parse a gimple postfix expression after the initial primary or compound | |||
1733 | literal. */ | |||
1734 | ||||
1735 | static struct c_expr | |||
1736 | c_parser_gimple_postfix_expression_after_primary (gimple_parser &parser, | |||
1737 | location_t expr_loc, | |||
1738 | struct c_expr expr) | |||
1739 | { | |||
1740 | location_t start; | |||
1741 | location_t finish; | |||
1742 | tree ident; | |||
1743 | location_t comp_loc; | |||
1744 | ||||
1745 | while (true) | |||
1746 | { | |||
1747 | location_t op_loc = c_parser_peek_token (parser)->location; | |||
1748 | switch (c_parser_peek_token (parser)->type) | |||
1749 | { | |||
1750 | case CPP_OPEN_SQUARE: | |||
1751 | { | |||
1752 | c_parser_consume_token (parser); | |||
1753 | tree idx = c_parser_gimple_unary_expression (parser).value; | |||
1754 | ||||
1755 | if (! c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>")) | |||
1756 | { | |||
1757 | c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULLnullptr); | |||
1758 | break; | |||
1759 | } | |||
1760 | ||||
1761 | start = expr.get_start (); | |||
1762 | finish = c_parser_tokens_buf (parser, 0)->location; | |||
1763 | expr.value = build_array_ref (op_loc, expr.value, idx); | |||
1764 | set_c_expr_source_range (&expr, start, finish); | |||
1765 | expr.m_decimal = 0; | |||
1766 | ||||
1767 | expr.original_code = ERROR_MARK; | |||
1768 | expr.original_type = NULLnullptr; | |||
1769 | break; | |||
1770 | } | |||
1771 | case CPP_OPEN_PAREN: | |||
1772 | { | |||
1773 | /* Function call. */ | |||
1774 | c_parser_consume_token (parser); | |||
1775 | auto_vec<tree> exprlist; | |||
1776 | if (! c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) | |||
1777 | c_parser_gimple_expr_list (parser, &exprlist); | |||
1778 | c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, | |||
1779 | "expected %<)%>"); | |||
1780 | if (!FUNC_OR_METHOD_TYPE_P (TREE_TYPE (expr.value))(((enum tree_code) (((contains_struct_check ((expr.value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1780, __FUNCTION__))->typed.type))->base.code) == FUNCTION_TYPE || ((enum tree_code) (((contains_struct_check ((expr.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1780, __FUNCTION__))->typed.type))->base.code) == METHOD_TYPE )) | |||
1781 | { | |||
1782 | c_parser_error (parser, "invalid call to non-function"); | |||
1783 | expr.set_error (); | |||
1784 | break; | |||
1785 | } | |||
1786 | expr.value = build_call_array_loc | |||
1787 | (expr_loc, TREE_TYPE (TREE_TYPE (expr.value))((contains_struct_check ((((contains_struct_check ((expr.value ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1787, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1787, __FUNCTION__))->typed.type), | |||
1788 | expr.value, exprlist.length (), exprlist.address ()); | |||
1789 | expr.m_decimal = 0; | |||
1790 | expr.original_code = ERROR_MARK; | |||
1791 | expr.original_type = NULLnullptr; | |||
1792 | break; | |||
1793 | } | |||
1794 | case CPP_DOT: | |||
1795 | { | |||
1796 | /* Structure element reference. */ | |||
1797 | c_parser_consume_token (parser); | |||
1798 | if (c_parser_next_token_is (parser, CPP_NAME)) | |||
1799 | { | |||
1800 | c_token *comp_tok = c_parser_peek_token (parser); | |||
1801 | ident = comp_tok->value; | |||
1802 | comp_loc = comp_tok->location; | |||
1803 | } | |||
1804 | else | |||
1805 | { | |||
1806 | c_parser_error (parser, "expected identifier"); | |||
1807 | expr.set_error (); | |||
1808 | expr.original_code = ERROR_MARK; | |||
1809 | expr.original_type = NULLnullptr; | |||
1810 | return expr; | |||
1811 | } | |||
1812 | start = expr.get_start (); | |||
1813 | finish = c_parser_peek_token (parser)->get_finish (); | |||
1814 | c_parser_consume_token (parser); | |||
1815 | expr.value = build_component_ref (op_loc, expr.value, ident, | |||
1816 | comp_loc, UNKNOWN_LOCATION((location_t) 0)); | |||
1817 | set_c_expr_source_range (&expr, start, finish); | |||
1818 | expr.m_decimal = 0; | |||
1819 | expr.original_code = ERROR_MARK; | |||
1820 | if (TREE_CODE (expr.value)((enum tree_code) (expr.value)->base.code) != COMPONENT_REF) | |||
1821 | expr.original_type = NULLnullptr; | |||
1822 | else | |||
1823 | { | |||
1824 | /* Remember the original type of a bitfield. */ | |||
1825 | tree field = TREE_OPERAND (expr.value, 1)(*((const_cast<tree*> (tree_operand_check ((expr.value) , (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1825, __FUNCTION__))))); | |||
1826 | if (TREE_CODE (field)((enum tree_code) (field)->base.code) != FIELD_DECL) | |||
1827 | expr.original_type = NULLnullptr; | |||
1828 | else | |||
1829 | expr.original_type = DECL_BIT_FIELD_TYPE (field)((tree_check ((field), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1829, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_field_type ); | |||
1830 | } | |||
1831 | break; | |||
1832 | } | |||
1833 | case CPP_DEREF: | |||
1834 | { | |||
1835 | /* Structure element reference. */ | |||
1836 | if (!POINTER_TYPE_P (TREE_TYPE (expr.value))(((enum tree_code) (((contains_struct_check ((expr.value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1836, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((expr.value), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1836, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE )) | |||
1837 | { | |||
1838 | c_parser_error (parser, "dereference of non-pointer"); | |||
1839 | expr.set_error (); | |||
1840 | expr.original_code = ERROR_MARK; | |||
1841 | expr.original_type = NULLnullptr; | |||
1842 | return expr; | |||
1843 | } | |||
1844 | c_parser_consume_token (parser); | |||
1845 | if (c_parser_next_token_is (parser, CPP_NAME)) | |||
1846 | { | |||
1847 | c_token *comp_tok = c_parser_peek_token (parser); | |||
1848 | ident = comp_tok->value; | |||
1849 | comp_loc = comp_tok->location; | |||
1850 | } | |||
1851 | else | |||
1852 | { | |||
1853 | c_parser_error (parser, "expected identifier"); | |||
1854 | expr.set_error (); | |||
1855 | expr.original_code = ERROR_MARK; | |||
1856 | expr.original_type = NULLnullptr; | |||
1857 | return expr; | |||
1858 | } | |||
1859 | start = expr.get_start (); | |||
1860 | finish = c_parser_peek_token (parser)->get_finish (); | |||
1861 | c_parser_consume_token (parser); | |||
1862 | expr.value = build_component_ref (op_loc, | |||
1863 | build_simple_mem_ref_loc | |||
1864 | (op_loc, expr.value), | |||
1865 | ident, comp_loc, | |||
1866 | expr.get_location ()); | |||
1867 | set_c_expr_source_range (&expr, start, finish); | |||
1868 | expr.m_decimal = 0; | |||
1869 | expr.original_code = ERROR_MARK; | |||
1870 | if (TREE_CODE (expr.value)((enum tree_code) (expr.value)->base.code) != COMPONENT_REF) | |||
1871 | expr.original_type = NULLnullptr; | |||
1872 | else | |||
1873 | { | |||
1874 | /* Remember the original type of a bitfield. */ | |||
1875 | tree field = TREE_OPERAND (expr.value, 1)(*((const_cast<tree*> (tree_operand_check ((expr.value) , (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1875, __FUNCTION__))))); | |||
1876 | if (TREE_CODE (field)((enum tree_code) (field)->base.code) != FIELD_DECL) | |||
1877 | expr.original_type = NULLnullptr; | |||
1878 | else | |||
1879 | expr.original_type = DECL_BIT_FIELD_TYPE (field)((tree_check ((field), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1879, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_field_type ); | |||
1880 | } | |||
1881 | break; | |||
1882 | } | |||
1883 | default: | |||
1884 | return expr; | |||
1885 | } | |||
1886 | } | |||
1887 | } | |||
1888 | ||||
1889 | /* Parse expression list. | |||
1890 | ||||
1891 | gimple-expr-list: | |||
1892 | gimple-unary-expression | |||
1893 | gimple-expr-list , gimple-unary-expression | |||
1894 | ||||
1895 | */ | |||
1896 | ||||
1897 | static void | |||
1898 | c_parser_gimple_expr_list (gimple_parser &parser, vec<tree> *ret) | |||
1899 | { | |||
1900 | struct c_expr expr; | |||
1901 | ||||
1902 | expr = c_parser_gimple_unary_expression (parser); | |||
1903 | ret->safe_push (expr.value); | |||
1904 | while (c_parser_next_token_is (parser, CPP_COMMA)) | |||
1905 | { | |||
1906 | c_parser_consume_token (parser); | |||
1907 | expr = c_parser_gimple_unary_expression (parser); | |||
1908 | ret->safe_push (expr.value); | |||
1909 | } | |||
1910 | } | |||
1911 | ||||
1912 | /* Parse gimple label. | |||
1913 | ||||
1914 | gimple-label: | |||
1915 | identifier : | |||
1916 | case constant-expression : | |||
1917 | default : | |||
1918 | ||||
1919 | */ | |||
1920 | ||||
1921 | static void | |||
1922 | c_parser_gimple_label (gimple_parser &parser, gimple_seq *seq) | |||
1923 | { | |||
1924 | tree name = c_parser_peek_token (parser)->value; | |||
1925 | location_t loc1 = c_parser_peek_token (parser)->location; | |||
1926 | gcc_assert (c_parser_next_token_is (parser, CPP_NAME))((void)(!(c_parser_next_token_is (parser, CPP_NAME)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1926, __FUNCTION__), 0 : 0)); | |||
1927 | c_parser_consume_token (parser); | |||
1928 | gcc_assert (c_parser_next_token_is (parser, CPP_COLON))((void)(!(c_parser_next_token_is (parser, CPP_COLON)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1928, __FUNCTION__), 0 : 0)); | |||
1929 | c_parser_consume_token (parser); | |||
1930 | tree label = define_label (loc1, name); | |||
1931 | if (label) | |||
1932 | gimple_seq_add_stmt_without_update (seq, gimple_build_label (label)); | |||
1933 | return; | |||
1934 | } | |||
1935 | ||||
1936 | /* Parse gimple/RTL pass list. | |||
1937 | ||||
1938 | gimple-or-rtl-pass-list: | |||
1939 | startwith("pass-name")[,{cfg,ssa}] | |||
1940 | */ | |||
1941 | ||||
1942 | void | |||
1943 | c_parser_gimple_or_rtl_pass_list (c_parser *parser, c_declspecs *specs) | |||
1944 | { | |||
1945 | char *pass = NULLnullptr; | |||
1946 | ||||
1947 | /* Accept __GIMPLE/__RTL. */ | |||
1948 | if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) | |||
1949 | return; | |||
1950 | c_parser_consume_token (parser); | |||
1951 | ||||
1952 | specs->entry_bb_count = profile_count::uninitialized (); | |||
1953 | while (c_parser_next_token_is (parser, CPP_NAME)) | |||
1954 | { | |||
1955 | profile_quality quality; | |||
1956 | const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value)((const char *) (tree_check ((c_parser_peek_token (parser)-> value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1956, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ); | |||
1957 | c_parser_consume_token (parser); | |||
1958 | if (! strcmp (op, "startwith")) | |||
1959 | { | |||
1960 | if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
1961 | return; | |||
1962 | if (c_parser_next_token_is_not (parser, CPP_STRING)) | |||
1963 | { | |||
1964 | error_at (c_parser_peek_token (parser)->location, | |||
1965 | "expected pass name"); | |||
1966 | return; | |||
1967 | } | |||
1968 | pass = xstrdup (TREE_STRING_POINTER((const char *)((tree_check ((c_parser_string_literal (parser , false, false).value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1970, __FUNCTION__, (STRING_CST)))->string.str)) | |||
1969 | (c_parser_string_literal (parser, false,((const char *)((tree_check ((c_parser_string_literal (parser , false, false).value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1970, __FUNCTION__, (STRING_CST)))->string.str)) | |||
1970 | false).value)((const char *)((tree_check ((c_parser_string_literal (parser , false, false).value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1970, __FUNCTION__, (STRING_CST)))->string.str))); | |||
1971 | if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<(%>")) | |||
1972 | return; | |||
1973 | } | |||
1974 | else if (parse_profile_quality (op, &quality)) | |||
1975 | { | |||
1976 | tree q; | |||
1977 | if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
1978 | return; | |||
1979 | ||||
1980 | if (!c_parser_next_token_is (parser, CPP_NUMBER) | |||
1981 | || (TREE_CODE (q = c_parser_peek_token (parser)->value)((enum tree_code) (q = c_parser_peek_token (parser)->value )->base.code) | |||
1982 | != INTEGER_CST)) | |||
1983 | { | |||
1984 | c_parser_error (parser, "expected count value"); | |||
1985 | return; | |||
1986 | } | |||
1987 | ||||
1988 | specs->entry_bb_count | |||
1989 | = profile_count::from_gcov_type (TREE_INT_CST_LOW (q)((unsigned long) (*tree_int_cst_elt_check ((q), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 1989, __FUNCTION__))), quality); | |||
1990 | c_parser_consume_token (parser); | |||
1991 | if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) | |||
1992 | return; | |||
1993 | } | |||
1994 | else if (specs->declspec_il != cdil_gimple) | |||
1995 | /* Allow only one IL specifier and none on RTL. */ | |||
1996 | ; | |||
1997 | else if (! strcmp (op, "cfg")) | |||
1998 | specs->declspec_il = cdil_gimple_cfg; | |||
1999 | else if (! strcmp (op, "ssa")) | |||
2000 | specs->declspec_il = cdil_gimple_ssa; | |||
2001 | else | |||
2002 | { | |||
2003 | error_at (c_parser_peek_token (parser)->location, | |||
2004 | "invalid operation"); | |||
2005 | return; | |||
2006 | } | |||
2007 | if (c_parser_next_token_is (parser, CPP_COMMA)) | |||
2008 | c_parser_consume_token (parser); | |||
2009 | } | |||
2010 | ||||
2011 | if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) | |||
2012 | return; | |||
2013 | ||||
2014 | specs->gimple_or_rtl_pass = pass; | |||
2015 | } | |||
2016 | ||||
2017 | /* Parse gimple local declaration. | |||
2018 | ||||
2019 | declaration-specifiers: | |||
2020 | storage-class-specifier declaration-specifiers[opt] | |||
2021 | type-specifier declaration-specifiers[opt] | |||
2022 | type-qualifier declaration-specifiers[opt] | |||
2023 | function-specifier declaration-specifiers[opt] | |||
2024 | alignment-specifier declaration-specifiers[opt] | |||
2025 | ||||
2026 | storage-class-specifier: | |||
2027 | typedef | |||
2028 | extern | |||
2029 | static | |||
2030 | auto | |||
2031 | register | |||
2032 | ||||
2033 | type-specifier: | |||
2034 | void | |||
2035 | char | |||
2036 | short | |||
2037 | int | |||
2038 | long | |||
2039 | float | |||
2040 | double | |||
2041 | signed | |||
2042 | unsigned | |||
2043 | _Bool | |||
2044 | _Complex | |||
2045 | ||||
2046 | type-qualifier: | |||
2047 | const | |||
2048 | restrict | |||
2049 | volatile | |||
2050 | address-space-qualifier | |||
2051 | _Atomic | |||
2052 | ||||
2053 | */ | |||
2054 | ||||
2055 | static void | |||
2056 | c_parser_gimple_declaration (gimple_parser &parser) | |||
2057 | { | |||
2058 | struct c_declarator *declarator; | |||
2059 | struct c_declspecs *specs = build_null_declspecs (); | |||
2060 | c_parser_declspecs (parser, specs, true, true, true, | |||
2061 | true, true, true, true, cla_nonabstract_decl); | |||
2062 | finish_declspecs (specs); | |||
2063 | ||||
2064 | /* Provide better error recovery. Note that a type name here is usually | |||
2065 | better diagnosed as a redeclaration. */ | |||
2066 | if (c_parser_next_token_starts_declspecs (parser) | |||
2067 | && ! c_parser_next_token_is (parser, CPP_NAME)) | |||
2068 | { | |||
2069 | c_parser_error (parser, "expected %<;%>"); | |||
2070 | c_parser_set_error (parser, false); | |||
2071 | return; | |||
2072 | } | |||
2073 | ||||
2074 | bool dummy = false; | |||
2075 | declarator = c_parser_declarator (parser, | |||
2076 | specs->typespec_kind != ctsk_none, | |||
2077 | C_DTR_NORMAL, &dummy); | |||
2078 | ||||
2079 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) | |||
2080 | { | |||
2081 | /* Handle SSA name decls specially, they do not go into the identifier | |||
2082 | table but we simply build the SSA name for later lookup. */ | |||
2083 | unsigned version, ver_offset; | |||
2084 | /* Handle SSA pointer declarations in a very simplistic ways, we | |||
2085 | probably would like to call grokdeclarator in a special mode to | |||
2086 | just build the type of the decl - start_decl already pushes | |||
2087 | the identifier to the bindings for lookup, something we do not | |||
2088 | want. */ | |||
2089 | struct c_declarator *id_declarator = declarator; | |||
2090 | while (id_declarator->kind == cdk_pointer) | |||
2091 | id_declarator = id_declarator->declarator; | |||
2092 | if (id_declarator->kind == cdk_id | |||
2093 | && (declarator->kind == cdk_pointer | |||
2094 | || is_gimple_reg_type (specs->type)) | |||
2095 | && c_parser_parse_ssa_name_id (id_declarator->u.id.id, | |||
2096 | &version, &ver_offset) | |||
2097 | /* The following restricts it to unnamed anonymous SSA names | |||
2098 | which fails parsing of named ones in dumps (we could | |||
2099 | decide to not dump their name for -gimple). */ | |||
2100 | && ver_offset == 0) | |||
2101 | { | |||
2102 | struct c_declarator *p = declarator; | |||
2103 | tree type = specs->type; | |||
2104 | while (p->kind == cdk_pointer) | |||
2105 | { | |||
2106 | type = build_pointer_type (type); | |||
2107 | p = p->declarator; | |||
2108 | } | |||
2109 | c_parser_parse_ssa_name (parser, id_declarator->u.id.id, type, | |||
2110 | version, ver_offset); | |||
2111 | } | |||
2112 | else | |||
2113 | { | |||
2114 | tree postfix_attrs = NULL_TREE(tree) nullptr; | |||
2115 | tree all_prefix_attrs = specs->attrs; | |||
2116 | specs->attrs = NULLnullptr; | |||
2117 | tree decl = start_decl (declarator, specs, false, | |||
2118 | chainon (postfix_attrs, all_prefix_attrs)); | |||
2119 | if (decl) | |||
2120 | finish_decl (decl, UNKNOWN_LOCATION((location_t) 0), NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr, | |||
2121 | NULL_TREE(tree) nullptr); | |||
2122 | } | |||
2123 | } | |||
2124 | else | |||
2125 | { | |||
2126 | c_parser_error (parser, "expected %<;%>"); | |||
2127 | return; | |||
2128 | } | |||
2129 | } | |||
2130 | ||||
2131 | /* Parse gimple goto statement. */ | |||
2132 | ||||
2133 | static void | |||
2134 | c_parser_gimple_goto_stmt (gimple_parser &parser, | |||
2135 | location_t loc, tree label, gimple_seq *seq) | |||
2136 | { | |||
2137 | if (cfun(cfun + 0)->curr_properties & PROP_cfg(1 << 3)) | |||
2138 | { | |||
2139 | int dest_index; | |||
2140 | profile_probability prob; | |||
2141 | if (c_parser_gimple_parse_bb_spec_edge_probability (label, parser, | |||
2142 | &dest_index, &prob)) | |||
2143 | { | |||
2144 | parser.push_edge (parser.current_bb->index, dest_index, | |||
2145 | EDGE_FALLTHRU, prob); | |||
2146 | return; | |||
2147 | } | |||
2148 | } | |||
2149 | tree decl = lookup_label_for_goto (loc, label); | |||
2150 | gimple_seq_add_stmt_without_update (seq, gimple_build_goto (decl)); | |||
2151 | } | |||
2152 | ||||
2153 | /* Parse a parenthesized condition. | |||
2154 | gimple-condition: | |||
2155 | ( gimple-binary-expression ) */ | |||
2156 | ||||
2157 | static tree | |||
2158 | c_parser_gimple_paren_condition (gimple_parser &parser) | |||
2159 | { | |||
2160 | if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
2161 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2162 | tree cond = c_parser_gimple_binary_expression (parser).value; | |||
2163 | if (cond != error_mark_nodeglobal_trees[TI_ERROR_MARK] | |||
2164 | && ! COMPARISON_CLASS_P (cond)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (cond)->base.code))] == tcc_comparison) | |||
2165 | && ! CONSTANT_CLASS_P (cond)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (cond)->base.code))] == tcc_constant) | |||
2166 | && ! SSA_VAR_P (cond)(((enum tree_code) (cond)->base.code) == VAR_DECL || ((enum tree_code) (cond)->base.code) == PARM_DECL || ((enum tree_code ) (cond)->base.code) == RESULT_DECL || ((enum tree_code) ( cond)->base.code) == SSA_NAME)) | |||
2167 | { | |||
2168 | c_parser_error (parser, "comparison required"); | |||
2169 | cond = error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2170 | } | |||
2171 | if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) | |||
2172 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | |||
2173 | return cond; | |||
2174 | } | |||
2175 | ||||
2176 | /* Parse gimple try statement. | |||
2177 | ||||
2178 | try-statement: | |||
2179 | try { ... } finally { ... } | |||
2180 | try { ... } finally { ... } else { ... } | |||
2181 | ||||
2182 | This could support try/catch as well, but it's not implemented yet. | |||
2183 | */ | |||
2184 | ||||
2185 | static void | |||
2186 | c_parser_gimple_try_stmt (gimple_parser &parser, gimple_seq *seq) | |||
2187 | { | |||
2188 | gimple_seq tryseq = NULLnullptr; | |||
2189 | c_parser_consume_token (parser); | |||
2190 | c_parser_gimple_compound_statement (parser, &tryseq); | |||
2191 | ||||
2192 | if ((c_parser_next_token_is (parser, CPP_KEYWORD) | |||
2193 | && c_parser_peek_token (parser)->keyword == RID_AT_FINALLY) | |||
2194 | || (c_parser_next_token_is (parser, CPP_NAME) | |||
2195 | && c_parser_peek_token (parser)->id_kind == C_ID_ID | |||
2196 | && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value)((const char *) (tree_check ((c_parser_peek_token (parser)-> value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 2196, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), | |||
2197 | "finally") == 0)) | |||
2198 | { | |||
2199 | gimple_seq finseq = NULLnullptr; | |||
2200 | c_parser_consume_token (parser); | |||
2201 | c_parser_gimple_compound_statement (parser, &finseq); | |||
2202 | ||||
2203 | if (c_parser_next_token_is (parser, CPP_KEYWORD) | |||
2204 | && c_parser_peek_token (parser)->keyword == RID_ELSE) | |||
2205 | { | |||
2206 | gimple_seq elsseq = NULLnullptr; | |||
2207 | c_parser_consume_token (parser); | |||
2208 | c_parser_gimple_compound_statement (parser, &elsseq); | |||
2209 | ||||
2210 | geh_else *stmt = gimple_build_eh_else (finseq, elsseq); | |||
2211 | finseq = NULLnullptr; | |||
2212 | gimple_seq_add_stmt_without_update (&finseq, stmt); | |||
2213 | } | |||
2214 | ||||
2215 | gtry *stmt = gimple_build_try (tryseq, finseq, GIMPLE_TRY_FINALLY); | |||
2216 | gimple_seq_add_stmt_without_update (seq, stmt); | |||
2217 | } | |||
2218 | else if (c_parser_next_token_is (parser, CPP_KEYWORD) | |||
2219 | && c_parser_peek_token (parser)->keyword == RID_AT_CATCH) | |||
2220 | c_parser_error (parser, "%<catch%> is not supported"); | |||
2221 | else | |||
2222 | c_parser_error (parser, "expected %<finally%> or %<catch%>"); | |||
2223 | } | |||
2224 | ||||
2225 | /* Parse gimple if-else statement. | |||
2226 | ||||
2227 | if-statement: | |||
2228 | if ( gimple-binary-expression ) gimple-goto-statement | |||
2229 | if ( gimple-binary-expression ) gimple-goto-statement \ | |||
2230 | else gimple-goto-statement | |||
2231 | */ | |||
2232 | ||||
2233 | static void | |||
2234 | c_parser_gimple_if_stmt (gimple_parser &parser, gimple_seq *seq) | |||
2235 | { | |||
2236 | tree t_label = NULL_TREE(tree) nullptr, f_label = NULL_TREE(tree) nullptr, label; | |||
2237 | location_t loc; | |||
2238 | c_parser_consume_token (parser); | |||
2239 | tree cond = c_parser_gimple_paren_condition (parser); | |||
2240 | ||||
2241 | if (c_parser_next_token_is_keyword (parser, RID_GOTO)) | |||
2242 | { | |||
2243 | loc = c_parser_peek_token (parser)->location; | |||
2244 | c_parser_consume_token (parser); | |||
2245 | if (! c_parser_next_token_is (parser, CPP_NAME)) | |||
2246 | { | |||
2247 | c_parser_error (parser, "expected label"); | |||
2248 | return; | |||
2249 | } | |||
2250 | label = c_parser_peek_token (parser)->value; | |||
2251 | c_parser_consume_token (parser); | |||
2252 | int dest_index; | |||
2253 | profile_probability prob; | |||
2254 | if ((cfun(cfun + 0)->curr_properties & PROP_cfg(1 << 3)) | |||
2255 | && c_parser_gimple_parse_bb_spec_edge_probability (label, parser, | |||
2256 | &dest_index, &prob)) | |||
2257 | parser.push_edge (parser.current_bb->index, dest_index, | |||
2258 | EDGE_TRUE_VALUE, prob); | |||
2259 | else | |||
2260 | t_label = lookup_label_for_goto (loc, label); | |||
2261 | if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) | |||
2262 | return; | |||
2263 | } | |||
2264 | else | |||
2265 | { | |||
2266 | c_parser_error (parser, "expected goto expression"); | |||
2267 | return; | |||
2268 | } | |||
2269 | ||||
2270 | if (c_parser_next_token_is_keyword (parser, RID_ELSE)) | |||
2271 | c_parser_consume_token (parser); | |||
2272 | else | |||
2273 | { | |||
2274 | c_parser_error (parser, "expected else statement"); | |||
2275 | return; | |||
2276 | } | |||
2277 | ||||
2278 | if (c_parser_next_token_is_keyword (parser, RID_GOTO)) | |||
2279 | { | |||
2280 | loc = c_parser_peek_token (parser)->location; | |||
2281 | c_parser_consume_token (parser); | |||
2282 | if (! c_parser_next_token_is (parser, CPP_NAME)) | |||
2283 | { | |||
2284 | c_parser_error (parser, "expected label"); | |||
2285 | return; | |||
2286 | } | |||
2287 | label = c_parser_peek_token (parser)->value; | |||
2288 | c_parser_consume_token (parser); | |||
2289 | int dest_index; | |||
2290 | profile_probability prob; | |||
2291 | if ((cfun(cfun + 0)->curr_properties & PROP_cfg(1 << 3)) | |||
2292 | && c_parser_gimple_parse_bb_spec_edge_probability (label, parser, | |||
2293 | &dest_index, &prob)) | |||
2294 | parser.push_edge (parser.current_bb->index, dest_index, | |||
2295 | EDGE_FALSE_VALUE, prob); | |||
2296 | else | |||
2297 | f_label = lookup_label_for_goto (loc, label); | |||
2298 | if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) | |||
2299 | return; | |||
2300 | } | |||
2301 | else | |||
2302 | { | |||
2303 | c_parser_error (parser, "expected goto expression"); | |||
2304 | return; | |||
2305 | } | |||
2306 | ||||
2307 | if (cond != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2308 | gimple_seq_add_stmt_without_update (seq, gimple_build_cond_from_tree (cond, t_label, | |||
2309 | f_label)); | |||
2310 | } | |||
2311 | ||||
2312 | /* Parse gimple switch-statement. | |||
2313 | ||||
2314 | gimple-switch-statement: | |||
2315 | switch (gimple-postfix-expression) gimple-case-statement | |||
2316 | ||||
2317 | gimple-case-statement: | |||
2318 | gimple-case-statement | |||
2319 | gimple-label-statement : gimple-goto-statment | |||
2320 | */ | |||
2321 | ||||
2322 | static void | |||
2323 | c_parser_gimple_switch_stmt (gimple_parser &parser, gimple_seq *seq) | |||
2324 | { | |||
2325 | c_expr cond_expr; | |||
2326 | tree case_label, label; | |||
2327 | auto_vec<tree> labels; | |||
2328 | tree default_label = NULL_TREE(tree) nullptr; | |||
2329 | c_parser_consume_token (parser); | |||
2330 | ||||
2331 | if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) | |||
2332 | return; | |||
2333 | cond_expr = c_parser_gimple_postfix_expression (parser); | |||
2334 | if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) | |||
2335 | return; | |||
2336 | ||||
2337 | if (! c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) | |||
2338 | return; | |||
2339 | ||||
2340 | while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) | |||
2341 | { | |||
2342 | if (c_parser_next_token_is (parser, CPP_EOF)) | |||
2343 | { | |||
2344 | c_parser_error (parser, "expected statement"); | |||
2345 | return; | |||
2346 | } | |||
2347 | ||||
2348 | switch (c_parser_peek_token (parser)->keyword) | |||
2349 | { | |||
2350 | case RID_CASE: | |||
2351 | { | |||
2352 | c_expr exp1; | |||
2353 | location_t loc = c_parser_peek_token (parser)->location; | |||
2354 | c_parser_consume_token (parser); | |||
2355 | ||||
2356 | if (c_parser_next_token_is (parser, CPP_NAME) | |||
2357 | || c_parser_peek_token (parser)->type == CPP_NUMBER) | |||
2358 | exp1 = c_parser_gimple_postfix_expression (parser); | |||
2359 | else | |||
2360 | { | |||
2361 | c_parser_error (parser, "expected expression"); | |||
2362 | return; | |||
2363 | } | |||
2364 | ||||
2365 | if (c_parser_next_token_is (parser, CPP_COLON)) | |||
2366 | { | |||
2367 | c_parser_consume_token (parser); | |||
2368 | if (c_parser_next_token_is (parser, CPP_NAME)) | |||
2369 | { | |||
2370 | label = c_parser_peek_token (parser)->value; | |||
2371 | c_parser_consume_token (parser); | |||
2372 | tree decl = lookup_label_for_goto (loc, label); | |||
2373 | case_label = build_case_label (exp1.value, NULL_TREE(tree) nullptr, | |||
2374 | decl); | |||
2375 | labels.safe_push (case_label); | |||
2376 | if (! c_parser_require (parser, CPP_SEMICOLON, | |||
2377 | "expected %<;%>")) | |||
2378 | return; | |||
2379 | } | |||
2380 | else if (! c_parser_require (parser, CPP_NAME, | |||
2381 | "expected label")) | |||
2382 | return; | |||
2383 | } | |||
2384 | else if (! c_parser_require (parser, CPP_SEMICOLON, | |||
2385 | "expected %<:%>")) | |||
2386 | return; | |||
2387 | break; | |||
2388 | } | |||
2389 | case RID_DEFAULT: | |||
2390 | { | |||
2391 | location_t loc = c_parser_peek_token (parser)->location; | |||
2392 | c_parser_consume_token (parser); | |||
2393 | if (c_parser_next_token_is (parser, CPP_COLON)) | |||
2394 | { | |||
2395 | c_parser_consume_token (parser); | |||
2396 | if (c_parser_next_token_is (parser, CPP_NAME)) | |||
2397 | { | |||
2398 | label = c_parser_peek_token (parser)->value; | |||
2399 | c_parser_consume_token (parser); | |||
2400 | tree decl = lookup_label_for_goto (loc, label); | |||
2401 | default_label = build_case_label (NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr, | |||
2402 | decl); | |||
2403 | if (! c_parser_require (parser, CPP_SEMICOLON, | |||
2404 | "expected %<;%>")) | |||
2405 | return; | |||
2406 | } | |||
2407 | else if (! c_parser_require (parser, CPP_NAME, | |||
2408 | "expected label")) | |||
2409 | return; | |||
2410 | } | |||
2411 | else if (! c_parser_require (parser, CPP_SEMICOLON, | |||
2412 | "expected %<:%>")) | |||
2413 | return; | |||
2414 | break; | |||
2415 | } | |||
2416 | default: | |||
2417 | c_parser_error (parser, "expected case label"); | |||
2418 | return; | |||
2419 | } | |||
2420 | ||||
2421 | } | |||
2422 | if (! c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>")) | |||
2423 | return; | |||
2424 | ||||
2425 | if (cond_expr.value != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2426 | { | |||
2427 | gswitch *s = gimple_build_switch (cond_expr.value, default_label, labels); | |||
2428 | gimple_seq_add_stmt_without_update (seq, s); | |||
2429 | } | |||
2430 | } | |||
2431 | ||||
2432 | /* Parse gimple return statement. */ | |||
2433 | ||||
2434 | static void | |||
2435 | c_parser_gimple_return_stmt (gimple_parser &parser, gimple_seq *seq) | |||
2436 | { | |||
2437 | location_t loc = c_parser_peek_token (parser)->location; | |||
2438 | gimple *ret = NULLnullptr; | |||
2439 | c_parser_consume_token (parser); | |||
2440 | if (c_parser_next_token_is (parser, CPP_SEMICOLON)) | |||
2441 | { | |||
2442 | c_finish_gimple_return (loc, NULL_TREE(tree) nullptr); | |||
2443 | ret = gimple_build_return (NULLnullptr); | |||
2444 | gimple_seq_add_stmt_without_update (seq, ret); | |||
2445 | } | |||
2446 | else | |||
2447 | { | |||
2448 | location_t xloc = c_parser_peek_token (parser)->location; | |||
2449 | c_expr expr = c_parser_gimple_unary_expression (parser); | |||
2450 | if (expr.value != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
2451 | { | |||
2452 | c_finish_gimple_return (xloc, expr.value); | |||
2453 | ret = gimple_build_return (expr.value); | |||
2454 | gimple_seq_add_stmt_without_update (seq, ret); | |||
2455 | } | |||
2456 | } | |||
2457 | } | |||
2458 | ||||
2459 | /* Support function for c_parser_gimple_return_stmt. */ | |||
2460 | ||||
2461 | static void | |||
2462 | c_finish_gimple_return (location_t loc, tree retval) | |||
2463 | { | |||
2464 | tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl))((contains_struct_check ((((contains_struct_check ((current_function_decl ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 2464, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 2464, __FUNCTION__))->typed.type); | |||
2465 | ||||
2466 | /* Use the expansion point to handle cases such as returning NULL | |||
2467 | in a function returning void. */ | |||
2468 | location_t xloc = expansion_point_location_if_in_system_header (loc); | |||
2469 | ||||
2470 | if (TREE_THIS_VOLATILE (current_function_decl)((current_function_decl)->base.volatile_flag)) | |||
2471 | warning_at (xloc, 0, | |||
2472 | "function declared %<noreturn%> has a %<return%> statement"); | |||
2473 | ||||
2474 | if (! retval) | |||
2475 | current_function_returns_null = 1; | |||
2476 | else if (valtype == 0 || TREE_CODE (valtype)((enum tree_code) (valtype)->base.code) == VOID_TYPE) | |||
2477 | { | |||
2478 | current_function_returns_null = 1; | |||
2479 | if (TREE_CODE (TREE_TYPE (retval))((enum tree_code) (((contains_struct_check ((retval), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 2479, __FUNCTION__))->typed.type))->base.code) != VOID_TYPE) | |||
2480 | { | |||
2481 | error_at | |||
2482 | (xloc, "%<return%> with a value, in function returning void"); | |||
2483 | inform (DECL_SOURCE_LOCATION (current_function_decl)((contains_struct_check ((current_function_decl), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 2483, __FUNCTION__))->decl_minimal.locus), | |||
2484 | "declared here"); | |||
2485 | } | |||
2486 | } | |||
2487 | else if (TREE_CODE (valtype)((enum tree_code) (valtype)->base.code) != TREE_CODE (TREE_TYPE (retval))((enum tree_code) (((contains_struct_check ((retval), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 2487, __FUNCTION__))->typed.type))->base.code)) | |||
2488 | { | |||
2489 | error_at | |||
2490 | (xloc, "invalid conversion in return statement"); | |||
2491 | inform (DECL_SOURCE_LOCATION (current_function_decl)((contains_struct_check ((current_function_decl), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/c/gimple-parser.cc" , 2491, __FUNCTION__))->decl_minimal.locus), | |||
2492 | "declared here"); | |||
2493 | } | |||
2494 | return; | |||
2495 | } |
1 | /* Vector API for GNU compiler. | ||||
2 | Copyright (C) 2004-2023 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.cc. */ | ||||
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 ("/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 == NULLnullptr) | ||||
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 = NULLnullptr; | ||||
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 = NULLnullptr; | ||||
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
| ||||
368 | if (!alloc) | ||||
369 | { | ||||
370 | ::ggc_free (v); | ||||
371 | v = NULLnullptr; | ||||
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 zero-initialized values for vec<T, A, L>. This is | ||||
545 | used to provide nil initializers for vec instances. Since vec must | ||||
546 | be a trivially copyable type that can be copied by memcpy and zeroed | ||||
547 | out by memset, it must have defaulted default and copy ctor and copy | ||||
548 | assignment. To initialize a vec either use value initialization | ||||
549 | (e.g., vec() or vec v{ };) or assign it the value vNULL. This isn't | ||||
550 | needed for file-scope and function-local static vectors, which are | ||||
551 | zero-initialized by default. */ | ||||
552 | struct vnull { }; | ||||
553 | constexpr vnull vNULL{ }; | ||||
554 | |||||
555 | |||||
556 | /* Embeddable vector. These vectors are suitable to be embedded | ||||
557 | in other data structures so that they can be pre-allocated in a | ||||
558 | contiguous memory block. | ||||
559 | |||||
560 | Embeddable vectors are implemented using the trailing array idiom, | ||||
561 | thus they are not resizeable without changing the address of the | ||||
562 | vector object itself. This means you cannot have variables or | ||||
563 | fields of embeddable vector type -- always use a pointer to a | ||||
564 | vector. The one exception is the final field of a structure, which | ||||
565 | could be a vector type. | ||||
566 | |||||
567 | You will have to use the embedded_size & embedded_init calls to | ||||
568 | create such objects, and they will not be resizeable (so the 'safe' | ||||
569 | allocation variants are not available). | ||||
570 | |||||
571 | Properties: | ||||
572 | |||||
573 | - The whole vector and control data are allocated in a single | ||||
574 | contiguous block. It uses the trailing-vector idiom, so | ||||
575 | allocation must reserve enough space for all the elements | ||||
576 | in the vector plus its control data. | ||||
577 | - The vector cannot be re-allocated. | ||||
578 | - The vector cannot grow nor shrink. | ||||
579 | - No indirections needed for access/manipulation. | ||||
580 | - It requires 2 words of storage (prior to vector allocation). */ | ||||
581 | |||||
582 | template<typename T, typename A> | ||||
583 | struct GTY((user)) vec<T, A, vl_embed> | ||||
584 | { | ||||
585 | public: | ||||
586 | unsigned allocated (void) const { return m_vecpfx.m_alloc; } | ||||
587 | unsigned length (void) const { return m_vecpfx.m_num; } | ||||
588 | bool is_empty (void) const { return m_vecpfx.m_num == 0; } | ||||
589 | T *address (void) { return reinterpret_cast <T *> (this + 1); } | ||||
590 | const T *address (void) const | ||||
591 | { return reinterpret_cast <const T *> (this + 1); } | ||||
592 | T *begin () { return address (); } | ||||
593 | const T *begin () const { return address (); } | ||||
594 | T *end () { return address () + length (); } | ||||
595 | const T *end () const { return address () + length (); } | ||||
596 | const T &operator[] (unsigned) const; | ||||
597 | T &operator[] (unsigned); | ||||
598 | T &last (void); | ||||
599 | bool space (unsigned) const; | ||||
600 | bool iterate (unsigned, T *) const; | ||||
601 | bool iterate (unsigned, T **) const; | ||||
602 | vec *copy (ALONE_CXX_MEM_STAT_INFO) const; | ||||
603 | void splice (const vec &); | ||||
604 | void splice (const vec *src); | ||||
605 | T *quick_push (const T &); | ||||
606 | T &pop (void); | ||||
607 | void truncate (unsigned); | ||||
608 | void quick_insert (unsigned, const T &); | ||||
609 | void ordered_remove (unsigned); | ||||
610 | void unordered_remove (unsigned); | ||||
611 | void block_remove (unsigned, unsigned); | ||||
612 | void qsort (int (*) (const void *, const void *))qsort (int (*) (const void *, const void *)); | ||||
613 | void sort (int (*) (const void *, const void *, void *), void *); | ||||
614 | void stablesort (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 (const 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 - This field should be private, but we need to cater to | ||||
634 | compilers that have stricter notions of PODness for types. */ | ||||
635 | /* Align m_vecpfx to simplify address (). */ | ||||
636 | alignas (T) alignas (vec_prefix) vec_prefix m_vecpfx; | ||||
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 () : NULLnullptr; | ||||
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 ? !vec_safe_space (v, nelems) : false; | ||||
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 = NULLnullptr; | ||||
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 ("/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) : NULLnullptr; | ||||
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 ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 882, __FUNCTION__), 0 : 0)); | ||||
883 | return address ()[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 ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 890, __FUNCTION__), 0 : 0)); | ||||
891 | return address ()[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 ("/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 (a copy of) 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; v->iterate (ix, &val); 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 = address ()[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 *, &address ()[ix])(const_cast<T *> ((&address ()[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 = NULLnullptr; | ||||
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 (), address (), 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 ("/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 ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1021, __FUNCTION__), 0 : 0)); | ||||
1022 | T *slot = &address ()[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 ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1034, __FUNCTION__), 0 : 0)); | ||||
1035 | return address ()[--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 ("/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 ("/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 ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1059, __FUNCTION__), 0 : 0)); | ||||
1060 | T *slot = &address ()[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 ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1074, __FUNCTION__), 0 : 0)); | ||||
1075 | T *slot = &address ()[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 ("/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 ("/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 ("/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 ("/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 ("/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 ("/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 ("/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 ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1121, __FUNCTION__), 0 : 0)); | ||||
1122 | T *p = address (); | ||||
1123 | p[ix] = p[--m_vecpfx.m_num]; | ||||
1124 | } | ||||
1125 | |||||
1126 | |||||
1127 | /* Remove LEN elements starting at the IXth. Ordering is retained. | ||||
1128 | This is an O(N) operation due to memmove. */ | ||||
1129 | |||||
1130 | template<typename T, typename A> | ||||
1131 | inline void | ||||
1132 | vec<T, A, vl_embed>::block_remove (unsigned ix, unsigned len) | ||||
1133 | { | ||||
1134 | gcc_checking_assert (ix + len <= length ())((void)(!(ix + len <= length ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1134, __FUNCTION__), 0 : 0)); | ||||
1135 | T *slot = &address ()[ix]; | ||||
1136 | m_vecpfx.m_num -= len; | ||||
1137 | memmove (slot, slot + len, (m_vecpfx.m_num - ix) * sizeof (T)); | ||||
1138 | } | ||||
1139 | |||||
1140 | |||||
1141 | /* Sort the contents of this vector with qsort. CMP is the comparison | ||||
1142 | function to pass to qsort. */ | ||||
1143 | |||||
1144 | template<typename T, typename A> | ||||
1145 | inline void | ||||
1146 | vec<T, A, vl_embed>::qsort (int (*cmp) (const void *, const void *))qsort (int (*cmp) (const void *, const void *)) | ||||
1147 | { | ||||
1148 | if (length () > 1) | ||||
1149 | gcc_qsort (address (), length (), sizeof (T), cmp); | ||||
1150 | } | ||||
1151 | |||||
1152 | /* Sort the contents of this vector with qsort. CMP is the comparison | ||||
1153 | function to pass to qsort. */ | ||||
1154 | |||||
1155 | template<typename T, typename A> | ||||
1156 | inline void | ||||
1157 | vec<T, A, vl_embed>::sort (int (*cmp) (const void *, const void *, void *), | ||||
1158 | void *data) | ||||
1159 | { | ||||
1160 | if (length () > 1) | ||||
1161 | gcc_sort_r (address (), length (), sizeof (T), cmp, data); | ||||
1162 | } | ||||
1163 | |||||
1164 | /* Sort the contents of this vector with gcc_stablesort_r. CMP is the | ||||
1165 | comparison function to pass to qsort. */ | ||||
1166 | |||||
1167 | template<typename T, typename A> | ||||
1168 | inline void | ||||
1169 | vec<T, A, vl_embed>::stablesort (int (*cmp) (const void *, const void *, | ||||
1170 | void *), void *data) | ||||
1171 | { | ||||
1172 | if (length () > 1) | ||||
1173 | gcc_stablesort_r (address (), length (), sizeof (T), cmp, data); | ||||
1174 | } | ||||
1175 | |||||
1176 | /* Search the contents of the sorted vector with a binary search. | ||||
1177 | CMP is the comparison function to pass to bsearch. */ | ||||
1178 | |||||
1179 | template<typename T, typename A> | ||||
1180 | inline T * | ||||
1181 | vec<T, A, vl_embed>::bsearch (const void *key, | ||||
1182 | int (*compar) (const void *, const void *)) | ||||
1183 | { | ||||
1184 | const void *base = this->address (); | ||||
1185 | size_t nmemb = this->length (); | ||||
1186 | size_t size = sizeof (T); | ||||
1187 | /* The following is a copy of glibc stdlib-bsearch.h. */ | ||||
1188 | size_t l, u, idx; | ||||
1189 | const void *p; | ||||
1190 | int comparison; | ||||
1191 | |||||
1192 | l = 0; | ||||
1193 | u = nmemb; | ||||
1194 | while (l < u) | ||||
1195 | { | ||||
1196 | idx = (l + u) / 2; | ||||
1197 | p = (const void *) (((const char *) base) + (idx * size)); | ||||
1198 | comparison = (*compar) (key, p); | ||||
1199 | if (comparison < 0) | ||||
1200 | u = idx; | ||||
1201 | else if (comparison > 0) | ||||
1202 | l = idx + 1; | ||||
1203 | else | ||||
1204 | return (T *)const_cast<void *>(p); | ||||
1205 | } | ||||
1206 | |||||
1207 | return NULLnullptr; | ||||
1208 | } | ||||
1209 | |||||
1210 | /* Search the contents of the sorted vector with a binary search. | ||||
1211 | CMP is the comparison function to pass to bsearch. */ | ||||
1212 | |||||
1213 | template<typename T, typename A> | ||||
1214 | inline T * | ||||
1215 | vec<T, A, vl_embed>::bsearch (const void *key, | ||||
1216 | int (*compar) (const void *, const void *, | ||||
1217 | void *), void *data) | ||||
1218 | { | ||||
1219 | const void *base = this->address (); | ||||
1220 | size_t nmemb = this->length (); | ||||
1221 | size_t size = sizeof (T); | ||||
1222 | /* The following is a copy of glibc stdlib-bsearch.h. */ | ||||
1223 | size_t l, u, idx; | ||||
1224 | const void *p; | ||||
1225 | int comparison; | ||||
1226 | |||||
1227 | l = 0; | ||||
1228 | u = nmemb; | ||||
1229 | while (l < u) | ||||
1230 | { | ||||
1231 | idx = (l + u) / 2; | ||||
1232 | p = (const void *) (((const char *) base) + (idx * size)); | ||||
1233 | comparison = (*compar) (key, p, data); | ||||
1234 | if (comparison < 0) | ||||
1235 | u = idx; | ||||
1236 | else if (comparison > 0) | ||||
1237 | l = idx + 1; | ||||
1238 | else | ||||
1239 | return (T *)const_cast<void *>(p); | ||||
1240 | } | ||||
1241 | |||||
1242 | return NULLnullptr; | ||||
1243 | } | ||||
1244 | |||||
1245 | /* Return true if SEARCH is an element of V. Note that this is O(N) in the | ||||
1246 | size of the vector and so should be used with care. */ | ||||
1247 | |||||
1248 | template<typename T, typename A> | ||||
1249 | inline bool | ||||
1250 | vec<T, A, vl_embed>::contains (const T &search) const | ||||
1251 | { | ||||
1252 | unsigned int len = length (); | ||||
1253 | const T *p = address (); | ||||
1254 | for (unsigned int i = 0; i < len; i++) | ||||
1255 | { | ||||
1256 | const T *slot = &p[i]; | ||||
1257 | if (*slot == search) | ||||
1258 | return true; | ||||
1259 | } | ||||
1260 | |||||
1261 | return false; | ||||
1262 | } | ||||
1263 | |||||
1264 | /* Find and return the first position in which OBJ could be inserted | ||||
1265 | without changing the ordering of this vector. LESSTHAN is a | ||||
1266 | function that returns true if the first argument is strictly less | ||||
1267 | than the second. */ | ||||
1268 | |||||
1269 | template<typename T, typename A> | ||||
1270 | unsigned | ||||
1271 | vec<T, A, vl_embed>::lower_bound (const T &obj, | ||||
1272 | bool (*lessthan)(const T &, const T &)) | ||||
1273 | const | ||||
1274 | { | ||||
1275 | unsigned int len = length (); | ||||
1276 | unsigned int half, middle; | ||||
1277 | unsigned int first = 0; | ||||
1278 | while (len > 0) | ||||
1279 | { | ||||
1280 | half = len / 2; | ||||
1281 | middle = first; | ||||
1282 | middle += half; | ||||
1283 | const T &middle_elem = address ()[middle]; | ||||
1284 | if (lessthan (middle_elem, obj)) | ||||
1285 | { | ||||
1286 | first = middle; | ||||
1287 | ++first; | ||||
1288 | len = len - half - 1; | ||||
1289 | } | ||||
1290 | else | ||||
1291 | len = half; | ||||
1292 | } | ||||
1293 | return first; | ||||
1294 | } | ||||
1295 | |||||
1296 | |||||
1297 | /* Return the number of bytes needed to embed an instance of an | ||||
1298 | embeddable vec inside another data structure. | ||||
1299 | |||||
1300 | Use these methods to determine the required size and initialization | ||||
1301 | of a vector V of type T embedded within another structure (as the | ||||
1302 | final member): | ||||
1303 | |||||
1304 | size_t vec<T, A, vl_embed>::embedded_size (unsigned alloc); | ||||
1305 | void v->embedded_init (unsigned alloc, unsigned num); | ||||
1306 | |||||
1307 | These allow the caller to perform the memory allocation. */ | ||||
1308 | |||||
1309 | template<typename T, typename A> | ||||
1310 | inline size_t | ||||
1311 | vec<T, A, vl_embed>::embedded_size (unsigned alloc) | ||||
1312 | { | ||||
1313 | struct alignas (T) U { char data[sizeof (T)]; }; | ||||
1314 | typedef vec<U, A, vl_embed> vec_embedded; | ||||
1315 | typedef typename std::conditional<std::is_standard_layout<T>::value, | ||||
1316 | vec, vec_embedded>::type vec_stdlayout; | ||||
1317 | static_assert (sizeof (vec_stdlayout) == sizeof (vec), ""); | ||||
1318 | static_assert (alignof (vec_stdlayout) == alignof (vec), ""); | ||||
1319 | return sizeof (vec_stdlayout) + alloc * sizeof (T); | ||||
1320 | } | ||||
1321 | |||||
1322 | |||||
1323 | /* Initialize the vector to contain room for ALLOC elements and | ||||
1324 | NUM active elements. */ | ||||
1325 | |||||
1326 | template<typename T, typename A> | ||||
1327 | inline void | ||||
1328 | vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num, unsigned aut) | ||||
1329 | { | ||||
1330 | m_vecpfx.m_alloc = alloc; | ||||
1331 | m_vecpfx.m_using_auto_storage = aut; | ||||
1332 | m_vecpfx.m_num = num; | ||||
1333 | } | ||||
1334 | |||||
1335 | |||||
1336 | /* Grow the vector to a specific length. LEN must be as long or longer than | ||||
1337 | the current length. The new elements are uninitialized. */ | ||||
1338 | |||||
1339 | template<typename T, typename A> | ||||
1340 | inline void | ||||
1341 | vec<T, A, vl_embed>::quick_grow (unsigned len) | ||||
1342 | { | ||||
1343 | gcc_checking_assert (length () <= len && len <= m_vecpfx.m_alloc)((void)(!(length () <= len && len <= m_vecpfx.m_alloc ) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1343, __FUNCTION__), 0 : 0)); | ||||
1344 | m_vecpfx.m_num = len; | ||||
1345 | } | ||||
1346 | |||||
1347 | |||||
1348 | /* Grow the vector to a specific length. LEN must be as long or longer than | ||||
1349 | the current length. The new elements are initialized to zero. */ | ||||
1350 | |||||
1351 | template<typename T, typename A> | ||||
1352 | inline void | ||||
1353 | vec<T, A, vl_embed>::quick_grow_cleared (unsigned len) | ||||
1354 | { | ||||
1355 | unsigned oldlen = length (); | ||||
1356 | size_t growby = len - oldlen; | ||||
1357 | quick_grow (len); | ||||
1358 | if (growby != 0) | ||||
1359 | vec_default_construct (address () + oldlen, growby); | ||||
1360 | } | ||||
1361 | |||||
1362 | /* Garbage collection support for vec<T, A, vl_embed>. */ | ||||
1363 | |||||
1364 | template<typename T> | ||||
1365 | void | ||||
1366 | gt_ggc_mx (vec<T, va_gc> *v) | ||||
1367 | { | ||||
1368 | extern void gt_ggc_mx (T &); | ||||
1369 | for (unsigned i = 0; i < v->length (); i++) | ||||
1370 | gt_ggc_mx ((*v)[i]); | ||||
1371 | } | ||||
1372 | |||||
1373 | template<typename T> | ||||
1374 | void | ||||
1375 | gt_ggc_mx (vec<T, va_gc_atomic, vl_embed> *v ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | ||||
1376 | { | ||||
1377 | /* Nothing to do. Vectors of atomic types wrt GC do not need to | ||||
1378 | be traversed. */ | ||||
1379 | } | ||||
1380 | |||||
1381 | |||||
1382 | /* PCH support for vec<T, A, vl_embed>. */ | ||||
1383 | |||||
1384 | template<typename T, typename A> | ||||
1385 | void | ||||
1386 | gt_pch_nx (vec<T, A, vl_embed> *v) | ||||
1387 | { | ||||
1388 | extern void gt_pch_nx (T &); | ||||
1389 | for (unsigned i = 0; i < v->length (); i++) | ||||
1390 | gt_pch_nx ((*v)[i]); | ||||
1391 | } | ||||
1392 | |||||
1393 | template<typename T, typename A> | ||||
1394 | void | ||||
1395 | gt_pch_nx (vec<T *, A, vl_embed> *v, gt_pointer_operator op, void *cookie) | ||||
1396 | { | ||||
1397 | for (unsigned i = 0; i < v->length (); i++) | ||||
1398 | op (&((*v)[i]), NULLnullptr, cookie); | ||||
1399 | } | ||||
1400 | |||||
1401 | template<typename T, typename A> | ||||
1402 | void | ||||
1403 | gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie) | ||||
1404 | { | ||||
1405 | extern void gt_pch_nx (T *, gt_pointer_operator, void *); | ||||
1406 | for (unsigned i = 0; i < v->length (); i++) | ||||
1407 | gt_pch_nx (&((*v)[i]), op, cookie); | ||||
1408 | } | ||||
1409 | |||||
1410 | |||||
1411 | /* Space efficient vector. These vectors can grow dynamically and are | ||||
1412 | allocated together with their control data. They are suited to be | ||||
1413 | included in data structures. Prior to initial allocation, they | ||||
1414 | only take a single word of storage. | ||||
1415 | |||||
1416 | These vectors are implemented as a pointer to an embeddable vector. | ||||
1417 | The semantics allow for this pointer to be NULL to represent empty | ||||
1418 | vectors. This way, empty vectors occupy minimal space in the | ||||
1419 | structure containing them. | ||||
1420 | |||||
1421 | Properties: | ||||
1422 | |||||
1423 | - The whole vector and control data are allocated in a single | ||||
1424 | contiguous block. | ||||
1425 | - The whole vector may be re-allocated. | ||||
1426 | - Vector data may grow and shrink. | ||||
1427 | - Access and manipulation requires a pointer test and | ||||
1428 | indirection. | ||||
1429 | - It requires 1 word of storage (prior to vector allocation). | ||||
1430 | |||||
1431 | |||||
1432 | Limitations: | ||||
1433 | |||||
1434 | These vectors must be PODs because they are stored in unions. | ||||
1435 | (http://en.wikipedia.org/wiki/Plain_old_data_structures). | ||||
1436 | As long as we use C++03, we cannot have constructors nor | ||||
1437 | destructors in classes that are stored in unions. */ | ||||
1438 | |||||
1439 | template<typename T, size_t N = 0> | ||||
1440 | class auto_vec; | ||||
1441 | |||||
1442 | template<typename T> | ||||
1443 | struct vec<T, va_heap, vl_ptr> | ||||
1444 | { | ||||
1445 | public: | ||||
1446 | /* Default ctors to ensure triviality. Use value-initialization | ||||
1447 | (e.g., vec() or vec v{ };) or vNULL to create a zero-initialized | ||||
1448 | instance. */ | ||||
1449 | vec () = default; | ||||
1450 | vec (const vec &) = default; | ||||
1451 | /* Initialization from the generic vNULL. */ | ||||
1452 | vec (vnull): m_vec () { } | ||||
1453 | /* Same as default ctor: vec storage must be released manually. */ | ||||
1454 | ~vec () = default; | ||||
1455 | |||||
1456 | /* Defaulted same as copy ctor. */ | ||||
1457 | vec& operator= (const vec &) = default; | ||||
1458 | |||||
1459 | /* Prevent implicit conversion from auto_vec. Use auto_vec::to_vec() | ||||
1460 | instead. */ | ||||
1461 | template <size_t N> | ||||
1462 | vec (auto_vec<T, N> &) = delete; | ||||
1463 | |||||
1464 | template <size_t N> | ||||
1465 | void operator= (auto_vec<T, N> &) = delete; | ||||
1466 | |||||
1467 | /* Memory allocation and deallocation for the embedded vector. | ||||
1468 | Needed because we cannot have proper ctors/dtors defined. */ | ||||
1469 | void create (unsigned nelems CXX_MEM_STAT_INFO); | ||||
1470 | void release (void); | ||||
1471 | |||||
1472 | /* Vector operations. */ | ||||
1473 | bool exists (void) const | ||||
1474 | { return m_vec != NULLnullptr; } | ||||
1475 | |||||
1476 | bool is_empty (void) const | ||||
1477 | { return m_vec ? m_vec->is_empty () : true; } | ||||
1478 | |||||
1479 | unsigned allocated (void) const | ||||
1480 | { return m_vec ? m_vec->allocated () : 0; } | ||||
1481 | |||||
1482 | unsigned length (void) const | ||||
1483 | { return m_vec ? m_vec->length () : 0; } | ||||
1484 | |||||
1485 | T *address (void) | ||||
1486 | { return m_vec ? m_vec->address () : NULLnullptr; } | ||||
1487 | |||||
1488 | const T *address (void) const | ||||
1489 | { return m_vec ? m_vec->address () : NULLnullptr; } | ||||
1490 | |||||
1491 | T *begin () { return address (); } | ||||
1492 | const T *begin () const { return address (); } | ||||
1493 | T *end () { return begin () + length (); } | ||||
1494 | const T *end () const { return begin () + length (); } | ||||
1495 | const T &operator[] (unsigned ix) const | ||||
1496 | { return (*m_vec)[ix]; } | ||||
1497 | |||||
1498 | bool operator!=(const vec &other) const | ||||
1499 | { return !(*this == other); } | ||||
1500 | |||||
1501 | bool operator==(const vec &other) const | ||||
1502 | { return address () == other.address (); } | ||||
1503 | |||||
1504 | T &operator[] (unsigned ix) | ||||
1505 | { return (*m_vec)[ix]; } | ||||
1506 | |||||
1507 | T &last (void) | ||||
1508 | { return m_vec->last (); } | ||||
1509 | |||||
1510 | bool space (int nelems) const | ||||
1511 | { return m_vec ? m_vec->space (nelems) : nelems == 0; } | ||||
1512 | |||||
1513 | bool iterate (unsigned ix, T *p) const; | ||||
1514 | bool iterate (unsigned ix, T **p) const; | ||||
1515 | vec copy (ALONE_CXX_MEM_STAT_INFO) const; | ||||
1516 | bool reserve (unsigned, bool = false CXX_MEM_STAT_INFO); | ||||
1517 | bool reserve_exact (unsigned CXX_MEM_STAT_INFO); | ||||
1518 | void splice (const vec &); | ||||
1519 | void safe_splice (const vec & CXX_MEM_STAT_INFO); | ||||
1520 | T *quick_push (const T &); | ||||
1521 | T *safe_push (const T &CXX_MEM_STAT_INFO); | ||||
1522 | T &pop (void); | ||||
1523 | void truncate (unsigned); | ||||
1524 | void safe_grow (unsigned, bool = false CXX_MEM_STAT_INFO); | ||||
1525 | void safe_grow_cleared (unsigned, bool = false CXX_MEM_STAT_INFO); | ||||
1526 | void quick_grow (unsigned); | ||||
1527 | void quick_grow_cleared (unsigned); | ||||
1528 | void quick_insert (unsigned, const T &); | ||||
1529 | void safe_insert (unsigned, const T & CXX_MEM_STAT_INFO); | ||||
1530 | void ordered_remove (unsigned); | ||||
1531 | void unordered_remove (unsigned); | ||||
1532 | void block_remove (unsigned, unsigned); | ||||
1533 | void qsort (int (*) (const void *, const void *))qsort (int (*) (const void *, const void *)); | ||||
1534 | void sort (int (*) (const void *, const void *, void *), void *); | ||||
1535 | void stablesort (int (*) (const void *, const void *, void *), void *); | ||||
1536 | T *bsearch (const void *key, int (*compar)(const void *, const void *)); | ||||
1537 | T *bsearch (const void *key, | ||||
1538 | int (*compar)(const void *, const void *, void *), void *); | ||||
1539 | unsigned lower_bound (T, bool (*)(const T &, const T &)) const; | ||||
1540 | bool contains (const T &search) const; | ||||
1541 | void reverse (void); | ||||
1542 | |||||
1543 | bool using_auto_storage () const; | ||||
1544 | |||||
1545 | /* FIXME - This field should be private, but we need to cater to | ||||
1546 | compilers that have stricter notions of PODness for types. */ | ||||
1547 | vec<T, va_heap, vl_embed> *m_vec; | ||||
1548 | }; | ||||
1549 | |||||
1550 | |||||
1551 | /* auto_vec is a subclass of vec that automatically manages creating and | ||||
1552 | releasing the internal vector. If N is non zero then it has N elements of | ||||
1553 | internal storage. The default is no internal storage, and you probably only | ||||
1554 | want to ask for internal storage for vectors on the stack because if the | ||||
1555 | size of the vector is larger than the internal storage that space is wasted. | ||||
1556 | */ | ||||
1557 | template<typename T, size_t N /* = 0 */> | ||||
1558 | class auto_vec : public vec<T, va_heap> | ||||
1559 | { | ||||
1560 | public: | ||||
1561 | auto_vec () | ||||
1562 | { | ||||
1563 | m_auto.embedded_init (N, 0, 1); | ||||
1564 | /* ??? Instead of initializing m_vec from &m_auto directly use an | ||||
1565 | expression that avoids refering to a specific member of 'this' | ||||
1566 | to derail the -Wstringop-overflow diagnostic code, avoiding | ||||
1567 | the impression that data accesses are supposed to be to the | ||||
1568 | m_auto member storage. */ | ||||
1569 | size_t off = (char *) &m_auto - (char *) this; | ||||
1570 | this->m_vec = (vec<T, va_heap, vl_embed> *) ((char *) this + off); | ||||
1571 | } | ||||
1572 | |||||
1573 | auto_vec (size_t s CXX_MEM_STAT_INFO) | ||||
1574 | { | ||||
1575 | if (s > N) | ||||
1576 | { | ||||
1577 | this->create (s PASS_MEM_STAT); | ||||
1578 | return; | ||||
1579 | } | ||||
1580 | |||||
1581 | m_auto.embedded_init (N, 0, 1); | ||||
1582 | /* ??? See above. */ | ||||
1583 | size_t off = (char *) &m_auto - (char *) this; | ||||
1584 | this->m_vec = (vec<T, va_heap, vl_embed> *) ((char *) this + off); | ||||
1585 | } | ||||
1586 | |||||
1587 | ~auto_vec () | ||||
1588 | { | ||||
1589 | this->release (); | ||||
1590 | } | ||||
1591 | |||||
1592 | /* Explicitly convert to the base class. There is no conversion | ||||
1593 | from a const auto_vec because a copy of the returned vec can | ||||
1594 | be used to modify *THIS. | ||||
1595 | This is a legacy function not to be used in new code. */ | ||||
1596 | vec<T, va_heap> to_vec_legacy () { | ||||
1597 | return *static_cast<vec<T, va_heap> *>(this); | ||||
1598 | } | ||||
1599 | |||||
1600 | private: | ||||
1601 | vec<T, va_heap, vl_embed> m_auto; | ||||
1602 | unsigned char m_data[sizeof (T) * N]; | ||||
1603 | }; | ||||
1604 | |||||
1605 | /* auto_vec is a sub class of vec whose storage is released when it is | ||||
1606 | destroyed. */ | ||||
1607 | template<typename T> | ||||
1608 | class auto_vec<T, 0> : public vec<T, va_heap> | ||||
1609 | { | ||||
1610 | public: | ||||
1611 | auto_vec () { this->m_vec = NULLnullptr; } | ||||
1612 | auto_vec (size_t n CXX_MEM_STAT_INFO) { this->create (n PASS_MEM_STAT); } | ||||
1613 | ~auto_vec () { this->release (); } | ||||
1614 | |||||
1615 | auto_vec (vec<T, va_heap>&& r) | ||||
1616 | { | ||||
1617 | gcc_assert (!r.using_auto_storage ())((void)(!(!r.using_auto_storage ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1617, __FUNCTION__), 0 : 0)); | ||||
1618 | this->m_vec = r.m_vec; | ||||
1619 | r.m_vec = NULLnullptr; | ||||
1620 | } | ||||
1621 | |||||
1622 | auto_vec (auto_vec<T> &&r) | ||||
1623 | { | ||||
1624 | gcc_assert (!r.using_auto_storage ())((void)(!(!r.using_auto_storage ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1624, __FUNCTION__), 0 : 0)); | ||||
1625 | this->m_vec = r.m_vec; | ||||
1626 | r.m_vec = NULLnullptr; | ||||
1627 | } | ||||
1628 | |||||
1629 | auto_vec& operator= (vec<T, va_heap>&& r) | ||||
1630 | { | ||||
1631 | if (this == &r) | ||||
1632 | return *this; | ||||
1633 | |||||
1634 | gcc_assert (!r.using_auto_storage ())((void)(!(!r.using_auto_storage ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1634, __FUNCTION__), 0 : 0)); | ||||
1635 | this->release (); | ||||
1636 | this->m_vec = r.m_vec; | ||||
1637 | r.m_vec = NULLnullptr; | ||||
1638 | return *this; | ||||
1639 | } | ||||
1640 | |||||
1641 | auto_vec& operator= (auto_vec<T> &&r) | ||||
1642 | { | ||||
1643 | if (this == &r) | ||||
1644 | return *this; | ||||
1645 | |||||
1646 | gcc_assert (!r.using_auto_storage ())((void)(!(!r.using_auto_storage ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 1646, __FUNCTION__), 0 : 0)); | ||||
1647 | this->release (); | ||||
1648 | this->m_vec = r.m_vec; | ||||
1649 | r.m_vec = NULLnullptr; | ||||
1650 | return *this; | ||||
1651 | } | ||||
1652 | |||||
1653 | /* Explicitly convert to the base class. There is no conversion | ||||
1654 | from a const auto_vec because a copy of the returned vec can | ||||
1655 | be used to modify *THIS. | ||||
1656 | This is a legacy function not to be used in new code. */ | ||||
1657 | vec<T, va_heap> to_vec_legacy () { | ||||
1658 | return *static_cast<vec<T, va_heap> *>(this); | ||||
1659 | } | ||||
1660 | |||||
1661 | // You probably don't want to copy a vector, so these are deleted to prevent | ||||
1662 | // unintentional use. If you really need a copy of the vectors contents you | ||||
1663 | // can use copy (). | ||||
1664 | auto_vec(const auto_vec &) = delete; | ||||
1665 | auto_vec &operator= (const auto_vec &) = delete; | ||||
1666 | }; | ||||
1667 | |||||
1668 | |||||
1669 | /* Allocate heap memory for pointer V and create the internal vector | ||||
1670 | with space for NELEMS elements. If NELEMS is 0, the internal | ||||
1671 | vector is initialized to empty. */ | ||||
1672 | |||||
1673 | template<typename T> | ||||
1674 | inline void | ||||
1675 | vec_alloc (vec<T> *&v, unsigned nelems CXX_MEM_STAT_INFO) | ||||
1676 | { | ||||
1677 | v = new vec<T>; | ||||
1678 | v->create (nelems PASS_MEM_STAT); | ||||
1679 | } | ||||
1680 | |||||
1681 | |||||
1682 | /* A subclass of auto_vec <char *> that frees all of its elements on | ||||
1683 | deletion. */ | ||||
1684 | |||||
1685 | class auto_string_vec : public auto_vec <char *> | ||||
1686 | { | ||||
1687 | public: | ||||
1688 | ~auto_string_vec (); | ||||
1689 | }; | ||||
1690 | |||||
1691 | /* A subclass of auto_vec <T *> that deletes all of its elements on | ||||
1692 | destruction. | ||||
1693 | |||||
1694 | This is a crude way for a vec to "own" the objects it points to | ||||
1695 | and clean up automatically. | ||||
1696 | |||||
1697 | For example, no attempt is made to delete elements when an item | ||||
1698 | within the vec is overwritten. | ||||
1699 | |||||
1700 | We can't rely on gnu::unique_ptr within a container, | ||||
1701 | since we can't rely on move semantics in C++98. */ | ||||
1702 | |||||
1703 | template <typename T> | ||||
1704 | class auto_delete_vec : public auto_vec <T *> | ||||
1705 | { | ||||
1706 | public: | ||||
1707 | auto_delete_vec () {} | ||||
1708 | auto_delete_vec (size_t s) : auto_vec <T *> (s) {} | ||||
1709 | |||||
1710 | ~auto_delete_vec (); | ||||
1711 | |||||
1712 | private: | ||||
1713 | DISABLE_COPY_AND_ASSIGN(auto_delete_vec)auto_delete_vec (const auto_delete_vec&) = delete; void operator = (const auto_delete_vec &) = delete; | ||||
1714 | }; | ||||
1715 | |||||
1716 | /* Conditionally allocate heap memory for VEC and its internal vector. */ | ||||
1717 | |||||
1718 | template<typename T> | ||||
1719 | inline void | ||||
1720 | vec_check_alloc (vec<T, va_heap> *&vec, unsigned nelems CXX_MEM_STAT_INFO) | ||||
1721 | { | ||||
1722 | if (!vec) | ||||
1723 | vec_alloc (vec, nelems PASS_MEM_STAT); | ||||
1724 | } | ||||
1725 | |||||
1726 | |||||
1727 | /* Free the heap memory allocated by vector V and set it to NULL. */ | ||||
1728 | |||||
1729 | template<typename T> | ||||
1730 | inline void | ||||
1731 | vec_free (vec<T> *&v) | ||||
1732 | { | ||||
1733 | if (v == NULLnullptr) | ||||
1734 | return; | ||||
1735 | |||||
1736 | v->release (); | ||||
1737 | delete v; | ||||
1738 | v = NULLnullptr; | ||||
1739 | } | ||||
1740 | |||||
1741 | |||||
1742 | /* Return iteration condition and update PTR to point to the IX'th | ||||
1743 | element of this vector. Use this to iterate over the elements of a | ||||
1744 | vector as follows, | ||||
1745 | |||||
1746 | for (ix = 0; v.iterate (ix, &ptr); ix++) | ||||
1747 | continue; */ | ||||
1748 | |||||
1749 | template<typename T> | ||||
1750 | inline bool | ||||
1751 | vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T *ptr) const | ||||
1752 | { | ||||
1753 | if (m_vec) | ||||
1754 | return m_vec->iterate (ix, ptr); | ||||
1755 | else | ||||
1756 | { | ||||
1757 | *ptr = 0; | ||||
1758 | return false; | ||||
1759 | } | ||||
1760 | } | ||||
1761 | |||||
1762 | |||||
1763 | /* Return iteration condition and update *PTR to point to the | ||||
1764 | IX'th element of this vector. Use this to iterate over the | ||||
1765 | elements of a vector as follows, | ||||
1766 | |||||
1767 | for (ix = 0; v->iterate (ix, &ptr); ix++) | ||||
1768 | continue; | ||||
1769 | |||||
1770 | This variant is for vectors of objects. */ | ||||
1771 | |||||
1772 | template<typename T> | ||||
1773 | inline bool | ||||
1774 | vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T **ptr) const | ||||
1775 | { | ||||
1776 | if (m_vec) | ||||
1777 | return m_vec->iterate (ix, ptr); | ||||
1778 | else | ||||
1779 | { | ||||
1780 | *ptr = 0; | ||||
1781 | return false; | ||||
1782 | } | ||||
1783 | } | ||||
1784 | |||||
1785 | |||||
1786 | /* Convenience macro for forward iteration. */ | ||||
1787 | #define FOR_EACH_VEC_ELT(V, I, P)for (I = 0; (V).iterate ((I), &(P)); ++(I)) \ | ||||
1788 | for (I = 0; (V).iterate ((I), &(P)); ++(I)) | ||||
1789 | |||||
1790 | #define FOR_EACH_VEC_SAFE_ELT(V, I, P)for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I)) \ | ||||
1791 | for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I)) | ||||
1792 | |||||
1793 | /* Likewise, but start from FROM rather than 0. */ | ||||
1794 | #define FOR_EACH_VEC_ELT_FROM(V, I, P, FROM)for (I = (FROM); (V).iterate ((I), &(P)); ++(I)) \ | ||||
1795 | for (I = (FROM); (V).iterate ((I), &(P)); ++(I)) | ||||
1796 | |||||
1797 | /* Convenience macro for reverse iteration. */ | ||||
1798 | #define FOR_EACH_VEC_ELT_REVERSE(V, I, P)for (I = (V).length () - 1; (V).iterate ((I), &(P)); (I)-- ) \ | ||||
1799 | for (I = (V).length () - 1; \ | ||||
1800 | (V).iterate ((I), &(P)); \ | ||||
1801 | (I)--) | ||||
1802 | |||||
1803 | #define FOR_EACH_VEC_SAFE_ELT_REVERSE(V, I, P)for (I = vec_safe_length (V) - 1; vec_safe_iterate ((V), (I), &(P)); (I)--) \ | ||||
1804 | for (I = vec_safe_length (V) - 1; \ | ||||
1805 | vec_safe_iterate ((V), (I), &(P)); \ | ||||
1806 | (I)--) | ||||
1807 | |||||
1808 | /* auto_string_vec's dtor, freeing all contained strings, automatically | ||||
1809 | chaining up to ~auto_vec <char *>, which frees the internal buffer. */ | ||||
1810 | |||||
1811 | inline | ||||
1812 | auto_string_vec::~auto_string_vec () | ||||
1813 | { | ||||
1814 | int i; | ||||
1815 | char *str; | ||||
1816 | FOR_EACH_VEC_ELT (*this, i, str)for (i = 0; (*this).iterate ((i), &(str)); ++(i)) | ||||
1817 | free (str); | ||||
1818 | } | ||||
1819 | |||||
1820 | /* auto_delete_vec's dtor, deleting all contained items, automatically | ||||
1821 | chaining up to ~auto_vec <T*>, which frees the internal buffer. */ | ||||
1822 | |||||
1823 | template <typename T> | ||||
1824 | inline | ||||
1825 | auto_delete_vec<T>::~auto_delete_vec () | ||||
1826 | { | ||||
1827 | int i; | ||||
1828 | T *item; | ||||
1829 | FOR_EACH_VEC_ELT (*this, i, item)for (i = 0; (*this).iterate ((i), &(item)); ++(i)) | ||||
1830 | delete item; | ||||
1831 | } | ||||
1832 | |||||
1833 | |||||
1834 | /* Return a copy of this vector. */ | ||||
1835 | |||||
1836 | template<typename T> | ||||
1837 | inline vec<T, va_heap, vl_ptr> | ||||
1838 | vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECLvoid) const | ||||
1839 | { | ||||
1840 | vec<T, va_heap, vl_ptr> new_vec{ }; | ||||
1841 | if (length ()) | ||||
1842 | new_vec.m_vec = m_vec->copy (ALONE_PASS_MEM_STAT); | ||||
1843 | return new_vec; | ||||
1844 | } | ||||
1845 | |||||
1846 | |||||
1847 | /* Ensure that the vector has at least RESERVE slots available (if | ||||
1848 | EXACT is false), or exactly RESERVE slots available (if EXACT is | ||||
1849 | true). | ||||
1850 | |||||
1851 | This may create additional headroom if EXACT is false. | ||||
1852 | |||||
1853 | Note that this can cause the embedded vector to be reallocated. | ||||
1854 | Returns true iff reallocation actually occurred. */ | ||||
1855 | |||||
1856 | template<typename T> | ||||
1857 | inline bool | ||||
1858 | vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL) | ||||
1859 | { | ||||
1860 | if (space (nelems)) | ||||
1861 | return false; | ||||
1862 | |||||
1863 | /* For now play a game with va_heap::reserve to hide our auto storage if any, | ||||
1864 | this is necessary because it doesn't have enough information to know the | ||||
1865 | embedded vector is in auto storage, and so should not be freed. */ | ||||
1866 | vec<T, va_heap, vl_embed> *oldvec = m_vec; | ||||
1867 | unsigned int oldsize = 0; | ||||
1868 | bool handle_auto_vec = m_vec && using_auto_storage (); | ||||
1869 | if (handle_auto_vec) | ||||
1870 | { | ||||
1871 | m_vec = NULLnullptr; | ||||
1872 | oldsize = oldvec->length (); | ||||
1873 | nelems += oldsize; | ||||
1874 | } | ||||
1875 | |||||
1876 | va_heap::reserve (m_vec, nelems, exact PASS_MEM_STAT); | ||||
1877 | if (handle_auto_vec) | ||||
1878 | { | ||||
1879 | vec_copy_construct (m_vec->address (), oldvec->address (), oldsize); | ||||
1880 | m_vec->m_vecpfx.m_num = oldsize; | ||||
1881 | } | ||||
1882 | |||||
1883 | return true; | ||||
1884 | } | ||||
1885 | |||||
1886 | |||||
1887 | /* Ensure that this vector has exactly NELEMS slots available. This | ||||
1888 | will not create additional headroom. Note this can cause the | ||||
1889 | embedded vector to be reallocated. Returns true iff reallocation | ||||
1890 | actually occurred. */ | ||||
1891 | |||||
1892 | template<typename T> | ||||
1893 | inline bool | ||||
1894 | vec<T, va_heap, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL) | ||||
1895 | { | ||||
1896 | return reserve (nelems, true PASS_MEM_STAT); | ||||
1897 | } | ||||
1898 | |||||
1899 | |||||
1900 | /* Create the internal vector and reserve NELEMS for it. This is | ||||
1901 | exactly like vec::reserve, but the internal vector is | ||||
1902 | unconditionally allocated from scratch. The old one, if it | ||||
1903 | existed, is lost. */ | ||||
1904 | |||||
1905 | template<typename T> | ||||
1906 | inline void | ||||
1907 | vec<T, va_heap, vl_ptr>::create (unsigned nelems MEM_STAT_DECL) | ||||
1908 | { | ||||
1909 | m_vec = NULLnullptr; | ||||
1910 | if (nelems > 0) | ||||
1911 | reserve_exact (nelems PASS_MEM_STAT); | ||||
1912 | } | ||||
1913 | |||||
1914 | |||||
1915 | /* Free the memory occupied by the embedded vector. */ | ||||
1916 | |||||
1917 | template<typename T> | ||||
1918 | inline void | ||||
1919 | vec<T, va_heap, vl_ptr>::release (void) | ||||
1920 | { | ||||
1921 | if (!m_vec) | ||||
1922 | return; | ||||
1923 | |||||
1924 | if (using_auto_storage ()) | ||||
1925 | { | ||||
1926 | m_vec->m_vecpfx.m_num = 0; | ||||
1927 | return; | ||||
1928 | } | ||||
1929 | |||||
1930 | va_heap::release (m_vec); | ||||
1931 | } | ||||
1932 | |||||
1933 | /* Copy the elements from SRC to the end of this vector as if by memcpy. | ||||
1934 | SRC and this vector must be allocated with the same memory | ||||
1935 | allocation mechanism. This vector is assumed to have sufficient | ||||
1936 | headroom available. */ | ||||
1937 | |||||
1938 | template<typename T> | ||||
1939 | inline void | ||||
1940 | vec<T, va_heap, vl_ptr>::splice (const vec<T, va_heap, vl_ptr> &src) | ||||
1941 | { | ||||
1942 | if (src.length ()) | ||||
1943 | m_vec->splice (*(src.m_vec)); | ||||
1944 | } | ||||
1945 | |||||
1946 | |||||
1947 | /* Copy the elements in SRC to the end of this vector as if by memcpy. | ||||
1948 | SRC and this vector must be allocated with the same mechanism. | ||||
1949 | If there is not enough headroom in this vector, it will be reallocated | ||||
1950 | as needed. */ | ||||
1951 | |||||
1952 | template<typename T> | ||||
1953 | inline void | ||||
1954 | vec<T, va_heap, vl_ptr>::safe_splice (const vec<T, va_heap, vl_ptr> &src | ||||
1955 | MEM_STAT_DECL) | ||||
1956 | { | ||||
1957 | if (src.length ()) | ||||
1958 | { | ||||
1959 | reserve_exact (src.length ()); | ||||
1960 | splice (src); | ||||
1961 | } | ||||
1962 | } | ||||
1963 | |||||
1964 | |||||
1965 | /* Push OBJ (a new element) onto the end of the vector. There must be | ||||
1966 | sufficient space in the vector. Return a pointer to the slot | ||||
1967 | where OBJ was inserted. */ | ||||
1968 | |||||
1969 | template<typename T> | ||||
1970 | inline T * | ||||
1971 | vec<T, va_heap, vl_ptr>::quick_push (const T &obj) | ||||
1972 | { | ||||
1973 | return m_vec->quick_push (obj); | ||||
1974 | } | ||||
1975 | |||||
1976 | |||||
1977 | /* Push a new element OBJ onto the end of this vector. Reallocates | ||||
1978 | the embedded vector, if needed. Return a pointer to the slot where | ||||
1979 | OBJ was inserted. */ | ||||
1980 | |||||
1981 | template<typename T> | ||||
1982 | inline T * | ||||
1983 | vec<T, va_heap, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL) | ||||
1984 | { | ||||
1985 | reserve (1, false PASS_MEM_STAT); | ||||
1986 | return quick_push (obj); | ||||
1987 | } | ||||
1988 | |||||
1989 | |||||
1990 | /* Pop and return the last element off the end of the vector. */ | ||||
1991 | |||||
1992 | template<typename T> | ||||
1993 | inline T & | ||||
1994 | vec<T, va_heap, vl_ptr>::pop (void) | ||||
1995 | { | ||||
1996 | return m_vec->pop (); | ||||
1997 | } | ||||
1998 | |||||
1999 | |||||
2000 | /* Set the length of the vector to LEN. The new length must be less | ||||
2001 | than or equal to the current length. This is an O(1) operation. */ | ||||
2002 | |||||
2003 | template<typename T> | ||||
2004 | inline void | ||||
2005 | vec<T, va_heap, vl_ptr>::truncate (unsigned size) | ||||
2006 | { | ||||
2007 | if (m_vec) | ||||
2008 | m_vec->truncate (size); | ||||
2009 | else | ||||
2010 | gcc_checking_assert (size == 0)((void)(!(size == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2010, __FUNCTION__), 0 : 0)); | ||||
2011 | } | ||||
2012 | |||||
2013 | |||||
2014 | /* Grow the vector to a specific length. LEN must be as long or | ||||
2015 | longer than the current length. The new elements are | ||||
2016 | uninitialized. Reallocate the internal vector, if needed. */ | ||||
2017 | |||||
2018 | template<typename T> | ||||
2019 | inline void | ||||
2020 | vec<T, va_heap, vl_ptr>::safe_grow (unsigned len, bool exact MEM_STAT_DECL) | ||||
2021 | { | ||||
2022 | unsigned oldlen = length (); | ||||
2023 | gcc_checking_assert (oldlen <= len)((void)(!(oldlen <= len) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2023, __FUNCTION__), 0 : 0)); | ||||
2024 | reserve (len - oldlen, exact PASS_MEM_STAT); | ||||
2025 | if (m_vec) | ||||
2026 | m_vec->quick_grow (len); | ||||
2027 | else | ||||
2028 | gcc_checking_assert (len == 0)((void)(!(len == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2028, __FUNCTION__), 0 : 0)); | ||||
2029 | } | ||||
2030 | |||||
2031 | |||||
2032 | /* Grow the embedded vector to a specific length. LEN must be as | ||||
2033 | long or longer than the current length. The new elements are | ||||
2034 | initialized to zero. Reallocate the internal vector, if needed. */ | ||||
2035 | |||||
2036 | template<typename T> | ||||
2037 | inline void | ||||
2038 | vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len, bool exact | ||||
2039 | MEM_STAT_DECL) | ||||
2040 | { | ||||
2041 | unsigned oldlen = length (); | ||||
2042 | size_t growby = len - oldlen; | ||||
2043 | safe_grow (len, exact PASS_MEM_STAT); | ||||
2044 | if (growby != 0) | ||||
2045 | vec_default_construct (address () + oldlen, growby); | ||||
2046 | } | ||||
2047 | |||||
2048 | |||||
2049 | /* Same as vec::safe_grow but without reallocation of the internal vector. | ||||
2050 | If the vector cannot be extended, a runtime assertion will be triggered. */ | ||||
2051 | |||||
2052 | template<typename T> | ||||
2053 | inline void | ||||
2054 | vec<T, va_heap, vl_ptr>::quick_grow (unsigned len) | ||||
2055 | { | ||||
2056 | gcc_checking_assert (m_vec)((void)(!(m_vec) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2056, __FUNCTION__), 0 : 0)); | ||||
2057 | m_vec->quick_grow (len); | ||||
2058 | } | ||||
2059 | |||||
2060 | |||||
2061 | /* Same as vec::quick_grow_cleared but without reallocation of the | ||||
2062 | internal vector. If the vector cannot be extended, a runtime | ||||
2063 | assertion will be triggered. */ | ||||
2064 | |||||
2065 | template<typename T> | ||||
2066 | inline void | ||||
2067 | vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len) | ||||
2068 | { | ||||
2069 | gcc_checking_assert (m_vec)((void)(!(m_vec) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2069, __FUNCTION__), 0 : 0)); | ||||
2070 | m_vec->quick_grow_cleared (len); | ||||
2071 | } | ||||
2072 | |||||
2073 | |||||
2074 | /* Insert an element, OBJ, at the IXth position of this vector. There | ||||
2075 | must be sufficient space. */ | ||||
2076 | |||||
2077 | template<typename T> | ||||
2078 | inline void | ||||
2079 | vec<T, va_heap, vl_ptr>::quick_insert (unsigned ix, const T &obj) | ||||
2080 | { | ||||
2081 | m_vec->quick_insert (ix, obj); | ||||
2082 | } | ||||
2083 | |||||
2084 | |||||
2085 | /* Insert an element, OBJ, at the IXth position of the vector. | ||||
2086 | Reallocate the embedded vector, if necessary. */ | ||||
2087 | |||||
2088 | template<typename T> | ||||
2089 | inline void | ||||
2090 | vec<T, va_heap, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL) | ||||
2091 | { | ||||
2092 | reserve (1, false PASS_MEM_STAT); | ||||
2093 | quick_insert (ix, obj); | ||||
2094 | } | ||||
2095 | |||||
2096 | |||||
2097 | /* Remove an element from the IXth position of this vector. Ordering of | ||||
2098 | remaining elements is preserved. This is an O(N) operation due to | ||||
2099 | a memmove. */ | ||||
2100 | |||||
2101 | template<typename T> | ||||
2102 | inline void | ||||
2103 | vec<T, va_heap, vl_ptr>::ordered_remove (unsigned ix) | ||||
2104 | { | ||||
2105 | m_vec->ordered_remove (ix); | ||||
2106 | } | ||||
2107 | |||||
2108 | |||||
2109 | /* Remove an element from the IXth position of this vector. Ordering | ||||
2110 | of remaining elements is destroyed. This is an O(1) operation. */ | ||||
2111 | |||||
2112 | template<typename T> | ||||
2113 | inline void | ||||
2114 | vec<T, va_heap, vl_ptr>::unordered_remove (unsigned ix) | ||||
2115 | { | ||||
2116 | m_vec->unordered_remove (ix); | ||||
2117 | } | ||||
2118 | |||||
2119 | |||||
2120 | /* Remove LEN elements starting at the IXth. Ordering is retained. | ||||
2121 | This is an O(N) operation due to memmove. */ | ||||
2122 | |||||
2123 | template<typename T> | ||||
2124 | inline void | ||||
2125 | vec<T, va_heap, vl_ptr>::block_remove (unsigned ix, unsigned len) | ||||
2126 | { | ||||
2127 | m_vec->block_remove (ix, len); | ||||
2128 | } | ||||
2129 | |||||
2130 | |||||
2131 | /* Sort the contents of this vector with qsort. CMP is the comparison | ||||
2132 | function to pass to qsort. */ | ||||
2133 | |||||
2134 | template<typename T> | ||||
2135 | inline void | ||||
2136 | vec<T, va_heap, vl_ptr>::qsort (int (*cmp) (const void *, const void *))qsort (int (*cmp) (const void *, const void *)) | ||||
2137 | { | ||||
2138 | if (m_vec) | ||||
2139 | m_vec->qsort (cmp)qsort (cmp); | ||||
2140 | } | ||||
2141 | |||||
2142 | /* Sort the contents of this vector with qsort. CMP is the comparison | ||||
2143 | function to pass to qsort. */ | ||||
2144 | |||||
2145 | template<typename T> | ||||
2146 | inline void | ||||
2147 | vec<T, va_heap, vl_ptr>::sort (int (*cmp) (const void *, const void *, | ||||
2148 | void *), void *data) | ||||
2149 | { | ||||
2150 | if (m_vec) | ||||
2151 | m_vec->sort (cmp, data); | ||||
2152 | } | ||||
2153 | |||||
2154 | /* Sort the contents of this vector with gcc_stablesort_r. CMP is the | ||||
2155 | comparison function to pass to qsort. */ | ||||
2156 | |||||
2157 | template<typename T> | ||||
2158 | inline void | ||||
2159 | vec<T, va_heap, vl_ptr>::stablesort (int (*cmp) (const void *, const void *, | ||||
2160 | void *), void *data) | ||||
2161 | { | ||||
2162 | if (m_vec) | ||||
2163 | m_vec->stablesort (cmp, data); | ||||
2164 | } | ||||
2165 | |||||
2166 | /* Search the contents of the sorted vector with a binary search. | ||||
2167 | CMP is the comparison function to pass to bsearch. */ | ||||
2168 | |||||
2169 | template<typename T> | ||||
2170 | inline T * | ||||
2171 | vec<T, va_heap, vl_ptr>::bsearch (const void *key, | ||||
2172 | int (*cmp) (const void *, const void *)) | ||||
2173 | { | ||||
2174 | if (m_vec) | ||||
2175 | return m_vec->bsearch (key, cmp); | ||||
2176 | return NULLnullptr; | ||||
2177 | } | ||||
2178 | |||||
2179 | /* Search the contents of the sorted vector with a binary search. | ||||
2180 | CMP is the comparison function to pass to bsearch. */ | ||||
2181 | |||||
2182 | template<typename T> | ||||
2183 | inline T * | ||||
2184 | vec<T, va_heap, vl_ptr>::bsearch (const void *key, | ||||
2185 | int (*cmp) (const void *, const void *, | ||||
2186 | void *), void *data) | ||||
2187 | { | ||||
2188 | if (m_vec) | ||||
2189 | return m_vec->bsearch (key, cmp, data); | ||||
2190 | return NULLnullptr; | ||||
2191 | } | ||||
2192 | |||||
2193 | |||||
2194 | /* Find and return the first position in which OBJ could be inserted | ||||
2195 | without changing the ordering of this vector. LESSTHAN is a | ||||
2196 | function that returns true if the first argument is strictly less | ||||
2197 | than the second. */ | ||||
2198 | |||||
2199 | template<typename T> | ||||
2200 | inline unsigned | ||||
2201 | vec<T, va_heap, vl_ptr>::lower_bound (T obj, | ||||
2202 | bool (*lessthan)(const T &, const T &)) | ||||
2203 | const | ||||
2204 | { | ||||
2205 | return m_vec ? m_vec->lower_bound (obj, lessthan) : 0; | ||||
2206 | } | ||||
2207 | |||||
2208 | /* Return true if SEARCH is an element of V. Note that this is O(N) in the | ||||
2209 | size of the vector and so should be used with care. */ | ||||
2210 | |||||
2211 | template<typename T> | ||||
2212 | inline bool | ||||
2213 | vec<T, va_heap, vl_ptr>::contains (const T &search) const | ||||
2214 | { | ||||
2215 | return m_vec ? m_vec->contains (search) : false; | ||||
2216 | } | ||||
2217 | |||||
2218 | /* Reverse content of the vector. */ | ||||
2219 | |||||
2220 | template<typename T> | ||||
2221 | inline void | ||||
2222 | vec<T, va_heap, vl_ptr>::reverse (void) | ||||
2223 | { | ||||
2224 | unsigned l = length (); | ||||
2225 | T *ptr = address (); | ||||
2226 | |||||
2227 | for (unsigned i = 0; i < l / 2; i++) | ||||
2228 | std::swap (ptr[i], ptr[l - i - 1]); | ||||
2229 | } | ||||
2230 | |||||
2231 | template<typename T> | ||||
2232 | inline bool | ||||
2233 | vec<T, va_heap, vl_ptr>::using_auto_storage () const | ||||
2234 | { | ||||
2235 | return m_vec ? m_vec->m_vecpfx.m_using_auto_storage : false; | ||||
2236 | } | ||||
2237 | |||||
2238 | /* Release VEC and call release of all element vectors. */ | ||||
2239 | |||||
2240 | template<typename T> | ||||
2241 | inline void | ||||
2242 | release_vec_vec (vec<vec<T> > &vec) | ||||
2243 | { | ||||
2244 | for (unsigned i = 0; i < vec.length (); i++) | ||||
2245 | vec[i].release (); | ||||
2246 | |||||
2247 | vec.release (); | ||||
2248 | } | ||||
2249 | |||||
2250 | // Provide a subset of the std::span functionality. (We can't use std::span | ||||
2251 | // itself because it's a C++20 feature.) | ||||
2252 | // | ||||
2253 | // In addition, provide an invalid value that is distinct from all valid | ||||
2254 | // sequences (including the empty sequence). This can be used to return | ||||
2255 | // failure without having to use std::optional. | ||||
2256 | // | ||||
2257 | // There is no operator bool because it would be ambiguous whether it is | ||||
2258 | // testing for a valid value or an empty sequence. | ||||
2259 | template<typename T> | ||||
2260 | class array_slice | ||||
2261 | { | ||||
2262 | template<typename OtherT> friend class array_slice; | ||||
2263 | |||||
2264 | public: | ||||
2265 | using value_type = T; | ||||
2266 | using iterator = T *; | ||||
2267 | using const_iterator = const T *; | ||||
2268 | |||||
2269 | array_slice () : m_base (nullptr), m_size (0) {} | ||||
2270 | |||||
2271 | template<typename OtherT> | ||||
2272 | array_slice (array_slice<OtherT> other) | ||||
2273 | : m_base (other.m_base), m_size (other.m_size) {} | ||||
2274 | |||||
2275 | array_slice (iterator base, unsigned int size) | ||||
2276 | : m_base (base), m_size (size) {} | ||||
2277 | |||||
2278 | template<size_t N> | ||||
2279 | array_slice (T (&array)[N]) : m_base (array), m_size (N) {} | ||||
2280 | |||||
2281 | template<typename OtherT> | ||||
2282 | array_slice (const vec<OtherT> &v) | ||||
2283 | : m_base (v.address ()), m_size (v.length ()) {} | ||||
2284 | |||||
2285 | template<typename OtherT> | ||||
2286 | array_slice (vec<OtherT> &v) | ||||
2287 | : m_base (v.address ()), m_size (v.length ()) {} | ||||
2288 | |||||
2289 | template<typename OtherT> | ||||
2290 | array_slice (const vec<OtherT, va_gc> *v) | ||||
2291 | : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {} | ||||
2292 | |||||
2293 | template<typename OtherT> | ||||
2294 | array_slice (vec<OtherT, va_gc> *v) | ||||
2295 | : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {} | ||||
2296 | |||||
2297 | iterator begin () { return m_base; } | ||||
2298 | iterator end () { return m_base + m_size; } | ||||
2299 | |||||
2300 | const_iterator begin () const { return m_base; } | ||||
2301 | const_iterator end () const { return m_base + m_size; } | ||||
2302 | |||||
2303 | value_type &front (); | ||||
2304 | value_type &back (); | ||||
2305 | value_type &operator[] (unsigned int i); | ||||
2306 | |||||
2307 | const value_type &front () const; | ||||
2308 | const value_type &back () const; | ||||
2309 | const value_type &operator[] (unsigned int i) const; | ||||
2310 | |||||
2311 | size_t size () const { return m_size; } | ||||
2312 | size_t size_bytes () const { return m_size * sizeof (T); } | ||||
2313 | bool empty () const { return m_size == 0; } | ||||
2314 | |||||
2315 | // An invalid array_slice that represents a failed operation. This is | ||||
2316 | // distinct from an empty slice, which is a valid result in some contexts. | ||||
2317 | static array_slice invalid () { return { nullptr, ~0U }; } | ||||
2318 | |||||
2319 | // True if the array is valid, false if it is an array like INVALID. | ||||
2320 | bool is_valid () const { return m_base || m_size == 0; } | ||||
2321 | |||||
2322 | private: | ||||
2323 | iterator m_base; | ||||
2324 | unsigned int m_size; | ||||
2325 | }; | ||||
2326 | |||||
2327 | template<typename T> | ||||
2328 | inline typename array_slice<T>::value_type & | ||||
2329 | array_slice<T>::front () | ||||
2330 | { | ||||
2331 | gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2331, __FUNCTION__), 0 : 0)); | ||||
2332 | return m_base[0]; | ||||
2333 | } | ||||
2334 | |||||
2335 | template<typename T> | ||||
2336 | inline const typename array_slice<T>::value_type & | ||||
2337 | array_slice<T>::front () const | ||||
2338 | { | ||||
2339 | gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2339, __FUNCTION__), 0 : 0)); | ||||
2340 | return m_base[0]; | ||||
2341 | } | ||||
2342 | |||||
2343 | template<typename T> | ||||
2344 | inline typename array_slice<T>::value_type & | ||||
2345 | array_slice<T>::back () | ||||
2346 | { | ||||
2347 | gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2347, __FUNCTION__), 0 : 0)); | ||||
2348 | return m_base[m_size - 1]; | ||||
2349 | } | ||||
2350 | |||||
2351 | template<typename T> | ||||
2352 | inline const typename array_slice<T>::value_type & | ||||
2353 | array_slice<T>::back () const | ||||
2354 | { | ||||
2355 | gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2355, __FUNCTION__), 0 : 0)); | ||||
2356 | return m_base[m_size - 1]; | ||||
2357 | } | ||||
2358 | |||||
2359 | template<typename T> | ||||
2360 | inline typename array_slice<T>::value_type & | ||||
2361 | array_slice<T>::operator[] (unsigned int i) | ||||
2362 | { | ||||
2363 | gcc_checking_assert (i < m_size)((void)(!(i < m_size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2363, __FUNCTION__), 0 : 0)); | ||||
2364 | return m_base[i]; | ||||
2365 | } | ||||
2366 | |||||
2367 | template<typename T> | ||||
2368 | inline const typename array_slice<T>::value_type & | ||||
2369 | array_slice<T>::operator[] (unsigned int i) const | ||||
2370 | { | ||||
2371 | gcc_checking_assert (i < m_size)((void)(!(i < m_size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h" , 2371, __FUNCTION__), 0 : 0)); | ||||
2372 | return m_base[i]; | ||||
2373 | } | ||||
2374 | |||||
2375 | template<typename T> | ||||
2376 | array_slice<T> | ||||
2377 | make_array_slice (T *base, unsigned int size) | ||||
2378 | { | ||||
2379 | return array_slice<T> (base, size); | ||||
2380 | } | ||||
2381 | |||||
2382 | #if (GCC_VERSION(4 * 1000 + 2) >= 3000) | ||||
2383 | # pragma GCC poison m_vec m_vecpfx m_vecdata | ||||
2384 | #endif | ||||
2385 | |||||
2386 | #endif // GCC_VEC_H |