]>
Commit | Line | Data |
---|---|---|
b4c522fa | 1 | /* d-convert.cc -- Data type conversion routines. |
a5544970 | 2 | Copyright (C) 2006-2019 Free Software Foundation, Inc. |
b4c522fa IB |
3 | |
4 | GCC is free software; you can redistribute it and/or modify | |
5 | it under the terms of the GNU General Public License as published by | |
6 | the Free Software Foundation; either version 3, or (at your option) | |
7 | any later version. | |
8 | ||
9 | GCC is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | GNU General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU General Public License | |
15 | along with GCC; see the file COPYING3. If not see | |
16 | <http://www.gnu.org/licenses/>. */ | |
17 | ||
18 | #include "config.h" | |
19 | #include "system.h" | |
20 | #include "coretypes.h" | |
21 | ||
22 | #include "dmd/aggregate.h" | |
23 | #include "dmd/declaration.h" | |
24 | #include "dmd/expression.h" | |
25 | #include "dmd/mtype.h" | |
26 | ||
27 | #include "tree.h" | |
28 | #include "fold-const.h" | |
29 | #include "diagnostic.h" | |
30 | #include "langhooks.h" | |
31 | #include "target.h" | |
32 | #include "convert.h" | |
33 | #include "stor-layout.h" | |
34 | ||
35 | #include "d-tree.h" | |
36 | ||
37 | ||
38 | /* Build CODE expression with operands OP0 and OP1. | |
39 | Helper function for d_truthvalue_conversion, so assumes bool result. */ | |
40 | ||
41 | static tree | |
42 | d_build_truthvalue_op (tree_code code, tree op0, tree op1) | |
43 | { | |
44 | tree type0, type1; | |
45 | ||
46 | tree result_type = NULL_TREE; | |
47 | ||
48 | type0 = TREE_TYPE (op0); | |
49 | type1 = TREE_TYPE (op1); | |
50 | ||
51 | /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */ | |
52 | STRIP_TYPE_NOPS (op0); | |
53 | STRIP_TYPE_NOPS (op1); | |
54 | ||
55 | /* Also need to convert pointer/int comparison. */ | |
56 | if (POINTER_TYPE_P (type0) && TREE_CODE (op1) == INTEGER_CST | |
57 | && integer_zerop (op1)) | |
58 | { | |
59 | result_type = type0; | |
60 | } | |
61 | else if (POINTER_TYPE_P (type1) && TREE_CODE (op0) == INTEGER_CST | |
62 | && integer_zerop (op0)) | |
63 | { | |
64 | result_type = type1; | |
65 | } | |
66 | /* If integral, need to convert unsigned/signed comparison. | |
67 | Will also need to convert if type precisions differ. */ | |
68 | else if (INTEGRAL_TYPE_P (type0) && INTEGRAL_TYPE_P (type1)) | |
69 | { | |
70 | if (TYPE_PRECISION (type0) > TYPE_PRECISION (type1)) | |
71 | result_type = type0; | |
72 | else if (TYPE_PRECISION (type0) < TYPE_PRECISION (type1)) | |
73 | result_type = type1; | |
74 | else if (TYPE_UNSIGNED (type0) != TYPE_UNSIGNED (type1)) | |
75 | result_type = TYPE_UNSIGNED (type0) ? type0 : type1; | |
76 | } | |
77 | ||
78 | if (result_type) | |
79 | { | |
80 | if (TREE_TYPE (op0) != result_type) | |
81 | op0 = convert (result_type, op0); | |
82 | if (TREE_TYPE (op1) != result_type) | |
83 | op1 = convert (result_type, op1); | |
84 | } | |
85 | ||
86 | return fold_build2 (code, d_bool_type, op0, op1); | |
87 | } | |
88 | ||
89 | /* Return whether EXPR is a declaration whose address can never be NULL. */ | |
90 | ||
91 | bool | |
92 | decl_with_nonnull_addr_p (const_tree expr) | |
93 | { | |
94 | return (DECL_P (expr) | |
95 | && (TREE_CODE (expr) == PARM_DECL | |
96 | || TREE_CODE (expr) == LABEL_DECL | |
97 | || !DECL_WEAK (expr))); | |
98 | } | |
99 | ||
100 | /* Convert EXPR to be a truth-value, validating its type for this purpose. */ | |
101 | ||
102 | tree | |
103 | d_truthvalue_conversion (tree expr) | |
104 | { | |
105 | switch (TREE_CODE (expr)) | |
106 | { | |
107 | case EQ_EXPR: case NE_EXPR: case LE_EXPR: | |
108 | case GE_EXPR: case LT_EXPR: case GT_EXPR: | |
109 | if (TREE_TYPE (expr) == d_bool_type) | |
110 | return expr; | |
111 | return build2 (TREE_CODE (expr), d_bool_type, | |
112 | TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1)); | |
113 | ||
114 | case TRUTH_ANDIF_EXPR: | |
115 | case TRUTH_ORIF_EXPR: | |
116 | case TRUTH_AND_EXPR: | |
117 | case TRUTH_OR_EXPR: | |
118 | case TRUTH_XOR_EXPR: | |
119 | if (TREE_TYPE (expr) == d_bool_type) | |
120 | return expr; | |
121 | return build2 (TREE_CODE (expr), d_bool_type, | |
122 | d_truthvalue_conversion (TREE_OPERAND (expr, 0)), | |
123 | d_truthvalue_conversion (TREE_OPERAND (expr, 1))); | |
124 | ||
125 | case TRUTH_NOT_EXPR: | |
126 | if (TREE_TYPE (expr) == d_bool_type) | |
127 | return expr; | |
128 | return build1 (TREE_CODE (expr), d_bool_type, | |
129 | d_truthvalue_conversion (TREE_OPERAND (expr, 0))); | |
130 | ||
131 | case ERROR_MARK: | |
132 | return expr; | |
133 | ||
134 | case INTEGER_CST: | |
135 | return integer_zerop (expr) ? boolean_false_node | |
136 | : boolean_true_node; | |
137 | ||
138 | case REAL_CST: | |
139 | return real_compare (NE_EXPR, &TREE_REAL_CST (expr), &dconst0) | |
140 | ? boolean_true_node | |
141 | : boolean_false_node; | |
142 | ||
143 | case ADDR_EXPR: | |
144 | /* If we are taking the address of a decl that can never be null, | |
145 | then the return result is always true. */ | |
146 | if (decl_with_nonnull_addr_p (TREE_OPERAND (expr, 0))) | |
147 | { | |
148 | warning (OPT_Waddress, | |
149 | "the address of %qD will always evaluate as %<true%>", | |
150 | TREE_OPERAND (expr, 0)); | |
151 | return boolean_true_node; | |
152 | } | |
153 | break; | |
154 | ||
155 | case COMPLEX_EXPR: | |
156 | return d_build_truthvalue_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)) | |
157 | ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR), | |
158 | d_truthvalue_conversion (TREE_OPERAND (expr, 0)), | |
159 | d_truthvalue_conversion (TREE_OPERAND (expr, 1))); | |
160 | ||
161 | case NEGATE_EXPR: | |
162 | case ABS_EXPR: | |
163 | case FLOAT_EXPR: | |
164 | /* These don't change whether an object is nonzero or zero. */ | |
165 | return d_truthvalue_conversion (TREE_OPERAND (expr, 0)); | |
166 | ||
167 | case LROTATE_EXPR: | |
168 | case RROTATE_EXPR: | |
169 | /* These don't change whether an object is zero or nonzero, but | |
170 | we can't ignore them if their second arg has side-effects. */ | |
171 | if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))) | |
172 | { | |
173 | return build2 (COMPOUND_EXPR, d_bool_type, TREE_OPERAND (expr, 1), | |
174 | d_truthvalue_conversion (TREE_OPERAND (expr, 0))); | |
175 | } | |
176 | else | |
177 | return d_truthvalue_conversion (TREE_OPERAND (expr, 0)); | |
178 | ||
179 | case COND_EXPR: | |
180 | /* Distribute the conversion into the arms of a COND_EXPR. */ | |
181 | return fold_build3 (COND_EXPR, d_bool_type, TREE_OPERAND (expr, 0), | |
182 | d_truthvalue_conversion (TREE_OPERAND (expr, 1)), | |
183 | d_truthvalue_conversion (TREE_OPERAND (expr, 2))); | |
184 | ||
185 | case CONVERT_EXPR: | |
186 | /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE, | |
187 | since that affects how `default_conversion' will behave. */ | |
188 | if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE | |
189 | || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE) | |
190 | break; | |
191 | /* Fall through. */ | |
192 | ||
193 | case NOP_EXPR: | |
194 | /* If this isn't narrowing the argument, we can ignore it. */ | |
195 | if (TYPE_PRECISION (TREE_TYPE (expr)) | |
196 | >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0)))) | |
197 | return d_truthvalue_conversion (TREE_OPERAND (expr, 0)); | |
198 | break; | |
199 | ||
200 | default: | |
201 | break; | |
202 | } | |
203 | ||
204 | if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE) | |
205 | { | |
206 | tree t = save_expr (expr); | |
207 | return d_build_truthvalue_op ((TREE_SIDE_EFFECTS (expr) | |
208 | ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR), | |
209 | d_truthvalue_conversion (real_part (t)), | |
210 | d_truthvalue_conversion (imaginary_part (t))); | |
211 | } | |
212 | else | |
213 | return d_build_truthvalue_op (NE_EXPR, expr, | |
214 | build_zero_cst (TREE_TYPE (expr))); | |
215 | } | |
216 | ||
217 | ||
218 | /* Creates an expression whose value is that of EXPR, converted to type TYPE. | |
219 | This function implements all reasonable scalar conversions. */ | |
220 | ||
221 | tree | |
222 | convert (tree type, tree expr) | |
223 | { | |
224 | tree e = expr; | |
225 | tree_code code = TREE_CODE (type); | |
226 | ||
227 | if (type == error_mark_node | |
228 | || expr == error_mark_node | |
229 | || TREE_TYPE (expr) == error_mark_node) | |
230 | return error_mark_node; | |
231 | ||
232 | const char *invalid_conv_diag | |
233 | = targetm.invalid_conversion (TREE_TYPE (expr), type); | |
234 | ||
235 | if (invalid_conv_diag) | |
236 | { | |
237 | error ("%s", invalid_conv_diag); | |
238 | return error_mark_node; | |
239 | } | |
240 | ||
241 | if (type == TREE_TYPE (expr)) | |
242 | return expr; | |
243 | ||
244 | if (TREE_CODE (type) == ARRAY_TYPE | |
245 | && TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE | |
246 | && TYPE_DOMAIN (type) == TYPE_DOMAIN (TREE_TYPE (expr))) | |
247 | return expr; | |
248 | ||
249 | tree ret = targetm.convert_to_type (type, expr); | |
250 | if (ret) | |
251 | return ret; | |
252 | ||
253 | STRIP_TYPE_NOPS (e); | |
254 | tree etype = TREE_TYPE (e); | |
255 | ||
256 | if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))) | |
257 | return fold_convert (type, expr); | |
258 | if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) | |
259 | return error_mark_node; | |
260 | if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE) | |
261 | { | |
262 | error ("void value not ignored as it ought to be"); | |
263 | return error_mark_node; | |
264 | } | |
265 | ||
266 | switch (code) | |
267 | { | |
268 | case VOID_TYPE: | |
269 | return fold_convert (type, e); | |
270 | ||
271 | case INTEGER_TYPE: | |
272 | case ENUMERAL_TYPE: | |
273 | if (TREE_CODE (etype) == POINTER_TYPE | |
274 | || TREE_CODE (etype) == REFERENCE_TYPE) | |
275 | { | |
276 | if (integer_zerop (e)) | |
277 | return build_int_cst (type, 0); | |
278 | ||
279 | /* Convert to an unsigned integer of the correct width first, and | |
280 | from there widen/truncate to the required type. */ | |
281 | tree utype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype), | |
282 | 1); | |
283 | ret = fold_build1 (CONVERT_EXPR, utype, e); | |
284 | return fold_convert (type, ret); | |
285 | } | |
286 | ||
287 | return fold (convert_to_integer (type, e)); | |
288 | ||
289 | case BOOLEAN_TYPE: | |
290 | return fold_convert (type, d_truthvalue_conversion (expr)); | |
291 | ||
292 | case POINTER_TYPE: | |
293 | case REFERENCE_TYPE: | |
294 | return fold (convert_to_pointer (type, e)); | |
295 | ||
296 | case REAL_TYPE: | |
297 | if (TREE_CODE (etype) == COMPLEX_TYPE && TYPE_IMAGINARY_FLOAT (type)) | |
298 | e = build1 (IMAGPART_EXPR, TREE_TYPE (etype), e); | |
299 | ||
300 | return fold (convert_to_real (type, e)); | |
301 | ||
302 | case COMPLEX_TYPE: | |
303 | if (TREE_CODE (etype) == REAL_TYPE && TYPE_IMAGINARY_FLOAT (etype)) | |
304 | return fold_build2 (COMPLEX_EXPR, type, | |
305 | build_zero_cst (TREE_TYPE (type)), | |
306 | convert (TREE_TYPE (type), expr)); | |
307 | ||
308 | return fold (convert_to_complex (type, e)); | |
309 | ||
310 | case VECTOR_TYPE: | |
311 | return fold (convert_to_vector (type, e)); | |
312 | ||
313 | case RECORD_TYPE: | |
314 | case UNION_TYPE: | |
315 | if (lang_hooks.types_compatible_p (type, TREE_TYPE (expr))) | |
316 | return fold_build1 (VIEW_CONVERT_EXPR, type, expr); | |
317 | break; | |
318 | ||
319 | default: | |
320 | break; | |
321 | } | |
322 | ||
323 | error ("conversion to non-scalar type requested"); | |
324 | return error_mark_node; | |
325 | } | |
326 | ||
327 | /* Return expression EXP, whose type has been converted to TYPE. */ | |
328 | ||
329 | tree | |
330 | d_convert (tree type, tree exp) | |
331 | { | |
332 | /* Check this first before retrieving frontend type. */ | |
333 | if (error_operand_p (type) || error_operand_p (exp)) | |
334 | return error_mark_node; | |
335 | ||
336 | Type *totype = TYPE_LANG_FRONTEND (type); | |
337 | Type *etype = TYPE_LANG_FRONTEND (TREE_TYPE (exp)); | |
338 | ||
339 | if (totype && etype) | |
340 | return convert_expr (exp, etype, totype); | |
341 | ||
342 | return convert (type, exp); | |
343 | } | |
344 | ||
345 | /* Return expression EXP, whose type has been convert from ETYPE to TOTYPE. */ | |
346 | ||
347 | tree | |
348 | convert_expr (tree exp, Type *etype, Type *totype) | |
349 | { | |
350 | tree result = NULL_TREE; | |
351 | ||
352 | gcc_assert (etype && totype); | |
353 | Type *ebtype = etype->toBasetype (); | |
354 | Type *tbtype = totype->toBasetype (); | |
355 | ||
356 | if (same_type_p (etype, totype)) | |
357 | return exp; | |
358 | ||
359 | if (error_operand_p (exp)) | |
360 | return exp; | |
361 | ||
362 | switch (ebtype->ty) | |
363 | { | |
364 | case Tdelegate: | |
365 | if (tbtype->ty == Tdelegate) | |
366 | { | |
367 | exp = d_save_expr (exp); | |
368 | return build_delegate_cst (delegate_method (exp), | |
369 | delegate_object (exp), totype); | |
370 | } | |
371 | else if (tbtype->ty == Tpointer) | |
372 | { | |
373 | /* The front-end converts <delegate>.ptr to cast (void *)<delegate>. | |
374 | Maybe should only allow void* ? */ | |
375 | exp = delegate_object (exp); | |
376 | } | |
377 | else | |
378 | { | |
a9c697b8 | 379 | error ("cannot convert a delegate expression to %qs", |
b4c522fa IB |
380 | totype->toChars ()); |
381 | return error_mark_node; | |
382 | } | |
383 | break; | |
384 | ||
385 | case Tstruct: | |
386 | if (tbtype->ty == Tstruct) | |
387 | { | |
388 | if (totype->size () == etype->size ()) | |
389 | { | |
390 | /* Allowed to cast to structs with same type size. */ | |
391 | result = build_vconvert (build_ctype (totype), exp); | |
392 | } | |
393 | else | |
394 | { | |
a9c697b8 | 395 | error ("cannot convert struct %qs to %qs", |
b4c522fa IB |
396 | etype->toChars (), totype->toChars ()); |
397 | return error_mark_node; | |
398 | } | |
399 | } | |
400 | /* else, default conversion, which should produce an error. */ | |
401 | break; | |
402 | ||
403 | case Tclass: | |
404 | if (tbtype->ty == Tclass) | |
405 | { | |
406 | ClassDeclaration *cdfrom = ebtype->isClassHandle (); | |
407 | ClassDeclaration *cdto = tbtype->isClassHandle (); | |
408 | int offset; | |
409 | ||
410 | if (cdto->isBaseOf (cdfrom, &offset) && offset != OFFSET_RUNTIME) | |
411 | { | |
412 | /* Casting up the inheritance tree: Don't do anything special. | |
413 | Cast to an implemented interface: Handle at compile-time. */ | |
414 | if (offset) | |
415 | { | |
416 | /* Forward references should not leak from the frontend. */ | |
417 | gcc_assert (offset != OFFSET_FWDREF); | |
418 | ||
419 | tree type = build_ctype (totype); | |
420 | exp = d_save_expr (exp); | |
421 | ||
422 | tree cond = build_boolop (NE_EXPR, exp, null_pointer_node); | |
423 | tree object = build_offset (exp, size_int (offset)); | |
424 | ||
425 | return build_condition (build_ctype (totype), cond, | |
426 | build_nop (type, object), | |
427 | build_nop (type, null_pointer_node)); | |
428 | } | |
429 | ||
430 | /* d_convert will make a no-op cast. */ | |
431 | break; | |
432 | } | |
433 | else if (cdfrom->isCPPclass ()) | |
434 | { | |
435 | /* Downcasting in C++ is a no-op. */ | |
436 | if (cdto->isCPPclass ()) | |
437 | break; | |
438 | ||
439 | /* Casting from a C++ interface to a class/non-C++ interface | |
440 | always results in null as there is no run-time information, | |
441 | and no way one can derive from the other. */ | |
442 | warning (OPT_Wcast_result, "cast to %qs will produce null result", | |
443 | totype->toChars ()); | |
444 | result = d_convert (build_ctype (totype), null_pointer_node); | |
445 | ||
446 | /* Make sure the expression is still evaluated if necessary. */ | |
447 | if (TREE_SIDE_EFFECTS (exp)) | |
448 | result = compound_expr (exp, result); | |
449 | ||
450 | break; | |
451 | } | |
452 | ||
453 | /* The offset can only be determined at run-time, do dynamic cast. */ | |
454 | libcall_fn libcall = cdfrom->isInterfaceDeclaration () | |
455 | ? LIBCALL_INTERFACE_CAST : LIBCALL_DYNAMIC_CAST; | |
456 | ||
457 | return build_libcall (libcall, totype, 2, exp, | |
458 | build_address (get_classinfo_decl (cdto))); | |
459 | } | |
460 | /* else default conversion. */ | |
461 | break; | |
462 | ||
463 | case Tsarray: | |
464 | if (tbtype->ty == Tpointer) | |
465 | { | |
466 | result = build_nop (build_ctype (totype), build_address (exp)); | |
467 | } | |
468 | else if (tbtype->ty == Tarray) | |
469 | { | |
470 | dinteger_t dim = ((TypeSArray *) ebtype)->dim->toInteger (); | |
471 | dinteger_t esize = ebtype->nextOf ()->size (); | |
472 | dinteger_t tsize = tbtype->nextOf ()->size (); | |
473 | ||
474 | tree ptrtype = build_ctype (tbtype->nextOf ()->pointerTo ()); | |
475 | ||
476 | if ((dim * esize) % tsize != 0) | |
477 | { | |
a9c697b8 | 478 | error ("cannot cast %qs to %qs since sizes do not line up", |
b4c522fa IB |
479 | etype->toChars (), totype->toChars ()); |
480 | return error_mark_node; | |
481 | } | |
482 | dim = (dim * esize) / tsize; | |
483 | ||
484 | /* Assumes casting to dynamic array of same type or void. */ | |
485 | return d_array_value (build_ctype (totype), size_int (dim), | |
486 | build_nop (ptrtype, build_address (exp))); | |
487 | } | |
488 | else if (tbtype->ty == Tsarray) | |
489 | { | |
490 | /* D allows casting a static array to any static array type. */ | |
491 | return build_nop (build_ctype (totype), exp); | |
492 | } | |
493 | else if (tbtype->ty == Tstruct) | |
494 | { | |
495 | /* And allows casting a static array to any struct type too. | |
496 | Type sizes should have already been checked by the frontend. */ | |
497 | gcc_assert (totype->size () == etype->size ()); | |
498 | result = build_vconvert (build_ctype (totype), exp); | |
499 | } | |
500 | else | |
501 | { | |
502 | error ("cannot cast expression of type %qs to type %qs", | |
503 | etype->toChars (), totype->toChars ()); | |
504 | return error_mark_node; | |
505 | } | |
506 | break; | |
507 | ||
508 | case Tarray: | |
509 | if (tbtype->ty == Tpointer) | |
510 | { | |
511 | return d_convert (build_ctype (totype), d_array_ptr (exp)); | |
512 | } | |
513 | else if (tbtype->ty == Tarray) | |
514 | { | |
515 | /* Assume tvoid->size() == 1. */ | |
516 | d_uns64 fsize = ebtype->nextOf ()->toBasetype ()->size (); | |
517 | d_uns64 tsize = tbtype->nextOf ()->toBasetype ()->size (); | |
518 | ||
519 | if (fsize != tsize) | |
520 | { | |
521 | /* Conversion requires a reinterpret cast of array. */ | |
522 | return build_libcall (LIBCALL_ARRAYCAST, totype, 3, | |
523 | size_int (tsize), size_int (fsize), exp); | |
524 | } | |
525 | else | |
526 | { | |
527 | /* Convert from void[] or elements are the same size | |
528 | -- don't change length. */ | |
529 | return build_vconvert (build_ctype (totype), exp); | |
530 | } | |
531 | } | |
532 | else if (tbtype->ty == Tsarray) | |
533 | { | |
534 | /* Strings are treated as dynamic arrays in D2. */ | |
535 | if (ebtype->isString () && tbtype->isString ()) | |
536 | return indirect_ref (build_ctype (totype), d_array_ptr (exp)); | |
537 | } | |
538 | else | |
539 | { | |
540 | error ("cannot cast expression of type %qs to %qs", | |
541 | etype->toChars (), totype->toChars ()); | |
542 | return error_mark_node; | |
543 | } | |
544 | break; | |
545 | ||
546 | case Taarray: | |
547 | if (tbtype->ty == Taarray) | |
548 | return build_vconvert (build_ctype (totype), exp); | |
549 | /* Can convert associative arrays to void pointers. */ | |
550 | else if (tbtype->ty == Tpointer && tbtype->nextOf ()->ty == Tvoid) | |
551 | return build_vconvert (build_ctype (totype), exp); | |
552 | /* Else, default conversion, which should product an error. */ | |
553 | break; | |
554 | ||
555 | case Tpointer: | |
556 | /* Can convert void pointers to associative arrays too. */ | |
557 | if (tbtype->ty == Taarray && ebtype->nextOf ()->ty == Tvoid) | |
558 | return build_vconvert (build_ctype (totype), exp); | |
559 | break; | |
560 | ||
561 | case Tnull: | |
562 | /* Casting from typeof(null) is represented as all zeros. */ | |
5e95646e | 563 | result = build_typeof_null_value (totype); |
b4c522fa | 564 | |
5e95646e IB |
565 | /* Make sure the expression is still evaluated if necessary. */ |
566 | if (TREE_SIDE_EFFECTS (exp)) | |
567 | result = compound_expr (exp, result); | |
568 | break; | |
b4c522fa IB |
569 | |
570 | case Tvector: | |
571 | if (tbtype->ty == Tsarray) | |
572 | { | |
573 | if (tbtype->size () == ebtype->size ()) | |
574 | return build_vconvert (build_ctype (totype), exp); | |
575 | } | |
576 | break; | |
577 | ||
578 | default: | |
579 | /* All casts between imaginary and non-imaginary result in 0.0, | |
580 | except for casts between complex and imaginary types. */ | |
581 | if (!ebtype->iscomplex () && !tbtype->iscomplex () | |
582 | && (ebtype->isimaginary () != tbtype->isimaginary ())) | |
583 | { | |
584 | warning (OPT_Wcast_result, | |
585 | "cast from %qs to %qs will produce zero result", | |
586 | ebtype->toChars (), tbtype->toChars ()); | |
587 | ||
588 | return compound_expr (exp, build_zero_cst (build_ctype (tbtype))); | |
589 | } | |
590 | ||
591 | exp = fold_convert (build_ctype (etype), exp); | |
592 | gcc_assert (TREE_CODE (exp) != STRING_CST); | |
593 | break; | |
594 | } | |
595 | ||
596 | return result ? result : convert (build_ctype (totype), exp); | |
597 | } | |
598 | ||
599 | ||
600 | /* Apply semantics of assignment to a value of type TOTYPE to EXPR | |
601 | (e.g., pointer = array -> pointer = &array[0]) | |
602 | ||
603 | Return a TREE representation of EXPR implicitly converted to TOTYPE | |
604 | for use in assignment expressions MODIFY_EXPR, INIT_EXPR. */ | |
605 | ||
606 | tree | |
607 | convert_for_assignment (tree expr, Type *etype, Type *totype) | |
608 | { | |
609 | Type *ebtype = etype->toBasetype (); | |
610 | Type *tbtype = totype->toBasetype (); | |
611 | ||
612 | /* Assuming this only has to handle converting a non Tsarray type to | |
613 | arbitrarily dimensioned Tsarrays. */ | |
614 | if (tbtype->ty == Tsarray) | |
615 | { | |
616 | Type *telem = tbtype->nextOf ()->baseElemOf (); | |
617 | ||
618 | if (same_type_p (telem, ebtype)) | |
619 | { | |
620 | TypeSArray *sa_type = (TypeSArray *) tbtype; | |
621 | uinteger_t count = sa_type->dim->toUInteger (); | |
622 | ||
623 | tree ctor = build_constructor (build_ctype (totype), NULL); | |
624 | if (count) | |
625 | { | |
626 | vec<constructor_elt, va_gc> *ce = NULL; | |
627 | tree index = build2 (RANGE_EXPR, build_ctype (Type::tsize_t), | |
628 | size_zero_node, size_int (count - 1)); | |
629 | tree value = convert_for_assignment (expr, etype, sa_type->next); | |
630 | ||
631 | /* Can't use VAR_DECLs in CONSTRUCTORS. */ | |
632 | if (VAR_P (value)) | |
633 | { | |
634 | value = DECL_INITIAL (value); | |
635 | gcc_assert (value); | |
636 | } | |
637 | ||
638 | CONSTRUCTOR_APPEND_ELT (ce, index, value); | |
639 | CONSTRUCTOR_ELTS (ctor) = ce; | |
640 | } | |
641 | TREE_READONLY (ctor) = 1; | |
642 | TREE_CONSTANT (ctor) = 1; | |
643 | return ctor; | |
644 | } | |
645 | } | |
646 | ||
647 | /* D Front end uses IntegerExp(0) to mean zero-init an array or structure. */ | |
648 | if ((tbtype->ty == Tsarray || tbtype->ty == Tstruct) | |
649 | && ebtype->isintegral ()) | |
650 | { | |
651 | if (!integer_zerop (expr)) | |
652 | gcc_unreachable (); | |
653 | ||
654 | return expr; | |
655 | } | |
656 | ||
657 | return convert_expr (expr, etype, totype); | |
658 | } | |
659 | ||
660 | /* Return a TREE representation of EXPR converted to represent | |
661 | the parameter type ARG. */ | |
662 | ||
663 | tree | |
664 | convert_for_argument (tree expr, Parameter *arg) | |
665 | { | |
666 | /* Lazy arguments: expr should already be a delegate. */ | |
667 | if (arg->storageClass & STClazy) | |
668 | return expr; | |
669 | ||
670 | if (valist_array_p (arg->type)) | |
671 | { | |
672 | /* Do nothing if the va_list has already been decayed to a pointer. */ | |
673 | if (!POINTER_TYPE_P (TREE_TYPE (expr))) | |
674 | return build_address (expr); | |
675 | } | |
676 | else if (argument_reference_p (arg)) | |
677 | { | |
678 | /* Front-end shouldn't automatically take the address. */ | |
679 | return convert (type_passed_as (arg), build_address (expr)); | |
680 | } | |
681 | ||
682 | return expr; | |
683 | } | |
684 | ||
685 | /* Perform default promotions for data used in expressions. | |
686 | Arrays and functions are converted to pointers; | |
687 | enumeral types or short or char, to int. | |
688 | In addition, manifest constants symbols are replaced by their values. | |
689 | ||
690 | Return truth-value conversion of expression EXPR from value type TYPE. */ | |
691 | ||
692 | tree | |
693 | convert_for_condition (tree expr, Type *type) | |
694 | { | |
695 | tree result = NULL_TREE; | |
696 | ||
697 | switch (type->toBasetype ()->ty) | |
698 | { | |
699 | case Taarray: | |
700 | /* Checks that aa.ptr !is null. */ | |
701 | result = component_ref (expr, TYPE_FIELDS (TREE_TYPE (expr))); | |
702 | break; | |
703 | ||
704 | case Tarray: | |
705 | { | |
706 | /* Checks (arr.length || arr.ptr) (i.e arr !is null). */ | |
707 | expr = d_save_expr (expr); | |
708 | tree len = d_array_length (expr); | |
709 | tree ptr = d_array_ptr (expr); | |
710 | if (TYPE_MODE (TREE_TYPE (len)) == TYPE_MODE (TREE_TYPE (ptr))) | |
711 | { | |
712 | result = build2 (BIT_IOR_EXPR, TREE_TYPE (len), len, | |
713 | d_convert (TREE_TYPE (len), ptr)); | |
714 | } | |
715 | else | |
716 | { | |
717 | len = d_truthvalue_conversion (len); | |
718 | ptr = d_truthvalue_conversion (ptr); | |
719 | /* Probably not worth using TRUTH_OROR here. */ | |
720 | result = build2 (TRUTH_OR_EXPR, TREE_TYPE (len), len, ptr); | |
721 | } | |
722 | break; | |
723 | } | |
724 | ||
725 | case Tdelegate: | |
726 | { | |
727 | /* Checks (function || object), but what good is it if there is | |
728 | a null function pointer? */ | |
729 | tree obj, func; | |
730 | if (METHOD_CALL_EXPR (expr)) | |
731 | extract_from_method_call (expr, obj, func); | |
732 | else | |
733 | { | |
734 | expr = d_save_expr (expr); | |
735 | obj = delegate_object (expr); | |
736 | func = delegate_method (expr); | |
737 | } | |
738 | ||
739 | obj = d_truthvalue_conversion (obj); | |
740 | func = d_truthvalue_conversion (func); | |
741 | /* Probably not worth using TRUTH_ORIF here. */ | |
742 | result = build2 (BIT_IOR_EXPR, TREE_TYPE (obj), obj, func); | |
743 | break; | |
744 | } | |
745 | ||
746 | default: | |
747 | result = expr; | |
748 | break; | |
749 | } | |
750 | ||
751 | return d_truthvalue_conversion (result); | |
752 | } | |
753 | ||
754 | ||
755 | /* Convert EXP to a dynamic array. | |
756 | EXP must be a static array or dynamic array. */ | |
757 | ||
758 | tree | |
759 | d_array_convert (Expression *exp) | |
760 | { | |
761 | Type *tb = exp->type->toBasetype (); | |
762 | ||
763 | if (tb->ty == Tarray) | |
764 | return build_expr (exp); | |
765 | ||
766 | if (tb->ty == Tsarray) | |
767 | { | |
768 | Type *totype = tb->nextOf ()->arrayOf (); | |
769 | return convert_expr (build_expr (exp), exp->type, totype); | |
770 | } | |
771 | ||
772 | /* Invalid type passed. */ | |
773 | gcc_unreachable (); | |
774 | } | |
775 | ||
776 | /* Convert EXP to a dynamic array, where ETYPE is the element type. | |
777 | Similar to above, except that EXP is allowed to be an element of an array. | |
778 | Temporary variables that need some kind of BIND_EXPR are pushed to VARS. */ | |
779 | ||
780 | tree | |
781 | d_array_convert (Type *etype, Expression *exp, vec<tree, va_gc> **vars) | |
782 | { | |
783 | Type *tb = exp->type->toBasetype (); | |
784 | ||
785 | if ((tb->ty != Tarray && tb->ty != Tsarray) || same_type_p (tb, etype)) | |
786 | { | |
787 | /* Convert single element to an array. */ | |
788 | tree var = NULL_TREE; | |
789 | tree expr = maybe_temporary_var (build_expr (exp), &var); | |
790 | ||
791 | if (var != NULL_TREE) | |
792 | vec_safe_push (*vars, var); | |
793 | ||
794 | return d_array_value (build_ctype (exp->type->arrayOf ()), | |
795 | size_int (1), build_address (expr)); | |
796 | } | |
797 | else | |
798 | return d_array_convert (exp); | |
799 | } |