annotate gcc/gimple-ssa-warn-restrict.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1 /* Pass to detect and issue warnings for violations of the restrict
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2 qualifier.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3 Copyright (C) 2017-2020 Free Software Foundation, Inc.
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
4 Contributed by Martin Sebor <msebor@redhat.com>.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
5
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
6 This file is part of GCC.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
7
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
8 GCC is free software; you can redistribute it and/or modify it under
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
9 the terms of the GNU General Public License as published by the Free
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
10 Software Foundation; either version 3, or (at your option) any later
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
11 version.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
12
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
16 for more details.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
17
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
18 You should have received a copy of the GNU General Public License
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
19 along with GCC; see the file COPYING3. If not see
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
20 <http://www.gnu.org/licenses/>. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
21
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
22 #include "config.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
23 #include "system.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
24 #include "coretypes.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
25 #include "backend.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
26 #include "tree.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
27 #include "gimple.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
28 #include "domwalk.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
29 #include "tree-pass.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
30 #include "builtins.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
31 #include "ssa.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
32 #include "gimple-pretty-print.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
33 #include "gimple-ssa-warn-restrict.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
34 #include "diagnostic-core.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
35 #include "fold-const.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
36 #include "gimple-iterator.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
37 #include "tree-dfa.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
38 #include "tree-ssa.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
39 #include "tree-cfg.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
40 #include "tree-object-size.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
41 #include "calls.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
42 #include "cfgloop.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
43 #include "intl.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
44
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
45 namespace {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
46
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
47 const pass_data pass_data_wrestrict = {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
48 GIMPLE_PASS,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
49 "wrestrict",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
50 OPTGROUP_NONE,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
51 TV_NONE,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
52 PROP_cfg, /* Properties_required. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
53 0, /* properties_provided. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
54 0, /* properties_destroyed. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
55 0, /* properties_start */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
56 0, /* properties_finish */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
57 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
58
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
59 /* Pass to detect violations of strict aliasing requirements in calls
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
60 to built-in string and raw memory functions. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
61 class pass_wrestrict : public gimple_opt_pass
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
62 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
63 public:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
64 pass_wrestrict (gcc::context *ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
65 : gimple_opt_pass (pass_data_wrestrict, ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
66 { }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
67
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
68 opt_pass *clone () { return new pass_wrestrict (m_ctxt); }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
69
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
70 virtual bool gate (function *);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
71 virtual unsigned int execute (function *);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
72 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
73
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
74 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
75 pass_wrestrict::gate (function *fun ATTRIBUTE_UNUSED)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
76 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
77 return warn_array_bounds || warn_restrict || warn_stringop_overflow;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
78 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
79
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
80 /* Class to walk the basic blocks of a function in dominator order. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
81 class wrestrict_dom_walker : public dom_walker
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
82 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
83 public:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
84 wrestrict_dom_walker () : dom_walker (CDI_DOMINATORS) {}
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
85
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
86 edge before_dom_children (basic_block) FINAL OVERRIDE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
87 bool handle_gimple_call (gimple_stmt_iterator *);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
88
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
89 private:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
90 void check_call (gimple *);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
91 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
92
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
93 edge
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
94 wrestrict_dom_walker::before_dom_children (basic_block bb)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
95 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
96 /* Iterate over statements, looking for function calls. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
97 for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
98 gsi_next (&si))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
99 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
100 gimple *stmt = gsi_stmt (si);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
101 if (!is_gimple_call (stmt))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
102 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
103
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
104 check_call (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
105 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
106
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
107 return NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
108 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
109
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
110 /* Execute the pass for function FUN, walking in dominator order. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
111
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
112 unsigned
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
113 pass_wrestrict::execute (function *fun)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
114 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
115 calculate_dominance_info (CDI_DOMINATORS);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
116
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
117 wrestrict_dom_walker walker;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
118 walker.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
119
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
120 return 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
121 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
122
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
123 /* Description of a memory reference by a built-in function. This
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
124 is similar to ao_ref but made especially suitable for -Wrestrict
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
125 and not for optimization. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
126 class builtin_memref
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
127 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
128 public:
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
129 /* The original pointer argument to the built-in function. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
130 tree ptr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
131 /* The referenced subobject or NULL if not available, and the base
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
132 object of the memory reference or NULL. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
133 tree ref;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
134 tree base;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
135
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
136 /* The size of the BASE object, PTRDIFF_MAX if indeterminate,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
137 and negative until (possibly lazily) initialized. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
138 offset_int basesize;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
139 /* Same for the subobject. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
140 offset_int refsize;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
141
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
142 /* The non-negative offset of the referenced subobject. Used to avoid
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
143 warnings for (apparently) possibly but not definitively overlapping
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
144 accesses to member arrays. Negative when unknown/invalid. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
145 offset_int refoff;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
146
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
147 /* The offset range relative to the base. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
148 offset_int offrange[2];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
149 /* The size range of the access to this reference. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
150 offset_int sizrange[2];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
151
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
152 /* Cached result of get_max_objsize(). */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
153 const offset_int maxobjsize;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
154
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
155 /* True for "bounded" string functions like strncat, and strncpy
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
156 and their variants that specify either an exact or upper bound
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
157 on the size of the accesses they perform. For strncat both
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
158 the source and destination references are bounded. For strncpy
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
159 only the destination reference is. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
160 bool strbounded_p;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
161
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
162 builtin_memref (tree, tree);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
163
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
164 tree offset_out_of_bounds (int, offset_int[3]) const;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
165
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
166 private:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
167
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
168 /* Ctor helper to set or extend OFFRANGE based on argument. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
169 void extend_offset_range (tree);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
170
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
171 /* Ctor helper to determine BASE and OFFRANGE from argument. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
172 void set_base_and_offset (tree);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
173 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
174
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
175 /* Description of a memory access by a raw memory or string built-in
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
176 function involving a pair of builtin_memref's. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
177 class builtin_access
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
178 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
179 public:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
180 /* Destination and source memory reference. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
181 builtin_memref* const dstref;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
182 builtin_memref* const srcref;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
183 /* The size range of the access. It's the greater of the accesses
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
184 to the two references. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
185 HOST_WIDE_INT sizrange[2];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
186
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
187 /* The minimum and maximum offset of an overlap of the access
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
188 (if it does, in fact, overlap), and the size of the overlap. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
189 HOST_WIDE_INT ovloff[2];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
190 HOST_WIDE_INT ovlsiz[2];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
191
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
192 /* True to consider valid only accesses to the smallest subobject
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
193 and false for raw memory functions. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
194 bool strict () const
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
195 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
196 return (detect_overlap != &builtin_access::generic_overlap
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
197 && detect_overlap != &builtin_access::no_overlap);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
198 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
199
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
200 builtin_access (gimple *, builtin_memref &, builtin_memref &);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
201
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
202 /* Entry point to determine overlap. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
203 bool overlap ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
204
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
205 offset_int write_off (tree) const;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
206
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
207 void dump (FILE *) const;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
208
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
209 private:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
210 /* Implementation functions used to determine overlap. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
211 bool generic_overlap ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
212 bool strcat_overlap ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
213 bool strcpy_overlap ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
214
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
215 bool no_overlap ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
216 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
217 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
218 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
219
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
220 offset_int overlap_size (const offset_int [2], const offset_int[2],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
221 offset_int [2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
222
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
223 private:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
224 /* Temporaries used to compute the final result. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
225 offset_int dstoff[2];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
226 offset_int srcoff[2];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
227 offset_int dstsiz[2];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
228 offset_int srcsiz[2];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
229
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
230 /* Pointer to a member function to call to determine overlap. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
231 bool (builtin_access::*detect_overlap) ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
232 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
233
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
234 /* Initialize a memory reference representation from a pointer EXPR and
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
235 a size SIZE in bytes. If SIZE is NULL_TREE then the size is assumed
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
236 to be unknown. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
237
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
238 builtin_memref::builtin_memref (tree expr, tree size)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
239 : ptr (expr),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
240 ref (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
241 base (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
242 basesize (-1),
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
243 refsize (-1),
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
244 refoff (HOST_WIDE_INT_MIN),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
245 offrange (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
246 sizrange (),
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
247 maxobjsize (tree_to_shwi (max_object_size ())),
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
248 strbounded_p ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
249 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
250 /* Unfortunately, wide_int default ctor is a no-op so array members
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
251 of the type must be set individually. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
252 offrange[0] = offrange[1] = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
253 sizrange[0] = sizrange[1] = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
254
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
255 if (!expr)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
256 return;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
257
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
258 /* Find the BASE object or pointer referenced by EXPR and set
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
259 the offset range OFFRANGE in the process. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
260 set_base_and_offset (expr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
261
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
262 if (size)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
263 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
264 tree range[2];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
265 /* Determine the size range, allowing for the result to be [0, 0]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
266 for SIZE in the anti-range ~[0, N] where N >= PTRDIFF_MAX. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
267 get_size_range (size, range, true);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
268 sizrange[0] = wi::to_offset (range[0]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
269 sizrange[1] = wi::to_offset (range[1]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
270 /* get_size_range returns SIZE_MAX for the maximum size.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
271 Constrain it to the real maximum of PTRDIFF_MAX. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
272 if (sizrange[0] <= maxobjsize && sizrange[1] > maxobjsize)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
273 sizrange[1] = maxobjsize;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
274 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
275 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
276 sizrange[1] = maxobjsize;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
277
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
278 if (!DECL_P (base))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
279 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
280
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
281 /* If the offset could be in the range of the referenced object
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
282 constrain its bounds so neither exceeds those of the object. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
283 if (offrange[0] < 0 && offrange[1] > 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
284 offrange[0] = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
285
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
286 offset_int maxoff = maxobjsize;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
287 tree basetype = TREE_TYPE (base);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
288 if (TREE_CODE (basetype) == ARRAY_TYPE)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
289 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
290 if (ref && array_at_struct_end_p (ref))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
291 ; /* Use the maximum possible offset for last member arrays. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
292 else if (tree basesize = TYPE_SIZE_UNIT (basetype))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
293 if (TREE_CODE (basesize) == INTEGER_CST)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
294 /* Size could be non-constant for a variable-length type such
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
295 as a struct with a VLA member (a GCC extension). */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
296 maxoff = wi::to_offset (basesize);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
297 }
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
298
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
299 if (offrange[0] >= 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
300 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
301 if (offrange[1] < 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
302 offrange[1] = offrange[0] <= maxoff ? maxoff : maxobjsize;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
303 else if (offrange[0] <= maxoff && offrange[1] > maxoff)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
304 offrange[1] = maxoff;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
305 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
306 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
307
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
308 /* Based on the initial length of the destination STARTLEN, returns
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
309 the offset of the first write access from the beginning of
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
310 the destination. Nonzero only for strcat-type of calls. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
311
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
312 offset_int builtin_access::write_off (tree startlen) const
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
313 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
314 if (detect_overlap != &builtin_access::strcat_overlap
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
315 || !startlen || TREE_CODE (startlen) != INTEGER_CST)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
316 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
317
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
318 return wi::to_offset (startlen);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
319 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
320
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
321 /* Ctor helper to set or extend OFFRANGE based on the OFFSET argument.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
322 Pointer offsets are represented as unsigned sizetype but must be
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
323 treated as signed. */
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
324
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
325 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
326 builtin_memref::extend_offset_range (tree offset)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
327 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
328 if (TREE_CODE (offset) == INTEGER_CST)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
329 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
330 offset_int off = int_cst_value (offset);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
331 if (off != 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
332 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
333 offrange[0] += off;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
334 offrange[1] += off;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
335 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
336 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
337 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
338
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
339 if (TREE_CODE (offset) == SSA_NAME)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
340 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
341 /* A pointer offset is represented as sizetype but treated
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
342 as signed. */
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
343 wide_int min, max;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
344 value_range_kind rng = get_range_info (offset, &min, &max);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
345 if (rng == VR_ANTI_RANGE && wi::lts_p (max, min))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
346 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
347 /* Convert an anti-range whose upper bound is less than
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
348 its lower bound to a signed range. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
349 offrange[0] += offset_int::from (max + 1, SIGNED);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
350 offrange[1] += offset_int::from (min - 1, SIGNED);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
351 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
352 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
353
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
354 if (rng == VR_RANGE
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
355 && (DECL_P (base) || wi::lts_p (min, max)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
356 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
357 /* Preserve the bounds of the range for an offset into
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
358 a known object (it may be adjusted later relative to
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
359 a constant offset from its beginning). Otherwise use
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
360 the bounds only when they are ascending when treated
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
361 as signed. */
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
362 offrange[0] += offset_int::from (min, SIGNED);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
363 offrange[1] += offset_int::from (max, SIGNED);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
364 return;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
365 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
366
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
367 /* Handle an anti-range the same as no range at all. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
368 gimple *stmt = SSA_NAME_DEF_STMT (offset);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
369 tree type;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
370 if (is_gimple_assign (stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
371 && (type = TREE_TYPE (gimple_assign_rhs1 (stmt)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
372 && INTEGRAL_TYPE_P (type))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
373 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
374 tree_code code = gimple_assign_rhs_code (stmt);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
375 if (code == NOP_EXPR)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
376 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
377 /* Use the bounds of the type of the NOP_EXPR operand
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
378 even if it's signed. The result doesn't trigger
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
379 warnings but makes their output more readable. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
380 offrange[0] += wi::to_offset (TYPE_MIN_VALUE (type));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
381 offrange[1] += wi::to_offset (TYPE_MAX_VALUE (type));
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
382 return;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
383 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
384 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
385 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
386
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
387 const offset_int maxoff = tree_to_shwi (max_object_size ()) >> 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
388 const offset_int minoff = -maxoff - 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
389
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
390 offrange[0] += minoff;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
391 offrange[1] += maxoff;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
392 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
393
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
394 /* Determines the base object or pointer of the reference EXPR
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
395 and the offset range from the beginning of the base. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
396
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
397 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
398 builtin_memref::set_base_and_offset (tree expr)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
399 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
400 tree offset = NULL_TREE;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
401
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
402 if (TREE_CODE (expr) == SSA_NAME)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
403 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
404 /* Try to tease the offset out of the pointer. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
405 gimple *stmt = SSA_NAME_DEF_STMT (expr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
406 if (!base
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
407 && gimple_assign_single_p (stmt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
408 && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
409 expr = gimple_assign_rhs1 (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
410 else if (is_gimple_assign (stmt))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
411 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
412 tree_code code = gimple_assign_rhs_code (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
413 if (code == NOP_EXPR)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
414 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
415 tree rhs = gimple_assign_rhs1 (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
416 if (POINTER_TYPE_P (TREE_TYPE (rhs)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
417 expr = gimple_assign_rhs1 (stmt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
418 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
419 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
420 base = expr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
421 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
422 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
423 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
424 else if (code == POINTER_PLUS_EXPR)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
425 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
426 expr = gimple_assign_rhs1 (stmt);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
427 offset = gimple_assign_rhs2 (stmt);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
428 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
429 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
430 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
431 base = expr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
432 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
433 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
434 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
435 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
436 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
437 /* FIXME: Handle PHI nodes in case like:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
438 _12 = &MEM[(void *)&a + 2B] + _10;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
439
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
440 <bb> [local count: 1073741824]:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
441 # prephitmp_13 = PHI <_12, &MEM[(void *)&a + 2B]>
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
442 memcpy (prephitmp_13, p_7(D), 6); */
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
443 base = expr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
444 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
445 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
446 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
447
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
448 if (TREE_CODE (expr) == ADDR_EXPR)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
449 expr = TREE_OPERAND (expr, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
450
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
451 /* Stash the reference for offset validation. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
452 ref = expr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
453
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
454 poly_int64 bitsize, bitpos;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
455 tree var_off;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
456 machine_mode mode;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
457 int sign, reverse, vol;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
458
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
459 /* Determine the base object or pointer of the reference and
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
460 the constant bit offset from the beginning of the base.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
461 If the offset has a non-constant component, it will be in
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
462 VAR_OFF. MODE, SIGN, REVERSE, and VOL are write only and
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
463 unused here. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
464 base = get_inner_reference (expr, &bitsize, &bitpos, &var_off,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
465 &mode, &sign, &reverse, &vol);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
466
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
467 /* get_inner_reference is not expected to return null. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
468 gcc_assert (base != NULL);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
469
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
470 if (offset)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
471 extend_offset_range (offset);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
472
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
473 poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
474
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
475 /* Convert the poly_int64 offset to offset_int. The offset
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
476 should be constant but be prepared for it not to be just in
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
477 case. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
478 offset_int cstoff;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
479 if (bytepos.is_constant (&cstoff))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
480 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
481 offrange[0] += cstoff;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
482 offrange[1] += cstoff;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
483
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
484 /* Besides the reference saved above, also stash the offset
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
485 for validation. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
486 if (TREE_CODE (expr) == COMPONENT_REF)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
487 refoff = cstoff;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
488 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
489 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
490 offrange[1] += maxobjsize;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
491
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
492 if (var_off)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
493 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
494 if (TREE_CODE (var_off) == INTEGER_CST)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
495 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
496 cstoff = wi::to_offset (var_off);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
497 offrange[0] += cstoff;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
498 offrange[1] += cstoff;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
499 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
500 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
501 offrange[1] += maxobjsize;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
502 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
503
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
504 if (TREE_CODE (base) == MEM_REF)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
505 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
506 tree memrefoff = fold_convert (ptrdiff_type_node, TREE_OPERAND (base, 1));
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
507 extend_offset_range (memrefoff);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
508 base = TREE_OPERAND (base, 0);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
509
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
510 if (refoff != HOST_WIDE_INT_MIN
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
511 && TREE_CODE (expr) == COMPONENT_REF)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
512 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
513 /* Bump up the offset of the referenced subobject to reflect
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
514 the offset to the enclosing object. For example, so that
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
515 in
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
516 struct S { char a, b[3]; } s[2];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
517 strcpy (s[1].b, "1234");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
518 REFOFF is set to s[1].b - (char*)s. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
519 offset_int off = tree_to_shwi (memrefoff);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
520 refoff += off;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
521 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
522
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
523 if (!integer_zerop (memrefoff))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
524 /* A non-zero offset into an array of struct with flexible array
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
525 members implies that the array is empty because there is no
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
526 way to initialize such a member when it belongs to an array.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
527 This must be some sort of a bug. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
528 refsize = 0;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
529 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
530
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
531 if (TREE_CODE (ref) == COMPONENT_REF)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
532 if (tree size = component_ref_size (ref))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
533 if (TREE_CODE (size) == INTEGER_CST)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
534 refsize = wi::to_offset (size);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
535
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
536 if (TREE_CODE (base) == SSA_NAME)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
537 set_base_and_offset (base);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
538 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
539
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
540 /* Return error_mark_node if the signed offset exceeds the bounds
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
541 of the address space (PTRDIFF_MAX). Otherwise, return either BASE
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
542 or REF when the offset exceeds the bounds of the BASE or REF object,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
543 and set OOBOFF to the past-the-end offset formed by the reference,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
544 including its size. OOBOFF is initially setto the range of offsets,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
545 and OOBOFF[2] to the offset of the first write access (nonzero for
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
546 the strcat family). When STRICT is nonzero use REF size, when
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
547 available, otherwise use BASE size. When STRICT is greater than 1,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
548 use the size of the last array member as the bound, otherwise treat
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
549 such a member as a flexible array member. Return NULL when the offset
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
550 is in bounds. */
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
551
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
552 tree
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
553 builtin_memref::offset_out_of_bounds (int strict, offset_int ooboff[3]) const
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
554 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
555 if (!ptr)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
556 return NULL_TREE;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
557
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
558 /* The offset of the first write access or zero. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
559 offset_int wroff = ooboff[2];
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
560
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
561 /* A temporary, possibly adjusted, copy of the offset range. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
562 offset_int offrng[2] = { ooboff[0], ooboff[1] };
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
563
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
564 if (DECL_P (base) && TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
565 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
566 /* Check for offset in an anti-range with a negative lower bound.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
567 For such a range, consider only the non-negative subrange. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
568 if (offrng[1] < offrng[0] && offrng[1] < 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
569 offrng[1] = maxobjsize;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
570 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
571
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
572 /* Conservative offset of the last byte of the referenced object. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
573 offset_int endoff;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
574
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
575 /* The bounds need not be ordered. Set HIB to use as the index
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
576 of the larger of the bounds and LOB as the opposite. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
577 bool hib = wi::les_p (offrng[0], offrng[1]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
578 bool lob = !hib;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
579
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
580 /* Set to the size remaining in the object object after subtracting
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
581 REFOFF. It may become negative as a result of negative indices
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
582 into the enclosing object, such as in:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
583 extern struct S { char a[4], b[3], c[1]; } *p;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
584 strcpy (p[-3].b, "123"); */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
585 offset_int size = basesize;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
586 tree obj = base;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
587
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
588 const bool decl_p = DECL_P (obj);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
589
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
590 if (basesize < 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
591 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
592 endoff = offrng[lob] + (sizrange[0] - wroff);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
593
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
594 /* For a reference through a pointer to an object of unknown size
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
595 all initial offsets are considered valid, positive as well as
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
596 negative, since the pointer itself can point past the beginning
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
597 of the object. However, the sum of the lower bound of the offset
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
598 and that of the size must be less than or equal than PTRDIFF_MAX. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
599 if (endoff > maxobjsize)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
600 return error_mark_node;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
601
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
602 /* When the referenced subobject is known, the end offset must be
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
603 within its bounds. Otherwise there is nothing to do. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
604 if (strict
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
605 && !decl_p
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
606 && ref
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
607 && refsize >= 0
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
608 && TREE_CODE (ref) == COMPONENT_REF)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
609 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
610 /* If REFOFF is negative, SIZE will become negative here. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
611 size = refoff + refsize;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
612 obj = ref;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
613 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
614 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
615 return NULL_TREE;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
616 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
617
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
618 /* A reference to an object of known size must be within the bounds
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
619 of either the base object or the subobject (see above for when
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
620 a subobject can be used). */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
621 if ((decl_p && offrng[hib] < 0) || offrng[lob] > size)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
622 return obj;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
623
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
624 /* The extent of the reference must also be within the bounds of
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
625 the base object (if known) or the subobject or the maximum object
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
626 size otherwise. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
627 endoff = offrng[lob] + sizrange[0];
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
628 if (endoff > maxobjsize)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
629 return error_mark_node;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
630
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
631 if (strict
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
632 && decl_p
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
633 && ref
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
634 && refsize >= 0
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
635 && TREE_CODE (ref) == COMPONENT_REF)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
636 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
637 /* If the reference is to a member subobject of a declared object,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
638 the offset must be within the bounds of the subobject. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
639 size = refoff + refsize;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
640 obj = ref;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
641 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
642
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
643 if (endoff <= size)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
644 return NULL_TREE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
645
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
646 /* Set the out-of-bounds offset range to be one greater than
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
647 that delimited by the reference including its size. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
648 ooboff[lob] = size;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
649
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
650 if (endoff > ooboff[lob])
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
651 ooboff[hib] = endoff - 1;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
652 else
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
653 ooboff[hib] = offrng[lob] + sizrange[1];
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
654
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
655 return obj;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
656 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
657
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
658 /* Create an association between the memory references DST and SRC
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
659 for access by a call EXPR to a memory or string built-in funtion. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
660
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
661 builtin_access::builtin_access (gimple *call, builtin_memref &dst,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
662 builtin_memref &src)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
663 : dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
664 dstoff (), srcoff (), dstsiz (), srcsiz ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
665 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
666 dstoff[0] = dst.offrange[0];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
667 dstoff[1] = dst.offrange[1];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
668
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
669 /* Zero out since the offset_int ctors invoked above are no-op. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
670 srcoff[0] = srcoff[1] = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
671 dstsiz[0] = dstsiz[1] = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
672 srcsiz[0] = srcsiz[1] = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
673
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
674 /* Object Size Type to use to determine the size of the destination
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
675 and source objects. Overridden below for raw memory functions. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
676 int ostype = 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
677
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
678 /* True when the size of one reference depends on the offset of
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
679 itself or the other. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
680 bool depends_p = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
681
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
682 /* True when the size of the destination reference DSTREF has been
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
683 determined from SRCREF and so needs to be adjusted by the latter's
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
684 offset. Only meaningful for bounded string functions like strncpy. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
685 bool dstadjust_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
686
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
687 /* The size argument number (depends on the built-in). */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
688 unsigned sizeargno = 2;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
689
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
690 tree func = gimple_call_fndecl (call);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
691 switch (DECL_FUNCTION_CODE (func))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
692 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
693 case BUILT_IN_MEMCPY:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
694 case BUILT_IN_MEMCPY_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
695 case BUILT_IN_MEMPCPY:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
696 case BUILT_IN_MEMPCPY_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
697 ostype = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
698 depends_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
699 detect_overlap = &builtin_access::generic_overlap;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
700 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
701
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
702 case BUILT_IN_MEMMOVE:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
703 case BUILT_IN_MEMMOVE_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
704 /* For memmove there is never any overlap to check for. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
705 ostype = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
706 depends_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
707 detect_overlap = &builtin_access::no_overlap;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
708 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
709
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
710 case BUILT_IN_MEMSET:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
711 case BUILT_IN_MEMSET_CHK:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
712 /* For memset there is never any overlap to check for. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
713 ostype = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
714 depends_p = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
715 detect_overlap = &builtin_access::no_overlap;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
716 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
717
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
718 case BUILT_IN_STPNCPY:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
719 case BUILT_IN_STPNCPY_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
720 case BUILT_IN_STRNCPY:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
721 case BUILT_IN_STRNCPY_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
722 dstref->strbounded_p = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
723 detect_overlap = &builtin_access::strcpy_overlap;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
724 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
725
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
726 case BUILT_IN_STPCPY:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
727 case BUILT_IN_STPCPY_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
728 case BUILT_IN_STRCPY:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
729 case BUILT_IN_STRCPY_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
730 detect_overlap = &builtin_access::strcpy_overlap;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
731 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
732
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
733 case BUILT_IN_STRCAT:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
734 case BUILT_IN_STRCAT_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
735 detect_overlap = &builtin_access::strcat_overlap;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
736 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
737
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
738 case BUILT_IN_STRNCAT:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
739 case BUILT_IN_STRNCAT_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
740 dstref->strbounded_p = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
741 srcref->strbounded_p = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
742 detect_overlap = &builtin_access::strcat_overlap;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
743 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
744
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
745 default:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
746 /* Handle other string functions here whose access may need
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
747 to be validated for in-bounds offsets and non-overlapping
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
748 copies. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
749 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
750 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
751
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
752 const offset_int maxobjsize = dst.maxobjsize;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
753
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
754 /* Try to determine the size of the base object. compute_objsize
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
755 expects a pointer so create one if BASE is a non-pointer object. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
756 tree addr;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
757 if (dst.basesize < 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
758 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
759 addr = dst.base;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
760 if (!POINTER_TYPE_P (TREE_TYPE (addr)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
761 addr = build1 (ADDR_EXPR, (TREE_TYPE (addr)), addr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
762
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
763 if (tree dstsize = compute_objsize (addr, ostype))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
764 dst.basesize = wi::to_offset (dstsize);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
765 else if (POINTER_TYPE_P (TREE_TYPE (addr)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
766 dst.basesize = HOST_WIDE_INT_MIN;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
767 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
768 dst.basesize = maxobjsize;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
769 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
770
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
771 if (src.base && src.basesize < 0)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
772 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
773 addr = src.base;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
774 if (!POINTER_TYPE_P (TREE_TYPE (addr)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
775 addr = build1 (ADDR_EXPR, (TREE_TYPE (addr)), addr);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
776
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
777 if (tree srcsize = compute_objsize (addr, ostype))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
778 src.basesize = wi::to_offset (srcsize);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
779 else if (POINTER_TYPE_P (TREE_TYPE (addr)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
780 src.basesize = HOST_WIDE_INT_MIN;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
781 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
782 src.basesize = maxobjsize;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
783 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
784
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
785 /* Make adjustments for references to the same object by string
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
786 built-in functions to reflect the constraints imposed by
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
787 the function. */
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
788
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
789 /* For bounded string functions determine the range of the bound
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
790 on the access. For others, the range stays unbounded. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
791 offset_int bounds[2] = { maxobjsize, maxobjsize };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
792 if (dstref->strbounded_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
793 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
794 unsigned nargs = gimple_call_num_args (call);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
795 if (nargs <= sizeargno)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
796 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
797
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
798 tree size = gimple_call_arg (call, sizeargno);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
799 tree range[2];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
800 if (get_size_range (size, range, true))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
801 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
802 bounds[0] = wi::to_offset (range[0]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
803 bounds[1] = wi::to_offset (range[1]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
804 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
805
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
806 /* If both references' size ranges are indeterminate use the last
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
807 (size) argument from the function call as a substitute. This
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
808 may only be necessary for strncpy (but not for memcpy where
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
809 the size range would have been already determined this way). */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
810 if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
811 && srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
812 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
813 dstref->sizrange[0] = bounds[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
814 dstref->sizrange[1] = bounds[1];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
815 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
816 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
817
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
818 bool dstsize_set = false;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
819 /* The size range of one reference involving the same base object
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
820 can be determined from the size range of the other reference.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
821 This makes it possible to compute accurate offsets for warnings
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
822 involving functions like strcpy where the length of just one of
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
823 the two arguments is known (determined by tree-ssa-strlen). */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
824 if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
825 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
826 /* When the destination size is unknown set it to the size of
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
827 the source. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
828 dstref->sizrange[0] = srcref->sizrange[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
829 dstref->sizrange[1] = srcref->sizrange[1];
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
830 dstsize_set = true;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
831 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
832 else if (srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
833 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
834 /* When the source size is unknown set it to the size of
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
835 the destination. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
836 srcref->sizrange[0] = dstref->sizrange[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
837 srcref->sizrange[1] = dstref->sizrange[1];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
838
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
839 if (depends_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
840 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
841 if (dstref->strbounded_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
842 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
843 /* Read access by strncpy is constrained by the third
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
844 argument but except for a zero bound is at least one. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
845 offset_int size = wi::umax (srcref->basesize, 1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
846 offset_int bound = wi::umin (size, bounds[0]);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
847 if (bound < srcref->sizrange[0])
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
848 srcref->sizrange[0] = bound;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
849 bound = wi::umin (srcref->basesize, bounds[1]);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
850 if (bound < srcref->sizrange[1])
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
851 srcref->sizrange[1] = bound;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
852 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
853
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
854 /* For string functions, adjust the size range of the source
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
855 reference by the inverse boundaries of the offset (because
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
856 the higher the offset into the string the shorter its
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
857 length). */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
858 if (srcref->offrange[1] >= 0
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
859 && srcref->offrange[1] < srcref->sizrange[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
860 srcref->sizrange[0] -= srcref->offrange[1];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
861 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
862 srcref->sizrange[0] = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
863
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
864 if (srcref->offrange[0] > 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
865 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
866 if (srcref->offrange[0] < srcref->sizrange[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
867 srcref->sizrange[1] -= srcref->offrange[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
868 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
869 srcref->sizrange[1] = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
870 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
871
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
872 dstadjust_p = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
873 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
874 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
875
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
876 if (detect_overlap == &builtin_access::generic_overlap)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
877 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
878 if (dstref->strbounded_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
879 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
880 dstref->sizrange[0] = bounds[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
881 dstref->sizrange[1] = bounds[1];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
882
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
883 if (dstref->sizrange[0] < srcref->sizrange[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
884 srcref->sizrange[0] = dstref->sizrange[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
885
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
886 if (dstref->sizrange[1] < srcref->sizrange[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
887 srcref->sizrange[1] = dstref->sizrange[1];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
888 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
889 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
890 else if (detect_overlap == &builtin_access::strcpy_overlap)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
891 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
892 if (!dstref->strbounded_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
893 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
894 /* For strcpy, adjust the destination size range to match that
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
895 of the source computed above. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
896 if (depends_p && dstadjust_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
897 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
898 dstref->sizrange[0] = srcref->sizrange[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
899 dstref->sizrange[1] = srcref->sizrange[1];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
900 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
901 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
902 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
903 else if (!dstsize_set && detect_overlap == &builtin_access::strcat_overlap)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
904 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
905 dstref->sizrange[0] += srcref->sizrange[0] - 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
906 dstref->sizrange[1] += srcref->sizrange[1] - 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
907 }
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
908
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
909 if (dstref->strbounded_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
910 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
911 /* For strncpy, adjust the destination size range to match that
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
912 of the source computed above. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
913 dstref->sizrange[0] = bounds[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
914 dstref->sizrange[1] = bounds[1];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
915
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
916 if (bounds[0] < srcref->sizrange[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
917 srcref->sizrange[0] = bounds[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
918
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
919 if (bounds[1] < srcref->sizrange[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
920 srcref->sizrange[1] = bounds[1];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
921 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
922 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
923
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
924 offset_int
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
925 builtin_access::overlap_size (const offset_int a[2], const offset_int b[2],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
926 offset_int *off)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
927 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
928 const offset_int *p = a;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
929 const offset_int *q = b;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
930
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
931 /* Point P at the bigger of the two ranges and Q at the smaller. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
932 if (wi::lts_p (a[1] - a[0], b[1] - b[0]))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
933 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
934 p = b;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
935 q = a;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
936 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
937
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
938 if (p[0] < q[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
939 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
940 if (p[1] < q[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
941 return 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
942
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
943 *off = q[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
944 return wi::smin (p[1], q[1]) - q[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
945 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
946
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
947 if (q[1] < p[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
948 return 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
949
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
950 off[0] = p[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
951 return q[1] - p[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
952 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
953
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
954 /* Return true if the bounded mempry (memcpy amd similar) or string function
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
955 access (strncpy and similar) ACS overlaps. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
956
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
957 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
958 builtin_access::generic_overlap ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
959 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
960 builtin_access &acs = *this;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
961 const builtin_memref *dstref = acs.dstref;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
962 const builtin_memref *srcref = acs.srcref;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
963
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
964 gcc_assert (dstref->base == srcref->base);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
965
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
966 const offset_int maxobjsize = acs.dstref->maxobjsize;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
967
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
968 offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
969
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
970 /* Adjust the larger bounds of the offsets (which may be the first
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
971 element if the lower bound is larger than the upper bound) to
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
972 make them valid for the smallest access (if possible) but no smaller
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
973 than the smaller bounds. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
974 gcc_assert (wi::les_p (acs.dstoff[0], acs.dstoff[1]));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
975
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
976 if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
977 acs.dstoff[1] = maxsize - acs.dstsiz[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
978 if (acs.dstoff[1] < acs.dstoff[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
979 acs.dstoff[1] = acs.dstoff[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
980
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
981 gcc_assert (wi::les_p (acs.srcoff[0], acs.srcoff[1]));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
982
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
983 if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
984 acs.srcoff[1] = maxsize - acs.srcsiz[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
985 if (acs.srcoff[1] < acs.srcoff[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
986 acs.srcoff[1] = acs.srcoff[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
987
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
988 /* Determine the minimum and maximum space for the access given
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
989 the offsets. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
990 offset_int space[2];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
991 space[0] = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
992 space[1] = space[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
993
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
994 offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
995 if (acs.srcsiz[0] > 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
996 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
997 if (d < space[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
998 space[0] = d;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
999
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1000 if (space[1] < d)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1001 space[1] = d;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1002 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1003 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1004 space[1] = acs.dstsiz[1];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1005
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1006 d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1007 if (d < space[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1008 space[0] = d;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1009
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1010 if (space[1] < d)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1011 space[1] = d;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1012
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1013 /* Treat raw memory functions both of whose references are bounded
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1014 as special and permit uncertain overlaps to go undetected. For
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1015 all kinds of constant offset and constant size accesses, if
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1016 overlap isn't certain it is not possible. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1017 bool overlap_possible = space[0] < acs.dstsiz[1];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1018 if (!overlap_possible)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1019 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1020
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1021 bool overlap_certain = space[1] < acs.dstsiz[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1022
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1023 /* True when the size of one reference depends on the offset of
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1024 the other. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1025 bool depends_p = detect_overlap != &builtin_access::generic_overlap;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1026
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1027 if (!overlap_certain)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1028 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1029 if (!dstref->strbounded_p && !depends_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1030 /* Memcpy only considers certain overlap. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1031 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1032
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1033 /* There's no way to distinguish an access to the same member
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1034 of a structure from one to two distinct members of the same
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1035 structure. Give up to avoid excessive false positives. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1036 tree basetype = TREE_TYPE (dstref->base);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1037
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1038 if (POINTER_TYPE_P (basetype))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1039 basetype = TREE_TYPE (basetype);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1040 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1041 while (TREE_CODE (basetype) == ARRAY_TYPE)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1042 basetype = TREE_TYPE (basetype);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1043
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1044 if (RECORD_OR_UNION_TYPE_P (basetype))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1045 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1046 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1047
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1048 /* True for stpcpy and strcpy. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1049 bool stxcpy_p = (!dstref->strbounded_p
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1050 && detect_overlap == &builtin_access::strcpy_overlap);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1051
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1052 if (dstref->refoff >= 0
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1053 && srcref->refoff >= 0
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1054 && dstref->refoff != srcref->refoff
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1055 && (stxcpy_p || dstref->strbounded_p || srcref->strbounded_p))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1056 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1057
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1058 offset_int siz[2] = { maxobjsize + 1, 0 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1059
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1060 ovloff[0] = HOST_WIDE_INT_MAX;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1061 ovloff[1] = HOST_WIDE_INT_MIN;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1062
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1063 /* Adjustment to the lower bound of the offset of the overlap to
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1064 account for a subset of unbounded string calls where the size
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1065 of the destination string depends on the length of the source
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1066 which in turn depends on the offset into it. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1067 bool sub1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1068
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1069 if (stxcpy_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1070 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1071 sub1 = acs.dstoff[0] <= acs.srcoff[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1072
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1073 /* Iterate over the extreme locations (on the horizontal axis formed
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1074 by their offsets) and sizes of two regions and find their smallest
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1075 and largest overlap and the corresponding offsets. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1076 for (unsigned i = 0; i != 2; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1077 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1078 const offset_int a[2] = {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1079 acs.dstoff[i], acs.dstoff[i] + acs.dstsiz[!i]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1080 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1081
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1082 const offset_int b[2] = {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1083 acs.srcoff[i], acs.srcoff[i] + acs.srcsiz[!i]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1084 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1085
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1086 offset_int off;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1087 offset_int sz = overlap_size (a, b, &off);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1088 if (sz < siz[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1089 siz[0] = sz;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1090
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1091 if (siz[1] <= sz)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1092 siz[1] = sz;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1093
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1094 if (sz != 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1095 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1096 if (wi::lts_p (off, ovloff[0]))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1097 ovloff[0] = off.to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1098 if (wi::lts_p (ovloff[1], off))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1099 ovloff[1] = off.to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1100 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1101 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1102 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1103 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1104 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1105 sub1 = !depends_p;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1106
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1107 /* Iterate over the extreme locations (on the horizontal axis
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1108 formed by their offsets) and sizes of two regions and find
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1109 their smallest and largest overlap and the corresponding
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1110 offsets. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1111
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1112 for (unsigned io = 0; io != 2; ++io)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1113 for (unsigned is = 0; is != 2; ++is)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1114 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1115 const offset_int a[2] = {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1116 acs.dstoff[io], acs.dstoff[io] + acs.dstsiz[is]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1117 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1118
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1119 for (unsigned jo = 0; jo != 2; ++jo)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1120 for (unsigned js = 0; js != 2; ++js)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1121 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1122 if (depends_p)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1123 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1124 /* For st{p,r}ncpy the size of the source sequence
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1125 depends on the offset into it. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1126 if (js)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1127 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1128 js = !jo;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1129 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1130
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1131 const offset_int b[2] = {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1132 acs.srcoff[jo], acs.srcoff[jo] + acs.srcsiz[js]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1133 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1134
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1135 offset_int off;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1136 offset_int sz = overlap_size (a, b, &off);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1137 if (sz < siz[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1138 siz[0] = sz;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1139
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1140 if (siz[1] <= sz)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1141 siz[1] = sz;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1142
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1143 if (sz != 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1144 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1145 if (wi::lts_p (off, ovloff[0]))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1146 ovloff[0] = off.to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1147 if (wi::lts_p (ovloff[1], off))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1148 ovloff[1] = off.to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1149 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1150 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1151 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1152 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1153
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1154 ovlsiz[0] = siz[0].to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1155 ovlsiz[1] = siz[1].to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1156
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1157 if (ovlsiz[0] == 0 && ovlsiz[1] > 1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1158 ovloff[0] = ovloff[1] + ovlsiz[1] - 1 - sub1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1159
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1160 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1161 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1162
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1163 /* Return true if the strcat-like access overlaps. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1164
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1165 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1166 builtin_access::strcat_overlap ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1167 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1168 builtin_access &acs = *this;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1169 const builtin_memref *dstref = acs.dstref;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1170 const builtin_memref *srcref = acs.srcref;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1171
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1172 gcc_assert (dstref->base == srcref->base);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1173
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1174 const offset_int maxobjsize = acs.dstref->maxobjsize;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1175
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1176 gcc_assert (dstref->base && dstref->base == srcref->base);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1177
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1178 /* Adjust for strcat-like accesses. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1179
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1180 /* As a special case for strcat, set the DSTREF offsets to the length
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1181 of the destination string since the function starts writing over
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1182 its terminating nul, and set the destination size to 1 for the length
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1183 of the nul. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1184 acs.dstoff[0] += dstsiz[0] - srcref->sizrange[0];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1185 acs.dstoff[1] += dstsiz[1] - srcref->sizrange[1];
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1186
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1187 bool strfunc_unknown_args = acs.dstsiz[0] == 0 && acs.dstsiz[1] != 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1188
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1189 /* The lower bound is zero when the size is unknown because then
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1190 overlap is not certain. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1191 acs.dstsiz[0] = strfunc_unknown_args ? 0 : 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1192 acs.dstsiz[1] = 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1193
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1194 offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1195
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1196 /* For references to the same base object, determine if there's a pair
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1197 of valid offsets into the two references such that access between
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1198 them doesn't overlap. Adjust both upper bounds to be valid for
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1199 the smaller size (i.e., at most MAXSIZE - SIZE). */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1200
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1201 if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1202 acs.dstoff[1] = maxsize - acs.dstsiz[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1203
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1204 if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1205 acs.srcoff[1] = maxsize - acs.srcsiz[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1206
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1207 /* Check to see if there's enough space for both accesses without
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1208 overlap. Determine the optimistic (maximum) amount of available
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1209 space. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1210 offset_int space;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1211 if (acs.dstoff[0] <= acs.srcoff[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1212 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1213 if (acs.dstoff[1] < acs.srcoff[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1214 space = acs.srcoff[1] + acs.srcsiz[0] - acs.dstoff[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1215 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1216 space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1217 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1218 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1219 space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1220
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1221 /* Overlap is certain if the distance between the farthest offsets
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1222 of the opposite accesses is less than the sum of the lower bounds
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1223 of the sizes of the two accesses. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1224 bool overlap_certain = space < acs.dstsiz[0] + acs.srcsiz[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1225
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1226 /* For a constant-offset, constant size access, consider the largest
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1227 distance between the offset bounds and the lower bound of the access
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1228 size. If the overlap isn't certain return success. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1229 if (!overlap_certain
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1230 && acs.dstoff[0] == acs.dstoff[1]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1231 && acs.srcoff[0] == acs.srcoff[1]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1232 && acs.dstsiz[0] == acs.dstsiz[1]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1233 && acs.srcsiz[0] == acs.srcsiz[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1234 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1235
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1236 /* Overlap is not certain but may be possible. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1237
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1238 offset_int access_min = acs.dstsiz[0] + acs.srcsiz[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1239
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1240 /* Determine the conservative (minimum) amount of space. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1241 space = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1242 offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1243 if (d < space)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1244 space = d;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1245 d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1246 if (d < space)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1247 space = d;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1248
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1249 /* For a strict test (used for strcpy and similar with unknown or
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1250 variable bounds or sizes), consider the smallest distance between
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1251 the offset bounds and either the upper bound of the access size
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1252 if known, or the lower bound otherwise. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1253 if (access_min <= space && (access_min != 0 || !strfunc_unknown_args))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1254 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1255
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1256 /* When strcat overlap is certain it is always a single byte:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1257 the terminating NUL, regardless of offsets and sizes. When
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1258 overlap is only possible its range is [0, 1]. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1259 acs.ovlsiz[0] = dstref->sizrange[0] == dstref->sizrange[1] ? 1 : 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1260 acs.ovlsiz[1] = 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1261
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1262 offset_int endoff
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1263 = dstref->offrange[0] + (dstref->sizrange[0] - srcref->sizrange[0]);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1264 if (endoff <= srcref->offrange[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1265 acs.ovloff[0] = wi::smin (maxobjsize, srcref->offrange[0]).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1266 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1267 acs.ovloff[0] = wi::smin (maxobjsize, endoff).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1268
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1269 acs.sizrange[0] = wi::smax (wi::abs (endoff - srcref->offrange[0]) + 1,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1270 srcref->sizrange[0]).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1271 if (dstref->offrange[0] == dstref->offrange[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1272 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1273 if (srcref->offrange[0] == srcref->offrange[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1274 acs.ovloff[1] = acs.ovloff[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1275 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1276 acs.ovloff[1]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1277 = wi::smin (maxobjsize,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1278 srcref->offrange[1] + srcref->sizrange[1]).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1279 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1280 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1281 acs.ovloff[1]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1282 = wi::smin (maxobjsize,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1283 dstref->offrange[1] + dstref->sizrange[1]).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1284
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1285 if (acs.sizrange[0] == 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1286 acs.sizrange[0] = 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1287 acs.sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1288 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1289 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1290
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1291 /* Return true if the strcpy-like access overlaps. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1292
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1293 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1294 builtin_access::strcpy_overlap ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1295 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1296 return generic_overlap ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1297 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1298
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1299
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1300 /* Return true if DSTREF and SRCREF describe accesses that either overlap
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1301 one another or that, in order not to overlap, would imply that the size
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1302 of the referenced object(s) exceeds the maximum size of an object. Set
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1303 Otherwise, if DSTREF and SRCREF do not definitely overlap (even though
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1304 they may overlap in a way that's not apparent from the available data),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1305 return false. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1306
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1307 bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1308 builtin_access::overlap ()
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1309 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1310 builtin_access &acs = *this;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1311
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1312 const offset_int maxobjsize = dstref->maxobjsize;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1313
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1314 acs.sizrange[0] = wi::smax (dstref->sizrange[0],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1315 srcref->sizrange[0]).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1316 acs.sizrange[1] = wi::smax (dstref->sizrange[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1317 srcref->sizrange[1]).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1318
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1319 /* Check to see if the two references refer to regions that are
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1320 too large not to overlap in the address space (whose maximum
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1321 size is PTRDIFF_MAX). */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1322 offset_int size = dstref->sizrange[0] + srcref->sizrange[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1323 if (maxobjsize < size)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1324 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1325 acs.ovloff[0] = (maxobjsize - dstref->sizrange[0]).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1326 acs.ovlsiz[0] = (size - maxobjsize).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1327 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1328 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1329
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1330 /* If both base objects aren't known return the maximum possible
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1331 offset that would make them not overlap. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1332 if (!dstref->base || !srcref->base)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1333 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1334
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1335 /* If the base object is an array adjust the bounds of the offset
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1336 to be non-negative and within the bounds of the array if possible. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1337 if (dstref->base
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1338 && TREE_CODE (TREE_TYPE (dstref->base)) == ARRAY_TYPE)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1339 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1340 if (acs.dstoff[0] < 0 && acs.dstoff[1] >= 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1341 acs.dstoff[0] = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1342
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1343 if (acs.dstoff[1] < acs.dstoff[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1344 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1345 if (tree size = TYPE_SIZE_UNIT (TREE_TYPE (dstref->base)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1346 acs.dstoff[1] = wi::umin (acs.dstoff[1], wi::to_offset (size));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1347 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1348 acs.dstoff[1] = wi::umin (acs.dstoff[1], maxobjsize);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1349 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1350 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1351
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1352 acs.srcoff[0] = srcref->offrange[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1353 acs.srcoff[1] = srcref->offrange[1];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1354
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1355 if (srcref->base
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1356 && TREE_CODE (TREE_TYPE (srcref->base)) == ARRAY_TYPE)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1357 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1358 if (acs.srcoff[0] < 0 && acs.srcoff[1] >= 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1359 acs.srcoff[0] = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1360
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1361 if (tree size = TYPE_SIZE_UNIT (TREE_TYPE (srcref->base)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1362 acs.srcoff[1] = wi::umin (acs.srcoff[1], wi::to_offset (size));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1363 else if (acs.srcoff[1] < acs.srcoff[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1364 acs.srcoff[1] = wi::umin (acs.srcoff[1], maxobjsize);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1365 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1366
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1367 /* When the upper bound of the offset is less than the lower bound
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1368 the former is the result of a negative offset being represented
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1369 as a large positive value or vice versa. The resulting range is
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1370 a union of two subranges: [MIN, UB] and [LB, MAX]. Since such
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1371 a union is not representable using the current data structure
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1372 replace it with the full range of offsets. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1373 if (acs.dstoff[1] < acs.dstoff[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1374 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1375 acs.dstoff[0] = -maxobjsize - 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1376 acs.dstoff[1] = maxobjsize;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1377 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1378
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1379 /* Validate the offset and size of each reference on its own first.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1380 This is independent of whether or not the base objects are the
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1381 same. Normally, this would have already been detected and
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1382 diagnosed by -Warray-bounds, unless it has been disabled. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1383 offset_int maxoff = acs.dstoff[0] + dstref->sizrange[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1384 if (maxobjsize < maxoff)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1385 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1386 acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1387 acs.ovloff[0] = acs.dstoff[0].to_shwi () - acs.ovlsiz[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1388 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1389 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1390
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1391 /* Repeat the same as above but for the source offsets. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1392 if (acs.srcoff[1] < acs.srcoff[0])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1393 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1394 acs.srcoff[0] = -maxobjsize - 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1395 acs.srcoff[1] = maxobjsize;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1396 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1397
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1398 maxoff = acs.srcoff[0] + srcref->sizrange[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1399 if (maxobjsize < maxoff)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1400 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1401 acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1402 acs.ovlsiz[1] = (acs.srcoff[0] + srcref->sizrange[1]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1403 - maxobjsize).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1404 acs.ovloff[0] = acs.srcoff[0].to_shwi () - acs.ovlsiz[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1405 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1406 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1407
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1408 if (dstref->base != srcref->base)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1409 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1410
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1411 acs.dstsiz[0] = dstref->sizrange[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1412 acs.dstsiz[1] = dstref->sizrange[1];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1413
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1414 acs.srcsiz[0] = srcref->sizrange[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1415 acs.srcsiz[1] = srcref->sizrange[1];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1416
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1417 /* Call the appropriate function to determine the overlap. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1418 if ((this->*detect_overlap) ())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1419 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1420 if (!sizrange[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1421 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1422 /* Unless the access size range has already been set, do so here. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1423 sizrange[0] = wi::smax (acs.dstsiz[0], srcref->sizrange[0]).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1424 sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1425 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1426 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1427 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1428
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1429 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1430 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1431
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1432 /* Attempt to detect and diagnose an overlapping copy in a call expression
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1433 EXPR involving an an access ACS to a built-in memory or string function.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1434 Return true when one has been detected, false otherwise. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1435
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1436 static bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1437 maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1438 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1439 if (!acs.overlap ())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1440 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1441
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1442 if (gimple_no_warning_p (call))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1443 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1444
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1445 /* For convenience. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1446 const builtin_memref &dstref = *acs.dstref;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1447 const builtin_memref &srcref = *acs.srcref;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1448
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1449 /* Determine the range of offsets and sizes of the overlap if it
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1450 exists and issue diagnostics. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1451 HOST_WIDE_INT *ovloff = acs.ovloff;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1452 HOST_WIDE_INT *ovlsiz = acs.ovlsiz;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1453 HOST_WIDE_INT *sizrange = acs.sizrange;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1454
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1455 tree func = gimple_call_fndecl (call);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1456
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1457 /* To avoid a combinatorial explosion of diagnostics format the offsets
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1458 or their ranges as strings and use them in the warning calls below. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1459 char offstr[3][64];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1460
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1461 if (dstref.offrange[0] == dstref.offrange[1]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1462 || dstref.offrange[1] > HOST_WIDE_INT_MAX)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1463 sprintf (offstr[0], HOST_WIDE_INT_PRINT_DEC,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1464 dstref.offrange[0].to_shwi ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1465 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1466 sprintf (offstr[0],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1467 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1468 dstref.offrange[0].to_shwi (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1469 dstref.offrange[1].to_shwi ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1470
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1471 if (srcref.offrange[0] == srcref.offrange[1]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1472 || srcref.offrange[1] > HOST_WIDE_INT_MAX)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1473 sprintf (offstr[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1474 HOST_WIDE_INT_PRINT_DEC,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1475 srcref.offrange[0].to_shwi ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1476 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1477 sprintf (offstr[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1478 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1479 srcref.offrange[0].to_shwi (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1480 srcref.offrange[1].to_shwi ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1481
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1482 if (ovloff[0] == ovloff[1] || !ovloff[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1483 sprintf (offstr[2], HOST_WIDE_INT_PRINT_DEC, ovloff[0]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1484 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1485 sprintf (offstr[2],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1486 "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1487 ovloff[0], ovloff[1]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1488
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1489 const offset_int maxobjsize = dstref.maxobjsize;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1490 bool must_overlap = ovlsiz[0] > 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1491
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1492 if (ovlsiz[1] == 0)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1493 ovlsiz[1] = ovlsiz[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1494
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1495 if (must_overlap)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1496 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1497 /* Issue definitive "overlaps" diagnostic in this block. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1498
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1499 if (sizrange[0] == sizrange[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1500 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1501 if (ovlsiz[0] == ovlsiz[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1502 warning_at (loc, OPT_Wrestrict,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1503 sizrange[0] == 1
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1504 ? (ovlsiz[0] == 1
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1505 ? G_("%G%qD accessing %wu byte at offsets %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1506 "and %s overlaps %wu byte at offset %s")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1507 : G_("%G%qD accessing %wu byte at offsets %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1508 "and %s overlaps %wu bytes at offset "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1509 "%s"))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1510 : (ovlsiz[0] == 1
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1511 ? G_("%G%qD accessing %wu bytes at offsets %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1512 "and %s overlaps %wu byte at offset %s")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1513 : G_("%G%qD accessing %wu bytes at offsets %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1514 "and %s overlaps %wu bytes at offset "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1515 "%s")),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1516 call, func, sizrange[0],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1517 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1518 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1519 warning_n (loc, OPT_Wrestrict, sizrange[0],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1520 "%G%qD accessing %wu byte at offsets %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1521 "and %s overlaps between %wu and %wu bytes "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1522 "at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1523 "%G%qD accessing %wu bytes at offsets %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1524 "and %s overlaps between %wu and %wu bytes "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1525 "at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1526 call, func, sizrange[0], offstr[0], offstr[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1527 ovlsiz[0], ovlsiz[1], offstr[2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1528 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1529 warning_n (loc, OPT_Wrestrict, sizrange[0],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1530 "%G%qD accessing %wu byte at offsets %s and "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1531 "%s overlaps %wu or more bytes at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1532 "%G%qD accessing %wu bytes at offsets %s and "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1533 "%s overlaps %wu or more bytes at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1534 call, func, sizrange[0],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1535 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1536 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1537 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1538
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1539 if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1540 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1541 if (ovlsiz[0] == ovlsiz[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1542 warning_n (loc, OPT_Wrestrict, ovlsiz[0],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1543 "%G%qD accessing between %wu and %wu bytes "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1544 "at offsets %s and %s overlaps %wu byte at "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1545 "offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1546 "%G%qD accessing between %wu and %wu bytes "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1547 "at offsets %s and %s overlaps %wu bytes "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1548 "at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1549 call, func, sizrange[0], sizrange[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1550 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1551 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1552 warning_at (loc, OPT_Wrestrict,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1553 "%G%qD accessing between %wu and %wu bytes at "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1554 "offsets %s and %s overlaps between %wu and %wu "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1555 "bytes at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1556 call, func, sizrange[0], sizrange[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1557 offstr[0], offstr[1], ovlsiz[0], ovlsiz[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1558 offstr[2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1559 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1560 warning_at (loc, OPT_Wrestrict,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1561 "%G%qD accessing between %wu and %wu bytes at "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1562 "offsets %s and %s overlaps %wu or more bytes "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1563 "at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1564 call, func, sizrange[0], sizrange[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1565 offstr[0], offstr[1], ovlsiz[0], offstr[2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1566 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1567 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1568
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1569 if (ovlsiz[0] != ovlsiz[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1570 ovlsiz[1] = maxobjsize.to_shwi ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1571
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1572 if (ovlsiz[0] == ovlsiz[1])
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1573 warning_n (loc, OPT_Wrestrict, ovlsiz[0],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1574 "%G%qD accessing %wu or more bytes at offsets "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1575 "%s and %s overlaps %wu byte at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1576 "%G%qD accessing %wu or more bytes at offsets "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1577 "%s and %s overlaps %wu bytes at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1578 call, func, sizrange[0], offstr[0], offstr[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1579 ovlsiz[0], offstr[2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1580 else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1581 warning_at (loc, OPT_Wrestrict,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1582 "%G%qD accessing %wu or more bytes at offsets %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1583 "and %s overlaps between %wu and %wu bytes "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1584 "at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1585 call, func, sizrange[0], offstr[0], offstr[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1586 ovlsiz[0], ovlsiz[1], offstr[2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1587 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1588 warning_at (loc, OPT_Wrestrict,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1589 "%G%qD accessing %wu or more bytes at offsets %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1590 "and %s overlaps %wu or more bytes at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1591 call, func, sizrange[0], offstr[0], offstr[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1592 ovlsiz[0], offstr[2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1593 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1594 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1595
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1596 /* Use more concise wording when one of the offsets is unbounded
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1597 to avoid confusing the user with large and mostly meaningless
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1598 numbers. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1599 bool open_range;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1600 if (DECL_P (dstref.base) && TREE_CODE (TREE_TYPE (dstref.base)) == ARRAY_TYPE)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1601 open_range = ((dstref.offrange[0] == 0
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1602 && dstref.offrange[1] == maxobjsize)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1603 || (srcref.offrange[0] == 0
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1604 && srcref.offrange[1] == maxobjsize));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1605 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1606 open_range = ((dstref.offrange[0] == -maxobjsize - 1
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1607 && dstref.offrange[1] == maxobjsize)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1608 || (srcref.offrange[0] == -maxobjsize - 1
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1609 && srcref.offrange[1] == maxobjsize));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1610
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1611 if (sizrange[0] == sizrange[1] || sizrange[1] == 1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1612 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1613 if (ovlsiz[1] == 1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1614 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1615 if (open_range)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1616 warning_n (loc, OPT_Wrestrict, sizrange[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1617 "%G%qD accessing %wu byte may overlap "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1618 "%wu byte",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1619 "%G%qD accessing %wu bytes may overlap "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1620 "%wu byte",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1621 call, func, sizrange[1], ovlsiz[1]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1622 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1623 warning_n (loc, OPT_Wrestrict, sizrange[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1624 "%G%qD accessing %wu byte at offsets %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1625 "and %s may overlap %wu byte at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1626 "%G%qD accessing %wu bytes at offsets %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1627 "and %s may overlap %wu byte at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1628 call, func, sizrange[1], offstr[0], offstr[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1629 ovlsiz[1], offstr[2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1630 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1631 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1632
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1633 if (open_range)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1634 warning_n (loc, OPT_Wrestrict, sizrange[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1635 "%G%qD accessing %wu byte may overlap "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1636 "up to %wu bytes",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1637 "%G%qD accessing %wu bytes may overlap "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1638 "up to %wu bytes",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1639 call, func, sizrange[1], ovlsiz[1]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1640 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1641 warning_n (loc, OPT_Wrestrict, sizrange[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1642 "%G%qD accessing %wu byte at offsets %s and "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1643 "%s may overlap up to %wu bytes at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1644 "%G%qD accessing %wu bytes at offsets %s and "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1645 "%s may overlap up to %wu bytes at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1646 call, func, sizrange[1], offstr[0], offstr[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1647 ovlsiz[1], offstr[2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1648 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1649 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1650
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1651 if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1652 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1653 if (open_range)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1654 warning_n (loc, OPT_Wrestrict, ovlsiz[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1655 "%G%qD accessing between %wu and %wu bytes "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1656 "may overlap %wu byte",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1657 "%G%qD accessing between %wu and %wu bytes "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1658 "may overlap up to %wu bytes",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1659 call, func, sizrange[0], sizrange[1], ovlsiz[1]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1660 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1661 warning_n (loc, OPT_Wrestrict, ovlsiz[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1662 "%G%qD accessing between %wu and %wu bytes "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1663 "at offsets %s and %s may overlap %wu byte "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1664 "at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1665 "%G%qD accessing between %wu and %wu bytes "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1666 "at offsets %s and %s may overlap up to %wu "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1667 "bytes at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1668 call, func, sizrange[0], sizrange[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1669 offstr[0], offstr[1], ovlsiz[1], offstr[2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1670 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1671 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1672
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1673 warning_n (loc, OPT_Wrestrict, ovlsiz[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1674 "%G%qD accessing %wu or more bytes at offsets %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1675 "and %s may overlap %wu byte at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1676 "%G%qD accessing %wu or more bytes at offsets %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1677 "and %s may overlap up to %wu bytes at offset %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1678 call, func, sizrange[0], offstr[0], offstr[1],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1679 ovlsiz[1], offstr[2]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1680
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1681 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1682 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1683
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1684 /* Validate REF size and offsets in an expression passed as an argument
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1685 to a CALL to a built-in function FUNC to make sure they are within
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1686 the bounds of the referenced object if its size is known, or
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1687 PTRDIFF_MAX otherwise. DO_WARN is true when a diagnostic should
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1688 be issued, false otherwise.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1689 Both initial values of the offsets and their final value computed
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1690 by the function by incrementing the initial value by the size are
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1691 validated. Return true if the offsets are not valid and a diagnostic
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1692 has been issued, or would have been issued if DO_WARN had been true. */
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1693
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1694 static bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1695 maybe_diag_access_bounds (location_t loc, gimple *call, tree func, int strict,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1696 const builtin_memref &ref, offset_int wroff,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1697 bool do_warn)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1698 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1699 const offset_int maxobjsize = ref.maxobjsize;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1700
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1701 /* Check for excessive size first and regardless of warning options
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1702 since the result is used to make codegen decisions. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1703 if (ref.sizrange[0] > maxobjsize)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1704 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1705 /* Return true without issuing a warning. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1706 if (!do_warn)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1707 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1708
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1709 if (ref.ref && TREE_NO_WARNING (ref.ref))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1710 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1711
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1712 if (warn_stringop_overflow)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1713 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1714 if (EXPR_HAS_LOCATION (ref.ptr))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1715 loc = EXPR_LOCATION (ref.ptr);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1716
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1717 loc = expansion_point_location_if_in_system_header (loc);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1718
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1719 if (ref.sizrange[0] == ref.sizrange[1])
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1720 return warning_at (loc, OPT_Wstringop_overflow_,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1721 "%G%qD specified bound %wu "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1722 "exceeds maximum object size %wu",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1723 call, func, ref.sizrange[0].to_uhwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1724 maxobjsize.to_uhwi ());
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1725
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1726 return warning_at (loc, OPT_Wstringop_overflow_,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1727 "%G%qD specified bound between %wu and %wu "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1728 "exceeds maximum object size %wu",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1729 call, func, ref.sizrange[0].to_uhwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1730 ref.sizrange[1].to_uhwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1731 maxobjsize.to_uhwi ());
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1732 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1733 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1734
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1735 /* Check for out-bounds pointers regardless of warning options since
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1736 the result is used to make codegen decisions. An excessive WROFF
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1737 can only come up as a result of an invalid strncat bound and is
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1738 diagnosed separately using a more meaningful warning. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1739 if (maxobjsize < wroff)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1740 wroff = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1741 offset_int ooboff[] = { ref.offrange[0], ref.offrange[1], wroff };
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1742 tree oobref = ref.offset_out_of_bounds (strict, ooboff);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1743 if (!oobref)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1744 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1745
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1746 /* Return true without issuing a warning. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1747 if (!do_warn)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1748 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1749
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1750 if (!warn_array_bounds)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1751 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1752
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1753 if (TREE_NO_WARNING (ref.ptr)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1754 || (ref.ref && TREE_NO_WARNING (ref.ref)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1755 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1756
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1757 if (EXPR_HAS_LOCATION (ref.ptr))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1758 loc = EXPR_LOCATION (ref.ptr);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1759
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1760 loc = expansion_point_location_if_in_system_header (loc);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1761
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1762 char rangestr[2][64];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1763 if (ooboff[0] == ooboff[1]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1764 || (ooboff[0] != ref.offrange[0]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1765 && ooboff[0].to_shwi () >= ooboff[1].to_shwi ()))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1766 sprintf (rangestr[0], "%lli", (long long) ooboff[0].to_shwi ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1767 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1768 sprintf (rangestr[0], "[%lli, %lli]",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1769 (long long) ooboff[0].to_shwi (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1770 (long long) ooboff[1].to_shwi ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1771
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1772 bool warned = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1773
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1774 if (oobref == error_mark_node)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1775 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1776 if (ref.sizrange[0] == ref.sizrange[1])
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1777 sprintf (rangestr[1], "%llu",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1778 (unsigned long long) ref.sizrange[0].to_shwi ());
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1779 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1780 sprintf (rangestr[1], "[%lli, %lli]",
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1781 (unsigned long long) ref.sizrange[0].to_uhwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1782 (unsigned long long) ref.sizrange[1].to_uhwi ());
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1783
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1784 tree type;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1785
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1786 if (DECL_P (ref.base)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1787 && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1788 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1789 auto_diagnostic_group d;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1790 if (warning_at (loc, OPT_Warray_bounds,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1791 "%G%qD pointer overflow between offset %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1792 "and size %s accessing array %qD with type %qT",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1793 call, func, rangestr[0], rangestr[1], ref.base, type))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1794 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1795 inform (DECL_SOURCE_LOCATION (ref.base),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1796 "array %qD declared here", ref.base);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1797 warned = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1798 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1799 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1800 warned = warning_at (loc, OPT_Warray_bounds,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1801 "%G%qD pointer overflow between offset %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1802 "and size %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1803 call, func, rangestr[0], rangestr[1]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1804 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1805 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1806 warned = warning_at (loc, OPT_Warray_bounds,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1807 "%G%qD pointer overflow between offset %s "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1808 "and size %s",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1809 call, func, rangestr[0], rangestr[1]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1810 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1811 else if (oobref == ref.base)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1812 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1813 /* True when the offset formed by an access to the reference
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1814 is out of bounds, rather than the initial offset wich is
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1815 in bounds. This implies access past the end. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1816 bool form = ooboff[0] != ref.offrange[0];
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1817
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1818 if (DECL_P (ref.base))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1819 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1820 auto_diagnostic_group d;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1821 if ((ref.basesize < maxobjsize
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1822 && warning_at (loc, OPT_Warray_bounds,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1823 form
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1824 ? G_("%G%qD forming offset %s is out of "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1825 "the bounds [0, %wu] of object %qD with "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1826 "type %qT")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1827 : G_("%G%qD offset %s is out of the bounds "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1828 "[0, %wu] of object %qD with type %qT"),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1829 call, func, rangestr[0], ref.basesize.to_uhwi (),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1830 ref.base, TREE_TYPE (ref.base)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1831 || warning_at (loc, OPT_Warray_bounds,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1832 form
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1833 ? G_("%G%qD forming offset %s is out of "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1834 "the bounds of object %qD with type %qT")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1835 : G_("%G%qD offset %s is out of the bounds "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1836 "of object %qD with type %qT"),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1837 call, func, rangestr[0],
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1838 ref.base, TREE_TYPE (ref.base)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1839 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1840 inform (DECL_SOURCE_LOCATION (ref.base),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1841 "%qD declared here", ref.base);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1842 warned = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1843 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1844 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1845 else if (ref.basesize < maxobjsize)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1846 warned = warning_at (loc, OPT_Warray_bounds,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1847 form
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1848 ? G_("%G%qD forming offset %s is out "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1849 "of the bounds [0, %wu]")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1850 : G_("%G%qD offset %s is out "
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1851 "of the bounds [0, %wu]"),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1852 call, func, rangestr[0], ref.basesize.to_uhwi ());
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1853 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1854 warned = warning_at (loc, OPT_Warray_bounds,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1855 form
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1856 ? G_("%G%qD forming offset %s is out of bounds")
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1857 : G_("%G%qD offset %s is out of bounds"),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1858 call, func, rangestr[0]);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1859 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1860 else if (TREE_CODE (ref.ref) == MEM_REF)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1861 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1862 tree refop = TREE_OPERAND (ref.ref, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1863 tree type = TREE_TYPE (refop);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1864 if (POINTER_TYPE_P (type))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1865 type = TREE_TYPE (type);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1866 type = TYPE_MAIN_VARIANT (type);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1867
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1868 if (warning_at (loc, OPT_Warray_bounds,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1869 "%G%qD offset %s from the object at %qE is out "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1870 "of the bounds of %qT",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1871 call, func, rangestr[0], ref.base, type))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1872 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1873 if (TREE_CODE (ref.ref) == COMPONENT_REF)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1874 refop = TREE_OPERAND (ref.ref, 1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1875 if (DECL_P (refop))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1876 inform (DECL_SOURCE_LOCATION (refop),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1877 "subobject %qD declared here", refop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1878 warned = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1879 }
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1880 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1881 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1882 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1883 tree refop = TREE_OPERAND (ref.ref, 0);
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1884 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1885
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1886 if (warning_at (loc, OPT_Warray_bounds,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1887 "%G%qD offset %s from the object at %qE is out "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1888 "of the bounds of referenced subobject %qD with "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1889 "type %qT at offset %wi",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1890 call, func, rangestr[0], ref.base,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1891 TREE_OPERAND (ref.ref, 1), type,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1892 ref.refoff.to_shwi ()))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1893 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1894 if (TREE_CODE (ref.ref) == COMPONENT_REF)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1895 refop = TREE_OPERAND (ref.ref, 1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1896 if (DECL_P (refop))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1897 inform (DECL_SOURCE_LOCATION (refop),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1898 "subobject %qD declared here", refop);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1899 warned = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1900 }
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1901 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1902
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1903 return warned;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1904 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1905
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1906 /* Check a CALL statement for restrict-violations and issue warnings
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1907 if/when appropriate. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1908
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1909 void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1910 wrestrict_dom_walker::check_call (gimple *call)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1911 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1912 /* Avoid checking the call if it has already been diagnosed for
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1913 some reason. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1914 if (gimple_no_warning_p (call))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1915 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1916
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1917 tree func = gimple_call_fndecl (call);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1918 if (!func || !fndecl_built_in_p (func, BUILT_IN_NORMAL))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1919 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1920
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1921 /* Argument number to extract from the call (depends on the built-in
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1922 and its kind). */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1923 unsigned dst_idx = -1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1924 unsigned src_idx = -1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1925 unsigned bnd_idx = -1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1926
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1927 /* Is this CALL to a string function (as opposed to one to a raw
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1928 memory function). */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1929 bool strfun = true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1930
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1931 switch (DECL_FUNCTION_CODE (func))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1932 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1933 case BUILT_IN_MEMCPY:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1934 case BUILT_IN_MEMCPY_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1935 case BUILT_IN_MEMPCPY:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1936 case BUILT_IN_MEMPCPY_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1937 case BUILT_IN_MEMMOVE:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1938 case BUILT_IN_MEMMOVE_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1939 strfun = false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1940 /* Fall through. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1941
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1942 case BUILT_IN_STPNCPY:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1943 case BUILT_IN_STPNCPY_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1944 case BUILT_IN_STRNCAT:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1945 case BUILT_IN_STRNCAT_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1946 case BUILT_IN_STRNCPY:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1947 case BUILT_IN_STRNCPY_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1948 dst_idx = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1949 src_idx = 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1950 bnd_idx = 2;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1951 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1952
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1953 case BUILT_IN_MEMSET:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1954 case BUILT_IN_MEMSET_CHK:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1955 dst_idx = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1956 bnd_idx = 2;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1957 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1958
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1959 case BUILT_IN_STPCPY:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1960 case BUILT_IN_STPCPY_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1961 case BUILT_IN_STRCPY:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1962 case BUILT_IN_STRCPY_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1963 case BUILT_IN_STRCAT:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1964 case BUILT_IN_STRCAT_CHK:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1965 dst_idx = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1966 src_idx = 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1967 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1968
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1969 default:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1970 /* Handle other string functions here whose access may need
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1971 to be validated for in-bounds offsets and non-overlapping
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1972 copies. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1973 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1974 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1975
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1976 unsigned nargs = gimple_call_num_args (call);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1977
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1978 tree dst = dst_idx < nargs ? gimple_call_arg (call, dst_idx) : NULL_TREE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1979 tree src = src_idx < nargs ? gimple_call_arg (call, src_idx) : NULL_TREE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1980 tree dstwr = bnd_idx < nargs ? gimple_call_arg (call, bnd_idx) : NULL_TREE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1981
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1982 /* For string functions with an unspecified or unknown bound,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1983 assume the size of the access is one. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1984 if (!dstwr && strfun)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1985 dstwr = size_one_node;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1986
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1987 /* DST and SRC can be null for a call with an insufficient number
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1988 of arguments to a built-in function declared without a protype. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1989 if (!dst || (src_idx < nargs && !src))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1990 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1991
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1992 /* DST, SRC, or DSTWR can also have the wrong type in a call to
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1993 a function declared without a prototype. Avoid checking such
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1994 invalid calls. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1995 if (TREE_CODE (TREE_TYPE (dst)) != POINTER_TYPE
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1996 || (src && TREE_CODE (TREE_TYPE (src)) != POINTER_TYPE)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1997 || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr))))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1998 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1999
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2000 if (!check_bounds_or_overlap (call, dst, src, dstwr, NULL_TREE))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2001 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2002
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2003 /* Avoid diagnosing the call again. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2004 gimple_set_no_warning (call, true);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2005 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2006
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2007 } /* anonymous namespace */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2008
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2009 /* Attempt to detect and diagnose invalid offset bounds and (except for
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2010 memmove) overlapping copy in a call expression EXPR from SRC to DST
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2011 and DSTSIZE and SRCSIZE bytes, respectively. Both DSTSIZE and
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2012 SRCSIZE may be NULL. DO_WARN is false to detect either problem
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2013 without issue a warning. Return the OPT_Wxxx constant corresponding
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2014 to the warning if one has been detected and zero otherwise. */
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2015
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2016 int
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2017 check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2018 tree srcsize, bool bounds_only /* = false */,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2019 bool do_warn /* = true */)
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2020 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2021 location_t loc = gimple_nonartificial_location (call);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2022 loc = expansion_point_location_if_in_system_header (loc);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2023
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2024 tree func = gimple_call_fndecl (call);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2025
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2026 builtin_memref dstref (dst, dstsize);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2027 builtin_memref srcref (src, srcsize);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2028
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2029 /* Create a descriptor of the access. This may adjust both DSTREF
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2030 and SRCREF based on one another and the kind of the access. */
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2031 builtin_access acs (call, dstref, srcref);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2032
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2033 /* Set STRICT to the value of the -Warray-bounds=N argument for
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2034 string functions or when N > 1. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2035 int strict = (acs.strict () || warn_array_bounds > 1 ? warn_array_bounds : 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2036
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2037 /* The starting offset of the destination write access. Nonzero only
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2038 for the strcat family of functions. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2039 offset_int wroff = acs.write_off (dstsize);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2040
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2041 /* Validate offsets to each reference before the access first to make
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2042 sure they are within the bounds of the destination object if its
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2043 size is known, or PTRDIFF_MAX otherwise. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2044 if (maybe_diag_access_bounds (loc, call, func, strict, dstref, wroff, do_warn)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2045 || maybe_diag_access_bounds (loc, call, func, strict, srcref, 0, do_warn))
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2046 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2047 if (do_warn)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2048 gimple_set_no_warning (call, true);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2049 return OPT_Warray_bounds;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2050 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2051
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2052 if (!warn_restrict || bounds_only || !src)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2053 return 0;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2054
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2055 if (!bounds_only)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2056 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2057 switch (DECL_FUNCTION_CODE (func))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2058 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2059 case BUILT_IN_MEMMOVE:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2060 case BUILT_IN_MEMMOVE_CHK:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2061 case BUILT_IN_MEMSET:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2062 case BUILT_IN_MEMSET_CHK:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2063 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2064 default:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2065 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2066 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2067 }
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2068
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2069 if (operand_equal_p (dst, src, 0))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2070 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2071 /* Issue -Wrestrict unless the pointers are null (those do
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2072 not point to objects and so do not indicate an overlap;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2073 such calls could be the result of sanitization and jump
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2074 threading). */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2075 if (!integer_zerop (dst) && !gimple_no_warning_p (call))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2076 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2077 warning_at (loc, OPT_Wrestrict,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2078 "%G%qD source argument is the same as destination",
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2079 call, func);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2080 gimple_set_no_warning (call, true);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2081 return OPT_Wrestrict;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2082 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2083
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2084 return 0;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2085 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2086
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2087 /* Return false when overlap has been detected. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2088 if (maybe_diag_overlap (loc, call, acs))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2089 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2090 gimple_set_no_warning (call, true);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2091 return OPT_Wrestrict;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2092 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2093
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2094 return 0;
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2095 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2096
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2097 gimple_opt_pass *
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2098 make_pass_warn_restrict (gcc::context *ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2099 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2100 return new pass_wrestrict (ctxt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2101 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2102
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2103 DEBUG_FUNCTION void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2104 dump_builtin_memref (FILE *fp, const builtin_memref &ref)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2105 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2106 fprintf (fp, "\n ptr = ");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2107 print_generic_expr (fp, ref.ptr, TDF_LINENO);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2108 fprintf (fp, "\n ref = ");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2109 if (ref.ref)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2110 print_generic_expr (fp, ref.ref, TDF_LINENO);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2111 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2112 fputs ("null", fp);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2113 fprintf (fp, "\n base = ");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2114 print_generic_expr (fp, ref.base, TDF_LINENO);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2115 fprintf (fp,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2116 "\n basesize = %lli"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2117 "\n refsize = %lli"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2118 "\n refoff = %lli"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2119 "\n offrange = [%lli, %lli]"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2120 "\n sizrange = [%lli, %lli]"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2121 "\n strbounded_p = %s\n",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2122 (long long)ref.basesize.to_shwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2123 (long long)ref.refsize.to_shwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2124 (long long)ref.refoff.to_shwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2125 (long long)ref.offrange[0].to_shwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2126 (long long)ref.offrange[1].to_shwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2127 (long long)ref.sizrange[0].to_shwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2128 (long long)ref.sizrange[1].to_shwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2129 ref.strbounded_p ? "true" : "false");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2130 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2131
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2132 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2133 builtin_access::dump (FILE *fp) const
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2134 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2135 fprintf (fp, " dstref:");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2136 dump_builtin_memref (fp, *dstref);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2137 fprintf (fp, "\n srcref:");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2138 dump_builtin_memref (fp, *srcref);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2139
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2140 fprintf (fp,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2141 " sizrange = [%lli, %lli]\n"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2142 " ovloff = [%lli, %lli]\n"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2143 " ovlsiz = [%lli, %lli]\n"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2144 " dstoff = [%lli, %lli]\n"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2145 " dstsiz = [%lli, %lli]\n"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2146 " srcoff = [%lli, %lli]\n"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2147 " srcsiz = [%lli, %lli]\n",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2148 (long long)sizrange[0], (long long)sizrange[1],
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2149 (long long)ovloff[0], (long long)ovloff[1],
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2150 (long long)ovlsiz[0], (long long)ovlsiz[1],
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2151 (long long)dstoff[0].to_shwi (), (long long)dstoff[1].to_shwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2152 (long long)dstsiz[0].to_shwi (), (long long)dstsiz[1].to_shwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2153 (long long)srcoff[0].to_shwi (), (long long)srcoff[1].to_shwi (),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2154 (long long)srcsiz[0].to_shwi (), (long long)srcsiz[1].to_shwi ());
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2155 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2156
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2157 DEBUG_FUNCTION void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2158 dump_builtin_access (FILE *fp, gimple *stmt, const builtin_access &acs)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2159 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2160 if (stmt)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2161 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2162 fprintf (fp, "\nDumping builtin_access for ");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2163 print_gimple_expr (fp, stmt, TDF_LINENO);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2164 fputs (":\n", fp);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2165 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2166
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2167 acs.dump (fp);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2168 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2169
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2170 DEBUG_FUNCTION void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2171 debug (gimple *stmt, const builtin_access &acs)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2172 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2173 dump_builtin_access (stdout, stmt, acs);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2174 }