annotate gcc/gimple-ssa-warn-restrict.c @ 131:84e7813d76e9

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