File: | build/gcc/tree-object-size.cc |
Warning: | line 1502, column 7 1st function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* __builtin_object_size (ptr, object_size_type) computation | ||||
2 | Copyright (C) 2004-2023 Free Software Foundation, Inc. | ||||
3 | Contributed by Jakub Jelinek <jakub@redhat.com> | ||||
4 | |||||
5 | This file is part of GCC. | ||||
6 | |||||
7 | GCC is free software; you can redistribute it and/or modify | ||||
8 | it under the terms of the GNU General Public License as published by | ||||
9 | the Free Software Foundation; either version 3, or (at your option) | ||||
10 | any later version. | ||||
11 | |||||
12 | GCC is distributed in the hope that it will be useful, | ||||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
15 | GNU General Public License for more details. | ||||
16 | |||||
17 | You should have received a copy of the GNU General Public License | ||||
18 | along with GCC; see the file COPYING3. If not see | ||||
19 | <http://www.gnu.org/licenses/>. */ | ||||
20 | |||||
21 | #include "config.h" | ||||
22 | #include "system.h" | ||||
23 | #include "coretypes.h" | ||||
24 | #include "backend.h" | ||||
25 | #include "tree.h" | ||||
26 | #include "gimple.h" | ||||
27 | #include "tree-pass.h" | ||||
28 | #include "ssa.h" | ||||
29 | #include "gimple-pretty-print.h" | ||||
30 | #include "fold-const.h" | ||||
31 | #include "tree-object-size.h" | ||||
32 | #include "gimple-iterator.h" | ||||
33 | #include "gimple-fold.h" | ||||
34 | #include "tree-cfg.h" | ||||
35 | #include "tree-dfa.h" | ||||
36 | #include "stringpool.h" | ||||
37 | #include "attribs.h" | ||||
38 | #include "builtins.h" | ||||
39 | #include "gimplify-me.h" | ||||
40 | |||||
41 | struct object_size_info | ||||
42 | { | ||||
43 | int object_size_type; | ||||
44 | unsigned char pass; | ||||
45 | bool changed; | ||||
46 | bitmap visited, reexamine, unknowns; | ||||
47 | unsigned int *depths; | ||||
48 | unsigned int *stack, *tos; | ||||
49 | }; | ||||
50 | |||||
51 | struct GTY(()) object_size | ||||
52 | { | ||||
53 | /* Estimate of bytes till the end of the object. */ | ||||
54 | tree size; | ||||
55 | /* Estimate of the size of the whole object. */ | ||||
56 | tree wholesize; | ||||
57 | }; | ||||
58 | |||||
59 | static tree compute_object_offset (tree, const_tree); | ||||
60 | static bool addr_object_size (struct object_size_info *, | ||||
61 | const_tree, int, tree *, tree *t = NULLnullptr); | ||||
62 | static tree alloc_object_size (const gcall *, int); | ||||
63 | static tree pass_through_call (const gcall *); | ||||
64 | static void collect_object_sizes_for (struct object_size_info *, tree); | ||||
65 | static void expr_object_size (struct object_size_info *, tree, tree); | ||||
66 | static bool merge_object_sizes (struct object_size_info *, tree, tree); | ||||
67 | static bool plus_stmt_object_size (struct object_size_info *, tree, gimple *); | ||||
68 | static bool cond_expr_object_size (struct object_size_info *, tree, gimple *); | ||||
69 | static void init_offset_limit (void); | ||||
70 | static void check_for_plus_in_loops (struct object_size_info *, tree); | ||||
71 | static void check_for_plus_in_loops_1 (struct object_size_info *, tree, | ||||
72 | unsigned int); | ||||
73 | |||||
74 | /* object_sizes[0] is upper bound for the object size and number of bytes till | ||||
75 | the end of the object. | ||||
76 | object_sizes[1] is upper bound for the object size and number of bytes till | ||||
77 | the end of the subobject (innermost array or field with address taken). | ||||
78 | object_sizes[2] is lower bound for the object size and number of bytes till | ||||
79 | the end of the object and object_sizes[3] lower bound for subobject. | ||||
80 | |||||
81 | For static object sizes, the object size and the bytes till the end of the | ||||
82 | object are both INTEGER_CST. In the dynamic case, they are finally either a | ||||
83 | gimple variable or an INTEGER_CST. */ | ||||
84 | static vec<object_size> object_sizes[OST_END]; | ||||
85 | |||||
86 | /* Bitmaps what object sizes have been computed already. */ | ||||
87 | static bitmap computed[OST_END]; | ||||
88 | |||||
89 | /* Maximum value of offset we consider to be addition. */ | ||||
90 | static unsigned HOST_WIDE_INTlong offset_limit; | ||||
91 | |||||
92 | /* Tell the generic SSA updater what kind of update is needed after the pass | ||||
93 | executes. */ | ||||
94 | static unsigned todo; | ||||
95 | |||||
96 | /* Return true if VAL represents an initial size for OBJECT_SIZE_TYPE. */ | ||||
97 | |||||
98 | static inline bool | ||||
99 | size_initval_p (tree val, int object_size_type) | ||||
100 | { | ||||
101 | return ((object_size_type & OST_MINIMUM) | ||||
102 | ? integer_all_onesp (val) : integer_zerop (val)); | ||||
103 | } | ||||
104 | |||||
105 | /* Return true if VAL represents an unknown size for OBJECT_SIZE_TYPE. */ | ||||
106 | |||||
107 | static inline bool | ||||
108 | size_unknown_p (tree val, int object_size_type) | ||||
109 | { | ||||
110 | return ((object_size_type & OST_MINIMUM) | ||||
111 | ? integer_zerop (val) : integer_all_onesp (val)); | ||||
112 | } | ||||
113 | |||||
114 | /* Return true if VAL represents a valid size for OBJECT_SIZE_TYPE. */ | ||||
115 | |||||
116 | static inline bool | ||||
117 | size_valid_p (tree val, int object_size_type) | ||||
118 | { | ||||
119 | return ((object_size_type & OST_DYNAMIC) || TREE_CODE (val)((enum tree_code) (val)->base.code) == INTEGER_CST); | ||||
120 | } | ||||
121 | |||||
122 | /* Return true if VAL is usable as an object size in the object_sizes | ||||
123 | vectors. */ | ||||
124 | |||||
125 | static inline bool | ||||
126 | size_usable_p (tree val) | ||||
127 | { | ||||
128 | return TREE_CODE (val)((enum tree_code) (val)->base.code) == SSA_NAME || TREE_CODE (val)((enum tree_code) (val)->base.code) == INTEGER_CST; | ||||
129 | } | ||||
130 | |||||
131 | /* Return a tree with initial value for OBJECT_SIZE_TYPE. */ | ||||
132 | |||||
133 | static inline tree | ||||
134 | size_initval (int object_size_type) | ||||
135 | { | ||||
136 | return ((object_size_type & OST_MINIMUM) | ||||
137 | ? TYPE_MAX_VALUE (sizetype)((tree_check5 ((sizetype_tab[(int) stk_sizetype]), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 137, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval ) : size_zero_nodeglobal_trees[TI_SIZE_ZERO]); | ||||
138 | } | ||||
139 | |||||
140 | /* Return a tree with unknown value for OBJECT_SIZE_TYPE. */ | ||||
141 | |||||
142 | static inline tree | ||||
143 | size_unknown (int object_size_type) | ||||
144 | { | ||||
145 | return ((object_size_type & OST_MINIMUM) | ||||
146 | ? size_zero_nodeglobal_trees[TI_SIZE_ZERO] : TYPE_MAX_VALUE (sizetype)((tree_check5 ((sizetype_tab[(int) stk_sizetype]), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 146, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval )); | ||||
147 | } | ||||
148 | |||||
149 | /* Grow object_sizes[OBJECT_SIZE_TYPE] to num_ssa_names. */ | ||||
150 | |||||
151 | static inline void | ||||
152 | object_sizes_grow (int object_size_type) | ||||
153 | { | ||||
154 | if (num_ssa_names(vec_safe_length ((cfun + 0)->gimple_df->ssa_names)) > object_sizes[object_size_type].length ()) | ||||
155 | object_sizes[object_size_type].safe_grow (num_ssa_names(vec_safe_length ((cfun + 0)->gimple_df->ssa_names)), true); | ||||
156 | } | ||||
157 | |||||
158 | /* Release object_sizes[OBJECT_SIZE_TYPE]. */ | ||||
159 | |||||
160 | static inline void | ||||
161 | object_sizes_release (int object_size_type) | ||||
162 | { | ||||
163 | object_sizes[object_size_type].release (); | ||||
164 | } | ||||
165 | |||||
166 | /* Return true if object_sizes[OBJECT_SIZE_TYPE][VARNO] is unknown. */ | ||||
167 | |||||
168 | static inline bool | ||||
169 | object_sizes_unknown_p (int object_size_type, unsigned varno) | ||||
170 | { | ||||
171 | return size_unknown_p (object_sizes[object_size_type][varno].size, | ||||
172 | object_size_type); | ||||
173 | } | ||||
174 | |||||
175 | /* Return the raw size expression for VARNO corresponding to OSI. This returns | ||||
176 | the TREE_VEC as is and should only be used during gimplification. */ | ||||
177 | |||||
178 | static inline object_size | ||||
179 | object_sizes_get_raw (struct object_size_info *osi, unsigned varno) | ||||
180 | { | ||||
181 | gcc_assert (osi->pass != 0)((void)(!(osi->pass != 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 181, __FUNCTION__), 0 : 0)); | ||||
182 | return object_sizes[osi->object_size_type][varno]; | ||||
183 | } | ||||
184 | |||||
185 | /* Return a size tree for VARNO corresponding to OSI. If WHOLE is true, return | ||||
186 | the whole object size. Use this for building size expressions based on size | ||||
187 | of VARNO. */ | ||||
188 | |||||
189 | static inline tree | ||||
190 | object_sizes_get (struct object_size_info *osi, unsigned varno, | ||||
191 | bool whole = false) | ||||
192 | { | ||||
193 | tree ret; | ||||
194 | int object_size_type = osi->object_size_type; | ||||
195 | |||||
196 | if (whole) | ||||
197 | ret = object_sizes[object_size_type][varno].wholesize; | ||||
198 | else | ||||
199 | ret = object_sizes[object_size_type][varno].size; | ||||
200 | |||||
201 | if (object_size_type & OST_DYNAMIC) | ||||
202 | { | ||||
203 | if (TREE_CODE (ret)((enum tree_code) (ret)->base.code) == MODIFY_EXPR) | ||||
204 | return TREE_OPERAND (ret, 0)(*((const_cast<tree*> (tree_operand_check ((ret), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 204, __FUNCTION__))))); | ||||
205 | else if (TREE_CODE (ret)((enum tree_code) (ret)->base.code) == TREE_VEC) | ||||
206 | return TREE_VEC_ELT (ret, TREE_VEC_LENGTH (ret) - 1)(*((const_cast<tree *> (tree_vec_elt_check ((ret), (((tree_check ((ret), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 206, __FUNCTION__, (TREE_VEC)))->base.u.length) - 1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 206, __FUNCTION__))))); | ||||
207 | else | ||||
208 | gcc_checking_assert (size_usable_p (ret))((void)(!(size_usable_p (ret)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 208, __FUNCTION__), 0 : 0)); | ||||
209 | } | ||||
210 | |||||
211 | return ret; | ||||
212 | } | ||||
213 | |||||
214 | /* Set size for VARNO corresponding to OSI to VAL. */ | ||||
215 | |||||
216 | static inline void | ||||
217 | object_sizes_initialize (struct object_size_info *osi, unsigned varno, | ||||
218 | tree val, tree wholeval) | ||||
219 | { | ||||
220 | int object_size_type = osi->object_size_type; | ||||
221 | |||||
222 | object_sizes[object_size_type][varno].size = val; | ||||
223 | object_sizes[object_size_type][varno].wholesize = wholeval; | ||||
224 | } | ||||
225 | |||||
226 | /* Return a MODIFY_EXPR for cases where SSA and EXPR have the same type. The | ||||
227 | TREE_VEC is returned only in case of PHI nodes. */ | ||||
228 | |||||
229 | static tree | ||||
230 | bundle_sizes (tree name, tree expr) | ||||
231 | { | ||||
232 | gcc_checking_assert (TREE_TYPE (name) == sizetype)((void)(!(((contains_struct_check ((name), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 232, __FUNCTION__))->typed.type) == sizetype_tab[(int) stk_sizetype ]) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 232, __FUNCTION__), 0 : 0)); | ||||
233 | |||||
234 | if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == TREE_VEC) | ||||
235 | { | ||||
236 | TREE_VEC_ELT (expr, TREE_VEC_LENGTH (expr) - 1)(*((const_cast<tree *> (tree_vec_elt_check ((expr), ((( tree_check ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 236, __FUNCTION__, (TREE_VEC)))->base.u.length) - 1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 236, __FUNCTION__))))) = name; | ||||
237 | return expr; | ||||
238 | } | ||||
239 | |||||
240 | gcc_checking_assert (types_compatible_p (TREE_TYPE (expr), sizetype))((void)(!(types_compatible_p (((contains_struct_check ((expr) , (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 240, __FUNCTION__))->typed.type), sizetype_tab[(int) stk_sizetype ])) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 240, __FUNCTION__), 0 : 0)); | ||||
241 | return build2 (MODIFY_EXPR, sizetypesizetype_tab[(int) stk_sizetype], name, expr); | ||||
242 | } | ||||
243 | |||||
244 | /* Set size for VARNO corresponding to OSI to VAL if it is the new minimum or | ||||
245 | maximum. For static sizes, each element of TREE_VEC is always INTEGER_CST | ||||
246 | throughout the computation. For dynamic sizes, each element may either be a | ||||
247 | gimple variable, a MODIFY_EXPR or a TREE_VEC. The MODIFY_EXPR is for | ||||
248 | expressions that need to be gimplified. TREE_VECs are special, they're | ||||
249 | emitted only for GIMPLE_PHI and the PHI result variable is the last element | ||||
250 | of the vector. */ | ||||
251 | |||||
252 | static bool | ||||
253 | object_sizes_set (struct object_size_info *osi, unsigned varno, tree val, | ||||
254 | tree wholeval) | ||||
255 | { | ||||
256 | int object_size_type = osi->object_size_type; | ||||
257 | object_size osize = object_sizes[object_size_type][varno]; | ||||
258 | bool changed = true; | ||||
259 | |||||
260 | tree oldval = osize.size; | ||||
261 | tree old_wholeval = osize.wholesize; | ||||
262 | |||||
263 | if (object_size_type & OST_DYNAMIC) | ||||
264 | { | ||||
265 | if (bitmap_bit_p (osi->reexamine, varno)) | ||||
266 | { | ||||
267 | if (size_unknown_p (val, object_size_type)) | ||||
268 | { | ||||
269 | oldval = object_sizes_get (osi, varno); | ||||
270 | old_wholeval = object_sizes_get (osi, varno, true); | ||||
271 | bitmap_set_bit (osi->unknowns, SSA_NAME_VERSION (oldval)(tree_check ((oldval), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 271, __FUNCTION__, (SSA_NAME)))->base.u.version); | ||||
272 | bitmap_set_bit (osi->unknowns, SSA_NAME_VERSION (old_wholeval)(tree_check ((old_wholeval), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 272, __FUNCTION__, (SSA_NAME)))->base.u.version); | ||||
273 | bitmap_clear_bit (osi->reexamine, varno); | ||||
274 | } | ||||
275 | else | ||||
276 | { | ||||
277 | val = bundle_sizes (oldval, val); | ||||
278 | wholeval = bundle_sizes (old_wholeval, wholeval); | ||||
279 | } | ||||
280 | } | ||||
281 | else | ||||
282 | { | ||||
283 | gcc_checking_assert (size_initval_p (oldval, object_size_type))((void)(!(size_initval_p (oldval, object_size_type)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 283, __FUNCTION__), 0 : 0)); | ||||
284 | gcc_checking_assert (size_initval_p (old_wholeval,((void)(!(size_initval_p (old_wholeval, object_size_type)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 285, __FUNCTION__), 0 : 0)) | ||||
285 | object_size_type))((void)(!(size_initval_p (old_wholeval, object_size_type)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 285, __FUNCTION__), 0 : 0)); | ||||
286 | /* For dynamic object sizes, all object sizes that are not gimple | ||||
287 | variables will need to be gimplified. */ | ||||
288 | if (wholeval != val && !size_usable_p (wholeval)) | ||||
289 | { | ||||
290 | bitmap_set_bit (osi->reexamine, varno); | ||||
291 | wholeval = bundle_sizes (make_ssa_name (sizetypesizetype_tab[(int) stk_sizetype]), wholeval); | ||||
292 | } | ||||
293 | if (!size_usable_p (val)) | ||||
294 | { | ||||
295 | bitmap_set_bit (osi->reexamine, varno); | ||||
296 | tree newval = bundle_sizes (make_ssa_name (sizetypesizetype_tab[(int) stk_sizetype]), val); | ||||
297 | if (val == wholeval) | ||||
298 | wholeval = newval; | ||||
299 | val = newval; | ||||
300 | } | ||||
301 | /* If the new value is a temporary variable, mark it for | ||||
302 | reexamination. */ | ||||
303 | else if (TREE_CODE (val)((enum tree_code) (val)->base.code) == SSA_NAME && !SSA_NAME_DEF_STMT (val)(tree_check ((val), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 303, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt) | ||||
304 | bitmap_set_bit (osi->reexamine, varno); | ||||
305 | } | ||||
306 | } | ||||
307 | else | ||||
308 | { | ||||
309 | enum tree_code code = (object_size_type & OST_MINIMUM | ||||
310 | ? MIN_EXPR : MAX_EXPR); | ||||
311 | |||||
312 | val = size_binop (code, val, oldval)size_binop_loc (((location_t) 0), code, val, oldval); | ||||
313 | wholeval = size_binop (code, wholeval, old_wholeval)size_binop_loc (((location_t) 0), code, wholeval, old_wholeval ); | ||||
314 | changed = (tree_int_cst_compare (val, oldval) != 0 | ||||
315 | || tree_int_cst_compare (old_wholeval, wholeval) != 0); | ||||
316 | } | ||||
317 | |||||
318 | object_sizes[object_size_type][varno].size = val; | ||||
319 | object_sizes[object_size_type][varno].wholesize = wholeval; | ||||
320 | |||||
321 | return changed; | ||||
322 | } | ||||
323 | |||||
324 | /* Set temporary SSA names for object size and whole size to resolve dependency | ||||
325 | loops in dynamic size computation. */ | ||||
326 | |||||
327 | static inline void | ||||
328 | object_sizes_set_temp (struct object_size_info *osi, unsigned varno) | ||||
329 | { | ||||
330 | tree val = object_sizes_get (osi, varno); | ||||
331 | |||||
332 | if (size_initval_p (val, osi->object_size_type)) | ||||
333 | object_sizes_set (osi, varno, | ||||
334 | make_ssa_name (sizetypesizetype_tab[(int) stk_sizetype]), | ||||
335 | make_ssa_name (sizetypesizetype_tab[(int) stk_sizetype])); | ||||
336 | } | ||||
337 | |||||
338 | /* Initialize OFFSET_LIMIT variable. */ | ||||
339 | static void | ||||
340 | init_offset_limit (void) | ||||
341 | { | ||||
342 | if (tree_fits_uhwi_p (TYPE_MAX_VALUE (sizetype)((tree_check5 ((sizetype_tab[(int) stk_sizetype]), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 342, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval ))) | ||||
343 | offset_limit = tree_to_uhwi (TYPE_MAX_VALUE (sizetype)((tree_check5 ((sizetype_tab[(int) stk_sizetype]), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 343, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval )); | ||||
344 | else | ||||
345 | offset_limit = -1; | ||||
346 | offset_limit /= 2; | ||||
347 | } | ||||
348 | |||||
349 | /* Bytes at end of the object with SZ from offset OFFSET. If WHOLESIZE is not | ||||
350 | NULL_TREE, use it to get the net offset of the pointer, which should always | ||||
351 | be positive and hence, be within OFFSET_LIMIT for valid offsets. */ | ||||
352 | |||||
353 | static tree | ||||
354 | size_for_offset (tree sz, tree offset, tree wholesize = NULL_TREE(tree) nullptr) | ||||
355 | { | ||||
356 | gcc_checking_assert (types_compatible_p (TREE_TYPE (sz), sizetype))((void)(!(types_compatible_p (((contains_struct_check ((sz), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 356, __FUNCTION__))->typed.type), sizetype_tab[(int) stk_sizetype ])) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 356, __FUNCTION__), 0 : 0)); | ||||
357 | |||||
358 | /* For negative offsets, if we have a distinct WHOLESIZE, use it to get a net | ||||
359 | offset from the whole object. */ | ||||
360 | if (wholesize && wholesize != sz | ||||
361 | && (TREE_CODE (sz)((enum tree_code) (sz)->base.code) != INTEGER_CST | ||||
362 | || TREE_CODE (wholesize)((enum tree_code) (wholesize)->base.code) != INTEGER_CST | ||||
363 | || tree_int_cst_compare (sz, wholesize))) | ||||
364 | { | ||||
365 | gcc_checking_assert (types_compatible_p (TREE_TYPE (wholesize),((void)(!(types_compatible_p (((contains_struct_check ((wholesize ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 365, __FUNCTION__))->typed.type), sizetype_tab[(int) stk_sizetype ])) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 366, __FUNCTION__), 0 : 0)) | ||||
366 | sizetype))((void)(!(types_compatible_p (((contains_struct_check ((wholesize ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 365, __FUNCTION__))->typed.type), sizetype_tab[(int) stk_sizetype ])) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 366, __FUNCTION__), 0 : 0)); | ||||
367 | |||||
368 | /* Restructure SZ - OFFSET as | ||||
369 | WHOLESIZE - (WHOLESIZE + OFFSET - SZ) so that the offset part, i.e. | ||||
370 | WHOLESIZE + OFFSET - SZ is only allowed to be positive. */ | ||||
371 | tree tmp = size_binop (MAX_EXPR, wholesize, sz)size_binop_loc (((location_t) 0), MAX_EXPR, wholesize, sz); | ||||
372 | offset = fold_build2 (PLUS_EXPR, sizetype, tmp, offset)fold_build2_loc (((location_t) 0), PLUS_EXPR, sizetype_tab[(int ) stk_sizetype], tmp, offset ); | ||||
373 | offset = fold_build2 (MINUS_EXPR, sizetype, offset, sz)fold_build2_loc (((location_t) 0), MINUS_EXPR, sizetype_tab[( int) stk_sizetype], offset, sz ); | ||||
374 | sz = tmp; | ||||
375 | } | ||||
376 | |||||
377 | /* Safe to convert now, since a valid net offset should be non-negative. */ | ||||
378 | if (!useless_type_conversion_p (sizetypesizetype_tab[(int) stk_sizetype], TREE_TYPE (offset)((contains_struct_check ((offset), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 378, __FUNCTION__))->typed.type))) | ||||
379 | offset = fold_convert (sizetype, offset)fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_sizetype ], offset); | ||||
380 | |||||
381 | if (TREE_CODE (offset)((enum tree_code) (offset)->base.code) == INTEGER_CST) | ||||
382 | { | ||||
383 | if (integer_zerop (offset)) | ||||
384 | return sz; | ||||
385 | |||||
386 | /* Negative or too large offset even after adjustment, cannot be within | ||||
387 | bounds of an object. */ | ||||
388 | if (compare_tree_int (offset, offset_limit) > 0) | ||||
389 | return size_zero_nodeglobal_trees[TI_SIZE_ZERO]; | ||||
390 | } | ||||
391 | |||||
392 | return size_binop (MINUS_EXPR, size_binop (MAX_EXPR, sz, offset), offset)size_binop_loc (((location_t) 0), MINUS_EXPR, size_binop_loc ( ((location_t) 0), MAX_EXPR, sz, offset), offset); | ||||
393 | } | ||||
394 | |||||
395 | /* Compute offset of EXPR within VAR. Return error_mark_node | ||||
396 | if unknown. */ | ||||
397 | |||||
398 | static tree | ||||
399 | compute_object_offset (tree expr, const_tree var) | ||||
400 | { | ||||
401 | enum tree_code code = PLUS_EXPR; | ||||
402 | tree base, off, t; | ||||
403 | |||||
404 | if (expr == var) | ||||
405 | return size_zero_nodeglobal_trees[TI_SIZE_ZERO]; | ||||
406 | |||||
407 | switch (TREE_CODE (expr)((enum tree_code) (expr)->base.code)) | ||||
408 | { | ||||
409 | case COMPONENT_REF: | ||||
410 | base = compute_object_offset (TREE_OPERAND (expr, 0)(*((const_cast<tree*> (tree_operand_check ((expr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 410, __FUNCTION__))))), var); | ||||
411 | if (base == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | ||||
412 | return base; | ||||
413 | |||||
414 | t = TREE_OPERAND (expr, 1)(*((const_cast<tree*> (tree_operand_check ((expr), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 414, __FUNCTION__))))); | ||||
415 | off = size_binop (PLUS_EXPR,size_binop_loc (((location_t) 0), PLUS_EXPR, component_ref_field_offset (expr), size_int_kind (tree_to_uhwi (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 417, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_offset )) / (8), stk_sizetype)) | ||||
416 | component_ref_field_offset (expr),size_binop_loc (((location_t) 0), PLUS_EXPR, component_ref_field_offset (expr), size_int_kind (tree_to_uhwi (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 417, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_offset )) / (8), stk_sizetype)) | ||||
417 | size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))size_binop_loc (((location_t) 0), PLUS_EXPR, component_ref_field_offset (expr), size_int_kind (tree_to_uhwi (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 417, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_offset )) / (8), stk_sizetype)) | ||||
418 | / BITS_PER_UNIT))size_binop_loc (((location_t) 0), PLUS_EXPR, component_ref_field_offset (expr), size_int_kind (tree_to_uhwi (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 417, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_offset )) / (8), stk_sizetype)); | ||||
419 | break; | ||||
420 | |||||
421 | case REALPART_EXPR: | ||||
422 | CASE_CONVERTcase NOP_EXPR: case CONVERT_EXPR: | ||||
423 | case VIEW_CONVERT_EXPR: | ||||
424 | case NON_LVALUE_EXPR: | ||||
425 | return compute_object_offset (TREE_OPERAND (expr, 0)(*((const_cast<tree*> (tree_operand_check ((expr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 425, __FUNCTION__))))), var); | ||||
426 | |||||
427 | case IMAGPART_EXPR: | ||||
428 | base = compute_object_offset (TREE_OPERAND (expr, 0)(*((const_cast<tree*> (tree_operand_check ((expr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 428, __FUNCTION__))))), var); | ||||
429 | if (base == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | ||||
430 | return base; | ||||
431 | |||||
432 | off = TYPE_SIZE_UNIT (TREE_TYPE (expr))((tree_class_check ((((contains_struct_check ((expr), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 432, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 432, __FUNCTION__))->type_common.size_unit); | ||||
433 | break; | ||||
434 | |||||
435 | case ARRAY_REF: | ||||
436 | base = compute_object_offset (TREE_OPERAND (expr, 0)(*((const_cast<tree*> (tree_operand_check ((expr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 436, __FUNCTION__))))), var); | ||||
437 | if (base == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | ||||
438 | return base; | ||||
439 | |||||
440 | t = TREE_OPERAND (expr, 1)(*((const_cast<tree*> (tree_operand_check ((expr), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 440, __FUNCTION__))))); | ||||
441 | tree low_bound, unit_size; | ||||
442 | low_bound = array_ref_low_bound (CONST_CAST_TREE (expr)(const_cast<union tree_node *> (((expr))))); | ||||
443 | unit_size = array_ref_element_size (CONST_CAST_TREE (expr)(const_cast<union tree_node *> (((expr))))); | ||||
444 | if (! integer_zerop (low_bound)) | ||||
445 | t = fold_build2 (MINUS_EXPR, TREE_TYPE (t), t, low_bound)fold_build2_loc (((location_t) 0), MINUS_EXPR, ((contains_struct_check ((t), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 445, __FUNCTION__))->typed.type), t, low_bound ); | ||||
446 | if (TREE_CODE (t)((enum tree_code) (t)->base.code) == INTEGER_CST && tree_int_cst_sgn (t) < 0) | ||||
447 | { | ||||
448 | code = MINUS_EXPR; | ||||
449 | t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t)fold_build1_loc (((location_t) 0), NEGATE_EXPR, ((contains_struct_check ((t), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 449, __FUNCTION__))->typed.type), t ); | ||||
450 | } | ||||
451 | t = fold_convert (sizetype, t)fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_sizetype ], t); | ||||
452 | off = size_binop (MULT_EXPR, unit_size, t)size_binop_loc (((location_t) 0), MULT_EXPR, unit_size, t); | ||||
453 | break; | ||||
454 | |||||
455 | case MEM_REF: | ||||
456 | gcc_assert (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)((void)(!(((enum tree_code) ((*((const_cast<tree*> (tree_operand_check ((expr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 456, __FUNCTION__))))))->base.code) == ADDR_EXPR) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 456, __FUNCTION__), 0 : 0)); | ||||
457 | return wide_int_to_tree (sizetypesizetype_tab[(int) stk_sizetype], mem_ref_offset (expr)); | ||||
458 | |||||
459 | default: | ||||
460 | return error_mark_nodeglobal_trees[TI_ERROR_MARK]; | ||||
461 | } | ||||
462 | |||||
463 | return size_binop (code, base, off)size_binop_loc (((location_t) 0), code, base, off); | ||||
464 | } | ||||
465 | |||||
466 | /* Returns the size of the object designated by DECL considering its | ||||
467 | initializer if it either has one or if it would not affect its size, | ||||
468 | otherwise the size of the object without the initializer when MIN | ||||
469 | is true, else null. An object's initializer affects the object's | ||||
470 | size if it's a struct type with a flexible array member. */ | ||||
471 | |||||
472 | tree | ||||
473 | decl_init_size (tree decl, bool min) | ||||
474 | { | ||||
475 | tree size = DECL_SIZE_UNIT (decl)((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 475, __FUNCTION__))->decl_common.size_unit); | ||||
476 | tree type = TREE_TYPE (decl)((contains_struct_check ((decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 476, __FUNCTION__))->typed.type); | ||||
477 | if (TREE_CODE (type)((enum tree_code) (type)->base.code) != RECORD_TYPE) | ||||
478 | return size; | ||||
479 | |||||
480 | tree last = last_field (type); | ||||
481 | if (!last) | ||||
482 | return size; | ||||
483 | |||||
484 | tree last_type = TREE_TYPE (last)((contains_struct_check ((last), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 484, __FUNCTION__))->typed.type); | ||||
485 | if (TREE_CODE (last_type)((enum tree_code) (last_type)->base.code) != ARRAY_TYPE | ||||
486 | || TYPE_SIZE (last_type)((tree_class_check ((last_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 486, __FUNCTION__))->type_common.size)) | ||||
487 | return size; | ||||
488 | |||||
489 | /* Use TYPE_SIZE_UNIT; DECL_SIZE_UNIT sometimes reflects the size | ||||
490 | of the initializer and sometimes doesn't. */ | ||||
491 | size = TYPE_SIZE_UNIT (type)((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 491, __FUNCTION__))->type_common.size_unit); | ||||
492 | tree ref = build3 (COMPONENT_REF, type, decl, last, NULL_TREE(tree) nullptr); | ||||
493 | tree compsize = component_ref_size (ref); | ||||
494 | if (!compsize) | ||||
495 | return min ? size : NULL_TREE(tree) nullptr; | ||||
496 | |||||
497 | /* The size includes tail padding and initializer elements. */ | ||||
498 | tree pos = byte_position (last); | ||||
499 | size = fold_build2 (PLUS_EXPR, TREE_TYPE (size), pos, compsize)fold_build2_loc (((location_t) 0), PLUS_EXPR, ((contains_struct_check ((size), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 499, __FUNCTION__))->typed.type), pos, compsize ); | ||||
500 | return size; | ||||
501 | } | ||||
502 | |||||
503 | /* Compute __builtin_object_size for PTR, which is a ADDR_EXPR. | ||||
504 | OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. | ||||
505 | If unknown, return size_unknown (object_size_type). */ | ||||
506 | |||||
507 | static bool | ||||
508 | addr_object_size (struct object_size_info *osi, const_tree ptr, | ||||
509 | int object_size_type, tree *psize, tree *pwholesize) | ||||
510 | { | ||||
511 | tree pt_var, pt_var_size = NULL_TREE(tree) nullptr, pt_var_wholesize = NULL_TREE(tree) nullptr; | ||||
512 | tree var_size, bytes, wholebytes; | ||||
513 | |||||
514 | gcc_assert (TREE_CODE (ptr) == ADDR_EXPR)((void)(!(((enum tree_code) (ptr)->base.code) == ADDR_EXPR ) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 514, __FUNCTION__), 0 : 0)); | ||||
| |||||
515 | |||||
516 | /* Set to unknown and overwrite just before returning if the size | ||||
517 | could be determined. */ | ||||
518 | *psize = size_unknown (object_size_type); | ||||
519 | if (pwholesize) | ||||
520 | *pwholesize = size_unknown (object_size_type); | ||||
521 | |||||
522 | pt_var = TREE_OPERAND (ptr, 0)(*((const_cast<tree*> (tree_operand_check ((ptr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 522, __FUNCTION__))))); | ||||
523 | while (handled_component_p (pt_var)) | ||||
524 | pt_var = TREE_OPERAND (pt_var, 0)(*((const_cast<tree*> (tree_operand_check ((pt_var), (0 ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 524, __FUNCTION__))))); | ||||
525 | |||||
526 | if (!pt_var
| ||||
527 | return false; | ||||
528 | |||||
529 | if (TREE_CODE (pt_var)((enum tree_code) (pt_var)->base.code) == MEM_REF) | ||||
530 | { | ||||
531 | tree sz, wholesize; | ||||
532 | |||||
533 | if (!osi || (object_size_type & OST_SUBOBJECT) != 0 | ||||
534 | || TREE_CODE (TREE_OPERAND (pt_var, 0))((enum tree_code) ((*((const_cast<tree*> (tree_operand_check ((pt_var), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 534, __FUNCTION__))))))->base.code) != SSA_NAME) | ||||
535 | { | ||||
536 | compute_builtin_object_size (TREE_OPERAND (pt_var, 0)(*((const_cast<tree*> (tree_operand_check ((pt_var), (0 ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 536, __FUNCTION__))))), | ||||
537 | object_size_type & ~OST_SUBOBJECT, &sz); | ||||
538 | wholesize = sz; | ||||
539 | } | ||||
540 | else | ||||
541 | { | ||||
542 | tree var = TREE_OPERAND (pt_var, 0)(*((const_cast<tree*> (tree_operand_check ((pt_var), (0 ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 542, __FUNCTION__))))); | ||||
543 | if (osi->pass == 0) | ||||
544 | collect_object_sizes_for (osi, var); | ||||
545 | if (bitmap_bit_p (computed[object_size_type], | ||||
546 | SSA_NAME_VERSION (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 546, __FUNCTION__, (SSA_NAME)))->base.u.version)) | ||||
547 | { | ||||
548 | sz = object_sizes_get (osi, SSA_NAME_VERSION (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 548, __FUNCTION__, (SSA_NAME)))->base.u.version); | ||||
549 | wholesize = object_sizes_get (osi, SSA_NAME_VERSION (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 549, __FUNCTION__, (SSA_NAME)))->base.u.version, true); | ||||
550 | } | ||||
551 | else | ||||
552 | sz = wholesize = size_unknown (object_size_type); | ||||
553 | } | ||||
554 | if (!size_unknown_p (sz, object_size_type)) | ||||
555 | sz = size_for_offset (sz, TREE_OPERAND (pt_var, 1)(*((const_cast<tree*> (tree_operand_check ((pt_var), (1 ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 555, __FUNCTION__))))), wholesize); | ||||
556 | |||||
557 | if (!size_unknown_p (sz, object_size_type) | ||||
558 | && (TREE_CODE (sz)((enum tree_code) (sz)->base.code) != INTEGER_CST | ||||
559 | || compare_tree_int (sz, offset_limit) < 0)) | ||||
560 | { | ||||
561 | pt_var_size = sz; | ||||
562 | pt_var_wholesize = wholesize; | ||||
563 | } | ||||
564 | } | ||||
565 | else if (DECL_P (pt_var)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (pt_var)->base.code))] == tcc_declaration)) | ||||
566 | { | ||||
567 | pt_var_size = pt_var_wholesize | ||||
568 | = decl_init_size (pt_var, object_size_type & OST_MINIMUM); | ||||
569 | if (!pt_var_size) | ||||
570 | return false; | ||||
571 | } | ||||
572 | else if (TREE_CODE (pt_var)((enum tree_code) (pt_var)->base.code) == STRING_CST) | ||||
573 | pt_var_size = pt_var_wholesize = TYPE_SIZE_UNIT (TREE_TYPE (pt_var))((tree_class_check ((((contains_struct_check ((pt_var), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 573, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 573, __FUNCTION__))->type_common.size_unit); | ||||
574 | else | ||||
575 | return false; | ||||
576 | |||||
577 | if (pt_var_size) | ||||
578 | { | ||||
579 | /* Validate the size determined above if it is a constant. */ | ||||
580 | if (TREE_CODE (pt_var_size)((enum tree_code) (pt_var_size)->base.code) == INTEGER_CST | ||||
581 | && compare_tree_int (pt_var_size, offset_limit) >= 0) | ||||
582 | return false; | ||||
583 | } | ||||
584 | |||||
585 | if (pt_var != TREE_OPERAND (ptr, 0)(*((const_cast<tree*> (tree_operand_check ((ptr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 585, __FUNCTION__)))))) | ||||
586 | { | ||||
587 | tree var; | ||||
588 | |||||
589 | if (object_size_type & OST_SUBOBJECT) | ||||
590 | { | ||||
591 | var = TREE_OPERAND (ptr, 0)(*((const_cast<tree*> (tree_operand_check ((ptr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 591, __FUNCTION__))))); | ||||
592 | |||||
593 | while (var != pt_var | ||||
594 | && TREE_CODE (var)((enum tree_code) (var)->base.code) != BIT_FIELD_REF | ||||
595 | && TREE_CODE (var)((enum tree_code) (var)->base.code) != COMPONENT_REF | ||||
596 | && TREE_CODE (var)((enum tree_code) (var)->base.code) != ARRAY_REF | ||||
597 | && TREE_CODE (var)((enum tree_code) (var)->base.code) != ARRAY_RANGE_REF | ||||
598 | && TREE_CODE (var)((enum tree_code) (var)->base.code) != REALPART_EXPR | ||||
599 | && TREE_CODE (var)((enum tree_code) (var)->base.code) != IMAGPART_EXPR) | ||||
600 | var = TREE_OPERAND (var, 0)(*((const_cast<tree*> (tree_operand_check ((var), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 600, __FUNCTION__))))); | ||||
601 | if (var != pt_var && TREE_CODE (var)((enum tree_code) (var)->base.code) == ARRAY_REF) | ||||
602 | var = TREE_OPERAND (var, 0)(*((const_cast<tree*> (tree_operand_check ((var), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 602, __FUNCTION__))))); | ||||
603 | if (! TYPE_SIZE_UNIT (TREE_TYPE (var))((tree_class_check ((((contains_struct_check ((var), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 603, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 603, __FUNCTION__))->type_common.size_unit) | ||||
604 | || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (var))((tree_class_check ((((contains_struct_check ((var), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 604, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 604, __FUNCTION__))->type_common.size_unit)) | ||||
605 | || (pt_var_size && TREE_CODE (pt_var_size)((enum tree_code) (pt_var_size)->base.code) == INTEGER_CST | ||||
606 | && tree_int_cst_lt (pt_var_size, | ||||
607 | TYPE_SIZE_UNIT (TREE_TYPE (var))((tree_class_check ((((contains_struct_check ((var), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 607, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 607, __FUNCTION__))->type_common.size_unit)))) | ||||
608 | var = pt_var; | ||||
609 | else if (var != pt_var && TREE_CODE (pt_var)((enum tree_code) (pt_var)->base.code) == MEM_REF) | ||||
610 | { | ||||
611 | tree v = var; | ||||
612 | /* For &X->fld, compute object size if fld isn't a flexible array | ||||
613 | member. */ | ||||
614 | bool is_flexible_array_mem_ref = false; | ||||
615 | while (v && v != pt_var) | ||||
616 | switch (TREE_CODE (v)((enum tree_code) (v)->base.code)) | ||||
617 | { | ||||
618 | case ARRAY_REF: | ||||
619 | if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_OPERAND (v, 0)))((tree_class_check ((((contains_struct_check (((*((const_cast <tree*> (tree_operand_check ((v), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 619, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 619, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 619, __FUNCTION__))->type_common.size_unit)) | ||||
620 | { | ||||
621 | tree domain | ||||
622 | = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (v, 0)))((tree_check ((((contains_struct_check (((*((const_cast<tree *> (tree_operand_check ((v), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 622, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 622, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 622, __FUNCTION__, (ARRAY_TYPE)))->type_non_common.values ); | ||||
623 | if (domain && TYPE_MAX_VALUE (domain)((tree_check5 ((domain), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 623, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE ), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval )) | ||||
624 | { | ||||
625 | v = NULL_TREE(tree) nullptr; | ||||
626 | break; | ||||
627 | } | ||||
628 | } | ||||
629 | v = TREE_OPERAND (v, 0)(*((const_cast<tree*> (tree_operand_check ((v), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 629, __FUNCTION__))))); | ||||
630 | break; | ||||
631 | case REALPART_EXPR: | ||||
632 | case IMAGPART_EXPR: | ||||
633 | v = NULL_TREE(tree) nullptr; | ||||
634 | break; | ||||
635 | case COMPONENT_REF: | ||||
636 | if (TREE_CODE (TREE_TYPE (v))((enum tree_code) (((contains_struct_check ((v), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 636, __FUNCTION__))->typed.type))->base.code) != ARRAY_TYPE) | ||||
637 | { | ||||
638 | v = NULL_TREE(tree) nullptr; | ||||
639 | break; | ||||
640 | } | ||||
641 | is_flexible_array_mem_ref = array_ref_flexible_size_p (v); | ||||
642 | while (v != pt_var && TREE_CODE (v)((enum tree_code) (v)->base.code) == COMPONENT_REF) | ||||
643 | if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))((enum tree_code) (((contains_struct_check (((*((const_cast< tree*> (tree_operand_check ((v), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 643, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 643, __FUNCTION__))->typed.type))->base.code) | ||||
644 | != UNION_TYPE | ||||
645 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))((enum tree_code) (((contains_struct_check (((*((const_cast< tree*> (tree_operand_check ((v), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 645, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 645, __FUNCTION__))->typed.type))->base.code) | ||||
646 | != QUAL_UNION_TYPE) | ||||
647 | break; | ||||
648 | else | ||||
649 | v = TREE_OPERAND (v, 0)(*((const_cast<tree*> (tree_operand_check ((v), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 649, __FUNCTION__))))); | ||||
650 | if (TREE_CODE (v)((enum tree_code) (v)->base.code) == COMPONENT_REF | ||||
651 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))((enum tree_code) (((contains_struct_check (((*((const_cast< tree*> (tree_operand_check ((v), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 651, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 651, __FUNCTION__))->typed.type))->base.code) | ||||
652 | == RECORD_TYPE) | ||||
653 | { | ||||
654 | /* compute object size only if v is not a | ||||
655 | flexible array member. */ | ||||
656 | if (!is_flexible_array_mem_ref) | ||||
657 | { | ||||
658 | v = NULL_TREE(tree) nullptr; | ||||
659 | break; | ||||
660 | } | ||||
661 | v = TREE_OPERAND (v, 0)(*((const_cast<tree*> (tree_operand_check ((v), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 661, __FUNCTION__))))); | ||||
662 | } | ||||
663 | while (v != pt_var && TREE_CODE (v)((enum tree_code) (v)->base.code) == COMPONENT_REF) | ||||
664 | if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))((enum tree_code) (((contains_struct_check (((*((const_cast< tree*> (tree_operand_check ((v), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 664, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 664, __FUNCTION__))->typed.type))->base.code) | ||||
665 | != UNION_TYPE | ||||
666 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))((enum tree_code) (((contains_struct_check (((*((const_cast< tree*> (tree_operand_check ((v), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 666, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 666, __FUNCTION__))->typed.type))->base.code) | ||||
667 | != QUAL_UNION_TYPE) | ||||
668 | break; | ||||
669 | else | ||||
670 | v = TREE_OPERAND (v, 0)(*((const_cast<tree*> (tree_operand_check ((v), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 670, __FUNCTION__))))); | ||||
671 | if (v != pt_var) | ||||
672 | v = NULL_TREE(tree) nullptr; | ||||
673 | else | ||||
674 | v = pt_var; | ||||
675 | break; | ||||
676 | default: | ||||
677 | v = pt_var; | ||||
678 | break; | ||||
679 | } | ||||
680 | if (v == pt_var) | ||||
681 | var = pt_var; | ||||
682 | } | ||||
683 | } | ||||
684 | else | ||||
685 | var = pt_var; | ||||
686 | |||||
687 | if (var != pt_var) | ||||
688 | { | ||||
689 | var_size = TYPE_SIZE_UNIT (TREE_TYPE (var))((tree_class_check ((((contains_struct_check ((var), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 689, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 689, __FUNCTION__))->type_common.size_unit); | ||||
690 | if (!TREE_CONSTANT (var_size)((non_type_check ((var_size), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 690, __FUNCTION__))->base.constant_flag)) | ||||
691 | var_size = get_or_create_ssa_default_def (cfun(cfun + 0), var_size); | ||||
692 | if (!var_size) | ||||
693 | return false; | ||||
694 | } | ||||
695 | else if (!pt_var_size) | ||||
696 | return false; | ||||
697 | else | ||||
698 | var_size = pt_var_size; | ||||
699 | bytes = compute_object_offset (TREE_OPERAND (ptr, 0)(*((const_cast<tree*> (tree_operand_check ((ptr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 699, __FUNCTION__))))), var); | ||||
700 | if (bytes != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | ||||
701 | { | ||||
702 | bytes = size_for_offset (var_size, bytes); | ||||
703 | if (var != pt_var && pt_var_size && TREE_CODE (pt_var)((enum tree_code) (pt_var)->base.code) == MEM_REF) | ||||
704 | { | ||||
705 | tree bytes2 = compute_object_offset (TREE_OPERAND (ptr, 0)(*((const_cast<tree*> (tree_operand_check ((ptr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 705, __FUNCTION__))))), | ||||
706 | pt_var); | ||||
707 | if (bytes2 != error_mark_nodeglobal_trees[TI_ERROR_MARK]) | ||||
708 | { | ||||
709 | bytes2 = size_for_offset (pt_var_size, bytes2); | ||||
710 | bytes = size_binop (MIN_EXPR, bytes, bytes2)size_binop_loc (((location_t) 0), MIN_EXPR, bytes, bytes2); | ||||
711 | } | ||||
712 | } | ||||
713 | } | ||||
714 | else | ||||
715 | bytes = size_unknown (object_size_type); | ||||
716 | |||||
717 | wholebytes | ||||
718 | = object_size_type & OST_SUBOBJECT ? var_size : pt_var_wholesize; | ||||
719 | } | ||||
720 | else if (!pt_var_size) | ||||
721 | return false; | ||||
722 | else | ||||
723 | { | ||||
724 | bytes = pt_var_size; | ||||
725 | wholebytes = pt_var_wholesize; | ||||
726 | } | ||||
727 | |||||
728 | if (!size_unknown_p (bytes, object_size_type) | ||||
729 | && size_valid_p (bytes, object_size_type) | ||||
730 | && !size_unknown_p (bytes, object_size_type) | ||||
731 | && size_valid_p (wholebytes, object_size_type)) | ||||
732 | { | ||||
733 | *psize = bytes; | ||||
734 | if (pwholesize) | ||||
735 | *pwholesize = wholebytes; | ||||
736 | return true; | ||||
737 | } | ||||
738 | |||||
739 | return false; | ||||
740 | } | ||||
741 | |||||
742 | |||||
743 | /* Compute __builtin_object_size for CALL, which is a GIMPLE_CALL. | ||||
744 | Handles calls to functions declared with attribute alloc_size. | ||||
745 | OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. | ||||
746 | If unknown, return size_unknown (object_size_type). */ | ||||
747 | |||||
748 | static tree | ||||
749 | alloc_object_size (const gcall *call, int object_size_type) | ||||
750 | { | ||||
751 | gcc_assert (is_gimple_call (call))((void)(!(is_gimple_call (call)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 751, __FUNCTION__), 0 : 0)); | ||||
752 | |||||
753 | tree calltype; | ||||
754 | tree callfn = gimple_call_fndecl (call); | ||||
755 | if (callfn) | ||||
756 | calltype = TREE_TYPE (callfn)((contains_struct_check ((callfn), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 756, __FUNCTION__))->typed.type); | ||||
757 | else | ||||
758 | calltype = gimple_call_fntype (call); | ||||
759 | |||||
760 | if (!calltype) | ||||
761 | return size_unknown (object_size_type); | ||||
762 | |||||
763 | /* Set to positions of alloc_size arguments. */ | ||||
764 | int arg1 = -1, arg2 = -1; | ||||
765 | tree alloc_size = lookup_attribute ("alloc_size", | ||||
766 | TYPE_ATTRIBUTES (calltype)((tree_class_check ((calltype), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 766, __FUNCTION__))->type_common.attributes)); | ||||
767 | if (alloc_size && TREE_VALUE (alloc_size)((tree_check ((alloc_size), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 767, __FUNCTION__, (TREE_LIST)))->list.value)) | ||||
768 | { | ||||
769 | tree p = TREE_VALUE (alloc_size)((tree_check ((alloc_size), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 769, __FUNCTION__, (TREE_LIST)))->list.value); | ||||
770 | |||||
771 | arg1 = TREE_INT_CST_LOW (TREE_VALUE (p))((unsigned long) (*tree_int_cst_elt_check ((((tree_check ((p) , "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 771, __FUNCTION__, (TREE_LIST)))->list.value)), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 771, __FUNCTION__)))-1; | ||||
772 | if (TREE_CHAIN (p)((contains_struct_check ((p), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 772, __FUNCTION__))->common.chain)) | ||||
773 | arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))((unsigned long) (*tree_int_cst_elt_check ((((tree_check (((( contains_struct_check ((p), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 773, __FUNCTION__))->common.chain)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 773, __FUNCTION__, (TREE_LIST)))->list.value)), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 773, __FUNCTION__)))-1; | ||||
774 | } | ||||
775 | else if (gimple_call_builtin_p (call, BUILT_IN_NORMAL) | ||||
776 | && callfn && ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (callfn))((DECL_FUNCTION_CODE (callfn)) == BUILT_IN_ALLOCA || (DECL_FUNCTION_CODE (callfn)) == BUILT_IN_ALLOCA_WITH_ALIGN || (DECL_FUNCTION_CODE (callfn)) == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX)) | ||||
777 | arg1 = 0; | ||||
778 | |||||
779 | /* Non-const arguments are OK here, let the caller handle constness. */ | ||||
780 | if (arg1 < 0 || arg1 >= (int) gimple_call_num_args (call) | ||||
781 | || arg2 >= (int) gimple_call_num_args (call)) | ||||
782 | return size_unknown (object_size_type); | ||||
783 | |||||
784 | tree bytes = NULL_TREE(tree) nullptr; | ||||
785 | if (arg2 >= 0) | ||||
786 | bytes = size_binop (MULT_EXPR,size_binop_loc (((location_t) 0), MULT_EXPR, fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_sizetype], gimple_call_arg (call, arg1)), fold_convert_loc (((location_t) 0), sizetype_tab [(int) stk_sizetype], gimple_call_arg (call, arg2))) | ||||
787 | fold_convert (sizetype, gimple_call_arg (call, arg1)),size_binop_loc (((location_t) 0), MULT_EXPR, fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_sizetype], gimple_call_arg (call, arg1)), fold_convert_loc (((location_t) 0), sizetype_tab [(int) stk_sizetype], gimple_call_arg (call, arg2))) | ||||
788 | fold_convert (sizetype, gimple_call_arg (call, arg2)))size_binop_loc (((location_t) 0), MULT_EXPR, fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_sizetype], gimple_call_arg (call, arg1)), fold_convert_loc (((location_t) 0), sizetype_tab [(int) stk_sizetype], gimple_call_arg (call, arg2))); | ||||
789 | else if (arg1 >= 0) | ||||
790 | bytes = fold_convert (sizetype, gimple_call_arg (call, arg1))fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_sizetype ], gimple_call_arg (call, arg1)); | ||||
791 | |||||
792 | return bytes ? bytes : size_unknown (object_size_type); | ||||
793 | } | ||||
794 | |||||
795 | /* Compute __builtin_object_size for CALL, which is a call to either | ||||
796 | BUILT_IN_STRDUP or BUILT_IN_STRNDUP; IS_STRNDUP indicates which it is. | ||||
797 | OBJECT_SIZE_TYPE is the second argument from __builtin_object_size. | ||||
798 | If unknown, return size_unknown (object_size_type). */ | ||||
799 | |||||
800 | static tree | ||||
801 | strdup_object_size (const gcall *call, int object_size_type, bool is_strndup) | ||||
802 | { | ||||
803 | tree src = gimple_call_arg (call, 0); | ||||
804 | tree sz = size_unknown (object_size_type); | ||||
805 | tree n = NULL_TREE(tree) nullptr; | ||||
806 | |||||
807 | if (is_strndup) | ||||
808 | n = fold_build2 (PLUS_EXPR, sizetype, size_one_node,fold_build2_loc (((location_t) 0), PLUS_EXPR, sizetype_tab[(int ) stk_sizetype], global_trees[TI_SIZE_ONE], gimple_call_arg ( call, 1) ) | ||||
809 | gimple_call_arg (call, 1))fold_build2_loc (((location_t) 0), PLUS_EXPR, sizetype_tab[(int ) stk_sizetype], global_trees[TI_SIZE_ONE], gimple_call_arg ( call, 1) ); | ||||
810 | /* For strdup, simply emit strlen (SRC) + 1 and let the optimizer fold it the | ||||
811 | way it likes. */ | ||||
812 | else | ||||
813 | { | ||||
814 | tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN); | ||||
815 | if (strlen_fn) | ||||
816 | { | ||||
817 | sz = fold_build2 (PLUS_EXPR, sizetype, size_one_node,fold_build2_loc (((location_t) 0), PLUS_EXPR, sizetype_tab[(int ) stk_sizetype], global_trees[TI_SIZE_ONE], build_call_expr ( strlen_fn, 1, src) ) | ||||
818 | build_call_expr (strlen_fn, 1, src))fold_build2_loc (((location_t) 0), PLUS_EXPR, sizetype_tab[(int ) stk_sizetype], global_trees[TI_SIZE_ONE], build_call_expr ( strlen_fn, 1, src) ); | ||||
819 | todo = TODO_update_ssa_only_virtuals(1 << 14); | ||||
820 | } | ||||
821 | } | ||||
822 | |||||
823 | /* In all other cases, return the size of SRC since the object size cannot | ||||
824 | exceed that. We cannot do this for OST_MINIMUM unless SRC points into a | ||||
825 | string constant since otherwise the object size could go all the way down | ||||
826 | to zero. */ | ||||
827 | if (!size_valid_p (sz, object_size_type) | ||||
828 | || size_unknown_p (sz, object_size_type)) | ||||
829 | { | ||||
830 | tree wholesrc = NULL_TREE(tree) nullptr; | ||||
831 | if (TREE_CODE (src)((enum tree_code) (src)->base.code) == ADDR_EXPR) | ||||
832 | wholesrc = get_base_address (TREE_OPERAND (src, 0)(*((const_cast<tree*> (tree_operand_check ((src), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 832, __FUNCTION__)))))); | ||||
833 | |||||
834 | /* If the source points within a string constant, we try to get its | ||||
835 | length. */ | ||||
836 | if (wholesrc && TREE_CODE (wholesrc)((enum tree_code) (wholesrc)->base.code) == STRING_CST) | ||||
837 | { | ||||
838 | tree len = c_strlen (src, 0); | ||||
839 | if (len) | ||||
840 | sz = fold_build2 (PLUS_EXPR, sizetype, size_one_node, len)fold_build2_loc (((location_t) 0), PLUS_EXPR, sizetype_tab[(int ) stk_sizetype], global_trees[TI_SIZE_ONE], len ); | ||||
841 | } | ||||
842 | |||||
843 | /* For maximum estimate, our next best guess is the object size of the | ||||
844 | source. */ | ||||
845 | if (size_unknown_p (sz, object_size_type) | ||||
846 | && !(object_size_type & OST_MINIMUM)) | ||||
847 | compute_builtin_object_size (src, object_size_type, &sz); | ||||
848 | } | ||||
849 | |||||
850 | /* String duplication allocates at least one byte, so we should never fail | ||||
851 | for OST_MINIMUM. */ | ||||
852 | if ((!size_valid_p (sz, object_size_type) | ||||
853 | || size_unknown_p (sz, object_size_type)) | ||||
854 | && (object_size_type & OST_MINIMUM)) | ||||
855 | sz = size_one_nodeglobal_trees[TI_SIZE_ONE]; | ||||
856 | |||||
857 | /* Factor in the N. */ | ||||
858 | return n ? fold_build2 (MIN_EXPR, sizetype, n, sz)fold_build2_loc (((location_t) 0), MIN_EXPR, sizetype_tab[(int ) stk_sizetype], n, sz ) : sz; | ||||
859 | } | ||||
860 | |||||
861 | /* If object size is propagated from one of function's arguments directly | ||||
862 | to its return value, return that argument for GIMPLE_CALL statement CALL. | ||||
863 | Otherwise return NULL. */ | ||||
864 | |||||
865 | static tree | ||||
866 | pass_through_call (const gcall *call) | ||||
867 | { | ||||
868 | unsigned rf = gimple_call_return_flags (call); | ||||
869 | if (rf & ERF_RETURNS_ARG(1 << 2)) | ||||
870 | { | ||||
871 | unsigned argnum = rf & ERF_RETURN_ARG_MASK(3); | ||||
872 | if (argnum < gimple_call_num_args (call)) | ||||
873 | return gimple_call_arg (call, argnum); | ||||
874 | } | ||||
875 | |||||
876 | /* __builtin_assume_aligned is intentionally not marked RET1. */ | ||||
877 | if (gimple_call_builtin_p (call, BUILT_IN_ASSUME_ALIGNED)) | ||||
878 | return gimple_call_arg (call, 0); | ||||
879 | |||||
880 | return NULL_TREE(tree) nullptr; | ||||
881 | } | ||||
882 | |||||
883 | /* Emit PHI nodes for size expressions fo. */ | ||||
884 | |||||
885 | static void | ||||
886 | emit_phi_nodes (gimple *stmt, tree size, tree wholesize) | ||||
887 | { | ||||
888 | tree phires; | ||||
889 | gphi *wholephi = NULLnullptr; | ||||
890 | |||||
891 | if (wholesize != size) | ||||
892 | { | ||||
893 | phires = TREE_VEC_ELT (wholesize, TREE_VEC_LENGTH (wholesize) - 1)(*((const_cast<tree *> (tree_vec_elt_check ((wholesize) , (((tree_check ((wholesize), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 893, __FUNCTION__, (TREE_VEC)))->base.u.length) - 1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 893, __FUNCTION__))))); | ||||
894 | wholephi = create_phi_node (phires, gimple_bb (stmt)); | ||||
895 | } | ||||
896 | |||||
897 | phires = TREE_VEC_ELT (size, TREE_VEC_LENGTH (size) - 1)(*((const_cast<tree *> (tree_vec_elt_check ((size), ((( tree_check ((size), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 897, __FUNCTION__, (TREE_VEC)))->base.u.length) - 1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 897, __FUNCTION__))))); | ||||
898 | gphi *phi = create_phi_node (phires, gimple_bb (stmt)); | ||||
899 | gphi *obj_phi = as_a <gphi *> (stmt); | ||||
900 | |||||
901 | gcc_checking_assert (TREE_CODE (wholesize) == TREE_VEC)((void)(!(((enum tree_code) (wholesize)->base.code) == TREE_VEC ) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 901, __FUNCTION__), 0 : 0)); | ||||
902 | gcc_checking_assert (TREE_CODE (size) == TREE_VEC)((void)(!(((enum tree_code) (size)->base.code) == TREE_VEC ) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 902, __FUNCTION__), 0 : 0)); | ||||
903 | |||||
904 | for (unsigned i = 0; i < gimple_phi_num_args (stmt); i++) | ||||
905 | { | ||||
906 | gimple_seq seq = NULLnullptr; | ||||
907 | tree wsz = TREE_VEC_ELT (wholesize, i)(*((const_cast<tree *> (tree_vec_elt_check ((wholesize) , (i), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 907, __FUNCTION__))))); | ||||
908 | tree sz = TREE_VEC_ELT (size, i)(*((const_cast<tree *> (tree_vec_elt_check ((size), (i) , "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 908, __FUNCTION__))))); | ||||
909 | |||||
910 | /* If we built an expression, we will need to build statements | ||||
911 | and insert them on the edge right away. */ | ||||
912 | if (TREE_CODE (wsz)((enum tree_code) (wsz)->base.code) != SSA_NAME) | ||||
913 | wsz = force_gimple_operand (wsz, &seq, true, NULLnullptr); | ||||
914 | if (TREE_CODE (sz)((enum tree_code) (sz)->base.code) != SSA_NAME) | ||||
915 | { | ||||
916 | gimple_seq s; | ||||
917 | sz = force_gimple_operand (sz, &s, true, NULLnullptr); | ||||
918 | gimple_seq_add_seq (&seq, s); | ||||
919 | } | ||||
920 | |||||
921 | if (seq) | ||||
922 | gsi_insert_seq_on_edge (gimple_phi_arg_edge (obj_phi, i), seq); | ||||
923 | |||||
924 | if (wholephi) | ||||
925 | add_phi_arg (wholephi, wsz, | ||||
926 | gimple_phi_arg_edge (obj_phi, i), | ||||
927 | gimple_phi_arg_location (obj_phi, i)); | ||||
928 | |||||
929 | add_phi_arg (phi, sz, | ||||
930 | gimple_phi_arg_edge (obj_phi, i), | ||||
931 | gimple_phi_arg_location (obj_phi, i)); | ||||
932 | } | ||||
933 | } | ||||
934 | |||||
935 | /* Descend through EXPR and return size_unknown if it uses any SSA variable | ||||
936 | object_size_set or object_size_set_temp generated, which turned out to be | ||||
937 | size_unknown, as noted in UNKNOWNS. */ | ||||
938 | |||||
939 | static tree | ||||
940 | propagate_unknowns (object_size_info *osi, tree expr) | ||||
941 | { | ||||
942 | int object_size_type = osi->object_size_type; | ||||
943 | |||||
944 | switch (TREE_CODE (expr)((enum tree_code) (expr)->base.code)) | ||||
945 | { | ||||
946 | case SSA_NAME: | ||||
947 | if (bitmap_bit_p (osi->unknowns, SSA_NAME_VERSION (expr)(tree_check ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 947, __FUNCTION__, (SSA_NAME)))->base.u.version)) | ||||
948 | return size_unknown (object_size_type); | ||||
949 | return expr; | ||||
950 | |||||
951 | case MIN_EXPR: | ||||
952 | case MAX_EXPR: | ||||
953 | { | ||||
954 | tree res = propagate_unknowns (osi, TREE_OPERAND (expr, 0)(*((const_cast<tree*> (tree_operand_check ((expr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 954, __FUNCTION__)))))); | ||||
955 | if (size_unknown_p (res, object_size_type)) | ||||
956 | return res; | ||||
957 | |||||
958 | res = propagate_unknowns (osi, TREE_OPERAND (expr, 1)(*((const_cast<tree*> (tree_operand_check ((expr), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 958, __FUNCTION__)))))); | ||||
959 | if (size_unknown_p (res, object_size_type)) | ||||
960 | return res; | ||||
961 | |||||
962 | return expr; | ||||
963 | } | ||||
964 | case MODIFY_EXPR: | ||||
965 | { | ||||
966 | tree res = propagate_unknowns (osi, TREE_OPERAND (expr, 1)(*((const_cast<tree*> (tree_operand_check ((expr), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 966, __FUNCTION__)))))); | ||||
967 | if (size_unknown_p (res, object_size_type)) | ||||
968 | return res; | ||||
969 | return expr; | ||||
970 | } | ||||
971 | case TREE_VEC: | ||||
972 | for (int i = 0; i < TREE_VEC_LENGTH (expr)((tree_check ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 972, __FUNCTION__, (TREE_VEC)))->base.u.length); i++) | ||||
973 | { | ||||
974 | tree res = propagate_unknowns (osi, TREE_VEC_ELT (expr, i)(*((const_cast<tree *> (tree_vec_elt_check ((expr), (i) , "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 974, __FUNCTION__)))))); | ||||
975 | if (size_unknown_p (res, object_size_type)) | ||||
976 | return res; | ||||
977 | } | ||||
978 | return expr; | ||||
979 | case PLUS_EXPR: | ||||
980 | case MINUS_EXPR: | ||||
981 | { | ||||
982 | tree res = propagate_unknowns (osi, TREE_OPERAND (expr, 0)(*((const_cast<tree*> (tree_operand_check ((expr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 982, __FUNCTION__)))))); | ||||
983 | if (size_unknown_p (res, object_size_type)) | ||||
984 | return res; | ||||
985 | |||||
986 | return expr; | ||||
987 | } | ||||
988 | default: | ||||
989 | return expr; | ||||
990 | } | ||||
991 | } | ||||
992 | |||||
993 | /* Walk through size expressions that need reexamination and generate | ||||
994 | statements for them. */ | ||||
995 | |||||
996 | static void | ||||
997 | gimplify_size_expressions (object_size_info *osi) | ||||
998 | { | ||||
999 | int object_size_type = osi->object_size_type; | ||||
1000 | bitmap_iterator bi; | ||||
1001 | unsigned int i; | ||||
1002 | bool changed; | ||||
1003 | |||||
1004 | /* Step 1: Propagate unknowns into expressions. */ | ||||
1005 | bitmap reexamine = BITMAP_ALLOCbitmap_alloc (NULLnullptr); | ||||
1006 | bitmap_copy (reexamine, osi->reexamine); | ||||
1007 | do | ||||
1008 | { | ||||
1009 | changed = false; | ||||
1010 | EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)for (bmp_iter_set_init (&(bi), (reexamine), (0), &(i) ); bmp_iter_set (&(bi), &(i)); bmp_iter_next (&(bi ), &(i))) | ||||
1011 | { | ||||
1012 | object_size cur = object_sizes_get_raw (osi, i); | ||||
1013 | |||||
1014 | if (size_unknown_p (propagate_unknowns (osi, cur.size), | ||||
1015 | object_size_type) | ||||
1016 | || size_unknown_p (propagate_unknowns (osi, cur.wholesize), | ||||
1017 | object_size_type)) | ||||
1018 | { | ||||
1019 | object_sizes_set (osi, i, | ||||
1020 | size_unknown (object_size_type), | ||||
1021 | size_unknown (object_size_type)); | ||||
1022 | changed = true; | ||||
1023 | } | ||||
1024 | } | ||||
1025 | bitmap_copy (reexamine, osi->reexamine); | ||||
1026 | } | ||||
1027 | while (changed); | ||||
1028 | |||||
1029 | /* Release all unknowns. */ | ||||
1030 | EXECUTE_IF_SET_IN_BITMAP (osi->unknowns, 0, i, bi)for (bmp_iter_set_init (&(bi), (osi->unknowns), (0), & (i)); bmp_iter_set (&(bi), &(i)); bmp_iter_next (& (bi), &(i))) | ||||
1031 | release_ssa_name (ssa_name (i)((*(cfun + 0)->gimple_df->ssa_names)[(i)])); | ||||
1032 | |||||
1033 | /* Expand all size expressions to put their definitions close to the objects | ||||
1034 | for which size is being computed. */ | ||||
1035 | EXECUTE_IF_SET_IN_BITMAP (osi->reexamine, 0, i, bi)for (bmp_iter_set_init (&(bi), (osi->reexamine), (0), & (i)); bmp_iter_set (&(bi), &(i)); bmp_iter_next (& (bi), &(i))) | ||||
1036 | { | ||||
1037 | gimple_seq seq = NULLnullptr; | ||||
1038 | object_size osize = object_sizes_get_raw (osi, i); | ||||
1039 | |||||
1040 | gimple *stmt = SSA_NAME_DEF_STMT (ssa_name (i))(tree_check ((((*(cfun + 0)->gimple_df->ssa_names)[(i)] )), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1040, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt; | ||||
1041 | enum gimple_code code = gimple_code (stmt); | ||||
1042 | |||||
1043 | /* PHI nodes need special attention. */ | ||||
1044 | if (code == GIMPLE_PHI) | ||||
1045 | emit_phi_nodes (stmt, osize.size, osize.wholesize); | ||||
1046 | else | ||||
1047 | { | ||||
1048 | tree size_expr = NULL_TREE(tree) nullptr; | ||||
1049 | |||||
1050 | /* Bundle wholesize in with the size to gimplify if needed. */ | ||||
1051 | if (osize.wholesize != osize.size | ||||
1052 | && !size_usable_p (osize.wholesize)) | ||||
1053 | size_expr = size_binop (COMPOUND_EXPR,size_binop_loc (((location_t) 0), COMPOUND_EXPR, osize.wholesize , osize.size) | ||||
1054 | osize.wholesize,size_binop_loc (((location_t) 0), COMPOUND_EXPR, osize.wholesize , osize.size) | ||||
1055 | osize.size)size_binop_loc (((location_t) 0), COMPOUND_EXPR, osize.wholesize , osize.size); | ||||
1056 | else if (!size_usable_p (osize.size)) | ||||
1057 | size_expr = osize.size; | ||||
1058 | |||||
1059 | if (size_expr) | ||||
1060 | { | ||||
1061 | gimple_stmt_iterator gsi; | ||||
1062 | if (code == GIMPLE_NOP) | ||||
1063 | gsi = gsi_start_bb (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_entry_block_ptr))); | ||||
1064 | else | ||||
1065 | gsi = gsi_for_stmt (stmt); | ||||
1066 | |||||
1067 | force_gimple_operand (size_expr, &seq, true, NULLnullptr); | ||||
1068 | gsi_insert_seq_before (&gsi, seq, GSI_CONTINUE_LINKING); | ||||
1069 | } | ||||
1070 | } | ||||
1071 | |||||
1072 | /* We're done, so replace the MODIFY_EXPRs with the SSA names. */ | ||||
1073 | object_sizes_initialize (osi, i, | ||||
1074 | object_sizes_get (osi, i), | ||||
1075 | object_sizes_get (osi, i, true)); | ||||
1076 | } | ||||
1077 | } | ||||
1078 | |||||
1079 | /* Compute __builtin_object_size value for PTR and set *PSIZE to | ||||
1080 | the resulting value. If the declared object is known and PDECL | ||||
1081 | is nonnull, sets *PDECL to the object's DECL. OBJECT_SIZE_TYPE | ||||
1082 | is the second argument to __builtin_object_size. | ||||
1083 | Returns true on success and false when the object size could not | ||||
1084 | be determined. */ | ||||
1085 | |||||
1086 | bool | ||||
1087 | compute_builtin_object_size (tree ptr, int object_size_type, | ||||
1088 | tree *psize) | ||||
1089 | { | ||||
1090 | gcc_assert (object_size_type >= 0 && object_size_type < OST_END)((void)(!(object_size_type >= 0 && object_size_type < OST_END) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1090, __FUNCTION__), 0 : 0)); | ||||
1091 | |||||
1092 | /* Set to unknown and overwrite just before returning if the size | ||||
1093 | could be determined. */ | ||||
1094 | *psize = size_unknown (object_size_type); | ||||
1095 | |||||
1096 | if (! offset_limit) | ||||
1097 | init_offset_limit (); | ||||
1098 | |||||
1099 | if (TREE_CODE (ptr)((enum tree_code) (ptr)->base.code) == ADDR_EXPR) | ||||
1100 | return addr_object_size (NULLnullptr, ptr, object_size_type, psize); | ||||
1101 | |||||
1102 | if (TREE_CODE (ptr)((enum tree_code) (ptr)->base.code) != SSA_NAME | ||||
1103 | || !POINTER_TYPE_P (TREE_TYPE (ptr))(((enum tree_code) (((contains_struct_check ((ptr), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1103, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((ptr), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1103, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE )) | ||||
1104 | return false; | ||||
1105 | |||||
1106 | if (computed[object_size_type] == NULLnullptr) | ||||
1107 | { | ||||
1108 | if (optimizeglobal_options.x_optimize || object_size_type & OST_SUBOBJECT) | ||||
1109 | return false; | ||||
1110 | |||||
1111 | /* When not optimizing, rather than failing, make a small effort | ||||
1112 | to determine the object size without the full benefit of | ||||
1113 | the (costly) computation below. */ | ||||
1114 | gimple *def = SSA_NAME_DEF_STMT (ptr)(tree_check ((ptr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1114, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt; | ||||
1115 | if (gimple_code (def) == GIMPLE_ASSIGN) | ||||
1116 | { | ||||
1117 | tree_code code = gimple_assign_rhs_code (def); | ||||
1118 | if (code == POINTER_PLUS_EXPR) | ||||
1119 | { | ||||
1120 | tree offset = gimple_assign_rhs2 (def); | ||||
1121 | ptr = gimple_assign_rhs1 (def); | ||||
1122 | |||||
1123 | if (((object_size_type & OST_DYNAMIC) | ||||
1124 | || (tree_fits_shwi_p (offset) | ||||
1125 | && compare_tree_int (offset, offset_limit) <= 0)) | ||||
1126 | && compute_builtin_object_size (ptr, object_size_type, | ||||
1127 | psize)) | ||||
1128 | { | ||||
1129 | *psize = size_for_offset (*psize, offset); | ||||
1130 | return true; | ||||
1131 | } | ||||
1132 | } | ||||
1133 | } | ||||
1134 | return false; | ||||
1135 | } | ||||
1136 | |||||
1137 | struct object_size_info osi; | ||||
1138 | osi.object_size_type = object_size_type; | ||||
1139 | if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr)(tree_check ((ptr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1139, __FUNCTION__, (SSA_NAME)))->base.u.version)) | ||||
1140 | { | ||||
1141 | bitmap_iterator bi; | ||||
1142 | unsigned int i; | ||||
1143 | |||||
1144 | object_sizes_grow (object_size_type); | ||||
1145 | if (dump_file) | ||||
1146 | { | ||||
1147 | fprintf (dump_file, "Computing %s %s%sobject size for ", | ||||
1148 | (object_size_type & OST_MINIMUM) ? "minimum" : "maximum", | ||||
1149 | (object_size_type & OST_DYNAMIC) ? "dynamic " : "", | ||||
1150 | (object_size_type & OST_SUBOBJECT) ? "sub" : ""); | ||||
1151 | print_generic_expr (dump_file, ptr, dump_flags); | ||||
1152 | fprintf (dump_file, ":\n"); | ||||
1153 | } | ||||
1154 | |||||
1155 | osi.visited = BITMAP_ALLOCbitmap_alloc (NULLnullptr); | ||||
1156 | osi.reexamine = BITMAP_ALLOCbitmap_alloc (NULLnullptr); | ||||
1157 | |||||
1158 | if (object_size_type & OST_DYNAMIC) | ||||
1159 | osi.unknowns = BITMAP_ALLOCbitmap_alloc (NULLnullptr); | ||||
1160 | else | ||||
1161 | { | ||||
1162 | osi.depths = NULLnullptr; | ||||
1163 | osi.stack = NULLnullptr; | ||||
1164 | osi.tos = NULLnullptr; | ||||
1165 | } | ||||
1166 | |||||
1167 | /* First pass: walk UD chains, compute object sizes that | ||||
1168 | can be computed. osi.reexamine bitmap at the end will | ||||
1169 | contain what variables were found in dependency cycles | ||||
1170 | and therefore need to be reexamined. */ | ||||
1171 | osi.pass = 0; | ||||
1172 | osi.changed = false; | ||||
1173 | collect_object_sizes_for (&osi, ptr); | ||||
1174 | |||||
1175 | if (object_size_type & OST_DYNAMIC) | ||||
1176 | { | ||||
1177 | osi.pass = 1; | ||||
1178 | gimplify_size_expressions (&osi); | ||||
1179 | BITMAP_FREE (osi.unknowns)((void) (bitmap_obstack_free ((bitmap) osi.unknowns), (osi.unknowns ) = (bitmap) nullptr)); | ||||
1180 | bitmap_clear (osi.reexamine); | ||||
1181 | } | ||||
1182 | |||||
1183 | /* Second pass: keep recomputing object sizes of variables | ||||
1184 | that need reexamination, until no object sizes are | ||||
1185 | increased or all object sizes are computed. */ | ||||
1186 | if (! bitmap_empty_p (osi.reexamine)) | ||||
1187 | { | ||||
1188 | bitmap reexamine = BITMAP_ALLOCbitmap_alloc (NULLnullptr); | ||||
1189 | |||||
1190 | /* If looking for minimum instead of maximum object size, | ||||
1191 | detect cases where a pointer is increased in a loop. | ||||
1192 | Although even without this detection pass 2 would eventually | ||||
1193 | terminate, it could take a long time. If a pointer is | ||||
1194 | increasing this way, we need to assume 0 object size. | ||||
1195 | E.g. p = &buf[0]; while (cond) p = p + 4; */ | ||||
1196 | if (object_size_type & OST_MINIMUM) | ||||
1197 | { | ||||
1198 | osi.depths = XCNEWVEC (unsigned int, num_ssa_names)((unsigned int *) xcalloc (((vec_safe_length ((cfun + 0)-> gimple_df->ssa_names))), sizeof (unsigned int))); | ||||
1199 | osi.stack = XNEWVEC (unsigned int, num_ssa_names)((unsigned int *) xmalloc (sizeof (unsigned int) * ((vec_safe_length ((cfun + 0)->gimple_df->ssa_names))))); | ||||
1200 | osi.tos = osi.stack; | ||||
1201 | osi.pass = 1; | ||||
1202 | /* collect_object_sizes_for is changing | ||||
1203 | osi.reexamine bitmap, so iterate over a copy. */ | ||||
1204 | bitmap_copy (reexamine, osi.reexamine); | ||||
1205 | EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)for (bmp_iter_set_init (&(bi), (reexamine), (0), &(i) ); bmp_iter_set (&(bi), &(i)); bmp_iter_next (&(bi ), &(i))) | ||||
1206 | if (bitmap_bit_p (osi.reexamine, i)) | ||||
1207 | check_for_plus_in_loops (&osi, ssa_name (i)((*(cfun + 0)->gimple_df->ssa_names)[(i)])); | ||||
1208 | |||||
1209 | free (osi.depths); | ||||
1210 | osi.depths = NULLnullptr; | ||||
1211 | free (osi.stack); | ||||
1212 | osi.stack = NULLnullptr; | ||||
1213 | osi.tos = NULLnullptr; | ||||
1214 | } | ||||
1215 | |||||
1216 | do | ||||
1217 | { | ||||
1218 | osi.pass = 2; | ||||
1219 | osi.changed = false; | ||||
1220 | /* collect_object_sizes_for is changing | ||||
1221 | osi.reexamine bitmap, so iterate over a copy. */ | ||||
1222 | bitmap_copy (reexamine, osi.reexamine); | ||||
1223 | EXECUTE_IF_SET_IN_BITMAP (reexamine, 0, i, bi)for (bmp_iter_set_init (&(bi), (reexamine), (0), &(i) ); bmp_iter_set (&(bi), &(i)); bmp_iter_next (&(bi ), &(i))) | ||||
1224 | if (bitmap_bit_p (osi.reexamine, i)) | ||||
1225 | { | ||||
1226 | collect_object_sizes_for (&osi, ssa_name (i)((*(cfun + 0)->gimple_df->ssa_names)[(i)])); | ||||
1227 | if (dump_file && (dump_flags & TDF_DETAILS)) | ||||
1228 | { | ||||
1229 | fprintf (dump_file, "Reexamining "); | ||||
1230 | print_generic_expr (dump_file, ssa_name (i)((*(cfun + 0)->gimple_df->ssa_names)[(i)]), | ||||
1231 | dump_flags); | ||||
1232 | fprintf (dump_file, "\n"); | ||||
1233 | } | ||||
1234 | } | ||||
1235 | } | ||||
1236 | while (osi.changed); | ||||
1237 | |||||
1238 | BITMAP_FREE (reexamine)((void) (bitmap_obstack_free ((bitmap) reexamine), (reexamine ) = (bitmap) nullptr)); | ||||
1239 | } | ||||
1240 | EXECUTE_IF_SET_IN_BITMAP (osi.reexamine, 0, i, bi)for (bmp_iter_set_init (&(bi), (osi.reexamine), (0), & (i)); bmp_iter_set (&(bi), &(i)); bmp_iter_next (& (bi), &(i))) | ||||
1241 | bitmap_set_bit (computed[object_size_type], i); | ||||
1242 | |||||
1243 | /* Debugging dumps. */ | ||||
1244 | if (dump_file) | ||||
1245 | { | ||||
1246 | EXECUTE_IF_SET_IN_BITMAP (osi.visited, 0, i, bi)for (bmp_iter_set_init (&(bi), (osi.visited), (0), &( i)); bmp_iter_set (&(bi), &(i)); bmp_iter_next (& (bi), &(i))) | ||||
1247 | if (!object_sizes_unknown_p (object_size_type, i)) | ||||
1248 | { | ||||
1249 | print_generic_expr (dump_file, ssa_name (i)((*(cfun + 0)->gimple_df->ssa_names)[(i)]), | ||||
1250 | dump_flags); | ||||
1251 | fprintf (dump_file, | ||||
1252 | ": %s %s%sobject size ", | ||||
1253 | ((object_size_type & OST_MINIMUM) ? "minimum" | ||||
1254 | : "maximum"), | ||||
1255 | (object_size_type & OST_DYNAMIC) ? "dynamic " : "", | ||||
1256 | (object_size_type & OST_SUBOBJECT) ? "sub" : ""); | ||||
1257 | print_generic_expr (dump_file, object_sizes_get (&osi, i), | ||||
1258 | dump_flags); | ||||
1259 | fprintf (dump_file, "\n"); | ||||
1260 | } | ||||
1261 | } | ||||
1262 | |||||
1263 | BITMAP_FREE (osi.reexamine)((void) (bitmap_obstack_free ((bitmap) osi.reexamine), (osi.reexamine ) = (bitmap) nullptr)); | ||||
1264 | BITMAP_FREE (osi.visited)((void) (bitmap_obstack_free ((bitmap) osi.visited), (osi.visited ) = (bitmap) nullptr)); | ||||
1265 | } | ||||
1266 | |||||
1267 | *psize = object_sizes_get (&osi, SSA_NAME_VERSION (ptr)(tree_check ((ptr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1267, __FUNCTION__, (SSA_NAME)))->base.u.version); | ||||
1268 | return !size_unknown_p (*psize, object_size_type); | ||||
1269 | } | ||||
1270 | |||||
1271 | /* Compute object_sizes for PTR, defined to VALUE, which is not an SSA_NAME. */ | ||||
1272 | |||||
1273 | static void | ||||
1274 | expr_object_size (struct object_size_info *osi, tree ptr, tree value) | ||||
1275 | { | ||||
1276 | int object_size_type = osi->object_size_type; | ||||
1277 | unsigned int varno = SSA_NAME_VERSION (ptr)(tree_check ((ptr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1277, __FUNCTION__, (SSA_NAME)))->base.u.version; | ||||
1278 | tree bytes, wholesize; | ||||
1279 | |||||
1280 | gcc_assert (!object_sizes_unknown_p (object_size_type, varno))((void)(!(!object_sizes_unknown_p (object_size_type, varno)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1280, __FUNCTION__), 0 : 0)); | ||||
1281 | gcc_assert (osi->pass == 0)((void)(!(osi->pass == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1281, __FUNCTION__), 0 : 0)); | ||||
1282 | |||||
1283 | if (TREE_CODE (value)((enum tree_code) (value)->base.code) == WITH_SIZE_EXPR) | ||||
1284 | value = TREE_OPERAND (value, 0)(*((const_cast<tree*> (tree_operand_check ((value), (0) , "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1284, __FUNCTION__))))); | ||||
1285 | |||||
1286 | /* Pointer variables should have been handled by merge_object_sizes. */ | ||||
1287 | gcc_assert (TREE_CODE (value) != SSA_NAME((void)(!(((enum tree_code) (value)->base.code) != SSA_NAME || !(((enum tree_code) (((contains_struct_check ((value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1288, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1288, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE )) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1288, __FUNCTION__), 0 : 0)) | ||||
1288 | || !POINTER_TYPE_P (TREE_TYPE (value)))((void)(!(((enum tree_code) (value)->base.code) != SSA_NAME || !(((enum tree_code) (((contains_struct_check ((value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1288, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((value), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1288, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE )) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1288, __FUNCTION__), 0 : 0)); | ||||
1289 | |||||
1290 | if (TREE_CODE (value)((enum tree_code) (value)->base.code) == ADDR_EXPR) | ||||
1291 | addr_object_size (osi, value, object_size_type, &bytes, &wholesize); | ||||
1292 | else | ||||
1293 | bytes = wholesize = size_unknown (object_size_type); | ||||
1294 | |||||
1295 | object_sizes_set (osi, varno, bytes, wholesize); | ||||
1296 | } | ||||
1297 | |||||
1298 | |||||
1299 | /* Compute object_sizes for PTR, defined to the result of a call. */ | ||||
1300 | |||||
1301 | static void | ||||
1302 | call_object_size (struct object_size_info *osi, tree ptr, gcall *call) | ||||
1303 | { | ||||
1304 | int object_size_type = osi->object_size_type; | ||||
1305 | unsigned int varno = SSA_NAME_VERSION (ptr)(tree_check ((ptr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1305, __FUNCTION__, (SSA_NAME)))->base.u.version; | ||||
1306 | tree bytes = NULL_TREE(tree) nullptr; | ||||
1307 | |||||
1308 | gcc_assert (is_gimple_call (call))((void)(!(is_gimple_call (call)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1308, __FUNCTION__), 0 : 0)); | ||||
1309 | |||||
1310 | gcc_assert (!object_sizes_unknown_p (object_size_type, varno))((void)(!(!object_sizes_unknown_p (object_size_type, varno)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1310, __FUNCTION__), 0 : 0)); | ||||
1311 | gcc_assert (osi->pass == 0)((void)(!(osi->pass == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1311, __FUNCTION__), 0 : 0)); | ||||
1312 | |||||
1313 | bool is_strdup = gimple_call_builtin_p (call, BUILT_IN_STRDUP); | ||||
1314 | bool is_strndup = gimple_call_builtin_p (call, BUILT_IN_STRNDUP); | ||||
1315 | if (is_strdup || is_strndup) | ||||
1316 | bytes = strdup_object_size (call, object_size_type, is_strndup); | ||||
1317 | else | ||||
1318 | bytes = alloc_object_size (call, object_size_type); | ||||
1319 | |||||
1320 | if (!size_valid_p (bytes, object_size_type)) | ||||
1321 | bytes = size_unknown (object_size_type); | ||||
1322 | |||||
1323 | object_sizes_set (osi, varno, bytes, bytes); | ||||
1324 | } | ||||
1325 | |||||
1326 | |||||
1327 | /* Compute object_sizes for PTR, defined to an unknown value. */ | ||||
1328 | |||||
1329 | static void | ||||
1330 | unknown_object_size (struct object_size_info *osi, tree ptr) | ||||
1331 | { | ||||
1332 | int object_size_type = osi->object_size_type; | ||||
1333 | unsigned int varno = SSA_NAME_VERSION (ptr)(tree_check ((ptr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1333, __FUNCTION__, (SSA_NAME)))->base.u.version; | ||||
1334 | |||||
1335 | gcc_checking_assert (!object_sizes_unknown_p (object_size_type, varno))((void)(!(!object_sizes_unknown_p (object_size_type, varno)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1335, __FUNCTION__), 0 : 0)); | ||||
1336 | gcc_checking_assert (osi->pass == 0)((void)(!(osi->pass == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1336, __FUNCTION__), 0 : 0)); | ||||
1337 | tree bytes = size_unknown (object_size_type); | ||||
1338 | |||||
1339 | object_sizes_set (osi, varno, bytes, bytes); | ||||
1340 | } | ||||
1341 | |||||
1342 | |||||
1343 | /* Merge object sizes of ORIG + OFFSET into DEST. Return true if | ||||
1344 | the object size might need reexamination later. */ | ||||
1345 | |||||
1346 | static bool | ||||
1347 | merge_object_sizes (struct object_size_info *osi, tree dest, tree orig) | ||||
1348 | { | ||||
1349 | int object_size_type = osi->object_size_type; | ||||
1350 | unsigned int varno = SSA_NAME_VERSION (dest)(tree_check ((dest), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1350, __FUNCTION__, (SSA_NAME)))->base.u.version; | ||||
1351 | tree orig_bytes, wholesize; | ||||
1352 | |||||
1353 | if (object_sizes_unknown_p (object_size_type, varno)) | ||||
1354 | return false; | ||||
1355 | |||||
1356 | if (osi->pass
| ||||
1357 | collect_object_sizes_for (osi, orig); | ||||
1358 | |||||
1359 | orig_bytes = object_sizes_get (osi, SSA_NAME_VERSION (orig)(tree_check ((orig), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1359, __FUNCTION__, (SSA_NAME)))->base.u.version); | ||||
1360 | wholesize = object_sizes_get (osi, SSA_NAME_VERSION (orig)(tree_check ((orig), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1360, __FUNCTION__, (SSA_NAME)))->base.u.version, true); | ||||
1361 | |||||
1362 | if (object_sizes_set (osi, varno, orig_bytes, wholesize)) | ||||
1363 | osi->changed = true; | ||||
1364 | |||||
1365 | return bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (orig)(tree_check ((orig), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1365, __FUNCTION__, (SSA_NAME)))->base.u.version); | ||||
1366 | } | ||||
1367 | |||||
1368 | |||||
1369 | /* Compute object_sizes for VAR, defined to the result of an assignment | ||||
1370 | with operator POINTER_PLUS_EXPR. Return true if the object size might | ||||
1371 | need reexamination later. */ | ||||
1372 | |||||
1373 | static bool | ||||
1374 | plus_stmt_object_size (struct object_size_info *osi, tree var, gimple *stmt) | ||||
1375 | { | ||||
1376 | int object_size_type = osi->object_size_type; | ||||
1377 | unsigned int varno = SSA_NAME_VERSION (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1377, __FUNCTION__, (SSA_NAME)))->base.u.version; | ||||
1378 | tree bytes, wholesize; | ||||
1379 | tree op0, op1; | ||||
1380 | bool reexamine = false; | ||||
1381 | |||||
1382 | if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) | ||||
1383 | { | ||||
1384 | op0 = gimple_assign_rhs1 (stmt); | ||||
1385 | op1 = gimple_assign_rhs2 (stmt); | ||||
1386 | } | ||||
1387 | else if (gimple_assign_rhs_code (stmt) == ADDR_EXPR) | ||||
1388 | { | ||||
1389 | tree rhs = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0)(*((const_cast<tree*> (tree_operand_check ((gimple_assign_rhs1 (stmt)), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1389, __FUNCTION__))))); | ||||
1390 | gcc_assert (TREE_CODE (rhs) == MEM_REF)((void)(!(((enum tree_code) (rhs)->base.code) == MEM_REF) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1390, __FUNCTION__), 0 : 0)); | ||||
1391 | op0 = TREE_OPERAND (rhs, 0)(*((const_cast<tree*> (tree_operand_check ((rhs), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1391, __FUNCTION__))))); | ||||
1392 | op1 = TREE_OPERAND (rhs, 1)(*((const_cast<tree*> (tree_operand_check ((rhs), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1392, __FUNCTION__))))); | ||||
1393 | } | ||||
1394 | else | ||||
1395 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1395, __FUNCTION__)); | ||||
1396 | |||||
1397 | if (object_sizes_unknown_p (object_size_type, varno)) | ||||
1398 | return false; | ||||
1399 | |||||
1400 | /* Handle PTR + OFFSET here. */ | ||||
1401 | if (size_valid_p (op1, object_size_type) | ||||
1402 | && (TREE_CODE (op0)((enum tree_code) (op0)->base.code) == SSA_NAME || TREE_CODE (op0)((enum tree_code) (op0)->base.code) == ADDR_EXPR)) | ||||
1403 | { | ||||
1404 | if (TREE_CODE (op0)((enum tree_code) (op0)->base.code) == SSA_NAME) | ||||
1405 | { | ||||
1406 | if (osi->pass == 0) | ||||
1407 | collect_object_sizes_for (osi, op0); | ||||
1408 | |||||
1409 | bytes = object_sizes_get (osi, SSA_NAME_VERSION (op0)(tree_check ((op0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1409, __FUNCTION__, (SSA_NAME)))->base.u.version); | ||||
1410 | wholesize = object_sizes_get (osi, SSA_NAME_VERSION (op0)(tree_check ((op0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1410, __FUNCTION__, (SSA_NAME)))->base.u.version, true); | ||||
1411 | reexamine = bitmap_bit_p (osi->reexamine, SSA_NAME_VERSION (op0)(tree_check ((op0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1411, __FUNCTION__, (SSA_NAME)))->base.u.version); | ||||
1412 | } | ||||
1413 | else | ||||
1414 | { | ||||
1415 | /* op0 will be ADDR_EXPR here. We should never come here during | ||||
1416 | reexamination. */ | ||||
1417 | gcc_checking_assert (osi->pass == 0)((void)(!(osi->pass == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1417, __FUNCTION__), 0 : 0)); | ||||
1418 | addr_object_size (osi, op0, object_size_type, &bytes, &wholesize); | ||||
1419 | } | ||||
1420 | |||||
1421 | /* size_for_offset doesn't make sense for -1 size, but it does for size 0 | ||||
1422 | since the wholesize could be non-zero and a negative offset could give | ||||
1423 | a non-zero size. */ | ||||
1424 | if (size_unknown_p (bytes, 0)) | ||||
1425 | ; | ||||
1426 | else if ((object_size_type & OST_DYNAMIC) | ||||
1427 | || compare_tree_int (op1, offset_limit) <= 0) | ||||
1428 | bytes = size_for_offset (bytes, op1, wholesize); | ||||
1429 | /* In the static case, with a negative offset, the best estimate for | ||||
1430 | minimum size is size_unknown but for maximum size, the wholesize is a | ||||
1431 | better estimate than size_unknown. */ | ||||
1432 | else if (object_size_type & OST_MINIMUM) | ||||
1433 | bytes = size_unknown (object_size_type); | ||||
1434 | else | ||||
1435 | bytes = wholesize; | ||||
1436 | } | ||||
1437 | else | ||||
1438 | bytes = wholesize = size_unknown (object_size_type); | ||||
1439 | |||||
1440 | if (!size_valid_p (bytes, object_size_type) | ||||
1441 | || !size_valid_p (wholesize, object_size_type)) | ||||
1442 | bytes = wholesize = size_unknown (object_size_type); | ||||
1443 | |||||
1444 | if (object_sizes_set (osi, varno, bytes, wholesize)) | ||||
1445 | osi->changed = true; | ||||
1446 | return reexamine; | ||||
1447 | } | ||||
1448 | |||||
1449 | /* Compute the dynamic object size for VAR. Return the result in SIZE and | ||||
1450 | WHOLESIZE. */ | ||||
1451 | |||||
1452 | static void | ||||
1453 | dynamic_object_size (struct object_size_info *osi, tree var, | ||||
1454 | tree *size, tree *wholesize) | ||||
1455 | { | ||||
1456 | int object_size_type = osi->object_size_type; | ||||
1457 | |||||
1458 | if (TREE_CODE (var)((enum tree_code) (var)->base.code) == SSA_NAME) | ||||
1459 | { | ||||
1460 | unsigned varno = SSA_NAME_VERSION (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1460, __FUNCTION__, (SSA_NAME)))->base.u.version; | ||||
1461 | |||||
1462 | collect_object_sizes_for (osi, var); | ||||
1463 | *size = object_sizes_get (osi, varno); | ||||
1464 | *wholesize = object_sizes_get (osi, varno, true); | ||||
1465 | } | ||||
1466 | else if (TREE_CODE (var)((enum tree_code) (var)->base.code) == ADDR_EXPR) | ||||
1467 | addr_object_size (osi, var, object_size_type, size, wholesize); | ||||
1468 | else | ||||
1469 | *size = *wholesize = size_unknown (object_size_type); | ||||
1470 | } | ||||
1471 | |||||
1472 | /* Compute object_sizes for VAR, defined at STMT, which is | ||||
1473 | a COND_EXPR. Return true if the object size might need reexamination | ||||
1474 | later. */ | ||||
1475 | |||||
1476 | static bool | ||||
1477 | cond_expr_object_size (struct object_size_info *osi, tree var, gimple *stmt) | ||||
1478 | { | ||||
1479 | tree then_, else_; | ||||
1480 | int object_size_type = osi->object_size_type; | ||||
1481 | unsigned int varno = SSA_NAME_VERSION (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1481, __FUNCTION__, (SSA_NAME)))->base.u.version; | ||||
1482 | bool reexamine = false; | ||||
1483 | |||||
1484 | gcc_assert (gimple_assign_rhs_code (stmt) == COND_EXPR)((void)(!(gimple_assign_rhs_code (stmt) == COND_EXPR) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1484, __FUNCTION__), 0 : 0)); | ||||
1485 | |||||
1486 | if (object_sizes_unknown_p (object_size_type, varno)) | ||||
1487 | return false; | ||||
1488 | |||||
1489 | then_ = gimple_assign_rhs2 (stmt); | ||||
1490 | else_ = gimple_assign_rhs3 (stmt); | ||||
1491 | |||||
1492 | if (object_size_type & OST_DYNAMIC) | ||||
1493 | { | ||||
1494 | tree then_size, then_wholesize, else_size, else_wholesize; | ||||
1495 | |||||
1496 | dynamic_object_size (osi, then_, &then_size, &then_wholesize); | ||||
1497 | if (!size_unknown_p (then_size, object_size_type)) | ||||
1498 | dynamic_object_size (osi, else_, &else_size, &else_wholesize); | ||||
1499 | |||||
1500 | tree cond_size, cond_wholesize; | ||||
1501 | if (size_unknown_p (then_size, object_size_type) | ||||
1502 | || size_unknown_p (else_size, object_size_type)) | ||||
| |||||
1503 | cond_size = cond_wholesize = size_unknown (object_size_type); | ||||
1504 | else | ||||
1505 | { | ||||
1506 | cond_size = fold_build3 (COND_EXPR, sizetype,fold_build3_loc (((location_t) 0), COND_EXPR, sizetype_tab[(int ) stk_sizetype], gimple_assign_rhs1 (stmt), then_size, else_size ) | ||||
1507 | gimple_assign_rhs1 (stmt),fold_build3_loc (((location_t) 0), COND_EXPR, sizetype_tab[(int ) stk_sizetype], gimple_assign_rhs1 (stmt), then_size, else_size ) | ||||
1508 | then_size, else_size)fold_build3_loc (((location_t) 0), COND_EXPR, sizetype_tab[(int ) stk_sizetype], gimple_assign_rhs1 (stmt), then_size, else_size ); | ||||
1509 | cond_wholesize = fold_build3 (COND_EXPR, sizetype,fold_build3_loc (((location_t) 0), COND_EXPR, sizetype_tab[(int ) stk_sizetype], gimple_assign_rhs1 (stmt), then_wholesize, else_wholesize ) | ||||
1510 | gimple_assign_rhs1 (stmt),fold_build3_loc (((location_t) 0), COND_EXPR, sizetype_tab[(int ) stk_sizetype], gimple_assign_rhs1 (stmt), then_wholesize, else_wholesize ) | ||||
1511 | then_wholesize, else_wholesize)fold_build3_loc (((location_t) 0), COND_EXPR, sizetype_tab[(int ) stk_sizetype], gimple_assign_rhs1 (stmt), then_wholesize, else_wholesize ); | ||||
1512 | } | ||||
1513 | |||||
1514 | object_sizes_set (osi, varno, cond_size, cond_wholesize); | ||||
1515 | |||||
1516 | return false; | ||||
1517 | } | ||||
1518 | |||||
1519 | if (TREE_CODE (then_)((enum tree_code) (then_)->base.code) == SSA_NAME) | ||||
1520 | reexamine |= merge_object_sizes (osi, var, then_); | ||||
1521 | else | ||||
1522 | expr_object_size (osi, var, then_); | ||||
1523 | |||||
1524 | if (object_sizes_unknown_p (object_size_type, varno)) | ||||
1525 | return reexamine; | ||||
1526 | |||||
1527 | if (TREE_CODE (else_)((enum tree_code) (else_)->base.code) == SSA_NAME) | ||||
1528 | reexamine |= merge_object_sizes (osi, var, else_); | ||||
1529 | else | ||||
1530 | expr_object_size (osi, var, else_); | ||||
1531 | |||||
1532 | return reexamine; | ||||
1533 | } | ||||
1534 | |||||
1535 | /* Find size of an object passed as a parameter to the function. */ | ||||
1536 | |||||
1537 | static void | ||||
1538 | parm_object_size (struct object_size_info *osi, tree var) | ||||
1539 | { | ||||
1540 | int object_size_type = osi->object_size_type; | ||||
1541 | tree parm = SSA_NAME_VAR (var)((tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1541, __FUNCTION__, (SSA_NAME)))->ssa_name.var == (tree) nullptr || ((enum tree_code) ((var)->ssa_name.var)->base .code) == IDENTIFIER_NODE ? (tree) nullptr : (var)->ssa_name .var); | ||||
1542 | |||||
1543 | if (!(object_size_type & OST_DYNAMIC) || !POINTER_TYPE_P (TREE_TYPE (parm))(((enum tree_code) (((contains_struct_check ((parm), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1543, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((parm), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1543, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE )) | ||||
1544 | { | ||||
1545 | expr_object_size (osi, var, parm); | ||||
1546 | return; | ||||
1547 | } | ||||
1548 | |||||
1549 | /* Look for access attribute. */ | ||||
1550 | rdwr_map rdwr_idx; | ||||
1551 | |||||
1552 | tree fndecl = cfun(cfun + 0)->decl; | ||||
1553 | const attr_access *access = get_parm_access (rdwr_idx, parm, fndecl); | ||||
1554 | tree typesize = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (parm)))((tree_class_check ((((contains_struct_check ((((contains_struct_check ((parm), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1554, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1554, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1554, __FUNCTION__))->type_common.size_unit); | ||||
1555 | tree sz = NULL_TREE(tree) nullptr; | ||||
1556 | |||||
1557 | /* If we have an explicit access attribute with a usable size argument... */ | ||||
1558 | if (access && access->sizarg != UINT_MAX(2147483647 *2U +1U) && !access->internal_p | ||||
1559 | /* ... and either PARM is void * or has a type that is complete and has a | ||||
1560 | constant size... */ | ||||
1561 | && ((typesize && poly_int_tree_p (typesize)) | ||||
1562 | || (!typesize && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (parm)))(((enum tree_code) (((contains_struct_check ((((contains_struct_check ((parm), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1562, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1562, __FUNCTION__))->typed.type))->base.code) == VOID_TYPE )))) | ||||
1563 | { | ||||
1564 | tree fnargs = DECL_ARGUMENTS (fndecl)((tree_check ((fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1564, __FUNCTION__, (FUNCTION_DECL)))->function_decl.arguments ); | ||||
1565 | tree arg = NULL_TREE(tree) nullptr; | ||||
1566 | unsigned argpos = 0; | ||||
1567 | |||||
1568 | /* ... then walk through the parameters to pick the size parameter and | ||||
1569 | safely scale it by the type size if needed. */ | ||||
1570 | for (arg = fnargs; arg; arg = TREE_CHAIN (arg)((contains_struct_check ((arg), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1570, __FUNCTION__))->common.chain), ++argpos) | ||||
1571 | if (argpos == access->sizarg && INTEGRAL_TYPE_P (TREE_TYPE (arg))(((enum tree_code) (((contains_struct_check ((arg), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1571, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((arg), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1571, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((arg), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1571, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE )) | ||||
1572 | { | ||||
1573 | sz = get_or_create_ssa_default_def (cfun(cfun + 0), arg); | ||||
1574 | if (sz != NULL_TREE(tree) nullptr) | ||||
1575 | { | ||||
1576 | sz = fold_convert (sizetype, sz)fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_sizetype ], sz); | ||||
1577 | if (typesize) | ||||
1578 | sz = size_binop (MULT_EXPR, sz, typesize)size_binop_loc (((location_t) 0), MULT_EXPR, sz, typesize); | ||||
1579 | } | ||||
1580 | break; | ||||
1581 | } | ||||
1582 | } | ||||
1583 | if (!sz) | ||||
1584 | sz = size_unknown (object_size_type); | ||||
1585 | |||||
1586 | object_sizes_set (osi, SSA_NAME_VERSION (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1586, __FUNCTION__, (SSA_NAME)))->base.u.version, sz, sz); | ||||
1587 | } | ||||
1588 | |||||
1589 | /* Compute an object size expression for VAR, which is the result of a PHI | ||||
1590 | node. */ | ||||
1591 | |||||
1592 | static void | ||||
1593 | phi_dynamic_object_size (struct object_size_info *osi, tree var) | ||||
1594 | { | ||||
1595 | int object_size_type = osi->object_size_type; | ||||
1596 | unsigned int varno = SSA_NAME_VERSION (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1596, __FUNCTION__, (SSA_NAME)))->base.u.version; | ||||
1597 | gimple *stmt = SSA_NAME_DEF_STMT (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1597, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt; | ||||
1598 | unsigned i, num_args = gimple_phi_num_args (stmt); | ||||
1599 | bool wholesize_needed = false; | ||||
1600 | |||||
1601 | /* The extra space is for the PHI result at the end, which object_sizes_set | ||||
1602 | sets for us. */ | ||||
1603 | tree sizes = make_tree_vec (num_args + 1); | ||||
1604 | tree wholesizes = make_tree_vec (num_args + 1); | ||||
1605 | |||||
1606 | /* Bail out if the size of any of the PHI arguments cannot be | ||||
1607 | determined. */ | ||||
1608 | for (i = 0; i < num_args; i++) | ||||
1609 | { | ||||
1610 | edge e = gimple_phi_arg_edge (as_a <gphi *> (stmt), i); | ||||
1611 | if (e->flags & EDGE_COMPLEX(EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_PRESERVE )) | ||||
1612 | break; | ||||
1613 | |||||
1614 | tree rhs = gimple_phi_arg_def (stmt, i); | ||||
1615 | tree size, wholesize; | ||||
1616 | |||||
1617 | dynamic_object_size (osi, rhs, &size, &wholesize); | ||||
1618 | |||||
1619 | if (size_unknown_p (size, object_size_type)) | ||||
1620 | break; | ||||
1621 | |||||
1622 | if (size != wholesize) | ||||
1623 | wholesize_needed = true; | ||||
1624 | |||||
1625 | TREE_VEC_ELT (sizes, i)(*((const_cast<tree *> (tree_vec_elt_check ((sizes), (i ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1625, __FUNCTION__))))) = size; | ||||
1626 | TREE_VEC_ELT (wholesizes, i)(*((const_cast<tree *> (tree_vec_elt_check ((wholesizes ), (i), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1626, __FUNCTION__))))) = wholesize; | ||||
1627 | } | ||||
1628 | |||||
1629 | if (i < num_args) | ||||
1630 | { | ||||
1631 | ggc_free (sizes); | ||||
1632 | ggc_free (wholesizes); | ||||
1633 | sizes = wholesizes = size_unknown (object_size_type); | ||||
1634 | } | ||||
1635 | |||||
1636 | /* Point to the same TREE_VEC so that we can avoid emitting two PHI | ||||
1637 | nodes. */ | ||||
1638 | else if (!wholesize_needed) | ||||
1639 | { | ||||
1640 | ggc_free (wholesizes); | ||||
1641 | wholesizes = sizes; | ||||
1642 | } | ||||
1643 | |||||
1644 | object_sizes_set (osi, varno, sizes, wholesizes); | ||||
1645 | } | ||||
1646 | |||||
1647 | /* Compute object sizes for VAR. | ||||
1648 | For ADDR_EXPR an object size is the number of remaining bytes | ||||
1649 | to the end of the object (where what is considered an object depends on | ||||
1650 | OSI->object_size_type). | ||||
1651 | For allocation GIMPLE_CALL like malloc or calloc object size is the size | ||||
1652 | of the allocation. | ||||
1653 | For POINTER_PLUS_EXPR where second operand is a constant integer, | ||||
1654 | object size is object size of the first operand minus the constant. | ||||
1655 | If the constant is bigger than the number of remaining bytes until the | ||||
1656 | end of the object, object size is 0, but if it is instead a pointer | ||||
1657 | subtraction, object size is size_unknown (object_size_type). | ||||
1658 | To differentiate addition from subtraction, ADDR_EXPR returns | ||||
1659 | size_unknown (object_size_type) for all objects bigger than half of the | ||||
1660 | address space, and constants less than half of the address space are | ||||
1661 | considered addition, while bigger constants subtraction. | ||||
1662 | For a memcpy like GIMPLE_CALL that always returns one of its arguments, the | ||||
1663 | object size is object size of that argument. | ||||
1664 | Otherwise, object size is the maximum of object sizes of variables | ||||
1665 | that it might be set to. */ | ||||
1666 | |||||
1667 | static void | ||||
1668 | collect_object_sizes_for (struct object_size_info *osi, tree var) | ||||
1669 | { | ||||
1670 | int object_size_type = osi->object_size_type; | ||||
1671 | unsigned int varno = SSA_NAME_VERSION (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1671, __FUNCTION__, (SSA_NAME)))->base.u.version; | ||||
1672 | gimple *stmt; | ||||
1673 | bool reexamine; | ||||
1674 | |||||
1675 | if (bitmap_bit_p (computed[object_size_type], varno)) | ||||
1676 | return; | ||||
1677 | |||||
1678 | if (osi->pass
| ||||
1679 | { | ||||
1680 | if (bitmap_set_bit (osi->visited, varno)) | ||||
1681 | { | ||||
1682 | /* Initialize to 0 for maximum size and M1U for minimum size so that | ||||
1683 | it gets immediately overridden. */ | ||||
1684 | object_sizes_initialize (osi, varno, | ||||
1685 | size_initval (object_size_type), | ||||
1686 | size_initval (object_size_type)); | ||||
1687 | } | ||||
1688 | else | ||||
1689 | { | ||||
1690 | /* Found a dependency loop. Mark the variable for later | ||||
1691 | re-examination. */ | ||||
1692 | if (object_size_type & OST_DYNAMIC) | ||||
1693 | object_sizes_set_temp (osi, varno); | ||||
1694 | |||||
1695 | bitmap_set_bit (osi->reexamine, varno); | ||||
1696 | if (dump_file && (dump_flags & TDF_DETAILS)) | ||||
1697 | { | ||||
1698 | fprintf (dump_file, "Found a dependency loop at "); | ||||
1699 | print_generic_expr (dump_file, var, dump_flags); | ||||
1700 | fprintf (dump_file, "\n"); | ||||
1701 | } | ||||
1702 | return; | ||||
1703 | } | ||||
1704 | } | ||||
1705 | |||||
1706 | if (dump_file && (dump_flags & TDF_DETAILS)) | ||||
1707 | { | ||||
1708 | fprintf (dump_file, "Visiting use-def links for "); | ||||
1709 | print_generic_expr (dump_file, var, dump_flags); | ||||
1710 | fprintf (dump_file, "\n"); | ||||
1711 | } | ||||
1712 | |||||
1713 | stmt = SSA_NAME_DEF_STMT (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1713, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt; | ||||
1714 | reexamine = false; | ||||
1715 | |||||
1716 | switch (gimple_code (stmt)) | ||||
1717 | { | ||||
1718 | case GIMPLE_ASSIGN: | ||||
1719 | { | ||||
1720 | tree rhs = gimple_assign_rhs1 (stmt); | ||||
1721 | if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR | ||||
1722 | || (gimple_assign_rhs_code (stmt) == ADDR_EXPR | ||||
1723 | && TREE_CODE (TREE_OPERAND (rhs, 0))((enum tree_code) ((*((const_cast<tree*> (tree_operand_check ((rhs), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1723, __FUNCTION__))))))->base.code) == MEM_REF)) | ||||
1724 | reexamine = plus_stmt_object_size (osi, var, stmt); | ||||
1725 | else if (gimple_assign_rhs_code (stmt) == COND_EXPR) | ||||
1726 | reexamine = cond_expr_object_size (osi, var, stmt); | ||||
1727 | else if (gimple_assign_single_p (stmt) | ||||
1728 | || gimple_assign_unary_nop_p (stmt)) | ||||
1729 | { | ||||
1730 | if (TREE_CODE (rhs)((enum tree_code) (rhs)->base.code) == SSA_NAME | ||||
1731 | && POINTER_TYPE_P (TREE_TYPE (rhs))(((enum tree_code) (((contains_struct_check ((rhs), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1731, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((rhs), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1731, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE )) | ||||
1732 | reexamine = merge_object_sizes (osi, var, rhs); | ||||
1733 | else | ||||
1734 | expr_object_size (osi, var, rhs); | ||||
1735 | } | ||||
1736 | else | ||||
1737 | unknown_object_size (osi, var); | ||||
1738 | break; | ||||
1739 | } | ||||
1740 | |||||
1741 | case GIMPLE_CALL: | ||||
1742 | { | ||||
1743 | gcall *call_stmt = as_a <gcall *> (stmt); | ||||
1744 | tree arg = pass_through_call (call_stmt); | ||||
1745 | if (arg) | ||||
1746 | { | ||||
1747 | if (TREE_CODE (arg)((enum tree_code) (arg)->base.code) == SSA_NAME | ||||
1748 | && POINTER_TYPE_P (TREE_TYPE (arg))(((enum tree_code) (((contains_struct_check ((arg), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1748, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((arg), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1748, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE )) | ||||
1749 | reexamine = merge_object_sizes (osi, var, arg); | ||||
1750 | else | ||||
1751 | expr_object_size (osi, var, arg); | ||||
1752 | } | ||||
1753 | else | ||||
1754 | call_object_size (osi, var, call_stmt); | ||||
1755 | break; | ||||
1756 | } | ||||
1757 | |||||
1758 | case GIMPLE_ASM: | ||||
1759 | /* Pointers defined by __asm__ statements can point anywhere. */ | ||||
1760 | unknown_object_size (osi, var); | ||||
1761 | break; | ||||
1762 | |||||
1763 | case GIMPLE_NOP: | ||||
1764 | if (SSA_NAME_VAR (var)((tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1764, __FUNCTION__, (SSA_NAME)))->ssa_name.var == (tree) nullptr || ((enum tree_code) ((var)->ssa_name.var)->base .code) == IDENTIFIER_NODE ? (tree) nullptr : (var)->ssa_name .var) | ||||
1765 | && TREE_CODE (SSA_NAME_VAR (var))((enum tree_code) (((tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1765, __FUNCTION__, (SSA_NAME)))->ssa_name.var == (tree) nullptr || ((enum tree_code) ((var)->ssa_name.var)->base .code) == IDENTIFIER_NODE ? (tree) nullptr : (var)->ssa_name .var))->base.code) == PARM_DECL) | ||||
1766 | parm_object_size (osi, var); | ||||
1767 | else | ||||
1768 | /* Uninitialized SSA names point nowhere. */ | ||||
1769 | unknown_object_size (osi, var); | ||||
1770 | break; | ||||
1771 | |||||
1772 | case GIMPLE_PHI: | ||||
1773 | { | ||||
1774 | unsigned i; | ||||
1775 | |||||
1776 | if (object_size_type & OST_DYNAMIC) | ||||
1777 | { | ||||
1778 | phi_dynamic_object_size (osi, var); | ||||
1779 | break; | ||||
1780 | } | ||||
1781 | |||||
1782 | for (i = 0; i < gimple_phi_num_args (stmt); i++) | ||||
1783 | { | ||||
1784 | tree rhs = gimple_phi_arg (stmt, i)->def; | ||||
1785 | |||||
1786 | if (object_sizes_unknown_p (object_size_type, varno)) | ||||
1787 | break; | ||||
1788 | |||||
1789 | if (TREE_CODE (rhs)((enum tree_code) (rhs)->base.code) == SSA_NAME) | ||||
1790 | reexamine |= merge_object_sizes (osi, var, rhs); | ||||
1791 | else if (osi->pass == 0) | ||||
1792 | expr_object_size (osi, var, rhs); | ||||
1793 | } | ||||
1794 | break; | ||||
1795 | } | ||||
1796 | |||||
1797 | default: | ||||
1798 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1798, __FUNCTION__)); | ||||
1799 | } | ||||
1800 | |||||
1801 | if (! reexamine || object_sizes_unknown_p (object_size_type, varno)) | ||||
1802 | { | ||||
1803 | bitmap_set_bit (computed[object_size_type], varno); | ||||
1804 | if (!(object_size_type & OST_DYNAMIC)) | ||||
1805 | bitmap_clear_bit (osi->reexamine, varno); | ||||
1806 | } | ||||
1807 | else | ||||
1808 | { | ||||
1809 | bitmap_set_bit (osi->reexamine, varno); | ||||
1810 | if (dump_file && (dump_flags & TDF_DETAILS)) | ||||
1811 | { | ||||
1812 | fprintf (dump_file, "Need to reexamine "); | ||||
1813 | print_generic_expr (dump_file, var, dump_flags); | ||||
1814 | fprintf (dump_file, "\n"); | ||||
1815 | } | ||||
1816 | } | ||||
1817 | } | ||||
1818 | |||||
1819 | |||||
1820 | /* Helper function for check_for_plus_in_loops. Called recursively | ||||
1821 | to detect loops. */ | ||||
1822 | |||||
1823 | static void | ||||
1824 | check_for_plus_in_loops_1 (struct object_size_info *osi, tree var, | ||||
1825 | unsigned int depth) | ||||
1826 | { | ||||
1827 | gimple *stmt = SSA_NAME_DEF_STMT (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1827, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt; | ||||
1828 | unsigned int varno = SSA_NAME_VERSION (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1828, __FUNCTION__, (SSA_NAME)))->base.u.version; | ||||
1829 | |||||
1830 | if (osi->depths[varno]) | ||||
1831 | { | ||||
1832 | if (osi->depths[varno] != depth) | ||||
1833 | { | ||||
1834 | unsigned int *sp; | ||||
1835 | |||||
1836 | /* Found a loop involving pointer addition. */ | ||||
1837 | for (sp = osi->tos; sp > osi->stack; ) | ||||
1838 | { | ||||
1839 | --sp; | ||||
1840 | bitmap_clear_bit (osi->reexamine, *sp); | ||||
1841 | bitmap_set_bit (computed[osi->object_size_type], *sp); | ||||
1842 | object_sizes_set (osi, *sp, size_zero_nodeglobal_trees[TI_SIZE_ZERO], | ||||
1843 | object_sizes_get (osi, *sp, true)); | ||||
1844 | if (*sp == varno) | ||||
1845 | break; | ||||
1846 | } | ||||
1847 | } | ||||
1848 | return; | ||||
1849 | } | ||||
1850 | else if (! bitmap_bit_p (osi->reexamine, varno)) | ||||
1851 | return; | ||||
1852 | |||||
1853 | osi->depths[varno] = depth; | ||||
1854 | *osi->tos++ = varno; | ||||
1855 | |||||
1856 | switch (gimple_code (stmt)) | ||||
1857 | { | ||||
1858 | |||||
1859 | case GIMPLE_ASSIGN: | ||||
1860 | { | ||||
1861 | if ((gimple_assign_single_p (stmt) | ||||
1862 | || gimple_assign_unary_nop_p (stmt)) | ||||
1863 | && TREE_CODE (gimple_assign_rhs1 (stmt))((enum tree_code) (gimple_assign_rhs1 (stmt))->base.code) == SSA_NAME) | ||||
1864 | { | ||||
1865 | tree rhs = gimple_assign_rhs1 (stmt); | ||||
1866 | |||||
1867 | check_for_plus_in_loops_1 (osi, rhs, depth); | ||||
1868 | } | ||||
1869 | else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) | ||||
1870 | { | ||||
1871 | tree basevar = gimple_assign_rhs1 (stmt); | ||||
1872 | tree cst = gimple_assign_rhs2 (stmt); | ||||
1873 | |||||
1874 | gcc_assert (TREE_CODE (cst) == INTEGER_CST)((void)(!(((enum tree_code) (cst)->base.code) == INTEGER_CST ) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1874, __FUNCTION__), 0 : 0)); | ||||
1875 | |||||
1876 | check_for_plus_in_loops_1 (osi, basevar, | ||||
1877 | depth + !integer_zerop (cst)); | ||||
1878 | } | ||||
1879 | else | ||||
1880 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1880, __FUNCTION__)); | ||||
1881 | break; | ||||
1882 | } | ||||
1883 | |||||
1884 | case GIMPLE_CALL: | ||||
1885 | { | ||||
1886 | gcall *call_stmt = as_a <gcall *> (stmt); | ||||
1887 | tree arg = pass_through_call (call_stmt); | ||||
1888 | if (arg) | ||||
1889 | { | ||||
1890 | if (TREE_CODE (arg)((enum tree_code) (arg)->base.code) == SSA_NAME) | ||||
1891 | check_for_plus_in_loops_1 (osi, arg, depth); | ||||
1892 | else | ||||
1893 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1893, __FUNCTION__)); | ||||
1894 | } | ||||
1895 | break; | ||||
1896 | } | ||||
1897 | |||||
1898 | case GIMPLE_PHI: | ||||
1899 | { | ||||
1900 | unsigned i; | ||||
1901 | |||||
1902 | for (i = 0; i < gimple_phi_num_args (stmt); i++) | ||||
1903 | { | ||||
1904 | tree rhs = gimple_phi_arg (stmt, i)->def; | ||||
1905 | |||||
1906 | if (TREE_CODE (rhs)((enum tree_code) (rhs)->base.code) == SSA_NAME) | ||||
1907 | check_for_plus_in_loops_1 (osi, rhs, depth); | ||||
1908 | } | ||||
1909 | break; | ||||
1910 | } | ||||
1911 | |||||
1912 | default: | ||||
1913 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1913, __FUNCTION__)); | ||||
1914 | } | ||||
1915 | |||||
1916 | osi->depths[varno] = 0; | ||||
1917 | osi->tos--; | ||||
1918 | } | ||||
1919 | |||||
1920 | |||||
1921 | /* Check if some pointer we are computing object size of is being increased | ||||
1922 | within a loop. If yes, assume all the SSA variables participating in | ||||
1923 | that loop have minimum object sizes 0. */ | ||||
1924 | |||||
1925 | static void | ||||
1926 | check_for_plus_in_loops (struct object_size_info *osi, tree var) | ||||
1927 | { | ||||
1928 | gimple *stmt = SSA_NAME_DEF_STMT (var)(tree_check ((var), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1928, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt; | ||||
1929 | |||||
1930 | /* NOTE: In the pre-tuples code, we handled a CALL_EXPR here, | ||||
1931 | and looked for a POINTER_PLUS_EXPR in the pass-through | ||||
1932 | argument, if any. In GIMPLE, however, such an expression | ||||
1933 | is not a valid call operand. */ | ||||
1934 | |||||
1935 | if (is_gimple_assign (stmt) | ||||
1936 | && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) | ||||
1937 | { | ||||
1938 | tree basevar = gimple_assign_rhs1 (stmt); | ||||
1939 | tree cst = gimple_assign_rhs2 (stmt); | ||||
1940 | |||||
1941 | gcc_assert (TREE_CODE (cst) == INTEGER_CST)((void)(!(((enum tree_code) (cst)->base.code) == INTEGER_CST ) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1941, __FUNCTION__), 0 : 0)); | ||||
1942 | |||||
1943 | /* Skip non-positive offsets. */ | ||||
1944 | if (integer_zerop (cst) || compare_tree_int (cst, offset_limit) > 0) | ||||
1945 | return; | ||||
1946 | |||||
1947 | osi->depths[SSA_NAME_VERSION (basevar)(tree_check ((basevar), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1947, __FUNCTION__, (SSA_NAME)))->base.u.version] = 1; | ||||
1948 | *osi->tos++ = SSA_NAME_VERSION (basevar)(tree_check ((basevar), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1948, __FUNCTION__, (SSA_NAME)))->base.u.version; | ||||
1949 | check_for_plus_in_loops_1 (osi, var, 2); | ||||
1950 | osi->depths[SSA_NAME_VERSION (basevar)(tree_check ((basevar), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 1950, __FUNCTION__, (SSA_NAME)))->base.u.version] = 0; | ||||
1951 | osi->tos--; | ||||
1952 | } | ||||
1953 | } | ||||
1954 | |||||
1955 | |||||
1956 | /* Initialize data structures for the object size computation. */ | ||||
1957 | |||||
1958 | void | ||||
1959 | init_object_sizes (void) | ||||
1960 | { | ||||
1961 | int object_size_type; | ||||
1962 | |||||
1963 | if (computed[0]) | ||||
1964 | return; | ||||
1965 | |||||
1966 | for (object_size_type = 0; object_size_type < OST_END; object_size_type++) | ||||
1967 | { | ||||
1968 | object_sizes_grow (object_size_type); | ||||
1969 | computed[object_size_type] = BITMAP_ALLOCbitmap_alloc (NULLnullptr); | ||||
1970 | } | ||||
1971 | |||||
1972 | init_offset_limit (); | ||||
1973 | } | ||||
1974 | |||||
1975 | |||||
1976 | /* Destroy data structures after the object size computation. */ | ||||
1977 | |||||
1978 | void | ||||
1979 | fini_object_sizes (void) | ||||
1980 | { | ||||
1981 | int object_size_type; | ||||
1982 | |||||
1983 | for (object_size_type = 0; object_size_type < OST_END; object_size_type++) | ||||
1984 | { | ||||
1985 | object_sizes_release (object_size_type); | ||||
1986 | BITMAP_FREE (computed[object_size_type])((void) (bitmap_obstack_free ((bitmap) computed[object_size_type ]), (computed[object_size_type]) = (bitmap) nullptr)); | ||||
1987 | } | ||||
1988 | } | ||||
1989 | |||||
1990 | /* Dummy valueize function. */ | ||||
1991 | |||||
1992 | static tree | ||||
1993 | do_valueize (tree t) | ||||
1994 | { | ||||
1995 | return t; | ||||
1996 | } | ||||
1997 | |||||
1998 | /* Process a __builtin_object_size or __builtin_dynamic_object_size call in | ||||
1999 | CALL early for subobjects before any object information is lost due to | ||||
2000 | optimization. Insert a MIN or MAX expression of the result and | ||||
2001 | __builtin_object_size at I so that it may be processed in the second pass. | ||||
2002 | __builtin_dynamic_object_size is treated like __builtin_object_size here | ||||
2003 | since we're only looking for constant bounds. */ | ||||
2004 | |||||
2005 | static void | ||||
2006 | early_object_sizes_execute_one (gimple_stmt_iterator *i, gimple *call) | ||||
2007 | { | ||||
2008 | tree ost = gimple_call_arg (call, 1); | ||||
2009 | tree lhs = gimple_call_lhs (call); | ||||
2010 | gcc_assert (lhs != NULL_TREE)((void)(!(lhs != (tree) nullptr) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 2010, __FUNCTION__), 0 : 0)); | ||||
2011 | |||||
2012 | if (!tree_fits_uhwi_p (ost)) | ||||
2013 | return; | ||||
2014 | |||||
2015 | unsigned HOST_WIDE_INTlong object_size_type = tree_to_uhwi (ost); | ||||
2016 | tree ptr = gimple_call_arg (call, 0); | ||||
2017 | |||||
2018 | if (object_size_type != 1 && object_size_type != 3) | ||||
2019 | return; | ||||
2020 | |||||
2021 | if (TREE_CODE (ptr)((enum tree_code) (ptr)->base.code) != ADDR_EXPR && TREE_CODE (ptr)((enum tree_code) (ptr)->base.code) != SSA_NAME) | ||||
2022 | return; | ||||
2023 | |||||
2024 | tree type = TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 2024, __FUNCTION__))->typed.type); | ||||
2025 | tree bytes; | ||||
2026 | if (!compute_builtin_object_size (ptr, object_size_type, &bytes) | ||||
2027 | || !int_fits_type_p (bytes, type)) | ||||
2028 | return; | ||||
2029 | |||||
2030 | tree tem = make_ssa_name (type); | ||||
2031 | gimple_call_set_lhs (call, tem); | ||||
2032 | enum tree_code code = object_size_type & OST_MINIMUM ? MAX_EXPR : MIN_EXPR; | ||||
2033 | tree cst = fold_convert (type, bytes)fold_convert_loc (((location_t) 0), type, bytes); | ||||
2034 | gimple *g = gimple_build_assign (lhs, code, tem, cst); | ||||
2035 | gsi_insert_after (i, g, GSI_NEW_STMT); | ||||
2036 | update_stmt (call); | ||||
2037 | } | ||||
2038 | |||||
2039 | /* Attempt to fold one __builtin_dynamic_object_size call in CALL into an | ||||
2040 | expression and insert it at I. Return true if it succeeds. */ | ||||
2041 | |||||
2042 | static bool | ||||
2043 | dynamic_object_sizes_execute_one (gimple_stmt_iterator *i, gimple *call) | ||||
2044 | { | ||||
2045 | gcc_assert (gimple_call_num_args (call) == 2)((void)(!(gimple_call_num_args (call) == 2) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 2045, __FUNCTION__), 0 : 0)); | ||||
2046 | |||||
2047 | tree args[2]; | ||||
2048 | args[0] = gimple_call_arg (call, 0); | ||||
2049 | args[1] = gimple_call_arg (call, 1); | ||||
2050 | |||||
2051 | location_t loc = EXPR_LOC_OR_LOC (args[0], input_location)((((IS_ADHOC_LOC (((((args[0])) && ((tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) ((args[0] ))->base.code))]) >= tcc_reference && (tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) ((args[0] ))->base.code))]) <= tcc_expression)) ? (args[0])->exp .locus : ((location_t) 0)))) ? get_location_from_adhoc_loc (line_table , ((((args[0])) && ((tree_code_type_tmpl <0>::tree_code_type [(int) (((enum tree_code) ((args[0]))->base.code))]) >= tcc_reference && (tree_code_type_tmpl <0>::tree_code_type [(int) (((enum tree_code) ((args[0]))->base.code))]) <= tcc_expression)) ? (args[0])->exp.locus : ((location_t) 0 ))) : (((((args[0])) && ((tree_code_type_tmpl <0> ::tree_code_type[(int) (((enum tree_code) ((args[0]))->base .code))]) >= tcc_reference && (tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) ((args[0] ))->base.code))]) <= tcc_expression)) ? (args[0])->exp .locus : ((location_t) 0)))) != ((location_t) 0)) ? (args[0]) ->exp.locus : (input_location)); | ||||
2052 | tree result_type = gimple_call_return_type (as_a <gcall *> (call)); | ||||
2053 | tree result = fold_builtin_call_array (loc, result_type, | ||||
2054 | gimple_call_fn (call), 2, args); | ||||
2055 | |||||
2056 | if (!result) | ||||
2057 | return false; | ||||
2058 | |||||
2059 | /* fold_builtin_call_array may wrap the result inside a | ||||
2060 | NOP_EXPR. */ | ||||
2061 | STRIP_NOPS (result)(result) = tree_strip_nop_conversions ((const_cast<union tree_node *> (((result))))); | ||||
2062 | gimplify_and_update_call_from_tree (i, result); | ||||
2063 | |||||
2064 | if (dump_file && (dump_flags & TDF_DETAILS)) | ||||
2065 | { | ||||
2066 | fprintf (dump_file, "Simplified (dynamic)\n "); | ||||
2067 | print_gimple_stmt (dump_file, call, 0, dump_flags); | ||||
2068 | fprintf (dump_file, " to "); | ||||
2069 | print_generic_expr (dump_file, result); | ||||
2070 | fprintf (dump_file, "\n"); | ||||
2071 | } | ||||
2072 | return true; | ||||
2073 | } | ||||
2074 | |||||
2075 | static unsigned int | ||||
2076 | object_sizes_execute (function *fun, bool early) | ||||
2077 | { | ||||
2078 | todo = 0; | ||||
2079 | |||||
2080 | basic_block bb; | ||||
2081 | FOR_EACH_BB_FN (bb, fun)for (bb = (fun)->cfg->x_entry_block_ptr->next_bb; bb != (fun)->cfg->x_exit_block_ptr; bb = bb->next_bb) | ||||
2082 | { | ||||
2083 | gimple_stmt_iterator i; | ||||
2084 | for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) | ||||
2085 | { | ||||
2086 | tree result; | ||||
2087 | bool dynamic = false; | ||||
2088 | |||||
2089 | gimple *call = gsi_stmt (i); | ||||
2090 | if (gimple_call_builtin_p (call, BUILT_IN_DYNAMIC_OBJECT_SIZE)) | ||||
2091 | dynamic = true; | ||||
2092 | else if (!gimple_call_builtin_p (call, BUILT_IN_OBJECT_SIZE)) | ||||
2093 | continue; | ||||
2094 | |||||
2095 | tree lhs = gimple_call_lhs (call); | ||||
2096 | if (!lhs) | ||||
2097 | continue; | ||||
2098 | |||||
2099 | init_object_sizes (); | ||||
2100 | |||||
2101 | /* If early, only attempt to fold | ||||
2102 | __builtin_object_size (x, 1) and __builtin_object_size (x, 3), | ||||
2103 | and rather than folding the builtin to the constant if any, | ||||
2104 | create a MIN_EXPR or MAX_EXPR of the __builtin_object_size | ||||
2105 | call result and the computed constant. Do the same for | ||||
2106 | __builtin_dynamic_object_size too. */ | ||||
2107 | if (early) | ||||
2108 | { | ||||
2109 | early_object_sizes_execute_one (&i, call); | ||||
2110 | continue; | ||||
2111 | } | ||||
2112 | |||||
2113 | if (dynamic) | ||||
2114 | { | ||||
2115 | if (dynamic_object_sizes_execute_one (&i, call)) | ||||
2116 | continue; | ||||
2117 | else | ||||
2118 | { | ||||
2119 | /* If we could not find a suitable size expression, lower to | ||||
2120 | __builtin_object_size so that we may at least get a | ||||
2121 | constant lower or higher estimate. */ | ||||
2122 | tree bosfn = builtin_decl_implicit (BUILT_IN_OBJECT_SIZE); | ||||
2123 | gimple_call_set_fndecl (call, bosfn); | ||||
2124 | update_stmt (call); | ||||
2125 | |||||
2126 | if (dump_file && (dump_flags & TDF_DETAILS)) | ||||
2127 | { | ||||
2128 | print_generic_expr (dump_file, gimple_call_arg (call, 0), | ||||
2129 | dump_flags); | ||||
2130 | fprintf (dump_file, | ||||
2131 | ": Retrying as __builtin_object_size\n"); | ||||
2132 | } | ||||
2133 | } | ||||
2134 | } | ||||
2135 | |||||
2136 | result = gimple_fold_stmt_to_constant (call, do_valueize); | ||||
2137 | if (!result) | ||||
2138 | { | ||||
2139 | tree ost = gimple_call_arg (call, 1); | ||||
2140 | |||||
2141 | if (tree_fits_uhwi_p (ost)) | ||||
2142 | { | ||||
2143 | unsigned HOST_WIDE_INTlong object_size_type = tree_to_uhwi (ost); | ||||
2144 | |||||
2145 | if (object_size_type & OST_MINIMUM) | ||||
2146 | result = build_zero_cst (size_type_nodeglobal_trees[TI_SIZE_TYPE]); | ||||
2147 | else if (object_size_type < OST_END) | ||||
2148 | result = fold_convert (size_type_node,fold_convert_loc (((location_t) 0), global_trees[TI_SIZE_TYPE ], global_trees[TI_INTEGER_MINUS_ONE]) | ||||
2149 | integer_minus_one_node)fold_convert_loc (((location_t) 0), global_trees[TI_SIZE_TYPE ], global_trees[TI_INTEGER_MINUS_ONE]); | ||||
2150 | } | ||||
2151 | |||||
2152 | if (!result) | ||||
2153 | continue; | ||||
2154 | } | ||||
2155 | |||||
2156 | gcc_assert (TREE_CODE (result) == INTEGER_CST)((void)(!(((enum tree_code) (result)->base.code) == INTEGER_CST ) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 2156, __FUNCTION__), 0 : 0)); | ||||
2157 | |||||
2158 | if (dump_file && (dump_flags & TDF_DETAILS)) | ||||
2159 | { | ||||
2160 | fprintf (dump_file, "Simplified\n "); | ||||
2161 | print_gimple_stmt (dump_file, call, 0, dump_flags); | ||||
2162 | fprintf (dump_file, " to "); | ||||
2163 | print_generic_expr (dump_file, result); | ||||
2164 | fprintf (dump_file, "\n"); | ||||
2165 | } | ||||
2166 | |||||
2167 | /* Propagate into all uses and fold those stmts. */ | ||||
2168 | if (!SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)(tree_check ((lhs), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-object-size.cc" , 2168, __FUNCTION__, (SSA_NAME)))->base.asm_written_flag) | ||||
2169 | replace_uses_by (lhs, result); | ||||
2170 | else | ||||
2171 | replace_call_with_value (&i, result); | ||||
2172 | } | ||||
2173 | } | ||||
2174 | |||||
2175 | fini_object_sizes (); | ||||
2176 | return todo; | ||||
2177 | } | ||||
2178 | |||||
2179 | /* Simple pass to optimize all __builtin_object_size () builtins. */ | ||||
2180 | |||||
2181 | namespace { | ||||
2182 | |||||
2183 | const pass_data pass_data_object_sizes = | ||||
2184 | { | ||||
2185 | GIMPLE_PASS, /* type */ | ||||
2186 | "objsz", /* name */ | ||||
2187 | OPTGROUP_NONE, /* optinfo_flags */ | ||||
2188 | TV_NONE, /* tv_id */ | ||||
2189 | ( PROP_cfg(1 << 3) | PROP_ssa(1 << 5) ), /* properties_required */ | ||||
2190 | PROP_objsz(1 << 4), /* properties_provided */ | ||||
2191 | 0, /* properties_destroyed */ | ||||
2192 | 0, /* todo_flags_start */ | ||||
2193 | 0, /* todo_flags_finish */ | ||||
2194 | }; | ||||
2195 | |||||
2196 | class pass_object_sizes : public gimple_opt_pass | ||||
2197 | { | ||||
2198 | public: | ||||
2199 | pass_object_sizes (gcc::context *ctxt) | ||||
2200 | : gimple_opt_pass (pass_data_object_sizes, ctxt) | ||||
2201 | {} | ||||
2202 | |||||
2203 | /* opt_pass methods: */ | ||||
2204 | opt_pass * clone () final override { return new pass_object_sizes (m_ctxt); } | ||||
2205 | unsigned int execute (function *fun) final override | ||||
2206 | { | ||||
2207 | return object_sizes_execute (fun, false); | ||||
2208 | } | ||||
2209 | }; // class pass_object_sizes | ||||
2210 | |||||
2211 | } // anon namespace | ||||
2212 | |||||
2213 | gimple_opt_pass * | ||||
2214 | make_pass_object_sizes (gcc::context *ctxt) | ||||
2215 | { | ||||
2216 | return new pass_object_sizes (ctxt); | ||||
2217 | } | ||||
2218 | |||||
2219 | /* Early version of pass to optimize all __builtin_object_size () builtins. */ | ||||
2220 | |||||
2221 | namespace { | ||||
2222 | |||||
2223 | const pass_data pass_data_early_object_sizes = | ||||
2224 | { | ||||
2225 | GIMPLE_PASS, /* type */ | ||||
2226 | "early_objsz", /* name */ | ||||
2227 | OPTGROUP_NONE, /* optinfo_flags */ | ||||
2228 | TV_NONE, /* tv_id */ | ||||
2229 | ( PROP_cfg(1 << 3) | PROP_ssa(1 << 5) ), /* properties_required */ | ||||
2230 | 0, /* properties_provided */ | ||||
2231 | 0, /* properties_destroyed */ | ||||
2232 | 0, /* todo_flags_start */ | ||||
2233 | 0, /* todo_flags_finish */ | ||||
2234 | }; | ||||
2235 | |||||
2236 | class pass_early_object_sizes : public gimple_opt_pass | ||||
2237 | { | ||||
2238 | public: | ||||
2239 | pass_early_object_sizes (gcc::context *ctxt) | ||||
2240 | : gimple_opt_pass (pass_data_early_object_sizes, ctxt) | ||||
2241 | {} | ||||
2242 | |||||
2243 | /* opt_pass methods: */ | ||||
2244 | unsigned int execute (function *fun) final override | ||||
2245 | { | ||||
2246 | return object_sizes_execute (fun, true); | ||||
2247 | } | ||||
2248 | }; // class pass_object_sizes | ||||
2249 | |||||
2250 | } // anon namespace | ||||
2251 | |||||
2252 | gimple_opt_pass * | ||||
2253 | make_pass_early_object_sizes (gcc::context *ctxt) | ||||
2254 | { | ||||
2255 | return new pass_early_object_sizes (ctxt); | ||||
2256 | } |