Mercurial > hg > CbC > CbC_gcc
comparison gcc/d/d-convert.cc @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* d-convert.cc -- Data type conversion routines. | |
2 Copyright (C) 2006-2020 Free Software Foundation, Inc. | |
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 { | |
379 error ("cannot convert a delegate expression to %qs", | |
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 { | |
395 error ("cannot convert struct %qs to %qs", | |
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 { | |
478 error ("cannot cast %qs to %qs since sizes do not line up", | |
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. */ | |
563 result = build_typeof_null_value (totype); | |
564 | |
565 /* Make sure the expression is still evaluated if necessary. */ | |
566 if (TREE_SIDE_EFFECTS (exp)) | |
567 result = compound_expr (exp, result); | |
568 break; | |
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 gcc_assert (TREE_CODE (exp) != STRING_CST); | |
592 break; | |
593 } | |
594 | |
595 return result ? result : convert (build_ctype (totype), exp); | |
596 } | |
597 | |
598 | |
599 /* Apply semantics of assignment to a value of type TOTYPE to EXPR | |
600 (e.g., pointer = array -> pointer = &array[0]) | |
601 | |
602 Return a TREE representation of EXPR implicitly converted to TOTYPE | |
603 for use in assignment expressions MODIFY_EXPR, INIT_EXPR. */ | |
604 | |
605 tree | |
606 convert_for_assignment (tree expr, Type *etype, Type *totype) | |
607 { | |
608 Type *ebtype = etype->toBasetype (); | |
609 Type *tbtype = totype->toBasetype (); | |
610 | |
611 /* Assuming this only has to handle converting a non Tsarray type to | |
612 arbitrarily dimensioned Tsarrays. */ | |
613 if (tbtype->ty == Tsarray) | |
614 { | |
615 Type *telem = tbtype->nextOf ()->baseElemOf (); | |
616 | |
617 if (same_type_p (telem, ebtype)) | |
618 { | |
619 TypeSArray *sa_type = (TypeSArray *) tbtype; | |
620 uinteger_t count = sa_type->dim->toUInteger (); | |
621 | |
622 tree ctor = build_constructor (build_ctype (totype), NULL); | |
623 if (count) | |
624 { | |
625 vec<constructor_elt, va_gc> *ce = NULL; | |
626 tree index = build2 (RANGE_EXPR, build_ctype (Type::tsize_t), | |
627 size_zero_node, size_int (count - 1)); | |
628 tree value = convert_for_assignment (expr, etype, sa_type->next); | |
629 | |
630 /* Can't use VAR_DECLs in CONSTRUCTORS. */ | |
631 if (VAR_P (value)) | |
632 { | |
633 value = DECL_INITIAL (value); | |
634 gcc_assert (value); | |
635 } | |
636 | |
637 CONSTRUCTOR_APPEND_ELT (ce, index, value); | |
638 CONSTRUCTOR_ELTS (ctor) = ce; | |
639 } | |
640 TREE_READONLY (ctor) = 1; | |
641 TREE_CONSTANT (ctor) = 1; | |
642 return ctor; | |
643 } | |
644 } | |
645 | |
646 /* D Front end uses IntegerExp(0) to mean zero-init an array or structure. */ | |
647 if ((tbtype->ty == Tsarray || tbtype->ty == Tstruct) | |
648 && ebtype->isintegral ()) | |
649 { | |
650 if (!integer_zerop (expr)) | |
651 gcc_unreachable (); | |
652 | |
653 return expr; | |
654 } | |
655 | |
656 return convert_expr (expr, etype, totype); | |
657 } | |
658 | |
659 /* Return a TREE representation of EXPR converted to represent | |
660 the parameter type ARG. */ | |
661 | |
662 tree | |
663 convert_for_argument (tree expr, Parameter *arg) | |
664 { | |
665 /* Lazy arguments: expr should already be a delegate. */ | |
666 if (arg->storageClass & STClazy) | |
667 return expr; | |
668 | |
669 if (valist_array_p (arg->type)) | |
670 { | |
671 /* Do nothing if the va_list has already been decayed to a pointer. */ | |
672 if (!POINTER_TYPE_P (TREE_TYPE (expr))) | |
673 return build_address (expr); | |
674 } | |
675 else if (argument_reference_p (arg)) | |
676 { | |
677 /* Front-end shouldn't automatically take the address. */ | |
678 return convert (type_passed_as (arg), build_address (expr)); | |
679 } | |
680 | |
681 return expr; | |
682 } | |
683 | |
684 /* Perform default promotions for data used in expressions. | |
685 Arrays and functions are converted to pointers; | |
686 enumeral types or short or char, to int. | |
687 In addition, manifest constants symbols are replaced by their values. | |
688 | |
689 Return truth-value conversion of expression EXPR from value type TYPE. */ | |
690 | |
691 tree | |
692 convert_for_condition (tree expr, Type *type) | |
693 { | |
694 tree result = NULL_TREE; | |
695 | |
696 switch (type->toBasetype ()->ty) | |
697 { | |
698 case Taarray: | |
699 /* Checks that aa.ptr !is null. */ | |
700 result = component_ref (expr, TYPE_FIELDS (TREE_TYPE (expr))); | |
701 break; | |
702 | |
703 case Tarray: | |
704 { | |
705 /* Checks (arr.length || arr.ptr) (i.e arr !is null). */ | |
706 expr = d_save_expr (expr); | |
707 tree len = d_array_length (expr); | |
708 tree ptr = d_array_ptr (expr); | |
709 if (TYPE_MODE (TREE_TYPE (len)) == TYPE_MODE (TREE_TYPE (ptr))) | |
710 { | |
711 result = build2 (BIT_IOR_EXPR, TREE_TYPE (len), len, | |
712 d_convert (TREE_TYPE (len), ptr)); | |
713 } | |
714 else | |
715 { | |
716 len = d_truthvalue_conversion (len); | |
717 ptr = d_truthvalue_conversion (ptr); | |
718 /* Probably not worth using TRUTH_OROR here. */ | |
719 result = build2 (TRUTH_OR_EXPR, TREE_TYPE (len), len, ptr); | |
720 } | |
721 break; | |
722 } | |
723 | |
724 case Tdelegate: | |
725 { | |
726 /* Checks (function || object), but what good is it if there is | |
727 a null function pointer? */ | |
728 tree obj, func; | |
729 if (METHOD_CALL_EXPR (expr)) | |
730 extract_from_method_call (expr, obj, func); | |
731 else | |
732 { | |
733 expr = d_save_expr (expr); | |
734 obj = delegate_object (expr); | |
735 func = delegate_method (expr); | |
736 } | |
737 | |
738 obj = d_truthvalue_conversion (obj); | |
739 func = d_truthvalue_conversion (func); | |
740 /* Probably not worth using TRUTH_ORIF here. */ | |
741 result = build2 (BIT_IOR_EXPR, TREE_TYPE (obj), obj, func); | |
742 break; | |
743 } | |
744 | |
745 default: | |
746 result = expr; | |
747 break; | |
748 } | |
749 | |
750 return d_truthvalue_conversion (result); | |
751 } | |
752 | |
753 | |
754 /* Convert EXP to a dynamic array. | |
755 EXP must be a static array or dynamic array. */ | |
756 | |
757 tree | |
758 d_array_convert (Expression *exp) | |
759 { | |
760 Type *tb = exp->type->toBasetype (); | |
761 | |
762 if (tb->ty == Tarray) | |
763 return build_expr (exp); | |
764 | |
765 if (tb->ty == Tsarray) | |
766 { | |
767 Type *totype = tb->nextOf ()->arrayOf (); | |
768 return convert_expr (build_expr (exp), exp->type, totype); | |
769 } | |
770 | |
771 /* Invalid type passed. */ | |
772 gcc_unreachable (); | |
773 } | |
774 | |
775 /* Convert EXP to a dynamic array, where ETYPE is the element type. | |
776 Similar to above, except that EXP is allowed to be an element of an array. | |
777 Temporary variables that need some kind of BIND_EXPR are pushed to VARS. */ | |
778 | |
779 tree | |
780 d_array_convert (Type *etype, Expression *exp, vec<tree, va_gc> **vars) | |
781 { | |
782 Type *tb = exp->type->toBasetype (); | |
783 | |
784 if ((tb->ty != Tarray && tb->ty != Tsarray) || same_type_p (tb, etype)) | |
785 { | |
786 /* Convert single element to an array. */ | |
787 tree var = NULL_TREE; | |
788 tree expr = maybe_temporary_var (build_expr (exp), &var); | |
789 | |
790 if (var != NULL_TREE) | |
791 vec_safe_push (*vars, var); | |
792 | |
793 return d_array_value (build_ctype (exp->type->arrayOf ()), | |
794 size_int (1), build_address (expr)); | |
795 } | |
796 else | |
797 return d_array_convert (exp); | |
798 } |