1 /* expr.cc -- Lower D frontend expressions to GCC trees.
2 Copyright (C) 2015-2023 Free Software Foundation, Inc.
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)
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.
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/>. */
20 #include "coretypes.h"
22 #include "dmd/aggregate.h"
24 #include "dmd/declaration.h"
26 #include "dmd/expression.h"
27 #include "dmd/identifier.h"
29 #include "dmd/module.h"
30 #include "dmd/mtype.h"
31 #include "dmd/template.h"
34 #include "fold-const.h"
35 #include "diagnostic.h"
36 #include "langhooks.h"
42 #include "stor-layout.h"
47 /* Determine if type T is a struct that has a postblit. */
50 needs_postblit (Type
*t
)
54 if (TypeStruct
*ts
= t
->isTypeStruct ())
56 if (ts
->sym
->postblit
)
63 /* Determine if type T is a struct that has a destructor. */
70 if (TypeStruct
*ts
= t
->isTypeStruct ())
79 /* Determine if expression E is a suitable lvalue. */
82 lvalue_p (Expression
*e
)
84 SliceExp
*se
= e
->isSliceExp ();
85 if (se
!= NULL
&& se
->e1
->isLvalue ())
88 CastExp
*ce
= e
->isCastExp ();
89 if (ce
!= NULL
&& ce
->e1
->isLvalue ())
92 return (e
->op
!= EXP::slice
&& e
->isLvalue ());
95 /* Build an expression of code CODE, data type TYPE, and operands ARG0 and
96 ARG1. Perform relevant conversions needed for correct code operations. */
99 binary_op (tree_code code
, tree type
, tree arg0
, tree arg1
)
101 tree t0
= TREE_TYPE (arg0
);
102 tree t1
= TREE_TYPE (arg1
);
103 tree ret
= NULL_TREE
;
105 /* Deal with float mod expressions immediately. */
106 if (code
== FLOAT_MOD_EXPR
)
107 return build_float_modulus (type
, arg0
, arg1
);
109 if (POINTER_TYPE_P (t0
) && INTEGRAL_TYPE_P (t1
))
110 return build_nop (type
, build_offset_op (code
, arg0
, arg1
));
112 if (INTEGRAL_TYPE_P (t0
) && POINTER_TYPE_P (t1
))
113 return build_nop (type
, build_offset_op (code
, arg1
, arg0
));
115 if (POINTER_TYPE_P (t0
) && POINTER_TYPE_P (t1
))
117 gcc_assert (code
== MINUS_EXPR
);
118 tree ptrtype
= lang_hooks
.types
.type_for_mode (ptr_mode
, 0);
120 /* POINTER_DIFF_EXPR requires a signed integer type of the same size as
121 pointers. If some platform cannot provide that, or has a larger
122 ptrdiff_type to support differences larger than half the address
123 space, cast the pointers to some larger integer type and do the
124 computations in that type. */
125 if (TYPE_PRECISION (ptrtype
) > TYPE_PRECISION (t0
))
126 ret
= fold_build2 (MINUS_EXPR
, ptrtype
,
127 d_convert (ptrtype
, arg0
),
128 d_convert (ptrtype
, arg1
));
130 ret
= fold_build2 (POINTER_DIFF_EXPR
, ptrtype
, arg0
, arg1
);
134 /* If the operation needs excess precision. */
135 tree eptype
= excess_precision_type (type
);
136 if (eptype
!= NULL_TREE
)
138 arg0
= d_convert (eptype
, arg0
);
139 arg1
= d_convert (eptype
, arg1
);
143 /* Front-end does not do this conversion and GCC does not
144 always do it right. */
145 if (COMPLEX_FLOAT_TYPE_P (t0
) && !COMPLEX_FLOAT_TYPE_P (t1
))
146 arg1
= d_convert (t0
, arg1
);
147 else if (COMPLEX_FLOAT_TYPE_P (t1
) && !COMPLEX_FLOAT_TYPE_P (t0
))
148 arg0
= d_convert (t1
, arg0
);
153 ret
= build2 (code
, eptype
, arg0
, arg1
);
156 return d_convert (type
, ret
);
159 /* Build a binary expression of code CODE, assigning the result into E1. */
162 binop_assignment (tree_code code
, Expression
*e1
, Expression
*e2
)
164 /* Skip casts for lhs assignment. */
165 Expression
*e1b
= e1
;
166 while (e1b
->op
== EXP::cast_
)
168 CastExp
*ce
= e1b
->isCastExp ();
169 gcc_assert (same_type_p (ce
->type
, ce
->to
));
173 /* Stabilize LHS for assignment. */
174 tree lhs
= build_expr (e1b
);
175 tree lexpr
= stabilize_expr (&lhs
);
177 /* The LHS expression could be an assignment, to which its operation gets
178 lost during gimplification. */
179 if (TREE_CODE (lhs
) == MODIFY_EXPR
)
181 /* If LHS has side effects, call stabilize_reference on it, so it can
182 be evaluated multiple times. */
183 if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs
, 0)))
184 lhs
= build_assign (MODIFY_EXPR
,
185 stabilize_reference (TREE_OPERAND (lhs
, 0)),
186 TREE_OPERAND (lhs
, 1));
188 lexpr
= compound_expr (lexpr
, lhs
);
189 lhs
= TREE_OPERAND (lhs
, 0);
192 lhs
= stabilize_reference (lhs
);
194 /* Save RHS, to ensure that the expression is evaluated before LHS. */
195 tree rhs
= build_expr (e2
);
196 tree rexpr
= d_save_expr (rhs
);
198 rhs
= binary_op (code
, build_ctype (e1
->type
),
199 convert_expr (lhs
, e1b
->type
, e1
->type
), rexpr
);
200 if (TREE_SIDE_EFFECTS (rhs
))
201 rhs
= compound_expr (rexpr
, rhs
);
203 tree expr
= modify_expr (lhs
, convert_expr (rhs
, e1
->type
, e1b
->type
));
204 return compound_expr (lexpr
, expr
);
207 /* Implements the visitor interface to build the GCC trees of all Expression
208 AST classes emitted from the D Front-end.
209 All visit methods accept one parameter E, which holds the frontend AST
210 of the expression to compile. They also don't return any value, instead
211 generated code is cached in RESULT_ and returned from the caller. */
213 class ExprVisitor
: public Visitor
215 using Visitor::visit
;
222 ExprVisitor (bool constp
, bool literalp
)
224 this->result_
= NULL_TREE
;
225 this->constp_
= constp
;
226 this->literalp_
= literalp
;
231 return this->result_
;
234 /* Visitor interfaces, each Expression class should have
235 overridden the default. */
237 void visit (Expression
*) final override
242 /* Build a conditional expression. If either the second or third
243 expression is void, then the resulting type is void. Otherwise
244 they are implicitly converted to a common type. */
246 void visit (CondExp
*e
) final override
248 tree cond
= convert_for_condition (build_expr (e
->econd
),
250 tree t1
= build_expr (e
->e1
);
251 tree t2
= build_expr (e
->e2
);
253 if (e
->type
->ty
!= TY::Tvoid
)
255 t1
= convert_expr (t1
, e
->e1
->type
, e
->type
);
256 t2
= convert_expr (t2
, e
->e2
->type
, e
->type
);
259 this->result_
= build_condition (build_ctype (e
->type
), cond
, t1
, t2
);
262 /* Build an identity comparison expression. Operands go through the
263 usual conversions to bring them to a common type before comparison.
264 The result type is bool. */
266 void visit (IdentityExp
*e
) final override
268 tree_code code
= (e
->op
== EXP::identity
) ? EQ_EXPR
: NE_EXPR
;
269 Type
*tb1
= e
->e1
->type
->toBasetype ();
270 Type
*tb2
= e
->e2
->type
->toBasetype ();
272 if ((tb1
->ty
== TY::Tsarray
|| tb1
->ty
== TY::Tarray
)
273 && (tb2
->ty
== TY::Tsarray
|| tb2
->ty
== TY::Tarray
))
275 /* For static and dynamic arrays, identity is defined as referring to
276 the same array elements and the same number of elements. */
277 tree t1
= d_array_convert (e
->e1
);
278 tree t2
= d_array_convert (e
->e2
);
279 this->result_
= d_convert (build_ctype (e
->type
),
280 build_boolop (code
, t1
, t2
));
282 else if (tb1
->isfloating () && tb1
->ty
!= TY::Tvector
)
284 /* For floating-point values, identity is defined as the bits in the
285 operands being identical. */
286 tree t1
= d_save_expr (build_expr (e
->e1
));
287 tree t2
= d_save_expr (build_expr (e
->e2
));
289 if (!tb1
->iscomplex ())
290 this->result_
= build_float_identity (code
, t1
, t2
);
293 /* Compare the real and imaginary parts separately. */
294 tree req
= build_float_identity (code
, real_part (t1
),
296 tree ieq
= build_float_identity (code
, imaginary_part (t1
),
297 imaginary_part (t2
));
300 this->result_
= build_boolop (TRUTH_ANDIF_EXPR
, req
, ieq
);
302 this->result_
= build_boolop (TRUTH_ORIF_EXPR
, req
, ieq
);
305 else if (TypeStruct
*ts
= tb1
->isTypeStruct ())
307 /* For struct objects, identity is defined as bits in operands being
308 identical also. Alignment holes in structs are ignored. */
309 tree t1
= build_expr (e
->e1
);
310 tree t2
= build_expr (e
->e2
);
312 gcc_assert (same_type_p (tb1
, tb2
));
314 this->result_
= build_struct_comparison (code
, ts
->sym
, t1
, t2
);
316 else if (tb1
->ty
== TY::Tvector
&& tb2
->ty
== TY::Tvector
)
318 /* For vectors, identity is defined as all values being equal. */
319 tree t1
= build_expr (e
->e1
);
320 tree t2
= build_expr (e
->e2
);
321 tree mask
= build_boolop (code
, t1
, t2
);
323 /* To reinterpret the vector comparison as a boolean expression, bitcast
324 the bitmask result and generate an additional integer comparison. */
325 opt_scalar_int_mode mode
=
326 int_mode_for_mode (TYPE_MODE (TREE_TYPE (mask
)));
327 gcc_assert (mode
.exists ());
329 tree type
= lang_hooks
.types
.type_for_mode (mode
.require (), 1);
330 if (type
== NULL_TREE
)
331 type
= make_unsigned_type (GET_MODE_BITSIZE (mode
.require ()));
333 /* In `t1 is t2', all mask bits must be set for vectors to be equal.
334 Otherwise any bit set is enough for vectors to be not-equal. */
335 tree mask_eq
= (code
== EQ_EXPR
)
336 ? build_all_ones_cst (type
) : build_zero_cst (type
);
338 this->result_
= build_boolop (code
, mask_eq
,
339 build_vconvert (type
, mask
));
343 /* For operands of other types, identity is defined as being the
344 same as equality expressions. */
345 tree t1
= build_expr (e
->e1
);
346 tree t2
= build_expr (e
->e2
);
347 this->result_
= d_convert (build_ctype (e
->type
),
348 build_boolop (code
, t1
, t2
));
352 /* Build an equality expression, which compare the two operands for either
353 equality or inequality. Operands go through the usual conversions to bring
354 them to a common type before comparison. The result type is bool. */
356 void visit (EqualExp
*e
) final override
358 Type
*tb1
= e
->e1
->type
->toBasetype ();
359 Type
*tb2
= e
->e2
->type
->toBasetype ();
360 tree_code code
= (e
->op
== EXP::equal
) ? EQ_EXPR
: NE_EXPR
;
362 if ((tb1
->ty
== TY::Tsarray
|| tb1
->ty
== TY::Tarray
)
363 && (tb2
->ty
== TY::Tsarray
|| tb2
->ty
== TY::Tarray
))
365 /* For static and dynamic arrays, equality is defined as the lengths of
366 the arrays matching, and all the elements are equal. */
367 Type
*t1elem
= tb1
->nextOf ()->toBasetype ();
368 Type
*t2elem
= tb1
->nextOf ()->toBasetype ();
370 /* Check if comparisons of arrays can be optimized using memcmp.
371 This will inline EQ expressions as:
372 e1.length == e2.length && memcmp(e1.ptr, e2.ptr, size) == 0;
373 Or when generating a NE expression:
374 e1.length != e2.length || memcmp(e1.ptr, e2.ptr, size) != 0; */
375 if ((t1elem
->isintegral () || t1elem
->ty
== TY::Tvoid
376 || (t1elem
->ty
== TY::Tstruct
377 && !t1elem
->isTypeStruct ()->sym
->xeq
))
378 && t1elem
->ty
== t2elem
->ty
)
380 tree t1
= d_array_convert (e
->e1
);
381 tree t2
= d_array_convert (e
->e2
);
384 /* Make temporaries to prevent multiple evaluations. */
385 tree t1saved
= d_save_expr (t1
);
386 tree t2saved
= d_save_expr (t2
);
388 /* Length of arrays, for comparisons done before calling memcmp. */
389 tree t1len
= d_array_length (t1saved
);
390 tree t2len
= d_array_length (t2saved
);
392 /* Reference to array data. */
393 tree t1ptr
= d_array_ptr (t1saved
);
394 tree t2ptr
= d_array_ptr (t2saved
);
396 /* Compare arrays using memcmp if possible, otherwise for structs,
397 each field is compared inline. */
398 if (t1elem
->ty
!= TY::Tstruct
399 || identity_compare_p (t1elem
->isTypeStruct ()->sym
))
401 tree size
= size_mult_expr (t1len
, size_int (t1elem
->size ()));
403 result
= build_memcmp_call (t1ptr
, t2ptr
, size
);
404 result
= build_boolop (code
, result
, integer_zero_node
);
408 StructDeclaration
*sd
= t1elem
->isTypeStruct ()->sym
;
410 result
= build_array_struct_comparison (code
, sd
, t1len
,
414 /* Check array length first before passing to memcmp.
415 For equality expressions, this becomes:
416 (e1.length == 0 || memcmp);
417 Otherwise for inequality:
418 (e1.length != 0 && memcmp); */
419 tree tsizecmp
= build_boolop (code
, t1len
, size_zero_node
);
420 if (e
->op
== EXP::equal
)
421 result
= build_boolop (TRUTH_ORIF_EXPR
, tsizecmp
, result
);
423 result
= build_boolop (TRUTH_ANDIF_EXPR
, tsizecmp
, result
);
425 /* Finally, check if lengths of both arrays match if dynamic.
426 The frontend should have already guaranteed that static arrays
428 if (tb1
->ty
== TY::Tsarray
&& tb2
->ty
== TY::Tsarray
)
429 gcc_assert (tb1
->size () == tb2
->size ());
432 tree tlencmp
= build_boolop (code
, t1len
, t2len
);
433 if (e
->op
== EXP::equal
)
434 result
= build_boolop (TRUTH_ANDIF_EXPR
, tlencmp
, result
);
436 result
= build_boolop (TRUTH_ORIF_EXPR
, tlencmp
, result
);
439 /* Ensure left-to-right order of evaluation. */
440 if (TREE_SIDE_EFFECTS (t2
))
441 result
= compound_expr (t2saved
, result
);
443 if (TREE_SIDE_EFFECTS (t1
))
444 result
= compound_expr (t1saved
, result
);
446 this->result_
= result
;
450 /* Use _adEq2() to compare each element. */
451 Type
*t1array
= t1elem
->arrayOf ();
452 tree result
= build_libcall (LIBCALL_ADEQ2
, e
->type
, 3,
453 d_array_convert (e
->e1
),
454 d_array_convert (e
->e2
),
455 build_typeinfo (e
, t1array
));
457 if (e
->op
== EXP::notEqual
)
458 result
= build1 (TRUTH_NOT_EXPR
, build_ctype (e
->type
), result
);
460 this->result_
= result
;
463 else if (TypeStruct
*ts
= tb1
->isTypeStruct ())
465 /* Equality for struct objects means the logical product of all
466 equality results of the corresponding object fields. */
467 tree t1
= build_expr (e
->e1
);
468 tree t2
= build_expr (e
->e2
);
470 gcc_assert (same_type_p (tb1
, tb2
));
472 this->result_
= build_struct_comparison (code
, ts
->sym
, t1
, t2
);
474 else if (tb1
->ty
== TY::Taarray
&& tb2
->ty
== TY::Taarray
)
476 /* Use _aaEqual() for associative arrays. */
477 tree result
= build_libcall (LIBCALL_AAEQUAL
, e
->type
, 3,
478 build_typeinfo (e
, tb1
),
482 if (e
->op
== EXP::notEqual
)
483 result
= build1 (TRUTH_NOT_EXPR
, build_ctype (e
->type
), result
);
485 this->result_
= result
;
489 /* For operands of other types, equality is defined as the bit pattern
490 of the type matches exactly. */
491 tree t1
= build_expr (e
->e1
);
492 tree t2
= build_expr (e
->e2
);
494 this->result_
= d_convert (build_ctype (e
->type
),
495 build_boolop (code
, t1
, t2
));
499 /* Build an `in' expression. This is a condition to see if an element
500 exists in an associative array. The result is a pointer to the
501 element, or null if false. */
503 void visit (InExp
*e
) final override
505 Type
*tb2
= e
->e2
->type
->toBasetype ();
506 Type
*tkey
= tb2
->isTypeAArray ()->index
->toBasetype ();
507 tree key
= convert_expr (build_expr (e
->e1
), e
->e1
->type
, tkey
);
509 /* Build a call to _aaInX(). */
510 this->result_
= build_libcall (LIBCALL_AAINX
, e
->type
, 3,
512 build_typeinfo (e
, tkey
),
513 build_address (key
));
516 /* Build a relational expression. The result type is bool. */
518 void visit (CmpExp
*e
) final override
520 Type
*tb1
= e
->e1
->type
->toBasetype ();
521 Type
*tb2
= e
->e2
->type
->toBasetype ();
528 case EXP::lessOrEqual
:
536 case EXP::greaterOrEqual
:
540 case EXP::greaterThan
:
548 /* For static and dynamic arrays, the relational op is turned into a
549 library call. It is not lowered during codegen. */
550 if ((tb1
->ty
== TY::Tsarray
|| tb1
->ty
== TY::Tarray
)
551 && (tb2
->ty
== TY::Tsarray
|| tb2
->ty
== TY::Tarray
))
553 error ("cannot handle comparison of type %<%s == %s%>",
554 tb1
->toChars (), tb2
->toChars ());
558 /* Simple comparison. */
559 result
= build_boolop (code
, build_expr (e
->e1
), build_expr (e
->e2
));
560 this->result_
= d_convert (build_ctype (e
->type
), result
);
563 /* Build a logical `and if' or `or if' expression. If the right operand
564 expression is void, then the resulting type is void. Otherwise the
567 void visit (LogicalExp
*e
) final override
569 tree_code code
= (e
->op
== EXP::andAnd
) ? TRUTH_ANDIF_EXPR
: TRUTH_ORIF_EXPR
;
571 if (e
->e2
->type
->toBasetype ()->ty
!= TY::Tvoid
)
573 tree t1
= build_expr (e
->e1
);
574 tree t2
= build_expr (e
->e2
);
576 t1
= convert_for_condition (t1
, e
->e1
->type
);
577 t2
= convert_for_condition (t2
, e
->e2
->type
);
579 this->result_
= d_convert (build_ctype (e
->type
),
580 build_boolop (code
, t1
, t2
));
584 tree t1
= convert_for_condition (build_expr (e
->e1
), e
->e1
->type
);
585 tree t2
= build_expr_dtor (e
->e2
);
587 /* Invert condition for logical or if expression. */
588 if (e
->op
== EXP::orOr
)
589 t1
= build1 (TRUTH_NOT_EXPR
, d_bool_type
, t1
);
591 this->result_
= build_condition (build_ctype (e
->type
),
596 /* Build a binary operand expression. Operands go through usual arithmetic
597 conversions to bring them to a common type before evaluating. */
599 void visit (BinExp
*e
) final override
607 if ((e
->e1
->type
->isreal () && e
->e2
->type
->isimaginary ())
608 || (e
->e1
->type
->isimaginary () && e
->e2
->type
->isreal ()))
610 /* If the result is complex, then we can shortcut binary_op.
611 Frontend should have already validated types and sizes. */
612 tree t1
= build_expr (e
->e1
);
613 tree t2
= build_expr (e
->e2
);
615 if (e
->op
== EXP::min
)
616 t2
= build1 (NEGATE_EXPR
, TREE_TYPE (t2
), t2
);
618 if (e
->e1
->type
->isreal ())
619 this->result_
= complex_expr (build_ctype (e
->type
), t1
, t2
);
621 this->result_
= complex_expr (build_ctype (e
->type
), t2
, t1
);
626 code
= (e
->op
== EXP::add
)
627 ? PLUS_EXPR
: MINUS_EXPR
;
635 /* Determine if the div expression is a lowered pointer diff operation.
636 The front-end rewrites `(p1 - p2)' into `(p1 - p2) / stride'. */
637 if (MinExp
*me
= e
->e1
->isMinExp ())
639 if (me
->e1
->type
->ty
== TY::Tpointer
640 && me
->e2
->type
->ty
== TY::Tpointer
641 && e
->e2
->op
== EXP::int64
)
643 code
= EXACT_DIV_EXPR
;
648 code
= e
->e1
->type
->isintegral ()
649 ? TRUNC_DIV_EXPR
: RDIV_EXPR
;
653 code
= e
->e1
->type
->isfloating ()
654 ? FLOAT_MOD_EXPR
: TRUNC_MOD_EXPR
;
673 case EXP::rightShift
:
677 case EXP::unsignedRightShift
:
678 code
= UNSIGNED_RSHIFT_EXPR
;
685 this->result_
= binary_op (code
, build_ctype (e
->type
),
686 build_expr (e
->e1
), build_expr (e
->e2
));
690 /* Build a concat expression, which concatenates two or more arrays of the
691 same type, producing a dynamic array with the result. If one operand
692 is an element type, that element is converted to an array of length 1. */
694 void visit (CatExp
*e
) final override
696 /* This error is only emitted during the code generation pass because
697 concatentation is allowed in CTFE. */
698 if (!global
.params
.useGC
)
700 error_at (make_location_t (e
->loc
),
701 "array concatenation of expression %qs requires the GC and "
702 "cannot be used with %<-fno-druntime%>", e
->toChars ());
703 this->result_
= error_mark_node
;
707 /* All concat expressions should have been rewritten to `_d_arraycatnTX` in
708 the semantic phase. */
709 gcc_assert (e
->lowering
);
711 this->result_
= build_expr (e
->lowering
);
714 /* Build an assignment operator expression. The right operand is implicitly
715 converted to the type of the left operand, and assigned to it. */
717 void visit (BinAssignExp
*e
) final override
720 Expression
*e1b
= e
->e1
;
737 code
= e
->e1
->type
->isintegral ()
738 ? TRUNC_DIV_EXPR
: RDIV_EXPR
;
742 code
= e
->e1
->type
->isfloating ()
743 ? FLOAT_MOD_EXPR
: TRUNC_MOD_EXPR
;
761 case EXP::leftShiftAssign
:
765 case EXP::rightShiftAssign
:
766 case EXP::unsignedRightShiftAssign
:
767 /* Use the original lhs type before it was promoted. The left operand
768 of `>>>=' does not undergo integral promotions before shifting.
769 Strip off casts just incase anyway. */
770 while (e1b
->op
== EXP::cast_
)
772 CastExp
*ce
= e1b
->isCastExp ();
773 gcc_assert (same_type_p (ce
->type
, ce
->to
));
776 code
= (e
->op
== EXP::rightShiftAssign
) ? RSHIFT_EXPR
: UNSIGNED_RSHIFT_EXPR
;
783 tree exp
= binop_assignment (code
, e1b
, e
->e2
);
784 this->result_
= convert_expr (exp
, e1b
->type
, e
->type
);
787 /* Build a concat assignment expression. The right operand is appended
788 to the left operand. */
790 void visit (CatAssignExp
*e
) final override
792 Type
*tb1
= e
->e1
->type
->toBasetype ();
793 Type
*tb2
= e
->e2
->type
->toBasetype ();
794 Type
*etype
= tb1
->nextOf ()->toBasetype ();
796 /* Save the address of `e1', so it can be evaluated first.
797 As all D run-time library functions for concat assignments update `e1'
798 in-place and then return its value, the saved address can also be used as
799 the result of this expression as well. */
800 tree lhs
= build_expr (e
->e1
);
801 tree lexpr
= stabilize_expr (&lhs
);
802 tree ptr
= d_save_expr (build_address (lhs
));
803 tree result
= NULL_TREE
;
805 if (tb1
->ty
== TY::Tarray
&& tb2
->ty
== TY::Tdchar
806 && (etype
->ty
== TY::Tchar
|| etype
->ty
== TY::Twchar
))
808 /* Append a dchar to a char[] or wchar[]:
809 The assignment is handled by the D run-time library, so only
810 need to call `_d_arrayappend[cw]d(&e1, e2)' */
811 libcall_fn libcall
= (etype
->ty
== TY::Tchar
)
812 ? LIBCALL_ARRAYAPPENDCD
: LIBCALL_ARRAYAPPENDWD
;
814 result
= build_libcall (libcall
, e
->type
, 2,
815 ptr
, build_expr (e
->e2
));
819 /* Appending an element or array to another array has already been
820 handled by the front-end. */
821 gcc_assert (tb1
->ty
== TY::Tarray
|| tb2
->ty
== TY::Tsarray
);
825 /* Construct in order: ptr = &e1, _d_arrayappend(ptr, e2), *ptr; */
826 result
= compound_expr (compound_expr (lexpr
, ptr
), result
);
827 this->result_
= compound_expr (result
, build_deref (ptr
));
830 /* Build an assignment expression. The right operand is implicitly
831 converted to the type of the left operand, and assigned to it. */
833 void visit (AssignExp
*e
) final override
835 /* First, handle special assignment semantics. */
837 /* Look for array.length = n; */
838 if (e
->e1
->op
== EXP::arrayLength
)
840 /* This case should have been rewritten to `_d_arraysetlengthT` in the
845 /* Look for exp = noreturn; */
846 if (e
->e2
->type
->isTypeNoreturn ())
848 /* If the RHS is a `noreturn' expression, there is no point generating
849 any code for the assignment, just evaluate side effects. */
850 tree t1
= build_expr (e
->e1
);
851 tree t2
= build_expr (e
->e2
);
852 this->result_
= compound_expr (t1
, t2
);
856 /* Look for array[] = n; */
857 if (e
->e1
->op
== EXP::slice
)
859 SliceExp
*se
= e
->e1
->isSliceExp ();
860 Type
*stype
= se
->e1
->type
->toBasetype ();
861 Type
*etype
= stype
->nextOf ()->toBasetype ();
863 /* Determine if we need to run postblit or dtor. */
864 bool postblit
= needs_postblit (etype
) && lvalue_p (e
->e2
);
865 bool destructor
= needs_dtor (etype
);
867 if (e
->memset
== MemorySet::blockAssign
)
869 /* Set a range of elements to one value. */
870 tree t1
= build_expr (e
->e1
);
871 tree t2
= build_expr (e
->e2
);
874 /* Extract any array bounds checks from the slice expression. */
875 tree init
= stabilize_expr (&t1
);
876 t1
= d_save_expr (t1
);
878 if ((postblit
|| destructor
) && e
->op
!= EXP::blit
)
880 /* This case should have been rewritten to `_d_arraysetassign`
881 in the semantic phase. */
885 if (integer_zerop (t2
))
887 tree size
= size_mult_expr (d_array_length (t1
),
888 size_int (etype
->size ()));
889 result
= build_memset_call (d_array_ptr (t1
), size
);
892 result
= build_array_set (d_array_ptr (t1
),
893 d_array_length (t1
), t2
);
895 result
= compound_expr (init
, result
);
896 this->result_
= compound_expr (result
, t1
);
900 /* Perform a memcpy operation. */
901 gcc_assert (e
->e2
->type
->ty
!= TY::Tpointer
);
903 if (!postblit
&& !destructor
)
905 tree t1
= d_save_expr (d_array_convert (e
->e1
));
906 tree t2
= d_save_expr (d_array_convert (e
->e2
));
908 /* References to array data. */
909 tree t1ptr
= d_array_ptr (t1
);
910 tree t1len
= d_array_length (t1
);
911 tree t2ptr
= d_array_ptr (t2
);
913 /* Generate: memcpy(to, from, size) */
914 tree size
= size_mult_expr (t1len
, size_int (etype
->size ()));
915 tree result
= build_memcpy_call (t1ptr
, t2ptr
, size
);
917 /* Insert check that array lengths match and do not overlap. */
918 if (array_bounds_check ())
920 /* tlencmp = (t1len == t2len) */
921 tree t2len
= d_array_length (t2
);
922 tree tlencmp
= build_boolop (EQ_EXPR
, t1len
, t2len
);
924 /* toverlap = (t1ptr + size <= t2ptr
925 || t2ptr + size <= t1ptr) */
926 tree t1ptrcmp
= build_boolop (LE_EXPR
,
927 build_offset (t1ptr
, size
),
929 tree t2ptrcmp
= build_boolop (LE_EXPR
,
930 build_offset (t2ptr
, size
),
932 tree toverlap
= build_boolop (TRUTH_ORIF_EXPR
, t1ptrcmp
,
935 /* (tlencmp && toverlap) ? memcpy() : _d_arraybounds() */
936 tree tassert
= build_array_bounds_call (e
->loc
);
937 tree tboundscheck
= build_boolop (TRUTH_ANDIF_EXPR
,
940 result
= build_condition (void_type_node
, tboundscheck
,
944 this->result_
= compound_expr (result
, t1
);
946 else if ((postblit
|| destructor
)
947 && e
->op
!= EXP::blit
&& e
->op
!= EXP::construct
)
949 /* Assigning to a non-trivially copyable array has already been
950 handled by the front-end. */
955 /* Generate: _d_arraycopy() */
956 this->result_
= build_libcall (LIBCALL_ARRAYCOPY
, e
->type
, 3,
957 size_int (etype
->size ()),
958 d_array_convert (e
->e2
),
959 d_array_convert (e
->e1
));
966 /* Look for reference initializations. */
967 if (e
->memset
== MemorySet::referenceInit
)
969 gcc_assert (e
->op
== EXP::construct
|| e
->op
== EXP::blit
);
970 gcc_assert (e
->e1
->op
== EXP::variable
);
972 Declaration
*decl
= e
->e1
->isVarExp ()->var
;
973 if (decl
->storage_class
& (STCout
| STCref
))
975 tree t2
= convert_for_assignment (build_expr (e
->e2
),
976 e
->e2
->type
, e
->e1
->type
);
977 tree t1
= build_expr (e
->e1
);
978 /* Want reference to lhs, not indirect ref. */
979 t1
= TREE_OPERAND (t1
, 0);
980 t2
= build_address (t2
);
982 this->result_
= indirect_ref (build_ctype (e
->type
),
983 build_assign (INIT_EXPR
, t1
, t2
));
988 /* Other types of assignments that may require post construction. */
989 Type
*tb1
= e
->e1
->type
->toBasetype ();
990 tree_code modifycode
= (e
->op
== EXP::construct
) ? INIT_EXPR
: MODIFY_EXPR
;
992 /* Look for struct assignment. */
993 if (tb1
->ty
== TY::Tstruct
)
995 tree t1
= build_expr (e
->e1
);
996 tree t2
= convert_for_assignment (build_expr (e
->e2
, false, true),
997 e
->e2
->type
, e
->e1
->type
);
998 StructDeclaration
*sd
= tb1
->isTypeStruct ()->sym
;
1000 /* Look for struct = 0. */
1001 if (e
->e2
->op
== EXP::int64
)
1003 /* Use memset to fill struct. */
1004 gcc_assert (e
->op
== EXP::blit
);
1005 tree result
= build_memset_call (t1
);
1007 /* Maybe set-up hidden pointer to outer scope context. */
1008 if (sd
->isNested ())
1010 tree field
= get_symbol_decl (sd
->vthis
);
1011 tree value
= build_vthis (sd
);
1013 tree vthis_exp
= modify_expr (component_ref (t1
, field
), value
);
1014 result
= compound_expr (result
, vthis_exp
);
1017 this->result_
= compound_expr (result
, t1
);
1021 /* Simple struct literal assignment. */
1022 tree init
= NULL_TREE
;
1024 /* Fill any alignment holes in the struct using memset. */
1025 if ((e
->op
== EXP::construct
1026 || (e
->e2
->op
== EXP::structLiteral
&& e
->op
== EXP::blit
))
1027 && (sd
->isUnionDeclaration () || !identity_compare_p (sd
)))
1029 t1
= stabilize_reference (t1
);
1030 init
= build_memset_call (t1
);
1033 /* Elide generating assignment if init is all zeroes. */
1034 if (init
!= NULL_TREE
&& initializer_zerop (t2
))
1035 this->result_
= compound_expr (init
, t1
);
1038 tree result
= build_assign (modifycode
, t1
, t2
);
1039 this->result_
= compound_expr (init
, result
);
1046 /* Look for static array assignment. */
1047 if (tb1
->ty
== TY::Tsarray
)
1049 /* Look for array = 0. */
1050 if (e
->e2
->op
== EXP::int64
)
1052 /* Use memset to fill the array. */
1053 gcc_assert (e
->op
== EXP::blit
);
1054 this->result_
= build_memset_call (build_expr (e
->e1
));
1058 Type
*etype
= tb1
->nextOf ();
1059 gcc_assert (e
->e2
->type
->toBasetype ()->ty
== TY::Tsarray
);
1061 /* Determine if we need to run postblit. */
1062 const bool postblit
= needs_postblit (etype
);
1063 const bool destructor
= needs_dtor (etype
);
1064 const bool lvalue
= lvalue_p (e
->e2
);
1066 /* Optimize static array assignment with array literal. Even if the
1067 elements in rhs are all rvalues and don't have to call postblits,
1068 this assignment should call dtors on old assigned elements. */
1069 if ((!postblit
&& !destructor
)
1070 || (e
->op
== EXP::construct
&& e
->e2
->op
== EXP::arrayLiteral
)
1071 || (e
->op
== EXP::construct
&& e
->e2
->op
== EXP::call
)
1072 || (e
->op
== EXP::construct
&& !lvalue
&& postblit
)
1073 || (e
->op
== EXP::blit
|| e
->e1
->type
->size () == 0))
1075 tree t1
= build_expr (e
->e1
);
1076 tree t2
= convert_for_assignment (build_expr (e
->e2
),
1077 e
->e2
->type
, e
->e1
->type
);
1079 this->result_
= build_assign (modifycode
, t1
, t2
);
1083 /* All other kinds of lvalue or rvalue static array assignment.
1084 Array construction has already been handled by the front-end. */
1085 gcc_assert (e
->op
!= EXP::construct
);
1089 /* Simple assignment. */
1090 tree t1
= build_expr (e
->e1
);
1091 tree t2
= convert_for_assignment (build_expr (e
->e2
),
1092 e
->e2
->type
, e
->e1
->type
);
1094 this->result_
= build_assign (modifycode
, t1
, t2
);
1097 /* Build an assignment expression that has been lowered in the front-end. */
1099 void visit (LoweredAssignExp
*e
) final override
1101 this->result_
= build_expr (e
->lowering
);
1104 /* Build a throw expression. */
1106 void visit (ThrowExp
*e
) final override
1108 tree arg
= build_expr_dtor (e
->e1
);
1109 this->result_
= build_libcall (LIBCALL_THROW
, Type::tvoid
, 1, arg
);
1112 /* Build a postfix expression. */
1114 void visit (PostExp
*e
) final override
1118 if (e
->op
== EXP::plusPlus
)
1120 result
= build2 (POSTINCREMENT_EXPR
, build_ctype (e
->type
),
1121 build_expr (e
->e1
), build_expr (e
->e2
));
1123 else if (e
->op
== EXP::minusMinus
)
1125 result
= build2 (POSTDECREMENT_EXPR
, build_ctype (e
->type
),
1126 build_expr (e
->e1
), build_expr (e
->e2
));
1131 TREE_SIDE_EFFECTS (result
) = 1;
1132 this->result_
= result
;
1135 /* Build an index expression. */
1137 void visit (IndexExp
*e
) final override
1139 Type
*tb1
= e
->e1
->type
->toBasetype ();
1141 if (tb1
->ty
== TY::Taarray
)
1143 /* Get the key for the associative array. */
1144 Type
*tkey
= tb1
->isTypeAArray ()->index
->toBasetype ();
1145 tree key
= convert_expr (build_expr (e
->e2
), e
->e2
->type
, tkey
);
1151 libcall
= LIBCALL_AAGETY
;
1152 ptr
= build_address (build_expr (e
->e1
));
1153 tinfo
= build_typeinfo (e
, tb1
->unSharedOf ()->mutableOf ());
1157 libcall
= LIBCALL_AAGETRVALUEX
;
1158 ptr
= build_expr (e
->e1
);
1159 tinfo
= build_typeinfo (e
, tkey
);
1162 /* Index the associative array. */
1163 tree result
= build_libcall (libcall
, e
->type
->pointerTo (), 4,
1165 size_int (tb1
->nextOf ()->size ()),
1166 build_address (key
));
1168 if (!e
->indexIsInBounds
&& array_bounds_check ())
1170 tree tassert
= build_array_bounds_call (e
->loc
);
1172 result
= d_save_expr (result
);
1173 result
= build_condition (TREE_TYPE (result
),
1174 d_truthvalue_conversion (result
),
1178 this->result_
= indirect_ref (build_ctype (e
->type
), result
);
1182 /* Get the array and length for static and dynamic arrays. */
1183 tree array
= d_save_expr (build_expr (e
->e1
));
1185 tree length
= NULL_TREE
;
1186 if (tb1
->ty
!= TY::Tpointer
)
1187 length
= get_array_length (array
, tb1
);
1189 gcc_assert (e
->lengthVar
== NULL
);
1191 /* The __dollar variable just becomes a placeholder for the
1194 e
->lengthVar
->csym
= length
;
1196 /* Generate the index. */
1197 tree index
= build_expr (e
->e2
);
1199 /* If it's a static array and the index is constant, the front end has
1200 already checked the bounds. */
1201 if (tb1
->ty
!= TY::Tpointer
)
1202 index
= build_bounds_index_condition (e
, index
, length
);
1204 /* Convert vectors to their underlying array type. */
1205 if (VECTOR_TYPE_P (TREE_TYPE (array
)))
1208 build_array_type_nelts (TREE_TYPE (TREE_TYPE (array
)),
1209 TYPE_VECTOR_SUBPARTS (TREE_TYPE (array
)));
1210 d_mark_addressable (array
, false);
1211 array
= build1 (VIEW_CONVERT_EXPR
, array_type
, array
);
1214 if (TREE_CODE (TREE_TYPE (array
)) == ARRAY_TYPE
)
1216 /* Generate `array[index]'. When the index is non-constant, we must
1217 mark the array as addressable because we'll need to do pointer
1218 arithmetic on its address. */
1219 if (TREE_CODE (index
) != INTEGER_CST
)
1220 d_mark_addressable (array
);
1222 this->result_
= build4 (ARRAY_REF
, TREE_TYPE (TREE_TYPE (array
)),
1223 array
, index
, NULL_TREE
, NULL_TREE
);
1227 /* Generate `array.ptr[index]'. */
1228 tree ptr
= convert_expr (array
, tb1
, tb1
->nextOf ()->pointerTo ());
1229 ptr
= void_okay_p (ptr
);
1230 this->result_
= indirect_ref (TREE_TYPE (TREE_TYPE (ptr
)),
1231 build_pointer_index (ptr
, index
));
1236 /* Build a comma expression. The type is the type of the right operand. */
1238 void visit (CommaExp
*e
) final override
1240 tree t1
= build_expr (e
->e1
);
1241 tree t2
= build_expr (e
->e2
);
1242 tree type
= e
->type
? build_ctype (e
->type
) : void_type_node
;
1244 this->result_
= build2 (COMPOUND_EXPR
, type
, t1
, t2
);
1247 /* Build an array length expression. Returns the number of elements
1248 in the array. The result is of type size_t. */
1250 void visit (ArrayLengthExp
*e
) final override
1252 if (e
->e1
->type
->toBasetype ()->ty
== TY::Tarray
)
1253 this->result_
= d_array_length (build_expr (e
->e1
));
1256 /* Static arrays have already been handled by the front-end. */
1257 error ("unexpected type for array length: %qs", e
->type
->toChars ());
1258 this->result_
= error_mark_node
;
1262 /* Build a delegate pointer expression. This will return the frame
1263 pointer value as a type void*. */
1265 void visit (DelegatePtrExp
*e
) final override
1267 tree t1
= build_expr (e
->e1
);
1268 this->result_
= delegate_object (t1
);
1271 /* Build a delegate function pointer expression. This will return the
1272 function pointer value as a function type. */
1274 void visit (DelegateFuncptrExp
*e
) final override
1276 tree t1
= build_expr (e
->e1
);
1277 this->result_
= delegate_method (t1
);
1280 /* Build a slice expression. */
1282 void visit (SliceExp
*e
) final override
1284 Type
*tb
= e
->type
->toBasetype ();
1285 Type
*tb1
= e
->e1
->type
->toBasetype ();
1286 gcc_assert (tb
->ty
== TY::Tarray
|| tb
->ty
== TY::Tsarray
);
1288 /* Use convert-to-dynamic-array code if possible. */
1291 tree result
= build_expr (e
->e1
);
1292 if (e
->e1
->type
->toBasetype ()->ty
== TY::Tsarray
)
1293 result
= convert_expr (result
, e
->e1
->type
, e
->type
);
1295 this->result_
= result
;
1299 gcc_assert (e
->upr
!= NULL
);
1301 /* Get the data pointer and length for static and dynamic arrays. */
1302 tree array
= d_save_expr (build_expr (e
->e1
));
1303 tree ptr
= convert_expr (array
, tb1
, tb1
->nextOf ()->pointerTo ());
1304 tree length
= NULL_TREE
;
1306 /* Our array is already a SAVE_EXPR if necessary, so we don't make length
1307 a SAVE_EXPR which is, at most, a COMPONENT_REF on top of array. */
1308 if (tb1
->ty
!= TY::Tpointer
)
1309 length
= get_array_length (array
, tb1
);
1311 gcc_assert (e
->lengthVar
== NULL
);
1313 /* The __dollar variable just becomes a placeholder for the
1316 e
->lengthVar
->csym
= length
;
1318 /* Generate upper and lower bounds. */
1319 tree lwr_tree
= d_save_expr (build_expr (e
->lwr
));
1320 tree upr_tree
= d_save_expr (build_expr (e
->upr
));
1322 /* If the upper bound has any side effects, then the lower bound should be
1323 copied to a temporary always. */
1324 if (TREE_CODE (upr_tree
) == SAVE_EXPR
&& TREE_CODE (lwr_tree
) != SAVE_EXPR
)
1325 lwr_tree
= save_expr (lwr_tree
);
1327 /* Adjust the .ptr offset. */
1328 if (!integer_zerop (lwr_tree
))
1330 tree ptrtype
= TREE_TYPE (ptr
);
1331 ptr
= build_pointer_index (void_okay_p (ptr
), lwr_tree
);
1332 ptr
= build_nop (ptrtype
, ptr
);
1335 /* Nothing more to do for static arrays, their bounds checking has been
1336 done at compile-time. */
1337 if (tb
->ty
== TY::Tsarray
)
1339 this->result_
= indirect_ref (build_ctype (e
->type
), ptr
);
1343 gcc_assert (tb
->ty
== TY::Tarray
);
1345 /* Generate bounds checking code. */
1346 tree newlength
= build_bounds_slice_condition (e
, lwr_tree
, upr_tree
,
1348 tree result
= d_array_value (build_ctype (e
->type
), newlength
, ptr
);
1349 this->result_
= compound_expr (array
, result
);
1352 /* Build a cast expression, which converts the given unary expression to the
1355 void visit (CastExp
*e
) final override
1357 Type
*ebtype
= e
->e1
->type
->toBasetype ();
1358 Type
*tbtype
= e
->to
->toBasetype ();
1359 tree result
= build_expr (e
->e1
, this->constp_
, this->literalp_
);
1361 /* Just evaluate e1 if it has any side effects. */
1362 if (tbtype
->ty
== TY::Tvoid
)
1363 this->result_
= build_nop (build_ctype (tbtype
), result
);
1365 this->result_
= convert_for_rvalue (result
, ebtype
, tbtype
);
1368 /* Build a delete expression. */
1370 void visit (DeleteExp
*e
) final override
1372 tree t1
= build_expr (e
->e1
);
1373 Type
*tb1
= e
->e1
->type
->toBasetype ();
1375 if (tb1
->ty
== TY::Tclass
)
1377 /* For class object references, if there is a destructor for that class,
1378 the destructor is called for the object instance. */
1379 gcc_assert (e
->e1
->op
== EXP::variable
);
1381 VarDeclaration
*v
= e
->e1
->isVarExp ()->var
->isVarDeclaration ();
1382 gcc_assert (v
&& v
->onstack ());
1384 libcall_fn libcall
= tb1
->isClassHandle ()->isInterfaceDeclaration ()
1385 ? LIBCALL_CALLINTERFACEFINALIZER
: LIBCALL_CALLFINALIZER
;
1387 this->result_
= build_libcall (libcall
, Type::tvoid
, 1, t1
);
1392 error ("don%'t know how to delete %qs", e
->e1
->toChars ());
1393 this->result_
= error_mark_node
;
1397 /* Build a remove expression, which removes a particular key from an
1398 associative array. */
1400 void visit (RemoveExp
*e
) final override
1402 /* Check that the array is actually an associative array. */
1403 if (e
->e1
->type
->toBasetype ()->ty
== TY::Taarray
)
1405 Type
*tb
= e
->e1
->type
->toBasetype ();
1406 Type
*tkey
= tb
->isTypeAArray ()->index
->toBasetype ();
1407 tree index
= convert_expr (build_expr (e
->e2
), e
->e2
->type
, tkey
);
1409 this->result_
= build_libcall (LIBCALL_AADELX
, Type::tbool
, 3,
1411 build_typeinfo (e
, tkey
),
1412 build_address (index
));
1416 error ("%qs is not an associative array", e
->e1
->toChars ());
1417 this->result_
= error_mark_node
;
1421 /* Build an unary not expression. */
1423 void visit (NotExp
*e
) final override
1425 tree result
= convert_for_condition (build_expr (e
->e1
), e
->e1
->type
);
1426 /* Need to convert to boolean type or this will fail. */
1427 result
= fold_build1 (TRUTH_NOT_EXPR
, d_bool_type
, result
);
1429 this->result_
= d_convert (build_ctype (e
->type
), result
);
1432 /* Build a compliment expression, where all the bits in the value are
1433 complemented. Note: unlike in C, the usual integral promotions
1434 are not performed prior to the complement operation. */
1436 void visit (ComExp
*e
) final override
1438 TY ty1
= e
->e1
->type
->toBasetype ()->ty
;
1439 gcc_assert (ty1
!= TY::Tarray
&& ty1
!= TY::Tsarray
);
1441 this->result_
= fold_build1 (BIT_NOT_EXPR
, build_ctype (e
->type
),
1442 build_expr (e
->e1
));
1445 /* Build an unary negation expression. */
1447 void visit (NegExp
*e
) final override
1449 TY ty1
= e
->e1
->type
->toBasetype ()->ty
;
1450 gcc_assert (ty1
!= TY::Tarray
&& ty1
!= TY::Tsarray
);
1452 tree type
= build_ctype (e
->type
);
1453 tree expr
= build_expr (e
->e1
);
1455 /* If the operation needs excess precision. */
1456 tree eptype
= excess_precision_type (type
);
1457 if (eptype
!= NULL_TREE
)
1458 expr
= d_convert (eptype
, expr
);
1462 tree ret
= fold_build1 (NEGATE_EXPR
, eptype
, expr
);
1463 this->result_
= d_convert (type
, ret
);
1466 /* Build a pointer index expression. */
1468 void visit (PtrExp
*e
) final override
1474 if (e
->e1
->op
== EXP::add
)
1476 AddExp
*ae
= e
->e1
->isAddExp ();
1477 if (ae
->e1
->op
== EXP::address
1478 && ae
->e2
->isConst () && ae
->e2
->type
->isintegral ())
1480 Expression
*ex
= ae
->e1
->isAddrExp ()->e1
;
1481 tnext
= ex
->type
->toBasetype ();
1482 result
= build_expr (ex
);
1483 offset
= ae
->e2
->toUInteger ();
1486 else if (e
->e1
->op
== EXP::symbolOffset
)
1488 SymOffExp
*se
= e
->e1
->isSymOffExp ();
1489 if (!declaration_reference_p (se
->var
))
1491 tnext
= se
->var
->type
->toBasetype ();
1492 result
= get_decl_tree (se
->var
);
1493 offset
= se
->offset
;
1497 /* Produce better code by converting *(#record + n) to
1498 COMPONENT_REFERENCE. Otherwise, the variable will always be
1499 allocated in memory because its address is taken. */
1500 if (tnext
&& tnext
->ty
== TY::Tstruct
)
1502 StructDeclaration
*sd
= tnext
->isTypeStruct ()->sym
;
1504 for (size_t i
= 0; i
< sd
->fields
.length
; i
++)
1506 VarDeclaration
*field
= sd
->fields
[i
];
1508 if (field
->offset
== offset
1509 && same_type_p (field
->type
, e
->type
))
1511 /* Catch errors, backend will ICE otherwise. */
1512 if (error_operand_p (result
))
1513 this->result_
= result
;
1516 result
= component_ref (result
, get_symbol_decl (field
));
1517 this->result_
= result
;
1521 else if (field
->offset
> offset
)
1526 this->result_
= indirect_ref (build_ctype (e
->type
), build_expr (e
->e1
));
1529 /* Build an unary address expression. */
1531 void visit (AddrExp
*e
) final override
1533 tree type
= build_ctype (e
->type
);
1536 /* The frontend optimizer can convert const symbol into a struct literal.
1537 Taking the address of a struct literal is otherwise illegal. */
1538 if (e
->e1
->op
== EXP::structLiteral
)
1540 StructLiteralExp
*sle
= e
->e1
->isStructLiteralExp ()->origin
;
1541 gcc_assert (sle
!= NULL
);
1543 /* Build the reference symbol, the decl is built first as the
1544 initializer may have recursive references. */
1547 sle
->sym
= build_artificial_decl (build_ctype (sle
->type
),
1549 DECL_INITIAL (sle
->sym
) = build_expr (sle
, true);
1550 d_pushdecl (sle
->sym
);
1551 rest_of_decl_compilation (sle
->sym
, 1, 0);
1557 exp
= build_expr (e
->e1
, this->constp_
, this->literalp_
);
1559 TREE_CONSTANT (exp
) = 0;
1560 this->result_
= d_convert (type
, build_address (exp
));
1563 /* Build a function call expression. */
1565 void visit (CallExp
*e
) final override
1567 Type
*tb
= e
->e1
->type
->toBasetype ();
1568 Expression
*e1b
= e
->e1
;
1570 tree callee
= NULL_TREE
;
1571 tree object
= NULL_TREE
;
1572 tree cleanup
= NULL_TREE
;
1573 tree returnvalue
= NULL_TREE
;
1574 TypeFunction
*tf
= NULL
;
1576 /* Calls to delegates can sometimes look like this. */
1577 if (e1b
->op
== EXP::comma
)
1579 e1b
= e1b
->isCommaExp ()->e2
;
1580 gcc_assert (e1b
->op
== EXP::variable
);
1582 Declaration
*var
= e1b
->isVarExp ()->var
;
1583 gcc_assert (var
->isFuncDeclaration () && !var
->needThis ());
1586 if (e1b
->op
== EXP::dotVariable
&& tb
->ty
!= TY::Tdelegate
)
1588 DotVarExp
*dve
= e1b
->isDotVarExp ();
1590 /* Don't modify the static initializer for struct literals. */
1591 if (dve
->e1
->op
== EXP::structLiteral
)
1593 StructLiteralExp
*sle
= dve
->e1
->isStructLiteralExp ();
1594 sle
->useStaticInit
= false;
1597 FuncDeclaration
*fd
= dve
->var
->isFuncDeclaration ();
1600 /* Get the correct callee from the DotVarExp object. */
1601 tree fndecl
= get_symbol_decl (fd
);
1602 AggregateDeclaration
*ad
= fd
->isThis ();
1604 /* Static method; ignore the object instance. */
1606 callee
= build_address (fndecl
);
1609 tree thisexp
= build_expr (dve
->e1
);
1611 /* When constructing temporaries, if the constructor throws,
1612 then the object is destructed even though it is not a fully
1613 constructed object yet. And so this call will need to be
1614 moved inside the TARGET_EXPR_INITIAL slot. */
1615 if (fd
->isCtorDeclaration ()
1616 && TREE_CODE (thisexp
) == COMPOUND_EXPR
1617 && TREE_CODE (TREE_OPERAND (thisexp
, 0)) == TARGET_EXPR
1618 && TARGET_EXPR_CLEANUP (TREE_OPERAND (thisexp
, 0)))
1620 cleanup
= TREE_OPERAND (thisexp
, 0);
1621 thisexp
= TREE_OPERAND (thisexp
, 1);
1624 if (TREE_CODE (thisexp
) == CONSTRUCTOR
)
1625 thisexp
= force_target_expr (thisexp
);
1627 /* Want reference to `this' object. */
1628 if (!POINTER_TYPE_P (TREE_TYPE (thisexp
)))
1629 thisexp
= build_address (thisexp
);
1631 /* Make the callee a virtual call. */
1632 if (fd
->isVirtual () && !fd
->isFinalFunc () && !e
->directcall
)
1634 tree fntype
= build_pointer_type (TREE_TYPE (fndecl
));
1635 tree thistype
= build_ctype (ad
->handleType ());
1636 thisexp
= build_nop (thistype
, d_save_expr (thisexp
));
1637 fndecl
= build_vindex_ref (thisexp
, fntype
, fd
->vtblIndex
);
1640 fndecl
= build_address (fndecl
);
1642 /* C++ constructors return void, even though front-end semantic
1643 treats them as implicitly returning `this'. Set returnvalue
1644 to override the result of this expression. */
1645 if (fd
->isCtorDeclaration ())
1647 thisexp
= d_save_expr (thisexp
);
1648 returnvalue
= thisexp
;
1651 callee
= build_method_call (fndecl
, thisexp
, fd
->type
);
1656 if (callee
== NULL_TREE
)
1657 callee
= build_expr (e1b
);
1659 if (METHOD_CALL_EXPR (callee
))
1661 /* This could be a delegate expression (TY == Tdelegate), but not
1662 actually a delegate variable. */
1663 if (e1b
->op
== EXP::dotVariable
)
1665 /* This gets the true function type, getting the function type
1666 from e1->type can sometimes be incorrect, such as when calling
1667 a `ref' return function. */
1668 tf
= get_function_type (e1b
->isDotVarExp ()->var
->type
);
1671 tf
= get_function_type (tb
);
1673 extract_from_method_call (callee
, callee
, object
);
1675 else if (tb
->ty
== TY::Tdelegate
)
1677 /* Delegate call, extract .object and .funcptr from var. */
1678 callee
= d_save_expr (callee
);
1679 tf
= get_function_type (tb
);
1680 object
= delegate_object (callee
);
1681 callee
= delegate_method (callee
);
1683 else if (e1b
->op
== EXP::variable
)
1685 FuncDeclaration
*fd
= e1b
->isVarExp ()->var
->isFuncDeclaration ();
1686 gcc_assert (fd
!= NULL
);
1687 tf
= get_function_type (fd
->type
);
1689 if (fd
->isNested ())
1691 /* Maybe re-evaluate symbol storage treating `fd' as public. */
1692 if (call_by_alias_p (d_function_chain
->function
, fd
))
1693 TREE_PUBLIC (callee
) = 1;
1695 object
= get_frame_for_symbol (fd
);
1697 else if (fd
->needThis ())
1699 error_at (make_location_t (e1b
->loc
),
1700 "need %<this%> to access member %qs", fd
->toChars ());
1701 /* Continue compiling... */
1702 object
= null_pointer_node
;
1707 /* Normal direct function call. */
1708 tf
= get_function_type (tb
);
1711 gcc_assert (tf
!= NULL
);
1713 /* Now we have the type, callee and maybe object reference,
1714 build the call expression. */
1715 tree exp
= d_build_call (tf
, callee
, object
, e
->arguments
);
1717 if (returnvalue
!= NULL_TREE
)
1718 exp
= compound_expr (exp
, returnvalue
);
1721 exp
= build_deref (exp
);
1723 /* Some library calls are defined to return a generic type.
1724 this->type is the real type we want to return. */
1725 if (e
->type
->isTypeBasic ())
1726 exp
= d_convert (build_ctype (e
->type
), exp
);
1728 /* If this call was found to be a constructor for a temporary with a
1729 cleanup, then move the call inside the TARGET_EXPR. */
1730 if (cleanup
!= NULL_TREE
)
1732 tree init
= TARGET_EXPR_INITIAL (cleanup
);
1733 TARGET_EXPR_INITIAL (cleanup
) = compound_expr (init
, exp
);
1735 /* Keep the return value outside the TARGET_EXPR. */
1736 if (returnvalue
!= NULL_TREE
)
1737 cleanup
= compound_expr (cleanup
, TREE_OPERAND (exp
, 1));
1742 this->result_
= exp
;
1745 /* Build a delegate expression. */
1747 void visit (DelegateExp
*e
) final override
1749 if (e
->func
->semanticRun
== PASS::semantic3done
)
1751 /* Add the function as nested function if it belongs to this module.
1752 ie: it is a member of this module, or it is a template instance. */
1753 Dsymbol
*owner
= e
->func
->toParent ();
1754 while (!owner
->isTemplateInstance () && owner
->toParent ())
1755 owner
= owner
->toParent ();
1756 if (owner
->isTemplateInstance () || owner
== d_function_chain
->module
)
1757 build_decl_tree (e
->func
);
1763 if (e
->func
->isNested () && !e
->func
->isThis ())
1765 if (e
->e1
->op
== EXP::null_
)
1766 object
= build_expr (e
->e1
);
1768 object
= get_frame_for_symbol (e
->func
);
1770 fndecl
= build_address (get_symbol_decl (e
->func
));
1774 if (!e
->func
->isThis ())
1776 error ("delegates are only for non-static functions");
1777 this->result_
= error_mark_node
;
1781 object
= build_expr (e
->e1
);
1783 /* Want reference to `this' object. */
1784 if (e
->e1
->type
->ty
!= TY::Tclass
&& e
->e1
->type
->ty
!= TY::Tpointer
)
1785 object
= build_address (object
);
1787 /* Object reference could be the outer `this' field of a class or
1788 closure of type `void*'. Cast it to the right type. */
1789 if (e
->e1
->type
->ty
== TY::Tclass
)
1790 object
= d_convert (build_ctype (e
->e1
->type
), object
);
1792 fndecl
= get_symbol_decl (e
->func
);
1794 /* Get pointer to function out of the virtual table. */
1795 if (e
->func
->isVirtual () && !e
->func
->isFinalFunc ()
1796 && e
->e1
->op
!= EXP::super_
&& e
->e1
->op
!= EXP::dotType
)
1798 tree fntype
= build_pointer_type (TREE_TYPE (fndecl
));
1799 object
= d_save_expr (object
);
1800 fndecl
= build_vindex_ref (object
, fntype
, e
->func
->vtblIndex
);
1803 fndecl
= build_address (fndecl
);
1806 this->result_
= build_method_call (fndecl
, object
, e
->type
);
1809 /* Build a type component expression. */
1811 void visit (DotTypeExp
*e
) final override
1813 /* Just a pass through to underlying expression. */
1814 this->result_
= build_expr (e
->e1
);
1817 /* Build a component reference expression. */
1819 void visit (DotVarExp
*e
) final override
1821 VarDeclaration
*vd
= e
->var
->isVarDeclaration ();
1823 /* This could also be a function, but relying on that being taken
1824 care of by the visitor interface for CallExp. */
1827 if (!vd
->isField ())
1828 this->result_
= get_decl_tree (vd
);
1831 tree object
= build_expr (e
->e1
);
1832 Type
*tb
= e
->e1
->type
->toBasetype ();
1834 if (tb
->ty
!= TY::Tstruct
)
1835 object
= build_deref (object
);
1837 /* __complex is represented as a struct in the front-end, but
1838 underlying is really a complex type. */
1839 if (e
->e1
->type
->ty
== TY::Tenum
1840 && e
->e1
->type
->isTypeEnum ()->sym
->isSpecial ())
1841 object
= underlying_complex_expr (build_ctype (tb
), object
);
1843 this->result_
= component_ref (object
, get_symbol_decl (vd
));
1848 error ("%qs is not a field, but a %qs",
1849 e
->var
->toChars (), e
->var
->kind ());
1850 this->result_
= error_mark_node
;
1854 /* Build an assert expression, used to declare conditions that must hold at
1855 that a given point in the program. */
1857 void visit (AssertExp
*e
) final override
1859 Type
*tb1
= e
->e1
->type
->toBasetype ();
1860 tree arg
= build_expr (e
->e1
);
1861 tree tmsg
= NULL_TREE
;
1862 tree assert_pass
= void_node
;
1865 if (global
.params
.useAssert
== CHECKENABLEon
&& !checkaction_trap_p ())
1867 /* Generate: ((bool) e1 ? (void)0 : _d_assert (...))
1868 or: (e1 != null ? e1._invariant() : _d_assert (...)) */
1869 bool unittest_p
= d_function_chain
->function
->isUnitTestDeclaration ();
1874 tmsg
= build_expr_dtor (e
->msg
);
1875 libcall
= unittest_p
? LIBCALL_UNITTEST_MSG
: LIBCALL_ASSERT_MSG
;
1878 libcall
= unittest_p
? LIBCALL_UNITTESTP
: LIBCALL_ASSERTP
;
1880 /* Build a call to _d_assert(). */
1881 assert_fail
= build_assert_call (e
->loc
, libcall
, tmsg
);
1883 if (global
.params
.useInvariants
== CHECKENABLEon
)
1885 /* If the condition is a D class or struct object with an invariant,
1886 call it if the condition result is true. */
1887 if (tb1
->ty
== TY::Tclass
)
1889 ClassDeclaration
*cd
= tb1
->isClassHandle ();
1890 if (!cd
->isInterfaceDeclaration () && !cd
->isCPPclass ())
1892 arg
= d_save_expr (arg
);
1893 assert_pass
= build_libcall (LIBCALL_INVARIANT
,
1894 Type::tvoid
, 1, arg
);
1897 else if (tb1
->ty
== TY::Tpointer
1898 && tb1
->nextOf ()->ty
== TY::Tstruct
)
1900 StructDeclaration
*sd
= tb1
->nextOf ()->isTypeStruct ()->sym
;
1901 if (sd
->inv
!= NULL
)
1904 arg
= d_save_expr (arg
);
1905 assert_pass
= d_build_call_expr (sd
->inv
, arg
, &args
);
1910 else if (global
.params
.useAssert
== CHECKENABLEon
&& checkaction_trap_p ())
1912 /* Generate: __builtin_trap() */
1913 tree fn
= builtin_decl_explicit (BUILT_IN_TRAP
);
1914 assert_fail
= build_call_expr (fn
, 0);
1918 /* Assert contracts are turned off. */
1919 this->result_
= void_node
;
1923 /* Build condition that we are asserting in this contract. */
1924 tree condition
= convert_for_condition (arg
, e
->e1
->type
);
1926 /* We expect the condition to always be true, as what happens if an assert
1927 contract is false is undefined behavior. */
1928 tree fn
= builtin_decl_explicit (BUILT_IN_EXPECT
);
1929 tree arg_types
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
1930 tree pred_type
= TREE_VALUE (arg_types
);
1931 tree expected_type
= TREE_VALUE (TREE_CHAIN (arg_types
));
1933 condition
= build_call_expr (fn
, 2, d_convert (pred_type
, condition
),
1934 build_int_cst (expected_type
, 1));
1935 condition
= d_truthvalue_conversion (condition
);
1937 this->result_
= build_vcondition (condition
, assert_pass
, assert_fail
);
1940 /* Build a declaration expression. */
1942 void visit (DeclarationExp
*e
) final override
1944 /* Compile the declaration. */
1946 build_decl_tree (e
->declaration
);
1947 tree result
= pop_stmt_list ();
1949 /* Construction of an array for typesafe-variadic function arguments
1950 can cause an empty STMT_LIST here. This can causes problems
1951 during gimplification. */
1952 if (TREE_CODE (result
) == STATEMENT_LIST
&& !STATEMENT_LIST_HEAD (result
))
1953 result
= build_empty_stmt (input_location
);
1955 this->result_
= result
;
1958 /* Build a typeid expression. Returns an instance of class TypeInfo
1959 corresponding to. */
1961 void visit (TypeidExp
*e
) final override
1963 if (Type
*tid
= isType (e
->obj
))
1965 tree ti
= build_typeinfo (e
, tid
);
1967 /* If the typeinfo is at an offset. */
1968 if (tid
->vtinfo
->offset
)
1969 ti
= build_offset (ti
, size_int (tid
->vtinfo
->offset
));
1971 this->result_
= build_nop (build_ctype (e
->type
), ti
);
1973 else if (Expression
*tid
= isExpression (e
->obj
))
1975 Type
*type
= tid
->type
->toBasetype ();
1976 assert (type
->ty
== TY::Tclass
);
1978 /* Generate **classptr to get the classinfo. */
1979 tree ci
= build_expr (tid
);
1980 ci
= indirect_ref (ptr_type_node
, ci
);
1981 ci
= indirect_ref (ptr_type_node
, ci
);
1983 /* Add extra indirection for interfaces. */
1984 if (type
->isTypeClass ()->sym
->isInterfaceDeclaration ())
1985 ci
= indirect_ref (ptr_type_node
, ci
);
1987 this->result_
= build_nop (build_ctype (e
->type
), ci
);
1993 /* Build a function/lambda expression. */
1995 void visit (FuncExp
*e
) final override
1997 Type
*ftype
= e
->type
->toBasetype ();
1999 /* This check is for lambda's, remove `vthis' as function isn't nested. */
2000 if (e
->fd
->tok
== TOK::reserved
&& ftype
->ty
== TY::Tpointer
)
2002 e
->fd
->tok
= TOK::function_
;
2003 e
->fd
->vthis
= NULL
;
2006 /* Compile the function literal body. */
2007 build_decl_tree (e
->fd
);
2009 /* If nested, this will be a trampoline. */
2010 if (e
->fd
->isNested ())
2012 tree func
= build_address (get_symbol_decl (e
->fd
));
2017 /* Static delegate variables have no context pointer. */
2018 object
= null_pointer_node
;
2019 this->result_
= build_method_call (func
, object
, e
->fd
->type
);
2020 TREE_CONSTANT (this->result_
) = 1;
2024 object
= get_frame_for_symbol (e
->fd
);
2025 this->result_
= build_method_call (func
, object
, e
->fd
->type
);
2030 this->result_
= build_nop (build_ctype (e
->type
),
2031 build_address (get_symbol_decl (e
->fd
)));
2035 /* Build a halt expression. */
2037 void visit (HaltExp
*) final override
2039 /* Should we use trap() or abort()? */
2040 tree ttrap
= builtin_decl_explicit (BUILT_IN_TRAP
);
2041 this->result_
= build_call_expr (ttrap
, 0);
2044 /* Build a symbol pointer offset expression. */
2046 void visit (SymOffExp
*e
) final override
2048 /* Build the address and offset of the symbol. */
2049 size_t soffset
= e
->isSymOffExp ()->offset
;
2050 tree result
= get_decl_tree (e
->var
);
2051 TREE_USED (result
) = 1;
2053 if (declaration_reference_p (e
->var
))
2054 gcc_assert (POINTER_TYPE_P (TREE_TYPE (result
)));
2056 result
= build_address (result
);
2059 result
= d_convert (build_ctype (e
->type
), result
);
2062 tree offset
= size_int (soffset
);
2063 result
= build_nop (build_ctype (e
->type
),
2064 build_offset (result
, offset
));
2067 this->result_
= result
;
2070 /* Build a variable expression. */
2072 void visit (VarExp
*e
) final override
2074 if (e
->var
->needThis ())
2076 error ("need %<this%> to access member %qs", e
->var
->ident
->toChars ());
2077 this->result_
= error_mark_node
;
2080 else if (e
->var
->ident
== Identifier::idPool ("__ctfe"))
2082 /* __ctfe is always false at run-time. */
2083 this->result_
= integer_zero_node
;
2087 /* This check is same as is done in FuncExp for lambdas. */
2088 FuncLiteralDeclaration
*fld
= e
->var
->isFuncLiteralDeclaration ();
2091 if (fld
->tok
== TOK::reserved
)
2093 fld
->tok
= TOK::function_
;
2097 /* Compiler the function literal body. */
2098 build_decl_tree (fld
);
2103 /* Want the initializer, not the expression. */
2104 VarDeclaration
*var
= e
->var
->isVarDeclaration ();
2105 SymbolDeclaration
*sdecl
= e
->var
->isSymbolDeclaration ();
2106 tree init
= NULL_TREE
;
2108 if (var
&& (var
->isConst () || var
->isImmutable ())
2109 && e
->type
->toBasetype ()->ty
!= TY::Tsarray
&& var
->_init
)
2112 error_at (make_location_t (e
->loc
), "recursive reference %qs",
2117 init
= build_expr (initializerToExpression (var
->_init
), true);
2121 else if (sdecl
&& sdecl
->dsym
)
2123 if (StructDeclaration
*sd
= sdecl
->dsym
->isStructDeclaration ())
2124 init
= layout_struct_initializer (sd
);
2125 else if (ClassDeclaration
*cd
= sdecl
->dsym
->isClassDeclaration ())
2126 init
= layout_class_initializer (cd
);
2131 error_at (make_location_t (e
->loc
), "non-constant expression %qs",
2134 if (init
!= NULL_TREE
)
2135 this->result_
= init
;
2137 this->result_
= error_mark_node
;
2141 tree result
= get_decl_tree (e
->var
);
2142 TREE_USED (result
) = 1;
2144 /* The variable expression generated for `__traits(initSymbol)'. */
2145 if (SymbolDeclaration
*sd
= e
->var
->isSymbolDeclaration ())
2147 if (e
->type
->isTypeDArray ())
2149 /* Generate a slice for non-zero initialized aggregates,
2150 otherwise create an empty array. */
2151 gcc_assert (e
->type
== Type::tvoid
->arrayOf ()->constOf ());
2153 tree type
= build_ctype (e
->type
);
2154 tree length
= size_int (sd
->dsym
->structsize
);
2155 tree ptr
= (sd
->dsym
->isStructDeclaration ()
2156 && sd
->dsym
->type
->isZeroInit (e
->loc
))
2157 ? null_pointer_node
: build_address (result
);
2159 this->result_
= d_array_value (type
, length
, ptr
);
2164 /* For variables that are references - currently only out/inout
2165 arguments; objects don't count - evaluating the variable means
2166 we want what it refers to. */
2167 if (declaration_reference_p (e
->var
))
2168 result
= indirect_ref (build_ctype (e
->var
->type
), result
);
2170 this->result_
= result
;
2174 /* Build a this variable expression. */
2176 void visit (ThisExp
*e
) final override
2178 FuncDeclaration
*fd
= d_function_chain
? d_function_chain
->function
: NULL
;
2179 tree result
= NULL_TREE
;
2182 result
= get_decl_tree (e
->var
);
2185 gcc_assert (fd
&& fd
->vthis
);
2186 result
= get_decl_tree (fd
->vthis
);
2189 if (e
->type
->ty
== TY::Tstruct
)
2190 result
= build_deref (result
);
2192 this->result_
= result
;
2195 /* Build a new expression, which allocates memory either on the garbage
2196 collected heap or by using a class or struct specific allocator. */
2198 void visit (NewExp
*e
) final override
2200 Type
*tb
= e
->type
->toBasetype ();
2203 if (tb
->ty
== TY::Tclass
)
2205 /* Allocating a new class. */
2206 tb
= e
->newtype
->toBasetype ();
2208 ClassDeclaration
*cd
= tb
->isTypeClass ()->sym
;
2209 tree type
= build_ctype (tb
);
2210 tree setup_exp
= NULL_TREE
;
2215 /* If being used as an initializer for a local variable with scope
2216 storage class, then the instance is allocated on the stack
2217 rather than the heap or using the class specific allocator. */
2218 tree var
= build_local_temp (TREE_TYPE (type
));
2219 new_call
= build_nop (type
, build_address (var
));
2220 setup_exp
= modify_expr (var
, aggregate_initializer_decl (cd
));
2222 else if (global
.params
.ehnogc
&& e
->thrownew
)
2224 /* Allocating a `@nogc' Exception with `_d_newThrowable' has already
2225 been handled by the front-end. */
2230 /* Generate: _d_newclass() */
2231 new_call
= build_expr (e
->lowering
);
2234 /* Set the context pointer for nested classes. */
2235 if (cd
->isNested ())
2237 tree field
= get_symbol_decl (cd
->vthis
);
2238 tree value
= NULL_TREE
;
2242 ClassDeclaration
*tcd
= e
->thisexp
->type
->isClassHandle ();
2243 /* The class or function we're nested in. */
2244 Dsymbol
*outer
= cd
->toParentLocal ();
2246 value
= build_expr (e
->thisexp
);
2250 ClassDeclaration
*ocd
= outer
->isClassDeclaration ();
2252 gcc_assert (ocd
->isBaseOf (tcd
, &offset
));
2253 /* Could just add offset... */
2254 value
= convert_expr (value
, e
->thisexp
->type
, ocd
->type
);
2258 value
= build_vthis (cd
);
2260 if (value
!= NULL_TREE
)
2262 /* Generate: (new())->vthis = this; */
2263 new_call
= d_save_expr (new_call
);
2264 field
= component_ref (build_deref (new_call
), field
);
2265 setup_exp
= compound_expr (setup_exp
,
2266 modify_expr (field
, value
));
2269 new_call
= compound_expr (setup_exp
, new_call
);
2271 /* Call the class constructor. */
2273 result
= d_build_call_expr (e
->member
, new_call
, e
->arguments
);
2278 result
= compound_expr (build_expr (e
->argprefix
), result
);
2280 else if (tb
->ty
== TY::Tpointer
2281 && tb
->nextOf ()->toBasetype ()->ty
== TY::Tstruct
)
2283 /* Allocating memory for a new struct. */
2284 Type
*htype
= e
->newtype
->toBasetype ();
2285 gcc_assert (!e
->onstack
);
2287 TypeStruct
*stype
= htype
->isTypeStruct ();
2288 StructDeclaration
*sd
= stype
->sym
;
2291 /* Cannot new an opaque struct. */
2292 if (sd
->size (e
->loc
) == 0)
2294 this->result_
= d_convert (build_ctype (e
->type
),
2299 /* This case should have been rewritten to `_d_newitemT' during the
2301 gcc_assert (e
->lowering
);
2303 /* Generate: _d_newitemT() */
2304 new_call
= build_expr (e
->lowering
);
2306 if (e
->member
|| !e
->arguments
)
2308 /* Set the context pointer for nested structs. */
2309 if (sd
->isNested ())
2311 tree value
= build_vthis (sd
);
2312 tree field
= get_symbol_decl (sd
->vthis
);
2313 tree type
= build_ctype (stype
);
2315 new_call
= d_save_expr (new_call
);
2316 field
= component_ref (indirect_ref (type
, new_call
), field
);
2317 new_call
= compound_expr (modify_expr (field
, value
), new_call
);
2320 /* Call the struct constructor. */
2322 result
= d_build_call_expr (e
->member
, new_call
, e
->arguments
);
2328 /* If we have a user supplied initializer, then set-up with a
2330 if (e
->arguments
!= NULL
&& sd
->fields
.length
!= 0)
2332 StructLiteralExp
*se
= StructLiteralExp::create (e
->loc
, sd
,
2335 new_call
= d_save_expr (new_call
);
2336 se
->type
= sd
->type
;
2338 result
= compound_expr (build_expr (se
), new_call
);
2345 result
= compound_expr (build_expr (e
->argprefix
), result
);
2347 else if (tb
->ty
== TY::Tarray
)
2349 /* Allocating memory for a new D array. */
2350 tb
= e
->newtype
->toBasetype ();
2351 TypeDArray
*tarray
= tb
->isTypeDArray ();
2353 gcc_assert (e
->arguments
&& e
->arguments
->length
>= 1);
2355 if (e
->arguments
->length
== 1)
2357 /* Single dimension array allocations. */
2358 Expression
*arg
= (*e
->arguments
)[0];
2360 if (tarray
->next
->size () == 0)
2362 /* Array element size is unknown. */
2363 this->result_
= d_array_value (build_ctype (e
->type
),
2364 size_int (0), null_pointer_node
);
2368 libcall_fn libcall
= tarray
->next
->isZeroInit ()
2369 ? LIBCALL_NEWARRAYT
: LIBCALL_NEWARRAYIT
;
2370 result
= build_libcall (libcall
, tb
, 2,
2371 build_typeinfo (e
, e
->type
),
2376 /* Multidimensional array allocations. */
2377 tree tarray
= make_array_type (Type::tsize_t
, e
->arguments
->length
);
2378 tree var
= build_local_temp (tarray
);
2379 vec
<constructor_elt
, va_gc
> *elms
= NULL
;
2381 /* Get the base element type for the array, generating the
2382 initializer for the dims parameter along the way. */
2383 Type
*telem
= e
->newtype
->toBasetype ();
2384 for (size_t i
= 0; i
< e
->arguments
->length
; i
++)
2386 Expression
*arg
= (*e
->arguments
)[i
];
2387 CONSTRUCTOR_APPEND_ELT (elms
, size_int (i
), build_expr (arg
));
2389 gcc_assert (telem
->ty
== TY::Tarray
);
2390 telem
= telem
->toBasetype ()->nextOf ();
2394 /* Initialize the temporary. */
2395 tree init
= modify_expr (var
, build_constructor (tarray
, elms
));
2396 var
= compound_expr (init
, var
);
2398 /* Generate: _d_newarraymTX(ti, dims)
2399 or: _d_newarraymiTX(ti, dims) */
2400 libcall_fn libcall
= telem
->isZeroInit ()
2401 ? LIBCALL_NEWARRAYMTX
: LIBCALL_NEWARRAYMITX
;
2403 tree tinfo
= build_typeinfo (e
, e
->type
);
2404 tree dims
= d_array_value (build_ctype (Type::tsize_t
->arrayOf ()),
2405 size_int (e
->arguments
->length
),
2406 build_address (var
));
2408 result
= build_libcall (libcall
, tb
, 2, tinfo
, dims
);
2412 result
= compound_expr (build_expr (e
->argprefix
), result
);
2414 else if (tb
->ty
== TY::Tpointer
)
2416 /* Allocating memory for a new pointer. */
2417 TypePointer
*tpointer
= tb
->isTypePointer ();
2419 if (tpointer
->next
->size () == 0)
2421 /* Pointer element size is unknown. */
2422 this->result_
= d_convert (build_ctype (e
->type
),
2427 /* This case should have been rewritten to `_d_newitemT' during the
2429 gcc_assert (e
->lowering
);
2431 /* Generate: _d_newitemT() */
2432 result
= build_expr (e
->lowering
);
2434 if (e
->arguments
&& e
->arguments
->length
== 1)
2436 result
= d_save_expr (result
);
2437 tree init
= modify_expr (build_deref (result
),
2438 build_expr ((*e
->arguments
)[0]));
2439 result
= compound_expr (init
, result
);
2443 result
= compound_expr (build_expr (e
->argprefix
), result
);
2445 else if (tb
->ty
== TY::Taarray
)
2447 /* Allocating memory for a new associative array. */
2448 tree arg
= build_typeinfo (e
, e
->newtype
);
2449 tree mem
= build_libcall (LIBCALL_AANEW
, Type::tvoidptr
, 1, arg
);
2451 /* Return an associative array pointed to by MEM. */
2452 tree aatype
= build_ctype (tb
);
2453 vec
<constructor_elt
, va_gc
> *ce
= NULL
;
2454 CONSTRUCTOR_APPEND_ELT (ce
, TYPE_FIELDS (aatype
), mem
);
2456 result
= build_nop (build_ctype (e
->type
),
2457 build_constructor (aatype
, ce
));
2462 this->result_
= convert_expr (result
, tb
, e
->type
);
2465 /* Build an integer literal. */
2467 void visit (IntegerExp
*e
) final override
2469 tree ctype
= build_ctype (e
->type
->toBasetype ());
2470 this->result_
= build_integer_cst (e
->value
, ctype
);
2473 /* Build a floating-point literal. */
2475 void visit (RealExp
*e
) final override
2477 this->result_
= build_float_cst (e
->value
, e
->type
->toBasetype ());
2480 /* Build a complex literal. */
2482 void visit (ComplexExp
*e
) final override
2486 switch (e
->type
->toBasetype ()->ty
)
2488 case TY::Tcomplex32
:
2489 tnext
= (TypeBasic
*) Type::tfloat32
;
2492 case TY::Tcomplex64
:
2493 tnext
= (TypeBasic
*) Type::tfloat64
;
2496 case TY::Tcomplex80
:
2497 tnext
= (TypeBasic
*) Type::tfloat80
;
2504 this->result_
= build_complex (build_ctype (e
->type
),
2505 build_float_cst (creall (e
->value
), tnext
),
2506 build_float_cst (cimagl (e
->value
), tnext
));
2509 /* Build a string literal, all strings are null terminated except for
2512 void visit (StringExp
*e
) final override
2514 Type
*tb
= e
->type
->toBasetype ();
2515 tree type
= build_ctype (e
->type
);
2517 if (tb
->ty
== TY::Tsarray
)
2519 /* Turn the string into a constructor for the static array. */
2520 vec
<constructor_elt
, va_gc
> *elms
= NULL
;
2521 vec_safe_reserve (elms
, e
->len
);
2522 tree etype
= TREE_TYPE (type
);
2524 for (size_t i
= 0; i
< e
->len
; i
++)
2526 tree value
= build_integer_cst (e
->getCodeUnit (i
), etype
);
2527 CONSTRUCTOR_APPEND_ELT (elms
, size_int (i
), value
);
2530 tree ctor
= build_constructor (type
, elms
);
2531 TREE_CONSTANT (ctor
) = 1;
2532 this->result_
= ctor
;
2536 /* Copy the string contents to a null terminated string. */
2537 dinteger_t length
= (e
->len
* e
->sz
);
2538 char *string
= XALLOCAVEC (char, length
+ e
->sz
);
2539 memset (string
, 0, length
+ e
->sz
);
2541 memcpy (string
, e
->string
, length
);
2543 /* String value and type includes the null terminator. */
2544 tree value
= build_string (length
+ e
->sz
, string
);
2545 TREE_TYPE (value
) = make_array_type (tb
->nextOf (), length
+ 1);
2546 value
= build_address (value
);
2548 if (tb
->ty
== TY::Tarray
)
2549 value
= d_array_value (type
, size_int (e
->len
), value
);
2551 TREE_CONSTANT (value
) = 1;
2552 this->result_
= d_convert (type
, value
);
2556 /* Build a tuple literal. Just an argument list that may have
2557 side effects that need evaluation. */
2559 void visit (TupleExp
*e
) final override
2561 tree result
= NULL_TREE
;
2564 result
= build_expr (e
->e0
, this->constp_
, true);
2566 for (size_t i
= 0; i
< e
->exps
->length
; ++i
)
2568 Expression
*exp
= (*e
->exps
)[i
];
2569 result
= compound_expr (result
, build_expr (exp
, this->constp_
, true));
2572 if (result
== NULL_TREE
)
2575 this->result_
= result
;
2578 /* Build an array literal. The common type of the all elements is taken to
2579 be the type of the array element, and all elements are implicitly
2580 converted to that type. */
2582 void visit (ArrayLiteralExp
*e
) final override
2584 Type
*tb
= e
->type
->toBasetype ();
2586 /* Implicitly convert void[n] to ubyte[n]. */
2587 if (tb
->ty
== TY::Tsarray
&& tb
->nextOf ()->toBasetype ()->ty
== TY::Tvoid
)
2588 tb
= Type::tuns8
->sarrayOf (tb
->isTypeSArray ()->dim
->toUInteger ());
2590 gcc_assert (tb
->ty
== TY::Tarray
|| tb
->ty
== TY::Tsarray
2591 || tb
->ty
== TY::Tpointer
);
2593 /* Handle empty array literals. */
2594 if (e
->elements
->length
== 0)
2596 if (tb
->ty
== TY::Tarray
)
2597 this->result_
= d_array_value (build_ctype (e
->type
),
2598 size_int (0), null_pointer_node
);
2600 this->result_
= build_constructor (make_array_type (tb
->nextOf (), 0),
2606 /* Build an expression that assigns the expressions in ELEMENTS to
2608 vec
<constructor_elt
, va_gc
> *elms
= NULL
;
2609 vec_safe_reserve (elms
, e
->elements
->length
);
2610 bool constant_p
= true;
2611 tree saved_elems
= NULL_TREE
;
2613 Type
*etype
= tb
->nextOf ();
2614 tree satype
= make_array_type (etype
, e
->elements
->length
);
2616 for (size_t i
= 0; i
< e
->elements
->length
; i
++)
2618 Expression
*expr
= e
->getElement (i
);
2619 tree value
= build_expr (expr
, this->constp_
, true);
2621 /* Only append nonzero values, the backend will zero out the rest
2622 of the constructor as we don't set CONSTRUCTOR_NO_CLEARING. */
2623 if (!initializer_zerop (value
))
2625 if (!TREE_CONSTANT (value
))
2628 /* Split construction of values out of the constructor if there
2629 may be side effects. */
2630 tree init
= stabilize_expr (&value
);
2631 if (init
!= NULL_TREE
)
2632 saved_elems
= compound_expr (saved_elems
, init
);
2634 CONSTRUCTOR_APPEND_ELT (elms
, size_int (i
),
2635 convert_expr (value
, expr
->type
, etype
));
2639 /* Now return the constructor as the correct type. For static arrays there
2640 is nothing else to do. For dynamic arrays, return a two field struct.
2641 For pointers, return the address. */
2642 tree ctor
= build_constructor (satype
, elms
);
2643 tree type
= build_ctype (e
->type
);
2645 /* Nothing else to do for static arrays. */
2646 if (tb
->ty
== TY::Tsarray
|| this->constp_
)
2648 /* Can't take the address of the constructor, so create an anonymous
2649 static symbol, and then refer to it. */
2650 if (tb
->ty
!= TY::Tsarray
)
2652 tree decl
= build_artificial_decl (TREE_TYPE (ctor
), ctor
, "A");
2653 ctor
= build_address (decl
);
2654 if (tb
->ty
== TY::Tarray
)
2655 ctor
= d_array_value (type
, size_int (e
->elements
->length
), ctor
);
2657 /* Immutable literals can be placed in rodata. */
2658 if (tb
->isImmutable ())
2659 TREE_READONLY (decl
) = 1;
2662 rest_of_decl_compilation (decl
, 1, 0);
2665 /* If the array literal is readonly or static. */
2667 TREE_CONSTANT (ctor
) = 1;
2668 if (constant_p
&& initializer_constant_valid_p (ctor
, TREE_TYPE (ctor
)))
2669 TREE_STATIC (ctor
) = 1;
2671 /* Use memset to fill any alignment holes in the array. */
2672 if (!this->constp_
&& !this->literalp_
)
2674 TypeStruct
*ts
= etype
->baseElemOf ()->isTypeStruct ();
2676 if (ts
!= NULL
&& (!identity_compare_p (ts
->sym
)
2677 || ts
->sym
->isUnionDeclaration ()))
2679 tree var
= build_local_temp (TREE_TYPE (ctor
));
2680 tree init
= build_memset_call (var
);
2681 /* Evaluate memset() first, then any saved elements. */
2682 saved_elems
= compound_expr (init
, saved_elems
);
2683 ctor
= compound_expr (modify_expr (var
, ctor
), var
);
2687 this->result_
= compound_expr (saved_elems
, d_convert (type
, ctor
));
2689 else if (e
->onstack
)
2691 /* Array literal for a `scope' dynamic array. */
2692 gcc_assert (tb
->ty
== TY::Tarray
);
2693 ctor
= force_target_expr (ctor
);
2694 this->result_
= d_array_value (type
, size_int (e
->elements
->length
),
2695 build_address (ctor
));
2699 /* Allocate space on the memory managed heap. */
2700 tree mem
= build_libcall (LIBCALL_ARRAYLITERALTX
,
2701 etype
->pointerTo (), 2,
2702 build_typeinfo (e
, etype
->arrayOf ()),
2703 size_int (e
->elements
->length
));
2704 mem
= d_save_expr (mem
);
2706 /* Now copy the constructor into memory. */
2707 tree size
= size_mult_expr (size_int (e
->elements
->length
),
2708 size_int (tb
->nextOf ()->size ()));
2710 tree result
= build_memcpy_call (mem
, build_address (ctor
), size
);
2712 /* Return the array pointed to by MEM. */
2713 result
= compound_expr (result
, mem
);
2715 if (tb
->ty
== TY::Tarray
)
2716 result
= d_array_value (type
, size_int (e
->elements
->length
), result
);
2718 this->result_
= compound_expr (saved_elems
, result
);
2722 /* Build an associative array literal. The common type of the all keys is
2723 taken to be the key type, and common type of all values the value type.
2724 All keys and values are then implicitly converted as needed. */
2726 void visit (AssocArrayLiteralExp
*e
) final override
2728 /* Want the mutable type for typeinfo reference. */
2729 Type
*tb
= e
->type
->toBasetype ()->mutableOf ();
2731 /* Handle empty assoc array literals. */
2732 TypeAArray
*ta
= tb
->isTypeAArray ();
2733 if (e
->keys
->length
== 0)
2735 this->result_
= build_constructor (build_ctype (ta
), NULL
);
2739 /* Build an expression that assigns all expressions in KEYS
2740 to a constructor. */
2741 tree akeys
= build_array_from_exprs (ta
->index
->sarrayOf (e
->keys
->length
),
2742 e
->keys
, this->constp_
);
2743 tree init
= stabilize_expr (&akeys
);
2745 /* Do the same with all expressions in VALUES. */
2746 tree avals
= build_array_from_exprs (ta
->next
->sarrayOf (e
->values
->length
),
2747 e
->values
, this->constp_
);
2748 init
= compound_expr (init
, stabilize_expr (&avals
));
2750 /* Generate: _d_assocarrayliteralTX (ti, keys, vals); */
2751 tree keys
= d_array_value (build_ctype (ta
->index
->arrayOf ()),
2752 size_int (e
->keys
->length
),
2753 build_address (akeys
));
2754 tree vals
= d_array_value (build_ctype (ta
->next
->arrayOf ()),
2755 size_int (e
->values
->length
),
2756 build_address (avals
));
2758 tree mem
= build_libcall (LIBCALL_ASSOCARRAYLITERALTX
, Type::tvoidptr
, 3,
2759 build_typeinfo (e
, ta
), keys
, vals
);
2761 /* Return an associative array pointed to by MEM. */
2762 tree aatype
= build_ctype (ta
);
2763 vec
<constructor_elt
, va_gc
> *ce
= NULL
;
2764 CONSTRUCTOR_APPEND_ELT (ce
, TYPE_FIELDS (aatype
), mem
);
2766 tree result
= build_nop (build_ctype (e
->type
),
2767 build_constructor (aatype
, ce
));
2768 this->result_
= compound_expr (init
, result
);
2771 /* Build a struct literal. */
2773 void visit (StructLiteralExp
*e
) final override
2775 /* Handle empty struct literals. */
2776 if (e
->elements
== NULL
|| e
->sd
->fields
.length
== 0)
2778 this->result_
= build_constructor (build_ctype (e
->type
), NULL
);
2782 /* Building sinit trees are delayed until after frontend semantic
2783 processing has complete. Build the static initializer now. */
2784 if (e
->useStaticInit
&& !this->constp_
&& !e
->sd
->isCsymbol ())
2786 tree init
= aggregate_initializer_decl (e
->sd
);
2788 /* If initializing a symbol, don't forget to set it. */
2791 tree var
= build_deref (e
->sym
);
2792 init
= compound_expr (modify_expr (var
, init
), var
);
2795 this->result_
= init
;
2799 /* Build a constructor that assigns the expressions in ELEMENTS
2800 at each field index that has been filled in. */
2801 vec
<constructor_elt
, va_gc
> *ve
= NULL
;
2802 tree saved_elems
= NULL_TREE
;
2804 /* CTFE may fill the hidden pointer by NullExp. */
2805 gcc_assert (e
->elements
->length
<= e
->sd
->fields
.length
);
2807 Type
*tb
= e
->type
->toBasetype ();
2808 gcc_assert (tb
->ty
== TY::Tstruct
);
2810 for (size_t i
= 0; i
< e
->elements
->length
; i
++)
2812 Expression
*exp
= (*e
->elements
)[i
];
2816 VarDeclaration
*field
= e
->sd
->fields
[i
];
2817 Type
*type
= exp
->type
->toBasetype ();
2818 Type
*ftype
= field
->type
->toBasetype ();
2819 tree value
= NULL_TREE
;
2821 if (ftype
->ty
== TY::Tsarray
&& !same_type_p (type
, ftype
))
2823 /* Initialize a static array with a single element. */
2824 tree elem
= build_expr (exp
, this->constp_
, true);
2825 saved_elems
= compound_expr (saved_elems
, stabilize_expr (&elem
));
2826 elem
= d_save_expr (elem
);
2828 if (initializer_zerop (elem
))
2829 value
= build_constructor (build_ctype (ftype
), NULL
);
2831 value
= build_array_from_val (ftype
, elem
);
2835 value
= convert_expr (build_expr (exp
, this->constp_
, true),
2836 exp
->type
, field
->type
);
2839 /* Split construction of values out of the constructor. */
2840 saved_elems
= compound_expr (saved_elems
, stabilize_expr (&value
));
2842 CONSTRUCTOR_APPEND_ELT (ve
, get_symbol_decl (field
), value
);
2845 /* Maybe setup hidden pointer to outer scope context. */
2846 if (e
->sd
->isNested () && e
->elements
->length
!= e
->sd
->fields
.length
2847 && this->constp_
== false)
2849 tree field
= get_symbol_decl (e
->sd
->vthis
);
2850 tree value
= build_vthis (e
->sd
);
2851 CONSTRUCTOR_APPEND_ELT (ve
, field
, value
);
2852 gcc_assert (e
->useStaticInit
== false);
2855 /* Build a constructor in the correct shape of the aggregate type. */
2856 tree ctor
= build_struct_literal (build_ctype (e
->type
), ve
);
2858 /* Nothing more to do for constant literals. */
2861 /* If the struct literal is a valid for static data. */
2862 if (TREE_CONSTANT (ctor
)
2863 && initializer_constant_valid_p (ctor
, TREE_TYPE (ctor
)))
2864 TREE_STATIC (ctor
) = 1;
2866 this->result_
= compound_expr (saved_elems
, ctor
);
2870 /* Construct the struct literal for run-time. */
2873 /* Store the result in a symbol to initialize the literal. */
2874 tree var
= build_deref (e
->sym
);
2875 ctor
= compound_expr (modify_expr (var
, ctor
), var
);
2877 else if (!this->literalp_
)
2879 /* Use memset to fill any alignment holes in the object. */
2880 if (!identity_compare_p (e
->sd
) || e
->sd
->isUnionDeclaration ())
2882 tree var
= build_local_temp (TREE_TYPE (ctor
));
2883 tree init
= build_memset_call (var
);
2884 /* Evaluate memset() first, then any saved element constructors. */
2885 saved_elems
= compound_expr (init
, saved_elems
);
2886 ctor
= compound_expr (modify_expr (var
, ctor
), var
);
2890 this->result_
= compound_expr (saved_elems
, ctor
);
2893 /* Build a null literal. */
2895 void visit (NullExp
*e
) final override
2897 this->result_
= build_typeof_null_value (e
->type
);
2900 /* Build a vector literal. */
2902 void visit (VectorExp
*e
) final override
2904 /* First handle array literal expressions. */
2905 if (e
->e1
->op
== EXP::arrayLiteral
)
2907 ArrayLiteralExp
*ale
= e
->e1
->isArrayLiteralExp ();
2908 vec
<constructor_elt
, va_gc
> *elms
= NULL
;
2909 bool constant_p
= true;
2910 tree type
= build_ctype (e
->type
);
2912 vec_safe_reserve (elms
, ale
->elements
->length
);
2913 for (size_t i
= 0; i
< ale
->elements
->length
; i
++)
2915 Expression
*expr
= ale
->getElement (i
);
2916 tree value
= d_convert (TREE_TYPE (type
),
2917 build_expr (expr
, this->constp_
, true));
2918 if (!CONSTANT_CLASS_P (value
))
2921 CONSTRUCTOR_APPEND_ELT (elms
, size_int (i
), value
);
2924 /* Build a VECTOR_CST from a constant vector constructor. */
2926 this->result_
= build_vector_from_ctor (type
, elms
);
2928 this->result_
= build_constructor (type
, elms
);
2930 else if (e
->e1
->type
->toBasetype ()->ty
== TY::Tsarray
)
2932 /* Build a vector representation from a static array. */
2933 this->result_
= convert_expr (build_expr (e
->e1
, this->constp_
),
2934 e
->e1
->type
, e
->type
);
2938 /* Build constructor from single value. */
2939 tree type
= build_ctype (e
->type
);
2940 tree value
= d_convert (TREE_TYPE (type
),
2941 build_expr (e
->e1
, this->constp_
, true));
2942 this->result_
= build_vector_from_val (type
, value
);
2946 /* Build a static array representation of a vector expression. */
2948 void visit (VectorArrayExp
*e
) final override
2950 this->result_
= convert_expr (build_expr (e
->e1
, this->constp_
, true),
2951 e
->e1
->type
, e
->type
);
2954 /* Build a static class literal, return its reference. */
2956 void visit (ClassReferenceExp
*e
) final override
2958 /* The result of build_new_class_expr is a RECORD_TYPE, we want
2960 tree var
= build_address (build_new_class_expr (e
));
2962 /* If the type of this literal is an interface, the we must add the
2963 interface offset to symbol. */
2966 TypeClass
*tc
= e
->type
->toBasetype ()->isTypeClass ();
2967 InterfaceDeclaration
*to
= tc
->sym
->isInterfaceDeclaration ();
2971 ClassDeclaration
*from
= e
->originalClass ();
2974 gcc_assert (to
->isBaseOf (from
, &offset
) != 0);
2977 var
= build_offset (var
, size_int (offset
));
2981 this->result_
= var
;
2984 /* Build an uninitialized value, generated from void initializers. */
2986 void visit (VoidInitExp
*e
) final override
2988 /* The front-end only generates these for the initializer of globals.
2989 Represent `void' as zeroes, regardless of the type's default value. */
2990 gcc_assert (this->constp_
);
2991 this->result_
= build_zero_cst (build_ctype (e
->type
));
2994 /* These expressions are mainly just a placeholders in the frontend.
2995 We shouldn't see them here. */
2997 void visit (ScopeExp
*e
) final override
2999 error_at (make_location_t (e
->loc
), "%qs is not an expression",
3001 this->result_
= error_mark_node
;
3004 void visit (TypeExp
*e
) final override
3006 error_at (make_location_t (e
->loc
), "type %qs is not an expression",
3008 this->result_
= error_mark_node
;
3013 /* Main entry point for ExprVisitor interface to generate code for
3014 the Expression AST class E. If CONST_P is true, then E is a
3015 constant expression. If LITERAL_P is true, then E is a value used
3016 in the initialization of another literal. */
3019 build_expr (Expression
*e
, bool const_p
, bool literal_p
)
3021 ExprVisitor v
= ExprVisitor (const_p
, literal_p
);
3022 location_t saved_location
= input_location
;
3024 input_location
= make_location_t (e
->loc
);
3026 tree expr
= v
.result ();
3027 input_location
= saved_location
;
3029 /* Check if initializer expression is valid constant. */
3030 if (const_p
&& !initializer_constant_valid_p (expr
, TREE_TYPE (expr
)))
3032 error_at (make_location_t (e
->loc
), "non-constant expression %qs",
3034 return error_mark_node
;
3040 /* Same as build_expr, but also calls destructors on any temporaries. */
3043 build_expr_dtor (Expression
*e
)
3045 /* Codegen can be improved by determining if no exceptions can be thrown
3046 between the ctor and dtor, and eliminating the ctor and dtor. */
3047 size_t saved_vars
= vec_safe_length (d_function_chain
->vars_in_scope
);
3048 tree result
= build_expr (e
);
3050 if (saved_vars
!= vec_safe_length (d_function_chain
->vars_in_scope
))
3052 result
= fold_build_cleanup_point_expr (TREE_TYPE (result
), result
);
3053 vec_safe_truncate (d_function_chain
->vars_in_scope
, saved_vars
);
3059 /* Same as build_expr_dtor, but handles the result of E as a return value. */
3062 build_return_dtor (Expression
*e
, Type
*type
, TypeFunction
*tf
)
3064 size_t saved_vars
= vec_safe_length (d_function_chain
->vars_in_scope
);
3065 tree result
= build_expr (e
);
3067 /* Convert for initializing the DECL_RESULT. */
3070 /* If we are returning a reference, take the address. */
3071 result
= convert_expr (result
, e
->type
, type
);
3072 result
= build_address (result
);
3075 result
= convert_for_rvalue (result
, e
->type
, type
);
3077 /* The decl to store the return expression. */
3078 tree decl
= DECL_RESULT (cfun
->decl
);
3080 /* Split comma expressions, so that the result is returned directly. */
3081 tree expr
= stabilize_expr (&result
);
3082 result
= build_assign (INIT_EXPR
, decl
, result
);
3083 result
= compound_expr (expr
, return_expr (result
));
3085 /* May nest the return expression inside the try/finally expression. */
3086 if (saved_vars
!= vec_safe_length (d_function_chain
->vars_in_scope
))
3088 result
= fold_build_cleanup_point_expr (TREE_TYPE (result
), result
);
3089 vec_safe_truncate (d_function_chain
->vars_in_scope
, saved_vars
);