Bug Summary

File:build/gcc/vec.h
Warning:line 815, column 10
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ubsan.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model static -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D IN_GCC -D HAVE_CONFIG_H -I . -I . -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/. -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../include -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libcpp/include -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libcody -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libdecnumber -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libdecnumber/bid -I ../libdecnumber -I /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libbacktrace -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/10/../../../../include/c++/10/x86_64-suse-linux -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-narrowing -Wwrite-strings -Wno-error=format-diag -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fdeprecated-macro -fdebug-compilation-dir /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/objdir/gcc -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=plist-html -analyzer-config silence-checkers=core.NullDereference -faddrsig -o /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/objdir/clang-static-analyzer/2021-01-16-135054-17580-1/report-3Cos_A.plist -x c++ /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c

/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c

1/* UndefinedBehaviorSanitizer, undefined behavior detector.
2 Copyright (C) 2013-2021 Free Software Foundation, Inc.
3 Contributed by Marek Polacek <polacek@redhat.com>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along 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 "rtl.h"
26#include "c-family/c-common.h"
27#include "gimple.h"
28#include "cfghooks.h"
29#include "tree-pass.h"
30#include "memmodel.h"
31#include "tm_p.h"
32#include "ssa.h"
33#include "cgraph.h"
34#include "tree-pretty-print.h"
35#include "stor-layout.h"
36#include "cfganal.h"
37#include "gimple-iterator.h"
38#include "output.h"
39#include "cfgloop.h"
40#include "ubsan.h"
41#include "expr.h"
42#include "stringpool.h"
43#include "attribs.h"
44#include "asan.h"
45#include "gimplify-me.h"
46#include "dfp.h"
47#include "builtins.h"
48#include "tree-object-size.h"
49#include "tree-cfg.h"
50#include "gimple-fold.h"
51#include "varasm.h"
52
53/* Map from a tree to a VAR_DECL tree. */
54
55struct GTY((for_user)) tree_type_map {
56 struct tree_map_base type;
57 tree decl;
58};
59
60struct tree_type_map_cache_hasher : ggc_cache_ptr_hash<tree_type_map>
61{
62 static inline hashval_t
63 hash (tree_type_map *t)
64 {
65 return TYPE_UID (t->type.from)((tree_class_check ((t->type.from), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 65, __FUNCTION__))->type_common.uid)
;
66 }
67
68 static inline bool
69 equal (tree_type_map *a, tree_type_map *b)
70 {
71 return a->type.from == b->type.from;
72 }
73
74 static int
75 keep_cache_entry (tree_type_map *&m)
76 {
77 return ggc_marked_p (m->type.from);
78 }
79};
80
81static GTY ((cache))
82 hash_table<tree_type_map_cache_hasher> *decl_tree_for_type;
83
84/* Lookup a VAR_DECL for TYPE, and return it if we find one. */
85
86static tree
87decl_for_type_lookup (tree type)
88{
89 /* If the hash table is not initialized yet, create it now. */
90 if (decl_tree_for_type == NULLnullptr)
91 {
92 decl_tree_for_type
93 = hash_table<tree_type_map_cache_hasher>::create_ggc (10);
94 /* That also means we don't have to bother with the lookup. */
95 return NULL_TREE(tree) nullptr;
96 }
97
98 struct tree_type_map *h, in;
99 in.type.from = type;
100
101 h = decl_tree_for_type->find_with_hash (&in, TYPE_UID (type)((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 101, __FUNCTION__))->type_common.uid)
);
102 return h ? h->decl : NULL_TREE(tree) nullptr;
103}
104
105/* Insert a mapping TYPE->DECL in the VAR_DECL for type hashtable. */
106
107static void
108decl_for_type_insert (tree type, tree decl)
109{
110 struct tree_type_map *h;
111
112 h = ggc_alloc<tree_type_map> ();
113 h->type.from = type;
114 h->decl = decl;
115 *decl_tree_for_type->find_slot_with_hash (h, TYPE_UID (type)((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 115, __FUNCTION__))->type_common.uid)
, INSERT) = h;
116}
117
118/* Helper routine, which encodes a value in the pointer_sized_int_node.
119 Arguments with precision <= POINTER_SIZE are passed directly,
120 the rest is passed by reference. T is a value we are to encode.
121 PHASE determines when this function is called. */
122
123tree
124ubsan_encode_value (tree t, enum ubsan_encode_value_phase phase)
125{
126 tree type = TREE_TYPE (t)((contains_struct_check ((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 126, __FUNCTION__))->typed.type)
;
127 scalar_mode mode = SCALAR_TYPE_MODE (type)(as_a <scalar_mode> ((tree_class_check ((type), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 127, __FUNCTION__))->type_common.mode))
;
128 const unsigned int bitsize = GET_MODE_BITSIZE (mode);
129 if (bitsize <= POINTER_SIZE(((global_options.x_ix86_isa_flags & (1UL << 58)) !=
0) ? 32 : ((8) * (((global_options.x_ix86_isa_flags & (1UL
<< 1)) != 0) ? 8 : 4)))
)
130 switch (TREE_CODE (type)((enum tree_code) (type)->base.code))
131 {
132 case BOOLEAN_TYPE:
133 case ENUMERAL_TYPE:
134 case INTEGER_TYPE:
135 return fold_build1 (NOP_EXPR, pointer_sized_int_node, t)fold_build1_loc (((location_t) 0), NOP_EXPR, global_trees[TI_POINTER_SIZED_TYPE
], t )
;
136 case REAL_TYPE:
137 {
138 tree itype = build_nonstandard_integer_type (bitsize, true);
139 t = fold_build1 (VIEW_CONVERT_EXPR, itype, t)fold_build1_loc (((location_t) 0), VIEW_CONVERT_EXPR, itype, t
)
;
140 return fold_convert (pointer_sized_int_node, t)fold_convert_loc (((location_t) 0), global_trees[TI_POINTER_SIZED_TYPE
], t)
;
141 }
142 default:
143 gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 143, __FUNCTION__))
;
144 }
145 else
146 {
147 if (!DECL_P (t)(tree_code_type[(int) (((enum tree_code) (t)->base.code))]
== tcc_declaration)
|| !TREE_ADDRESSABLE (t)((t)->base.addressable_flag))
148 {
149 /* The reason for this is that we don't want to pessimize
150 code by making vars unnecessarily addressable. */
151 tree var;
152 if (phase != UBSAN_ENCODE_VALUE_GENERIC)
153 {
154 var = create_tmp_var (type);
155 mark_addressable (var);
156 }
157 else
158 {
159 var = create_tmp_var_raw (type);
160 TREE_ADDRESSABLE (var)((var)->base.addressable_flag) = 1;
161 DECL_CONTEXT (var)((contains_struct_check ((var), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 161, __FUNCTION__))->decl_minimal.context)
= current_function_decl;
162 }
163 if (phase == UBSAN_ENCODE_VALUE_RTL)
164 {
165 rtx mem = assign_stack_temp_for_type (mode, GET_MODE_SIZE (mode),
166 type);
167 SET_DECL_RTL (var, mem)set_decl_rtl (var, mem);
168 expand_assignment (var, t, false);
169 return build_fold_addr_expr (var)build_fold_addr_expr_loc (((location_t) 0), (var));
170 }
171 if (phase != UBSAN_ENCODE_VALUE_GENERIC)
172 {
173 tree tem = build2 (MODIFY_EXPR, void_type_nodeglobal_trees[TI_VOID_TYPE], var, t);
174 t = build_fold_addr_expr (var)build_fold_addr_expr_loc (((location_t) 0), (var));
175 return build2 (COMPOUND_EXPR, TREE_TYPE (t)((contains_struct_check ((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 175, __FUNCTION__))->typed.type)
, tem, t);
176 }
177 else
178 {
179 var = build4 (TARGET_EXPR, type, var, t, NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
180 return build_fold_addr_expr (var)build_fold_addr_expr_loc (((location_t) 0), (var));
181 }
182 }
183 else
184 return build_fold_addr_expr (t)build_fold_addr_expr_loc (((location_t) 0), (t));
185 }
186}
187
188/* Cached ubsan_get_type_descriptor_type () return value. */
189static GTY(()) tree ubsan_type_descriptor_type;
190
191/* Build
192 struct __ubsan_type_descriptor
193 {
194 unsigned short __typekind;
195 unsigned short __typeinfo;
196 char __typename[];
197 }
198 type. */
199
200static tree
201ubsan_get_type_descriptor_type (void)
202{
203 static const char *field_names[3]
204 = { "__typekind", "__typeinfo", "__typename" };
205 tree fields[3], ret;
206
207 if (ubsan_type_descriptor_type)
208 return ubsan_type_descriptor_type;
209
210 tree itype = build_range_type (sizetypesizetype_tab[(int) stk_sizetype], size_zero_nodeglobal_trees[TI_SIZE_ZERO], NULL_TREE(tree) nullptr);
211 tree flex_arr_type = build_array_type (char_type_nodeinteger_types[itk_char], itype);
212
213 ret = make_node (RECORD_TYPE);
214 for (int i = 0; i < 3; i++)
215 {
216 fields[i] = build_decl (UNKNOWN_LOCATION((location_t) 0), FIELD_DECL,
217 get_identifier (field_names[i])(__builtin_constant_p (field_names[i]) ? get_identifier_with_length
((field_names[i]), strlen (field_names[i])) : get_identifier
(field_names[i]))
,
218 (i == 2) ? flex_arr_type
219 : short_unsigned_type_nodeinteger_types[itk_unsigned_short]);
220 DECL_CONTEXT (fields[i])((contains_struct_check ((fields[i]), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 220, __FUNCTION__))->decl_minimal.context)
= ret;
221 if (i)
222 DECL_CHAIN (fields[i - 1])(((contains_struct_check (((contains_struct_check ((fields[i -
1]), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 222, __FUNCTION__))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 222, __FUNCTION__))->common.chain))
= fields[i];
223 }
224 tree type_decl = build_decl (input_location, TYPE_DECL,
225 get_identifier ("__ubsan_type_descriptor")(__builtin_constant_p ("__ubsan_type_descriptor") ? get_identifier_with_length
(("__ubsan_type_descriptor"), strlen ("__ubsan_type_descriptor"
)) : get_identifier ("__ubsan_type_descriptor"))
,
226 ret);
227 DECL_IGNORED_P (type_decl)((contains_struct_check ((type_decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 227, __FUNCTION__))->decl_common.ignored_flag)
= 1;
228 DECL_ARTIFICIAL (type_decl)((contains_struct_check ((type_decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 228, __FUNCTION__))->decl_common.artificial_flag)
= 1;
229 TYPE_FIELDS (ret)((tree_check3 ((ret), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 229, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
= fields[0];
230 TYPE_NAME (ret)((tree_class_check ((ret), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 230, __FUNCTION__))->type_common.name)
= type_decl;
231 TYPE_STUB_DECL (ret)(((contains_struct_check (((tree_class_check ((ret), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 231, __FUNCTION__))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 231, __FUNCTION__))->common.chain))
= type_decl;
232 TYPE_ARTIFICIAL (ret)((tree_class_check ((ret), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 232, __FUNCTION__))->base.nowarning_flag)
= 1;
233 layout_type (ret);
234 ubsan_type_descriptor_type = ret;
235 return ret;
236}
237
238/* Cached ubsan_get_source_location_type () return value. */
239static GTY(()) tree ubsan_source_location_type;
240
241/* Build
242 struct __ubsan_source_location
243 {
244 const char *__filename;
245 unsigned int __line;
246 unsigned int __column;
247 }
248 type. */
249
250tree
251ubsan_get_source_location_type (void)
252{
253 static const char *field_names[3]
254 = { "__filename", "__line", "__column" };
255 tree fields[3], ret;
256 if (ubsan_source_location_type)
257 return ubsan_source_location_type;
258
259 tree const_char_type = build_qualified_type (char_type_nodeinteger_types[itk_char],
260 TYPE_QUAL_CONST);
261
262 ret = make_node (RECORD_TYPE);
263 for (int i = 0; i < 3; i++)
264 {
265 fields[i] = build_decl (UNKNOWN_LOCATION((location_t) 0), FIELD_DECL,
266 get_identifier (field_names[i])(__builtin_constant_p (field_names[i]) ? get_identifier_with_length
((field_names[i]), strlen (field_names[i])) : get_identifier
(field_names[i]))
,
267 (i == 0) ? build_pointer_type (const_char_type)
268 : unsigned_type_nodeinteger_types[itk_unsigned_int]);
269 DECL_CONTEXT (fields[i])((contains_struct_check ((fields[i]), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 269, __FUNCTION__))->decl_minimal.context)
= ret;
270 if (i)
271 DECL_CHAIN (fields[i - 1])(((contains_struct_check (((contains_struct_check ((fields[i -
1]), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 271, __FUNCTION__))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 271, __FUNCTION__))->common.chain))
= fields[i];
272 }
273 tree type_decl = build_decl (input_location, TYPE_DECL,
274 get_identifier ("__ubsan_source_location")(__builtin_constant_p ("__ubsan_source_location") ? get_identifier_with_length
(("__ubsan_source_location"), strlen ("__ubsan_source_location"
)) : get_identifier ("__ubsan_source_location"))
,
275 ret);
276 DECL_IGNORED_P (type_decl)((contains_struct_check ((type_decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 276, __FUNCTION__))->decl_common.ignored_flag)
= 1;
277 DECL_ARTIFICIAL (type_decl)((contains_struct_check ((type_decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 277, __FUNCTION__))->decl_common.artificial_flag)
= 1;
278 TYPE_FIELDS (ret)((tree_check3 ((ret), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 278, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
= fields[0];
279 TYPE_NAME (ret)((tree_class_check ((ret), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 279, __FUNCTION__))->type_common.name)
= type_decl;
280 TYPE_STUB_DECL (ret)(((contains_struct_check (((tree_class_check ((ret), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 280, __FUNCTION__))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 280, __FUNCTION__))->common.chain))
= type_decl;
281 TYPE_ARTIFICIAL (ret)((tree_class_check ((ret), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 281, __FUNCTION__))->base.nowarning_flag)
= 1;
282 layout_type (ret);
283 ubsan_source_location_type = ret;
284 return ret;
285}
286
287/* Helper routine that returns a CONSTRUCTOR of __ubsan_source_location
288 type with its fields filled from a location_t LOC. */
289
290static tree
291ubsan_source_location (location_t loc)
292{
293 expanded_location xloc;
294 tree type = ubsan_get_source_location_type ();
295
296 xloc = expand_location (loc);
297 tree str;
298 if (xloc.file == NULLnullptr)
299 {
300 str = build_int_cst (ptr_type_nodeglobal_trees[TI_PTR_TYPE], 0);
301 xloc.line = 0;
302 xloc.column = 0;
303 }
304 else
305 {
306 /* Fill in the values from LOC. */
307 size_t len = strlen (xloc.file) + 1;
308 str = build_string (len, xloc.file);
309 TREE_TYPE (str)((contains_struct_check ((str), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 309, __FUNCTION__))->typed.type)
= build_array_type_nelts (char_type_nodeinteger_types[itk_char], len);
310 TREE_READONLY (str)((non_type_check ((str), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 310, __FUNCTION__))->base.readonly_flag)
= 1;
311 TREE_STATIC (str)((str)->base.static_flag) = 1;
312 str = build_fold_addr_expr (str)build_fold_addr_expr_loc (((location_t) 0), (str));
313 }
314 tree ctor = build_constructor_va (type, 3, NULL_TREE(tree) nullptr, str, NULL_TREE(tree) nullptr,
315 build_int_cst (unsigned_type_nodeinteger_types[itk_unsigned_int],
316 xloc.line), NULL_TREE(tree) nullptr,
317 build_int_cst (unsigned_type_nodeinteger_types[itk_unsigned_int],
318 xloc.column));
319 TREE_CONSTANT (ctor)((non_type_check ((ctor), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 319, __FUNCTION__))->base.constant_flag)
= 1;
320 TREE_STATIC (ctor)((ctor)->base.static_flag) = 1;
321
322 return ctor;
323}
324
325/* This routine returns a magic number for TYPE. */
326
327static unsigned short
328get_ubsan_type_info_for_type (tree type)
329{
330 if (TREE_CODE (type)((enum tree_code) (type)->base.code) == REAL_TYPE)
331 return tree_to_uhwi (TYPE_SIZE (type)((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 331, __FUNCTION__))->type_common.size)
);
332 else if (INTEGRAL_TYPE_P (type)(((enum tree_code) (type)->base.code) == ENUMERAL_TYPE || (
(enum tree_code) (type)->base.code) == BOOLEAN_TYPE || ((enum
tree_code) (type)->base.code) == INTEGER_TYPE)
)
333 {
334 int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type)((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 334, __FUNCTION__))->type_common.size)
));
335 gcc_assert (prec != -1)((void)(!(prec != -1) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 335, __FUNCTION__), 0 : 0))
;
336 return (prec << 1) | !TYPE_UNSIGNED (type)((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 336, __FUNCTION__))->base.u.bits.unsigned_flag)
;
337 }
338 else
339 return 0;
340}
341
342/* Counters for internal labels. ubsan_ids[0] for Lubsan_type,
343 ubsan_ids[1] for Lubsan_data labels. */
344static GTY(()) unsigned int ubsan_ids[2];
345
346/* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type
347 descriptor. It first looks into the hash table; if not found,
348 create the VAR_DECL, put it into the hash table and return the
349 ADDR_EXPR of it. TYPE describes a particular type. PSTYLE is
350 an enum controlling how we want to print the type. */
351
352tree
353ubsan_type_descriptor (tree type, enum ubsan_print_style pstyle)
354{
355 /* See through any typedefs. */
356 type = TYPE_MAIN_VARIANT (type)((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 356, __FUNCTION__))->type_common.main_variant)
;
357
358 tree decl = decl_for_type_lookup (type);
359 /* It is possible that some of the earlier created DECLs were found
360 unused, in that case they weren't emitted and varpool_node::get
361 returns NULL node on them. But now we really need them. Thus,
362 renew them here. */
363 if (decl != NULL_TREE(tree) nullptr && varpool_node::get (decl))
364 return build_fold_addr_expr (decl)build_fold_addr_expr_loc (((location_t) 0), (decl));
365
366 tree dtype = ubsan_get_type_descriptor_type ();
367 tree type2 = type;
368 const char *tname = NULLnullptr;
369 pretty_printer pretty_name;
370 unsigned char deref_depth = 0;
371 unsigned short tkind, tinfo;
372
373 /* Get the name of the type, or the name of the pointer type. */
374 if (pstyle == UBSAN_PRINT_POINTER)
375 {
376 gcc_assert (POINTER_TYPE_P (type))((void)(!((((enum tree_code) (type)->base.code) == POINTER_TYPE
|| ((enum tree_code) (type)->base.code) == REFERENCE_TYPE
)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 376, __FUNCTION__), 0 : 0))
;
377 type2 = TREE_TYPE (type)((contains_struct_check ((type), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 377, __FUNCTION__))->typed.type)
;
378
379 /* Remove any '*' operators from TYPE. */
380 while (POINTER_TYPE_P (type2)(((enum tree_code) (type2)->base.code) == POINTER_TYPE || (
(enum tree_code) (type2)->base.code) == REFERENCE_TYPE)
)
381 deref_depth++, type2 = TREE_TYPE (type2)((contains_struct_check ((type2), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 381, __FUNCTION__))->typed.type)
;
382
383 if (TREE_CODE (type2)((enum tree_code) (type2)->base.code) == METHOD_TYPE)
384 type2 = TYPE_METHOD_BASETYPE (type2)((tree_check2 ((type2), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 384, __FUNCTION__, (FUNCTION_TYPE), (METHOD_TYPE)))->type_non_common
.maxval)
;
385 }
386
387 /* If an array, get its type. */
388 type2 = strip_array_types (type2);
389
390 if (pstyle == UBSAN_PRINT_ARRAY)
391 {
392 while (POINTER_TYPE_P (type2)(((enum tree_code) (type2)->base.code) == POINTER_TYPE || (
(enum tree_code) (type2)->base.code) == REFERENCE_TYPE)
)
393 deref_depth++, type2 = TREE_TYPE (type2)((contains_struct_check ((type2), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 393, __FUNCTION__))->typed.type)
;
394 }
395
396 if (TYPE_NAME (type2)((tree_class_check ((type2), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 396, __FUNCTION__))->type_common.name)
!= NULLnullptr)
397 {
398 if (TREE_CODE (TYPE_NAME (type2))((enum tree_code) (((tree_class_check ((type2), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 398, __FUNCTION__))->type_common.name))->base.code)
== IDENTIFIER_NODE)
399 tname = IDENTIFIER_POINTER (TYPE_NAME (type2))((const char *) (tree_check ((((tree_class_check ((type2), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 399, __FUNCTION__))->type_common.name)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 399, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str
)
;
400 else if (DECL_NAME (TYPE_NAME (type2))((contains_struct_check ((((tree_class_check ((type2), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 400, __FUNCTION__))->type_common.name)), (TS_DECL_MINIMAL
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 400, __FUNCTION__))->decl_minimal.name)
!= NULLnullptr)
401 tname = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type2)))((const char *) (tree_check ((((contains_struct_check ((((tree_class_check
((type2), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 401, __FUNCTION__))->type_common.name)), (TS_DECL_MINIMAL
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 401, __FUNCTION__))->decl_minimal.name)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 401, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str
)
;
402 }
403
404 if (tname == NULLnullptr)
405 /* We weren't able to determine the type name. */
406 tname = "<unknown>";
407
408 pp_quote (&pretty_name)pp_character (&pretty_name, '\'');
409
410 tree eltype = type;
411 if (pstyle == UBSAN_PRINT_POINTER)
412 {
413 pp_printf (&pretty_name, "%s%s%s%s%s%s%s",
414 TYPE_VOLATILE (type2)((tree_class_check ((type2), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 414, __FUNCTION__))->base.volatile_flag)
? "volatile " : "",
415 TYPE_READONLY (type2)((tree_class_check ((type2), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 415, __FUNCTION__))->base.readonly_flag)
? "const " : "",
416 TYPE_RESTRICT (type2)((tree_class_check ((type2), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 416, __FUNCTION__))->type_common.restrict_flag)
? "restrict " : "",
417 TYPE_ATOMIC (type2)((tree_class_check ((type2), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 417, __FUNCTION__))->base.u.bits.atomic_flag)
? "_Atomic " : "",
418 TREE_CODE (type2)((enum tree_code) (type2)->base.code) == RECORD_TYPE
419 ? "struct "
420 : TREE_CODE (type2)((enum tree_code) (type2)->base.code) == UNION_TYPE
421 ? "union " : "", tname,
422 deref_depth == 0 ? "" : " ");
423 while (deref_depth-- > 0)
424 pp_star (&pretty_name)pp_character (&pretty_name, '*');
425 }
426 else if (pstyle == UBSAN_PRINT_ARRAY)
427 {
428 /* Pretty print the array dimensions. */
429 gcc_assert (TREE_CODE (type) == ARRAY_TYPE)((void)(!(((enum tree_code) (type)->base.code) == ARRAY_TYPE
) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 429, __FUNCTION__), 0 : 0))
;
430 tree t = type;
431 pp_string (&pretty_name, tname);
432 pp_space (&pretty_name)pp_character (&pretty_name, ' ');
433 while (deref_depth-- > 0)
434 pp_star (&pretty_name)pp_character (&pretty_name, '*');
435 while (TREE_CODE (t)((enum tree_code) (t)->base.code) == ARRAY_TYPE)
436 {
437 pp_left_bracket (&pretty_name)pp_character (&pretty_name, '[');
438 tree dom = TYPE_DOMAIN (t)((tree_check ((t), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 438, __FUNCTION__, (ARRAY_TYPE)))->type_non_common.values
)
;
439 if (dom != NULL_TREE(tree) nullptr
440 && TYPE_MAX_VALUE (dom)((tree_check5 ((dom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 440, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE
), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval
)
!= NULL_TREE(tree) nullptr
441 && TREE_CODE (TYPE_MAX_VALUE (dom))((enum tree_code) (((tree_check5 ((dom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 441, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE
), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval
))->base.code)
== INTEGER_CST)
442 {
443 unsigned HOST_WIDE_INTlong m;
444 if (tree_fits_uhwi_p (TYPE_MAX_VALUE (dom)((tree_check5 ((dom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 444, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE
), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval
)
)
445 && (m = tree_to_uhwi (TYPE_MAX_VALUE (dom)((tree_check5 ((dom), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 445, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE
), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval
)
)) + 1 != 0)
446 pp_unsigned_wide_integer (&pretty_name, m + 1)do { sprintf ((&pretty_name)->buffer->digit_buffer,
"%" "l" "u", (unsigned long) m + 1); pp_string (&pretty_name
, (&pretty_name)->buffer->digit_buffer); } while (0
)
;
447 else
448 pp_wide_int (&pretty_name,do { print_dec (wi::add (wi::to_widest (((tree_check5 ((dom),
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 449, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE
), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval
)), 1), (&pretty_name)->buffer->digit_buffer, ((signop
) ((tree_class_check ((((contains_struct_check ((dom), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 450, __FUNCTION__))->typed.type)), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 450, __FUNCTION__))->base.u.bits.unsigned_flag))); pp_string
(&pretty_name, (&pretty_name)->buffer->digit_buffer
); } while (0)
449 wi::add (wi::to_widest (TYPE_MAX_VALUE (dom)), 1),do { print_dec (wi::add (wi::to_widest (((tree_check5 ((dom),
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 449, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE
), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval
)), 1), (&pretty_name)->buffer->digit_buffer, ((signop
) ((tree_class_check ((((contains_struct_check ((dom), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 450, __FUNCTION__))->typed.type)), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 450, __FUNCTION__))->base.u.bits.unsigned_flag))); pp_string
(&pretty_name, (&pretty_name)->buffer->digit_buffer
); } while (0)
450 TYPE_SIGN (TREE_TYPE (dom)))do { print_dec (wi::add (wi::to_widest (((tree_check5 ((dom),
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 449, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE
), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval
)), 1), (&pretty_name)->buffer->digit_buffer, ((signop
) ((tree_class_check ((((contains_struct_check ((dom), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 450, __FUNCTION__))->typed.type)), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 450, __FUNCTION__))->base.u.bits.unsigned_flag))); pp_string
(&pretty_name, (&pretty_name)->buffer->digit_buffer
); } while (0)
;
451 }
452 else
453 /* ??? We can't determine the variable name; print VLA unspec. */
454 pp_star (&pretty_name)pp_character (&pretty_name, '*');
455 pp_right_bracket (&pretty_name)pp_character (&pretty_name, ']');
456 t = TREE_TYPE (t)((contains_struct_check ((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 456, __FUNCTION__))->typed.type)
;
457 }
458
459 /* Save the tree with stripped types. */
460 eltype = t;
461 }
462 else
463 pp_string (&pretty_name, tname);
464
465 pp_quote (&pretty_name)pp_character (&pretty_name, '\'');
466
467 switch (TREE_CODE (eltype)((enum tree_code) (eltype)->base.code))
468 {
469 case BOOLEAN_TYPE:
470 case ENUMERAL_TYPE:
471 case INTEGER_TYPE:
472 tkind = 0x0000;
473 break;
474 case REAL_TYPE:
475 /* FIXME: libubsan right now only supports float, double and
476 long double type formats. */
477 if (TYPE_MODE (eltype)((((enum tree_code) ((tree_class_check ((eltype), (tcc_type),
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 477, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(eltype) : (eltype)->type_common.mode)
== TYPE_MODE (float_type_node)((((enum tree_code) ((tree_class_check ((global_trees[TI_FLOAT_TYPE
]), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 477, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(global_trees[TI_FLOAT_TYPE]) : (global_trees[TI_FLOAT_TYPE]
)->type_common.mode)
478 || TYPE_MODE (eltype)((((enum tree_code) ((tree_class_check ((eltype), (tcc_type),
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 478, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(eltype) : (eltype)->type_common.mode)
== TYPE_MODE (double_type_node)((((enum tree_code) ((tree_class_check ((global_trees[TI_DOUBLE_TYPE
]), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 478, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(global_trees[TI_DOUBLE_TYPE]) : (global_trees[TI_DOUBLE_TYPE
])->type_common.mode)
479 || TYPE_MODE (eltype)((((enum tree_code) ((tree_class_check ((eltype), (tcc_type),
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 479, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(eltype) : (eltype)->type_common.mode)
== TYPE_MODE (long_double_type_node)((((enum tree_code) ((tree_class_check ((global_trees[TI_LONG_DOUBLE_TYPE
]), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 479, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(global_trees[TI_LONG_DOUBLE_TYPE]) : (global_trees[TI_LONG_DOUBLE_TYPE
])->type_common.mode)
)
480 tkind = 0x0001;
481 else
482 tkind = 0xffff;
483 break;
484 default:
485 tkind = 0xffff;
486 break;
487 }
488 tinfo = get_ubsan_type_info_for_type (eltype);
489
490 /* Create a new VAR_DECL of type descriptor. */
491 const char *tmp = pp_formatted_text (&pretty_name);
492 size_t len = strlen (tmp) + 1;
493 tree str = build_string (len, tmp);
494 TREE_TYPE (str)((contains_struct_check ((str), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 494, __FUNCTION__))->typed.type)
= build_array_type_nelts (char_type_nodeinteger_types[itk_char], len);
495 TREE_READONLY (str)((non_type_check ((str), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 495, __FUNCTION__))->base.readonly_flag)
= 1;
496 TREE_STATIC (str)((str)->base.static_flag) = 1;
497
498 char tmp_name[32];
499 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_type", ubsan_ids[0]++)do { char *__p; (tmp_name)[0] = '*'; (tmp_name)[1] = '.'; __p
= stpcpy (&(tmp_name)[2], "Lubsan_type"); sprint_ul (__p
, (unsigned long) (ubsan_ids[0]++)); } while (0)
;
500 decl = build_decl (UNKNOWN_LOCATION((location_t) 0), VAR_DECL, get_identifier (tmp_name)(__builtin_constant_p (tmp_name) ? get_identifier_with_length
((tmp_name), strlen (tmp_name)) : get_identifier (tmp_name))
,
501 dtype);
502 TREE_STATIC (decl)((decl)->base.static_flag) = 1;
503 TREE_PUBLIC (decl)((decl)->base.public_flag) = 0;
504 DECL_ARTIFICIAL (decl)((contains_struct_check ((decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 504, __FUNCTION__))->decl_common.artificial_flag)
= 1;
505 DECL_IGNORED_P (decl)((contains_struct_check ((decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 505, __FUNCTION__))->decl_common.ignored_flag)
= 1;
506 DECL_EXTERNAL (decl)((contains_struct_check ((decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 506, __FUNCTION__))->decl_common.decl_flag_1)
= 0;
507 DECL_SIZE (decl)((contains_struct_check ((decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 507, __FUNCTION__))->decl_common.size)
508 = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (TREE_TYPE (str)))size_binop_loc (((location_t) 0), PLUS_EXPR, ((contains_struct_check
((decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 508, __FUNCTION__))->decl_common.size), ((tree_class_check
((((contains_struct_check ((str), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 508, __FUNCTION__))->typed.type)), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 508, __FUNCTION__))->type_common.size))
;
509 DECL_SIZE_UNIT (decl)((contains_struct_check ((decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 509, __FUNCTION__))->decl_common.size_unit)
510 = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),size_binop_loc (((location_t) 0), PLUS_EXPR, ((contains_struct_check
((decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 510, __FUNCTION__))->decl_common.size_unit), ((tree_class_check
((((contains_struct_check ((str), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 511, __FUNCTION__))->typed.type)), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 511, __FUNCTION__))->type_common.size_unit))
511 TYPE_SIZE_UNIT (TREE_TYPE (str)))size_binop_loc (((location_t) 0), PLUS_EXPR, ((contains_struct_check
((decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 510, __FUNCTION__))->decl_common.size_unit), ((tree_class_check
((((contains_struct_check ((str), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 511, __FUNCTION__))->typed.type)), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 511, __FUNCTION__))->type_common.size_unit))
;
512
513 tree ctor = build_constructor_va (dtype, 3, NULL_TREE(tree) nullptr,
514 build_int_cst (short_unsigned_type_nodeinteger_types[itk_unsigned_short],
515 tkind), NULL_TREE(tree) nullptr,
516 build_int_cst (short_unsigned_type_nodeinteger_types[itk_unsigned_short],
517 tinfo), NULL_TREE(tree) nullptr, str);
518 TREE_CONSTANT (ctor)((non_type_check ((ctor), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 518, __FUNCTION__))->base.constant_flag)
= 1;
519 TREE_STATIC (ctor)((ctor)->base.static_flag) = 1;
520 DECL_INITIAL (decl)((contains_struct_check ((decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 520, __FUNCTION__))->decl_common.initial)
= ctor;
521 varpool_node::finalize_decl (decl);
522
523 /* Save the VAR_DECL into the hash table. */
524 decl_for_type_insert (type, decl);
525
526 return build_fold_addr_expr (decl)build_fold_addr_expr_loc (((location_t) 0), (decl));
527}
528
529/* Create a structure for the ubsan library. NAME is a name of the new
530 structure. LOCCNT is number of locations, PLOC points to array of
531 locations. The arguments in ... are of __ubsan_type_descriptor type
532 and there are at most two of them, followed by NULL_TREE, followed
533 by optional extra arguments and another NULL_TREE. */
534
535tree
536ubsan_create_data (const char *name, int loccnt, const location_t *ploc, ...)
537{
538 va_list args;
539 tree ret, t;
540 tree fields[6];
541 vec<tree, va_gc> *saved_args = NULLnullptr;
542 size_t i = 0;
543 int j;
544
545 /* It is possible that PCH zapped table with definitions of sanitizer
546 builtins. Reinitialize them if needed. */
547 initialize_sanitizer_builtins ();
548
549 /* Firstly, create a pointer to type descriptor type. */
550 tree td_type = ubsan_get_type_descriptor_type ();
551 td_type = build_pointer_type (td_type);
552
553 /* Create the structure type. */
554 ret = make_node (RECORD_TYPE);
555 for (j = 0; j < loccnt; j++)
1
Assuming 'j' is >= 'loccnt'
2
Loop condition is false. Execution continues on line 566
556 {
557 gcc_checking_assert (i < 2)((void)(!(i < 2) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 557, __FUNCTION__), 0 : 0))
;
558 fields[i] = build_decl (UNKNOWN_LOCATION((location_t) 0), FIELD_DECL, NULL_TREE(tree) nullptr,
559 ubsan_get_source_location_type ());
560 DECL_CONTEXT (fields[i])((contains_struct_check ((fields[i]), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 560, __FUNCTION__))->decl_minimal.context)
= ret;
561 if (i)
562 DECL_CHAIN (fields[i - 1])(((contains_struct_check (((contains_struct_check ((fields[i -
1]), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 562, __FUNCTION__))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 562, __FUNCTION__))->common.chain))
= fields[i];
563 i++;
564 }
565
566 va_start (args, ploc)__builtin_va_start(args, ploc);
567 for (t = va_arg (args, tree)__builtin_va_arg(args, tree); t != NULL_TREE(tree) nullptr;
3
Assuming the condition is true
4
Loop condition is true. Entering loop body
29
Assuming the condition is true
30
Loop condition is true. Entering loop body
568 i++, t = va_arg (args, tree)__builtin_va_arg(args, tree))
569 {
570 gcc_checking_assert (i < 4)((void)(!(i < 4) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 570, __FUNCTION__), 0 : 0))
;
5
'?' condition is false
31
'?' condition is false
571 /* Save the tree arguments for later use. */
572 vec_safe_push (saved_args, t);
6
Calling 'vec_safe_push<tree_node *, va_gc>'
27
Returning from 'vec_safe_push<tree_node *, va_gc>'
32
Passing value via 1st parameter 'v'
33
Calling 'vec_safe_push<tree_node *, va_gc>'
573 fields[i] = build_decl (UNKNOWN_LOCATION((location_t) 0), FIELD_DECL, NULL_TREE(tree) nullptr,
574 td_type);
575 DECL_CONTEXT (fields[i])((contains_struct_check ((fields[i]), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 575, __FUNCTION__))->decl_minimal.context)
= ret;
576 if (i
27.1
'i' is 0
27.1
'i' is 0
)
28
Taking false branch
577 DECL_CHAIN (fields[i - 1])(((contains_struct_check (((contains_struct_check ((fields[i -
1]), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 577, __FUNCTION__))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 577, __FUNCTION__))->common.chain))
= fields[i];
578 }
579
580 for (t = va_arg (args, tree)__builtin_va_arg(args, tree); t != NULL_TREE(tree) nullptr;
581 i++, t = va_arg (args, tree)__builtin_va_arg(args, tree))
582 {
583 gcc_checking_assert (i < 6)((void)(!(i < 6) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 583, __FUNCTION__), 0 : 0))
;
584 /* Save the tree arguments for later use. */
585 vec_safe_push (saved_args, t);
586 fields[i] = build_decl (UNKNOWN_LOCATION((location_t) 0), FIELD_DECL, NULL_TREE(tree) nullptr,
587 TREE_TYPE (t)((contains_struct_check ((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 587, __FUNCTION__))->typed.type)
);
588 DECL_CONTEXT (fields[i])((contains_struct_check ((fields[i]), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 588, __FUNCTION__))->decl_minimal.context)
= ret;
589 if (i)
590 DECL_CHAIN (fields[i - 1])(((contains_struct_check (((contains_struct_check ((fields[i -
1]), (TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 590, __FUNCTION__))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 590, __FUNCTION__))->common.chain))
= fields[i];
591 }
592 va_end (args)__builtin_va_end(args);
593
594 tree type_decl = build_decl (input_location, TYPE_DECL,
595 get_identifier (name)(__builtin_constant_p (name) ? get_identifier_with_length ((name
), strlen (name)) : get_identifier (name))
, ret);
596 DECL_IGNORED_P (type_decl)((contains_struct_check ((type_decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 596, __FUNCTION__))->decl_common.ignored_flag)
= 1;
597 DECL_ARTIFICIAL (type_decl)((contains_struct_check ((type_decl), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 597, __FUNCTION__))->decl_common.artificial_flag)
= 1;
598 TYPE_FIELDS (ret)((tree_check3 ((ret), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 598, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE
)))->type_non_common.values)
= fields[0];
599 TYPE_NAME (ret)((tree_class_check ((ret), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 599, __FUNCTION__))->type_common.name)
= type_decl;
600 TYPE_STUB_DECL (ret)(((contains_struct_check (((tree_class_check ((ret), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 600, __FUNCTION__))), (TS_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 600, __FUNCTION__))->common.chain))
= type_decl;
601 TYPE_ARTIFICIAL (ret)((tree_class_check ((ret), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 601, __FUNCTION__))->base.nowarning_flag)
= 1;
602 layout_type (ret);
603
604 /* Now, fill in the type. */
605 char tmp_name[32];
606 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lubsan_data", ubsan_ids[1]++)do { char *__p; (tmp_name)[0] = '*'; (tmp_name)[1] = '.'; __p
= stpcpy (&(tmp_name)[2], "Lubsan_data"); sprint_ul (__p
, (unsigned long) (ubsan_ids[1]++)); } while (0)
;
607 tree var = build_decl (UNKNOWN_LOCATION((location_t) 0), VAR_DECL, get_identifier (tmp_name)(__builtin_constant_p (tmp_name) ? get_identifier_with_length
((tmp_name), strlen (tmp_name)) : get_identifier (tmp_name))
,
608 ret);
609 TREE_STATIC (var)((var)->base.static_flag) = 1;
610 TREE_PUBLIC (var)((var)->base.public_flag) = 0;
611 DECL_ARTIFICIAL (var)((contains_struct_check ((var), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 611, __FUNCTION__))->decl_common.artificial_flag)
= 1;
612 DECL_IGNORED_P (var)((contains_struct_check ((var), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 612, __FUNCTION__))->decl_common.ignored_flag)
= 1;
613 DECL_EXTERNAL (var)((contains_struct_check ((var), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 613, __FUNCTION__))->decl_common.decl_flag_1)
= 0;
614
615 vec<constructor_elt, va_gc> *v;
616 vec_alloc (v, i);
617 tree ctor = build_constructor (ret, v);
618
619 /* If desirable, set the __ubsan_source_location element. */
620 for (j = 0; j < loccnt; j++)
621 {
622 location_t loc = LOCATION_LOCUS (ploc[j])((IS_ADHOC_LOC (ploc[j])) ? get_location_from_adhoc_loc (line_table
, ploc[j]) : (ploc[j]))
;
623 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, ubsan_source_location (loc))do { constructor_elt _ce___ = {(tree) nullptr, ubsan_source_location
(loc)}; vec_safe_push ((v), _ce___); } while (0)
;
624 }
625
626 size_t nelts = vec_safe_length (saved_args);
627 for (i = 0; i < nelts; i++)
628 {
629 t = (*saved_args)[i];
630 CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t)do { constructor_elt _ce___ = {(tree) nullptr, t}; vec_safe_push
((v), _ce___); } while (0)
;
631 }
632
633 TREE_CONSTANT (ctor)((non_type_check ((ctor), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 633, __FUNCTION__))->base.constant_flag)
= 1;
634 TREE_STATIC (ctor)((ctor)->base.static_flag) = 1;
635 DECL_INITIAL (var)((contains_struct_check ((var), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 635, __FUNCTION__))->decl_common.initial)
= ctor;
636 varpool_node::finalize_decl (var);
637
638 return var;
639}
640
641/* Instrument the __builtin_unreachable call. We just call the libubsan
642 routine instead. */
643
644bool
645ubsan_instrument_unreachable (gimple_stmt_iterator *gsi)
646{
647 gimple *g;
648 location_t loc = gimple_location (gsi_stmt (*gsi));
649
650 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
651 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
652 else
653 {
654 tree data = ubsan_create_data ("__ubsan_unreachable_data", 1, &loc,
655 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
656 data = build_fold_addr_expr_loc (loc, data);
657 tree fn
658 = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE);
659 g = gimple_build_call (fn, 1, data);
660 }
661 gimple_set_location (g, loc);
662 gsi_replace (gsi, g, false);
663 return false;
664}
665
666/* Return true if T is a call to a libubsan routine. */
667
668bool
669is_ubsan_builtin_p (tree t)
670{
671 return TREE_CODE (t)((enum tree_code) (t)->base.code) == FUNCTION_DECL
672 && fndecl_built_in_p (t, BUILT_IN_NORMAL)
673 && strncmp (IDENTIFIER_POINTER (DECL_NAME (t))((const char *) (tree_check ((((contains_struct_check ((t), (
TS_DECL_MINIMAL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 673, __FUNCTION__))->decl_minimal.name)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 673, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str
)
,
674 "__builtin___ubsan_", 18) == 0;
675}
676
677/* Create a callgraph edge for statement STMT. */
678
679static void
680ubsan_create_edge (gimple *stmt)
681{
682 gcall *call_stmt = dyn_cast <gcall *> (stmt);
683 basic_block bb = gimple_bb (stmt);
684 cgraph_node *node = cgraph_node::get (current_function_decl);
685 tree decl = gimple_call_fndecl (call_stmt);
686 if (decl)
687 node->create_edge (cgraph_node::get_create (decl), call_stmt, bb->count);
688}
689
690/* Expand the UBSAN_BOUNDS special builtin function. */
691
692bool
693ubsan_expand_bounds_ifn (gimple_stmt_iterator *gsi)
694{
695 gimple *stmt = gsi_stmt (*gsi);
696 location_t loc = gimple_location (stmt);
697 gcc_assert (gimple_call_num_args (stmt) == 3)((void)(!(gimple_call_num_args (stmt) == 3) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 697, __FUNCTION__), 0 : 0))
;
698
699 /* Pick up the arguments of the UBSAN_BOUNDS call. */
700 tree type = TREE_TYPE (TREE_TYPE (gimple_call_arg (stmt, 0)))((contains_struct_check ((((contains_struct_check ((gimple_call_arg
(stmt, 0)), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 700, __FUNCTION__))->typed.type)), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 700, __FUNCTION__))->typed.type)
;
701 tree index = gimple_call_arg (stmt, 1);
702 tree orig_index = index;
703 tree bound = gimple_call_arg (stmt, 2);
704
705 gimple_stmt_iterator gsi_orig = *gsi;
706
707 /* Create condition "if (index > bound)". */
708 basic_block then_bb, fallthru_bb;
709 gimple_stmt_iterator cond_insert_point
710 = create_cond_insert_point (gsi, false, false, true,
711 &then_bb, &fallthru_bb);
712 index = fold_convert (TREE_TYPE (bound), index)fold_convert_loc (((location_t) 0), ((contains_struct_check (
(bound), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 712, __FUNCTION__))->typed.type), index)
;
713 index = force_gimple_operand_gsi (&cond_insert_point, index,
714 true, NULL_TREE(tree) nullptr,
715 false, GSI_NEW_STMT);
716 gimple *g = gimple_build_cond (GT_EXPR, index, bound, NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
717 gimple_set_location (g, loc);
718 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
719
720 /* Generate __ubsan_handle_out_of_bounds call. */
721 *gsi = gsi_after_labels (then_bb);
722 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
723 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
724 else
725 {
726 tree data
727 = ubsan_create_data ("__ubsan_out_of_bounds_data", 1, &loc,
728 ubsan_type_descriptor (type, UBSAN_PRINT_ARRAY),
729 ubsan_type_descriptor (TREE_TYPE (orig_index)((contains_struct_check ((orig_index), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 729, __FUNCTION__))->typed.type)
),
730 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
731 data = build_fold_addr_expr_loc (loc, data);
732 enum built_in_function bcode
733 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_BOUNDS)
734 ? BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS
735 : BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT;
736 tree fn = builtin_decl_explicit (bcode);
737 tree val = ubsan_encode_value (orig_index, UBSAN_ENCODE_VALUE_GIMPLE);
738 val = force_gimple_operand_gsi (gsi, val, true, NULL_TREE(tree) nullptr, true,
739 GSI_SAME_STMT);
740 g = gimple_build_call (fn, 2, data, val);
741 }
742 gimple_set_location (g, loc);
743 gsi_insert_before (gsi, g, GSI_SAME_STMT);
744
745 /* Get rid of the UBSAN_BOUNDS call from the IR. */
746 unlink_stmt_vdef (stmt);
747 gsi_remove (&gsi_orig, true);
748
749 /* Point GSI to next logical statement. */
750 *gsi = gsi_start_bb (fallthru_bb);
751 return true;
752}
753
754/* Expand UBSAN_NULL internal call. The type is kept on the ckind
755 argument which is a constant, because the middle-end treats pointer
756 conversions as useless and therefore the type of the first argument
757 could be changed to any other pointer type. */
758
759bool
760ubsan_expand_null_ifn (gimple_stmt_iterator *gsip)
761{
762 gimple_stmt_iterator gsi = *gsip;
763 gimple *stmt = gsi_stmt (gsi);
764 location_t loc = gimple_location (stmt);
765 gcc_assert (gimple_call_num_args (stmt) == 3)((void)(!(gimple_call_num_args (stmt) == 3) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 765, __FUNCTION__), 0 : 0))
;
766 tree ptr = gimple_call_arg (stmt, 0);
767 tree ckind = gimple_call_arg (stmt, 1);
768 tree align = gimple_call_arg (stmt, 2);
769 tree check_align = NULL_TREE(tree) nullptr;
770 bool check_null;
771
772 basic_block cur_bb = gsi_bb (gsi);
773
774 gimple *g;
775 if (!integer_zerop (align))
776 {
777 unsigned int ptralign = get_pointer_alignment (ptr) / BITS_PER_UNIT(8);
778 if (compare_tree_int (align, ptralign) == 1)
779 {
780 check_align = make_ssa_name (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE]);
781 g = gimple_build_assign (check_align, NOP_EXPR, ptr);
782 gimple_set_location (g, loc);
783 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
784 }
785 }
786 check_null = sanitize_flags_p (SANITIZE_NULL);
787
788 if (check_align == NULL_TREE(tree) nullptr && !check_null)
789 {
790 gsi_remove (gsip, true);
791 /* Unlink the UBSAN_NULLs vops before replacing it. */
792 unlink_stmt_vdef (stmt);
793 return true;
794 }
795
796 /* Split the original block holding the pointer dereference. */
797 edge e = split_block (cur_bb, stmt);
798
799 /* Get a hold on the 'condition block', the 'then block' and the
800 'else block'. */
801 basic_block cond_bb = e->src;
802 basic_block fallthru_bb = e->dest;
803 basic_block then_bb = create_empty_bb (cond_bb);
804 add_bb_to_loop (then_bb, cond_bb->loop_father);
805 loops_state_set (LOOPS_NEED_FIXUP);
806
807 /* Make an edge coming from the 'cond block' into the 'then block';
808 this edge is unlikely taken, so set up the probability accordingly. */
809 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
810 e->probability = profile_probability::very_unlikely ();
811 then_bb->count = e->count ();
812
813 /* Connect 'then block' with the 'else block'. This is needed
814 as the ubsan routines we call in the 'then block' are not noreturn.
815 The 'then block' only has one outcoming edge. */
816 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
817
818 /* Set up the fallthrough basic block. */
819 e = find_edge (cond_bb, fallthru_bb);
820 e->flags = EDGE_FALSE_VALUE;
821 e->probability = profile_probability::very_likely ();
822
823 /* Update dominance info for the newly created then_bb; note that
824 fallthru_bb's dominance info has already been updated by
825 split_block. */
826 if (dom_info_available_p (CDI_DOMINATORS))
827 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
828
829 /* Put the ubsan builtin call into the newly created BB. */
830 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
831 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
832 else
833 {
834 enum built_in_function bcode
835 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & ((check_align ? SANITIZE_ALIGNMENT : 0)
836 | (check_null ? SANITIZE_NULL : 0)))
837 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
838 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT;
839 tree fn = builtin_decl_implicit (bcode);
840 int align_log = tree_log2 (align);
841 tree data
842 = ubsan_create_data ("__ubsan_null_data", 1, &loc,
843 ubsan_type_descriptor (TREE_TYPE (ckind)((contains_struct_check ((ckind), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 843, __FUNCTION__))->typed.type)
,
844 UBSAN_PRINT_POINTER),
845 NULL_TREE(tree) nullptr,
846 build_int_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char],
847 MAX (align_log, 0)((align_log) > (0) ? (align_log) : (0))),
848 fold_convert (unsigned_char_type_node, ckind)fold_convert_loc (((location_t) 0), integer_types[itk_unsigned_char
], ckind)
,
849 NULL_TREE(tree) nullptr);
850 data = build_fold_addr_expr_loc (loc, data);
851 g = gimple_build_call (fn, 2, data,
852 check_align ? check_align
853 : build_zero_cst (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE]));
854 }
855 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
856 gimple_set_location (g, loc);
857 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
858
859 /* Unlink the UBSAN_NULLs vops before replacing it. */
860 unlink_stmt_vdef (stmt);
861
862 if (check_null)
863 {
864 g = gimple_build_cond (EQ_EXPR, ptr, build_int_cst (TREE_TYPE (ptr)((contains_struct_check ((ptr), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 864, __FUNCTION__))->typed.type)
, 0),
865 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
866 gimple_set_location (g, loc);
867
868 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
869 gsi_replace (&gsi, g, false);
870 stmt = g;
871 }
872
873 if (check_align)
874 {
875 if (check_null)
876 {
877 /* Split the block with the condition again. */
878 e = split_block (cond_bb, stmt);
879 basic_block cond1_bb = e->src;
880 basic_block cond2_bb = e->dest;
881
882 /* Make an edge coming from the 'cond1 block' into the 'then block';
883 this edge is unlikely taken, so set up the probability
884 accordingly. */
885 e = make_edge (cond1_bb, then_bb, EDGE_TRUE_VALUE);
886 e->probability = profile_probability::very_unlikely ();
887
888 /* Set up the fallthrough basic block. */
889 e = find_edge (cond1_bb, cond2_bb);
890 e->flags = EDGE_FALSE_VALUE;
891 e->probability = profile_probability::very_likely ();
892
893 /* Update dominance info. */
894 if (dom_info_available_p (CDI_DOMINATORS))
895 {
896 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond1_bb);
897 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond1_bb);
898 }
899
900 gsi2 = gsi_start_bb (cond2_bb);
901 }
902
903 tree mask = build_int_cst (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE],
904 tree_to_uhwi (align) - 1);
905 g = gimple_build_assign (make_ssa_name (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE]),
906 BIT_AND_EXPR, check_align, mask);
907 gimple_set_location (g, loc);
908 if (check_null)
909 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
910 else
911 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
912
913 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g),
914 build_int_cst (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE], 0),
915 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
916 gimple_set_location (g, loc);
917 if (check_null)
918 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
919 else
920 /* Replace the UBSAN_NULL with a GIMPLE_COND stmt. */
921 gsi_replace (&gsi, g, false);
922 }
923 return false;
924}
925
926#define OBJSZ_MAX_OFFSET(1024 * 16) (1024 * 16)
927
928/* Expand UBSAN_OBJECT_SIZE internal call. */
929
930bool
931ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi)
932{
933 gimple *stmt = gsi_stmt (*gsi);
934 location_t loc = gimple_location (stmt);
935 gcc_assert (gimple_call_num_args (stmt) == 4)((void)(!(gimple_call_num_args (stmt) == 4) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 935, __FUNCTION__), 0 : 0))
;
936
937 tree ptr = gimple_call_arg (stmt, 0);
938 tree offset = gimple_call_arg (stmt, 1);
939 tree size = gimple_call_arg (stmt, 2);
940 tree ckind = gimple_call_arg (stmt, 3);
941 gimple_stmt_iterator gsi_orig = *gsi;
942 gimple *g;
943
944 /* See if we can discard the check. */
945 if (TREE_CODE (size)((enum tree_code) (size)->base.code) != INTEGER_CST
946 || integer_all_onesp (size))
947 /* Yes, __builtin_object_size couldn't determine the
948 object size. */;
949 else if (TREE_CODE (offset)((enum tree_code) (offset)->base.code) == INTEGER_CST
950 && wi::to_widest (offset) >= -OBJSZ_MAX_OFFSET(1024 * 16)
951 && wi::to_widest (offset) <= -1)
952 /* The offset is in range [-16K, -1]. */;
953 else
954 {
955 /* if (offset > objsize) */
956 basic_block then_bb, fallthru_bb;
957 gimple_stmt_iterator cond_insert_point
958 = create_cond_insert_point (gsi, false, false, true,
959 &then_bb, &fallthru_bb);
960 g = gimple_build_cond (GT_EXPR, offset, size, NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
961 gimple_set_location (g, loc);
962 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
963
964 /* If the offset is small enough, we don't need the second
965 run-time check. */
966 if (TREE_CODE (offset)((enum tree_code) (offset)->base.code) == INTEGER_CST
967 && wi::to_widest (offset) >= 0
968 && wi::to_widest (offset) <= OBJSZ_MAX_OFFSET(1024 * 16))
969 *gsi = gsi_after_labels (then_bb);
970 else
971 {
972 /* Don't issue run-time error if (ptr > ptr + offset). That
973 may happen when computing a POINTER_PLUS_EXPR. */
974 basic_block then2_bb, fallthru2_bb;
975
976 gimple_stmt_iterator gsi2 = gsi_after_labels (then_bb);
977 cond_insert_point = create_cond_insert_point (&gsi2, false, false,
978 true, &then2_bb,
979 &fallthru2_bb);
980 /* Convert the pointer to an integer type. */
981 tree p = make_ssa_name (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE]);
982 g = gimple_build_assign (p, NOP_EXPR, ptr);
983 gimple_set_location (g, loc);
984 gsi_insert_before (&cond_insert_point, g, GSI_NEW_STMT);
985 p = gimple_assign_lhs (g);
986 /* Compute ptr + offset. */
987 g = gimple_build_assign (make_ssa_name (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE]),
988 PLUS_EXPR, p, offset);
989 gimple_set_location (g, loc);
990 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
991 /* Now build the conditional and put it into the IR. */
992 g = gimple_build_cond (LE_EXPR, p, gimple_assign_lhs (g),
993 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
994 gimple_set_location (g, loc);
995 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
996 *gsi = gsi_after_labels (then2_bb);
997 }
998
999 /* Generate __ubsan_handle_type_mismatch call. */
1000 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
1001 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1002 else
1003 {
1004 tree data
1005 = ubsan_create_data ("__ubsan_objsz_data", 1, &loc,
1006 ubsan_type_descriptor (TREE_TYPE (ptr)((contains_struct_check ((ptr), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1006, __FUNCTION__))->typed.type)
,
1007 UBSAN_PRINT_POINTER),
1008 NULL_TREE(tree) nullptr,
1009 build_zero_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char]),
1010 ckind,
1011 NULL_TREE(tree) nullptr);
1012 data = build_fold_addr_expr_loc (loc, data);
1013 enum built_in_function bcode
1014 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_OBJECT_SIZE)
1015 ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1
1016 : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT;
1017 tree p = make_ssa_name (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE]);
1018 g = gimple_build_assign (p, NOP_EXPR, ptr);
1019 gimple_set_location (g, loc);
1020 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1021 g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p);
1022 }
1023 gimple_set_location (g, loc);
1024 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1025
1026 /* Point GSI to next logical statement. */
1027 *gsi = gsi_start_bb (fallthru_bb);
1028
1029 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1030 unlink_stmt_vdef (stmt);
1031 gsi_remove (&gsi_orig, true);
1032 return true;
1033 }
1034
1035 /* Get rid of the UBSAN_OBJECT_SIZE call from the IR. */
1036 unlink_stmt_vdef (stmt);
1037 gsi_remove (gsi, true);
1038 return true;
1039}
1040
1041/* Expand UBSAN_PTR internal call. */
1042
1043bool
1044ubsan_expand_ptr_ifn (gimple_stmt_iterator *gsip)
1045{
1046 gimple_stmt_iterator gsi = *gsip;
1047 gimple *stmt = gsi_stmt (gsi);
1048 location_t loc = gimple_location (stmt);
1049 gcc_assert (gimple_call_num_args (stmt) == 2)((void)(!(gimple_call_num_args (stmt) == 2) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1049, __FUNCTION__), 0 : 0))
;
1050 tree ptr = gimple_call_arg (stmt, 0);
1051 tree off = gimple_call_arg (stmt, 1);
1052
1053 if (integer_zerop (off))
1054 {
1055 gsi_remove (gsip, true);
1056 unlink_stmt_vdef (stmt);
1057 return true;
1058 }
1059
1060 basic_block cur_bb = gsi_bb (gsi);
1061 tree ptrplusoff = make_ssa_name (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE]);
1062 tree ptri = make_ssa_name (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE]);
1063 int pos_neg = get_range_pos_neg (off);
1064
1065 /* Split the original block holding the pointer dereference. */
1066 edge e = split_block (cur_bb, stmt);
1067
1068 /* Get a hold on the 'condition block', the 'then block' and the
1069 'else block'. */
1070 basic_block cond_bb = e->src;
1071 basic_block fallthru_bb = e->dest;
1072 basic_block then_bb = create_empty_bb (cond_bb);
1073 basic_block cond_pos_bb = NULLnullptr, cond_neg_bb = NULLnullptr;
1074 add_bb_to_loop (then_bb, cond_bb->loop_father);
1075 loops_state_set (LOOPS_NEED_FIXUP);
1076
1077 /* Set up the fallthrough basic block. */
1078 e->flags = EDGE_FALSE_VALUE;
1079 if (pos_neg != 3)
1080 {
1081 e->probability = profile_probability::very_likely ();
1082
1083 /* Connect 'then block' with the 'else block'. This is needed
1084 as the ubsan routines we call in the 'then block' are not noreturn.
1085 The 'then block' only has one outcoming edge. */
1086 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1087
1088 /* Make an edge coming from the 'cond block' into the 'then block';
1089 this edge is unlikely taken, so set up the probability
1090 accordingly. */
1091 e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
1092 e->probability = profile_probability::very_unlikely ();
1093 then_bb->count = e->count ();
1094 }
1095 else
1096 {
1097 e->probability = profile_probability::even ();
1098
1099 e = split_block (fallthru_bb, (gimple *) NULLnullptr);
1100 cond_neg_bb = e->src;
1101 fallthru_bb = e->dest;
1102 e->probability = profile_probability::very_likely ();
1103 e->flags = EDGE_FALSE_VALUE;
1104
1105 e = make_edge (cond_neg_bb, then_bb, EDGE_TRUE_VALUE);
1106 e->probability = profile_probability::very_unlikely ();
1107 then_bb->count = e->count ();
1108
1109 cond_pos_bb = create_empty_bb (cond_bb);
1110 add_bb_to_loop (cond_pos_bb, cond_bb->loop_father);
1111
1112 e = make_edge (cond_bb, cond_pos_bb, EDGE_TRUE_VALUE);
1113 e->probability = profile_probability::even ();
1114 cond_pos_bb->count = e->count ();
1115
1116 e = make_edge (cond_pos_bb, then_bb, EDGE_TRUE_VALUE);
1117 e->probability = profile_probability::very_unlikely ();
1118
1119 e = make_edge (cond_pos_bb, fallthru_bb, EDGE_FALSE_VALUE);
1120 e->probability = profile_probability::very_likely ();
1121
1122 make_single_succ_edge (then_bb, fallthru_bb, EDGE_FALLTHRU);
1123 }
1124
1125 gimple *g = gimple_build_assign (ptri, NOP_EXPR, ptr);
1126 gimple_set_location (g, loc);
1127 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1128 g = gimple_build_assign (ptrplusoff, PLUS_EXPR, ptri, off);
1129 gimple_set_location (g, loc);
1130 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1131
1132 /* Update dominance info for the newly created then_bb; note that
1133 fallthru_bb's dominance info has already been updated by
1134 split_block. */
1135 if (dom_info_available_p (CDI_DOMINATORS))
1136 {
1137 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
1138 if (pos_neg == 3)
1139 {
1140 set_immediate_dominator (CDI_DOMINATORS, cond_pos_bb, cond_bb);
1141 set_immediate_dominator (CDI_DOMINATORS, fallthru_bb, cond_bb);
1142 }
1143 }
1144
1145 /* Put the ubsan builtin call into the newly created BB. */
1146 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
1147 g = gimple_build_call (builtin_decl_implicit (BUILT_IN_TRAP), 0);
1148 else
1149 {
1150 enum built_in_function bcode
1151 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_POINTER_OVERFLOW)
1152 ? BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW
1153 : BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT;
1154 tree fn = builtin_decl_implicit (bcode);
1155 tree data
1156 = ubsan_create_data ("__ubsan_ptrovf_data", 1, &loc,
1157 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1158 data = build_fold_addr_expr_loc (loc, data);
1159 g = gimple_build_call (fn, 3, data, ptr, ptrplusoff);
1160 }
1161 gimple_stmt_iterator gsi2 = gsi_start_bb (then_bb);
1162 gimple_set_location (g, loc);
1163 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1164
1165 /* Unlink the UBSAN_PTRs vops before replacing it. */
1166 unlink_stmt_vdef (stmt);
1167
1168 if (TREE_CODE (off)((enum tree_code) (off)->base.code) == INTEGER_CST)
1169 g = gimple_build_cond (wi::neg_p (wi::to_wide (off)) ? LT_EXPR : GE_EXPR,
1170 ptri, fold_build1 (NEGATE_EXPR, sizetype, off)fold_build1_loc (((location_t) 0), NEGATE_EXPR, sizetype_tab[
(int) stk_sizetype], off )
,
1171 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1172 else if (pos_neg != 3)
1173 g = gimple_build_cond (pos_neg == 1 ? LT_EXPR : GT_EXPR,
1174 ptrplusoff, ptri, NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1175 else
1176 {
1177 gsi2 = gsi_start_bb (cond_pos_bb);
1178 g = gimple_build_cond (LT_EXPR, ptrplusoff, ptri, NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1179 gimple_set_location (g, loc);
1180 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1181
1182 gsi2 = gsi_start_bb (cond_neg_bb);
1183 g = gimple_build_cond (GT_EXPR, ptrplusoff, ptri, NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1184 gimple_set_location (g, loc);
1185 gsi_insert_after (&gsi2, g, GSI_NEW_STMT);
1186
1187 gimple_seq seq = NULLnullptr;
1188 tree t = gimple_build (&seq, loc, NOP_EXPR, ssizetypesizetype_tab[(int) stk_ssizetype], off);
1189 t = gimple_build (&seq, loc, GE_EXPR, boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE],
1190 t, ssize_int (0)size_int_kind (0, stk_ssizetype));
1191 gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
1192 g = gimple_build_cond (NE_EXPR, t, boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE],
1193 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1194 }
1195 gimple_set_location (g, loc);
1196 /* Replace the UBSAN_PTR with a GIMPLE_COND stmt. */
1197 gsi_replace (&gsi, g, false);
1198 return false;
1199}
1200
1201
1202/* Cached __ubsan_vptr_type_cache decl. */
1203static GTY(()) tree ubsan_vptr_type_cache_decl;
1204
1205/* Expand UBSAN_VPTR internal call. The type is kept on the ckind
1206 argument which is a constant, because the middle-end treats pointer
1207 conversions as useless and therefore the type of the first argument
1208 could be changed to any other pointer type. */
1209
1210bool
1211ubsan_expand_vptr_ifn (gimple_stmt_iterator *gsip)
1212{
1213 gimple_stmt_iterator gsi = *gsip;
1214 gimple *stmt = gsi_stmt (gsi);
1215 location_t loc = gimple_location (stmt);
1216 gcc_assert (gimple_call_num_args (stmt) == 5)((void)(!(gimple_call_num_args (stmt) == 5) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1216, __FUNCTION__), 0 : 0))
;
1217 tree op = gimple_call_arg (stmt, 0);
1218 tree vptr = gimple_call_arg (stmt, 1);
1219 tree str_hash = gimple_call_arg (stmt, 2);
1220 tree ti_decl_addr = gimple_call_arg (stmt, 3);
1221 tree ckind_tree = gimple_call_arg (stmt, 4);
1222 ubsan_null_ckind ckind = (ubsan_null_ckind) tree_to_uhwi (ckind_tree);
1223 tree type = TREE_TYPE (TREE_TYPE (ckind_tree))((contains_struct_check ((((contains_struct_check ((ckind_tree
), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1223, __FUNCTION__))->typed.type)), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1223, __FUNCTION__))->typed.type)
;
1224 gimple *g;
1225 basic_block fallthru_bb = NULLnullptr;
1226
1227 if (ckind == UBSAN_DOWNCAST_POINTER)
1228 {
1229 /* Guard everything with if (op != NULL) { ... }. */
1230 basic_block then_bb;
1231 gimple_stmt_iterator cond_insert_point
1232 = create_cond_insert_point (gsip, false, false, true,
1233 &then_bb, &fallthru_bb);
1234 g = gimple_build_cond (NE_EXPR, op, build_zero_cst (TREE_TYPE (op)((contains_struct_check ((op), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1234, __FUNCTION__))->typed.type)
),
1235 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1236 gimple_set_location (g, loc);
1237 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1238 *gsip = gsi_after_labels (then_bb);
1239 gsi_remove (&gsi, false);
1240 gsi_insert_before (gsip, stmt, GSI_NEW_STMT);
1241 gsi = *gsip;
1242 }
1243
1244 tree htype = TREE_TYPE (str_hash)((contains_struct_check ((str_hash), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1244, __FUNCTION__))->typed.type)
;
1245 tree cst = wide_int_to_tree (htype,
1246 wi::uhwi (((uint64_t) 0x9ddfea08 << 32)
1247 | 0xeb382d69, 64));
1248 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1249 vptr, str_hash);
1250 gimple_set_location (g, loc);
1251 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1252 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1253 gimple_assign_lhs (g), cst);
1254 gimple_set_location (g, loc);
1255 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1256 tree t1 = gimple_assign_lhs (g);
1257 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1258 t1, build_int_cst (integer_type_nodeinteger_types[itk_int], 47));
1259 gimple_set_location (g, loc);
1260 tree t2 = gimple_assign_lhs (g);
1261 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1262 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1263 vptr, t1);
1264 gimple_set_location (g, loc);
1265 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1266 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1267 t2, gimple_assign_lhs (g));
1268 gimple_set_location (g, loc);
1269 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1270 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1271 gimple_assign_lhs (g), cst);
1272 gimple_set_location (g, loc);
1273 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1274 tree t3 = gimple_assign_lhs (g);
1275 g = gimple_build_assign (make_ssa_name (htype), LSHIFT_EXPR,
1276 t3, build_int_cst (integer_type_nodeinteger_types[itk_int], 47));
1277 gimple_set_location (g, loc);
1278 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1279 g = gimple_build_assign (make_ssa_name (htype), BIT_XOR_EXPR,
1280 t3, gimple_assign_lhs (g));
1281 gimple_set_location (g, loc);
1282 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1283 g = gimple_build_assign (make_ssa_name (htype), MULT_EXPR,
1284 gimple_assign_lhs (g), cst);
1285 gimple_set_location (g, loc);
1286 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1287 if (!useless_type_conversion_p (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE], htype))
1288 {
1289 g = gimple_build_assign (make_ssa_name (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE]),
1290 NOP_EXPR, gimple_assign_lhs (g));
1291 gimple_set_location (g, loc);
1292 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1293 }
1294 tree hash = gimple_assign_lhs (g);
1295
1296 if (ubsan_vptr_type_cache_decl == NULL_TREE(tree) nullptr)
1297 {
1298 tree atype = build_array_type_nelts (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE], 128);
1299 tree array = build_decl (UNKNOWN_LOCATION((location_t) 0), VAR_DECL,
1300 get_identifier ("__ubsan_vptr_type_cache")(__builtin_constant_p ("__ubsan_vptr_type_cache") ? get_identifier_with_length
(("__ubsan_vptr_type_cache"), strlen ("__ubsan_vptr_type_cache"
)) : get_identifier ("__ubsan_vptr_type_cache"))
,
1301 atype);
1302 DECL_ARTIFICIAL (array)((contains_struct_check ((array), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1302, __FUNCTION__))->decl_common.artificial_flag)
= 1;
1303 DECL_IGNORED_P (array)((contains_struct_check ((array), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1303, __FUNCTION__))->decl_common.ignored_flag)
= 1;
1304 TREE_PUBLIC (array)((array)->base.public_flag) = 1;
1305 TREE_STATIC (array)((array)->base.static_flag) = 1;
1306 DECL_EXTERNAL (array)((contains_struct_check ((array), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1306, __FUNCTION__))->decl_common.decl_flag_1)
= 1;
1307 DECL_VISIBILITY (array)((contains_struct_check ((array), (TS_DECL_WITH_VIS), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1307, __FUNCTION__))->decl_with_vis.visibility)
= VISIBILITY_DEFAULT;
1308 DECL_VISIBILITY_SPECIFIED (array)((contains_struct_check ((array), (TS_DECL_WITH_VIS), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1308, __FUNCTION__))->decl_with_vis.visibility_specified
)
= 1;
1309 varpool_node::finalize_decl (array);
1310 ubsan_vptr_type_cache_decl = array;
1311 }
1312
1313 g = gimple_build_assign (make_ssa_name (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE]),
1314 BIT_AND_EXPR, hash,
1315 build_int_cst (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE], 127));
1316 gimple_set_location (g, loc);
1317 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1318
1319 tree c = build4_loc (loc, ARRAY_REF, pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE],
1320 ubsan_vptr_type_cache_decl, gimple_assign_lhs (g),
1321 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1322 g = gimple_build_assign (make_ssa_name (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE]),
1323 ARRAY_REF, c);
1324 gimple_set_location (g, loc);
1325 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1326
1327 basic_block then_bb, fallthru2_bb;
1328 gimple_stmt_iterator cond_insert_point
1329 = create_cond_insert_point (gsip, false, false, true,
1330 &then_bb, &fallthru2_bb);
1331 g = gimple_build_cond (NE_EXPR, gimple_assign_lhs (g), hash,
1332 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1333 gimple_set_location (g, loc);
1334 gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
1335 *gsip = gsi_after_labels (then_bb);
1336 if (fallthru_bb == NULLnullptr)
1337 fallthru_bb = fallthru2_bb;
1338
1339 tree data
1340 = ubsan_create_data ("__ubsan_vptr_data", 1, &loc,
1341 ubsan_type_descriptor (type), NULL_TREE(tree) nullptr, ti_decl_addr,
1342 build_int_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char], ckind),
1343 NULL_TREE(tree) nullptr);
1344 data = build_fold_addr_expr_loc (loc, data);
1345 enum built_in_function bcode
1346 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_VPTR)
1347 ? BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS
1348 : BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT;
1349
1350 g = gimple_build_call (builtin_decl_explicit (bcode), 3, data, op, hash);
1351 gimple_set_location (g, loc);
1352 gsi_insert_before (gsip, g, GSI_SAME_STMT);
1353
1354 /* Point GSI to next logical statement. */
1355 *gsip = gsi_start_bb (fallthru_bb);
1356
1357 /* Get rid of the UBSAN_VPTR call from the IR. */
1358 unlink_stmt_vdef (stmt);
1359 gsi_remove (&gsi, true);
1360 return true;
1361}
1362
1363/* Instrument a memory reference. BASE is the base of MEM, IS_LHS says
1364 whether the pointer is on the left hand side of the assignment. */
1365
1366static void
1367instrument_mem_ref (tree mem, tree base, gimple_stmt_iterator *iter,
1368 bool is_lhs)
1369{
1370 enum ubsan_null_ckind ikind = is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF;
1371 unsigned int align = 0;
1372 if (sanitize_flags_p (SANITIZE_ALIGNMENT))
1373 {
1374 align = min_align_of_type (TREE_TYPE (base)((contains_struct_check ((base), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1374, __FUNCTION__))->typed.type)
);
1375 if (align <= 1)
1376 align = 0;
1377 }
1378 if (align == 0 && !sanitize_flags_p (SANITIZE_NULL))
1379 return;
1380 tree t = TREE_OPERAND (base, 0)(*((const_cast<tree*> (tree_operand_check ((base), (0),
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1380, __FUNCTION__)))))
;
1381 if (!POINTER_TYPE_P (TREE_TYPE (t))(((enum tree_code) (((contains_struct_check ((t), (TS_TYPED),
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1381, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE
|| ((enum tree_code) (((contains_struct_check ((t), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1381, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
)
)
1382 return;
1383 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (base))(((enum tree_code) (((contains_struct_check ((base), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1383, __FUNCTION__))->typed.type))->base.code) == RECORD_TYPE
|| ((enum tree_code) (((contains_struct_check ((base), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1383, __FUNCTION__))->typed.type))->base.code) == UNION_TYPE
|| ((enum tree_code) (((contains_struct_check ((base), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1383, __FUNCTION__))->typed.type))->base.code) == QUAL_UNION_TYPE
)
&& mem != base)
1384 ikind = UBSAN_MEMBER_ACCESS;
1385 tree kind = build_int_cst (build_pointer_type (TREE_TYPE (base)((contains_struct_check ((base), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1385, __FUNCTION__))->typed.type)
), ikind);
1386 tree alignt = build_int_cst (pointer_sized_int_nodeglobal_trees[TI_POINTER_SIZED_TYPE], align);
1387 gcall *g = gimple_build_call_internal (IFN_UBSAN_NULL, 3, t, kind, alignt);
1388 gimple_set_location (g, gimple_location (gsi_stmt (*iter)));
1389 gsi_insert_before (iter, g, GSI_SAME_STMT);
1390}
1391
1392/* Perform the pointer instrumentation. */
1393
1394static void
1395instrument_null (gimple_stmt_iterator gsi, tree t, bool is_lhs)
1396{
1397 /* Handle also e.g. &s->i. */
1398 if (TREE_CODE (t)((enum tree_code) (t)->base.code) == ADDR_EXPR)
1399 t = TREE_OPERAND (t, 0)(*((const_cast<tree*> (tree_operand_check ((t), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1399, __FUNCTION__)))))
;
1400 tree base = get_base_address (t);
1401 if (base != NULL_TREE(tree) nullptr
1402 && TREE_CODE (base)((enum tree_code) (base)->base.code) == MEM_REF
1403 && TREE_CODE (TREE_OPERAND (base, 0))((enum tree_code) ((*((const_cast<tree*> (tree_operand_check
((base), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1403, __FUNCTION__))))))->base.code)
== SSA_NAME)
1404 instrument_mem_ref (t, base, &gsi, is_lhs);
1405}
1406
1407/* Instrument pointer arithmetics PTR p+ OFF. */
1408
1409static void
1410instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree ptr, tree off)
1411{
1412 if (TYPE_PRECISION (sizetype)((tree_class_check ((sizetype_tab[(int) stk_sizetype]), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1412, __FUNCTION__))->type_common.precision)
!= POINTER_SIZE(((global_options.x_ix86_isa_flags & (1UL << 58)) !=
0) ? 32 : ((8) * (((global_options.x_ix86_isa_flags & (1UL
<< 1)) != 0) ? 8 : 4)))
)
1413 return;
1414 gcall *g = gimple_build_call_internal (IFN_UBSAN_PTR, 2, ptr, off);
1415 gimple_set_location (g, gimple_location (gsi_stmt (*gsi)));
1416 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1417}
1418
1419/* Instrument pointer arithmetics if any. */
1420
1421static void
1422maybe_instrument_pointer_overflow (gimple_stmt_iterator *gsi, tree t)
1423{
1424 if (TYPE_PRECISION (sizetype)((tree_class_check ((sizetype_tab[(int) stk_sizetype]), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1424, __FUNCTION__))->type_common.precision)
!= POINTER_SIZE(((global_options.x_ix86_isa_flags & (1UL << 58)) !=
0) ? 32 : ((8) * (((global_options.x_ix86_isa_flags & (1UL
<< 1)) != 0) ? 8 : 4)))
)
1425 return;
1426
1427 /* Handle also e.g. &s->i. */
1428 if (TREE_CODE (t)((enum tree_code) (t)->base.code) == ADDR_EXPR)
1429 t = TREE_OPERAND (t, 0)(*((const_cast<tree*> (tree_operand_check ((t), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1429, __FUNCTION__)))))
;
1430
1431 if (!handled_component_p (t) && TREE_CODE (t)((enum tree_code) (t)->base.code) != MEM_REF)
1432 return;
1433
1434 poly_int64 bitsize, bitpos, bytepos;
1435 tree offset;
1436 machine_mode mode;
1437 int volatilep = 0, reversep, unsignedp = 0;
1438 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
1439 &unsignedp, &reversep, &volatilep);
1440 tree moff = NULL_TREE(tree) nullptr;
1441
1442 bool decl_p = DECL_P (inner)(tree_code_type[(int) (((enum tree_code) (inner)->base.code
))] == tcc_declaration)
;
1443 tree base;
1444 if (decl_p)
1445 {
1446 if (DECL_REGISTER (inner)((contains_struct_check ((inner), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1446, __FUNCTION__))->decl_common.decl_flag_0)
)
1447 return;
1448 base = inner;
1449 /* If BASE is a fixed size automatic variable or
1450 global variable defined in the current TU and bitpos
1451 fits, don't instrument anything. */
1452 poly_int64 base_size;
1453 if (offset == NULL_TREE(tree) nullptr
1454 && maybe_ne (bitpos, 0)
1455 && (VAR_P (base)(((enum tree_code) (base)->base.code) == VAR_DECL)
1456 || TREE_CODE (base)((enum tree_code) (base)->base.code) == PARM_DECL
1457 || TREE_CODE (base)((enum tree_code) (base)->base.code) == RESULT_DECL)
1458 && poly_int_tree_p (DECL_SIZE (base)((contains_struct_check ((base), (TS_DECL_COMMON), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1458, __FUNCTION__))->decl_common.size)
, &base_size)
1459 && known_ge (base_size, bitpos)(!maybe_lt (base_size, bitpos))
1460 && (!is_global_var (base) || decl_binds_to_current_def_p (base)))
1461 return;
1462 }
1463 else if (TREE_CODE (inner)((enum tree_code) (inner)->base.code) == MEM_REF)
1464 {
1465 base = TREE_OPERAND (inner, 0)(*((const_cast<tree*> (tree_operand_check ((inner), (0)
, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1465, __FUNCTION__)))))
;
1466 if (TREE_CODE (base)((enum tree_code) (base)->base.code) == ADDR_EXPR
1467 && DECL_P (TREE_OPERAND (base, 0))(tree_code_type[(int) (((enum tree_code) ((*((const_cast<tree
*> (tree_operand_check ((base), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1467, __FUNCTION__))))))->base.code))] == tcc_declaration
)
1468 && !TREE_ADDRESSABLE (TREE_OPERAND (base, 0))(((*((const_cast<tree*> (tree_operand_check ((base), (0
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1468, __FUNCTION__))))))->base.addressable_flag)
1469 && !is_global_var (TREE_OPERAND (base, 0)(*((const_cast<tree*> (tree_operand_check ((base), (0),
"/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1469, __FUNCTION__)))))
))
1470 return;
1471 moff = TREE_OPERAND (inner, 1)(*((const_cast<tree*> (tree_operand_check ((inner), (1)
, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1471, __FUNCTION__)))))
;
1472 if (integer_zerop (moff))
1473 moff = NULL_TREE(tree) nullptr;
1474 }
1475 else
1476 return;
1477
1478 if (!POINTER_TYPE_P (TREE_TYPE (base))(((enum tree_code) (((contains_struct_check ((base), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1478, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE
|| ((enum tree_code) (((contains_struct_check ((base), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1478, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
)
&& !DECL_P (base)(tree_code_type[(int) (((enum tree_code) (base)->base.code
))] == tcc_declaration)
)
1479 return;
1480 bytepos = bits_to_bytes_round_down (bitpos)force_align_down_and_div (bitpos, (8));
1481 if (offset == NULL_TREE(tree) nullptr && known_eq (bytepos, 0)(!maybe_ne (bytepos, 0)) && moff == NULL_TREE(tree) nullptr)
1482 return;
1483
1484 tree base_addr = base;
1485 if (decl_p)
1486 base_addr = build1 (ADDR_EXPR,
1487 build_pointer_type (TREE_TYPE (base)((contains_struct_check ((base), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1487, __FUNCTION__))->typed.type)
), base);
1488 t = offset;
1489 if (maybe_ne (bytepos, 0))
1490 {
1491 if (t)
1492 t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,fold_build2_loc (((location_t) 0), PLUS_EXPR, ((contains_struct_check
((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1492, __FUNCTION__))->typed.type), t, build_int_cst (((contains_struct_check
((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1493, __FUNCTION__))->typed.type), bytepos) )
1493 build_int_cst (TREE_TYPE (t), bytepos))fold_build2_loc (((location_t) 0), PLUS_EXPR, ((contains_struct_check
((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1492, __FUNCTION__))->typed.type), t, build_int_cst (((contains_struct_check
((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1493, __FUNCTION__))->typed.type), bytepos) )
;
1494 else
1495 t = size_int (bytepos)size_int_kind (bytepos, stk_sizetype);
1496 }
1497 if (moff)
1498 {
1499 if (t)
1500 t = fold_build2 (PLUS_EXPR, TREE_TYPE (t), t,fold_build2_loc (((location_t) 0), PLUS_EXPR, ((contains_struct_check
((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1500, __FUNCTION__))->typed.type), t, fold_convert_loc (
((location_t) 0), ((contains_struct_check ((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1501, __FUNCTION__))->typed.type), moff) )
1501 fold_convert (TREE_TYPE (t), moff))fold_build2_loc (((location_t) 0), PLUS_EXPR, ((contains_struct_check
((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1500, __FUNCTION__))->typed.type), t, fold_convert_loc (
((location_t) 0), ((contains_struct_check ((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1501, __FUNCTION__))->typed.type), moff) )
;
1502 else
1503 t = fold_convert (sizetype, moff)fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_sizetype
], moff)
;
1504 }
1505 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE(tree) nullptr, true,
1506 GSI_SAME_STMT);
1507 base_addr = force_gimple_operand_gsi (gsi, base_addr, true, NULL_TREE(tree) nullptr, true,
1508 GSI_SAME_STMT);
1509 instrument_pointer_overflow (gsi, base_addr, t);
1510}
1511
1512/* Build an ubsan builtin call for the signed-integer-overflow
1513 sanitization. CODE says what kind of builtin are we building,
1514 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1515 are operands of the binary operation. */
1516
1517tree
1518ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1519 tree op0, tree op1, tree *datap)
1520{
1521 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
1522 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1523
1524 tree data;
1525 if (datap && *datap)
1526 data = *datap;
1527 else
1528 data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1529 ubsan_type_descriptor (lhstype), NULL_TREE(tree) nullptr,
1530 NULL_TREE(tree) nullptr);
1531 if (datap)
1532 *datap = data;
1533 enum built_in_function fn_code;
1534
1535 switch (code)
1536 {
1537 case PLUS_EXPR:
1538 fn_code = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1539 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1540 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1541 break;
1542 case MINUS_EXPR:
1543 fn_code = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1544 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1545 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1546 break;
1547 case MULT_EXPR:
1548 fn_code = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1549 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1550 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1551 break;
1552 case NEGATE_EXPR:
1553 fn_code = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1554 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1555 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1556 break;
1557 default:
1558 gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1558, __FUNCTION__))
;
1559 }
1560 tree fn = builtin_decl_explicit (fn_code);
1561 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1562 build_fold_addr_expr_loc (loc, data),
1563 ubsan_encode_value (op0, UBSAN_ENCODE_VALUE_RTL),
1564 op1
1565 ? ubsan_encode_value (op1,
1566 UBSAN_ENCODE_VALUE_RTL)
1567 : NULL_TREE(tree) nullptr);
1568}
1569
1570/* Perform the signed integer instrumentation. GSI is the iterator
1571 pointing at statement we are trying to instrument. */
1572
1573static void
1574instrument_si_overflow (gimple_stmt_iterator gsi)
1575{
1576 gimple *stmt = gsi_stmt (gsi);
1577 tree_code code = gimple_assign_rhs_code (stmt);
1578 tree lhs = gimple_assign_lhs (stmt);
1579 tree lhstype = TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1579, __FUNCTION__))->typed.type)
;
1580 tree lhsinner = VECTOR_TYPE_P (lhstype)(((enum tree_code) (lhstype)->base.code) == VECTOR_TYPE) ? TREE_TYPE (lhstype)((contains_struct_check ((lhstype), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1580, __FUNCTION__))->typed.type)
: lhstype;
1581 tree a, b;
1582 gimple *g;
1583
1584 /* If this is not a signed operation, don't instrument anything here.
1585 Also punt on bit-fields. */
1586 if (!INTEGRAL_TYPE_P (lhsinner)(((enum tree_code) (lhsinner)->base.code) == ENUMERAL_TYPE
|| ((enum tree_code) (lhsinner)->base.code) == BOOLEAN_TYPE
|| ((enum tree_code) (lhsinner)->base.code) == INTEGER_TYPE
)
1587 || TYPE_OVERFLOW_WRAPS (lhsinner)((((enum tree_code) (lhsinner)->base.code) == POINTER_TYPE
|| ((enum tree_code) (lhsinner)->base.code) == REFERENCE_TYPE
) ? global_options.x_flag_wrapv_pointer : ((any_integral_type_check
((lhsinner), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1587, __FUNCTION__))->base.u.bits.unsigned_flag || global_options
.x_flag_wrapv))
1588 || maybe_ne (GET_MODE_BITSIZE (TYPE_MODE (lhsinner)((((enum tree_code) ((tree_class_check ((lhsinner), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1588, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(lhsinner) : (lhsinner)->type_common.mode)
),
1589 TYPE_PRECISION (lhsinner)((tree_class_check ((lhsinner), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1589, __FUNCTION__))->type_common.precision)
))
1590 return;
1591
1592 switch (code)
1593 {
1594 case MINUS_EXPR:
1595 case PLUS_EXPR:
1596 case MULT_EXPR:
1597 /* Transform
1598 i = u {+,-,*} 5;
1599 into
1600 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1601 a = gimple_assign_rhs1 (stmt);
1602 b = gimple_assign_rhs2 (stmt);
1603 g = gimple_build_call_internal (code == PLUS_EXPR
1604 ? IFN_UBSAN_CHECK_ADD
1605 : code == MINUS_EXPR
1606 ? IFN_UBSAN_CHECK_SUB
1607 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1608 gimple_call_set_lhs (g, lhs);
1609 gsi_replace (&gsi, g, true);
1610 break;
1611 case NEGATE_EXPR:
1612 /* Represent i = -u;
1613 as
1614 i = UBSAN_CHECK_SUB (0, u); */
1615 a = build_zero_cst (lhstype);
1616 b = gimple_assign_rhs1 (stmt);
1617 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1618 gimple_call_set_lhs (g, lhs);
1619 gsi_replace (&gsi, g, true);
1620 break;
1621 case ABS_EXPR:
1622 /* Transform i = ABS_EXPR<u>;
1623 into
1624 _N = UBSAN_CHECK_SUB (0, u);
1625 i = ABS_EXPR<_N>; */
1626 a = build_zero_cst (lhstype);
1627 b = gimple_assign_rhs1 (stmt);
1628 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1629 a = make_ssa_name (lhstype);
1630 gimple_call_set_lhs (g, a);
1631 gimple_set_location (g, gimple_location (stmt));
1632 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1633 gimple_assign_set_rhs1 (stmt, a);
1634 update_stmt (stmt);
1635 break;
1636 default:
1637 break;
1638 }
1639}
1640
1641/* Instrument loads from (non-bitfield) bool and C++ enum values
1642 to check if the memory value is outside of the range of the valid
1643 type values. */
1644
1645static void
1646instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1647{
1648 gimple *stmt = gsi_stmt (*gsi);
1649 tree rhs = gimple_assign_rhs1 (stmt);
1650 tree type = TREE_TYPE (rhs)((contains_struct_check ((rhs), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1650, __FUNCTION__))->typed.type)
;
1651 tree minv = NULL_TREE(tree) nullptr, maxv = NULL_TREE(tree) nullptr;
1652
1653 if (TREE_CODE (type)((enum tree_code) (type)->base.code) == BOOLEAN_TYPE
1654 && sanitize_flags_p (SANITIZE_BOOL))
1655 {
1656 minv = boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE];
1657 maxv = boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE];
1658 }
1659 else if (TREE_CODE (type)((enum tree_code) (type)->base.code) == ENUMERAL_TYPE
1660 && sanitize_flags_p (SANITIZE_ENUM)
1661 && TREE_TYPE (type)((contains_struct_check ((type), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1661, __FUNCTION__))->typed.type)
!= NULL_TREE(tree) nullptr
1662 && TREE_CODE (TREE_TYPE (type))((enum tree_code) (((contains_struct_check ((type), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1662, __FUNCTION__))->typed.type))->base.code)
== INTEGER_TYPE
1663 && (TYPE_PRECISION (TREE_TYPE (type))((tree_class_check ((((contains_struct_check ((type), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1663, __FUNCTION__))->typed.type)), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1663, __FUNCTION__))->type_common.precision)
1664 < GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (type)(as_a <scalar_int_mode> ((tree_class_check ((type), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1664, __FUNCTION__))->type_common.mode))
)))
1665 {
1666 minv = TYPE_MIN_VALUE (TREE_TYPE (type))((tree_check5 ((((contains_struct_check ((type), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1666, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1666, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE
), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.minval
)
;
1667 maxv = TYPE_MAX_VALUE (TREE_TYPE (type))((tree_check5 ((((contains_struct_check ((type), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1667, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1667, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE
), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval
)
;
1668 }
1669 else
1670 return;
1671
1672 int modebitsize = GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (type)(as_a <scalar_int_mode> ((tree_class_check ((type), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1672, __FUNCTION__))->type_common.mode))
);
1673 poly_int64 bitsize, bitpos;
1674 tree offset;
1675 machine_mode mode;
1676 int volatilep = 0, reversep, unsignedp = 0;
1677 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1678 &unsignedp, &reversep, &volatilep);
1679 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1680
1681 if ((VAR_P (base)(((enum tree_code) (base)->base.code) == VAR_DECL) && DECL_HARD_REGISTER (base)((tree_check ((base), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1681, __FUNCTION__, (VAR_DECL)))->decl_with_vis.hard_register
)
)
1682 || !multiple_p (bitpos, modebitsize)
1683 || maybe_ne (bitsize, modebitsize)
1684 || GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE (utype)(as_a <scalar_int_mode> ((tree_class_check ((utype), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1684, __FUNCTION__))->type_common.mode))
) != modebitsize
1685 || TREE_CODE (gimple_assign_lhs (stmt))((enum tree_code) (gimple_assign_lhs (stmt))->base.code) != SSA_NAME)
1686 return;
1687
1688 bool ends_bb = stmt_ends_bb_p (stmt);
1689 location_t loc = gimple_location (stmt);
1690 tree lhs = gimple_assign_lhs (stmt);
1691 tree ptype = build_pointer_type (TREE_TYPE (rhs)((contains_struct_check ((rhs), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1691, __FUNCTION__))->typed.type)
);
1692 tree atype = reference_alias_ptr_type (rhs);
1693 gimple *g = gimple_build_assign (make_ssa_name (ptype),
1694 build_fold_addr_expr (rhs)build_fold_addr_expr_loc (((location_t) 0), (rhs)));
1695 gimple_set_location (g, loc);
1696 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1697 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1698 build_int_cst (atype, 0));
1699 tree urhs = make_ssa_name (utype);
1700 if (ends_bb)
1701 {
1702 gimple_assign_set_lhs (stmt, urhs);
1703 g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1704 gimple_set_location (g, loc);
1705 edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1706 gsi_insert_on_edge_immediate (e, g);
1707 gimple_assign_set_rhs_from_tree (gsi, mem);
1708 update_stmt (stmt);
1709 *gsi = gsi_for_stmt (g);
1710 g = stmt;
1711 }
1712 else
1713 {
1714 g = gimple_build_assign (urhs, mem);
1715 gimple_set_location (g, loc);
1716 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1717 }
1718 minv = fold_convert (utype, minv)fold_convert_loc (((location_t) 0), utype, minv);
1719 maxv = fold_convert (utype, maxv)fold_convert_loc (((location_t) 0), utype, maxv);
1720 if (!integer_zerop (minv))
1721 {
1722 g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1723 gimple_set_location (g, loc);
1724 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1725 }
1726
1727 gimple_stmt_iterator gsi2 = *gsi;
1728 basic_block then_bb, fallthru_bb;
1729 *gsi = create_cond_insert_point (gsi, true, false, true,
1730 &then_bb, &fallthru_bb);
1731 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1732 int_const_binop (MINUS_EXPR, maxv, minv),
1733 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1734 gimple_set_location (g, loc);
1735 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1736
1737 if (!ends_bb)
1738 {
1739 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1740 update_stmt (stmt);
1741 }
1742
1743 gsi2 = gsi_after_labels (then_bb);
1744 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
1745 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1746 else
1747 {
1748 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1749 ubsan_type_descriptor (type), NULL_TREE(tree) nullptr,
1750 NULL_TREE(tree) nullptr);
1751 data = build_fold_addr_expr_loc (loc, data);
1752 enum built_in_function bcode
1753 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & (TREE_CODE (type)((enum tree_code) (type)->base.code) == BOOLEAN_TYPE
1754 ? SANITIZE_BOOL : SANITIZE_ENUM))
1755 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1756 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1757 tree fn = builtin_decl_explicit (bcode);
1758
1759 tree val = ubsan_encode_value (urhs, UBSAN_ENCODE_VALUE_GIMPLE);
1760 val = force_gimple_operand_gsi (&gsi2, val, true, NULL_TREE(tree) nullptr, true,
1761 GSI_SAME_STMT);
1762 g = gimple_build_call (fn, 2, data, val);
1763 }
1764 gimple_set_location (g, loc);
1765 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1766 ubsan_create_edge (g);
1767 *gsi = gsi_for_stmt (stmt);
1768}
1769
1770/* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1771 new style handlers. Libubsan uses heuristics to destinguish between old and
1772 new styles and relies on these properties for filename:
1773
1774 a) Location's filename must not be NULL.
1775 b) Location's filename must not be equal to "".
1776 c) Location's filename must not be equal to "\1".
1777 d) First two bytes of filename must not contain '\xff' symbol. */
1778
1779static bool
1780ubsan_use_new_style_p (location_t loc)
1781{
1782 if (loc == UNKNOWN_LOCATION((location_t) 0))
1783 return false;
1784
1785 expanded_location xloc = expand_location (loc);
1786 if (xloc.file == NULLnullptr || strncmp (xloc.file, "\1", 2) == 0
1787 || xloc.file[0] == '\0' || xloc.file[0] == '\xff'
1788 || xloc.file[1] == '\xff')
1789 return false;
1790
1791 return true;
1792}
1793
1794/* Instrument float point-to-integer conversion. TYPE is an integer type of
1795 destination, EXPR is floating-point expression. */
1796
1797tree
1798ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1799{
1800 tree expr_type = TREE_TYPE (expr)((contains_struct_check ((expr), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1800, __FUNCTION__))->typed.type)
;
1801 tree t, tt, fn, min, max;
1802 machine_mode mode = TYPE_MODE (expr_type)((((enum tree_code) ((tree_class_check ((expr_type), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1802, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(expr_type) : (expr_type)->type_common.mode)
;
1803 int prec = TYPE_PRECISION (type)((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1803, __FUNCTION__))->type_common.precision)
;
1804 bool uns_p = TYPE_UNSIGNED (type)((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1804, __FUNCTION__))->base.u.bits.unsigned_flag)
;
1805 if (loc == UNKNOWN_LOCATION((location_t) 0))
1806 loc = input_location;
1807
1808 /* Float to integer conversion first truncates toward zero, so
1809 even signed char c = 127.875f; is not problematic.
1810 Therefore, we should complain only if EXPR is unordered or smaller
1811 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1812 TYPE_MAX_VALUE + 1.0. */
1813 if (REAL_MODE_FORMAT (mode)(real_format_for_mode[(((enum mode_class) mode_class[mode]) ==
MODE_DECIMAL_FLOAT) ? (((mode) - MIN_MODE_DECIMAL_FLOAT) + (
MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) : ((enum mode_class) mode_class
[mode]) == MODE_FLOAT ? ((mode) - MIN_MODE_FLOAT) : ((fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1813, __FUNCTION__)), 0)])
->b == 2)
1814 {
1815 /* For maximum, TYPE_MAX_VALUE might not be representable
1816 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1817 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1818 either representable or infinity. */
1819 REAL_VALUE_TYPEstruct real_value maxval = dconst1;
1820 SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p)((&maxval)->uexp = ((unsigned int)(((int)((&maxval
)->uexp ^ (unsigned int)(1 << ((32 - 6) - 1))) - (1 <<
((32 - 6) - 1))) + prec - !uns_p) & (unsigned int)((1 <<
(32 - 6)) - 1)))
;
1821 real_convert (&maxval, mode, &maxval);
1822 max = build_real (expr_type, maxval);
1823
1824 /* For unsigned, assume -1.0 is always representable. */
1825 if (uns_p)
1826 min = build_minus_one_cst (expr_type);
1827 else
1828 {
1829 /* TYPE_MIN_VALUE is generally representable (or -inf),
1830 but TYPE_MIN_VALUE - 1.0 might not be. */
1831 REAL_VALUE_TYPEstruct real_value minval = dconstm1, minval2;
1832 SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1)((&minval)->uexp = ((unsigned int)(((int)((&minval
)->uexp ^ (unsigned int)(1 << ((32 - 6) - 1))) - (1 <<
((32 - 6) - 1))) + prec - 1) & (unsigned int)((1 <<
(32 - 6)) - 1)))
;
1833 real_convert (&minval, mode, &minval);
1834 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1835 real_convert (&minval2, mode, &minval2);
1836 if (real_compare (EQ_EXPR, &minval, &minval2)
1837 && !real_isinf (&minval))
1838 {
1839 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1840 rounds to TYPE_MIN_VALUE, we need to subtract
1841 more. As REAL_MODE_FORMAT (mode)->p is the number
1842 of base digits, we want to subtract a number that
1843 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1844 times smaller than minval. */
1845 minval2 = dconst1;
1846 gcc_assert (prec > REAL_MODE_FORMAT (mode)->p)((void)(!(prec > (real_format_for_mode[(((enum mode_class)
mode_class[mode]) == MODE_DECIMAL_FLOAT) ? (((mode) - MIN_MODE_DECIMAL_FLOAT
) + (MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) : ((enum mode_class
) mode_class[mode]) == MODE_FLOAT ? ((mode) - MIN_MODE_FLOAT)
: ((fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1846, __FUNCTION__)), 0)])->p) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1846, __FUNCTION__), 0 : 0))
;
1847 SET_REAL_EXP (&minval2,((&minval2)->uexp = ((unsigned int)(((int)((&minval2
)->uexp ^ (unsigned int)(1 << ((32 - 6) - 1))) - (1 <<
((32 - 6) - 1))) + prec - 1 - (real_format_for_mode[(((enum mode_class
) mode_class[mode]) == MODE_DECIMAL_FLOAT) ? (((mode) - MIN_MODE_DECIMAL_FLOAT
) + (MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) : ((enum mode_class
) mode_class[mode]) == MODE_FLOAT ? ((mode) - MIN_MODE_FLOAT)
: ((fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1849, __FUNCTION__)), 0)])->p + 1) & (unsigned int)(
(1 << (32 - 6)) - 1)))
1848 REAL_EXP (&minval2) + prec - 1((&minval2)->uexp = ((unsigned int)(((int)((&minval2
)->uexp ^ (unsigned int)(1 << ((32 - 6) - 1))) - (1 <<
((32 - 6) - 1))) + prec - 1 - (real_format_for_mode[(((enum mode_class
) mode_class[mode]) == MODE_DECIMAL_FLOAT) ? (((mode) - MIN_MODE_DECIMAL_FLOAT
) + (MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) : ((enum mode_class
) mode_class[mode]) == MODE_FLOAT ? ((mode) - MIN_MODE_FLOAT)
: ((fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1849, __FUNCTION__)), 0)])->p + 1) & (unsigned int)(
(1 << (32 - 6)) - 1)))
1849 - REAL_MODE_FORMAT (mode)->p + 1)((&minval2)->uexp = ((unsigned int)(((int)((&minval2
)->uexp ^ (unsigned int)(1 << ((32 - 6) - 1))) - (1 <<
((32 - 6) - 1))) + prec - 1 - (real_format_for_mode[(((enum mode_class
) mode_class[mode]) == MODE_DECIMAL_FLOAT) ? (((mode) - MIN_MODE_DECIMAL_FLOAT
) + (MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) : ((enum mode_class
) mode_class[mode]) == MODE_FLOAT ? ((mode) - MIN_MODE_FLOAT)
: ((fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1849, __FUNCTION__)), 0)])->p + 1) & (unsigned int)(
(1 << (32 - 6)) - 1)))
;
1850 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1851 real_convert (&minval2, mode, &minval2);
1852 }
1853 min = build_real (expr_type, minval2);
1854 }
1855 }
1856 else if (REAL_MODE_FORMAT (mode)(real_format_for_mode[(((enum mode_class) mode_class[mode]) ==
MODE_DECIMAL_FLOAT) ? (((mode) - MIN_MODE_DECIMAL_FLOAT) + (
MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) : ((enum mode_class) mode_class
[mode]) == MODE_FLOAT ? ((mode) - MIN_MODE_FLOAT) : ((fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1856, __FUNCTION__)), 0)])
->b == 10)
1857 {
1858 /* For _Decimal128 up to 34 decimal digits, - sign,
1859 dot, e, exponent. */
1860 char buf[64];
1861 mpfr_t m;
1862 int p = REAL_MODE_FORMAT (mode)(real_format_for_mode[(((enum mode_class) mode_class[mode]) ==
MODE_DECIMAL_FLOAT) ? (((mode) - MIN_MODE_DECIMAL_FLOAT) + (
MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) : ((enum mode_class) mode_class
[mode]) == MODE_FLOAT ? ((mode) - MIN_MODE_FLOAT) : ((fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1862, __FUNCTION__)), 0)])
->p;
1863 REAL_VALUE_TYPEstruct real_value maxval, minval;
1864
1865 /* Use mpfr_snprintf rounding to compute the smallest
1866 representable decimal number greater or equal than
1867 1 << (prec - !uns_p). */
1868 mpfr_init2 (m, prec + 2);
1869 mpfr_set_ui_2exp (m, 1, prec - !uns_p, MPFR_RNDN);
1870 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1871 decimal_real_from_string (&maxval, buf);
1872 max = build_real (expr_type, maxval);
1873
1874 /* For unsigned, assume -1.0 is always representable. */
1875 if (uns_p)
1876 min = build_minus_one_cst (expr_type);
1877 else
1878 {
1879 /* Use mpfr_snprintf rounding to compute the largest
1880 representable decimal number less or equal than
1881 (-1 << (prec - 1)) - 1. */
1882 mpfr_set_si_2exp (m, -1, prec - 1, MPFR_RNDN);
1883 mpfr_sub_ui (m, m, 1, MPFR_RNDN);
1884 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1885 decimal_real_from_string (&minval, buf);
1886 min = build_real (expr_type, minval);
1887 }
1888 mpfr_clear (m);
1889 }
1890 else
1891 return NULL_TREE(tree) nullptr;
1892
1893 t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min)fold_build2_loc (((location_t) 0), UNLE_EXPR, global_trees[TI_BOOLEAN_TYPE
], expr, min )
;
1894 tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max)fold_build2_loc (((location_t) 0), UNGE_EXPR, global_trees[TI_BOOLEAN_TYPE
], expr, max )
;
1895 t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt)fold_build2_loc (((location_t) 0), TRUTH_OR_EXPR, global_trees
[TI_BOOLEAN_TYPE], t, tt )
;
1896 if (integer_zerop (t))
1897 return NULL_TREE(tree) nullptr;
1898
1899 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
1900 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1901 else
1902 {
1903 location_t *loc_ptr = NULLnullptr;
1904 unsigned num_locations = 0;
1905 /* Figure out if we can propagate location to ubsan_data and use new
1906 style handlers in libubsan. */
1907 if (ubsan_use_new_style_p (loc))
1908 {
1909 loc_ptr = &loc;
1910 num_locations = 1;
1911 }
1912 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1913 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data",
1914 num_locations, loc_ptr,
1915 ubsan_type_descriptor (expr_type),
1916 ubsan_type_descriptor (type), NULL_TREE(tree) nullptr,
1917 NULL_TREE(tree) nullptr);
1918 enum built_in_function bcode
1919 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1920 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1921 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1922 fn = builtin_decl_explicit (bcode);
1923 fn = build_call_expr_loc (loc, fn, 2,
1924 build_fold_addr_expr_loc (loc, data),
1925 ubsan_encode_value (expr));
1926 }
1927
1928 return fold_build3 (COND_EXPR, void_type_node, t, fn, integer_zero_node)fold_build3_loc (((location_t) 0), COND_EXPR, global_trees[TI_VOID_TYPE
], t, fn, global_trees[TI_INTEGER_ZERO] )
;
1929}
1930
1931/* Instrument values passed to function arguments with nonnull attribute. */
1932
1933static void
1934instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1935{
1936 gimple *stmt = gsi_stmt (*gsi);
1937 location_t loc[2];
1938 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1939 while for nonnull sanitization it is clear. */
1940 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checksglobal_options.x_flag_delete_null_pointer_checks;
1941 flag_delete_null_pointer_checksglobal_options.x_flag_delete_null_pointer_checks = 1;
1942 loc[0] = gimple_location (stmt);
1943 loc[1] = UNKNOWN_LOCATION((location_t) 0);
1944 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1945 {
1946 tree arg = gimple_call_arg (stmt, i);
1947 if (POINTER_TYPE_P (TREE_TYPE (arg))(((enum tree_code) (((contains_struct_check ((arg), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1947, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE
|| ((enum tree_code) (((contains_struct_check ((arg), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1947, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
)
1948 && infer_nonnull_range_by_attribute (stmt, arg))
1949 {
1950 gimple *g;
1951 if (!is_gimple_val (arg))
1952 {
1953 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)((contains_struct_check ((arg), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1953, __FUNCTION__))->typed.type)
), arg);
1954 gimple_set_location (g, loc[0]);
1955 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1956 arg = gimple_assign_lhs (g);
1957 }
1958
1959 basic_block then_bb, fallthru_bb;
1960 *gsi = create_cond_insert_point (gsi, true, false, true,
1961 &then_bb, &fallthru_bb);
1962 g = gimple_build_cond (EQ_EXPR, arg,
1963 build_zero_cst (TREE_TYPE (arg)((contains_struct_check ((arg), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1963, __FUNCTION__))->typed.type)
),
1964 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1965 gimple_set_location (g, loc[0]);
1966 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1967
1968 *gsi = gsi_after_labels (then_bb);
1969 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
1970 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1971 else
1972 {
1973 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1974 2, loc, NULL_TREE(tree) nullptr,
1975 build_int_cst (integer_type_nodeinteger_types[itk_int],
1976 i + 1),
1977 NULL_TREE(tree) nullptr);
1978 data = build_fold_addr_expr_loc (loc[0], data);
1979 enum built_in_function bcode
1980 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1981 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1982 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1983 tree fn = builtin_decl_explicit (bcode);
1984
1985 g = gimple_build_call (fn, 1, data);
1986 }
1987 gimple_set_location (g, loc[0]);
1988 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1989 ubsan_create_edge (g);
1990 }
1991 *gsi = gsi_for_stmt (stmt);
1992 }
1993 flag_delete_null_pointer_checksglobal_options.x_flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
1994}
1995
1996/* Instrument returns in functions with returns_nonnull attribute. */
1997
1998static void
1999instrument_nonnull_return (gimple_stmt_iterator *gsi)
2000{
2001 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
2002 location_t loc[2];
2003 tree arg = gimple_return_retval (stmt);
2004 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
2005 while for nonnull return sanitization it is clear. */
2006 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checksglobal_options.x_flag_delete_null_pointer_checks;
2007 flag_delete_null_pointer_checksglobal_options.x_flag_delete_null_pointer_checks = 1;
2008 loc[0] = gimple_location (stmt);
2009 loc[1] = UNKNOWN_LOCATION((location_t) 0);
2010 if (arg
2011 && POINTER_TYPE_P (TREE_TYPE (arg))(((enum tree_code) (((contains_struct_check ((arg), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2011, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE
|| ((enum tree_code) (((contains_struct_check ((arg), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2011, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
)
2012 && is_gimple_val (arg)
2013 && infer_nonnull_range_by_attribute (stmt, arg))
2014 {
2015 basic_block then_bb, fallthru_bb;
2016 *gsi = create_cond_insert_point (gsi, true, false, true,
2017 &then_bb, &fallthru_bb);
2018 gimple *g = gimple_build_cond (EQ_EXPR, arg,
2019 build_zero_cst (TREE_TYPE (arg)((contains_struct_check ((arg), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2019, __FUNCTION__))->typed.type)
),
2020 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
2021 gimple_set_location (g, loc[0]);
2022 gsi_insert_after (gsi, g, GSI_NEW_STMT);
2023
2024 *gsi = gsi_after_labels (then_bb);
2025 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
2026 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
2027 else
2028 {
2029 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
2030 1, &loc[1], NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
2031 data = build_fold_addr_expr_loc (loc[0], data);
2032 tree data2 = ubsan_create_data ("__ubsan_nonnull_return_data",
2033 1, &loc[0], NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
2034 data2 = build_fold_addr_expr_loc (loc[0], data2);
2035 enum built_in_function bcode
2036 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
2037 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1
2038 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1_ABORT;
2039 tree fn = builtin_decl_explicit (bcode);
2040
2041 g = gimple_build_call (fn, 2, data, data2);
2042 }
2043 gimple_set_location (g, loc[0]);
2044 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2045 ubsan_create_edge (g);
2046 *gsi = gsi_for_stmt (stmt);
2047 }
2048 flag_delete_null_pointer_checksglobal_options.x_flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
2049}
2050
2051/* Instrument memory references. Here we check whether the pointer
2052 points to an out-of-bounds location. */
2053
2054static void
2055instrument_object_size (gimple_stmt_iterator *gsi, tree t, bool is_lhs)
2056{
2057 gimple *stmt = gsi_stmt (*gsi);
2058 location_t loc = gimple_location (stmt);
2059 tree type;
2060 tree index = NULL_TREE(tree) nullptr;
2061 HOST_WIDE_INTlong size_in_bytes;
2062
2063 type = TREE_TYPE (t)((contains_struct_check ((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2063, __FUNCTION__))->typed.type)
;
2064 if (VOID_TYPE_P (type)(((enum tree_code) (type)->base.code) == VOID_TYPE))
2065 return;
2066
2067 switch (TREE_CODE (t)((enum tree_code) (t)->base.code))
2068 {
2069 case COMPONENT_REF:
2070 if (TREE_CODE (t)((enum tree_code) (t)->base.code) == COMPONENT_REF
2071 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1))((tree_check (((*((const_cast<tree*> (tree_operand_check
((t), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2071, __FUNCTION__)))))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2071, __FUNCTION__, (FIELD_DECL)))->field_decl.qualifier
)
!= NULL_TREE(tree) nullptr)
2072 {
2073 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1))((tree_check (((*((const_cast<tree*> (tree_operand_check
((t), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2073, __FUNCTION__)))))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2073, __FUNCTION__, (FIELD_DECL)))->field_decl.qualifier
)
;
2074 t = build3 (COMPONENT_REF, TREE_TYPE (repr)((contains_struct_check ((repr), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2074, __FUNCTION__))->typed.type)
, TREE_OPERAND (t, 0)(*((const_cast<tree*> (tree_operand_check ((t), (0), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2074, __FUNCTION__)))))
,
2075 repr, TREE_OPERAND (t, 2)(*((const_cast<tree*> (tree_operand_check ((t), (2), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2075, __FUNCTION__)))))
);
2076 }
2077 break;
2078 case ARRAY_REF:
2079 index = TREE_OPERAND (t, 1)(*((const_cast<tree*> (tree_operand_check ((t), (1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2079, __FUNCTION__)))))
;
2080 break;
2081 case INDIRECT_REF:
2082 case MEM_REF:
2083 case VAR_DECL:
2084 case PARM_DECL:
2085 case RESULT_DECL:
2086 break;
2087 default:
2088 return;
2089 }
2090
2091 size_in_bytes = int_size_in_bytes (type);
2092 if (size_in_bytes <= 0)
2093 return;
2094
2095 poly_int64 bitsize, bitpos;
2096 tree offset;
2097 machine_mode mode;
2098 int volatilep = 0, reversep, unsignedp = 0;
2099 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
2100 &unsignedp, &reversep, &volatilep);
2101
2102 if (!multiple_p (bitpos, BITS_PER_UNIT(8))
2103 || maybe_ne (bitsize, size_in_bytes * BITS_PER_UNIT(8)))
2104 return;
2105
2106 bool decl_p = DECL_P (inner)(tree_code_type[(int) (((enum tree_code) (inner)->base.code
))] == tcc_declaration)
;
2107 tree base;
2108 if (decl_p)
2109 {
2110 if (DECL_REGISTER (inner)((contains_struct_check ((inner), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2110, __FUNCTION__))->decl_common.decl_flag_0)
)
2111 return;
2112 base = inner;
2113 }
2114 else if (TREE_CODE (inner)((enum tree_code) (inner)->base.code) == MEM_REF)
2115 base = TREE_OPERAND (inner, 0)(*((const_cast<tree*> (tree_operand_check ((inner), (0)
, "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2115, __FUNCTION__)))))
;
2116 else
2117 return;
2118 tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)((contains_struct_check ((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2118, __FUNCTION__))->typed.type)
), t);
2119
2120 while (TREE_CODE (base)((enum tree_code) (base)->base.code) == SSA_NAME)
2121 {
2122 gimple *def_stmt = SSA_NAME_DEF_STMT (base)(tree_check ((base), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2122, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
2123 if (gimple_assign_ssa_name_copy_p (def_stmt)
2124 || (gimple_assign_cast_p (def_stmt)
2125 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def_stmt)))(((enum tree_code) (((contains_struct_check ((gimple_assign_rhs1
(def_stmt)), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2125, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE
|| ((enum tree_code) (((contains_struct_check ((gimple_assign_rhs1
(def_stmt)), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2125, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
)
)
2126 || (is_gimple_assign (def_stmt)
2127 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
2128 {
2129 tree rhs1 = gimple_assign_rhs1 (def_stmt);
2130 if (TREE_CODE (rhs1)((enum tree_code) (rhs1)->base.code) == SSA_NAME
2131 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1)(tree_check ((rhs1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2131, __FUNCTION__, (SSA_NAME)))->base.asm_written_flag
)
2132 break;
2133 else
2134 base = rhs1;
2135 }
2136 else
2137 break;
2138 }
2139
2140 if (!POINTER_TYPE_P (TREE_TYPE (base))(((enum tree_code) (((contains_struct_check ((base), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2140, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE
|| ((enum tree_code) (((contains_struct_check ((base), (TS_TYPED
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2140, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
)
&& !DECL_P (base)(tree_code_type[(int) (((enum tree_code) (base)->base.code
))] == tcc_declaration)
)
2141 return;
2142
2143 tree sizet;
2144 tree base_addr = base;
2145 gimple *bos_stmt = NULLnullptr;
2146 if (decl_p)
2147 base_addr = build1 (ADDR_EXPR,
2148 build_pointer_type (TREE_TYPE (base)((contains_struct_check ((base), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2148, __FUNCTION__))->typed.type)
), base);
2149 unsigned HOST_WIDE_INTlong size;
2150 if (compute_builtin_object_size (base_addr, 0, &size))
2151 sizet = build_int_cst (sizetypesizetype_tab[(int) stk_sizetype], size);
2152 else if (optimizeglobal_options.x_optimize)
2153 {
2154 if (LOCATION_LOCUS (loc)((IS_ADHOC_LOC (loc)) ? get_location_from_adhoc_loc (line_table
, loc) : (loc))
== UNKNOWN_LOCATION((location_t) 0))
2155 loc = input_location;
2156 /* Generate __builtin_object_size call. */
2157 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
2158 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
2159 integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]);
2160 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE(tree) nullptr, true,
2161 GSI_SAME_STMT);
2162 /* If the call above didn't end up being an integer constant, go one
2163 statement back and get the __builtin_object_size stmt. Save it,
2164 we might need it later. */
2165 if (SSA_VAR_P (sizet)(((enum tree_code) (sizet)->base.code) == VAR_DECL || ((enum
tree_code) (sizet)->base.code) == PARM_DECL || ((enum tree_code
) (sizet)->base.code) == RESULT_DECL || ((enum tree_code) (
sizet)->base.code) == SSA_NAME)
)
2166 {
2167 gsi_prev (gsi);
2168 bos_stmt = gsi_stmt (*gsi);
2169
2170 /* Move on to where we were. */
2171 gsi_next (gsi);
2172 }
2173 }
2174 else
2175 return;
2176
2177 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
2178 call. */
2179 /* ptr + sizeof (*ptr) - base */
2180 t = fold_build2 (MINUS_EXPR, sizetype,fold_build2_loc (((location_t) 0), MINUS_EXPR, sizetype_tab[(
int) stk_sizetype], fold_convert_loc (((location_t) 0), global_trees
[TI_POINTER_SIZED_TYPE], ptr), fold_convert_loc (((location_t
) 0), global_trees[TI_POINTER_SIZED_TYPE], base_addr) )
2181 fold_convert (pointer_sized_int_node, ptr),fold_build2_loc (((location_t) 0), MINUS_EXPR, sizetype_tab[(
int) stk_sizetype], fold_convert_loc (((location_t) 0), global_trees
[TI_POINTER_SIZED_TYPE], ptr), fold_convert_loc (((location_t
) 0), global_trees[TI_POINTER_SIZED_TYPE], base_addr) )
2182 fold_convert (pointer_sized_int_node, base_addr))fold_build2_loc (((location_t) 0), MINUS_EXPR, sizetype_tab[(
int) stk_sizetype], fold_convert_loc (((location_t) 0), global_trees
[TI_POINTER_SIZED_TYPE], ptr), fold_convert_loc (((location_t
) 0), global_trees[TI_POINTER_SIZED_TYPE], base_addr) )
;
2183 t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type))fold_build2_loc (((location_t) 0), PLUS_EXPR, sizetype_tab[(int
) stk_sizetype], t, ((tree_class_check ((type), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2183, __FUNCTION__))->type_common.size_unit) )
;
2184
2185 /* Perhaps we can omit the check. */
2186 if (TREE_CODE (t)((enum tree_code) (t)->base.code) == INTEGER_CST
2187 && TREE_CODE (sizet)((enum tree_code) (sizet)->base.code) == INTEGER_CST
2188 && tree_int_cst_le (t, sizet))
2189 return;
2190
2191 if (index != NULL_TREE(tree) nullptr
2192 && TREE_CODE (index)((enum tree_code) (index)->base.code) == SSA_NAME
2193 && TREE_CODE (sizet)((enum tree_code) (sizet)->base.code) == INTEGER_CST)
2194 {
2195 gimple *def = SSA_NAME_DEF_STMT (index)(tree_check ((index), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2195, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
2196 if (is_gimple_assign (def)
2197 && gimple_assign_rhs_code (def) == BIT_AND_EXPR
2198 && TREE_CODE (gimple_assign_rhs2 (def))((enum tree_code) (gimple_assign_rhs2 (def))->base.code) == INTEGER_CST)
2199 {
2200 tree cst = gimple_assign_rhs2 (def);
2201 tree sz = fold_build2 (EXACT_DIV_EXPR, sizetype, sizet,fold_build2_loc (((location_t) 0), EXACT_DIV_EXPR, sizetype_tab
[(int) stk_sizetype], sizet, ((tree_class_check ((type), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2202, __FUNCTION__))->type_common.size_unit) )
2202 TYPE_SIZE_UNIT (type))fold_build2_loc (((location_t) 0), EXACT_DIV_EXPR, sizetype_tab
[(int) stk_sizetype], sizet, ((tree_class_check ((type), (tcc_type
), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2202, __FUNCTION__))->type_common.size_unit) )
;
2203 if (tree_int_cst_sgn (cst) >= 0
2204 && tree_int_cst_lt (cst, sz))
2205 return;
2206 }
2207 }
2208
2209 if (bos_stmt && gimple_call_builtin_p (bos_stmt, BUILT_IN_OBJECT_SIZE))
2210 ubsan_create_edge (bos_stmt);
2211
2212 /* We have to emit the check. */
2213 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE(tree) nullptr, true,
2214 GSI_SAME_STMT);
2215 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE(tree) nullptr, true,
2216 GSI_SAME_STMT);
2217 tree ckind = build_int_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char],
2218 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
2219 gimple *g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
2220 ptr, t, sizet, ckind);
2221 gimple_set_location (g, loc);
2222 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2223}
2224
2225/* Instrument values passed to builtin functions. */
2226
2227static void
2228instrument_builtin (gimple_stmt_iterator *gsi)
2229{
2230 gimple *stmt = gsi_stmt (*gsi);
2231 location_t loc = gimple_location (stmt);
2232 tree arg;
2233 enum built_in_function fcode
2234 = DECL_FUNCTION_CODE (gimple_call_fndecl (stmt));
2235 int kind = 0;
2236 switch (fcode)
2237 {
2238 CASE_INT_FN (BUILT_IN_CLZ)case BUILT_IN_CLZ: case BUILT_IN_CLZL: case BUILT_IN_CLZLL: case
BUILT_IN_CLZIMAX
:
2239 kind = 1;
2240 gcc_fallthrough ();
2241 CASE_INT_FN (BUILT_IN_CTZ)case BUILT_IN_CTZ: case BUILT_IN_CTZL: case BUILT_IN_CTZLL: case
BUILT_IN_CTZIMAX
:
2242 arg = gimple_call_arg (stmt, 0);
2243 if (!integer_nonzerop (arg))
2244 {
2245 gimple *g;
2246 if (!is_gimple_val (arg))
2247 {
2248 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)((contains_struct_check ((arg), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2248, __FUNCTION__))->typed.type)
), arg);
2249 gimple_set_location (g, loc);
2250 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2251 arg = gimple_assign_lhs (g);
2252 }
2253
2254 basic_block then_bb, fallthru_bb;
2255 *gsi = create_cond_insert_point (gsi, true, false, true,
2256 &then_bb, &fallthru_bb);
2257 g = gimple_build_cond (EQ_EXPR, arg,
2258 build_zero_cst (TREE_TYPE (arg)((contains_struct_check ((arg), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2258, __FUNCTION__))->typed.type)
),
2259 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
2260 gimple_set_location (g, loc);
2261 gsi_insert_after (gsi, g, GSI_NEW_STMT);
2262
2263 *gsi = gsi_after_labels (then_bb);
2264 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
2265 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
2266 else
2267 {
2268 tree t = build_int_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char], kind);
2269 tree data = ubsan_create_data ("__ubsan_builtin_data",
2270 1, &loc, NULL_TREE(tree) nullptr, t, NULL_TREE(tree) nullptr);
2271 data = build_fold_addr_expr_loc (loc, data);
2272 enum built_in_function bcode
2273 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_BUILTIN)
2274 ? BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN
2275 : BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN_ABORT;
2276 tree fn = builtin_decl_explicit (bcode);
2277
2278 g = gimple_build_call (fn, 1, data);
2279 }
2280 gimple_set_location (g, loc);
2281 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2282 ubsan_create_edge (g);
2283 }
2284 *gsi = gsi_for_stmt (stmt);
2285 break;
2286 default:
2287 break;
2288 }
2289}
2290
2291namespace {
2292
2293const pass_data pass_data_ubsan =
2294{
2295 GIMPLE_PASS, /* type */
2296 "ubsan", /* name */
2297 OPTGROUP_NONE, /* optinfo_flags */
2298 TV_TREE_UBSAN, /* tv_id */
2299 ( PROP_cfg(1 << 3) | PROP_ssa(1 << 5) ), /* properties_required */
2300 0, /* properties_provided */
2301 0, /* properties_destroyed */
2302 0, /* todo_flags_start */
2303 TODO_update_ssa(1 << 11), /* todo_flags_finish */
2304};
2305
2306class pass_ubsan : public gimple_opt_pass
2307{
2308public:
2309 pass_ubsan (gcc::context *ctxt)
2310 : gimple_opt_pass (pass_data_ubsan, ctxt)
2311 {}
2312
2313 /* opt_pass methods: */
2314 virtual bool gate (function *)
2315 {
2316 return sanitize_flags_p ((SANITIZE_NULL | SANITIZE_SI_OVERFLOW
2317 | SANITIZE_BOOL | SANITIZE_ENUM
2318 | SANITIZE_ALIGNMENT
2319 | SANITIZE_NONNULL_ATTRIBUTE
2320 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
2321 | SANITIZE_OBJECT_SIZE
2322 | SANITIZE_POINTER_OVERFLOW
2323 | SANITIZE_BUILTIN));
2324 }
2325
2326 virtual unsigned int execute (function *);
2327
2328}; // class pass_ubsan
2329
2330unsigned int
2331pass_ubsan::execute (function *fun)
2332{
2333 basic_block bb;
2334 gimple_stmt_iterator gsi;
2335 unsigned int ret = 0;
2336
2337 initialize_sanitizer_builtins ();
2338
2339 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)
2340 {
2341 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
2342 {
2343 gimple *stmt = gsi_stmt (gsi);
2344 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
2345 {
2346 gsi_next (&gsi);
2347 continue;
2348 }
2349
2350 if ((sanitize_flags_p (SANITIZE_SI_OVERFLOW, fun->decl))
2351 && is_gimple_assign (stmt))
2352 instrument_si_overflow (gsi);
2353
2354 if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT, fun->decl))
2355 {
2356 if (gimple_store_p (stmt))
2357 instrument_null (gsi, gimple_get_lhs (stmt), true);
2358 if (gimple_assign_single_p (stmt))
2359 instrument_null (gsi, gimple_assign_rhs1 (stmt), false);
2360 if (is_gimple_call (stmt))
2361 {
2362 unsigned args_num = gimple_call_num_args (stmt);
2363 for (unsigned i = 0; i < args_num; ++i)
2364 {
2365 tree arg = gimple_call_arg (stmt, i);
2366 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2367 continue;
2368 instrument_null (gsi, arg, false);
2369 }
2370 }
2371 }
2372
2373 if (sanitize_flags_p (SANITIZE_BOOL | SANITIZE_ENUM, fun->decl)
2374 && gimple_assign_load_p (stmt))
2375 {
2376 instrument_bool_enum_load (&gsi);
2377 bb = gimple_bb (stmt);
2378 }
2379
2380 if (sanitize_flags_p (SANITIZE_NONNULL_ATTRIBUTE, fun->decl)
2381 && is_gimple_call (stmt)
2382 && !gimple_call_internal_p (stmt))
2383 {
2384 instrument_nonnull_arg (&gsi);
2385 bb = gimple_bb (stmt);
2386 }
2387
2388 if (sanitize_flags_p (SANITIZE_BUILTIN, fun->decl)
2389 && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
2390 {
2391 instrument_builtin (&gsi);
2392 bb = gimple_bb (stmt);
2393 }
2394
2395 if (sanitize_flags_p (SANITIZE_RETURNS_NONNULL_ATTRIBUTE, fun->decl)
2396 && gimple_code (stmt) == GIMPLE_RETURN)
2397 {
2398 instrument_nonnull_return (&gsi);
2399 bb = gimple_bb (stmt);
2400 }
2401
2402 if (sanitize_flags_p (SANITIZE_OBJECT_SIZE, fun->decl))
2403 {
2404 if (gimple_store_p (stmt))
2405 instrument_object_size (&gsi, gimple_get_lhs (stmt), true);
2406 if (gimple_assign_load_p (stmt))
2407 instrument_object_size (&gsi, gimple_assign_rhs1 (stmt),
2408 false);
2409 if (is_gimple_call (stmt))
2410 {
2411 unsigned args_num = gimple_call_num_args (stmt);
2412 for (unsigned i = 0; i < args_num; ++i)
2413 {
2414 tree arg = gimple_call_arg (stmt, i);
2415 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2416 continue;
2417 instrument_object_size (&gsi, arg, false);
2418 }
2419 }
2420 }
2421
2422 if (sanitize_flags_p (SANITIZE_POINTER_OVERFLOW, fun->decl))
2423 {
2424 if (is_gimple_assign (stmt)
2425 && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
2426 instrument_pointer_overflow (&gsi,
2427 gimple_assign_rhs1 (stmt),
2428 gimple_assign_rhs2 (stmt));
2429 if (gimple_store_p (stmt))
2430 maybe_instrument_pointer_overflow (&gsi,
2431 gimple_get_lhs (stmt));
2432 if (gimple_assign_single_p (stmt))
2433 maybe_instrument_pointer_overflow (&gsi,
2434 gimple_assign_rhs1 (stmt));
2435 if (is_gimple_call (stmt))
2436 {
2437 unsigned args_num = gimple_call_num_args (stmt);
2438 for (unsigned i = 0; i < args_num; ++i)
2439 {
2440 tree arg = gimple_call_arg (stmt, i);
2441 if (is_gimple_reg (arg))
2442 continue;
2443 maybe_instrument_pointer_overflow (&gsi, arg);
2444 }
2445 }
2446 }
2447
2448 gsi_next (&gsi);
2449 }
2450 if (gimple_purge_dead_eh_edges (bb))
2451 ret = TODO_cleanup_cfg(1 << 5);
2452 }
2453 return ret;
2454}
2455
2456} // anon namespace
2457
2458gimple_opt_pass *
2459make_pass_ubsan (gcc::context *ctxt)
2460{
2461 return new pass_ubsan (ctxt);
2462}
2463
2464#include "gt-ubsan.h"

/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h

1/* Vector API for GNU compiler.
2 Copyright (C) 2004-2021 Free Software Foundation, Inc.
3 Contributed by Nathan Sidwell <nathan@codesourcery.com>
4 Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
22#ifndef GCC_VEC_H
23#define GCC_VEC_H
24
25/* Some gen* file have no ggc support as the header file gtype-desc.h is
26 missing. Provide these definitions in case ggc.h has not been included.
27 This is not a problem because any code that runs before gengtype is built
28 will never need to use GC vectors.*/
29
30extern void ggc_free (void *);
31extern size_t ggc_round_alloc_size (size_t requested_size);
32extern void *ggc_realloc (void *, size_t MEM_STAT_DECL);
33
34/* Templated vector type and associated interfaces.
35
36 The interface functions are typesafe and use inline functions,
37 sometimes backed by out-of-line generic functions. The vectors are
38 designed to interoperate with the GTY machinery.
39
40 There are both 'index' and 'iterate' accessors. The index accessor
41 is implemented by operator[]. The iterator returns a boolean
42 iteration condition and updates the iteration variable passed by
43 reference. Because the iterator will be inlined, the address-of
44 can be optimized away.
45
46 Each operation that increases the number of active elements is
47 available in 'quick' and 'safe' variants. The former presumes that
48 there is sufficient allocated space for the operation to succeed
49 (it dies if there is not). The latter will reallocate the
50 vector, if needed. Reallocation causes an exponential increase in
51 vector size. If you know you will be adding N elements, it would
52 be more efficient to use the reserve operation before adding the
53 elements with the 'quick' operation. This will ensure there are at
54 least as many elements as you ask for, it will exponentially
55 increase if there are too few spare slots. If you want reserve a
56 specific number of slots, but do not want the exponential increase
57 (for instance, you know this is the last allocation), use the
58 reserve_exact operation. You can also create a vector of a
59 specific size from the get go.
60
61 You should prefer the push and pop operations, as they append and
62 remove from the end of the vector. If you need to remove several
63 items in one go, use the truncate operation. The insert and remove
64 operations allow you to change elements in the middle of the
65 vector. There are two remove operations, one which preserves the
66 element ordering 'ordered_remove', and one which does not
67 'unordered_remove'. The latter function copies the end element
68 into the removed slot, rather than invoke a memmove operation. The
69 'lower_bound' function will determine where to place an item in the
70 array using insert that will maintain sorted order.
71
72 Vectors are template types with three arguments: the type of the
73 elements in the vector, the allocation strategy, and the physical
74 layout to use
75
76 Four allocation strategies are supported:
77
78 - Heap: allocation is done using malloc/free. This is the
79 default allocation strategy.
80
81 - GC: allocation is done using ggc_alloc/ggc_free.
82
83 - GC atomic: same as GC with the exception that the elements
84 themselves are assumed to be of an atomic type that does
85 not need to be garbage collected. This means that marking
86 routines do not need to traverse the array marking the
87 individual elements. This increases the performance of
88 GC activities.
89
90 Two physical layouts are supported:
91
92 - Embedded: The vector is structured using the trailing array
93 idiom. The last member of the structure is an array of size
94 1. When the vector is initially allocated, a single memory
95 block is created to hold the vector's control data and the
96 array of elements. These vectors cannot grow without
97 reallocation (see discussion on embeddable vectors below).
98
99 - Space efficient: The vector is structured as a pointer to an
100 embedded vector. This is the default layout. It means that
101 vectors occupy a single word of storage before initial
102 allocation. Vectors are allowed to grow (the internal
103 pointer is reallocated but the main vector instance does not
104 need to relocate).
105
106 The type, allocation and layout are specified when the vector is
107 declared.
108
109 If you need to directly manipulate a vector, then the 'address'
110 accessor will return the address of the start of the vector. Also
111 the 'space' predicate will tell you whether there is spare capacity
112 in the vector. You will not normally need to use these two functions.
113
114 Notes on the different layout strategies
115
116 * Embeddable vectors (vec<T, A, vl_embed>)
117
118 These vectors are suitable to be embedded in other data
119 structures so that they can be pre-allocated in a contiguous
120 memory block.
121
122 Embeddable vectors are implemented using the trailing array
123 idiom, thus they are not resizeable without changing the address
124 of the vector object itself. This means you cannot have
125 variables or fields of embeddable vector type -- always use a
126 pointer to a vector. The one exception is the final field of a
127 structure, which could be a vector type.
128
129 You will have to use the embedded_size & embedded_init calls to
130 create such objects, and they will not be resizeable (so the
131 'safe' allocation variants are not available).
132
133 Properties of embeddable vectors:
134
135 - The whole vector and control data are allocated in a single
136 contiguous block. It uses the trailing-vector idiom, so
137 allocation must reserve enough space for all the elements
138 in the vector plus its control data.
139 - The vector cannot be re-allocated.
140 - The vector cannot grow nor shrink.
141 - No indirections needed for access/manipulation.
142 - It requires 2 words of storage (prior to vector allocation).
143
144
145 * Space efficient vector (vec<T, A, vl_ptr>)
146
147 These vectors can grow dynamically and are allocated together
148 with their control data. They are suited to be included in data
149 structures. Prior to initial allocation, they only take a single
150 word of storage.
151
152 These vectors are implemented as a pointer to embeddable vectors.
153 The semantics allow for this pointer to be NULL to represent
154 empty vectors. This way, empty vectors occupy minimal space in
155 the structure containing them.
156
157 Properties:
158
159 - The whole vector and control data are allocated in a single
160 contiguous block.
161 - The whole vector may be re-allocated.
162 - Vector data may grow and shrink.
163 - Access and manipulation requires a pointer test and
164 indirection.
165 - It requires 1 word of storage (prior to vector allocation).
166
167 An example of their use would be,
168
169 struct my_struct {
170 // A space-efficient vector of tree pointers in GC memory.
171 vec<tree, va_gc, vl_ptr> v;
172 };
173
174 struct my_struct *s;
175
176 if (s->v.length ()) { we have some contents }
177 s->v.safe_push (decl); // append some decl onto the end
178 for (ix = 0; s->v.iterate (ix, &elt); ix++)
179 { do something with elt }
180*/
181
182/* Support function for statistics. */
183extern void dump_vec_loc_statistics (void);
184
185/* Hashtable mapping vec addresses to descriptors. */
186extern htab_t vec_mem_usage_hash;
187
188/* Control data for vectors. This contains the number of allocated
189 and used slots inside a vector. */
190
191struct vec_prefix
192{
193 /* FIXME - These fields should be private, but we need to cater to
194 compilers that have stricter notions of PODness for types. */
195
196 /* Memory allocation support routines in vec.c. */
197 void register_overhead (void *, size_t, size_t CXX_MEM_STAT_INFO);
198 void release_overhead (void *, size_t, size_t, bool CXX_MEM_STAT_INFO);
199 static unsigned calculate_allocation (vec_prefix *, unsigned, bool);
200 static unsigned calculate_allocation_1 (unsigned, unsigned);
201
202 /* Note that vec_prefix should be a base class for vec, but we use
203 offsetof() on vector fields of tree structures (e.g.,
204 tree_binfo::base_binfos), and offsetof only supports base types.
205
206 To compensate, we make vec_prefix a field inside vec and make
207 vec a friend class of vec_prefix so it can access its fields. */
208 template <typename, typename, typename> friend struct vec;
209
210 /* The allocator types also need access to our internals. */
211 friend struct va_gc;
212 friend struct va_gc_atomic;
213 friend struct va_heap;
214
215 unsigned m_alloc : 31;
216 unsigned m_using_auto_storage : 1;
217 unsigned m_num;
218};
219
220/* Calculate the number of slots to reserve a vector, making sure that
221 RESERVE slots are free. If EXACT grow exactly, otherwise grow
222 exponentially. PFX is the control data for the vector. */
223
224inline unsigned
225vec_prefix::calculate_allocation (vec_prefix *pfx, unsigned reserve,
226 bool exact)
227{
228 if (exact
16.1
'exact' is false
16.1
'exact' is false
)
17
Taking false branch
229 return (pfx ? pfx->m_num : 0) + reserve;
230 else if (!pfx
17.1
'pfx' is null
17.1
'pfx' is null
)
18
Taking true branch
231 return MAX (4, reserve)((4) > (reserve) ? (4) : (reserve));
19
'?' condition is true
20
Returning the value 4, which participates in a condition later
232 return calculate_allocation_1 (pfx->m_alloc, pfx->m_num + reserve);
233}
234
235template<typename, typename, typename> struct vec;
236
237/* Valid vector layouts
238
239 vl_embed - Embeddable vector that uses the trailing array idiom.
240 vl_ptr - Space efficient vector that uses a pointer to an
241 embeddable vector. */
242struct vl_embed { };
243struct vl_ptr { };
244
245
246/* Types of supported allocations
247
248 va_heap - Allocation uses malloc/free.
249 va_gc - Allocation uses ggc_alloc.
250 va_gc_atomic - Same as GC, but individual elements of the array
251 do not need to be marked during collection. */
252
253/* Allocator type for heap vectors. */
254struct va_heap
255{
256 /* Heap vectors are frequently regular instances, so use the vl_ptr
257 layout for them. */
258 typedef vl_ptr default_layout;
259
260 template<typename T>
261 static void reserve (vec<T, va_heap, vl_embed> *&, unsigned, bool
262 CXX_MEM_STAT_INFO);
263
264 template<typename T>
265 static void release (vec<T, va_heap, vl_embed> *&);
266};
267
268
269/* Allocator for heap memory. Ensure there are at least RESERVE free
270 slots in V. If EXACT is true, grow exactly, else grow
271 exponentially. As a special case, if the vector had not been
272 allocated and RESERVE is 0, no vector will be created. */
273
274template<typename T>
275inline void
276va_heap::reserve (vec<T, va_heap, vl_embed> *&v, unsigned reserve, bool exact
277 MEM_STAT_DECL)
278{
279 size_t elt_size = sizeof (T);
280 unsigned alloc
281 = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
282 gcc_checking_assert (alloc)((void)(!(alloc) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 282, __FUNCTION__), 0 : 0))
;
283
284 if (GATHER_STATISTICS0 && v)
285 v->m_vecpfx.release_overhead (v, elt_size * v->allocated (),
286 v->allocated (), false);
287
288 size_t size = vec<T, va_heap, vl_embed>::embedded_size (alloc);
289 unsigned nelem = v ? v->length () : 0;
290 v = static_cast <vec<T, va_heap, vl_embed> *> (xrealloc (v, size));
291 v->embedded_init (alloc, nelem);
292
293 if (GATHER_STATISTICS0)
294 v->m_vecpfx.register_overhead (v, alloc, elt_size PASS_MEM_STAT);
295}
296
297
298#if GCC_VERSION(4 * 1000 + 2) >= 4007
299#pragma GCC diagnostic push
300#pragma GCC diagnostic ignored "-Wfree-nonheap-object"
301#endif
302
303/* Free the heap space allocated for vector V. */
304
305template<typename T>
306void
307va_heap::release (vec<T, va_heap, vl_embed> *&v)
308{
309 size_t elt_size = sizeof (T);
310 if (v == NULLnullptr)
311 return;
312
313 if (GATHER_STATISTICS0)
314 v->m_vecpfx.release_overhead (v, elt_size * v->allocated (),
315 v->allocated (), true);
316 ::free (v);
317 v = NULLnullptr;
318}
319
320#if GCC_VERSION(4 * 1000 + 2) >= 4007
321#pragma GCC diagnostic pop
322#endif
323
324/* Allocator type for GC vectors. Notice that we need the structure
325 declaration even if GC is not enabled. */
326
327struct va_gc
328{
329 /* Use vl_embed as the default layout for GC vectors. Due to GTY
330 limitations, GC vectors must always be pointers, so it is more
331 efficient to use a pointer to the vl_embed layout, rather than
332 using a pointer to a pointer as would be the case with vl_ptr. */
333 typedef vl_embed default_layout;
334
335 template<typename T, typename A>
336 static void reserve (vec<T, A, vl_embed> *&, unsigned, bool
337 CXX_MEM_STAT_INFO);
338
339 template<typename T, typename A>
340 static void release (vec<T, A, vl_embed> *&v);
341};
342
343
344/* Free GC memory used by V and reset V to NULL. */
345
346template<typename T, typename A>
347inline void
348va_gc::release (vec<T, A, vl_embed> *&v)
349{
350 if (v)
351 ::ggc_free (v);
352 v = NULLnullptr;
353}
354
355
356/* Allocator for GC memory. Ensure there are at least RESERVE free
357 slots in V. If EXACT is true, grow exactly, else grow
358 exponentially. As a special case, if the vector had not been
359 allocated and RESERVE is 0, no vector will be created. */
360
361template<typename T, typename A>
362void
363va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact
364 MEM_STAT_DECL)
365{
366 unsigned alloc
367 = vec_prefix::calculate_allocation (v
14.1
'v' is null
38.1
'v' is non-null
14.1
'v' is null
38.1
'v' is non-null
? &v->m_vecpfx : 0, reserve, exact)
;
15
'?' condition is false
16
Calling 'vec_prefix::calculate_allocation'
21
Returning from 'vec_prefix::calculate_allocation'
39
'?' condition is true
368 if (!alloc
21.1
'alloc' is 4
21.1
'alloc' is 4
)
22
Taking false branch
40
Assuming 'alloc' is 0
41
Taking true branch
369 {
370 ::ggc_free (v);
371 v = NULLnullptr;
42
Null pointer value stored to 'saved_args'
372 return;
373 }
374
375 /* Calculate the amount of space we want. */
376 size_t size = vec<T, A, vl_embed>::embedded_size (alloc);
377
378 /* Ask the allocator how much space it will really give us. */
379 size = ::ggc_round_alloc_size (size);
380
381 /* Adjust the number of slots accordingly. */
382 size_t vec_offset = sizeof (vec_prefix);
383 size_t elt_size = sizeof (T);
384 alloc = (size - vec_offset) / elt_size;
385
386 /* And finally, recalculate the amount of space we ask for. */
387 size = vec_offset + alloc * elt_size;
388
389 unsigned nelem = v
22.1
'v' is null
22.1
'v' is null
? v->length () : 0;
23
'?' condition is false
390 v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc (v, size
24
Value assigned to 'saved_args'
391 PASS_MEM_STAT));
392 v->embedded_init (alloc, nelem);
393}
394
395
396/* Allocator type for GC vectors. This is for vectors of types
397 atomics w.r.t. collection, so allocation and deallocation is
398 completely inherited from va_gc. */
399struct va_gc_atomic : va_gc
400{
401};
402
403
404/* Generic vector template. Default values for A and L indicate the
405 most commonly used strategies.
406
407 FIXME - Ideally, they would all be vl_ptr to encourage using regular
408 instances for vectors, but the existing GTY machinery is limited
409 in that it can only deal with GC objects that are pointers
410 themselves.
411
412 This means that vector operations that need to deal with
413 potentially NULL pointers, must be provided as free
414 functions (see the vec_safe_* functions above). */
415template<typename T,
416 typename A = va_heap,
417 typename L = typename A::default_layout>
418struct GTY((user)) vec
419{
420};
421
422/* Allow C++11 range-based 'for' to work directly on vec<T>*. */
423template<typename T, typename A, typename L>
424T* begin (vec<T,A,L> *v) { return v ? v->begin () : nullptr; }
425template<typename T, typename A, typename L>
426T* end (vec<T,A,L> *v) { return v ? v->end () : nullptr; }
427template<typename T, typename A, typename L>
428const T* begin (const vec<T,A,L> *v) { return v ? v->begin () : nullptr; }
429template<typename T, typename A, typename L>
430const T* end (const vec<T,A,L> *v) { return v ? v->end () : nullptr; }
431
432/* Generic vec<> debug helpers.
433
434 These need to be instantiated for each vec<TYPE> used throughout
435 the compiler like this:
436
437 DEFINE_DEBUG_VEC (TYPE)
438
439 The reason we have a debug_helper() is because GDB can't
440 disambiguate a plain call to debug(some_vec), and it must be called
441 like debug<TYPE>(some_vec). */
442
443template<typename T>
444void
445debug_helper (vec<T> &ref)
446{
447 unsigned i;
448 for (i = 0; i < ref.length (); ++i)
449 {
450 fprintf (stderrstderr, "[%d] = ", i);
451 debug_slim (ref[i]);
452 fputc ('\n', stderrstderr);
453 }
454}
455
456/* We need a separate va_gc variant here because default template
457 argument for functions cannot be used in c++-98. Once this
458 restriction is removed, those variant should be folded with the
459 above debug_helper. */
460
461template<typename T>
462void
463debug_helper (vec<T, va_gc> &ref)
464{
465 unsigned i;
466 for (i = 0; i < ref.length (); ++i)
467 {
468 fprintf (stderrstderr, "[%d] = ", i);
469 debug_slim (ref[i]);
470 fputc ('\n', stderrstderr);
471 }
472}
473
474/* Macro to define debug(vec<T>) and debug(vec<T, va_gc>) helper
475 functions for a type T. */
476
477#define DEFINE_DEBUG_VEC(T)template void debug_helper (vec<T> &); template void
debug_helper (vec<T, va_gc> &); __attribute__ ((__used__
)) void debug (vec<T> &ref) { debug_helper <T>
(ref); } __attribute__ ((__used__)) void debug (vec<T>
*ptr) { if (ptr) debug (*ptr); else fprintf (stderr, "<nil>\n"
); } __attribute__ ((__used__)) void debug (vec<T, va_gc>
&ref) { debug_helper <T> (ref); } __attribute__ ((
__used__)) void debug (vec<T, va_gc> *ptr) { if (ptr) debug
(*ptr); else fprintf (stderr, "<nil>\n"); }
\
478 template void debug_helper (vec<T> &); \
479 template void debug_helper (vec<T, va_gc> &); \
480 /* Define the vec<T> debug functions. */ \
481 DEBUG_FUNCTION__attribute__ ((__used__)) void \
482 debug (vec<T> &ref) \
483 { \
484 debug_helper <T> (ref); \
485 } \
486 DEBUG_FUNCTION__attribute__ ((__used__)) void \
487 debug (vec<T> *ptr) \
488 { \
489 if (ptr) \
490 debug (*ptr); \
491 else \
492 fprintf (stderrstderr, "<nil>\n"); \
493 } \
494 /* Define the vec<T, va_gc> debug functions. */ \
495 DEBUG_FUNCTION__attribute__ ((__used__)) void \
496 debug (vec<T, va_gc> &ref) \
497 { \
498 debug_helper <T> (ref); \
499 } \
500 DEBUG_FUNCTION__attribute__ ((__used__)) void \
501 debug (vec<T, va_gc> *ptr) \
502 { \
503 if (ptr) \
504 debug (*ptr); \
505 else \
506 fprintf (stderrstderr, "<nil>\n"); \
507 }
508
509/* Default-construct N elements in DST. */
510
511template <typename T>
512inline void
513vec_default_construct (T *dst, unsigned n)
514{
515#ifdef BROKEN_VALUE_INITIALIZATION
516 /* Versions of GCC before 4.4 sometimes leave certain objects
517 uninitialized when value initialized, though if the type has
518 user defined default ctor, that ctor is invoked. As a workaround
519 perform clearing first and then the value initialization, which
520 fixes the case when value initialization doesn't initialize due to
521 the bugs and should initialize to all zeros, but still allows
522 vectors for types with user defined default ctor that initializes
523 some or all elements to non-zero. If T has no user defined
524 default ctor and some non-static data members have user defined
525 default ctors that initialize to non-zero the workaround will
526 still not work properly; in that case we just need to provide
527 user defined default ctor. */
528 memset (dst, '\0', sizeof (T) * n);
529#endif
530 for ( ; n; ++dst, --n)
531 ::new (static_cast<void*>(dst)) T ();
532}
533
534/* Copy-construct N elements in DST from *SRC. */
535
536template <typename T>
537inline void
538vec_copy_construct (T *dst, const T *src, unsigned n)
539{
540 for ( ; n; ++dst, ++src, --n)
541 ::new (static_cast<void*>(dst)) T (*src);
542}
543
544/* Type to provide NULL values for vec<T, A, L>. This is used to
545 provide nil initializers for vec instances. Since vec must be
546 a POD, we cannot have proper ctor/dtor for it. To initialize
547 a vec instance, you can assign it the value vNULL. This isn't
548 needed for file-scope and function-local static vectors, which
549 are zero-initialized by default. */
550struct vnull
551{
552 template <typename T, typename A, typename L>
553 CONSTEXPRconstexpr operator vec<T, A, L> () const { return vec<T, A, L>(); }
554};
555extern vnull vNULL;
556
557
558/* Embeddable vector. These vectors are suitable to be embedded
559 in other data structures so that they can be pre-allocated in a
560 contiguous memory block.
561
562 Embeddable vectors are implemented using the trailing array idiom,
563 thus they are not resizeable without changing the address of the
564 vector object itself. This means you cannot have variables or
565 fields of embeddable vector type -- always use a pointer to a
566 vector. The one exception is the final field of a structure, which
567 could be a vector type.
568
569 You will have to use the embedded_size & embedded_init calls to
570 create such objects, and they will not be resizeable (so the 'safe'
571 allocation variants are not available).
572
573 Properties:
574
575 - The whole vector and control data are allocated in a single
576 contiguous block. It uses the trailing-vector idiom, so
577 allocation must reserve enough space for all the elements
578 in the vector plus its control data.
579 - The vector cannot be re-allocated.
580 - The vector cannot grow nor shrink.
581 - No indirections needed for access/manipulation.
582 - It requires 2 words of storage (prior to vector allocation). */
583
584template<typename T, typename A>
585struct GTY((user)) vec<T, A, vl_embed>
586{
587public:
588 unsigned allocated (void) const { return m_vecpfx.m_alloc; }
589 unsigned length (void) const { return m_vecpfx.m_num; }
590 bool is_empty (void) const { return m_vecpfx.m_num == 0; }
591 T *address (void) { return m_vecdata; }
592 const T *address (void) const { return m_vecdata; }
593 T *begin () { return address (); }
594 const T *begin () const { return address (); }
595 T *end () { return address () + length (); }
596 const T *end () const { return address () + length (); }
597 const T &operator[] (unsigned) const;
598 T &operator[] (unsigned);
599 T &last (void);
600 bool space (unsigned) const;
601 bool iterate (unsigned, T *) const;
602 bool iterate (unsigned, T **) const;
603 vec *copy (ALONE_CXX_MEM_STAT_INFO) const;
604 void splice (const vec &);
605 void splice (const vec *src);
606 T *quick_push (const T &);
607 T &pop (void);
608 void truncate (unsigned);
609 void quick_insert (unsigned, const T &);
610 void ordered_remove (unsigned);
611 void unordered_remove (unsigned);
612 void block_remove (unsigned, unsigned);
613 void qsort (int (*) (const void *, const void *))qsort (int (*) (const void *, const void *));
614 void sort (int (*) (const void *, const void *, void *), void *);
615 T *bsearch (const void *key, int (*compar)(const void *, const void *));
616 T *bsearch (const void *key,
617 int (*compar)(const void *, const void *, void *), void *);
618 unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
619 bool contains (const T &search) const;
620 static size_t embedded_size (unsigned);
621 void embedded_init (unsigned, unsigned = 0, unsigned = 0);
622 void quick_grow (unsigned len);
623 void quick_grow_cleared (unsigned len);
624
625 /* vec class can access our internal data and functions. */
626 template <typename, typename, typename> friend struct vec;
627
628 /* The allocator types also need access to our internals. */
629 friend struct va_gc;
630 friend struct va_gc_atomic;
631 friend struct va_heap;
632
633 /* FIXME - These fields should be private, but we need to cater to
634 compilers that have stricter notions of PODness for types. */
635 vec_prefix m_vecpfx;
636 T m_vecdata[1];
637};
638
639
640/* Convenience wrapper functions to use when dealing with pointers to
641 embedded vectors. Some functionality for these vectors must be
642 provided via free functions for these reasons:
643
644 1- The pointer may be NULL (e.g., before initial allocation).
645
646 2- When the vector needs to grow, it must be reallocated, so
647 the pointer will change its value.
648
649 Because of limitations with the current GC machinery, all vectors
650 in GC memory *must* be pointers. */
651
652
653/* If V contains no room for NELEMS elements, return false. Otherwise,
654 return true. */
655template<typename T, typename A>
656inline bool
657vec_safe_space (const vec<T, A, vl_embed> *v, unsigned nelems)
658{
659 return v
9.1
'v' is null
9.1
'v' is null
? v->space (nelems) : nelems == 0
;
10
'?' condition is false
11
Returning zero, which participates in a condition later
660}
661
662
663/* If V is NULL, return 0. Otherwise, return V->length(). */
664template<typename T, typename A>
665inline unsigned
666vec_safe_length (const vec<T, A, vl_embed> *v)
667{
668 return v ? v->length () : 0;
669}
670
671
672/* If V is NULL, return NULL. Otherwise, return V->address(). */
673template<typename T, typename A>
674inline T *
675vec_safe_address (vec<T, A, vl_embed> *v)
676{
677 return v ? v->address () : NULLnullptr;
678}
679
680
681/* If V is NULL, return true. Otherwise, return V->is_empty(). */
682template<typename T, typename A>
683inline bool
684vec_safe_is_empty (vec<T, A, vl_embed> *v)
685{
686 return v ? v->is_empty () : true;
687}
688
689/* If V does not have space for NELEMS elements, call
690 V->reserve(NELEMS, EXACT). */
691template<typename T, typename A>
692inline bool
693vec_safe_reserve (vec<T, A, vl_embed> *&v, unsigned nelems, bool exact = false
694 CXX_MEM_STAT_INFO)
695{
696 bool extend = nelems
7.1
'nelems' is 1
34.1
'nelems' is 1
7.1
'nelems' is 1
34.1
'nelems' is 1
? !vec_safe_space (v, nelems) : false;
8
'?' condition is true
9
Calling 'vec_safe_space<tree_node *, va_gc>'
12
Returning from 'vec_safe_space<tree_node *, va_gc>'
35
'?' condition is true
36
Assuming the condition is true
697 if (extend
12.1
'extend' is true
36.1
'extend' is true
12.1
'extend' is true
36.1
'extend' is true
)
13
Taking true branch
37
Taking true branch
698 A::reserve (v, nelems, exact PASS_MEM_STAT);
14
Calling 'va_gc::reserve'
25
Returning from 'va_gc::reserve'
38
Calling 'va_gc::reserve'
43
Returning from 'va_gc::reserve'
699 return extend;
700}
701
702template<typename T, typename A>
703inline bool
704vec_safe_reserve_exact (vec<T, A, vl_embed> *&v, unsigned nelems
705 CXX_MEM_STAT_INFO)
706{
707 return vec_safe_reserve (v, nelems, true PASS_MEM_STAT);
708}
709
710
711/* Allocate GC memory for V with space for NELEMS slots. If NELEMS
712 is 0, V is initialized to NULL. */
713
714template<typename T, typename A>
715inline void
716vec_alloc (vec<T, A, vl_embed> *&v, unsigned nelems CXX_MEM_STAT_INFO)
717{
718 v = NULLnullptr;
719 vec_safe_reserve (v, nelems, false PASS_MEM_STAT);
720}
721
722
723/* Free the GC memory allocated by vector V and set it to NULL. */
724
725template<typename T, typename A>
726inline void
727vec_free (vec<T, A, vl_embed> *&v)
728{
729 A::release (v);
730}
731
732
733/* Grow V to length LEN. Allocate it, if necessary. */
734template<typename T, typename A>
735inline void
736vec_safe_grow (vec<T, A, vl_embed> *&v, unsigned len,
737 bool exact = false CXX_MEM_STAT_INFO)
738{
739 unsigned oldlen = vec_safe_length (v);
740 gcc_checking_assert (len >= oldlen)((void)(!(len >= oldlen) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 740, __FUNCTION__), 0 : 0))
;
741 vec_safe_reserve (v, len - oldlen, exact PASS_MEM_STAT);
742 v->quick_grow (len);
743}
744
745
746/* If V is NULL, allocate it. Call V->safe_grow_cleared(LEN). */
747template<typename T, typename A>
748inline void
749vec_safe_grow_cleared (vec<T, A, vl_embed> *&v, unsigned len,
750 bool exact = false CXX_MEM_STAT_INFO)
751{
752 unsigned oldlen = vec_safe_length (v);
753 vec_safe_grow (v, len, exact PASS_MEM_STAT);
754 vec_default_construct (v->address () + oldlen, len - oldlen);
755}
756
757
758/* Assume V is not NULL. */
759
760template<typename T>
761inline void
762vec_safe_grow_cleared (vec<T, va_heap, vl_ptr> *&v,
763 unsigned len, bool exact = false CXX_MEM_STAT_INFO)
764{
765 v->safe_grow_cleared (len, exact PASS_MEM_STAT);
766}
767
768/* If V does not have space for NELEMS elements, call
769 V->reserve(NELEMS, EXACT). */
770
771template<typename T>
772inline bool
773vec_safe_reserve (vec<T, va_heap, vl_ptr> *&v, unsigned nelems, bool exact = false
774 CXX_MEM_STAT_INFO)
775{
776 return v->reserve (nelems, exact);
777}
778
779
780/* If V is NULL return false, otherwise return V->iterate(IX, PTR). */
781template<typename T, typename A>
782inline bool
783vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T **ptr)
784{
785 if (v)
786 return v->iterate (ix, ptr);
787 else
788 {
789 *ptr = 0;
790 return false;
791 }
792}
793
794template<typename T, typename A>
795inline bool
796vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T *ptr)
797{
798 if (v)
799 return v->iterate (ix, ptr);
800 else
801 {
802 *ptr = 0;
803 return false;
804 }
805}
806
807
808/* If V has no room for one more element, reallocate it. Then call
809 V->quick_push(OBJ). */
810template<typename T, typename A>
811inline T *
812vec_safe_push (vec<T, A, vl_embed> *&v, const T &obj CXX_MEM_STAT_INFO)
813{
814 vec_safe_reserve (v, 1, false PASS_MEM_STAT);
7
Calling 'vec_safe_reserve<tree_node *, va_gc>'
26
Returning from 'vec_safe_reserve<tree_node *, va_gc>'
34
Calling 'vec_safe_reserve<tree_node *, va_gc>'
44
Returning from 'vec_safe_reserve<tree_node *, va_gc>'
815 return v->quick_push (obj);
45
Called C++ object pointer is null
816}
817
818
819/* if V has no room for one more element, reallocate it. Then call
820 V->quick_insert(IX, OBJ). */
821template<typename T, typename A>
822inline void
823vec_safe_insert (vec<T, A, vl_embed> *&v, unsigned ix, const T &obj
824 CXX_MEM_STAT_INFO)
825{
826 vec_safe_reserve (v, 1, false PASS_MEM_STAT);
827 v->quick_insert (ix, obj);
828}
829
830
831/* If V is NULL, do nothing. Otherwise, call V->truncate(SIZE). */
832template<typename T, typename A>
833inline void
834vec_safe_truncate (vec<T, A, vl_embed> *v, unsigned size)
835{
836 if (v)
837 v->truncate (size);
838}
839
840
841/* If SRC is not NULL, return a pointer to a copy of it. */
842template<typename T, typename A>
843inline vec<T, A, vl_embed> *
844vec_safe_copy (vec<T, A, vl_embed> *src CXX_MEM_STAT_INFO)
845{
846 return src ? src->copy (ALONE_PASS_MEM_STAT) : NULLnullptr;
847}
848
849/* Copy the elements from SRC to the end of DST as if by memcpy.
850 Reallocate DST, if necessary. */
851template<typename T, typename A>
852inline void
853vec_safe_splice (vec<T, A, vl_embed> *&dst, const vec<T, A, vl_embed> *src
854 CXX_MEM_STAT_INFO)
855{
856 unsigned src_len = vec_safe_length (src);
857 if (src_len)
858 {
859 vec_safe_reserve_exact (dst, vec_safe_length (dst) + src_len
860 PASS_MEM_STAT);
861 dst->splice (*src);
862 }
863}
864
865/* Return true if SEARCH is an element of V. Note that this is O(N) in the
866 size of the vector and so should be used with care. */
867
868template<typename T, typename A>
869inline bool
870vec_safe_contains (vec<T, A, vl_embed> *v, const T &search)
871{
872 return v ? v->contains (search) : false;
873}
874
875/* Index into vector. Return the IX'th element. IX must be in the
876 domain of the vector. */
877
878template<typename T, typename A>
879inline const T &
880vec<T, A, vl_embed>::operator[] (unsigned ix) const
881{
882 gcc_checking_assert (ix < m_vecpfx.m_num)((void)(!(ix < m_vecpfx.m_num) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 882, __FUNCTION__), 0 : 0))
;
883 return m_vecdata[ix];
884}
885
886template<typename T, typename A>
887inline T &
888vec<T, A, vl_embed>::operator[] (unsigned ix)
889{
890 gcc_checking_assert (ix < m_vecpfx.m_num)((void)(!(ix < m_vecpfx.m_num) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 890, __FUNCTION__), 0 : 0))
;
891 return m_vecdata[ix];
892}
893
894
895/* Get the final element of the vector, which must not be empty. */
896
897template<typename T, typename A>
898inline T &
899vec<T, A, vl_embed>::last (void)
900{
901 gcc_checking_assert (m_vecpfx.m_num > 0)((void)(!(m_vecpfx.m_num > 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 901, __FUNCTION__), 0 : 0))
;
902 return (*this)[m_vecpfx.m_num - 1];
903}
904
905
906/* If this vector has space for NELEMS additional entries, return
907 true. You usually only need to use this if you are doing your
908 own vector reallocation, for instance on an embedded vector. This
909 returns true in exactly the same circumstances that vec::reserve
910 will. */
911
912template<typename T, typename A>
913inline bool
914vec<T, A, vl_embed>::space (unsigned nelems) const
915{
916 return m_vecpfx.m_alloc - m_vecpfx.m_num >= nelems;
917}
918
919
920/* Return iteration condition and update PTR to point to the IX'th
921 element of this vector. Use this to iterate over the elements of a
922 vector as follows,
923
924 for (ix = 0; vec<T, A>::iterate (v, ix, &ptr); ix++)
925 continue; */
926
927template<typename T, typename A>
928inline bool
929vec<T, A, vl_embed>::iterate (unsigned ix, T *ptr) const
930{
931 if (ix < m_vecpfx.m_num)
932 {
933 *ptr = m_vecdata[ix];
934 return true;
935 }
936 else
937 {
938 *ptr = 0;
939 return false;
940 }
941}
942
943
944/* Return iteration condition and update *PTR to point to the
945 IX'th element of this vector. Use this to iterate over the
946 elements of a vector as follows,
947
948 for (ix = 0; v->iterate (ix, &ptr); ix++)
949 continue;
950
951 This variant is for vectors of objects. */
952
953template<typename T, typename A>
954inline bool
955vec<T, A, vl_embed>::iterate (unsigned ix, T **ptr) const
956{
957 if (ix < m_vecpfx.m_num)
958 {
959 *ptr = CONST_CAST (T *, &m_vecdata[ix])(const_cast<T *> ((&m_vecdata[ix])));
960 return true;
961 }
962 else
963 {
964 *ptr = 0;
965 return false;
966 }
967}
968
969
970/* Return a pointer to a copy of this vector. */
971
972template<typename T, typename A>
973inline vec<T, A, vl_embed> *
974vec<T, A, vl_embed>::copy (ALONE_MEM_STAT_DECLvoid) const
975{
976 vec<T, A, vl_embed> *new_vec = NULLnullptr;
977 unsigned len = length ();
978 if (len)
979 {
980 vec_alloc (new_vec, len PASS_MEM_STAT);
981 new_vec->embedded_init (len, len);
982 vec_copy_construct (new_vec->address (), m_vecdata, len);
983 }
984 return new_vec;
985}
986
987
988/* Copy the elements from SRC to the end of this vector as if by memcpy.
989 The vector must have sufficient headroom available. */
990
991template<typename T, typename A>
992inline void
993vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> &src)
994{
995 unsigned len = src.length ();
996 if (len)
997 {
998 gcc_checking_assert (space (len))((void)(!(space (len)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 998, __FUNCTION__), 0 : 0))
;
999 vec_copy_construct (end (), src.address (), len);
1000 m_vecpfx.m_num += len;
1001 }
1002}
1003
1004template<typename T, typename A>
1005inline void
1006vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> *src)
1007{
1008 if (src)
1009 splice (*src);
1010}
1011
1012
1013/* Push OBJ (a new element) onto the end of the vector. There must be
1014 sufficient space in the vector. Return a pointer to the slot
1015 where OBJ was inserted. */
1016
1017template<typename T, typename A>
1018inline T *
1019vec<T, A, vl_embed>::quick_push (const T &obj)
1020{
1021 gcc_checking_assert (space (1))((void)(!(space (1)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1021, __FUNCTION__), 0 : 0))
;
1022 T *slot = &m_vecdata[m_vecpfx.m_num++];
1023 *slot = obj;
1024 return slot;
1025}
1026
1027
1028/* Pop and return the last element off the end of the vector. */
1029
1030template<typename T, typename A>
1031inline T &
1032vec<T, A, vl_embed>::pop (void)
1033{
1034 gcc_checking_assert (length () > 0)((void)(!(length () > 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1034, __FUNCTION__), 0 : 0))
;
1035 return m_vecdata[--m_vecpfx.m_num];
1036}
1037
1038
1039/* Set the length of the vector to SIZE. The new length must be less
1040 than or equal to the current length. This is an O(1) operation. */
1041
1042template<typename T, typename A>
1043inline void
1044vec<T, A, vl_embed>::truncate (unsigned size)
1045{
1046 gcc_checking_assert (length () >= size)((void)(!(length () >= size) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1046, __FUNCTION__), 0 : 0))
;
1047 m_vecpfx.m_num = size;
1048}
1049
1050
1051/* Insert an element, OBJ, at the IXth position of this vector. There
1052 must be sufficient space. */
1053
1054template<typename T, typename A>
1055inline void
1056vec<T, A, vl_embed>::quick_insert (unsigned ix, const T &obj)
1057{
1058 gcc_checking_assert (length () < allocated ())((void)(!(length () < allocated ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1058, __FUNCTION__), 0 : 0))
;
1059 gcc_checking_assert (ix <= length ())((void)(!(ix <= length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1059, __FUNCTION__), 0 : 0))
;
1060 T *slot = &m_vecdata[ix];
1061 memmove (slot + 1, slot, (m_vecpfx.m_num++ - ix) * sizeof (T));
1062 *slot = obj;
1063}
1064
1065
1066/* Remove an element from the IXth position of this vector. Ordering of
1067 remaining elements is preserved. This is an O(N) operation due to
1068 memmove. */
1069
1070template<typename T, typename A>
1071inline void
1072vec<T, A, vl_embed>::ordered_remove (unsigned ix)
1073{
1074 gcc_checking_assert (ix < length ())((void)(!(ix < length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1074, __FUNCTION__), 0 : 0))
;
1075 T *slot = &m_vecdata[ix];
1076 memmove (slot, slot + 1, (--m_vecpfx.m_num - ix) * sizeof (T));
1077}
1078
1079
1080/* Remove elements in [START, END) from VEC for which COND holds. Ordering of
1081 remaining elements is preserved. This is an O(N) operation. */
1082
1083#define VEC_ORDERED_REMOVE_IF_FROM_TO(vec, read_index, write_index, \{ ((void)(!((end) <= (vec).length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1084, __FUNCTION__), 0 : 0)); for (read_index = write_index
= (start); read_index < (end); ++read_index) { elem_ptr =
&(vec)[read_index]; bool remove_p = (cond); if (remove_p
) continue; if (read_index != write_index) (vec)[write_index]
= (vec)[read_index]; write_index++; } if (read_index - write_index
> 0) (vec).block_remove (write_index, read_index - write_index
); }
1084 elem_ptr, start, end, cond){ ((void)(!((end) <= (vec).length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1084, __FUNCTION__), 0 : 0)); for (read_index = write_index
= (start); read_index < (end); ++read_index) { elem_ptr =
&(vec)[read_index]; bool remove_p = (cond); if (remove_p
) continue; if (read_index != write_index) (vec)[write_index]
= (vec)[read_index]; write_index++; } if (read_index - write_index
> 0) (vec).block_remove (write_index, read_index - write_index
); }
\
1085 { \
1086 gcc_assert ((end) <= (vec).length ())((void)(!((end) <= (vec).length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1086, __FUNCTION__), 0 : 0))
; \
1087 for (read_index = write_index = (start); read_index < (end); \
1088 ++read_index) \
1089 { \
1090 elem_ptr = &(vec)[read_index]; \
1091 bool remove_p = (cond); \
1092 if (remove_p) \
1093 continue; \
1094 \
1095 if (read_index != write_index) \
1096 (vec)[write_index] = (vec)[read_index]; \
1097 \
1098 write_index++; \
1099 } \
1100 \
1101 if (read_index - write_index > 0) \
1102 (vec).block_remove (write_index, read_index - write_index); \
1103 }
1104
1105
1106/* Remove elements from VEC for which COND holds. Ordering of remaining
1107 elements is preserved. This is an O(N) operation. */
1108
1109#define VEC_ORDERED_REMOVE_IF(vec, read_index, write_index, elem_ptr, \{ ((void)(!(((vec).length ()) <= ((vec)).length ()) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1110, __FUNCTION__), 0 : 0)); for (read_index = write_index
= (0); read_index < ((vec).length ()); ++read_index) { elem_ptr
= &((vec))[read_index]; bool remove_p = ((cond)); if (remove_p
) continue; if (read_index != write_index) ((vec))[write_index
] = ((vec))[read_index]; write_index++; } if (read_index - write_index
> 0) ((vec)).block_remove (write_index, read_index - write_index
); }
1110 cond){ ((void)(!(((vec).length ()) <= ((vec)).length ()) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1110, __FUNCTION__), 0 : 0)); for (read_index = write_index
= (0); read_index < ((vec).length ()); ++read_index) { elem_ptr
= &((vec))[read_index]; bool remove_p = ((cond)); if (remove_p
) continue; if (read_index != write_index) ((vec))[write_index
] = ((vec))[read_index]; write_index++; } if (read_index - write_index
> 0) ((vec)).block_remove (write_index, read_index - write_index
); }
\
1111 VEC_ORDERED_REMOVE_IF_FROM_TO ((vec), read_index, write_index, \{ ((void)(!(((vec).length ()) <= ((vec)).length ()) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1112, __FUNCTION__), 0 : 0)); for (read_index = write_index
= (0); read_index < ((vec).length ()); ++read_index) { elem_ptr
= &((vec))[read_index]; bool remove_p = ((cond)); if (remove_p
) continue; if (read_index != write_index) ((vec))[write_index
] = ((vec))[read_index]; write_index++; } if (read_index - write_index
> 0) ((vec)).block_remove (write_index, read_index - write_index
); }
1112 elem_ptr, 0, (vec).length (), (cond)){ ((void)(!(((vec).length ()) <= ((vec)).length ()) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1112, __FUNCTION__), 0 : 0)); for (read_index = write_index
= (0); read_index < ((vec).length ()); ++read_index) { elem_ptr
= &((vec))[read_index]; bool remove_p = ((cond)); if (remove_p
) continue; if (read_index != write_index) ((vec))[write_index
] = ((vec))[read_index]; write_index++; } if (read_index - write_index
> 0) ((vec)).block_remove (write_index, read_index - write_index
); }
1113
1114/* Remove an element from the IXth position of this vector. Ordering of
1115 remaining elements is destroyed. This is an O(1) operation. */
1116
1117template<typename T, typename A>
1118inline void
1119vec<T, A, vl_embed>::unordered_remove (unsigned ix)
1120{
1121 gcc_checking_assert (ix < length ())((void)(!(ix < length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1121, __FUNCTION__), 0 : 0))
;
1122 m_vecdata[ix] = m_vecdata[--m_vecpfx.m_num];
1123}
1124
1125
1126/* Remove LEN elements starting at the IXth. Ordering is retained.
1127 This is an O(N) operation due to memmove. */
1128
1129template<typename T, typename A>
1130inline void
1131vec<T, A, vl_embed>::block_remove (unsigned ix, unsigned len)
1132{
1133 gcc_checking_assert (ix + len <= length ())((void)(!(ix + len <= length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1133, __FUNCTION__), 0 : 0))
;
1134 T *slot = &m_vecdata[ix];
1135 m_vecpfx.m_num -= len;
1136 memmove (slot, slot + len, (m_vecpfx.m_num - ix) * sizeof (T));
1137}
1138
1139
1140/* Sort the contents of this vector with qsort. CMP is the comparison
1141 function to pass to qsort. */
1142
1143template<typename T, typename A>
1144inline void
1145vec<T, A, vl_embed>::qsort (int (*cmp) (const void *, const void *))qsort (int (*cmp) (const void *, const void *))
1146{
1147 if (length () > 1)
1148 gcc_qsort (address (), length (), sizeof (T), cmp);
1149}
1150
1151/* Sort the contents of this vector with qsort. CMP is the comparison
1152 function to pass to qsort. */
1153
1154template<typename T, typename A>
1155inline void
1156vec<T, A, vl_embed>::sort (int (*cmp) (const void *, const void *, void *),
1157 void *data)
1158{
1159 if (length () > 1)
1160 gcc_sort_r (address (), length (), sizeof (T), cmp, data);
1161}
1162
1163
1164/* Search the contents of the sorted vector with a binary search.
1165 CMP is the comparison function to pass to bsearch. */
1166
1167template<typename T, typename A>
1168inline T *
1169vec<T, A, vl_embed>::bsearch (const void *key,
1170 int (*compar) (const void *, const void *))
1171{
1172 const void *base = this->address ();
1173 size_t nmemb = this->length ();
1174 size_t size = sizeof (T);
1175 /* The following is a copy of glibc stdlib-bsearch.h. */
1176 size_t l, u, idx;
1177 const void *p;
1178 int comparison;
1179
1180 l = 0;
1181 u = nmemb;
1182 while (l < u)
1183 {
1184 idx = (l + u) / 2;
1185 p = (const void *) (((const char *) base) + (idx * size));
1186 comparison = (*compar) (key, p);
1187 if (comparison < 0)
1188 u = idx;
1189 else if (comparison > 0)
1190 l = idx + 1;
1191 else
1192 return (T *)const_cast<void *>(p);
1193 }
1194
1195 return NULLnullptr;
1196}
1197
1198/* Search the contents of the sorted vector with a binary search.
1199 CMP is the comparison function to pass to bsearch. */
1200
1201template<typename T, typename A>
1202inline T *
1203vec<T, A, vl_embed>::bsearch (const void *key,
1204 int (*compar) (const void *, const void *,
1205 void *), void *data)
1206{
1207 const void *base = this->address ();
1208 size_t nmemb = this->length ();
1209 size_t size = sizeof (T);
1210 /* The following is a copy of glibc stdlib-bsearch.h. */
1211 size_t l, u, idx;
1212 const void *p;
1213 int comparison;
1214
1215 l = 0;
1216 u = nmemb;
1217 while (l < u)
1218 {
1219 idx = (l + u) / 2;
1220 p = (const void *) (((const char *) base) + (idx * size));
1221 comparison = (*compar) (key, p, data);
1222 if (comparison < 0)
1223 u = idx;
1224 else if (comparison > 0)
1225 l = idx + 1;
1226 else
1227 return (T *)const_cast<void *>(p);
1228 }
1229
1230 return NULLnullptr;
1231}
1232
1233/* Return true if SEARCH is an element of V. Note that this is O(N) in the
1234 size of the vector and so should be used with care. */
1235
1236template<typename T, typename A>
1237inline bool
1238vec<T, A, vl_embed>::contains (const T &search) const
1239{
1240 unsigned int len = length ();
1241 for (unsigned int i = 0; i < len; i++)
1242 if ((*this)[i] == search)
1243 return true;
1244
1245 return false;
1246}
1247
1248/* Find and return the first position in which OBJ could be inserted
1249 without changing the ordering of this vector. LESSTHAN is a
1250 function that returns true if the first argument is strictly less
1251 than the second. */
1252
1253template<typename T, typename A>
1254unsigned
1255vec<T, A, vl_embed>::lower_bound (T obj, bool (*lessthan)(const T &, const T &))
1256 const
1257{
1258 unsigned int len = length ();
1259 unsigned int half, middle;
1260 unsigned int first = 0;
1261 while (len > 0)
1262 {
1263 half = len / 2;
1264 middle = first;
1265 middle += half;
1266 T middle_elem = (*this)[middle];
1267 if (lessthan (middle_elem, obj))
1268 {
1269 first = middle;
1270 ++first;
1271 len = len - half - 1;
1272 }
1273 else
1274 len = half;
1275 }
1276 return first;
1277}
1278
1279
1280/* Return the number of bytes needed to embed an instance of an
1281 embeddable vec inside another data structure.
1282
1283 Use these methods to determine the required size and initialization
1284 of a vector V of type T embedded within another structure (as the
1285 final member):
1286
1287 size_t vec<T, A, vl_embed>::embedded_size (unsigned alloc);
1288 void v->embedded_init (unsigned alloc, unsigned num);
1289
1290 These allow the caller to perform the memory allocation. */
1291
1292template<typename T, typename A>
1293inline size_t
1294vec<T, A, vl_embed>::embedded_size (unsigned alloc)
1295{
1296 struct alignas (T) U { char data[sizeof (T)]; };
1297 typedef vec<U, A, vl_embed> vec_embedded;
1298 typedef typename std::conditional<std::is_standard_layout<T>::value,
1299 vec, vec_embedded>::type vec_stdlayout;
1300 static_assert (sizeof (vec_stdlayout) == sizeof (vec), "");
1301 static_assert (alignof (vec_stdlayout) == alignof (vec), "");
1302 return offsetof (vec_stdlayout, m_vecdata)__builtin_offsetof(vec_stdlayout, m_vecdata) + alloc * sizeof (T);
1303}
1304
1305
1306/* Initialize the vector to contain room for ALLOC elements and
1307 NUM active elements. */
1308
1309template<typename T, typename A>
1310inline void
1311vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num, unsigned aut)
1312{
1313 m_vecpfx.m_alloc = alloc;
1314 m_vecpfx.m_using_auto_storage = aut;
1315 m_vecpfx.m_num = num;
1316}
1317
1318
1319/* Grow the vector to a specific length. LEN must be as long or longer than
1320 the current length. The new elements are uninitialized. */
1321
1322template<typename T, typename A>
1323inline void
1324vec<T, A, vl_embed>::quick_grow (unsigned len)
1325{
1326 gcc_checking_assert (length () <= len && len <= m_vecpfx.m_alloc)((void)(!(length () <= len && len <= m_vecpfx.m_alloc
) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1326, __FUNCTION__), 0 : 0))
;
1327 m_vecpfx.m_num = len;
1328}
1329
1330
1331/* Grow the vector to a specific length. LEN must be as long or longer than
1332 the current length. The new elements are initialized to zero. */
1333
1334template<typename T, typename A>
1335inline void
1336vec<T, A, vl_embed>::quick_grow_cleared (unsigned len)
1337{
1338 unsigned oldlen = length ();
1339 size_t growby = len - oldlen;
1340 quick_grow (len);
1341 if (growby != 0)
1342 vec_default_construct (address () + oldlen, growby);
1343}
1344
1345/* Garbage collection support for vec<T, A, vl_embed>. */
1346
1347template<typename T>
1348void
1349gt_ggc_mx (vec<T, va_gc> *v)
1350{
1351 extern void gt_ggc_mx (T &);
1352 for (unsigned i = 0; i < v->length (); i++)
1353 gt_ggc_mx ((*v)[i]);
1354}
1355
1356template<typename T>
1357void
1358gt_ggc_mx (vec<T, va_gc_atomic, vl_embed> *v ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
1359{
1360 /* Nothing to do. Vectors of atomic types wrt GC do not need to
1361 be traversed. */
1362}
1363
1364
1365/* PCH support for vec<T, A, vl_embed>. */
1366
1367template<typename T, typename A>
1368void
1369gt_pch_nx (vec<T, A, vl_embed> *v)
1370{
1371 extern void gt_pch_nx (T &);
1372 for (unsigned i = 0; i < v->length (); i++)
1373 gt_pch_nx ((*v)[i]);
1374}
1375
1376template<typename T, typename A>
1377void
1378gt_pch_nx (vec<T *, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
1379{
1380 for (unsigned i = 0; i < v->length (); i++)
1381 op (&((*v)[i]), cookie);
1382}
1383
1384template<typename T, typename A>
1385void
1386gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
1387{
1388 extern void gt_pch_nx (T *, gt_pointer_operator, void *);
1389 for (unsigned i = 0; i < v->length (); i++)
1390 gt_pch_nx (&((*v)[i]), op, cookie);
1391}
1392
1393
1394/* Space efficient vector. These vectors can grow dynamically and are
1395 allocated together with their control data. They are suited to be
1396 included in data structures. Prior to initial allocation, they
1397 only take a single word of storage.
1398
1399 These vectors are implemented as a pointer to an embeddable vector.
1400 The semantics allow for this pointer to be NULL to represent empty
1401 vectors. This way, empty vectors occupy minimal space in the
1402 structure containing them.
1403
1404 Properties:
1405
1406 - The whole vector and control data are allocated in a single
1407 contiguous block.
1408 - The whole vector may be re-allocated.
1409 - Vector data may grow and shrink.
1410 - Access and manipulation requires a pointer test and
1411 indirection.
1412 - It requires 1 word of storage (prior to vector allocation).
1413
1414
1415 Limitations:
1416
1417 These vectors must be PODs because they are stored in unions.
1418 (http://en.wikipedia.org/wiki/Plain_old_data_structures).
1419 As long as we use C++03, we cannot have constructors nor
1420 destructors in classes that are stored in unions. */
1421
1422template<typename T>
1423struct vec<T, va_heap, vl_ptr>
1424{
1425public:
1426 /* Memory allocation and deallocation for the embedded vector.
1427 Needed because we cannot have proper ctors/dtors defined. */
1428 void create (unsigned nelems CXX_MEM_STAT_INFO);
1429 void release (void);
1430
1431 /* Vector operations. */
1432 bool exists (void) const
1433 { return m_vec != NULLnullptr; }
1434
1435 bool is_empty (void) const
1436 { return m_vec ? m_vec->is_empty () : true; }
1437
1438 unsigned length (void) const
1439 { return m_vec ? m_vec->length () : 0; }
1440
1441 T *address (void)
1442 { return m_vec ? m_vec->m_vecdata : NULLnullptr; }
1443
1444 const T *address (void) const
1445 { return m_vec ? m_vec->m_vecdata : NULLnullptr; }
1446
1447 T *begin () { return address (); }
1448 const T *begin () const { return address (); }
1449 T *end () { return begin () + length (); }
1450 const T *end () const { return begin () + length (); }
1451 const T &operator[] (unsigned ix) const
1452 { return (*m_vec)[ix]; }
1453
1454 bool operator!=(const vec &other) const
1455 { return !(*this == other); }
1456
1457 bool operator==(const vec &other) const
1458 { return address () == other.address (); }
1459
1460 T &operator[] (unsigned ix)
1461 { return (*m_vec)[ix]; }
1462
1463 T &last (void)
1464 { return m_vec->last (); }
1465
1466 bool space (int nelems) const
1467 { return m_vec ? m_vec->space (nelems) : nelems == 0; }
1468
1469 bool iterate (unsigned ix, T *p) const;
1470 bool iterate (unsigned ix, T **p) const;
1471 vec copy (ALONE_CXX_MEM_STAT_INFO) const;
1472 bool reserve (unsigned, bool = false CXX_MEM_STAT_INFO);
1473 bool reserve_exact (unsigned CXX_MEM_STAT_INFO);
1474 void splice (const vec &);
1475 void safe_splice (const vec & CXX_MEM_STAT_INFO);
1476 T *quick_push (const T &);
1477 T *safe_push (const T &CXX_MEM_STAT_INFO);
1478 T &pop (void);
1479 void truncate (unsigned);
1480 void safe_grow (unsigned, bool = false CXX_MEM_STAT_INFO);
1481 void safe_grow_cleared (unsigned, bool = false CXX_MEM_STAT_INFO);
1482 void quick_grow (unsigned);
1483 void quick_grow_cleared (unsigned);
1484 void quick_insert (unsigned, const T &);
1485 void safe_insert (unsigned, const T & CXX_MEM_STAT_INFO);
1486 void ordered_remove (unsigned);
1487 void unordered_remove (unsigned);
1488 void block_remove (unsigned, unsigned);
1489 void qsort (int (*) (const void *, const void *))qsort (int (*) (const void *, const void *));
1490 void sort (int (*) (const void *, const void *, void *), void *);
1491 T *bsearch (const void *key, int (*compar)(const void *, const void *));
1492 T *bsearch (const void *key,
1493 int (*compar)(const void *, const void *, void *), void *);
1494 unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
1495 bool contains (const T &search) const;
1496 void reverse (void);
1497
1498 bool using_auto_storage () const;
1499
1500 /* FIXME - This field should be private, but we need to cater to
1501 compilers that have stricter notions of PODness for types. */
1502 vec<T, va_heap, vl_embed> *m_vec;
1503};
1504
1505
1506/* auto_vec is a subclass of vec that automatically manages creating and
1507 releasing the internal vector. If N is non zero then it has N elements of
1508 internal storage. The default is no internal storage, and you probably only
1509 want to ask for internal storage for vectors on the stack because if the
1510 size of the vector is larger than the internal storage that space is wasted.
1511 */
1512template<typename T, size_t N = 0>
1513class auto_vec : public vec<T, va_heap>
1514{
1515public:
1516 auto_vec ()
1517 {
1518 m_auto.embedded_init (MAX (N, 2)((N) > (2) ? (N) : (2)), 0, 1);
1519 this->m_vec = &m_auto;
1520 }
1521
1522 auto_vec (size_t s)
1523 {
1524 if (s > N)
1525 {
1526 this->create (s);
1527 return;
1528 }
1529
1530 m_auto.embedded_init (MAX (N, 2)((N) > (2) ? (N) : (2)), 0, 1);
1531 this->m_vec = &m_auto;
1532 }
1533
1534 ~auto_vec ()
1535 {
1536 this->release ();
1537 }
1538
1539private:
1540 vec<T, va_heap, vl_embed> m_auto;
1541 T m_data[MAX (N - 1, 1)((N - 1) > (1) ? (N - 1) : (1))];
1542};
1543
1544/* auto_vec is a sub class of vec whose storage is released when it is
1545 destroyed. */
1546template<typename T>
1547class auto_vec<T, 0> : public vec<T, va_heap>
1548{
1549public:
1550 auto_vec () { this->m_vec = NULLnullptr; }
1551 auto_vec (size_t n) { this->create (n); }
1552 ~auto_vec () { this->release (); }
1553
1554 auto_vec (vec<T, va_heap>&& r)
1555 {
1556 gcc_assert (!r.using_auto_storage ())((void)(!(!r.using_auto_storage ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1556, __FUNCTION__), 0 : 0))
;
1557 this->m_vec = r.m_vec;
1558 r.m_vec = NULLnullptr;
1559 }
1560 auto_vec& operator= (vec<T, va_heap>&& r)
1561 {
1562 gcc_assert (!r.using_auto_storage ())((void)(!(!r.using_auto_storage ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1562, __FUNCTION__), 0 : 0))
;
1563 this->release ();
1564 this->m_vec = r.m_vec;
1565 r.m_vec = NULLnullptr;
1566 return *this;
1567 }
1568};
1569
1570
1571/* Allocate heap memory for pointer V and create the internal vector
1572 with space for NELEMS elements. If NELEMS is 0, the internal
1573 vector is initialized to empty. */
1574
1575template<typename T>
1576inline void
1577vec_alloc (vec<T> *&v, unsigned nelems CXX_MEM_STAT_INFO)
1578{
1579 v = new vec<T>;
1580 v->create (nelems PASS_MEM_STAT);
1581}
1582
1583
1584/* A subclass of auto_vec <char *> that frees all of its elements on
1585 deletion. */
1586
1587class auto_string_vec : public auto_vec <char *>
1588{
1589 public:
1590 ~auto_string_vec ();
1591};
1592
1593/* A subclass of auto_vec <T *> that deletes all of its elements on
1594 destruction.
1595
1596 This is a crude way for a vec to "own" the objects it points to
1597 and clean up automatically.
1598
1599 For example, no attempt is made to delete elements when an item
1600 within the vec is overwritten.
1601
1602 We can't rely on gnu::unique_ptr within a container,
1603 since we can't rely on move semantics in C++98. */
1604
1605template <typename T>
1606class auto_delete_vec : public auto_vec <T *>
1607{
1608 public:
1609 auto_delete_vec () {}
1610 auto_delete_vec (size_t s) : auto_vec <T *> (s) {}
1611
1612 ~auto_delete_vec ();
1613
1614private:
1615 DISABLE_COPY_AND_ASSIGN(auto_delete_vec)auto_delete_vec (const auto_delete_vec&) = delete; void operator
= (const auto_delete_vec &) = delete
;
1616};
1617
1618/* Conditionally allocate heap memory for VEC and its internal vector. */
1619
1620template<typename T>
1621inline void
1622vec_check_alloc (vec<T, va_heap> *&vec, unsigned nelems CXX_MEM_STAT_INFO)
1623{
1624 if (!vec)
1625 vec_alloc (vec, nelems PASS_MEM_STAT);
1626}
1627
1628
1629/* Free the heap memory allocated by vector V and set it to NULL. */
1630
1631template<typename T>
1632inline void
1633vec_free (vec<T> *&v)
1634{
1635 if (v == NULLnullptr)
1636 return;
1637
1638 v->release ();
1639 delete v;
1640 v = NULLnullptr;
1641}
1642
1643
1644/* Return iteration condition and update PTR to point to the IX'th
1645 element of this vector. Use this to iterate over the elements of a
1646 vector as follows,
1647
1648 for (ix = 0; v.iterate (ix, &ptr); ix++)
1649 continue; */
1650
1651template<typename T>
1652inline bool
1653vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T *ptr) const
1654{
1655 if (m_vec)
1656 return m_vec->iterate (ix, ptr);
1657 else
1658 {
1659 *ptr = 0;
1660 return false;
1661 }
1662}
1663
1664
1665/* Return iteration condition and update *PTR to point to the
1666 IX'th element of this vector. Use this to iterate over the
1667 elements of a vector as follows,
1668
1669 for (ix = 0; v->iterate (ix, &ptr); ix++)
1670 continue;
1671
1672 This variant is for vectors of objects. */
1673
1674template<typename T>
1675inline bool
1676vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T **ptr) const
1677{
1678 if (m_vec)
1679 return m_vec->iterate (ix, ptr);
1680 else
1681 {
1682 *ptr = 0;
1683 return false;
1684 }
1685}
1686
1687
1688/* Convenience macro for forward iteration. */
1689#define FOR_EACH_VEC_ELT(V, I, P)for (I = 0; (V).iterate ((I), &(P)); ++(I)) \
1690 for (I = 0; (V).iterate ((I), &(P)); ++(I))
1691
1692#define FOR_EACH_VEC_SAFE_ELT(V, I, P)for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I)) \
1693 for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I))
1694
1695/* Likewise, but start from FROM rather than 0. */
1696#define FOR_EACH_VEC_ELT_FROM(V, I, P, FROM)for (I = (FROM); (V).iterate ((I), &(P)); ++(I)) \
1697 for (I = (FROM); (V).iterate ((I), &(P)); ++(I))
1698
1699/* Convenience macro for reverse iteration. */
1700#define FOR_EACH_VEC_ELT_REVERSE(V, I, P)for (I = (V).length () - 1; (V).iterate ((I), &(P)); (I)--
)
\
1701 for (I = (V).length () - 1; \
1702 (V).iterate ((I), &(P)); \
1703 (I)--)
1704
1705#define FOR_EACH_VEC_SAFE_ELT_REVERSE(V, I, P)for (I = vec_safe_length (V) - 1; vec_safe_iterate ((V), (I),
&(P)); (I)--)
\
1706 for (I = vec_safe_length (V) - 1; \
1707 vec_safe_iterate ((V), (I), &(P)); \
1708 (I)--)
1709
1710/* auto_string_vec's dtor, freeing all contained strings, automatically
1711 chaining up to ~auto_vec <char *>, which frees the internal buffer. */
1712
1713inline
1714auto_string_vec::~auto_string_vec ()
1715{
1716 int i;
1717 char *str;
1718 FOR_EACH_VEC_ELT (*this, i, str)for (i = 0; (*this).iterate ((i), &(str)); ++(i))
1719 free (str);
1720}
1721
1722/* auto_delete_vec's dtor, deleting all contained items, automatically
1723 chaining up to ~auto_vec <T*>, which frees the internal buffer. */
1724
1725template <typename T>
1726inline
1727auto_delete_vec<T>::~auto_delete_vec ()
1728{
1729 int i;
1730 T *item;
1731 FOR_EACH_VEC_ELT (*this, i, item)for (i = 0; (*this).iterate ((i), &(item)); ++(i))
1732 delete item;
1733}
1734
1735
1736/* Return a copy of this vector. */
1737
1738template<typename T>
1739inline vec<T, va_heap, vl_ptr>
1740vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECLvoid) const
1741{
1742 vec<T, va_heap, vl_ptr> new_vec = vNULL;
1743 if (length ())
1744 new_vec.m_vec = m_vec->copy (ALONE_PASS_MEM_STAT);
1745 return new_vec;
1746}
1747
1748
1749/* Ensure that the vector has at least RESERVE slots available (if
1750 EXACT is false), or exactly RESERVE slots available (if EXACT is
1751 true).
1752
1753 This may create additional headroom if EXACT is false.
1754
1755 Note that this can cause the embedded vector to be reallocated.
1756 Returns true iff reallocation actually occurred. */
1757
1758template<typename T>
1759inline bool
1760vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL)
1761{
1762 if (space (nelems))
1763 return false;
1764
1765 /* For now play a game with va_heap::reserve to hide our auto storage if any,
1766 this is necessary because it doesn't have enough information to know the
1767 embedded vector is in auto storage, and so should not be freed. */
1768 vec<T, va_heap, vl_embed> *oldvec = m_vec;
1769 unsigned int oldsize = 0;
1770 bool handle_auto_vec = m_vec && using_auto_storage ();
1771 if (handle_auto_vec)
1772 {
1773 m_vec = NULLnullptr;
1774 oldsize = oldvec->length ();
1775 nelems += oldsize;
1776 }
1777
1778 va_heap::reserve (m_vec, nelems, exact PASS_MEM_STAT);
1779 if (handle_auto_vec)
1780 {
1781 vec_copy_construct (m_vec->address (), oldvec->address (), oldsize);
1782 m_vec->m_vecpfx.m_num = oldsize;
1783 }
1784
1785 return true;
1786}
1787
1788
1789/* Ensure that this vector has exactly NELEMS slots available. This
1790 will not create additional headroom. Note this can cause the
1791 embedded vector to be reallocated. Returns true iff reallocation
1792 actually occurred. */
1793
1794template<typename T>
1795inline bool
1796vec<T, va_heap, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL)
1797{
1798 return reserve (nelems, true PASS_MEM_STAT);
1799}
1800
1801
1802/* Create the internal vector and reserve NELEMS for it. This is
1803 exactly like vec::reserve, but the internal vector is
1804 unconditionally allocated from scratch. The old one, if it
1805 existed, is lost. */
1806
1807template<typename T>
1808inline void
1809vec<T, va_heap, vl_ptr>::create (unsigned nelems MEM_STAT_DECL)
1810{
1811 m_vec = NULLnullptr;
1812 if (nelems > 0)
1813 reserve_exact (nelems PASS_MEM_STAT);
1814}
1815
1816
1817/* Free the memory occupied by the embedded vector. */
1818
1819template<typename T>
1820inline void
1821vec<T, va_heap, vl_ptr>::release (void)
1822{
1823 if (!m_vec)
1824 return;
1825
1826 if (using_auto_storage ())
1827 {
1828 m_vec->m_vecpfx.m_num = 0;
1829 return;
1830 }
1831
1832 va_heap::release (m_vec);
1833}
1834
1835/* Copy the elements from SRC to the end of this vector as if by memcpy.
1836 SRC and this vector must be allocated with the same memory
1837 allocation mechanism. This vector is assumed to have sufficient
1838 headroom available. */
1839
1840template<typename T>
1841inline void
1842vec<T, va_heap, vl_ptr>::splice (const vec<T, va_heap, vl_ptr> &src)
1843{
1844 if (src.length ())
1845 m_vec->splice (*(src.m_vec));
1846}
1847
1848
1849/* Copy the elements in SRC to the end of this vector as if by memcpy.
1850 SRC and this vector must be allocated with the same mechanism.
1851 If there is not enough headroom in this vector, it will be reallocated
1852 as needed. */
1853
1854template<typename T>
1855inline void
1856vec<T, va_heap, vl_ptr>::safe_splice (const vec<T, va_heap, vl_ptr> &src
1857 MEM_STAT_DECL)
1858{
1859 if (src.length ())
1860 {
1861 reserve_exact (src.length ());
1862 splice (src);
1863 }
1864}
1865
1866
1867/* Push OBJ (a new element) onto the end of the vector. There must be
1868 sufficient space in the vector. Return a pointer to the slot
1869 where OBJ was inserted. */
1870
1871template<typename T>
1872inline T *
1873vec<T, va_heap, vl_ptr>::quick_push (const T &obj)
1874{
1875 return m_vec->quick_push (obj);
1876}
1877
1878
1879/* Push a new element OBJ onto the end of this vector. Reallocates
1880 the embedded vector, if needed. Return a pointer to the slot where
1881 OBJ was inserted. */
1882
1883template<typename T>
1884inline T *
1885vec<T, va_heap, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL)
1886{
1887 reserve (1, false PASS_MEM_STAT);
1888 return quick_push (obj);
1889}
1890
1891
1892/* Pop and return the last element off the end of the vector. */
1893
1894template<typename T>
1895inline T &
1896vec<T, va_heap, vl_ptr>::pop (void)
1897{
1898 return m_vec->pop ();
1899}
1900
1901
1902/* Set the length of the vector to LEN. The new length must be less
1903 than or equal to the current length. This is an O(1) operation. */
1904
1905template<typename T>
1906inline void
1907vec<T, va_heap, vl_ptr>::truncate (unsigned size)
1908{
1909 if (m_vec)
1910 m_vec->truncate (size);
1911 else
1912 gcc_checking_assert (size == 0)((void)(!(size == 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1912, __FUNCTION__), 0 : 0))
;
1913}
1914
1915
1916/* Grow the vector to a specific length. LEN must be as long or
1917 longer than the current length. The new elements are
1918 uninitialized. Reallocate the internal vector, if needed. */
1919
1920template<typename T>
1921inline void
1922vec<T, va_heap, vl_ptr>::safe_grow (unsigned len, bool exact MEM_STAT_DECL)
1923{
1924 unsigned oldlen = length ();
1925 gcc_checking_assert (oldlen <= len)((void)(!(oldlen <= len) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1925, __FUNCTION__), 0 : 0))
;
1926 reserve (len - oldlen, exact PASS_MEM_STAT);
1927 if (m_vec)
1928 m_vec->quick_grow (len);
1929 else
1930 gcc_checking_assert (len == 0)((void)(!(len == 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1930, __FUNCTION__), 0 : 0))
;
1931}
1932
1933
1934/* Grow the embedded vector to a specific length. LEN must be as
1935 long or longer than the current length. The new elements are
1936 initialized to zero. Reallocate the internal vector, if needed. */
1937
1938template<typename T>
1939inline void
1940vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len, bool exact
1941 MEM_STAT_DECL)
1942{
1943 unsigned oldlen = length ();
1944 size_t growby = len - oldlen;
1945 safe_grow (len, exact PASS_MEM_STAT);
1946 if (growby != 0)
1947 vec_default_construct (address () + oldlen, growby);
1948}
1949
1950
1951/* Same as vec::safe_grow but without reallocation of the internal vector.
1952 If the vector cannot be extended, a runtime assertion will be triggered. */
1953
1954template<typename T>
1955inline void
1956vec<T, va_heap, vl_ptr>::quick_grow (unsigned len)
1957{
1958 gcc_checking_assert (m_vec)((void)(!(m_vec) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1958, __FUNCTION__), 0 : 0))
;
1959 m_vec->quick_grow (len);
1960}
1961
1962
1963/* Same as vec::quick_grow_cleared but without reallocation of the
1964 internal vector. If the vector cannot be extended, a runtime
1965 assertion will be triggered. */
1966
1967template<typename T>
1968inline void
1969vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len)
1970{
1971 gcc_checking_assert (m_vec)((void)(!(m_vec) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1971, __FUNCTION__), 0 : 0))
;
1972 m_vec->quick_grow_cleared (len);
1973}
1974
1975
1976/* Insert an element, OBJ, at the IXth position of this vector. There
1977 must be sufficient space. */
1978
1979template<typename T>
1980inline void
1981vec<T, va_heap, vl_ptr>::quick_insert (unsigned ix, const T &obj)
1982{
1983 m_vec->quick_insert (ix, obj);
1984}
1985
1986
1987/* Insert an element, OBJ, at the IXth position of the vector.
1988 Reallocate the embedded vector, if necessary. */
1989
1990template<typename T>
1991inline void
1992vec<T, va_heap, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL)
1993{
1994 reserve (1, false PASS_MEM_STAT);
1995 quick_insert (ix, obj);
1996}
1997
1998
1999/* Remove an element from the IXth position of this vector. Ordering of
2000 remaining elements is preserved. This is an O(N) operation due to
2001 a memmove. */
2002
2003template<typename T>
2004inline void
2005vec<T, va_heap, vl_ptr>::ordered_remove (unsigned ix)
2006{
2007 m_vec->ordered_remove (ix);
2008}
2009
2010
2011/* Remove an element from the IXth position of this vector. Ordering
2012 of remaining elements is destroyed. This is an O(1) operation. */
2013
2014template<typename T>
2015inline void
2016vec<T, va_heap, vl_ptr>::unordered_remove (unsigned ix)
2017{
2018 m_vec->unordered_remove (ix);
2019}
2020
2021
2022/* Remove LEN elements starting at the IXth. Ordering is retained.
2023 This is an O(N) operation due to memmove. */
2024
2025template<typename T>
2026inline void
2027vec<T, va_heap, vl_ptr>::block_remove (unsigned ix, unsigned len)
2028{
2029 m_vec->block_remove (ix, len);
2030}
2031
2032
2033/* Sort the contents of this vector with qsort. CMP is the comparison
2034 function to pass to qsort. */
2035
2036template<typename T>
2037inline void
2038vec<T, va_heap, vl_ptr>::qsort (int (*cmp) (const void *, const void *))qsort (int (*cmp) (const void *, const void *))
2039{
2040 if (m_vec)
2041 m_vec->qsort (cmp)qsort (cmp);
2042}
2043
2044/* Sort the contents of this vector with qsort. CMP is the comparison
2045 function to pass to qsort. */
2046
2047template<typename T>
2048inline void
2049vec<T, va_heap, vl_ptr>::sort (int (*cmp) (const void *, const void *,
2050 void *), void *data)
2051{
2052 if (m_vec)
2053 m_vec->sort (cmp, data);
2054}
2055
2056
2057/* Search the contents of the sorted vector with a binary search.
2058 CMP is the comparison function to pass to bsearch. */
2059
2060template<typename T>
2061inline T *
2062vec<T, va_heap, vl_ptr>::bsearch (const void *key,
2063 int (*cmp) (const void *, const void *))
2064{
2065 if (m_vec)
2066 return m_vec->bsearch (key, cmp);
2067 return NULLnullptr;
2068}
2069
2070/* Search the contents of the sorted vector with a binary search.
2071 CMP is the comparison function to pass to bsearch. */
2072
2073template<typename T>
2074inline T *
2075vec<T, va_heap, vl_ptr>::bsearch (const void *key,
2076 int (*cmp) (const void *, const void *,
2077 void *), void *data)
2078{
2079 if (m_vec)
2080 return m_vec->bsearch (key, cmp, data);
2081 return NULLnullptr;
2082}
2083
2084
2085/* Find and return the first position in which OBJ could be inserted
2086 without changing the ordering of this vector. LESSTHAN is a
2087 function that returns true if the first argument is strictly less
2088 than the second. */
2089
2090template<typename T>
2091inline unsigned
2092vec<T, va_heap, vl_ptr>::lower_bound (T obj,
2093 bool (*lessthan)(const T &, const T &))
2094 const
2095{
2096 return m_vec ? m_vec->lower_bound (obj, lessthan) : 0;
2097}
2098
2099/* Return true if SEARCH is an element of V. Note that this is O(N) in the
2100 size of the vector and so should be used with care. */
2101
2102template<typename T>
2103inline bool
2104vec<T, va_heap, vl_ptr>::contains (const T &search) const
2105{
2106 return m_vec ? m_vec->contains (search) : false;
2107}
2108
2109/* Reverse content of the vector. */
2110
2111template<typename T>
2112inline void
2113vec<T, va_heap, vl_ptr>::reverse (void)
2114{
2115 unsigned l = length ();
2116 T *ptr = address ();
2117
2118 for (unsigned i = 0; i < l / 2; i++)
2119 std::swap (ptr[i], ptr[l - i - 1]);
2120}
2121
2122template<typename T>
2123inline bool
2124vec<T, va_heap, vl_ptr>::using_auto_storage () const
2125{
2126 return m_vec->m_vecpfx.m_using_auto_storage;
2127}
2128
2129/* Release VEC and call release of all element vectors. */
2130
2131template<typename T>
2132inline void
2133release_vec_vec (vec<vec<T> > &vec)
2134{
2135 for (unsigned i = 0; i < vec.length (); i++)
2136 vec[i].release ();
2137
2138 vec.release ();
2139}
2140
2141// Provide a subset of the std::span functionality. (We can't use std::span
2142// itself because it's a C++20 feature.)
2143//
2144// In addition, provide an invalid value that is distinct from all valid
2145// sequences (including the empty sequence). This can be used to return
2146// failure without having to use std::optional.
2147//
2148// There is no operator bool because it would be ambiguous whether it is
2149// testing for a valid value or an empty sequence.
2150template<typename T>
2151class array_slice
2152{
2153 template<typename OtherT> friend class array_slice;
2154
2155public:
2156 using value_type = T;
2157 using iterator = T *;
2158 using const_iterator = const T *;
2159
2160 array_slice () : m_base (nullptr), m_size (0) {}
2161
2162 template<typename OtherT>
2163 array_slice (array_slice<OtherT> other)
2164 : m_base (other.m_base), m_size (other.m_size) {}
2165
2166 array_slice (iterator base, unsigned int size)
2167 : m_base (base), m_size (size) {}
2168
2169 template<size_t N>
2170 array_slice (T (&array)[N]) : m_base (array), m_size (N) {}
2171
2172 template<typename OtherT>
2173 array_slice (const vec<OtherT> &v)
2174 : m_base (v.address ()), m_size (v.length ()) {}
2175
2176 iterator begin () { return m_base; }
2177 iterator end () { return m_base + m_size; }
2178
2179 const_iterator begin () const { return m_base; }
2180 const_iterator end () const { return m_base + m_size; }
2181
2182 value_type &front ();
2183 value_type &back ();
2184 value_type &operator[] (unsigned int i);
2185
2186 const value_type &front () const;
2187 const value_type &back () const;
2188 const value_type &operator[] (unsigned int i) const;
2189
2190 size_t size () const { return m_size; }
2191 size_t size_bytes () const { return m_size * sizeof (T); }
2192 bool empty () const { return m_size == 0; }
2193
2194 // An invalid array_slice that represents a failed operation. This is
2195 // distinct from an empty slice, which is a valid result in some contexts.
2196 static array_slice invalid () { return { nullptr, ~0U }; }
2197
2198 // True if the array is valid, false if it is an array like INVALID.
2199 bool is_valid () const { return m_base || m_size == 0; }
2200
2201private:
2202 iterator m_base;
2203 unsigned int m_size;
2204};
2205
2206template<typename T>
2207inline typename array_slice<T>::value_type &
2208array_slice<T>::front ()
2209{
2210 gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2210, __FUNCTION__), 0 : 0))
;
2211 return m_base[0];
2212}
2213
2214template<typename T>
2215inline const typename array_slice<T>::value_type &
2216array_slice<T>::front () const
2217{
2218 gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2218, __FUNCTION__), 0 : 0))
;
2219 return m_base[0];
2220}
2221
2222template<typename T>
2223inline typename array_slice<T>::value_type &
2224array_slice<T>::back ()
2225{
2226 gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2226, __FUNCTION__), 0 : 0))
;
2227 return m_base[m_size - 1];
2228}
2229
2230template<typename T>
2231inline const typename array_slice<T>::value_type &
2232array_slice<T>::back () const
2233{
2234 gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2234, __FUNCTION__), 0 : 0))
;
2235 return m_base[m_size - 1];
2236}
2237
2238template<typename T>
2239inline typename array_slice<T>::value_type &
2240array_slice<T>::operator[] (unsigned int i)
2241{
2242 gcc_checking_assert (i < m_size)((void)(!(i < m_size) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2242, __FUNCTION__), 0 : 0))
;
2243 return m_base[i];
2244}
2245
2246template<typename T>
2247inline const typename array_slice<T>::value_type &
2248array_slice<T>::operator[] (unsigned int i) const
2249{
2250 gcc_checking_assert (i < m_size)((void)(!(i < m_size) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2250, __FUNCTION__), 0 : 0))
;
2251 return m_base[i];
2252}
2253
2254template<typename T>
2255array_slice<T>
2256make_array_slice (T *base, unsigned int size)
2257{
2258 return array_slice<T> (base, size);
2259}
2260
2261#if (GCC_VERSION(4 * 1000 + 2) >= 3000)
2262# pragma GCC poison m_vec m_vecpfx m_vecdata
2263#endif
2264
2265#endif // GCC_VEC_H