]>
Commit | Line | Data |
---|---|---|
8d08fdba MS |
1 | /* Convert language-specific tree expression to rtl instructions, |
2 | for GNU compiler. | |
a5544970 | 3 | Copyright (C) 1988-2019 Free Software Foundation, Inc. |
8d08fdba | 4 | |
f5adbb8d | 5 | This file is part of GCC. |
8d08fdba | 6 | |
f5adbb8d | 7 | GCC is free software; you can redistribute it and/or modify |
8d08fdba | 8 | it under the terms of the GNU General Public License as published by |
e77f031d | 9 | the Free Software Foundation; either version 3, or (at your option) |
8d08fdba MS |
10 | any later version. |
11 | ||
f5adbb8d | 12 | GCC is distributed in the hope that it will be useful, |
8d08fdba MS |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
e77f031d NC |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ | |
8d08fdba MS |
20 | |
21 | ||
22 | #include "config.h" | |
8d052bc7 | 23 | #include "system.h" |
4977bab6 | 24 | #include "coretypes.h" |
8d08fdba MS |
25 | #include "cp-tree.h" |
26 | ||
6524147c | 27 | /* Expand C++-specific constants. Currently, this means PTRMEM_CST. */ |
87533b37 | 28 | |
b928a651 | 29 | tree |
d9b4e85e | 30 | cplus_expand_constant (tree cst) |
87533b37 MM |
31 | { |
32 | switch (TREE_CODE (cst)) | |
33 | { | |
34 | case PTRMEM_CST: | |
35 | { | |
36 | tree type = TREE_TYPE (cst); | |
37 | tree member; | |
c8094d83 | 38 | |
87533b37 MM |
39 | /* Find the member. */ |
40 | member = PTRMEM_CST_MEMBER (cst); | |
41 | ||
deaae9d7 JM |
42 | /* We can't lower this until the class is complete. */ |
43 | if (!COMPLETE_TYPE_P (DECL_CONTEXT (member))) | |
44 | return cst; | |
45 | ||
c8094d83 | 46 | if (TREE_CODE (member) == FIELD_DECL) |
b3dd05b1 MM |
47 | { |
48 | /* Find the offset for the field. */ | |
49 | cst = byte_position (member); | |
50 | while (!same_type_p (DECL_CONTEXT (member), | |
51 | TYPE_PTRMEM_CLASS_TYPE (type))) | |
52 | { | |
53 | /* The MEMBER must have been nestled within an | |
54 | anonymous aggregate contained in TYPE. Find the | |
55 | anonymous aggregate. */ | |
56 | member = lookup_anon_field (TYPE_PTRMEM_CLASS_TYPE (type), | |
57 | DECL_CONTEXT (member)); | |
58 | cst = size_binop (PLUS_EXPR, cst, byte_position (member)); | |
59 | } | |
60 | cst = fold (build_nop (type, cst)); | |
61 | } | |
87533b37 MM |
62 | else |
63 | { | |
530ec96d MM |
64 | tree delta; |
65 | tree pfn; | |
87533b37 | 66 | |
18ae7f63 AO |
67 | expand_ptrmemfunc_cst (cst, &delta, &pfn); |
68 | cst = build_ptrmemfunc1 (type, delta, pfn); | |
87533b37 MM |
69 | } |
70 | } | |
71 | break; | |
72 | ||
2d7d7f0f JM |
73 | case CONSTRUCTOR: |
74 | { | |
75 | constructor_elt *elt; | |
76 | unsigned HOST_WIDE_INT idx; | |
77 | FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (cst), idx, elt) | |
78 | elt->value = cplus_expand_constant (elt->value); | |
79 | } | |
80 | ||
87533b37 MM |
81 | default: |
82 | /* There's nothing to do. */ | |
83 | break; | |
84 | } | |
85 | ||
86 | return cst; | |
87 | } | |
03a904b5 | 88 | |
281e6c1d JM |
89 | /* We've seen an actual use of EXPR. Possibly replace an outer variable |
90 | reference inside with its constant value or a lambda capture. */ | |
91 | ||
5a752e3f | 92 | tree |
281e6c1d JM |
93 | mark_use (tree expr, bool rvalue_p, bool read_p, |
94 | location_t loc /* = UNKNOWN_LOCATION */, | |
95 | bool reject_builtin /* = true */) | |
96 | { | |
97 | #define RECUR(t) mark_use ((t), rvalue_p, read_p, loc, reject_builtin) | |
98 | ||
84dd815f JM |
99 | if (expr == NULL_TREE || expr == error_mark_node) |
100 | return expr; | |
101 | ||
281e6c1d JM |
102 | if (reject_builtin && reject_gcc_builtin (expr, loc)) |
103 | return error_mark_node; | |
104 | ||
105 | if (read_p) | |
106 | mark_exp_read (expr); | |
107 | ||
84dd815f | 108 | tree oexpr = expr; |
281e6c1d JM |
109 | bool recurse_op[3] = { false, false, false }; |
110 | switch (TREE_CODE (expr)) | |
111 | { | |
112 | case VAR_DECL: | |
84dd815f | 113 | case PARM_DECL: |
68ad1bf7 | 114 | if (rvalue_p && is_normal_capture_proxy (expr)) |
c1051bf7 JM |
115 | { |
116 | /* Look through capture by copy. */ | |
117 | tree cap = DECL_CAPTURED_VARIABLE (expr); | |
118 | if (TREE_CODE (TREE_TYPE (cap)) == TREE_CODE (TREE_TYPE (expr)) | |
119 | && decl_constant_var_p (cap)) | |
1577f10a JM |
120 | { |
121 | tree val = RECUR (cap); | |
122 | if (!is_capture_proxy (val)) | |
123 | { | |
124 | tree l = current_lambda_expr (); | |
125 | LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true; | |
126 | } | |
127 | return val; | |
128 | } | |
c1051bf7 | 129 | } |
281e6c1d JM |
130 | if (outer_automatic_var_p (expr) |
131 | && decl_constant_var_p (expr)) | |
132 | { | |
133 | if (rvalue_p) | |
134 | { | |
135 | tree t = maybe_constant_value (expr); | |
136 | if (TREE_CONSTANT (t)) | |
137 | { | |
138 | expr = t; | |
139 | break; | |
140 | } | |
141 | } | |
57ea03ad JM |
142 | temp_override<location_t> l (input_location); |
143 | if (loc != UNKNOWN_LOCATION) | |
144 | input_location = loc; | |
281e6c1d | 145 | expr = process_outer_var_ref (expr, tf_warning_or_error, true); |
84dd815f | 146 | if (!(TREE_TYPE (oexpr) |
9f613f06 | 147 | && TYPE_REF_P (TREE_TYPE (oexpr)))) |
84dd815f | 148 | expr = convert_from_reference (expr); |
281e6c1d JM |
149 | } |
150 | break; | |
151 | case COMPONENT_REF: | |
84dd815f | 152 | case NON_DEPENDENT_EXPR: |
281e6c1d JM |
153 | recurse_op[0] = true; |
154 | break; | |
155 | case COMPOUND_EXPR: | |
156 | recurse_op[1] = true; | |
157 | break; | |
158 | case COND_EXPR: | |
159 | recurse_op[2] = true; | |
160 | if (TREE_OPERAND (expr, 1)) | |
161 | recurse_op[1] = true; | |
162 | break; | |
163 | case INDIRECT_REF: | |
164 | if (REFERENCE_REF_P (expr)) | |
165 | { | |
166 | /* Try to look through the reference. */ | |
167 | tree ref = TREE_OPERAND (expr, 0); | |
68ad1bf7 | 168 | if (rvalue_p && is_normal_capture_proxy (ref)) |
c1051bf7 JM |
169 | { |
170 | /* Look through capture by reference. */ | |
171 | tree cap = DECL_CAPTURED_VARIABLE (ref); | |
9f613f06 | 172 | if (!TYPE_REF_P (TREE_TYPE (cap)) |
c1051bf7 | 173 | && decl_constant_var_p (cap)) |
1577f10a JM |
174 | { |
175 | tree val = RECUR (cap); | |
176 | if (!is_capture_proxy (val)) | |
177 | { | |
178 | tree l = current_lambda_expr (); | |
179 | LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true; | |
180 | } | |
181 | return val; | |
182 | } | |
c1051bf7 | 183 | } |
281e6c1d JM |
184 | tree r = mark_rvalue_use (ref, loc, reject_builtin); |
185 | if (r != ref) | |
84dd815f | 186 | expr = convert_from_reference (r); |
281e6c1d JM |
187 | } |
188 | break; | |
94aedc1c JM |
189 | |
190 | CASE_CONVERT: | |
191 | case VIEW_CONVERT_EXPR: | |
57ea03ad | 192 | if (location_wrapper_p (expr)) |
94aedc1c JM |
193 | loc = EXPR_LOCATION (expr); |
194 | recurse_op[0] = true; | |
195 | break; | |
196 | ||
197 | default: | |
281e6c1d JM |
198 | break; |
199 | } | |
200 | ||
281e6c1d JM |
201 | for (int i = 0; i < 3; ++i) |
202 | if (recurse_op[i]) | |
203 | { | |
204 | tree op = TREE_OPERAND (expr, i); | |
84dd815f JM |
205 | op = RECUR (op); |
206 | if (op == error_mark_node) | |
207 | return error_mark_node; | |
208 | TREE_OPERAND (expr, i) = op; | |
281e6c1d JM |
209 | } |
210 | ||
281e6c1d JM |
211 | return expr; |
212 | #undef RECUR | |
213 | } | |
214 | ||
1807ffc1 MS |
215 | /* Called whenever the expression EXPR is used in an rvalue context. |
216 | When REJECT_BUILTIN is true the expression is checked to make sure | |
217 | it doesn't make it possible to obtain the address of a GCC built-in | |
218 | function with no library fallback (or any of its bits, such as in | |
219 | a conversion to bool). */ | |
281e6c1d | 220 | |
03a904b5 | 221 | tree |
281e6c1d | 222 | mark_rvalue_use (tree e, |
1807ffc1 MS |
223 | location_t loc /* = UNKNOWN_LOCATION */, |
224 | bool reject_builtin /* = true */) | |
03a904b5 | 225 | { |
281e6c1d | 226 | return mark_use (e, true, true, loc, reject_builtin); |
03a904b5 JJ |
227 | } |
228 | ||
b8461915 NS |
229 | /* Called whenever an expression is used in an lvalue context. */ |
230 | ||
231 | tree | |
232 | mark_lvalue_use (tree expr) | |
233 | { | |
234 | return mark_use (expr, false, true, input_location, false); | |
235 | } | |
236 | ||
237 | /* As above, but don't consider this use a read. */ | |
238 | ||
239 | tree | |
240 | mark_lvalue_use_nonread (tree expr) | |
241 | { | |
242 | return mark_use (expr, false, false, input_location, false); | |
243 | } | |
244 | ||
84dd815f JM |
245 | /* Called when expr appears as a discarded-value expression. */ |
246 | ||
247 | tree | |
248 | mark_discarded_use (tree expr) | |
249 | { | |
250 | /* The lvalue-to-rvalue conversion (7.1) is applied if and only if the | |
251 | expression is a glvalue of volatile-qualified type and it is one of the | |
252 | following: | |
253 | * ( expression ), where expression is one of these expressions, | |
254 | * id-expression (8.1.4), | |
255 | * subscripting (8.2.1), | |
256 | * class member access (8.2.5), | |
257 | * indirection (8.3.1), | |
258 | * pointer-to-member operation (8.5), | |
259 | * conditional expression (8.16) where both the second and the third | |
260 | operands are one of these expressions, or | |
261 | * comma expression (8.19) where the right operand is one of these | |
262 | expressions. */ | |
263 | if (expr == NULL_TREE) | |
264 | return expr; | |
265 | ||
dfd7fdca DM |
266 | STRIP_ANY_LOCATION_WRAPPER (expr); |
267 | ||
84dd815f JM |
268 | switch (TREE_CODE (expr)) |
269 | { | |
270 | case COND_EXPR: | |
271 | TREE_OPERAND (expr, 2) = mark_discarded_use (TREE_OPERAND (expr, 2)); | |
272 | gcc_fallthrough (); | |
273 | case COMPOUND_EXPR: | |
274 | TREE_OPERAND (expr, 1) = mark_discarded_use (TREE_OPERAND (expr, 1)); | |
275 | return expr; | |
276 | ||
277 | case COMPONENT_REF: | |
278 | case ARRAY_REF: | |
279 | case INDIRECT_REF: | |
280 | case MEMBER_REF: | |
281 | break; | |
282 | default: | |
283 | if (DECL_P (expr)) | |
284 | break; | |
285 | else | |
286 | return expr; | |
287 | } | |
288 | ||
289 | /* Like mark_rvalue_use, but don't reject built-ins. */ | |
290 | return mark_use (expr, true, true, input_location, false); | |
291 | } | |
292 | ||
03a904b5 JJ |
293 | /* Called whenever an expression is used in a type use context. */ |
294 | ||
295 | tree | |
296 | mark_type_use (tree expr) | |
297 | { | |
298 | mark_exp_read (expr); | |
299 | return expr; | |
300 | } | |
301 | ||
302 | /* Mark EXP as read, not just set, for set but not used -Wunused | |
303 | warning purposes. */ | |
304 | ||
305 | void | |
306 | mark_exp_read (tree exp) | |
307 | { | |
308 | if (exp == NULL) | |
309 | return; | |
310 | ||
311 | switch (TREE_CODE (exp)) | |
312 | { | |
313 | case VAR_DECL: | |
6fc9f7aa JJ |
314 | if (DECL_DECOMPOSITION_P (exp)) |
315 | mark_exp_read (DECL_DECOMP_BASE (exp)); | |
5726acd7 | 316 | gcc_fallthrough (); |
03a904b5 JJ |
317 | case PARM_DECL: |
318 | DECL_READ_P (exp) = 1; | |
319 | break; | |
320 | case ARRAY_REF: | |
321 | case COMPONENT_REF: | |
322 | case MODIFY_EXPR: | |
323 | case REALPART_EXPR: | |
324 | case IMAGPART_EXPR: | |
325 | CASE_CONVERT: | |
326 | case ADDR_EXPR: | |
d84686d1 | 327 | case INDIRECT_REF: |
759deff3 | 328 | case FLOAT_EXPR: |
76f39440 | 329 | case NON_DEPENDENT_EXPR: |
f17a223d | 330 | case VIEW_CONVERT_EXPR: |
03a904b5 JJ |
331 | mark_exp_read (TREE_OPERAND (exp, 0)); |
332 | break; | |
333 | case COMPOUND_EXPR: | |
334 | mark_exp_read (TREE_OPERAND (exp, 1)); | |
335 | break; | |
336 | case COND_EXPR: | |
337 | if (TREE_OPERAND (exp, 1)) | |
338 | mark_exp_read (TREE_OPERAND (exp, 1)); | |
339 | if (TREE_OPERAND (exp, 2)) | |
340 | mark_exp_read (TREE_OPERAND (exp, 2)); | |
341 | break; | |
342 | default: | |
343 | break; | |
344 | } | |
345 | } | |
346 | ||
bb9869d5 DM |
347 | /* Fold X for consideration by one of the warning functions when checking |
348 | whether an expression has a constant value. */ | |
349 | ||
350 | tree | |
351 | fold_for_warn (tree x) | |
352 | { | |
353 | /* C++ implementation. */ | |
354 | ||
355 | /* It's not generally safe to fully fold inside of a template, so | |
356 | call fold_non_dependent_expr instead. */ | |
357 | if (processing_template_decl) | |
e56f6629 JM |
358 | { |
359 | tree f = fold_non_dependent_expr (x, tf_none); | |
360 | if (f == error_mark_node) | |
361 | return x; | |
362 | else | |
363 | return f; | |
364 | } | |
bb9869d5 DM |
365 | |
366 | return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL); | |
367 | } |