Bug Summary

File:build/gcc/vec.h
Warning:line 814, 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 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/objdir/gcc -resource-dir /usr/lib64/clang/13.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/11/../../../../include/c++/11 -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/11/../../../../include/c++/11/x86_64-suse-linux -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/11/../../../../include/c++/11/backward -internal-isystem /usr/lib64/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/11/../../../../x86_64-suse-linux/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 -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/objdir/clang-static-analyzer/2021-11-20-133755-20252-1/report-jw7YQR.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 ((VAR_P (inner)(((enum tree_code) (inner)->base.code) == VAR_DECL)
1447 || TREE_CODE (inner)((enum tree_code) (inner)->base.code) == PARM_DECL
1448 || TREE_CODE (inner)((enum tree_code) (inner)->base.code) == RESULT_DECL)
1449 && DECL_REGISTER (inner)((contains_struct_check ((inner), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1449, __FUNCTION__))->decl_common.decl_flag_0)
)
1450 return;
1451 base = inner;
1452 /* If BASE is a fixed size automatic variable or
1453 global variable defined in the current TU and bitpos
1454 fits, don't instrument anything. */
1455 poly_int64 base_size;
1456 if (offset == NULL_TREE(tree) nullptr
1457 && maybe_ne (bitpos, 0)
1458 && (VAR_P (base)(((enum tree_code) (base)->base.code) == VAR_DECL)
1459 || TREE_CODE (base)((enum tree_code) (base)->base.code) == PARM_DECL
1460 || TREE_CODE (base)((enum tree_code) (base)->base.code) == RESULT_DECL)
1461 && 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"
, 1461, __FUNCTION__))->decl_common.size)
, &base_size)
1462 && known_ge (base_size, bitpos)(!maybe_lt (base_size, bitpos))
1463 && (!is_global_var (base) || decl_binds_to_current_def_p (base)))
1464 return;
1465 }
1466 else if (TREE_CODE (inner)((enum tree_code) (inner)->base.code) == MEM_REF)
1467 {
1468 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"
, 1468, __FUNCTION__)))))
;
1469 if (TREE_CODE (base)((enum tree_code) (base)->base.code) == ADDR_EXPR
1470 && 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"
, 1470, __FUNCTION__))))))->base.code))] == tcc_declaration
)
1471 && !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"
, 1471, __FUNCTION__))))))->base.addressable_flag)
1472 && !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"
, 1472, __FUNCTION__)))))
))
1473 return;
1474 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"
, 1474, __FUNCTION__)))))
;
1475 if (integer_zerop (moff))
1476 moff = NULL_TREE(tree) nullptr;
1477 }
1478 else
1479 return;
1480
1481 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"
, 1481, __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"
, 1481, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
)
&& !DECL_P (base)(tree_code_type[(int) (((enum tree_code) (base)->base.code
))] == tcc_declaration)
)
1482 return;
1483 bytepos = bits_to_bytes_round_down (bitpos)force_align_down_and_div (bitpos, (8));
1484 if (offset == NULL_TREE(tree) nullptr && known_eq (bytepos, 0)(!maybe_ne (bytepos, 0)) && moff == NULL_TREE(tree) nullptr)
1485 return;
1486
1487 tree base_addr = base;
1488 if (decl_p)
1489 base_addr = build1 (ADDR_EXPR,
1490 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"
, 1490, __FUNCTION__))->typed.type)
), base);
1491 t = offset;
1492 if (maybe_ne (bytepos, 0))
1493 {
1494 if (t)
1495 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"
, 1495, __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"
, 1496, __FUNCTION__))->typed.type), bytepos) )
1496 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"
, 1495, __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"
, 1496, __FUNCTION__))->typed.type), bytepos) )
;
1497 else
1498 t = size_int (bytepos)size_int_kind (bytepos, stk_sizetype);
1499 }
1500 if (moff)
1501 {
1502 if (t)
1503 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"
, 1503, __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"
, 1504, __FUNCTION__))->typed.type), moff) )
1504 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"
, 1503, __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"
, 1504, __FUNCTION__))->typed.type), moff) )
;
1505 else
1506 t = fold_convert (sizetype, moff)fold_convert_loc (((location_t) 0), sizetype_tab[(int) stk_sizetype
], moff)
;
1507 }
1508 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE(tree) nullptr, true,
1509 GSI_SAME_STMT);
1510 base_addr = force_gimple_operand_gsi (gsi, base_addr, true, NULL_TREE(tree) nullptr, true,
1511 GSI_SAME_STMT);
1512 instrument_pointer_overflow (gsi, base_addr, t);
1513}
1514
1515/* Build an ubsan builtin call for the signed-integer-overflow
1516 sanitization. CODE says what kind of builtin are we building,
1517 LOC is a location, LHSTYPE is the type of LHS, OP0 and OP1
1518 are operands of the binary operation. */
1519
1520tree
1521ubsan_build_overflow_builtin (tree_code code, location_t loc, tree lhstype,
1522 tree op0, tree op1, tree *datap)
1523{
1524 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
1525 return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1526
1527 tree data;
1528 if (datap && *datap)
1529 data = *datap;
1530 else
1531 data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
1532 ubsan_type_descriptor (lhstype), NULL_TREE(tree) nullptr,
1533 NULL_TREE(tree) nullptr);
1534 if (datap)
1535 *datap = data;
1536 enum built_in_function fn_code;
1537
1538 switch (code)
1539 {
1540 case PLUS_EXPR:
1541 fn_code = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1542 ? BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW
1543 : BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT;
1544 break;
1545 case MINUS_EXPR:
1546 fn_code = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1547 ? BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW
1548 : BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT;
1549 break;
1550 case MULT_EXPR:
1551 fn_code = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1552 ? BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW
1553 : BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT;
1554 break;
1555 case NEGATE_EXPR:
1556 fn_code = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_SI_OVERFLOW)
1557 ? BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW
1558 : BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT;
1559 break;
1560 default:
1561 gcc_unreachable ()(fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1561, __FUNCTION__))
;
1562 }
1563 tree fn = builtin_decl_explicit (fn_code);
1564 return build_call_expr_loc (loc, fn, 2 + (code != NEGATE_EXPR),
1565 build_fold_addr_expr_loc (loc, data),
1566 ubsan_encode_value (op0, UBSAN_ENCODE_VALUE_RTL),
1567 op1
1568 ? ubsan_encode_value (op1,
1569 UBSAN_ENCODE_VALUE_RTL)
1570 : NULL_TREE(tree) nullptr);
1571}
1572
1573/* Perform the signed integer instrumentation. GSI is the iterator
1574 pointing at statement we are trying to instrument. */
1575
1576static void
1577instrument_si_overflow (gimple_stmt_iterator gsi)
1578{
1579 gimple *stmt = gsi_stmt (gsi);
1580 tree_code code = gimple_assign_rhs_code (stmt);
1581 tree lhs = gimple_assign_lhs (stmt);
1582 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"
, 1582, __FUNCTION__))->typed.type)
;
1583 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"
, 1583, __FUNCTION__))->typed.type)
: lhstype;
1584 tree a, b;
1585 gimple *g;
1586
1587 /* If this is not a signed operation, don't instrument anything here.
1588 Also punt on bit-fields. */
1589 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
)
1590 || 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"
, 1590, __FUNCTION__))->base.u.bits.unsigned_flag || global_options
.x_flag_wrapv))
1591 || 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"
, 1591, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(lhsinner) : (lhsinner)->type_common.mode)
),
1592 TYPE_PRECISION (lhsinner)((tree_class_check ((lhsinner), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1592, __FUNCTION__))->type_common.precision)
))
1593 return;
1594
1595 switch (code)
1596 {
1597 case MINUS_EXPR:
1598 case PLUS_EXPR:
1599 case MULT_EXPR:
1600 /* Transform
1601 i = u {+,-,*} 5;
1602 into
1603 i = UBSAN_CHECK_{ADD,SUB,MUL} (u, 5); */
1604 a = gimple_assign_rhs1 (stmt);
1605 b = gimple_assign_rhs2 (stmt);
1606 g = gimple_build_call_internal (code == PLUS_EXPR
1607 ? IFN_UBSAN_CHECK_ADD
1608 : code == MINUS_EXPR
1609 ? IFN_UBSAN_CHECK_SUB
1610 : IFN_UBSAN_CHECK_MUL, 2, a, b);
1611 gimple_call_set_lhs (g, lhs);
1612 gsi_replace (&gsi, g, true);
1613 break;
1614 case NEGATE_EXPR:
1615 /* Represent i = -u;
1616 as
1617 i = UBSAN_CHECK_SUB (0, u); */
1618 a = build_zero_cst (lhstype);
1619 b = gimple_assign_rhs1 (stmt);
1620 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1621 gimple_call_set_lhs (g, lhs);
1622 gsi_replace (&gsi, g, true);
1623 break;
1624 case ABS_EXPR:
1625 /* Transform i = ABS_EXPR<u>;
1626 into
1627 _N = UBSAN_CHECK_SUB (0, u);
1628 i = ABS_EXPR<_N>; */
1629 a = build_zero_cst (lhstype);
1630 b = gimple_assign_rhs1 (stmt);
1631 g = gimple_build_call_internal (IFN_UBSAN_CHECK_SUB, 2, a, b);
1632 a = make_ssa_name (lhstype);
1633 gimple_call_set_lhs (g, a);
1634 gimple_set_location (g, gimple_location (stmt));
1635 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
1636 gimple_assign_set_rhs1 (stmt, a);
1637 update_stmt (stmt);
1638 break;
1639 default:
1640 break;
1641 }
1642}
1643
1644/* Instrument loads from (non-bitfield) bool and C++ enum values
1645 to check if the memory value is outside of the range of the valid
1646 type values. */
1647
1648static void
1649instrument_bool_enum_load (gimple_stmt_iterator *gsi)
1650{
1651 gimple *stmt = gsi_stmt (*gsi);
1652 tree rhs = gimple_assign_rhs1 (stmt);
1653 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"
, 1653, __FUNCTION__))->typed.type)
;
1654 tree minv = NULL_TREE(tree) nullptr, maxv = NULL_TREE(tree) nullptr;
1655
1656 if (TREE_CODE (type)((enum tree_code) (type)->base.code) == BOOLEAN_TYPE
1657 && sanitize_flags_p (SANITIZE_BOOL))
1658 {
1659 minv = boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE];
1660 maxv = boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE];
1661 }
1662 else if (TREE_CODE (type)((enum tree_code) (type)->base.code) == ENUMERAL_TYPE
1663 && sanitize_flags_p (SANITIZE_ENUM)
1664 && TREE_TYPE (type)((contains_struct_check ((type), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1664, __FUNCTION__))->typed.type)
!= NULL_TREE(tree) nullptr
1665 && 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"
, 1665, __FUNCTION__))->typed.type))->base.code)
== INTEGER_TYPE
1666 && (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"
, 1666, __FUNCTION__))->typed.type)), (tcc_type), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1666, __FUNCTION__))->type_common.precision)
1667 < 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"
, 1667, __FUNCTION__))->type_common.mode))
)))
1668 {
1669 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"
, 1669, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1669, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE
), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.minval
)
;
1670 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"
, 1670, __FUNCTION__))->typed.type)), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1670, __FUNCTION__, (INTEGER_TYPE), (ENUMERAL_TYPE), (BOOLEAN_TYPE
), (REAL_TYPE), (FIXED_POINT_TYPE)))->type_non_common.maxval
)
;
1671 }
1672 else
1673 return;
1674
1675 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"
, 1675, __FUNCTION__))->type_common.mode))
);
1676 poly_int64 bitsize, bitpos;
1677 tree offset;
1678 machine_mode mode;
1679 int volatilep = 0, reversep, unsignedp = 0;
1680 tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
1681 &unsignedp, &reversep, &volatilep);
1682 tree utype = build_nonstandard_integer_type (modebitsize, 1);
1683
1684 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"
, 1684, __FUNCTION__, (VAR_DECL)))->decl_with_vis.hard_register
)
)
1685 || !multiple_p (bitpos, modebitsize)
1686 || maybe_ne (bitsize, modebitsize)
1687 || 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"
, 1687, __FUNCTION__))->type_common.mode))
) != modebitsize
1688 || TREE_CODE (gimple_assign_lhs (stmt))((enum tree_code) (gimple_assign_lhs (stmt))->base.code) != SSA_NAME)
1689 return;
1690
1691 bool ends_bb = stmt_ends_bb_p (stmt);
1692 location_t loc = gimple_location (stmt);
1693 tree lhs = gimple_assign_lhs (stmt);
1694 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"
, 1694, __FUNCTION__))->typed.type)
);
1695 tree atype = reference_alias_ptr_type (rhs);
1696 gimple *g = gimple_build_assign (make_ssa_name (ptype),
1697 build_fold_addr_expr (rhs)build_fold_addr_expr_loc (((location_t) 0), (rhs)));
1698 gimple_set_location (g, loc);
1699 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1700 tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
1701 build_int_cst (atype, 0));
1702 tree urhs = make_ssa_name (utype);
1703 if (ends_bb)
1704 {
1705 gimple_assign_set_lhs (stmt, urhs);
1706 g = gimple_build_assign (lhs, NOP_EXPR, urhs);
1707 gimple_set_location (g, loc);
1708 edge e = find_fallthru_edge (gimple_bb (stmt)->succs);
1709 gsi_insert_on_edge_immediate (e, g);
1710 gimple_assign_set_rhs_from_tree (gsi, mem);
1711 update_stmt (stmt);
1712 *gsi = gsi_for_stmt (g);
1713 g = stmt;
1714 }
1715 else
1716 {
1717 g = gimple_build_assign (urhs, mem);
1718 gimple_set_location (g, loc);
1719 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1720 }
1721 minv = fold_convert (utype, minv)fold_convert_loc (((location_t) 0), utype, minv);
1722 maxv = fold_convert (utype, maxv)fold_convert_loc (((location_t) 0), utype, maxv);
1723 if (!integer_zerop (minv))
1724 {
1725 g = gimple_build_assign (make_ssa_name (utype), MINUS_EXPR, urhs, minv);
1726 gimple_set_location (g, loc);
1727 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1728 }
1729
1730 gimple_stmt_iterator gsi2 = *gsi;
1731 basic_block then_bb, fallthru_bb;
1732 *gsi = create_cond_insert_point (gsi, true, false, true,
1733 &then_bb, &fallthru_bb);
1734 g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
1735 int_const_binop (MINUS_EXPR, maxv, minv),
1736 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1737 gimple_set_location (g, loc);
1738 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1739
1740 if (!ends_bb)
1741 {
1742 gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs);
1743 update_stmt (stmt);
1744 }
1745
1746 gsi2 = gsi_after_labels (then_bb);
1747 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
1748 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1749 else
1750 {
1751 tree data = ubsan_create_data ("__ubsan_invalid_value_data", 1, &loc,
1752 ubsan_type_descriptor (type), NULL_TREE(tree) nullptr,
1753 NULL_TREE(tree) nullptr);
1754 data = build_fold_addr_expr_loc (loc, data);
1755 enum built_in_function bcode
1756 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & (TREE_CODE (type)((enum tree_code) (type)->base.code) == BOOLEAN_TYPE
1757 ? SANITIZE_BOOL : SANITIZE_ENUM))
1758 ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
1759 : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
1760 tree fn = builtin_decl_explicit (bcode);
1761
1762 tree val = ubsan_encode_value (urhs, UBSAN_ENCODE_VALUE_GIMPLE);
1763 val = force_gimple_operand_gsi (&gsi2, val, true, NULL_TREE(tree) nullptr, true,
1764 GSI_SAME_STMT);
1765 g = gimple_build_call (fn, 2, data, val);
1766 }
1767 gimple_set_location (g, loc);
1768 gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
1769 ubsan_create_edge (g);
1770 *gsi = gsi_for_stmt (stmt);
1771}
1772
1773/* Determine if we can propagate given LOCATION to ubsan_data descriptor to use
1774 new style handlers. Libubsan uses heuristics to destinguish between old and
1775 new styles and relies on these properties for filename:
1776
1777 a) Location's filename must not be NULL.
1778 b) Location's filename must not be equal to "".
1779 c) Location's filename must not be equal to "\1".
1780 d) First two bytes of filename must not contain '\xff' symbol. */
1781
1782static bool
1783ubsan_use_new_style_p (location_t loc)
1784{
1785 if (loc == UNKNOWN_LOCATION((location_t) 0))
1786 return false;
1787
1788 expanded_location xloc = expand_location (loc);
1789 if (xloc.file == NULLnullptr || startswith (xloc.file, "\1")
1790 || xloc.file[0] == '\0' || xloc.file[0] == '\xff'
1791 || xloc.file[1] == '\xff')
1792 return false;
1793
1794 return true;
1795}
1796
1797/* Instrument float point-to-integer conversion. TYPE is an integer type of
1798 destination, EXPR is floating-point expression. */
1799
1800tree
1801ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
1802{
1803 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"
, 1803, __FUNCTION__))->typed.type)
;
1804 tree t, tt, fn, min, max;
1805 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"
, 1805, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(expr_type) : (expr_type)->type_common.mode)
;
1806 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"
, 1806, __FUNCTION__))->type_common.precision)
;
1807 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"
, 1807, __FUNCTION__))->base.u.bits.unsigned_flag)
;
1808 if (loc == UNKNOWN_LOCATION((location_t) 0))
1809 loc = input_location;
1810
1811 /* Float to integer conversion first truncates toward zero, so
1812 even signed char c = 127.875f; is not problematic.
1813 Therefore, we should complain only if EXPR is unordered or smaller
1814 or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than
1815 TYPE_MAX_VALUE + 1.0. */
1816 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"
, 1816, __FUNCTION__)), 0)])
->b == 2)
1817 {
1818 /* For maximum, TYPE_MAX_VALUE might not be representable
1819 in EXPR_TYPE, e.g. if TYPE is 64-bit long long and
1820 EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is
1821 either representable or infinity. */
1822 REAL_VALUE_TYPEstruct real_value maxval = dconst1;
1823 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)))
;
1824 real_convert (&maxval, mode, &maxval);
1825 max = build_real (expr_type, maxval);
1826
1827 /* For unsigned, assume -1.0 is always representable. */
1828 if (uns_p)
1829 min = build_minus_one_cst (expr_type);
1830 else
1831 {
1832 /* TYPE_MIN_VALUE is generally representable (or -inf),
1833 but TYPE_MIN_VALUE - 1.0 might not be. */
1834 REAL_VALUE_TYPEstruct real_value minval = dconstm1, minval2;
1835 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)))
;
1836 real_convert (&minval, mode, &minval);
1837 real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1);
1838 real_convert (&minval2, mode, &minval2);
1839 if (real_compare (EQ_EXPR, &minval, &minval2)
1840 && !real_isinf (&minval))
1841 {
1842 /* If TYPE_MIN_VALUE - 1.0 is not representable and
1843 rounds to TYPE_MIN_VALUE, we need to subtract
1844 more. As REAL_MODE_FORMAT (mode)->p is the number
1845 of base digits, we want to subtract a number that
1846 will be 1 << (REAL_MODE_FORMAT (mode)->p - 1)
1847 times smaller than minval. */
1848 minval2 = dconst1;
1849 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"
, 1849, __FUNCTION__)), 0)])->p) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 1849, __FUNCTION__), 0 : 0))
;
1850 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"
, 1852, __FUNCTION__)), 0)])->p + 1) & (unsigned int)(
(1 << (32 - 6)) - 1)))
1851 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"
, 1852, __FUNCTION__)), 0)])->p + 1) & (unsigned int)(
(1 << (32 - 6)) - 1)))
1852 - 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"
, 1852, __FUNCTION__)), 0)])->p + 1) & (unsigned int)(
(1 << (32 - 6)) - 1)))
;
1853 real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2);
1854 real_convert (&minval2, mode, &minval2);
1855 }
1856 min = build_real (expr_type, minval2);
1857 }
1858 }
1859 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"
, 1859, __FUNCTION__)), 0)])
->b == 10)
1860 {
1861 /* For _Decimal128 up to 34 decimal digits, - sign,
1862 dot, e, exponent. */
1863 char buf[64];
1864 mpfr_t m;
1865 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"
, 1865, __FUNCTION__)), 0)])
->p;
1866 REAL_VALUE_TYPEstruct real_value maxval, minval;
1867
1868 /* Use mpfr_snprintf rounding to compute the smallest
1869 representable decimal number greater or equal than
1870 1 << (prec - !uns_p). */
1871 mpfr_init2 (m, prec + 2);
1872 mpfr_set_ui_2exp (m, 1, prec - !uns_p, MPFR_RNDN);
1873 mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
1874 decimal_real_from_string (&maxval, buf);
1875 max = build_real (expr_type, maxval);
1876
1877 /* For unsigned, assume -1.0 is always representable. */
1878 if (uns_p)
1879 min = build_minus_one_cst (expr_type);
1880 else
1881 {
1882 /* Use mpfr_snprintf rounding to compute the largest
1883 representable decimal number less or equal than
1884 (-1 << (prec - 1)) - 1. */
1885 mpfr_set_si_2exp (m, -1, prec - 1, MPFR_RNDN);
1886 mpfr_sub_ui (m, m, 1, MPFR_RNDN);
1887 mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
1888 decimal_real_from_string (&minval, buf);
1889 min = build_real (expr_type, minval);
1890 }
1891 mpfr_clear (m);
1892 }
1893 else
1894 return NULL_TREE(tree) nullptr;
1895
1896 if (HONOR_NANS (mode))
1897 {
1898 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 )
;
1899 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 )
;
1900 }
1901 else
1902 {
1903 t = fold_build2 (LE_EXPR, boolean_type_node, expr, min)fold_build2_loc (((location_t) 0), LE_EXPR, global_trees[TI_BOOLEAN_TYPE
], expr, min )
;
1904 tt = fold_build2 (GE_EXPR, boolean_type_node, expr, max)fold_build2_loc (((location_t) 0), GE_EXPR, global_trees[TI_BOOLEAN_TYPE
], expr, max )
;
1905 }
1906 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 )
;
1907 if (integer_zerop (t))
1908 return NULL_TREE(tree) nullptr;
1909
1910 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
1911 fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1912 else
1913 {
1914 location_t *loc_ptr = NULLnullptr;
1915 unsigned num_locations = 0;
1916 /* Figure out if we can propagate location to ubsan_data and use new
1917 style handlers in libubsan. */
1918 if (ubsan_use_new_style_p (loc))
1919 {
1920 loc_ptr = &loc;
1921 num_locations = 1;
1922 }
1923 /* Create the __ubsan_handle_float_cast_overflow fn call. */
1924 tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data",
1925 num_locations, loc_ptr,
1926 ubsan_type_descriptor (expr_type),
1927 ubsan_type_descriptor (type), NULL_TREE(tree) nullptr,
1928 NULL_TREE(tree) nullptr);
1929 enum built_in_function bcode
1930 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_FLOAT_CAST)
1931 ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW
1932 : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT;
1933 fn = builtin_decl_explicit (bcode);
1934 fn = build_call_expr_loc (loc, fn, 2,
1935 build_fold_addr_expr_loc (loc, data),
1936 ubsan_encode_value (expr));
1937 }
1938
1939 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] )
;
1940}
1941
1942/* Instrument values passed to function arguments with nonnull attribute. */
1943
1944static void
1945instrument_nonnull_arg (gimple_stmt_iterator *gsi)
1946{
1947 gimple *stmt = gsi_stmt (*gsi);
1948 location_t loc[2];
1949 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
1950 while for nonnull sanitization it is clear. */
1951 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checksglobal_options.x_flag_delete_null_pointer_checks;
1952 flag_delete_null_pointer_checksglobal_options.x_flag_delete_null_pointer_checks = 1;
1953 loc[0] = gimple_location (stmt);
1954 loc[1] = UNKNOWN_LOCATION((location_t) 0);
1955 for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
1956 {
1957 tree arg = gimple_call_arg (stmt, i);
1958 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"
, 1958, __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"
, 1958, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
)
1959 && infer_nonnull_range_by_attribute (stmt, arg))
1960 {
1961 gimple *g;
1962 if (!is_gimple_val (arg))
1963 {
1964 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"
, 1964, __FUNCTION__))->typed.type)
), arg);
1965 gimple_set_location (g, loc[0]);
1966 gsi_insert_before (gsi, g, GSI_SAME_STMT);
1967 arg = gimple_assign_lhs (g);
1968 }
1969
1970 basic_block then_bb, fallthru_bb;
1971 *gsi = create_cond_insert_point (gsi, true, false, true,
1972 &then_bb, &fallthru_bb);
1973 g = gimple_build_cond (EQ_EXPR, arg,
1974 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"
, 1974, __FUNCTION__))->typed.type)
),
1975 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1976 gimple_set_location (g, loc[0]);
1977 gsi_insert_after (gsi, g, GSI_NEW_STMT);
1978
1979 *gsi = gsi_after_labels (then_bb);
1980 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
1981 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1982 else
1983 {
1984 tree data = ubsan_create_data ("__ubsan_nonnull_arg_data",
1985 2, loc, NULL_TREE(tree) nullptr,
1986 build_int_cst (integer_type_nodeinteger_types[itk_int],
1987 i + 1),
1988 NULL_TREE(tree) nullptr);
1989 data = build_fold_addr_expr_loc (loc[0], data);
1990 enum built_in_function bcode
1991 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_NONNULL_ATTRIBUTE)
1992 ? BUILT_IN_UBSAN_HANDLE_NONNULL_ARG
1993 : BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT;
1994 tree fn = builtin_decl_explicit (bcode);
1995
1996 g = gimple_build_call (fn, 1, data);
1997 }
1998 gimple_set_location (g, loc[0]);
1999 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2000 ubsan_create_edge (g);
2001 }
2002 *gsi = gsi_for_stmt (stmt);
2003 }
2004 flag_delete_null_pointer_checksglobal_options.x_flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
2005}
2006
2007/* Instrument returns in functions with returns_nonnull attribute. */
2008
2009static void
2010instrument_nonnull_return (gimple_stmt_iterator *gsi)
2011{
2012 greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
2013 location_t loc[2];
2014 tree arg = gimple_return_retval (stmt);
2015 /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
2016 while for nonnull return sanitization it is clear. */
2017 int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checksglobal_options.x_flag_delete_null_pointer_checks;
2018 flag_delete_null_pointer_checksglobal_options.x_flag_delete_null_pointer_checks = 1;
2019 loc[0] = gimple_location (stmt);
2020 loc[1] = UNKNOWN_LOCATION((location_t) 0);
2021 if (arg
2022 && 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"
, 2022, __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"
, 2022, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
)
2023 && is_gimple_val (arg)
2024 && infer_nonnull_range_by_attribute (stmt, arg))
2025 {
2026 basic_block then_bb, fallthru_bb;
2027 *gsi = create_cond_insert_point (gsi, true, false, true,
2028 &then_bb, &fallthru_bb);
2029 gimple *g = gimple_build_cond (EQ_EXPR, arg,
2030 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"
, 2030, __FUNCTION__))->typed.type)
),
2031 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
2032 gimple_set_location (g, loc[0]);
2033 gsi_insert_after (gsi, g, GSI_NEW_STMT);
2034
2035 *gsi = gsi_after_labels (then_bb);
2036 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
2037 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
2038 else
2039 {
2040 tree data = ubsan_create_data ("__ubsan_nonnull_return_data",
2041 1, &loc[1], NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
2042 data = build_fold_addr_expr_loc (loc[0], data);
2043 tree data2 = ubsan_create_data ("__ubsan_nonnull_return_data",
2044 1, &loc[0], NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
2045 data2 = build_fold_addr_expr_loc (loc[0], data2);
2046 enum built_in_function bcode
2047 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_RETURNS_NONNULL_ATTRIBUTE)
2048 ? BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1
2049 : BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1_ABORT;
2050 tree fn = builtin_decl_explicit (bcode);
2051
2052 g = gimple_build_call (fn, 2, data, data2);
2053 }
2054 gimple_set_location (g, loc[0]);
2055 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2056 ubsan_create_edge (g);
2057 *gsi = gsi_for_stmt (stmt);
2058 }
2059 flag_delete_null_pointer_checksglobal_options.x_flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
2060}
2061
2062/* Instrument memory references. Here we check whether the pointer
2063 points to an out-of-bounds location. */
2064
2065static void
2066instrument_object_size (gimple_stmt_iterator *gsi, tree t, bool is_lhs)
2067{
2068 gimple *stmt = gsi_stmt (*gsi);
2069 location_t loc = gimple_location (stmt);
2070 tree type;
2071 tree index = NULL_TREE(tree) nullptr;
2072 HOST_WIDE_INTlong size_in_bytes;
2073
2074 type = TREE_TYPE (t)((contains_struct_check ((t), (TS_TYPED), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2074, __FUNCTION__))->typed.type)
;
2075 if (VOID_TYPE_P (type)(((enum tree_code) (type)->base.code) == VOID_TYPE))
2076 return;
2077
2078 switch (TREE_CODE (t)((enum tree_code) (t)->base.code))
2079 {
2080 case COMPONENT_REF:
2081 if (TREE_CODE (t)((enum tree_code) (t)->base.code) == COMPONENT_REF
2082 && 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"
, 2082, __FUNCTION__)))))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2082, __FUNCTION__, (FIELD_DECL)))->field_decl.qualifier
)
!= NULL_TREE(tree) nullptr)
2083 {
2084 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"
, 2084, __FUNCTION__)))))), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2084, __FUNCTION__, (FIELD_DECL)))->field_decl.qualifier
)
;
2085 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"
, 2085, __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"
, 2085, __FUNCTION__)))))
,
2086 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"
, 2086, __FUNCTION__)))))
);
2087 }
2088 break;
2089 case ARRAY_REF:
2090 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"
, 2090, __FUNCTION__)))))
;
2091 break;
2092 case INDIRECT_REF:
2093 case MEM_REF:
2094 case VAR_DECL:
2095 case PARM_DECL:
2096 case RESULT_DECL:
2097 break;
2098 default:
2099 return;
2100 }
2101
2102 size_in_bytes = int_size_in_bytes (type);
2103 if (size_in_bytes <= 0)
2104 return;
2105
2106 poly_int64 bitsize, bitpos;
2107 tree offset;
2108 machine_mode mode;
2109 int volatilep = 0, reversep, unsignedp = 0;
2110 tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
2111 &unsignedp, &reversep, &volatilep);
2112
2113 if (!multiple_p (bitpos, BITS_PER_UNIT(8))
2114 || maybe_ne (bitsize, size_in_bytes * BITS_PER_UNIT(8)))
2115 return;
2116
2117 bool decl_p = DECL_P (inner)(tree_code_type[(int) (((enum tree_code) (inner)->base.code
))] == tcc_declaration)
;
2118 tree base;
2119 if (decl_p)
2120 {
2121 if ((VAR_P (inner)(((enum tree_code) (inner)->base.code) == VAR_DECL)
2122 || TREE_CODE (inner)((enum tree_code) (inner)->base.code) == PARM_DECL
2123 || TREE_CODE (inner)((enum tree_code) (inner)->base.code) == RESULT_DECL)
2124 && DECL_REGISTER (inner)((contains_struct_check ((inner), (TS_DECL_WRTL), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2124, __FUNCTION__))->decl_common.decl_flag_0)
)
2125 return;
2126 base = inner;
2127 }
2128 else if (TREE_CODE (inner)((enum tree_code) (inner)->base.code) == MEM_REF)
2129 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"
, 2129, __FUNCTION__)))))
;
2130 else
2131 return;
2132 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"
, 2132, __FUNCTION__))->typed.type)
), t);
2133
2134 while (TREE_CODE (base)((enum tree_code) (base)->base.code) == SSA_NAME)
2135 {
2136 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"
, 2136, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
2137 if (gimple_assign_ssa_name_copy_p (def_stmt)
2138 || (gimple_assign_cast_p (def_stmt)
2139 && 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"
, 2139, __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"
, 2139, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
)
)
2140 || (is_gimple_assign (def_stmt)
2141 && gimple_assign_rhs_code (def_stmt) == POINTER_PLUS_EXPR))
2142 {
2143 tree rhs1 = gimple_assign_rhs1 (def_stmt);
2144 if (TREE_CODE (rhs1)((enum tree_code) (rhs1)->base.code) == SSA_NAME
2145 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1)(tree_check ((rhs1), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2145, __FUNCTION__, (SSA_NAME)))->base.asm_written_flag
)
2146 break;
2147 else
2148 base = rhs1;
2149 }
2150 else
2151 break;
2152 }
2153
2154 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"
, 2154, __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"
, 2154, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
)
&& !DECL_P (base)(tree_code_type[(int) (((enum tree_code) (base)->base.code
))] == tcc_declaration)
)
2155 return;
2156
2157 tree sizet;
2158 tree base_addr = base;
2159 gimple *bos_stmt = NULLnullptr;
2160 if (decl_p)
2161 base_addr = build1 (ADDR_EXPR,
2162 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"
, 2162, __FUNCTION__))->typed.type)
), base);
2163 unsigned HOST_WIDE_INTlong size;
2164 if (compute_builtin_object_size (base_addr, 0, &size))
2165 sizet = build_int_cst (sizetypesizetype_tab[(int) stk_sizetype], size);
2166 else if (optimizeglobal_options.x_optimize)
2167 {
2168 if (LOCATION_LOCUS (loc)((IS_ADHOC_LOC (loc)) ? get_location_from_adhoc_loc (line_table
, loc) : (loc))
== UNKNOWN_LOCATION((location_t) 0))
2169 loc = input_location;
2170 /* Generate __builtin_object_size call. */
2171 sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
2172 sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
2173 integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]);
2174 sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE(tree) nullptr, true,
2175 GSI_SAME_STMT);
2176 /* If the call above didn't end up being an integer constant, go one
2177 statement back and get the __builtin_object_size stmt. Save it,
2178 we might need it later. */
2179 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)
)
2180 {
2181 gsi_prev (gsi);
2182 bos_stmt = gsi_stmt (*gsi);
2183
2184 /* Move on to where we were. */
2185 gsi_next (gsi);
2186 }
2187 }
2188 else
2189 return;
2190
2191 /* Generate UBSAN_OBJECT_SIZE (ptr, ptr+sizeof(*ptr)-base, objsize, ckind)
2192 call. */
2193 /* ptr + sizeof (*ptr) - base */
2194 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) )
2195 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) )
2196 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) )
;
2197 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"
, 2197, __FUNCTION__))->type_common.size_unit) )
;
2198
2199 /* Perhaps we can omit the check. */
2200 if (TREE_CODE (t)((enum tree_code) (t)->base.code) == INTEGER_CST
2201 && TREE_CODE (sizet)((enum tree_code) (sizet)->base.code) == INTEGER_CST
2202 && tree_int_cst_le (t, sizet))
2203 return;
2204
2205 if (index != NULL_TREE(tree) nullptr
2206 && TREE_CODE (index)((enum tree_code) (index)->base.code) == SSA_NAME
2207 && TREE_CODE (sizet)((enum tree_code) (sizet)->base.code) == INTEGER_CST)
2208 {
2209 gimple *def = SSA_NAME_DEF_STMT (index)(tree_check ((index), "/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/ubsan.c"
, 2209, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
2210 if (is_gimple_assign (def)
2211 && gimple_assign_rhs_code (def) == BIT_AND_EXPR
2212 && TREE_CODE (gimple_assign_rhs2 (def))((enum tree_code) (gimple_assign_rhs2 (def))->base.code) == INTEGER_CST)
2213 {
2214 tree cst = gimple_assign_rhs2 (def);
2215 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"
, 2216, __FUNCTION__))->type_common.size_unit) )
2216 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"
, 2216, __FUNCTION__))->type_common.size_unit) )
;
2217 if (tree_int_cst_sgn (cst) >= 0
2218 && tree_int_cst_lt (cst, sz))
2219 return;
2220 }
2221 }
2222
2223 if (bos_stmt && gimple_call_builtin_p (bos_stmt, BUILT_IN_OBJECT_SIZE))
2224 ubsan_create_edge (bos_stmt);
2225
2226 /* We have to emit the check. */
2227 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE(tree) nullptr, true,
2228 GSI_SAME_STMT);
2229 ptr = force_gimple_operand_gsi (gsi, ptr, true, NULL_TREE(tree) nullptr, true,
2230 GSI_SAME_STMT);
2231 tree ckind = build_int_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char],
2232 is_lhs ? UBSAN_STORE_OF : UBSAN_LOAD_OF);
2233 gimple *g = gimple_build_call_internal (IFN_UBSAN_OBJECT_SIZE, 4,
2234 ptr, t, sizet, ckind);
2235 gimple_set_location (g, loc);
2236 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2237}
2238
2239/* Instrument values passed to builtin functions. */
2240
2241static void
2242instrument_builtin (gimple_stmt_iterator *gsi)
2243{
2244 gimple *stmt = gsi_stmt (*gsi);
2245 location_t loc = gimple_location (stmt);
2246 tree arg;
2247 enum built_in_function fcode
2248 = DECL_FUNCTION_CODE (gimple_call_fndecl (stmt));
2249 int kind = 0;
2250 switch (fcode)
2251 {
2252 CASE_INT_FN (BUILT_IN_CLZ)case BUILT_IN_CLZ: case BUILT_IN_CLZL: case BUILT_IN_CLZLL: case
BUILT_IN_CLZIMAX
:
2253 kind = 1;
2254 gcc_fallthrough ();
2255 CASE_INT_FN (BUILT_IN_CTZ)case BUILT_IN_CTZ: case BUILT_IN_CTZL: case BUILT_IN_CTZLL: case
BUILT_IN_CTZIMAX
:
2256 arg = gimple_call_arg (stmt, 0);
2257 if (!integer_nonzerop (arg))
2258 {
2259 gimple *g;
2260 if (!is_gimple_val (arg))
2261 {
2262 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"
, 2262, __FUNCTION__))->typed.type)
), arg);
2263 gimple_set_location (g, loc);
2264 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2265 arg = gimple_assign_lhs (g);
2266 }
2267
2268 basic_block then_bb, fallthru_bb;
2269 *gsi = create_cond_insert_point (gsi, true, false, true,
2270 &then_bb, &fallthru_bb);
2271 g = gimple_build_cond (EQ_EXPR, arg,
2272 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"
, 2272, __FUNCTION__))->typed.type)
),
2273 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
2274 gimple_set_location (g, loc);
2275 gsi_insert_after (gsi, g, GSI_NEW_STMT);
2276
2277 *gsi = gsi_after_labels (then_bb);
2278 if (flag_sanitize_undefined_trap_on_errorglobal_options.x_flag_sanitize_undefined_trap_on_error)
2279 g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
2280 else
2281 {
2282 tree t = build_int_cst (unsigned_char_type_nodeinteger_types[itk_unsigned_char], kind);
2283 tree data = ubsan_create_data ("__ubsan_builtin_data",
2284 1, &loc, NULL_TREE(tree) nullptr, t, NULL_TREE(tree) nullptr);
2285 data = build_fold_addr_expr_loc (loc, data);
2286 enum built_in_function bcode
2287 = (flag_sanitize_recoverglobal_options.x_flag_sanitize_recover & SANITIZE_BUILTIN)
2288 ? BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN
2289 : BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN_ABORT;
2290 tree fn = builtin_decl_explicit (bcode);
2291
2292 g = gimple_build_call (fn, 1, data);
2293 }
2294 gimple_set_location (g, loc);
2295 gsi_insert_before (gsi, g, GSI_SAME_STMT);
2296 ubsan_create_edge (g);
2297 }
2298 *gsi = gsi_for_stmt (stmt);
2299 break;
2300 default:
2301 break;
2302 }
2303}
2304
2305namespace {
2306
2307const pass_data pass_data_ubsan =
2308{
2309 GIMPLE_PASS, /* type */
2310 "ubsan", /* name */
2311 OPTGROUP_NONE, /* optinfo_flags */
2312 TV_TREE_UBSAN, /* tv_id */
2313 ( PROP_cfg(1 << 3) | PROP_ssa(1 << 5) ), /* properties_required */
2314 0, /* properties_provided */
2315 0, /* properties_destroyed */
2316 0, /* todo_flags_start */
2317 TODO_update_ssa(1 << 11), /* todo_flags_finish */
2318};
2319
2320class pass_ubsan : public gimple_opt_pass
2321{
2322public:
2323 pass_ubsan (gcc::context *ctxt)
2324 : gimple_opt_pass (pass_data_ubsan, ctxt)
2325 {}
2326
2327 /* opt_pass methods: */
2328 virtual bool gate (function *)
2329 {
2330 return sanitize_flags_p ((SANITIZE_NULL | SANITIZE_SI_OVERFLOW
2331 | SANITIZE_BOOL | SANITIZE_ENUM
2332 | SANITIZE_ALIGNMENT
2333 | SANITIZE_NONNULL_ATTRIBUTE
2334 | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
2335 | SANITIZE_OBJECT_SIZE
2336 | SANITIZE_POINTER_OVERFLOW
2337 | SANITIZE_BUILTIN));
2338 }
2339
2340 virtual unsigned int execute (function *);
2341
2342}; // class pass_ubsan
2343
2344unsigned int
2345pass_ubsan::execute (function *fun)
2346{
2347 basic_block bb;
2348 gimple_stmt_iterator gsi;
2349 unsigned int ret = 0;
2350
2351 initialize_sanitizer_builtins ();
2352
2353 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)
2354 {
2355 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
2356 {
2357 gimple *stmt = gsi_stmt (gsi);
2358 if (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
2359 {
2360 gsi_next (&gsi);
2361 continue;
2362 }
2363
2364 if ((sanitize_flags_p (SANITIZE_SI_OVERFLOW, fun->decl))
2365 && is_gimple_assign (stmt))
2366 instrument_si_overflow (gsi);
2367
2368 if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT, fun->decl))
2369 {
2370 if (gimple_store_p (stmt))
2371 instrument_null (gsi, gimple_get_lhs (stmt), true);
2372 if (gimple_assign_single_p (stmt))
2373 instrument_null (gsi, gimple_assign_rhs1 (stmt), false);
2374 if (is_gimple_call (stmt))
2375 {
2376 unsigned args_num = gimple_call_num_args (stmt);
2377 for (unsigned i = 0; i < args_num; ++i)
2378 {
2379 tree arg = gimple_call_arg (stmt, i);
2380 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2381 continue;
2382 instrument_null (gsi, arg, false);
2383 }
2384 }
2385 }
2386
2387 if (sanitize_flags_p (SANITIZE_BOOL | SANITIZE_ENUM, fun->decl)
2388 && gimple_assign_load_p (stmt))
2389 {
2390 instrument_bool_enum_load (&gsi);
2391 bb = gimple_bb (stmt);
2392 }
2393
2394 if (sanitize_flags_p (SANITIZE_NONNULL_ATTRIBUTE, fun->decl)
2395 && is_gimple_call (stmt)
2396 && !gimple_call_internal_p (stmt))
2397 {
2398 instrument_nonnull_arg (&gsi);
2399 bb = gimple_bb (stmt);
2400 }
2401
2402 if (sanitize_flags_p (SANITIZE_BUILTIN, fun->decl)
2403 && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
2404 {
2405 instrument_builtin (&gsi);
2406 bb = gimple_bb (stmt);
2407 }
2408
2409 if (sanitize_flags_p (SANITIZE_RETURNS_NONNULL_ATTRIBUTE, fun->decl)
2410 && gimple_code (stmt) == GIMPLE_RETURN)
2411 {
2412 instrument_nonnull_return (&gsi);
2413 bb = gimple_bb (stmt);
2414 }
2415
2416 if (sanitize_flags_p (SANITIZE_OBJECT_SIZE, fun->decl))
2417 {
2418 if (gimple_store_p (stmt))
2419 instrument_object_size (&gsi, gimple_get_lhs (stmt), true);
2420 if (gimple_assign_load_p (stmt))
2421 instrument_object_size (&gsi, gimple_assign_rhs1 (stmt),
2422 false);
2423 if (is_gimple_call (stmt))
2424 {
2425 unsigned args_num = gimple_call_num_args (stmt);
2426 for (unsigned i = 0; i < args_num; ++i)
2427 {
2428 tree arg = gimple_call_arg (stmt, i);
2429 if (is_gimple_reg (arg) || is_gimple_min_invariant (arg))
2430 continue;
2431 instrument_object_size (&gsi, arg, false);
2432 }
2433 }
2434 }
2435
2436 if (sanitize_flags_p (SANITIZE_POINTER_OVERFLOW, fun->decl))
2437 {
2438 if (is_gimple_assign (stmt)
2439 && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
2440 instrument_pointer_overflow (&gsi,
2441 gimple_assign_rhs1 (stmt),
2442 gimple_assign_rhs2 (stmt));
2443 if (gimple_store_p (stmt))
2444 maybe_instrument_pointer_overflow (&gsi,
2445 gimple_get_lhs (stmt));
2446 if (gimple_assign_single_p (stmt))
2447 maybe_instrument_pointer_overflow (&gsi,
2448 gimple_assign_rhs1 (stmt));
2449 if (is_gimple_call (stmt))
2450 {
2451 unsigned args_num = gimple_call_num_args (stmt);
2452 for (unsigned i = 0; i < args_num; ++i)
2453 {
2454 tree arg = gimple_call_arg (stmt, i);
2455 if (is_gimple_reg (arg))
2456 continue;
2457 maybe_instrument_pointer_overflow (&gsi, arg);
2458 }
2459 }
2460 }
2461
2462 gsi_next (&gsi);
2463 }
2464 if (gimple_purge_dead_eh_edges (bb))
2465 ret = TODO_cleanup_cfg(1 << 5);
2466 }
2467 return ret;
2468}
2469
2470} // anon namespace
2471
2472gimple_opt_pass *
2473make_pass_ubsan (gcc::context *ctxt)
2474{
2475 return new pass_ubsan (ctxt);
2476}
2477
2478#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 zero-initialized values for vec<T, A, L>. This is
545 used to provide nil initializers for vec instances. Since vec must
546 be a trivially copyable type that can be copied by memcpy and zeroed
547 out by memset, it must have defaulted default and copy ctor and copy
548 assignment. To initialize a vec either use value initialization
549 (e.g., vec() or vec v{ };) or assign it the value vNULL. This isn't
550 needed for file-scope and function-local static vectors, which are
551 zero-initialized by default. */
552struct vnull { };
553constexpr vnull vNULL{ };
554
555
556/* Embeddable vector. These vectors are suitable to be embedded
557 in other data structures so that they can be pre-allocated in a
558 contiguous memory block.
559
560 Embeddable vectors are implemented using the trailing array idiom,
561 thus they are not resizeable without changing the address of the
562 vector object itself. This means you cannot have variables or
563 fields of embeddable vector type -- always use a pointer to a
564 vector. The one exception is the final field of a structure, which
565 could be a vector type.
566
567 You will have to use the embedded_size & embedded_init calls to
568 create such objects, and they will not be resizeable (so the 'safe'
569 allocation variants are not available).
570
571 Properties:
572
573 - The whole vector and control data are allocated in a single
574 contiguous block. It uses the trailing-vector idiom, so
575 allocation must reserve enough space for all the elements
576 in the vector plus its control data.
577 - The vector cannot be re-allocated.
578 - The vector cannot grow nor shrink.
579 - No indirections needed for access/manipulation.
580 - It requires 2 words of storage (prior to vector allocation). */
581
582template<typename T, typename A>
583struct GTY((user)) vec<T, A, vl_embed>
584{
585public:
586 unsigned allocated (void) const { return m_vecpfx.m_alloc; }
587 unsigned length (void) const { return m_vecpfx.m_num; }
588 bool is_empty (void) const { return m_vecpfx.m_num == 0; }
589 T *address (void) { return m_vecdata; }
590 const T *address (void) const { return m_vecdata; }
591 T *begin () { return address (); }
592 const T *begin () const { return address (); }
593 T *end () { return address () + length (); }
594 const T *end () const { return address () + length (); }
595 const T &operator[] (unsigned) const;
596 T &operator[] (unsigned);
597 T &last (void);
598 bool space (unsigned) const;
599 bool iterate (unsigned, T *) const;
600 bool iterate (unsigned, T **) const;
601 vec *copy (ALONE_CXX_MEM_STAT_INFO) const;
602 void splice (const vec &);
603 void splice (const vec *src);
604 T *quick_push (const T &);
605 T &pop (void);
606 void truncate (unsigned);
607 void quick_insert (unsigned, const T &);
608 void ordered_remove (unsigned);
609 void unordered_remove (unsigned);
610 void block_remove (unsigned, unsigned);
611 void qsort (int (*) (const void *, const void *))qsort (int (*) (const void *, const void *));
612 void sort (int (*) (const void *, const void *, void *), void *);
613 void stablesort (int (*) (const void *, const void *, void *), void *);
614 T *bsearch (const void *key, int (*compar)(const void *, const void *));
615 T *bsearch (const void *key,
616 int (*compar)(const void *, const void *, void *), void *);
617 unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
618 bool contains (const T &search) const;
619 static size_t embedded_size (unsigned);
620 void embedded_init (unsigned, unsigned = 0, unsigned = 0);
621 void quick_grow (unsigned len);
622 void quick_grow_cleared (unsigned len);
623
624 /* vec class can access our internal data and functions. */
625 template <typename, typename, typename> friend struct vec;
626
627 /* The allocator types also need access to our internals. */
628 friend struct va_gc;
629 friend struct va_gc_atomic;
630 friend struct va_heap;
631
632 /* FIXME - These fields should be private, but we need to cater to
633 compilers that have stricter notions of PODness for types. */
634 vec_prefix m_vecpfx;
635 T m_vecdata[1];
636};
637
638
639/* Convenience wrapper functions to use when dealing with pointers to
640 embedded vectors. Some functionality for these vectors must be
641 provided via free functions for these reasons:
642
643 1- The pointer may be NULL (e.g., before initial allocation).
644
645 2- When the vector needs to grow, it must be reallocated, so
646 the pointer will change its value.
647
648 Because of limitations with the current GC machinery, all vectors
649 in GC memory *must* be pointers. */
650
651
652/* If V contains no room for NELEMS elements, return false. Otherwise,
653 return true. */
654template<typename T, typename A>
655inline bool
656vec_safe_space (const vec<T, A, vl_embed> *v, unsigned nelems)
657{
658 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
659}
660
661
662/* If V is NULL, return 0. Otherwise, return V->length(). */
663template<typename T, typename A>
664inline unsigned
665vec_safe_length (const vec<T, A, vl_embed> *v)
666{
667 return v ? v->length () : 0;
668}
669
670
671/* If V is NULL, return NULL. Otherwise, return V->address(). */
672template<typename T, typename A>
673inline T *
674vec_safe_address (vec<T, A, vl_embed> *v)
675{
676 return v ? v->address () : NULLnullptr;
677}
678
679
680/* If V is NULL, return true. Otherwise, return V->is_empty(). */
681template<typename T, typename A>
682inline bool
683vec_safe_is_empty (vec<T, A, vl_embed> *v)
684{
685 return v ? v->is_empty () : true;
686}
687
688/* If V does not have space for NELEMS elements, call
689 V->reserve(NELEMS, EXACT). */
690template<typename T, typename A>
691inline bool
692vec_safe_reserve (vec<T, A, vl_embed> *&v, unsigned nelems, bool exact = false
693 CXX_MEM_STAT_INFO)
694{
695 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
696 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
697 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'
698 return extend;
699}
700
701template<typename T, typename A>
702inline bool
703vec_safe_reserve_exact (vec<T, A, vl_embed> *&v, unsigned nelems
704 CXX_MEM_STAT_INFO)
705{
706 return vec_safe_reserve (v, nelems, true PASS_MEM_STAT);
707}
708
709
710/* Allocate GC memory for V with space for NELEMS slots. If NELEMS
711 is 0, V is initialized to NULL. */
712
713template<typename T, typename A>
714inline void
715vec_alloc (vec<T, A, vl_embed> *&v, unsigned nelems CXX_MEM_STAT_INFO)
716{
717 v = NULLnullptr;
718 vec_safe_reserve (v, nelems, false PASS_MEM_STAT);
719}
720
721
722/* Free the GC memory allocated by vector V and set it to NULL. */
723
724template<typename T, typename A>
725inline void
726vec_free (vec<T, A, vl_embed> *&v)
727{
728 A::release (v);
729}
730
731
732/* Grow V to length LEN. Allocate it, if necessary. */
733template<typename T, typename A>
734inline void
735vec_safe_grow (vec<T, A, vl_embed> *&v, unsigned len,
736 bool exact = false CXX_MEM_STAT_INFO)
737{
738 unsigned oldlen = vec_safe_length (v);
739 gcc_checking_assert (len >= oldlen)((void)(!(len >= oldlen) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 739, __FUNCTION__), 0 : 0))
;
740 vec_safe_reserve (v, len - oldlen, exact PASS_MEM_STAT);
741 v->quick_grow (len);
742}
743
744
745/* If V is NULL, allocate it. Call V->safe_grow_cleared(LEN). */
746template<typename T, typename A>
747inline void
748vec_safe_grow_cleared (vec<T, A, vl_embed> *&v, unsigned len,
749 bool exact = false CXX_MEM_STAT_INFO)
750{
751 unsigned oldlen = vec_safe_length (v);
752 vec_safe_grow (v, len, exact PASS_MEM_STAT);
753 vec_default_construct (v->address () + oldlen, len - oldlen);
754}
755
756
757/* Assume V is not NULL. */
758
759template<typename T>
760inline void
761vec_safe_grow_cleared (vec<T, va_heap, vl_ptr> *&v,
762 unsigned len, bool exact = false CXX_MEM_STAT_INFO)
763{
764 v->safe_grow_cleared (len, exact PASS_MEM_STAT);
765}
766
767/* If V does not have space for NELEMS elements, call
768 V->reserve(NELEMS, EXACT). */
769
770template<typename T>
771inline bool
772vec_safe_reserve (vec<T, va_heap, vl_ptr> *&v, unsigned nelems, bool exact = false
773 CXX_MEM_STAT_INFO)
774{
775 return v->reserve (nelems, exact);
776}
777
778
779/* If V is NULL return false, otherwise return V->iterate(IX, PTR). */
780template<typename T, typename A>
781inline bool
782vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T **ptr)
783{
784 if (v)
785 return v->iterate (ix, ptr);
786 else
787 {
788 *ptr = 0;
789 return false;
790 }
791}
792
793template<typename T, typename A>
794inline bool
795vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T *ptr)
796{
797 if (v)
798 return v->iterate (ix, ptr);
799 else
800 {
801 *ptr = 0;
802 return false;
803 }
804}
805
806
807/* If V has no room for one more element, reallocate it. Then call
808 V->quick_push(OBJ). */
809template<typename T, typename A>
810inline T *
811vec_safe_push (vec<T, A, vl_embed> *&v, const T &obj CXX_MEM_STAT_INFO)
812{
813 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>'
814 return v->quick_push (obj);
45
Called C++ object pointer is null
815}
816
817
818/* if V has no room for one more element, reallocate it. Then call
819 V->quick_insert(IX, OBJ). */
820template<typename T, typename A>
821inline void
822vec_safe_insert (vec<T, A, vl_embed> *&v, unsigned ix, const T &obj
823 CXX_MEM_STAT_INFO)
824{
825 vec_safe_reserve (v, 1, false PASS_MEM_STAT);
826 v->quick_insert (ix, obj);
827}
828
829
830/* If V is NULL, do nothing. Otherwise, call V->truncate(SIZE). */
831template<typename T, typename A>
832inline void
833vec_safe_truncate (vec<T, A, vl_embed> *v, unsigned size)
834{
835 if (v)
836 v->truncate (size);
837}
838
839
840/* If SRC is not NULL, return a pointer to a copy of it. */
841template<typename T, typename A>
842inline vec<T, A, vl_embed> *
843vec_safe_copy (vec<T, A, vl_embed> *src CXX_MEM_STAT_INFO)
844{
845 return src ? src->copy (ALONE_PASS_MEM_STAT) : NULLnullptr;
846}
847
848/* Copy the elements from SRC to the end of DST as if by memcpy.
849 Reallocate DST, if necessary. */
850template<typename T, typename A>
851inline void
852vec_safe_splice (vec<T, A, vl_embed> *&dst, const vec<T, A, vl_embed> *src
853 CXX_MEM_STAT_INFO)
854{
855 unsigned src_len = vec_safe_length (src);
856 if (src_len)
857 {
858 vec_safe_reserve_exact (dst, vec_safe_length (dst) + src_len
859 PASS_MEM_STAT);
860 dst->splice (*src);
861 }
862}
863
864/* Return true if SEARCH is an element of V. Note that this is O(N) in the
865 size of the vector and so should be used with care. */
866
867template<typename T, typename A>
868inline bool
869vec_safe_contains (vec<T, A, vl_embed> *v, const T &search)
870{
871 return v ? v->contains (search) : false;
872}
873
874/* Index into vector. Return the IX'th element. IX must be in the
875 domain of the vector. */
876
877template<typename T, typename A>
878inline const T &
879vec<T, A, vl_embed>::operator[] (unsigned ix) const
880{
881 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"
, 881, __FUNCTION__), 0 : 0))
;
882 return m_vecdata[ix];
883}
884
885template<typename T, typename A>
886inline T &
887vec<T, A, vl_embed>::operator[] (unsigned ix)
888{
889 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"
, 889, __FUNCTION__), 0 : 0))
;
890 return m_vecdata[ix];
891}
892
893
894/* Get the final element of the vector, which must not be empty. */
895
896template<typename T, typename A>
897inline T &
898vec<T, A, vl_embed>::last (void)
899{
900 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"
, 900, __FUNCTION__), 0 : 0))
;
901 return (*this)[m_vecpfx.m_num - 1];
902}
903
904
905/* If this vector has space for NELEMS additional entries, return
906 true. You usually only need to use this if you are doing your
907 own vector reallocation, for instance on an embedded vector. This
908 returns true in exactly the same circumstances that vec::reserve
909 will. */
910
911template<typename T, typename A>
912inline bool
913vec<T, A, vl_embed>::space (unsigned nelems) const
914{
915 return m_vecpfx.m_alloc - m_vecpfx.m_num >= nelems;
916}
917
918
919/* Return iteration condition and update PTR to point to the IX'th
920 element of this vector. Use this to iterate over the elements of a
921 vector as follows,
922
923 for (ix = 0; vec<T, A>::iterate (v, ix, &ptr); ix++)
924 continue; */
925
926template<typename T, typename A>
927inline bool
928vec<T, A, vl_embed>::iterate (unsigned ix, T *ptr) const
929{
930 if (ix < m_vecpfx.m_num)
931 {
932 *ptr = m_vecdata[ix];
933 return true;
934 }
935 else
936 {
937 *ptr = 0;
938 return false;
939 }
940}
941
942
943/* Return iteration condition and update *PTR to point to the
944 IX'th element of this vector. Use this to iterate over the
945 elements of a vector as follows,
946
947 for (ix = 0; v->iterate (ix, &ptr); ix++)
948 continue;
949
950 This variant is for vectors of objects. */
951
952template<typename T, typename A>
953inline bool
954vec<T, A, vl_embed>::iterate (unsigned ix, T **ptr) const
955{
956 if (ix < m_vecpfx.m_num)
957 {
958 *ptr = CONST_CAST (T *, &m_vecdata[ix])(const_cast<T *> ((&m_vecdata[ix])));
959 return true;
960 }
961 else
962 {
963 *ptr = 0;
964 return false;
965 }
966}
967
968
969/* Return a pointer to a copy of this vector. */
970
971template<typename T, typename A>
972inline vec<T, A, vl_embed> *
973vec<T, A, vl_embed>::copy (ALONE_MEM_STAT_DECLvoid) const
974{
975 vec<T, A, vl_embed> *new_vec = NULLnullptr;
976 unsigned len = length ();
977 if (len)
978 {
979 vec_alloc (new_vec, len PASS_MEM_STAT);
980 new_vec->embedded_init (len, len);
981 vec_copy_construct (new_vec->address (), m_vecdata, len);
982 }
983 return new_vec;
984}
985
986
987/* Copy the elements from SRC to the end of this vector as if by memcpy.
988 The vector must have sufficient headroom available. */
989
990template<typename T, typename A>
991inline void
992vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> &src)
993{
994 unsigned len = src.length ();
995 if (len)
996 {
997 gcc_checking_assert (space (len))((void)(!(space (len)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 997, __FUNCTION__), 0 : 0))
;
998 vec_copy_construct (end (), src.address (), len);
999 m_vecpfx.m_num += len;
1000 }
1001}
1002
1003template<typename T, typename A>
1004inline void
1005vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> *src)
1006{
1007 if (src)
1008 splice (*src);
1009}
1010
1011
1012/* Push OBJ (a new element) onto the end of the vector. There must be
1013 sufficient space in the vector. Return a pointer to the slot
1014 where OBJ was inserted. */
1015
1016template<typename T, typename A>
1017inline T *
1018vec<T, A, vl_embed>::quick_push (const T &obj)
1019{
1020 gcc_checking_assert (space (1))((void)(!(space (1)) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1020, __FUNCTION__), 0 : 0))
;
1021 T *slot = &m_vecdata[m_vecpfx.m_num++];
1022 *slot = obj;
1023 return slot;
1024}
1025
1026
1027/* Pop and return the last element off the end of the vector. */
1028
1029template<typename T, typename A>
1030inline T &
1031vec<T, A, vl_embed>::pop (void)
1032{
1033 gcc_checking_assert (length () > 0)((void)(!(length () > 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1033, __FUNCTION__), 0 : 0))
;
1034 return m_vecdata[--m_vecpfx.m_num];
1035}
1036
1037
1038/* Set the length of the vector to SIZE. The new length must be less
1039 than or equal to the current length. This is an O(1) operation. */
1040
1041template<typename T, typename A>
1042inline void
1043vec<T, A, vl_embed>::truncate (unsigned size)
1044{
1045 gcc_checking_assert (length () >= size)((void)(!(length () >= size) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1045, __FUNCTION__), 0 : 0))
;
1046 m_vecpfx.m_num = size;
1047}
1048
1049
1050/* Insert an element, OBJ, at the IXth position of this vector. There
1051 must be sufficient space. */
1052
1053template<typename T, typename A>
1054inline void
1055vec<T, A, vl_embed>::quick_insert (unsigned ix, const T &obj)
1056{
1057 gcc_checking_assert (length () < allocated ())((void)(!(length () < allocated ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1057, __FUNCTION__), 0 : 0))
;
1058 gcc_checking_assert (ix <= length ())((void)(!(ix <= length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1058, __FUNCTION__), 0 : 0))
;
1059 T *slot = &m_vecdata[ix];
1060 memmove (slot + 1, slot, (m_vecpfx.m_num++ - ix) * sizeof (T));
1061 *slot = obj;
1062}
1063
1064
1065/* Remove an element from the IXth position of this vector. Ordering of
1066 remaining elements is preserved. This is an O(N) operation due to
1067 memmove. */
1068
1069template<typename T, typename A>
1070inline void
1071vec<T, A, vl_embed>::ordered_remove (unsigned ix)
1072{
1073 gcc_checking_assert (ix < length ())((void)(!(ix < length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1073, __FUNCTION__), 0 : 0))
;
1074 T *slot = &m_vecdata[ix];
1075 memmove (slot, slot + 1, (--m_vecpfx.m_num - ix) * sizeof (T));
1076}
1077
1078
1079/* Remove elements in [START, END) from VEC for which COND holds. Ordering of
1080 remaining elements is preserved. This is an O(N) operation. */
1081
1082#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"
, 1083, __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
); }
1083 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"
, 1083, __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 { \
1085 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"
, 1085, __FUNCTION__), 0 : 0))
; \
1086 for (read_index = write_index = (start); read_index < (end); \
1087 ++read_index) \
1088 { \
1089 elem_ptr = &(vec)[read_index]; \
1090 bool remove_p = (cond); \
1091 if (remove_p) \
1092 continue; \
1093 \
1094 if (read_index != write_index) \
1095 (vec)[write_index] = (vec)[read_index]; \
1096 \
1097 write_index++; \
1098 } \
1099 \
1100 if (read_index - write_index > 0) \
1101 (vec).block_remove (write_index, read_index - write_index); \
1102 }
1103
1104
1105/* Remove elements from VEC for which COND holds. Ordering of remaining
1106 elements is preserved. This is an O(N) operation. */
1107
1108#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"
, 1109, __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
); }
1109 cond){ ((void)(!(((vec).length ()) <= ((vec)).length ()) ? fancy_abort
("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1109, __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 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"
, 1111, __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 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"
, 1111, __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
1113/* Remove an element from the IXth position of this vector. Ordering of
1114 remaining elements is destroyed. This is an O(1) operation. */
1115
1116template<typename T, typename A>
1117inline void
1118vec<T, A, vl_embed>::unordered_remove (unsigned ix)
1119{
1120 gcc_checking_assert (ix < length ())((void)(!(ix < length ()) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1120, __FUNCTION__), 0 : 0))
;
1121 m_vecdata[ix] = m_vecdata[--m_vecpfx.m_num];
1122}
1123
1124
1125/* Remove LEN elements starting at the IXth. Ordering is retained.
1126 This is an O(N) operation due to memmove. */
1127
1128template<typename T, typename A>
1129inline void
1130vec<T, A, vl_embed>::block_remove (unsigned ix, unsigned len)
1131{
1132 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"
, 1132, __FUNCTION__), 0 : 0))
;
1133 T *slot = &m_vecdata[ix];
1134 m_vecpfx.m_num -= len;
1135 memmove (slot, slot + len, (m_vecpfx.m_num - ix) * sizeof (T));
1136}
1137
1138
1139/* Sort the contents of this vector with qsort. CMP is the comparison
1140 function to pass to qsort. */
1141
1142template<typename T, typename A>
1143inline void
1144vec<T, A, vl_embed>::qsort (int (*cmp) (const void *, const void *))qsort (int (*cmp) (const void *, const void *))
1145{
1146 if (length () > 1)
1147 gcc_qsort (address (), length (), sizeof (T), cmp);
1148}
1149
1150/* Sort the contents of this vector with qsort. CMP is the comparison
1151 function to pass to qsort. */
1152
1153template<typename T, typename A>
1154inline void
1155vec<T, A, vl_embed>::sort (int (*cmp) (const void *, const void *, void *),
1156 void *data)
1157{
1158 if (length () > 1)
1159 gcc_sort_r (address (), length (), sizeof (T), cmp, data);
1160}
1161
1162/* Sort the contents of this vector with gcc_stablesort_r. CMP is the
1163 comparison function to pass to qsort. */
1164
1165template<typename T, typename A>
1166inline void
1167vec<T, A, vl_embed>::stablesort (int (*cmp) (const void *, const void *,
1168 void *), void *data)
1169{
1170 if (length () > 1)
1171 gcc_stablesort_r (address (), length (), sizeof (T), cmp, data);
1172}
1173
1174/* Search the contents of the sorted vector with a binary search.
1175 CMP is the comparison function to pass to bsearch. */
1176
1177template<typename T, typename A>
1178inline T *
1179vec<T, A, vl_embed>::bsearch (const void *key,
1180 int (*compar) (const void *, const void *))
1181{
1182 const void *base = this->address ();
1183 size_t nmemb = this->length ();
1184 size_t size = sizeof (T);
1185 /* The following is a copy of glibc stdlib-bsearch.h. */
1186 size_t l, u, idx;
1187 const void *p;
1188 int comparison;
1189
1190 l = 0;
1191 u = nmemb;
1192 while (l < u)
1193 {
1194 idx = (l + u) / 2;
1195 p = (const void *) (((const char *) base) + (idx * size));
1196 comparison = (*compar) (key, p);
1197 if (comparison < 0)
1198 u = idx;
1199 else if (comparison > 0)
1200 l = idx + 1;
1201 else
1202 return (T *)const_cast<void *>(p);
1203 }
1204
1205 return NULLnullptr;
1206}
1207
1208/* Search the contents of the sorted vector with a binary search.
1209 CMP is the comparison function to pass to bsearch. */
1210
1211template<typename T, typename A>
1212inline T *
1213vec<T, A, vl_embed>::bsearch (const void *key,
1214 int (*compar) (const void *, const void *,
1215 void *), void *data)
1216{
1217 const void *base = this->address ();
1218 size_t nmemb = this->length ();
1219 size_t size = sizeof (T);
1220 /* The following is a copy of glibc stdlib-bsearch.h. */
1221 size_t l, u, idx;
1222 const void *p;
1223 int comparison;
1224
1225 l = 0;
1226 u = nmemb;
1227 while (l < u)
1228 {
1229 idx = (l + u) / 2;
1230 p = (const void *) (((const char *) base) + (idx * size));
1231 comparison = (*compar) (key, p, data);
1232 if (comparison < 0)
1233 u = idx;
1234 else if (comparison > 0)
1235 l = idx + 1;
1236 else
1237 return (T *)const_cast<void *>(p);
1238 }
1239
1240 return NULLnullptr;
1241}
1242
1243/* Return true if SEARCH is an element of V. Note that this is O(N) in the
1244 size of the vector and so should be used with care. */
1245
1246template<typename T, typename A>
1247inline bool
1248vec<T, A, vl_embed>::contains (const T &search) const
1249{
1250 unsigned int len = length ();
1251 for (unsigned int i = 0; i < len; i++)
1252 if ((*this)[i] == search)
1253 return true;
1254
1255 return false;
1256}
1257
1258/* Find and return the first position in which OBJ could be inserted
1259 without changing the ordering of this vector. LESSTHAN is a
1260 function that returns true if the first argument is strictly less
1261 than the second. */
1262
1263template<typename T, typename A>
1264unsigned
1265vec<T, A, vl_embed>::lower_bound (T obj, bool (*lessthan)(const T &, const T &))
1266 const
1267{
1268 unsigned int len = length ();
1269 unsigned int half, middle;
1270 unsigned int first = 0;
1271 while (len > 0)
1272 {
1273 half = len / 2;
1274 middle = first;
1275 middle += half;
1276 T middle_elem = (*this)[middle];
1277 if (lessthan (middle_elem, obj))
1278 {
1279 first = middle;
1280 ++first;
1281 len = len - half - 1;
1282 }
1283 else
1284 len = half;
1285 }
1286 return first;
1287}
1288
1289
1290/* Return the number of bytes needed to embed an instance of an
1291 embeddable vec inside another data structure.
1292
1293 Use these methods to determine the required size and initialization
1294 of a vector V of type T embedded within another structure (as the
1295 final member):
1296
1297 size_t vec<T, A, vl_embed>::embedded_size (unsigned alloc);
1298 void v->embedded_init (unsigned alloc, unsigned num);
1299
1300 These allow the caller to perform the memory allocation. */
1301
1302template<typename T, typename A>
1303inline size_t
1304vec<T, A, vl_embed>::embedded_size (unsigned alloc)
1305{
1306 struct alignas (T) U { char data[sizeof (T)]; };
1307 typedef vec<U, A, vl_embed> vec_embedded;
1308 typedef typename std::conditional<std::is_standard_layout<T>::value,
1309 vec, vec_embedded>::type vec_stdlayout;
1310 static_assert (sizeof (vec_stdlayout) == sizeof (vec), "");
1311 static_assert (alignof (vec_stdlayout) == alignof (vec), "");
1312 return offsetof (vec_stdlayout, m_vecdata)__builtin_offsetof(vec_stdlayout, m_vecdata) + alloc * sizeof (T);
1313}
1314
1315
1316/* Initialize the vector to contain room for ALLOC elements and
1317 NUM active elements. */
1318
1319template<typename T, typename A>
1320inline void
1321vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num, unsigned aut)
1322{
1323 m_vecpfx.m_alloc = alloc;
1324 m_vecpfx.m_using_auto_storage = aut;
1325 m_vecpfx.m_num = num;
1326}
1327
1328
1329/* Grow the vector to a specific length. LEN must be as long or longer than
1330 the current length. The new elements are uninitialized. */
1331
1332template<typename T, typename A>
1333inline void
1334vec<T, A, vl_embed>::quick_grow (unsigned len)
1335{
1336 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"
, 1336, __FUNCTION__), 0 : 0))
;
1337 m_vecpfx.m_num = len;
1338}
1339
1340
1341/* Grow the vector to a specific length. LEN must be as long or longer than
1342 the current length. The new elements are initialized to zero. */
1343
1344template<typename T, typename A>
1345inline void
1346vec<T, A, vl_embed>::quick_grow_cleared (unsigned len)
1347{
1348 unsigned oldlen = length ();
1349 size_t growby = len - oldlen;
1350 quick_grow (len);
1351 if (growby != 0)
1352 vec_default_construct (address () + oldlen, growby);
1353}
1354
1355/* Garbage collection support for vec<T, A, vl_embed>. */
1356
1357template<typename T>
1358void
1359gt_ggc_mx (vec<T, va_gc> *v)
1360{
1361 extern void gt_ggc_mx (T &);
1362 for (unsigned i = 0; i < v->length (); i++)
1363 gt_ggc_mx ((*v)[i]);
1364}
1365
1366template<typename T>
1367void
1368gt_ggc_mx (vec<T, va_gc_atomic, vl_embed> *v ATTRIBUTE_UNUSED__attribute__ ((__unused__)))
1369{
1370 /* Nothing to do. Vectors of atomic types wrt GC do not need to
1371 be traversed. */
1372}
1373
1374
1375/* PCH support for vec<T, A, vl_embed>. */
1376
1377template<typename T, typename A>
1378void
1379gt_pch_nx (vec<T, A, vl_embed> *v)
1380{
1381 extern void gt_pch_nx (T &);
1382 for (unsigned i = 0; i < v->length (); i++)
1383 gt_pch_nx ((*v)[i]);
1384}
1385
1386template<typename T, typename A>
1387void
1388gt_pch_nx (vec<T *, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
1389{
1390 for (unsigned i = 0; i < v->length (); i++)
1391 op (&((*v)[i]), cookie);
1392}
1393
1394template<typename T, typename A>
1395void
1396gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
1397{
1398 extern void gt_pch_nx (T *, gt_pointer_operator, void *);
1399 for (unsigned i = 0; i < v->length (); i++)
1400 gt_pch_nx (&((*v)[i]), op, cookie);
1401}
1402
1403
1404/* Space efficient vector. These vectors can grow dynamically and are
1405 allocated together with their control data. They are suited to be
1406 included in data structures. Prior to initial allocation, they
1407 only take a single word of storage.
1408
1409 These vectors are implemented as a pointer to an embeddable vector.
1410 The semantics allow for this pointer to be NULL to represent empty
1411 vectors. This way, empty vectors occupy minimal space in the
1412 structure containing them.
1413
1414 Properties:
1415
1416 - The whole vector and control data are allocated in a single
1417 contiguous block.
1418 - The whole vector may be re-allocated.
1419 - Vector data may grow and shrink.
1420 - Access and manipulation requires a pointer test and
1421 indirection.
1422 - It requires 1 word of storage (prior to vector allocation).
1423
1424
1425 Limitations:
1426
1427 These vectors must be PODs because they are stored in unions.
1428 (http://en.wikipedia.org/wiki/Plain_old_data_structures).
1429 As long as we use C++03, we cannot have constructors nor
1430 destructors in classes that are stored in unions. */
1431
1432template<typename T, size_t N = 0>
1433class auto_vec;
1434
1435template<typename T>
1436struct vec<T, va_heap, vl_ptr>
1437{
1438public:
1439 /* Default ctors to ensure triviality. Use value-initialization
1440 (e.g., vec() or vec v{ };) or vNULL to create a zero-initialized
1441 instance. */
1442 vec () = default;
1443 vec (const vec &) = default;
1444 /* Initialization from the generic vNULL. */
1445 vec (vnull): m_vec () { }
1446 /* Same as default ctor: vec storage must be released manually. */
1447 ~vec () = default;
1448
1449 /* Defaulted same as copy ctor. */
1450 vec& operator= (const vec &) = default;
1451
1452 /* Prevent implicit conversion from auto_vec. Use auto_vec::to_vec()
1453 instead. */
1454 template <size_t N>
1455 vec (auto_vec<T, N> &) = delete;
1456
1457 template <size_t N>
1458 void operator= (auto_vec<T, N> &) = delete;
1459
1460 /* Memory allocation and deallocation for the embedded vector.
1461 Needed because we cannot have proper ctors/dtors defined. */
1462 void create (unsigned nelems CXX_MEM_STAT_INFO);
1463 void release (void);
1464
1465 /* Vector operations. */
1466 bool exists (void) const
1467 { return m_vec != NULLnullptr; }
1468
1469 bool is_empty (void) const
1470 { return m_vec ? m_vec->is_empty () : true; }
1471
1472 unsigned length (void) const
1473 { return m_vec ? m_vec->length () : 0; }
1474
1475 T *address (void)
1476 { return m_vec ? m_vec->m_vecdata : NULLnullptr; }
1477
1478 const T *address (void) const
1479 { return m_vec ? m_vec->m_vecdata : NULLnullptr; }
1480
1481 T *begin () { return address (); }
1482 const T *begin () const { return address (); }
1483 T *end () { return begin () + length (); }
1484 const T *end () const { return begin () + length (); }
1485 const T &operator[] (unsigned ix) const
1486 { return (*m_vec)[ix]; }
1487
1488 bool operator!=(const vec &other) const
1489 { return !(*this == other); }
1490
1491 bool operator==(const vec &other) const
1492 { return address () == other.address (); }
1493
1494 T &operator[] (unsigned ix)
1495 { return (*m_vec)[ix]; }
1496
1497 T &last (void)
1498 { return m_vec->last (); }
1499
1500 bool space (int nelems) const
1501 { return m_vec ? m_vec->space (nelems) : nelems == 0; }
1502
1503 bool iterate (unsigned ix, T *p) const;
1504 bool iterate (unsigned ix, T **p) const;
1505 vec copy (ALONE_CXX_MEM_STAT_INFO) const;
1506 bool reserve (unsigned, bool = false CXX_MEM_STAT_INFO);
1507 bool reserve_exact (unsigned CXX_MEM_STAT_INFO);
1508 void splice (const vec &);
1509 void safe_splice (const vec & CXX_MEM_STAT_INFO);
1510 T *quick_push (const T &);
1511 T *safe_push (const T &CXX_MEM_STAT_INFO);
1512 T &pop (void);
1513 void truncate (unsigned);
1514 void safe_grow (unsigned, bool = false CXX_MEM_STAT_INFO);
1515 void safe_grow_cleared (unsigned, bool = false CXX_MEM_STAT_INFO);
1516 void quick_grow (unsigned);
1517 void quick_grow_cleared (unsigned);
1518 void quick_insert (unsigned, const T &);
1519 void safe_insert (unsigned, const T & CXX_MEM_STAT_INFO);
1520 void ordered_remove (unsigned);
1521 void unordered_remove (unsigned);
1522 void block_remove (unsigned, unsigned);
1523 void qsort (int (*) (const void *, const void *))qsort (int (*) (const void *, const void *));
1524 void sort (int (*) (const void *, const void *, void *), void *);
1525 void stablesort (int (*) (const void *, const void *, void *), void *);
1526 T *bsearch (const void *key, int (*compar)(const void *, const void *));
1527 T *bsearch (const void *key,
1528 int (*compar)(const void *, const void *, void *), void *);
1529 unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
1530 bool contains (const T &search) const;
1531 void reverse (void);
1532
1533 bool using_auto_storage () const;
1534
1535 /* FIXME - This field should be private, but we need to cater to
1536 compilers that have stricter notions of PODness for types. */
1537 vec<T, va_heap, vl_embed> *m_vec;
1538};
1539
1540
1541/* auto_vec is a subclass of vec that automatically manages creating and
1542 releasing the internal vector. If N is non zero then it has N elements of
1543 internal storage. The default is no internal storage, and you probably only
1544 want to ask for internal storage for vectors on the stack because if the
1545 size of the vector is larger than the internal storage that space is wasted.
1546 */
1547template<typename T, size_t N /* = 0 */>
1548class auto_vec : public vec<T, va_heap>
1549{
1550public:
1551 auto_vec ()
1552 {
1553 m_auto.embedded_init (MAX (N, 2)((N) > (2) ? (N) : (2)), 0, 1);
1554 this->m_vec = &m_auto;
1555 }
1556
1557 auto_vec (size_t s CXX_MEM_STAT_INFO)
1558 {
1559 if (s > N)
1560 {
1561 this->create (s PASS_MEM_STAT);
1562 return;
1563 }
1564
1565 m_auto.embedded_init (MAX (N, 2)((N) > (2) ? (N) : (2)), 0, 1);
1566 this->m_vec = &m_auto;
1567 }
1568
1569 ~auto_vec ()
1570 {
1571 this->release ();
1572 }
1573
1574 /* Explicitly convert to the base class. There is no conversion
1575 from a const auto_vec because a copy of the returned vec can
1576 be used to modify *THIS.
1577 This is a legacy function not to be used in new code. */
1578 vec<T, va_heap> to_vec_legacy () {
1579 return *static_cast<vec<T, va_heap> *>(this);
1580 }
1581
1582private:
1583 vec<T, va_heap, vl_embed> m_auto;
1584 T m_data[MAX (N - 1, 1)((N - 1) > (1) ? (N - 1) : (1))];
1585};
1586
1587/* auto_vec is a sub class of vec whose storage is released when it is
1588 destroyed. */
1589template<typename T>
1590class auto_vec<T, 0> : public vec<T, va_heap>
1591{
1592public:
1593 auto_vec () { this->m_vec = NULLnullptr; }
1594 auto_vec (size_t n CXX_MEM_STAT_INFO) { this->create (n PASS_MEM_STAT); }
1595 ~auto_vec () { this->release (); }
1596
1597 auto_vec (vec<T, va_heap>&& r)
1598 {
1599 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"
, 1599, __FUNCTION__), 0 : 0))
;
1600 this->m_vec = r.m_vec;
1601 r.m_vec = NULLnullptr;
1602 }
1603
1604 auto_vec (auto_vec<T> &&r)
1605 {
1606 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"
, 1606, __FUNCTION__), 0 : 0))
;
1607 this->m_vec = r.m_vec;
1608 r.m_vec = NULLnullptr;
1609 }
1610
1611 auto_vec& operator= (vec<T, va_heap>&& r)
1612 {
1613 if (this == &r)
1614 return *this;
1615
1616 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"
, 1616, __FUNCTION__), 0 : 0))
;
1617 this->release ();
1618 this->m_vec = r.m_vec;
1619 r.m_vec = NULLnullptr;
1620 return *this;
1621 }
1622
1623 auto_vec& operator= (auto_vec<T> &&r)
1624 {
1625 if (this == &r)
1626 return *this;
1627
1628 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"
, 1628, __FUNCTION__), 0 : 0))
;
1629 this->release ();
1630 this->m_vec = r.m_vec;
1631 r.m_vec = NULLnullptr;
1632 return *this;
1633 }
1634
1635 /* Explicitly convert to the base class. There is no conversion
1636 from a const auto_vec because a copy of the returned vec can
1637 be used to modify *THIS.
1638 This is a legacy function not to be used in new code. */
1639 vec<T, va_heap> to_vec_legacy () {
1640 return *static_cast<vec<T, va_heap> *>(this);
1641 }
1642
1643 // You probably don't want to copy a vector, so these are deleted to prevent
1644 // unintentional use. If you really need a copy of the vectors contents you
1645 // can use copy ().
1646 auto_vec(const auto_vec &) = delete;
1647 auto_vec &operator= (const auto_vec &) = delete;
1648};
1649
1650
1651/* Allocate heap memory for pointer V and create the internal vector
1652 with space for NELEMS elements. If NELEMS is 0, the internal
1653 vector is initialized to empty. */
1654
1655template<typename T>
1656inline void
1657vec_alloc (vec<T> *&v, unsigned nelems CXX_MEM_STAT_INFO)
1658{
1659 v = new vec<T>;
1660 v->create (nelems PASS_MEM_STAT);
1661}
1662
1663
1664/* A subclass of auto_vec <char *> that frees all of its elements on
1665 deletion. */
1666
1667class auto_string_vec : public auto_vec <char *>
1668{
1669 public:
1670 ~auto_string_vec ();
1671};
1672
1673/* A subclass of auto_vec <T *> that deletes all of its elements on
1674 destruction.
1675
1676 This is a crude way for a vec to "own" the objects it points to
1677 and clean up automatically.
1678
1679 For example, no attempt is made to delete elements when an item
1680 within the vec is overwritten.
1681
1682 We can't rely on gnu::unique_ptr within a container,
1683 since we can't rely on move semantics in C++98. */
1684
1685template <typename T>
1686class auto_delete_vec : public auto_vec <T *>
1687{
1688 public:
1689 auto_delete_vec () {}
1690 auto_delete_vec (size_t s) : auto_vec <T *> (s) {}
1691
1692 ~auto_delete_vec ();
1693
1694private:
1695 DISABLE_COPY_AND_ASSIGN(auto_delete_vec)auto_delete_vec (const auto_delete_vec&) = delete; void operator
= (const auto_delete_vec &) = delete
;
1696};
1697
1698/* Conditionally allocate heap memory for VEC and its internal vector. */
1699
1700template<typename T>
1701inline void
1702vec_check_alloc (vec<T, va_heap> *&vec, unsigned nelems CXX_MEM_STAT_INFO)
1703{
1704 if (!vec)
1705 vec_alloc (vec, nelems PASS_MEM_STAT);
1706}
1707
1708
1709/* Free the heap memory allocated by vector V and set it to NULL. */
1710
1711template<typename T>
1712inline void
1713vec_free (vec<T> *&v)
1714{
1715 if (v == NULLnullptr)
1716 return;
1717
1718 v->release ();
1719 delete v;
1720 v = NULLnullptr;
1721}
1722
1723
1724/* Return iteration condition and update PTR to point to the IX'th
1725 element of this vector. Use this to iterate over the elements of a
1726 vector as follows,
1727
1728 for (ix = 0; v.iterate (ix, &ptr); ix++)
1729 continue; */
1730
1731template<typename T>
1732inline bool
1733vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T *ptr) const
1734{
1735 if (m_vec)
1736 return m_vec->iterate (ix, ptr);
1737 else
1738 {
1739 *ptr = 0;
1740 return false;
1741 }
1742}
1743
1744
1745/* Return iteration condition and update *PTR to point to the
1746 IX'th element of this vector. Use this to iterate over the
1747 elements of a vector as follows,
1748
1749 for (ix = 0; v->iterate (ix, &ptr); ix++)
1750 continue;
1751
1752 This variant is for vectors of objects. */
1753
1754template<typename T>
1755inline bool
1756vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T **ptr) const
1757{
1758 if (m_vec)
1759 return m_vec->iterate (ix, ptr);
1760 else
1761 {
1762 *ptr = 0;
1763 return false;
1764 }
1765}
1766
1767
1768/* Convenience macro for forward iteration. */
1769#define FOR_EACH_VEC_ELT(V, I, P)for (I = 0; (V).iterate ((I), &(P)); ++(I)) \
1770 for (I = 0; (V).iterate ((I), &(P)); ++(I))
1771
1772#define FOR_EACH_VEC_SAFE_ELT(V, I, P)for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I)) \
1773 for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I))
1774
1775/* Likewise, but start from FROM rather than 0. */
1776#define FOR_EACH_VEC_ELT_FROM(V, I, P, FROM)for (I = (FROM); (V).iterate ((I), &(P)); ++(I)) \
1777 for (I = (FROM); (V).iterate ((I), &(P)); ++(I))
1778
1779/* Convenience macro for reverse iteration. */
1780#define FOR_EACH_VEC_ELT_REVERSE(V, I, P)for (I = (V).length () - 1; (V).iterate ((I), &(P)); (I)--
)
\
1781 for (I = (V).length () - 1; \
1782 (V).iterate ((I), &(P)); \
1783 (I)--)
1784
1785#define FOR_EACH_VEC_SAFE_ELT_REVERSE(V, I, P)for (I = vec_safe_length (V) - 1; vec_safe_iterate ((V), (I),
&(P)); (I)--)
\
1786 for (I = vec_safe_length (V) - 1; \
1787 vec_safe_iterate ((V), (I), &(P)); \
1788 (I)--)
1789
1790/* auto_string_vec's dtor, freeing all contained strings, automatically
1791 chaining up to ~auto_vec <char *>, which frees the internal buffer. */
1792
1793inline
1794auto_string_vec::~auto_string_vec ()
1795{
1796 int i;
1797 char *str;
1798 FOR_EACH_VEC_ELT (*this, i, str)for (i = 0; (*this).iterate ((i), &(str)); ++(i))
1799 free (str);
1800}
1801
1802/* auto_delete_vec's dtor, deleting all contained items, automatically
1803 chaining up to ~auto_vec <T*>, which frees the internal buffer. */
1804
1805template <typename T>
1806inline
1807auto_delete_vec<T>::~auto_delete_vec ()
1808{
1809 int i;
1810 T *item;
1811 FOR_EACH_VEC_ELT (*this, i, item)for (i = 0; (*this).iterate ((i), &(item)); ++(i))
1812 delete item;
1813}
1814
1815
1816/* Return a copy of this vector. */
1817
1818template<typename T>
1819inline vec<T, va_heap, vl_ptr>
1820vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECLvoid) const
1821{
1822 vec<T, va_heap, vl_ptr> new_vec{ };
1823 if (length ())
1824 new_vec.m_vec = m_vec->copy (ALONE_PASS_MEM_STAT);
1825 return new_vec;
1826}
1827
1828
1829/* Ensure that the vector has at least RESERVE slots available (if
1830 EXACT is false), or exactly RESERVE slots available (if EXACT is
1831 true).
1832
1833 This may create additional headroom if EXACT is false.
1834
1835 Note that this can cause the embedded vector to be reallocated.
1836 Returns true iff reallocation actually occurred. */
1837
1838template<typename T>
1839inline bool
1840vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL)
1841{
1842 if (space (nelems))
1843 return false;
1844
1845 /* For now play a game with va_heap::reserve to hide our auto storage if any,
1846 this is necessary because it doesn't have enough information to know the
1847 embedded vector is in auto storage, and so should not be freed. */
1848 vec<T, va_heap, vl_embed> *oldvec = m_vec;
1849 unsigned int oldsize = 0;
1850 bool handle_auto_vec = m_vec && using_auto_storage ();
1851 if (handle_auto_vec)
1852 {
1853 m_vec = NULLnullptr;
1854 oldsize = oldvec->length ();
1855 nelems += oldsize;
1856 }
1857
1858 va_heap::reserve (m_vec, nelems, exact PASS_MEM_STAT);
1859 if (handle_auto_vec)
1860 {
1861 vec_copy_construct (m_vec->address (), oldvec->address (), oldsize);
1862 m_vec->m_vecpfx.m_num = oldsize;
1863 }
1864
1865 return true;
1866}
1867
1868
1869/* Ensure that this vector has exactly NELEMS slots available. This
1870 will not create additional headroom. Note this can cause the
1871 embedded vector to be reallocated. Returns true iff reallocation
1872 actually occurred. */
1873
1874template<typename T>
1875inline bool
1876vec<T, va_heap, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL)
1877{
1878 return reserve (nelems, true PASS_MEM_STAT);
1879}
1880
1881
1882/* Create the internal vector and reserve NELEMS for it. This is
1883 exactly like vec::reserve, but the internal vector is
1884 unconditionally allocated from scratch. The old one, if it
1885 existed, is lost. */
1886
1887template<typename T>
1888inline void
1889vec<T, va_heap, vl_ptr>::create (unsigned nelems MEM_STAT_DECL)
1890{
1891 m_vec = NULLnullptr;
1892 if (nelems > 0)
1893 reserve_exact (nelems PASS_MEM_STAT);
1894}
1895
1896
1897/* Free the memory occupied by the embedded vector. */
1898
1899template<typename T>
1900inline void
1901vec<T, va_heap, vl_ptr>::release (void)
1902{
1903 if (!m_vec)
1904 return;
1905
1906 if (using_auto_storage ())
1907 {
1908 m_vec->m_vecpfx.m_num = 0;
1909 return;
1910 }
1911
1912 va_heap::release (m_vec);
1913}
1914
1915/* Copy the elements from SRC to the end of this vector as if by memcpy.
1916 SRC and this vector must be allocated with the same memory
1917 allocation mechanism. This vector is assumed to have sufficient
1918 headroom available. */
1919
1920template<typename T>
1921inline void
1922vec<T, va_heap, vl_ptr>::splice (const vec<T, va_heap, vl_ptr> &src)
1923{
1924 if (src.length ())
1925 m_vec->splice (*(src.m_vec));
1926}
1927
1928
1929/* Copy the elements in SRC to the end of this vector as if by memcpy.
1930 SRC and this vector must be allocated with the same mechanism.
1931 If there is not enough headroom in this vector, it will be reallocated
1932 as needed. */
1933
1934template<typename T>
1935inline void
1936vec<T, va_heap, vl_ptr>::safe_splice (const vec<T, va_heap, vl_ptr> &src
1937 MEM_STAT_DECL)
1938{
1939 if (src.length ())
1940 {
1941 reserve_exact (src.length ());
1942 splice (src);
1943 }
1944}
1945
1946
1947/* Push OBJ (a new element) onto the end of the vector. There must be
1948 sufficient space in the vector. Return a pointer to the slot
1949 where OBJ was inserted. */
1950
1951template<typename T>
1952inline T *
1953vec<T, va_heap, vl_ptr>::quick_push (const T &obj)
1954{
1955 return m_vec->quick_push (obj);
1956}
1957
1958
1959/* Push a new element OBJ onto the end of this vector. Reallocates
1960 the embedded vector, if needed. Return a pointer to the slot where
1961 OBJ was inserted. */
1962
1963template<typename T>
1964inline T *
1965vec<T, va_heap, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL)
1966{
1967 reserve (1, false PASS_MEM_STAT);
1968 return quick_push (obj);
1969}
1970
1971
1972/* Pop and return the last element off the end of the vector. */
1973
1974template<typename T>
1975inline T &
1976vec<T, va_heap, vl_ptr>::pop (void)
1977{
1978 return m_vec->pop ();
1979}
1980
1981
1982/* Set the length of the vector to LEN. The new length must be less
1983 than or equal to the current length. This is an O(1) operation. */
1984
1985template<typename T>
1986inline void
1987vec<T, va_heap, vl_ptr>::truncate (unsigned size)
1988{
1989 if (m_vec)
1990 m_vec->truncate (size);
1991 else
1992 gcc_checking_assert (size == 0)((void)(!(size == 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 1992, __FUNCTION__), 0 : 0))
;
1993}
1994
1995
1996/* Grow the vector to a specific length. LEN must be as long or
1997 longer than the current length. The new elements are
1998 uninitialized. Reallocate the internal vector, if needed. */
1999
2000template<typename T>
2001inline void
2002vec<T, va_heap, vl_ptr>::safe_grow (unsigned len, bool exact MEM_STAT_DECL)
2003{
2004 unsigned oldlen = length ();
2005 gcc_checking_assert (oldlen <= len)((void)(!(oldlen <= len) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2005, __FUNCTION__), 0 : 0))
;
2006 reserve (len - oldlen, exact PASS_MEM_STAT);
2007 if (m_vec)
2008 m_vec->quick_grow (len);
2009 else
2010 gcc_checking_assert (len == 0)((void)(!(len == 0) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2010, __FUNCTION__), 0 : 0))
;
2011}
2012
2013
2014/* Grow the embedded vector to a specific length. LEN must be as
2015 long or longer than the current length. The new elements are
2016 initialized to zero. Reallocate the internal vector, if needed. */
2017
2018template<typename T>
2019inline void
2020vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len, bool exact
2021 MEM_STAT_DECL)
2022{
2023 unsigned oldlen = length ();
2024 size_t growby = len - oldlen;
2025 safe_grow (len, exact PASS_MEM_STAT);
2026 if (growby != 0)
2027 vec_default_construct (address () + oldlen, growby);
2028}
2029
2030
2031/* Same as vec::safe_grow but without reallocation of the internal vector.
2032 If the vector cannot be extended, a runtime assertion will be triggered. */
2033
2034template<typename T>
2035inline void
2036vec<T, va_heap, vl_ptr>::quick_grow (unsigned len)
2037{
2038 gcc_checking_assert (m_vec)((void)(!(m_vec) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2038, __FUNCTION__), 0 : 0))
;
2039 m_vec->quick_grow (len);
2040}
2041
2042
2043/* Same as vec::quick_grow_cleared but without reallocation of the
2044 internal vector. If the vector cannot be extended, a runtime
2045 assertion will be triggered. */
2046
2047template<typename T>
2048inline void
2049vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len)
2050{
2051 gcc_checking_assert (m_vec)((void)(!(m_vec) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2051, __FUNCTION__), 0 : 0))
;
2052 m_vec->quick_grow_cleared (len);
2053}
2054
2055
2056/* Insert an element, OBJ, at the IXth position of this vector. There
2057 must be sufficient space. */
2058
2059template<typename T>
2060inline void
2061vec<T, va_heap, vl_ptr>::quick_insert (unsigned ix, const T &obj)
2062{
2063 m_vec->quick_insert (ix, obj);
2064}
2065
2066
2067/* Insert an element, OBJ, at the IXth position of the vector.
2068 Reallocate the embedded vector, if necessary. */
2069
2070template<typename T>
2071inline void
2072vec<T, va_heap, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL)
2073{
2074 reserve (1, false PASS_MEM_STAT);
2075 quick_insert (ix, obj);
2076}
2077
2078
2079/* Remove an element from the IXth position of this vector. Ordering of
2080 remaining elements is preserved. This is an O(N) operation due to
2081 a memmove. */
2082
2083template<typename T>
2084inline void
2085vec<T, va_heap, vl_ptr>::ordered_remove (unsigned ix)
2086{
2087 m_vec->ordered_remove (ix);
2088}
2089
2090
2091/* Remove an element from the IXth position of this vector. Ordering
2092 of remaining elements is destroyed. This is an O(1) operation. */
2093
2094template<typename T>
2095inline void
2096vec<T, va_heap, vl_ptr>::unordered_remove (unsigned ix)
2097{
2098 m_vec->unordered_remove (ix);
2099}
2100
2101
2102/* Remove LEN elements starting at the IXth. Ordering is retained.
2103 This is an O(N) operation due to memmove. */
2104
2105template<typename T>
2106inline void
2107vec<T, va_heap, vl_ptr>::block_remove (unsigned ix, unsigned len)
2108{
2109 m_vec->block_remove (ix, len);
2110}
2111
2112
2113/* Sort the contents of this vector with qsort. CMP is the comparison
2114 function to pass to qsort. */
2115
2116template<typename T>
2117inline void
2118vec<T, va_heap, vl_ptr>::qsort (int (*cmp) (const void *, const void *))qsort (int (*cmp) (const void *, const void *))
2119{
2120 if (m_vec)
2121 m_vec->qsort (cmp)qsort (cmp);
2122}
2123
2124/* Sort the contents of this vector with qsort. CMP is the comparison
2125 function to pass to qsort. */
2126
2127template<typename T>
2128inline void
2129vec<T, va_heap, vl_ptr>::sort (int (*cmp) (const void *, const void *,
2130 void *), void *data)
2131{
2132 if (m_vec)
2133 m_vec->sort (cmp, data);
2134}
2135
2136/* Sort the contents of this vector with gcc_stablesort_r. CMP is the
2137 comparison function to pass to qsort. */
2138
2139template<typename T>
2140inline void
2141vec<T, va_heap, vl_ptr>::stablesort (int (*cmp) (const void *, const void *,
2142 void *), void *data)
2143{
2144 if (m_vec)
2145 m_vec->stablesort (cmp, data);
2146}
2147
2148/* Search the contents of the sorted vector with a binary search.
2149 CMP is the comparison function to pass to bsearch. */
2150
2151template<typename T>
2152inline T *
2153vec<T, va_heap, vl_ptr>::bsearch (const void *key,
2154 int (*cmp) (const void *, const void *))
2155{
2156 if (m_vec)
2157 return m_vec->bsearch (key, cmp);
2158 return NULLnullptr;
2159}
2160
2161/* Search the contents of the sorted vector with a binary search.
2162 CMP is the comparison function to pass to bsearch. */
2163
2164template<typename T>
2165inline T *
2166vec<T, va_heap, vl_ptr>::bsearch (const void *key,
2167 int (*cmp) (const void *, const void *,
2168 void *), void *data)
2169{
2170 if (m_vec)
2171 return m_vec->bsearch (key, cmp, data);
2172 return NULLnullptr;
2173}
2174
2175
2176/* Find and return the first position in which OBJ could be inserted
2177 without changing the ordering of this vector. LESSTHAN is a
2178 function that returns true if the first argument is strictly less
2179 than the second. */
2180
2181template<typename T>
2182inline unsigned
2183vec<T, va_heap, vl_ptr>::lower_bound (T obj,
2184 bool (*lessthan)(const T &, const T &))
2185 const
2186{
2187 return m_vec ? m_vec->lower_bound (obj, lessthan) : 0;
2188}
2189
2190/* Return true if SEARCH is an element of V. Note that this is O(N) in the
2191 size of the vector and so should be used with care. */
2192
2193template<typename T>
2194inline bool
2195vec<T, va_heap, vl_ptr>::contains (const T &search) const
2196{
2197 return m_vec ? m_vec->contains (search) : false;
2198}
2199
2200/* Reverse content of the vector. */
2201
2202template<typename T>
2203inline void
2204vec<T, va_heap, vl_ptr>::reverse (void)
2205{
2206 unsigned l = length ();
2207 T *ptr = address ();
2208
2209 for (unsigned i = 0; i < l / 2; i++)
2210 std::swap (ptr[i], ptr[l - i - 1]);
2211}
2212
2213template<typename T>
2214inline bool
2215vec<T, va_heap, vl_ptr>::using_auto_storage () const
2216{
2217 return m_vec ? m_vec->m_vecpfx.m_using_auto_storage : false;
2218}
2219
2220/* Release VEC and call release of all element vectors. */
2221
2222template<typename T>
2223inline void
2224release_vec_vec (vec<vec<T> > &vec)
2225{
2226 for (unsigned i = 0; i < vec.length (); i++)
2227 vec[i].release ();
2228
2229 vec.release ();
2230}
2231
2232// Provide a subset of the std::span functionality. (We can't use std::span
2233// itself because it's a C++20 feature.)
2234//
2235// In addition, provide an invalid value that is distinct from all valid
2236// sequences (including the empty sequence). This can be used to return
2237// failure without having to use std::optional.
2238//
2239// There is no operator bool because it would be ambiguous whether it is
2240// testing for a valid value or an empty sequence.
2241template<typename T>
2242class array_slice
2243{
2244 template<typename OtherT> friend class array_slice;
2245
2246public:
2247 using value_type = T;
2248 using iterator = T *;
2249 using const_iterator = const T *;
2250
2251 array_slice () : m_base (nullptr), m_size (0) {}
2252
2253 template<typename OtherT>
2254 array_slice (array_slice<OtherT> other)
2255 : m_base (other.m_base), m_size (other.m_size) {}
2256
2257 array_slice (iterator base, unsigned int size)
2258 : m_base (base), m_size (size) {}
2259
2260 template<size_t N>
2261 array_slice (T (&array)[N]) : m_base (array), m_size (N) {}
2262
2263 template<typename OtherT>
2264 array_slice (const vec<OtherT> &v)
2265 : m_base (v.address ()), m_size (v.length ()) {}
2266
2267 iterator begin () { return m_base; }
2268 iterator end () { return m_base + m_size; }
2269
2270 const_iterator begin () const { return m_base; }
2271 const_iterator end () const { return m_base + m_size; }
2272
2273 value_type &front ();
2274 value_type &back ();
2275 value_type &operator[] (unsigned int i);
2276
2277 const value_type &front () const;
2278 const value_type &back () const;
2279 const value_type &operator[] (unsigned int i) const;
2280
2281 size_t size () const { return m_size; }
2282 size_t size_bytes () const { return m_size * sizeof (T); }
2283 bool empty () const { return m_size == 0; }
2284
2285 // An invalid array_slice that represents a failed operation. This is
2286 // distinct from an empty slice, which is a valid result in some contexts.
2287 static array_slice invalid () { return { nullptr, ~0U }; }
2288
2289 // True if the array is valid, false if it is an array like INVALID.
2290 bool is_valid () const { return m_base || m_size == 0; }
2291
2292private:
2293 iterator m_base;
2294 unsigned int m_size;
2295};
2296
2297template<typename T>
2298inline typename array_slice<T>::value_type &
2299array_slice<T>::front ()
2300{
2301 gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2301, __FUNCTION__), 0 : 0))
;
2302 return m_base[0];
2303}
2304
2305template<typename T>
2306inline const typename array_slice<T>::value_type &
2307array_slice<T>::front () const
2308{
2309 gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2309, __FUNCTION__), 0 : 0))
;
2310 return m_base[0];
2311}
2312
2313template<typename T>
2314inline typename array_slice<T>::value_type &
2315array_slice<T>::back ()
2316{
2317 gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2317, __FUNCTION__), 0 : 0))
;
2318 return m_base[m_size - 1];
2319}
2320
2321template<typename T>
2322inline const typename array_slice<T>::value_type &
2323array_slice<T>::back () const
2324{
2325 gcc_checking_assert (m_size)((void)(!(m_size) ? fancy_abort ("/home/marxin/BIG/buildbot/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/vec.h"
, 2325, __FUNCTION__), 0 : 0))
;
2326 return m_base[m_size - 1];
2327}
2328
2329template<typename T>
2330inline typename array_slice<T>::value_type &
2331array_slice<T>::operator[] (unsigned int i)
2332{
2333 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"
, 2333, __FUNCTION__), 0 : 0))
;
2334 return m_base[i];
2335}
2336
2337template<typename T>
2338inline const typename array_slice<T>::value_type &
2339array_slice<T>::operator[] (unsigned int i) const
2340{
2341 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"
, 2341, __FUNCTION__), 0 : 0))
;
2342 return m_base[i];
2343}
2344
2345template<typename T>
2346array_slice<T>
2347make_array_slice (T *base, unsigned int size)
2348{
2349 return array_slice<T> (base, size);
2350}
2351
2352#if (GCC_VERSION(4 * 1000 + 2) >= 3000)
2353# pragma GCC poison m_vec m_vecpfx m_vecdata
2354#endif
2355
2356#endif // GCC_VEC_H