]>
Commit | Line | Data |
---|---|---|
b4c522fa | 1 | /* d-convert.cc -- Data type conversion routines. |
83ffe9cd | 2 | Copyright (C) 2006-2023 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 | { | |
5fee5ec3 IB |
364 | case TY::Tdelegate: |
365 | if (tbtype->ty == TY::Tdelegate) | |
b4c522fa IB |
366 | { |
367 | exp = d_save_expr (exp); | |
368 | return build_delegate_cst (delegate_method (exp), | |
369 | delegate_object (exp), totype); | |
370 | } | |
5fee5ec3 | 371 | else if (tbtype->ty == TY::Tpointer) |
b4c522fa IB |
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 | ||
5fee5ec3 IB |
385 | case TY::Tstruct: |
386 | if (tbtype->ty == TY::Tstruct) | |
b4c522fa IB |
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 | ||
5fee5ec3 IB |
403 | case TY::Tclass: |
404 | if (tbtype->ty == TY::Tclass) | |
b4c522fa IB |
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 | } | |
29ff25e7 | 433 | else if (cdfrom->isCPPclass () || cdto->isCPPclass ()) |
b4c522fa IB |
434 | { |
435 | /* Downcasting in C++ is a no-op. */ | |
29ff25e7 | 436 | if (cdfrom->isCPPclass () && cdto->isCPPclass ()) |
b4c522fa IB |
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 | ||
5fee5ec3 IB |
463 | case TY::Tsarray: |
464 | if (tbtype->ty == TY::Tpointer) | |
b4c522fa IB |
465 | { |
466 | result = build_nop (build_ctype (totype), build_address (exp)); | |
467 | } | |
5fee5ec3 | 468 | else if (tbtype->ty == TY::Tarray) |
b4c522fa | 469 | { |
89fdaf5a | 470 | dinteger_t dim = ebtype->isTypeSArray ()->dim->toInteger (); |
b4c522fa IB |
471 | dinteger_t esize = ebtype->nextOf ()->size (); |
472 | dinteger_t tsize = tbtype->nextOf ()->size (); | |
473 | ||
474 | tree ptrtype = build_ctype (tbtype->nextOf ()->pointerTo ()); | |
475 | ||
c936c39f | 476 | if (esize != tsize) |
b4c522fa | 477 | { |
c936c39f IB |
478 | /* Array element sizes do not match, so we must adjust the |
479 | dimensions. */ | |
480 | if (tsize == 0 || (dim * esize) % tsize != 0) | |
481 | { | |
482 | error ("cannot cast %qs to %qs since sizes do not line up", | |
483 | etype->toChars (), totype->toChars ()); | |
484 | return error_mark_node; | |
485 | } | |
486 | dim = (dim * esize) / tsize; | |
b4c522fa | 487 | } |
b4c522fa IB |
488 | |
489 | /* Assumes casting to dynamic array of same type or void. */ | |
490 | return d_array_value (build_ctype (totype), size_int (dim), | |
491 | build_nop (ptrtype, build_address (exp))); | |
492 | } | |
5fee5ec3 | 493 | else if (tbtype->ty == TY::Tsarray) |
b4c522fa IB |
494 | { |
495 | /* D allows casting a static array to any static array type. */ | |
496 | return build_nop (build_ctype (totype), exp); | |
497 | } | |
5fee5ec3 | 498 | else if (tbtype->ty == TY::Tstruct) |
b4c522fa IB |
499 | { |
500 | /* And allows casting a static array to any struct type too. | |
501 | Type sizes should have already been checked by the frontend. */ | |
502 | gcc_assert (totype->size () == etype->size ()); | |
503 | result = build_vconvert (build_ctype (totype), exp); | |
504 | } | |
329bef49 IB |
505 | else if (tbtype->ty == TY::Tvector && tbtype->size () == ebtype->size ()) |
506 | { | |
507 | /* Allow casting from array to vector as if its an unaligned load. */ | |
508 | tree type = build_ctype (totype); | |
509 | tree unaligned_type = build_variant_type_copy (type); | |
510 | SET_TYPE_ALIGN (unaligned_type, 1 * BITS_PER_UNIT); | |
511 | TYPE_USER_ALIGN (unaligned_type) = 1; | |
512 | result = convert (type, build_vconvert (unaligned_type, exp)); | |
513 | } | |
b4c522fa IB |
514 | else |
515 | { | |
516 | error ("cannot cast expression of type %qs to type %qs", | |
517 | etype->toChars (), totype->toChars ()); | |
518 | return error_mark_node; | |
519 | } | |
520 | break; | |
521 | ||
5fee5ec3 IB |
522 | case TY::Tarray: |
523 | if (tbtype->ty == TY::Tpointer) | |
b4c522fa IB |
524 | { |
525 | return d_convert (build_ctype (totype), d_array_ptr (exp)); | |
526 | } | |
5fee5ec3 | 527 | else if (tbtype->ty == TY::Tarray) |
b4c522fa IB |
528 | { |
529 | /* Assume tvoid->size() == 1. */ | |
fbdaa581 IB |
530 | dinteger_t fsize = ebtype->nextOf ()->toBasetype ()->size (); |
531 | dinteger_t tsize = tbtype->nextOf ()->toBasetype ()->size (); | |
b4c522fa IB |
532 | |
533 | if (fsize != tsize) | |
534 | { | |
5fee5ec3 IB |
535 | /* Conversion requires a reinterpret cast of array. |
536 | This case should have been lowered in the semantic pass. */ | |
537 | if (tsize != 0 && fsize % tsize == 0) | |
538 | { | |
539 | /* Set array dimension to (length * (fsize / tsize)). */ | |
540 | tree newlength = size_mult_expr (d_array_length (exp), | |
541 | size_int (fsize / tsize)); | |
542 | return d_array_value (build_ctype (totype), newlength, | |
543 | d_array_ptr (exp)); | |
544 | } | |
545 | else | |
546 | gcc_unreachable (); | |
b4c522fa IB |
547 | } |
548 | else | |
549 | { | |
550 | /* Convert from void[] or elements are the same size | |
551 | -- don't change length. */ | |
552 | return build_vconvert (build_ctype (totype), exp); | |
553 | } | |
554 | } | |
5fee5ec3 | 555 | else if (tbtype->ty == TY::Tsarray) |
b4c522fa IB |
556 | { |
557 | /* Strings are treated as dynamic arrays in D2. */ | |
558 | if (ebtype->isString () && tbtype->isString ()) | |
559 | return indirect_ref (build_ctype (totype), d_array_ptr (exp)); | |
560 | } | |
561 | else | |
562 | { | |
563 | error ("cannot cast expression of type %qs to %qs", | |
564 | etype->toChars (), totype->toChars ()); | |
565 | return error_mark_node; | |
566 | } | |
567 | break; | |
568 | ||
5fee5ec3 IB |
569 | case TY::Taarray: |
570 | if (tbtype->ty == TY::Taarray) | |
b4c522fa IB |
571 | return build_vconvert (build_ctype (totype), exp); |
572 | /* Can convert associative arrays to void pointers. */ | |
5fee5ec3 | 573 | else if (tbtype->ty == TY::Tpointer && tbtype->nextOf ()->ty == TY::Tvoid) |
b4c522fa IB |
574 | return build_vconvert (build_ctype (totype), exp); |
575 | /* Else, default conversion, which should product an error. */ | |
576 | break; | |
577 | ||
5fee5ec3 | 578 | case TY::Tpointer: |
b4c522fa | 579 | /* Can convert void pointers to associative arrays too. */ |
5fee5ec3 | 580 | if (tbtype->ty == TY::Taarray && ebtype->nextOf ()->ty == TY::Tvoid) |
b4c522fa IB |
581 | return build_vconvert (build_ctype (totype), exp); |
582 | break; | |
583 | ||
5fee5ec3 IB |
584 | case TY::Tnull: |
585 | case TY::Tnoreturn: | |
5a0aa603 IB |
586 | /* Casting from `typeof(null)' for `null' expressions, or `typeof(*null)' |
587 | for `noreturn' expressions is represented as all zeros. */ | |
5e95646e | 588 | result = build_typeof_null_value (totype); |
b4c522fa | 589 | |
5e95646e IB |
590 | /* Make sure the expression is still evaluated if necessary. */ |
591 | if (TREE_SIDE_EFFECTS (exp)) | |
592 | result = compound_expr (exp, result); | |
593 | break; | |
b4c522fa | 594 | |
5fee5ec3 IB |
595 | case TY::Tvector: |
596 | if (tbtype->ty == TY::Tsarray) | |
b4c522fa IB |
597 | { |
598 | if (tbtype->size () == ebtype->size ()) | |
599 | return build_vconvert (build_ctype (totype), exp); | |
600 | } | |
601 | break; | |
602 | ||
603 | default: | |
604 | /* All casts between imaginary and non-imaginary result in 0.0, | |
605 | except for casts between complex and imaginary types. */ | |
606 | if (!ebtype->iscomplex () && !tbtype->iscomplex () | |
607 | && (ebtype->isimaginary () != tbtype->isimaginary ())) | |
608 | { | |
609 | warning (OPT_Wcast_result, | |
610 | "cast from %qs to %qs will produce zero result", | |
611 | ebtype->toChars (), tbtype->toChars ()); | |
612 | ||
613 | return compound_expr (exp, build_zero_cst (build_ctype (tbtype))); | |
614 | } | |
615 | ||
b4c522fa IB |
616 | gcc_assert (TREE_CODE (exp) != STRING_CST); |
617 | break; | |
618 | } | |
619 | ||
620 | return result ? result : convert (build_ctype (totype), exp); | |
621 | } | |
622 | ||
5c9b7408 IB |
623 | /* Return a TREE represenwation of EXPR, whose type has been converted from |
624 | * ETYPE to TOTYPE, and is being used in an rvalue context. */ | |
625 | ||
626 | tree | |
627 | convert_for_rvalue (tree expr, Type *etype, Type *totype) | |
628 | { | |
629 | tree result = NULL_TREE; | |
630 | ||
631 | Type *ebtype = etype->toBasetype (); | |
632 | Type *tbtype = totype->toBasetype (); | |
633 | ||
5fee5ec3 | 634 | if (ebtype->ty == TY::Tbool) |
5c9b7408 | 635 | { |
5c9b7408 IB |
636 | /* If casting from bool, the result is either 0 or 1, any other value |
637 | violates @safe code, so enforce that it is never invalid. */ | |
638 | if (CONSTANT_CLASS_P (expr)) | |
639 | result = d_truthvalue_conversion (expr); | |
640 | else | |
641 | { | |
642 | /* Reinterpret the boolean as an integer and test the first bit. | |
643 | The generated code should end up being equivalent to: | |
644 | *cast(ubyte *)&expr & 1; */ | |
645 | machine_mode bool_mode = TYPE_MODE (TREE_TYPE (expr)); | |
646 | tree mtype = lang_hooks.types.type_for_mode (bool_mode, 1); | |
647 | result = fold_build2 (BIT_AND_EXPR, mtype, | |
648 | build_vconvert (mtype, expr), | |
649 | build_one_cst (mtype)); | |
650 | } | |
651 | ||
652 | result = convert (build_ctype (tbtype), result); | |
5c9b7408 IB |
653 | } |
654 | ||
329bef49 IB |
655 | if (tbtype->ty == TY::Tsarray |
656 | && ebtype->ty == TY::Tsarray | |
657 | && tbtype->nextOf ()->ty == ebtype->nextOf ()->ty | |
658 | && INDIRECT_REF_P (expr) | |
659 | && CONVERT_EXPR_CODE_P (TREE_CODE (TREE_OPERAND (expr, 0))) | |
660 | && TREE_CODE (TREE_OPERAND (TREE_OPERAND (expr, 0), 0)) == ADDR_EXPR) | |
661 | { | |
662 | /* If expression is a vector that was casted to an array either by | |
663 | explicit type cast or by taking the vector's `.array' value, strip the | |
664 | reinterpret cast and build a constructor instead. */ | |
665 | tree ptr = TREE_OPERAND (TREE_OPERAND (expr, 0), 0); | |
666 | ||
667 | if (VECTOR_TYPE_P (TREE_TYPE (TREE_TYPE (ptr)))) | |
668 | { | |
669 | /* Rewrite: `*(Array *)&vector' | |
670 | into: `{ vector[0], vector[1], ... }' */ | |
671 | tree array = d_save_expr (TREE_OPERAND (ptr, 0)); | |
672 | array = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (expr), array); | |
673 | ||
674 | uinteger_t dim = tbtype->isTypeSArray ()->dim->toUInteger (); | |
675 | vec <constructor_elt, va_gc> *elms = NULL; | |
676 | for (uinteger_t i = 0; i < dim; i++) | |
677 | { | |
678 | tree index = size_int (i); | |
679 | tree value = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (array)), | |
680 | array, index, NULL_TREE, NULL_TREE); | |
681 | CONSTRUCTOR_APPEND_ELT (elms, index, value); | |
682 | } | |
683 | ||
684 | return build_constructor (build_ctype (totype), elms); | |
685 | } | |
686 | } | |
687 | ||
5c9b7408 IB |
688 | return result ? result : convert_expr (expr, etype, totype); |
689 | } | |
b4c522fa IB |
690 | |
691 | /* Apply semantics of assignment to a value of type TOTYPE to EXPR | |
692 | (e.g., pointer = array -> pointer = &array[0]) | |
693 | ||
694 | Return a TREE representation of EXPR implicitly converted to TOTYPE | |
695 | for use in assignment expressions MODIFY_EXPR, INIT_EXPR. */ | |
696 | ||
697 | tree | |
698 | convert_for_assignment (tree expr, Type *etype, Type *totype) | |
699 | { | |
700 | Type *ebtype = etype->toBasetype (); | |
701 | Type *tbtype = totype->toBasetype (); | |
702 | ||
703 | /* Assuming this only has to handle converting a non Tsarray type to | |
704 | arbitrarily dimensioned Tsarrays. */ | |
5fee5ec3 | 705 | if (tbtype->ty == TY::Tsarray) |
b4c522fa IB |
706 | { |
707 | Type *telem = tbtype->nextOf ()->baseElemOf (); | |
708 | ||
709 | if (same_type_p (telem, ebtype)) | |
710 | { | |
89fdaf5a | 711 | TypeSArray *sa_type = tbtype->isTypeSArray (); |
b4c522fa IB |
712 | uinteger_t count = sa_type->dim->toUInteger (); |
713 | ||
714 | tree ctor = build_constructor (build_ctype (totype), NULL); | |
715 | if (count) | |
716 | { | |
af3c19f0 | 717 | vec <constructor_elt, va_gc> *ce = NULL; |
b4c522fa IB |
718 | tree index = build2 (RANGE_EXPR, build_ctype (Type::tsize_t), |
719 | size_zero_node, size_int (count - 1)); | |
720 | tree value = convert_for_assignment (expr, etype, sa_type->next); | |
721 | ||
722 | /* Can't use VAR_DECLs in CONSTRUCTORS. */ | |
723 | if (VAR_P (value)) | |
724 | { | |
725 | value = DECL_INITIAL (value); | |
726 | gcc_assert (value); | |
727 | } | |
728 | ||
729 | CONSTRUCTOR_APPEND_ELT (ce, index, value); | |
730 | CONSTRUCTOR_ELTS (ctor) = ce; | |
731 | } | |
732 | TREE_READONLY (ctor) = 1; | |
733 | TREE_CONSTANT (ctor) = 1; | |
734 | return ctor; | |
735 | } | |
736 | } | |
737 | ||
738 | /* D Front end uses IntegerExp(0) to mean zero-init an array or structure. */ | |
5fee5ec3 | 739 | if ((tbtype->ty == TY::Tsarray || tbtype->ty == TY::Tstruct) |
b4c522fa IB |
740 | && ebtype->isintegral ()) |
741 | { | |
742 | if (!integer_zerop (expr)) | |
743 | gcc_unreachable (); | |
744 | ||
745 | return expr; | |
746 | } | |
747 | ||
329bef49 | 748 | return convert_for_rvalue (expr, etype, totype); |
b4c522fa IB |
749 | } |
750 | ||
751 | /* Return a TREE representation of EXPR converted to represent | |
752 | the parameter type ARG. */ | |
753 | ||
754 | tree | |
755 | convert_for_argument (tree expr, Parameter *arg) | |
756 | { | |
757 | /* Lazy arguments: expr should already be a delegate. */ | |
758 | if (arg->storageClass & STClazy) | |
759 | return expr; | |
760 | ||
761 | if (valist_array_p (arg->type)) | |
762 | { | |
763 | /* Do nothing if the va_list has already been decayed to a pointer. */ | |
764 | if (!POINTER_TYPE_P (TREE_TYPE (expr))) | |
765 | return build_address (expr); | |
766 | } | |
2370bdbb | 767 | else if (parameter_reference_p (arg)) |
b4c522fa IB |
768 | { |
769 | /* Front-end shouldn't automatically take the address. */ | |
2370bdbb | 770 | return convert (parameter_type (arg), build_address (expr)); |
b4c522fa IB |
771 | } |
772 | ||
773 | return expr; | |
774 | } | |
775 | ||
776 | /* Perform default promotions for data used in expressions. | |
777 | Arrays and functions are converted to pointers; | |
778 | enumeral types or short or char, to int. | |
779 | In addition, manifest constants symbols are replaced by their values. | |
780 | ||
781 | Return truth-value conversion of expression EXPR from value type TYPE. */ | |
782 | ||
783 | tree | |
784 | convert_for_condition (tree expr, Type *type) | |
785 | { | |
786 | tree result = NULL_TREE; | |
787 | ||
788 | switch (type->toBasetype ()->ty) | |
789 | { | |
5fee5ec3 | 790 | case TY::Taarray: |
b4c522fa IB |
791 | /* Checks that aa.ptr !is null. */ |
792 | result = component_ref (expr, TYPE_FIELDS (TREE_TYPE (expr))); | |
793 | break; | |
794 | ||
5fee5ec3 | 795 | case TY::Tarray: |
b4c522fa IB |
796 | { |
797 | /* Checks (arr.length || arr.ptr) (i.e arr !is null). */ | |
798 | expr = d_save_expr (expr); | |
799 | tree len = d_array_length (expr); | |
800 | tree ptr = d_array_ptr (expr); | |
801 | if (TYPE_MODE (TREE_TYPE (len)) == TYPE_MODE (TREE_TYPE (ptr))) | |
802 | { | |
803 | result = build2 (BIT_IOR_EXPR, TREE_TYPE (len), len, | |
804 | d_convert (TREE_TYPE (len), ptr)); | |
805 | } | |
806 | else | |
807 | { | |
808 | len = d_truthvalue_conversion (len); | |
809 | ptr = d_truthvalue_conversion (ptr); | |
810 | /* Probably not worth using TRUTH_OROR here. */ | |
811 | result = build2 (TRUTH_OR_EXPR, TREE_TYPE (len), len, ptr); | |
812 | } | |
813 | break; | |
814 | } | |
815 | ||
5fee5ec3 | 816 | case TY::Tdelegate: |
b4c522fa IB |
817 | { |
818 | /* Checks (function || object), but what good is it if there is | |
819 | a null function pointer? */ | |
820 | tree obj, func; | |
821 | if (METHOD_CALL_EXPR (expr)) | |
822 | extract_from_method_call (expr, obj, func); | |
823 | else | |
824 | { | |
825 | expr = d_save_expr (expr); | |
826 | obj = delegate_object (expr); | |
827 | func = delegate_method (expr); | |
828 | } | |
829 | ||
830 | obj = d_truthvalue_conversion (obj); | |
831 | func = d_truthvalue_conversion (func); | |
832 | /* Probably not worth using TRUTH_ORIF here. */ | |
833 | result = build2 (BIT_IOR_EXPR, TREE_TYPE (obj), obj, func); | |
834 | break; | |
835 | } | |
836 | ||
5fee5ec3 | 837 | case TY::Tnoreturn: |
5a0aa603 IB |
838 | /* Front-end allows conditionals that never return, represent the |
839 | conditional result value as all zeros. */ | |
840 | result = build_zero_cst (d_bool_type); | |
841 | ||
842 | /* Make sure the expression is still evaluated if necessary. */ | |
843 | if (TREE_SIDE_EFFECTS (expr)) | |
844 | result = compound_expr (expr, result); | |
845 | break; | |
846 | ||
b4c522fa IB |
847 | default: |
848 | result = expr; | |
849 | break; | |
850 | } | |
851 | ||
852 | return d_truthvalue_conversion (result); | |
853 | } | |
854 | ||
855 | ||
856 | /* Convert EXP to a dynamic array. | |
857 | EXP must be a static array or dynamic array. */ | |
858 | ||
859 | tree | |
860 | d_array_convert (Expression *exp) | |
861 | { | |
862 | Type *tb = exp->type->toBasetype (); | |
863 | ||
5fee5ec3 | 864 | if (tb->ty == TY::Tarray) |
b4c522fa IB |
865 | return build_expr (exp); |
866 | ||
5fee5ec3 | 867 | if (tb->ty == TY::Tsarray) |
b4c522fa IB |
868 | { |
869 | Type *totype = tb->nextOf ()->arrayOf (); | |
870 | return convert_expr (build_expr (exp), exp->type, totype); | |
871 | } | |
872 | ||
873 | /* Invalid type passed. */ | |
874 | gcc_unreachable (); | |
875 | } | |
876 | ||
877 | /* Convert EXP to a dynamic array, where ETYPE is the element type. | |
878 | Similar to above, except that EXP is allowed to be an element of an array. | |
0af711e1 | 879 | Temporary variables are created inline if EXP is not an lvalue. */ |
b4c522fa IB |
880 | |
881 | tree | |
0af711e1 | 882 | d_array_convert (Type *etype, Expression *exp) |
b4c522fa IB |
883 | { |
884 | Type *tb = exp->type->toBasetype (); | |
885 | ||
5fee5ec3 IB |
886 | if ((tb->ty != TY::Tarray && tb->ty != TY::Tsarray) |
887 | || same_type_p (tb, etype)) | |
b4c522fa IB |
888 | { |
889 | /* Convert single element to an array. */ | |
0af711e1 | 890 | tree expr = build_expr (exp); |
b4c522fa | 891 | |
0af711e1 IB |
892 | if (!exp->isLvalue ()) |
893 | { | |
894 | tree var = build_local_temp (TREE_TYPE (expr)); | |
895 | expr = compound_expr (modify_expr (var, expr), var); | |
896 | } | |
b4c522fa IB |
897 | |
898 | return d_array_value (build_ctype (exp->type->arrayOf ()), | |
899 | size_int (1), build_address (expr)); | |
900 | } | |
901 | else | |
902 | return d_array_convert (exp); | |
903 | } |