Fix issue for pointers to anonymous types with -fdump-ada-spec
[official-gcc.git] / gcc / d / expr.cc
blob2a7fb690862ac785560502bcabc7312344e63469
1 /* expr.cc -- Lower D frontend expressions to GCC trees.
2 Copyright (C) 2015-2022 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)
7 any later version.
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/>. */
18 #include "config.h"
19 #include "system.h"
20 #include "coretypes.h"
22 #include "dmd/aggregate.h"
23 #include "dmd/ctfe.h"
24 #include "dmd/declaration.h"
25 #include "dmd/enum.h"
26 #include "dmd/expression.h"
27 #include "dmd/identifier.h"
28 #include "dmd/init.h"
29 #include "dmd/module.h"
30 #include "dmd/mtype.h"
31 #include "dmd/template.h"
33 #include "tree.h"
34 #include "fold-const.h"
35 #include "diagnostic.h"
36 #include "langhooks.h"
37 #include "tm.h"
38 #include "function.h"
39 #include "toplev.h"
40 #include "varasm.h"
41 #include "predict.h"
42 #include "stor-layout.h"
44 #include "d-tree.h"
47 /* Determine if type T is a struct that has a postblit. */
49 static bool
50 needs_postblit (Type *t)
52 t = t->baseElemOf ();
54 if (TypeStruct *ts = t->isTypeStruct ())
56 if (ts->sym->postblit)
57 return true;
60 return false;
63 /* Determine if type T is a struct that has a destructor. */
65 static bool
66 needs_dtor (Type *t)
68 t = t->baseElemOf ();
70 if (TypeStruct *ts = t->isTypeStruct ())
72 if (ts->sym->dtor)
73 return true;
76 return false;
79 /* Determine if expression E is a suitable lvalue. */
81 static bool
82 lvalue_p (Expression *e)
84 SliceExp *se = e->isSliceExp ();
85 if (se != NULL && se->e1->isLvalue ())
86 return true;
88 CastExp *ce = e->isCastExp ();
89 if (ce != NULL && ce->e1->isLvalue ())
90 return true;
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. */
98 static tree
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));
129 else
130 ret = fold_build2 (POINTER_DIFF_EXPR, ptrtype, arg0, arg1);
132 else
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);
141 else
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);
150 eptype = type;
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. */
161 static tree
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));
170 e1b = ce->e1;
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;
217 tree result_;
218 bool constp_;
219 bool literalp_;
221 public:
222 ExprVisitor (bool constp, bool literalp)
224 this->result_ = NULL_TREE;
225 this->constp_ = constp;
226 this->literalp_ = literalp;
229 tree result (void)
231 return this->result_;
234 /* Visitor interfaces, each Expression class should have
235 overridden the default. */
237 void visit (Expression *)
239 gcc_unreachable ();
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)
248 tree cond = convert_for_condition (build_expr (e->econd),
249 e->econd->type);
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)
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);
291 else
293 /* Compare the real and imaginary parts separately. */
294 tree req = build_float_identity (code, real_part (t1),
295 real_part (t2));
296 tree ieq = build_float_identity (code, imaginary_part (t1),
297 imaginary_part (t2));
299 if (code == EQ_EXPR)
300 this->result_ = build_boolop (TRUTH_ANDIF_EXPR, req, ieq);
301 else
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
318 /* For operands of other types, identity is defined as being the
319 same as equality expressions. */
320 tree t1 = build_expr (e->e1);
321 tree t2 = build_expr (e->e2);
322 this->result_ = d_convert (build_ctype (e->type),
323 build_boolop (code, t1, t2));
327 /* Build an equality expression, which compare the two operands for either
328 equality or inequality. Operands go through the usual conversions to bring
329 them to a common type before comparison. The result type is bool. */
331 void visit (EqualExp *e)
333 Type *tb1 = e->e1->type->toBasetype ();
334 Type *tb2 = e->e2->type->toBasetype ();
335 tree_code code = (e->op == EXP::equal) ? EQ_EXPR : NE_EXPR;
337 if ((tb1->ty == TY::Tsarray || tb1->ty == TY::Tarray)
338 && (tb2->ty == TY::Tsarray || tb2->ty == TY::Tarray))
340 /* For static and dynamic arrays, equality is defined as the lengths of
341 the arrays matching, and all the elements are equal. */
342 Type *t1elem = tb1->nextOf ()->toBasetype ();
343 Type *t2elem = tb1->nextOf ()->toBasetype ();
345 /* Check if comparisons of arrays can be optimized using memcmp.
346 This will inline EQ expressions as:
347 e1.length == e2.length && memcmp(e1.ptr, e2.ptr, size) == 0;
348 Or when generating a NE expression:
349 e1.length != e2.length || memcmp(e1.ptr, e2.ptr, size) != 0; */
350 if ((t1elem->isintegral () || t1elem->ty == TY::Tvoid
351 || (t1elem->ty == TY::Tstruct
352 && !t1elem->isTypeStruct ()->sym->xeq))
353 && t1elem->ty == t2elem->ty)
355 tree t1 = d_array_convert (e->e1);
356 tree t2 = d_array_convert (e->e2);
357 tree result;
359 /* Make temporaries to prevent multiple evaluations. */
360 tree t1saved = d_save_expr (t1);
361 tree t2saved = d_save_expr (t2);
363 /* Length of arrays, for comparisons done before calling memcmp. */
364 tree t1len = d_array_length (t1saved);
365 tree t2len = d_array_length (t2saved);
367 /* Reference to array data. */
368 tree t1ptr = d_array_ptr (t1saved);
369 tree t2ptr = d_array_ptr (t2saved);
371 /* Compare arrays using memcmp if possible, otherwise for structs,
372 each field is compared inline. */
373 if (t1elem->ty != TY::Tstruct
374 || identity_compare_p (t1elem->isTypeStruct ()->sym))
376 tree size = size_mult_expr (t1len, size_int (t1elem->size ()));
378 result = build_memcmp_call (t1ptr, t2ptr, size);
379 result = build_boolop (code, result, integer_zero_node);
381 else
383 StructDeclaration *sd = t1elem->isTypeStruct ()->sym;
385 result = build_array_struct_comparison (code, sd, t1len,
386 t1ptr, t2ptr);
389 /* Check array length first before passing to memcmp.
390 For equality expressions, this becomes:
391 (e1.length == 0 || memcmp);
392 Otherwise for inequality:
393 (e1.length != 0 && memcmp); */
394 tree tsizecmp = build_boolop (code, t1len, size_zero_node);
395 if (e->op == EXP::equal)
396 result = build_boolop (TRUTH_ORIF_EXPR, tsizecmp, result);
397 else
398 result = build_boolop (TRUTH_ANDIF_EXPR, tsizecmp, result);
400 /* Finally, check if lengths of both arrays match if dynamic.
401 The frontend should have already guaranteed that static arrays
402 have same size. */
403 if (tb1->ty == TY::Tsarray && tb2->ty == TY::Tsarray)
404 gcc_assert (tb1->size () == tb2->size ());
405 else
407 tree tlencmp = build_boolop (code, t1len, t2len);
408 if (e->op == EXP::equal)
409 result = build_boolop (TRUTH_ANDIF_EXPR, tlencmp, result);
410 else
411 result = build_boolop (TRUTH_ORIF_EXPR, tlencmp, result);
414 /* Ensure left-to-right order of evaluation. */
415 if (TREE_SIDE_EFFECTS (t2))
416 result = compound_expr (t2saved, result);
418 if (TREE_SIDE_EFFECTS (t1))
419 result = compound_expr (t1saved, result);
421 this->result_ = result;
423 else
425 /* Use _adEq2() to compare each element. */
426 Type *t1array = t1elem->arrayOf ();
427 tree result = build_libcall (LIBCALL_ADEQ2, e->type, 3,
428 d_array_convert (e->e1),
429 d_array_convert (e->e2),
430 build_typeinfo (e->loc, t1array));
432 if (e->op == EXP::notEqual)
433 result = build1 (TRUTH_NOT_EXPR, build_ctype (e->type), result);
435 this->result_ = result;
438 else if (TypeStruct *ts = tb1->isTypeStruct ())
440 /* Equality for struct objects means the logical product of all
441 equality results of the corresponding object fields. */
442 tree t1 = build_expr (e->e1);
443 tree t2 = build_expr (e->e2);
445 gcc_assert (same_type_p (tb1, tb2));
447 this->result_ = build_struct_comparison (code, ts->sym, t1, t2);
449 else if (tb1->ty == TY::Taarray && tb2->ty == TY::Taarray)
451 /* Use _aaEqual() for associative arrays. */
452 tree result = build_libcall (LIBCALL_AAEQUAL, e->type, 3,
453 build_typeinfo (e->loc, tb1),
454 build_expr (e->e1),
455 build_expr (e->e2));
457 if (e->op == EXP::notEqual)
458 result = build1 (TRUTH_NOT_EXPR, build_ctype (e->type), result);
460 this->result_ = result;
462 else
464 /* For operands of other types, equality is defined as the bit pattern
465 of the type matches exactly. */
466 tree t1 = build_expr (e->e1);
467 tree t2 = build_expr (e->e2);
469 this->result_ = d_convert (build_ctype (e->type),
470 build_boolop (code, t1, t2));
474 /* Build an `in' expression. This is a condition to see if an element
475 exists in an associative array. The result is a pointer to the
476 element, or null if false. */
478 void visit (InExp *e)
480 Type *tb2 = e->e2->type->toBasetype ();
481 Type *tkey = tb2->isTypeAArray ()->index->toBasetype ();
482 tree key = convert_expr (build_expr (e->e1), e->e1->type, tkey);
484 /* Build a call to _aaInX(). */
485 this->result_ = build_libcall (LIBCALL_AAINX, e->type, 3,
486 build_expr (e->e2),
487 build_typeinfo (e->loc, tkey),
488 build_address (key));
491 /* Build a relational expression. The result type is bool. */
493 void visit (CmpExp *e)
495 Type *tb1 = e->e1->type->toBasetype ();
496 Type *tb2 = e->e2->type->toBasetype ();
498 tree result;
499 tree_code code;
501 switch (e->op)
503 case EXP::lessOrEqual:
504 code = LE_EXPR;
505 break;
507 case EXP::lessThan:
508 code = LT_EXPR;
509 break;
511 case EXP::greaterOrEqual:
512 code = GE_EXPR;
513 break;
515 case EXP::greaterThan:
516 code = GT_EXPR;
517 break;
519 default:
520 gcc_unreachable ();
523 /* For static and dynamic arrays, the relational op is turned into a
524 library call. It is not lowered during codegen. */
525 if ((tb1->ty == TY::Tsarray || tb1->ty == TY::Tarray)
526 && (tb2->ty == TY::Tsarray || tb2->ty == TY::Tarray))
528 error ("cannot handle comparison of type %<%s == %s%>",
529 tb1->toChars (), tb2->toChars ());
530 gcc_unreachable ();
533 /* Simple comparison. */
534 result = build_boolop (code, build_expr (e->e1), build_expr (e->e2));
535 this->result_ = d_convert (build_ctype (e->type), result);
538 /* Build a logical `and if' or `or if' expression. If the right operand
539 expression is void, then the resulting type is void. Otherwise the
540 result is bool. */
542 void visit (LogicalExp *e)
544 tree_code code = (e->op == EXP::andAnd) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
546 if (e->e2->type->toBasetype ()->ty != TY::Tvoid)
548 tree t1 = build_expr (e->e1);
549 tree t2 = build_expr (e->e2);
551 t1 = convert_for_condition (t1, e->e1->type);
552 t2 = convert_for_condition (t2, e->e2->type);
554 this->result_ = d_convert (build_ctype (e->type),
555 build_boolop (code, t1, t2));
557 else
559 tree t1 = convert_for_condition (build_expr (e->e1), e->e1->type);
560 tree t2 = build_expr_dtor (e->e2);
562 /* Invert condition for logical or if expression. */
563 if (e->op == EXP::orOr)
564 t1 = build1 (TRUTH_NOT_EXPR, d_bool_type, t1);
566 this->result_ = build_condition (build_ctype (e->type),
567 t1, t2, void_node);
571 /* Build a binary operand expression. Operands go through usual arithmetic
572 conversions to bring them to a common type before evaluating. */
574 void visit (BinExp *e)
576 tree_code code;
578 switch (e->op)
580 case EXP::add:
581 case EXP::min:
582 if ((e->e1->type->isreal () && e->e2->type->isimaginary ())
583 || (e->e1->type->isimaginary () && e->e2->type->isreal ()))
585 /* If the result is complex, then we can shortcut binary_op.
586 Frontend should have already validated types and sizes. */
587 tree t1 = build_expr (e->e1);
588 tree t2 = build_expr (e->e2);
590 if (e->op == EXP::min)
591 t2 = build1 (NEGATE_EXPR, TREE_TYPE (t2), t2);
593 if (e->e1->type->isreal ())
594 this->result_ = complex_expr (build_ctype (e->type), t1, t2);
595 else
596 this->result_ = complex_expr (build_ctype (e->type), t2, t1);
598 return;
600 else
601 code = (e->op == EXP::add)
602 ? PLUS_EXPR : MINUS_EXPR;
603 break;
605 case EXP::mul:
606 code = MULT_EXPR;
607 break;
609 case EXP::div:
610 /* Determine if the div expression is a lowered pointer diff operation.
611 The front-end rewrites `(p1 - p2)' into `(p1 - p2) / stride'. */
612 if (MinExp *me = e->e1->isMinExp ())
614 if (me->e1->type->ty == TY::Tpointer
615 && me->e2->type->ty == TY::Tpointer
616 && e->e2->op == EXP::int64)
618 code = EXACT_DIV_EXPR;
619 break;
623 code = e->e1->type->isintegral ()
624 ? TRUNC_DIV_EXPR : RDIV_EXPR;
625 break;
627 case EXP::mod:
628 code = e->e1->type->isfloating ()
629 ? FLOAT_MOD_EXPR : TRUNC_MOD_EXPR;
630 break;
632 case EXP::and_:
633 code = BIT_AND_EXPR;
634 break;
636 case EXP::or_:
637 code = BIT_IOR_EXPR;
638 break;
640 case EXP::xor_:
641 code = BIT_XOR_EXPR;
642 break;
644 case EXP::leftShift:
645 code = LSHIFT_EXPR;
646 break;
648 case EXP::rightShift:
649 code = RSHIFT_EXPR;
650 break;
652 case EXP::unsignedRightShift:
653 code = UNSIGNED_RSHIFT_EXPR;
654 break;
656 default:
657 gcc_unreachable ();
660 this->result_ = binary_op (code, build_ctype (e->type),
661 build_expr (e->e1), build_expr (e->e2));
665 /* Build a concat expression, which concatenates two or more arrays of the
666 same type, producing a dynamic array with the result. If one operand
667 is an element type, that element is converted to an array of length 1. */
669 void visit (CatExp *e)
671 Type *tb1 = e->e1->type->toBasetype ();
672 Type *tb2 = e->e2->type->toBasetype ();
673 Type *etype;
675 if (tb1->ty == TY::Tarray || tb1->ty == TY::Tsarray)
676 etype = tb1->nextOf ();
677 else
678 etype = tb2->nextOf ();
680 tree result;
682 if (e->e1->op == EXP::concatenate)
684 /* Flatten multiple concatenations to an array.
685 So the expression ((a ~ b) ~ c) becomes [a, b, c] */
686 int ndims = 2;
688 for (Expression *ex = e->e1; ex->op == EXP::concatenate;)
690 if (ex->op == EXP::concatenate)
692 ex = ex->isCatExp ()->e1;
693 ndims++;
697 /* Store all concatenation args to a temporary byte[][ndims] array. */
698 Type *targselem = Type::tint8->arrayOf ();
699 tree var = build_local_temp (make_array_type (targselem, ndims));
701 /* Loop through each concatenation from right to left. */
702 vec <constructor_elt, va_gc> *elms = NULL;
703 CatExp *ce = e;
704 int dim = ndims - 1;
706 for (Expression *oe = ce->e2; oe != NULL;
707 (ce->e1->op != EXP::concatenate
708 ? (oe = ce->e1)
709 : (ce = ce->e1->isCatExp (), oe = ce->e2)))
711 tree arg = d_array_convert (etype, oe);
712 tree index = size_int (dim);
713 CONSTRUCTOR_APPEND_ELT (elms, index, d_save_expr (arg));
715 /* Finished pushing all arrays. */
716 if (oe == ce->e1)
717 break;
719 dim -= 1;
722 /* Check there is no logic bug in constructing byte[][] of arrays. */
723 gcc_assert (dim == 0);
724 tree init = build_constructor (TREE_TYPE (var), elms);
725 var = compound_expr (modify_expr (var, init), var);
727 tree arrs = d_array_value (build_ctype (targselem->arrayOf ()),
728 size_int (ndims), build_address (var));
730 result = build_libcall (LIBCALL_ARRAYCATNTX, e->type, 2,
731 build_typeinfo (e->loc, e->type), arrs);
733 else
735 /* Handle single concatenation (a ~ b). */
736 result = build_libcall (LIBCALL_ARRAYCATT, e->type, 3,
737 build_typeinfo (e->loc, e->type),
738 d_array_convert (etype, e->e1),
739 d_array_convert (etype, e->e2));
742 this->result_ = result;
745 /* Build an assignment operator expression. The right operand is implicitly
746 converted to the type of the left operand, and assigned to it. */
748 void visit (BinAssignExp *e)
750 tree_code code;
751 Expression *e1b = e->e1;
753 switch (e->op)
755 case EXP::addAssign:
756 code = PLUS_EXPR;
757 break;
759 case EXP::minAssign:
760 code = MINUS_EXPR;
761 break;
763 case EXP::mulAssign:
764 code = MULT_EXPR;
765 break;
767 case EXP::divAssign:
768 code = e->e1->type->isintegral ()
769 ? TRUNC_DIV_EXPR : RDIV_EXPR;
770 break;
772 case EXP::modAssign:
773 code = e->e1->type->isfloating ()
774 ? FLOAT_MOD_EXPR : TRUNC_MOD_EXPR;
775 break;
777 case EXP::andAssign:
778 code = BIT_AND_EXPR;
779 break;
781 case EXP::orAssign:
782 code = BIT_IOR_EXPR;
783 break;
785 case EXP::xorAssign:
786 code = BIT_XOR_EXPR;
787 break;
789 case EXP::powAssign:
790 gcc_unreachable ();
792 case EXP::leftShiftAssign:
793 code = LSHIFT_EXPR;
794 break;
796 case EXP::rightShiftAssign:
797 case EXP::unsignedRightShiftAssign:
798 /* Use the original lhs type before it was promoted. The left operand
799 of `>>>=' does not undergo integral promotions before shifting.
800 Strip off casts just incase anyway. */
801 while (e1b->op == EXP::cast_)
803 CastExp *ce = e1b->isCastExp ();
804 gcc_assert (same_type_p (ce->type, ce->to));
805 e1b = ce->e1;
807 code = (e->op == EXP::rightShiftAssign) ? RSHIFT_EXPR : UNSIGNED_RSHIFT_EXPR;
808 break;
810 default:
811 gcc_unreachable ();
814 tree exp = binop_assignment (code, e1b, e->e2);
815 this->result_ = convert_expr (exp, e1b->type, e->type);
818 /* Build a concat assignment expression. The right operand is appended
819 to the left operand. */
821 void visit (CatAssignExp *e)
823 Type *tb1 = e->e1->type->toBasetype ();
824 Type *tb2 = e->e2->type->toBasetype ();
825 Type *etype = tb1->nextOf ()->toBasetype ();
827 /* Save the address of `e1', so it can be evaluated first.
828 As all D run-time library functions for concat assignments update `e1'
829 in-place and then return its value, the saved address can also be used as
830 the result of this expression as well. */
831 tree lhs = build_expr (e->e1);
832 tree lexpr = stabilize_expr (&lhs);
833 tree ptr = d_save_expr (build_address (lhs));
834 tree result = NULL_TREE;
836 if (tb1->ty == TY::Tarray && tb2->ty == TY::Tdchar
837 && (etype->ty == TY::Tchar || etype->ty == TY::Twchar))
839 /* Append a dchar to a char[] or wchar[]:
840 The assignment is handled by the D run-time library, so only
841 need to call `_d_arrayappend[cw]d(&e1, e2)' */
842 libcall_fn libcall = (etype->ty == TY::Tchar)
843 ? LIBCALL_ARRAYAPPENDCD : LIBCALL_ARRAYAPPENDWD;
845 result = build_libcall (libcall, e->type, 2,
846 ptr, build_expr (e->e2));
848 else
850 gcc_assert (tb1->ty == TY::Tarray || tb2->ty == TY::Tsarray);
852 if ((tb2->ty == TY::Tarray || tb2->ty == TY::Tsarray)
853 && same_type_p (etype, tb2->nextOf ()->toBasetype ()))
855 /* Append an array to another array:
856 The assignment is handled by the D run-time library, so only
857 need to call `_d_arrayappendT(ti, &e1, e2)' */
858 result = build_libcall (LIBCALL_ARRAYAPPENDT, e->type, 3,
859 build_typeinfo (e->loc, e->type),
860 ptr, d_array_convert (e->e2));
862 else if (same_type_p (etype, tb2))
864 /* Append an element to an array:
865 The assignment is generated inline, so need to handle temporaries
866 here, and ensure that they are evaluated in the correct order.
868 The generated code should end up being equivalent to:
869 _d_arrayappendcTX(ti, &e1, 1)[e1.length - 1] = e2
871 tree callexp = build_libcall (LIBCALL_ARRAYAPPENDCTX, e->type, 3,
872 build_typeinfo (e->loc, e->type),
873 ptr, size_one_node);
874 callexp = d_save_expr (callexp);
876 /* Assign e2 to last element. */
877 tree offexp = d_array_length (callexp);
878 offexp = build2 (MINUS_EXPR, TREE_TYPE (offexp),
879 offexp, size_one_node);
881 tree ptrexp = d_array_ptr (callexp);
882 ptrexp = void_okay_p (ptrexp);
883 ptrexp = build_array_index (ptrexp, offexp);
885 /* Evaluate expression before appending. */
886 tree rhs = build_expr (e->e2);
887 tree rexpr = stabilize_expr (&rhs);
889 if (TREE_CODE (rhs) == CALL_EXPR)
890 rhs = force_target_expr (rhs);
892 result = modify_expr (build_deref (ptrexp), rhs);
893 result = compound_expr (rexpr, result);
895 else
896 gcc_unreachable ();
899 /* Construct in order: ptr = &e1, _d_arrayappend(ptr, e2), *ptr; */
900 result = compound_expr (compound_expr (lexpr, ptr), result);
901 this->result_ = compound_expr (result, build_deref (ptr));
904 /* Build an assignment expression. The right operand is implicitly
905 converted to the type of the left operand, and assigned to it. */
907 void visit (AssignExp *e)
909 /* First, handle special assignment semantics. */
911 /* Look for array.length = n; */
912 if (e->e1->op == EXP::arrayLength)
914 /* This case should have been rewritten to `_d_arraysetlengthT` in the
915 semantic phase. */
916 gcc_unreachable ();
919 /* Look for array[] = n; */
920 if (e->e1->op == EXP::slice)
922 SliceExp *se = e->e1->isSliceExp ();
923 Type *stype = se->e1->type->toBasetype ();
924 Type *etype = stype->nextOf ()->toBasetype ();
926 /* Determine if we need to run postblit or dtor. */
927 bool postblit = needs_postblit (etype) && lvalue_p (e->e2);
928 bool destructor = needs_dtor (etype);
930 if (e->memset == MemorySet::blockAssign)
932 /* Set a range of elements to one value. */
933 tree t1 = build_expr (e->e1);
934 tree t2 = build_expr (e->e2);
935 tree result;
937 /* Extract any array bounds checks from the slice expression. */
938 tree init = stabilize_expr (&t1);
939 t1 = d_save_expr (t1);
941 if ((postblit || destructor) && e->op != EXP::blit)
943 /* Need to call postblit/destructor as part of assignment.
944 Construction has already been handled by the front-end. */
945 gcc_assert (e->op != EXP::construct);
947 /* So we can call postblits on const/immutable objects. */
948 Type *tm = etype->unSharedOf ()->mutableOf ();
949 tree ti = build_typeinfo (e->loc, tm);
951 /* Generate: _d_arraysetassign (t1.ptr, &t2, t1.length, ti); */
952 result = build_libcall (LIBCALL_ARRAYSETASSIGN, Type::tvoid, 4,
953 d_array_ptr (t1),
954 build_address (t2),
955 d_array_length (t1), ti);
957 else if (integer_zerop (t2))
959 tree size = size_mult_expr (d_array_length (t1),
960 size_int (etype->size ()));
961 result = build_memset_call (d_array_ptr (t1), size);
963 else
964 result = build_array_set (d_array_ptr (t1),
965 d_array_length (t1), t2);
967 result = compound_expr (init, result);
968 this->result_ = compound_expr (result, t1);
970 else
972 /* Perform a memcpy operation. */
973 gcc_assert (e->e2->type->ty != TY::Tpointer);
975 if (!postblit && !destructor)
977 tree t1 = d_save_expr (d_array_convert (e->e1));
978 tree t2 = d_save_expr (d_array_convert (e->e2));
980 /* References to array data. */
981 tree t1ptr = d_array_ptr (t1);
982 tree t1len = d_array_length (t1);
983 tree t2ptr = d_array_ptr (t2);
985 /* Generate: memcpy(to, from, size) */
986 tree size = size_mult_expr (t1len, size_int (etype->size ()));
987 tree result = build_memcpy_call (t1ptr, t2ptr, size);
989 /* Insert check that array lengths match and do not overlap. */
990 if (array_bounds_check ())
992 /* tlencmp = (t1len == t2len) */
993 tree t2len = d_array_length (t2);
994 tree tlencmp = build_boolop (EQ_EXPR, t1len, t2len);
996 /* toverlap = (t1ptr + size <= t2ptr
997 || t2ptr + size <= t1ptr) */
998 tree t1ptrcmp = build_boolop (LE_EXPR,
999 build_offset (t1ptr, size),
1000 t2ptr);
1001 tree t2ptrcmp = build_boolop (LE_EXPR,
1002 build_offset (t2ptr, size),
1003 t1ptr);
1004 tree toverlap = build_boolop (TRUTH_ORIF_EXPR, t1ptrcmp,
1005 t2ptrcmp);
1007 /* (tlencmp && toverlap) ? memcpy() : _d_arraybounds() */
1008 tree tassert = build_array_bounds_call (e->loc);
1009 tree tboundscheck = build_boolop (TRUTH_ANDIF_EXPR,
1010 tlencmp, toverlap);
1012 result = build_condition (void_type_node, tboundscheck,
1013 result, tassert);
1016 this->result_ = compound_expr (result, t1);
1018 else if ((postblit || destructor)
1019 && e->op != EXP::blit && e->op != EXP::construct)
1021 /* Generate: _d_arrayassign(ti, from, to); */
1022 this->result_ = build_libcall (LIBCALL_ARRAYASSIGN, e->type, 3,
1023 build_typeinfo (e->loc, etype),
1024 d_array_convert (e->e2),
1025 d_array_convert (e->e1));
1027 else
1029 /* Generate: _d_arraycopy() */
1030 this->result_ = build_libcall (LIBCALL_ARRAYCOPY, e->type, 3,
1031 size_int (etype->size ()),
1032 d_array_convert (e->e2),
1033 d_array_convert (e->e1));
1037 return;
1040 /* Look for reference initializations. */
1041 if (e->memset == MemorySet::referenceInit)
1043 gcc_assert (e->op == EXP::construct || e->op == EXP::blit);
1044 gcc_assert (e->e1->op == EXP::variable);
1046 Declaration *decl = e->e1->isVarExp ()->var;
1047 if (decl->storage_class & (STCout | STCref))
1049 tree t2 = convert_for_assignment (build_expr (e->e2),
1050 e->e2->type, e->e1->type);
1051 tree t1 = build_expr (e->e1);
1052 /* Want reference to lhs, not indirect ref. */
1053 t1 = TREE_OPERAND (t1, 0);
1054 t2 = build_address (t2);
1056 this->result_ = indirect_ref (build_ctype (e->type),
1057 build_assign (INIT_EXPR, t1, t2));
1058 return;
1062 /* Other types of assignments that may require post construction. */
1063 Type *tb1 = e->e1->type->toBasetype ();
1064 tree_code modifycode = (e->op == EXP::construct) ? INIT_EXPR : MODIFY_EXPR;
1066 /* Look for struct assignment. */
1067 if (tb1->ty == TY::Tstruct)
1069 tree t1 = build_expr (e->e1);
1070 tree t2 = convert_for_assignment (build_expr (e->e2, false, true),
1071 e->e2->type, e->e1->type);
1072 StructDeclaration *sd = tb1->isTypeStruct ()->sym;
1074 /* Look for struct = 0. */
1075 if (e->e2->op == EXP::int64)
1077 /* Use memset to fill struct. */
1078 gcc_assert (e->op == EXP::blit);
1079 tree result = build_memset_call (t1);
1081 /* Maybe set-up hidden pointer to outer scope context. */
1082 if (sd->isNested ())
1084 tree field = get_symbol_decl (sd->vthis);
1085 tree value = build_vthis (sd);
1087 tree vthis_exp = modify_expr (component_ref (t1, field), value);
1088 result = compound_expr (result, vthis_exp);
1091 this->result_ = compound_expr (result, t1);
1093 else
1095 /* Simple struct literal assignment. */
1096 tree init = NULL_TREE;
1098 /* Fill any alignment holes in the struct using memset. */
1099 if ((e->op == EXP::construct
1100 || (e->e2->op == EXP::structLiteral && e->op == EXP::blit))
1101 && (sd->isUnionDeclaration () || !identity_compare_p (sd)))
1103 t1 = stabilize_reference (t1);
1104 init = build_memset_call (t1);
1107 /* Elide generating assignment if init is all zeroes. */
1108 if (init != NULL_TREE && initializer_zerop (t2))
1109 this->result_ = compound_expr (init, t1);
1110 else
1112 tree result = build_assign (modifycode, t1, t2);
1113 this->result_ = compound_expr (init, result);
1117 return;
1120 /* Look for static array assignment. */
1121 if (tb1->ty == TY::Tsarray)
1123 /* Look for array = 0. */
1124 if (e->e2->op == EXP::int64)
1126 /* Use memset to fill the array. */
1127 gcc_assert (e->op == EXP::blit);
1128 this->result_ = build_memset_call (build_expr (e->e1));
1129 return;
1132 Type *etype = tb1->nextOf ();
1133 gcc_assert (e->e2->type->toBasetype ()->ty == TY::Tsarray);
1135 /* Determine if we need to run postblit. */
1136 const bool postblit = needs_postblit (etype);
1137 const bool destructor = needs_dtor (etype);
1138 const bool lvalue = lvalue_p (e->e2);
1140 /* Optimize static array assignment with array literal. Even if the
1141 elements in rhs are all rvalues and don't have to call postblits,
1142 this assignment should call dtors on old assigned elements. */
1143 if ((!postblit && !destructor)
1144 || (e->op == EXP::construct && e->e2->op == EXP::arrayLiteral)
1145 || (e->op == EXP::construct && !lvalue && postblit)
1146 || (e->op == EXP::blit || e->e1->type->size () == 0))
1148 tree t1 = build_expr (e->e1);
1149 tree t2 = convert_for_assignment (build_expr (e->e2),
1150 e->e2->type, e->e1->type);
1152 this->result_ = build_assign (modifycode, t1, t2);
1153 return;
1156 /* All other kinds of lvalue or rvalue static array assignment.
1157 Array construction has already been handled by the front-end. */
1158 gcc_assert (e->op != EXP::construct);
1160 /* Generate: _d_arrayassign_l()
1161 or: _d_arrayassign_r() */
1162 libcall_fn libcall = (lvalue)
1163 ? LIBCALL_ARRAYASSIGN_L : LIBCALL_ARRAYASSIGN_R;
1164 tree elembuf = build_local_temp (build_ctype (etype));
1165 Type *arrtype = (e->type->ty == TY::Tsarray)
1166 ? etype->arrayOf () : e->type;
1167 tree result = build_libcall (libcall, arrtype, 4,
1168 build_typeinfo (e->loc, etype),
1169 d_array_convert (e->e2),
1170 d_array_convert (e->e1),
1171 build_address (elembuf));
1173 /* Cast the libcall result back to a static array. */
1174 if (e->type->ty == TY::Tsarray)
1175 result = indirect_ref (build_ctype (e->type),
1176 d_array_ptr (result));
1178 this->result_ = result;
1179 return;
1182 /* Simple assignment. */
1183 tree t1 = build_expr (e->e1);
1184 tree t2 = convert_for_assignment (build_expr (e->e2),
1185 e->e2->type, e->e1->type);
1187 this->result_ = build_assign (modifycode, t1, t2);
1190 /* Build a throw expression. */
1192 void visit (ThrowExp *e)
1194 tree arg = build_expr_dtor (e->e1);
1195 this->result_ = build_libcall (LIBCALL_THROW, Type::tvoid, 1, arg);
1198 /* Build a postfix expression. */
1200 void visit (PostExp *e)
1202 tree result;
1204 if (e->op == EXP::plusPlus)
1206 result = build2 (POSTINCREMENT_EXPR, build_ctype (e->type),
1207 build_expr (e->e1), build_expr (e->e2));
1209 else if (e->op == EXP::minusMinus)
1211 result = build2 (POSTDECREMENT_EXPR, build_ctype (e->type),
1212 build_expr (e->e1), build_expr (e->e2));
1214 else
1215 gcc_unreachable ();
1217 TREE_SIDE_EFFECTS (result) = 1;
1218 this->result_ = result;
1221 /* Build an index expression. */
1223 void visit (IndexExp *e)
1225 Type *tb1 = e->e1->type->toBasetype ();
1227 if (tb1->ty == TY::Taarray)
1229 /* Get the key for the associative array. */
1230 Type *tkey = tb1->isTypeAArray ()->index->toBasetype ();
1231 tree key = convert_expr (build_expr (e->e2), e->e2->type, tkey);
1232 libcall_fn libcall;
1233 tree tinfo, ptr;
1235 if (e->modifiable)
1237 libcall = LIBCALL_AAGETY;
1238 ptr = build_address (build_expr (e->e1));
1239 tinfo = build_typeinfo (e->loc, tb1->unSharedOf ()->mutableOf ());
1241 else
1243 libcall = LIBCALL_AAGETRVALUEX;
1244 ptr = build_expr (e->e1);
1245 tinfo = build_typeinfo (e->loc, tkey);
1248 /* Index the associative array. */
1249 tree result = build_libcall (libcall, e->type->pointerTo (), 4,
1250 ptr, tinfo,
1251 size_int (tb1->nextOf ()->size ()),
1252 build_address (key));
1254 if (!e->indexIsInBounds && array_bounds_check ())
1256 tree tassert = build_array_bounds_call (e->loc);
1258 result = d_save_expr (result);
1259 result = build_condition (TREE_TYPE (result),
1260 d_truthvalue_conversion (result),
1261 result, tassert);
1264 this->result_ = indirect_ref (build_ctype (e->type), result);
1266 else
1268 /* Get the data pointer and length for static and dynamic arrays. */
1269 tree array = d_save_expr (build_expr (e->e1));
1270 tree ptr = convert_expr (array, tb1, tb1->nextOf ()->pointerTo ());
1272 tree length = NULL_TREE;
1273 if (tb1->ty != TY::Tpointer)
1274 length = get_array_length (array, tb1);
1275 else
1276 gcc_assert (e->lengthVar == NULL);
1278 /* The __dollar variable just becomes a placeholder for the
1279 actual length. */
1280 if (e->lengthVar)
1281 e->lengthVar->csym = length;
1283 /* Generate the index. */
1284 tree index = build_expr (e->e2);
1286 /* If it's a static array and the index is constant, the front end has
1287 already checked the bounds. */
1288 if (tb1->ty != TY::Tpointer)
1289 index = build_bounds_index_condition (e, index, length);
1291 /* Index the .ptr. */
1292 ptr = void_okay_p (ptr);
1293 this->result_ = indirect_ref (TREE_TYPE (TREE_TYPE (ptr)),
1294 build_array_index (ptr, index));
1298 /* Build a comma expression. The type is the type of the right operand. */
1300 void visit (CommaExp *e)
1302 tree t1 = build_expr (e->e1);
1303 tree t2 = build_expr (e->e2);
1304 tree type = e->type ? build_ctype (e->type) : void_type_node;
1306 this->result_ = build2 (COMPOUND_EXPR, type, t1, t2);
1309 /* Build an array length expression. Returns the number of elements
1310 in the array. The result is of type size_t. */
1312 void visit (ArrayLengthExp *e)
1314 if (e->e1->type->toBasetype ()->ty == TY::Tarray)
1315 this->result_ = d_array_length (build_expr (e->e1));
1316 else
1318 /* Static arrays have already been handled by the front-end. */
1319 error ("unexpected type for array length: %qs", e->type->toChars ());
1320 this->result_ = error_mark_node;
1324 /* Build a delegate pointer expression. This will return the frame
1325 pointer value as a type void*. */
1327 void visit (DelegatePtrExp *e)
1329 tree t1 = build_expr (e->e1);
1330 this->result_ = delegate_object (t1);
1333 /* Build a delegate function pointer expression. This will return the
1334 function pointer value as a function type. */
1336 void visit (DelegateFuncptrExp *e)
1338 tree t1 = build_expr (e->e1);
1339 this->result_ = delegate_method (t1);
1342 /* Build a slice expression. */
1344 void visit (SliceExp *e)
1346 Type *tb = e->type->toBasetype ();
1347 Type *tb1 = e->e1->type->toBasetype ();
1348 gcc_assert (tb->ty == TY::Tarray || tb->ty == TY::Tsarray);
1350 /* Use convert-to-dynamic-array code if possible. */
1351 if (!e->lwr)
1353 tree result = build_expr (e->e1);
1354 if (e->e1->type->toBasetype ()->ty == TY::Tsarray)
1355 result = convert_expr (result, e->e1->type, e->type);
1357 this->result_ = result;
1358 return;
1360 else
1361 gcc_assert (e->upr != NULL);
1363 /* Get the data pointer and length for static and dynamic arrays. */
1364 tree array = d_save_expr (build_expr (e->e1));
1365 tree ptr = convert_expr (array, tb1, tb1->nextOf ()->pointerTo ());
1366 tree length = NULL_TREE;
1368 /* Our array is already a SAVE_EXPR if necessary, so we don't make length
1369 a SAVE_EXPR which is, at most, a COMPONENT_REF on top of array. */
1370 if (tb1->ty != TY::Tpointer)
1371 length = get_array_length (array, tb1);
1372 else
1373 gcc_assert (e->lengthVar == NULL);
1375 /* The __dollar variable just becomes a placeholder for the
1376 actual length. */
1377 if (e->lengthVar)
1378 e->lengthVar->csym = length;
1380 /* Generate upper and lower bounds. */
1381 tree lwr_tree = d_save_expr (build_expr (e->lwr));
1382 tree upr_tree = d_save_expr (build_expr (e->upr));
1384 /* If the upper bound has any side effects, then the lower bound should be
1385 copied to a temporary always. */
1386 if (TREE_CODE (upr_tree) == SAVE_EXPR && TREE_CODE (lwr_tree) != SAVE_EXPR)
1387 lwr_tree = save_expr (lwr_tree);
1389 /* Adjust the .ptr offset. */
1390 if (!integer_zerop (lwr_tree))
1392 tree ptrtype = TREE_TYPE (ptr);
1393 ptr = build_array_index (void_okay_p (ptr), lwr_tree);
1394 ptr = build_nop (ptrtype, ptr);
1397 /* Nothing more to do for static arrays, their bounds checking has been
1398 done at compile-time. */
1399 if (tb->ty == TY::Tsarray)
1401 this->result_ = indirect_ref (build_ctype (e->type), ptr);
1402 return;
1404 else
1405 gcc_assert (tb->ty == TY::Tarray);
1407 /* Generate bounds checking code. */
1408 tree newlength = build_bounds_slice_condition (e, lwr_tree, upr_tree,
1409 length);
1410 tree result = d_array_value (build_ctype (e->type), newlength, ptr);
1411 this->result_ = compound_expr (array, result);
1414 /* Build a cast expression, which converts the given unary expression to the
1415 type of result. */
1417 void visit (CastExp *e)
1419 Type *ebtype = e->e1->type->toBasetype ();
1420 Type *tbtype = e->to->toBasetype ();
1421 tree result = build_expr (e->e1, this->constp_, this->literalp_);
1423 /* Just evaluate e1 if it has any side effects. */
1424 if (tbtype->ty == TY::Tvoid)
1425 this->result_ = build_nop (build_ctype (tbtype), result);
1426 else
1427 this->result_ = convert_for_rvalue (result, ebtype, tbtype);
1430 /* Build a delete expression. */
1432 void visit (DeleteExp *e)
1434 tree t1 = build_expr (e->e1);
1435 Type *tb1 = e->e1->type->toBasetype ();
1437 if (tb1->ty == TY::Tclass)
1439 /* For class object references, if there is a destructor for that class,
1440 the destructor is called for the object instance. */
1441 gcc_assert (e->e1->op == EXP::variable);
1443 VarDeclaration *v = e->e1->isVarExp ()->var->isVarDeclaration ();
1444 gcc_assert (v && v->onstack);
1446 libcall_fn libcall = tb1->isClassHandle ()->isInterfaceDeclaration ()
1447 ? LIBCALL_CALLINTERFACEFINALIZER : LIBCALL_CALLFINALIZER;
1449 this->result_ = build_libcall (libcall, Type::tvoid, 1, t1);
1450 return;
1452 else
1454 error ("don%'t know how to delete %qs", e->e1->toChars ());
1455 this->result_ = error_mark_node;
1459 /* Build a remove expression, which removes a particular key from an
1460 associative array. */
1462 void visit (RemoveExp *e)
1464 /* Check that the array is actually an associative array. */
1465 if (e->e1->type->toBasetype ()->ty == TY::Taarray)
1467 Type *tb = e->e1->type->toBasetype ();
1468 Type *tkey = tb->isTypeAArray ()->index->toBasetype ();
1469 tree index = convert_expr (build_expr (e->e2), e->e2->type, tkey);
1471 this->result_ = build_libcall (LIBCALL_AADELX, Type::tbool, 3,
1472 build_expr (e->e1),
1473 build_typeinfo (e->loc, tkey),
1474 build_address (index));
1476 else
1478 error ("%qs is not an associative array", e->e1->toChars ());
1479 this->result_ = error_mark_node;
1483 /* Build an unary not expression. */
1485 void visit (NotExp *e)
1487 tree result = convert_for_condition (build_expr (e->e1), e->e1->type);
1488 /* Need to convert to boolean type or this will fail. */
1489 result = fold_build1 (TRUTH_NOT_EXPR, d_bool_type, result);
1491 this->result_ = d_convert (build_ctype (e->type), result);
1494 /* Build a compliment expression, where all the bits in the value are
1495 complemented. Note: unlike in C, the usual integral promotions
1496 are not performed prior to the complement operation. */
1498 void visit (ComExp *e)
1500 TY ty1 = e->e1->type->toBasetype ()->ty;
1501 gcc_assert (ty1 != TY::Tarray && ty1 != TY::Tsarray);
1503 this->result_ = fold_build1 (BIT_NOT_EXPR, build_ctype (e->type),
1504 build_expr (e->e1));
1507 /* Build an unary negation expression. */
1509 void visit (NegExp *e)
1511 TY ty1 = e->e1->type->toBasetype ()->ty;
1512 gcc_assert (ty1 != TY::Tarray && ty1 != TY::Tsarray);
1514 tree type = build_ctype (e->type);
1515 tree expr = build_expr (e->e1);
1517 /* If the operation needs excess precision. */
1518 tree eptype = excess_precision_type (type);
1519 if (eptype != NULL_TREE)
1520 expr = d_convert (eptype, expr);
1521 else
1522 eptype = type;
1524 tree ret = fold_build1 (NEGATE_EXPR, eptype, expr);
1525 this->result_ = d_convert (type, ret);
1528 /* Build a pointer index expression. */
1530 void visit (PtrExp *e)
1532 Type *tnext = NULL;
1533 size_t offset;
1534 tree result;
1536 if (e->e1->op == EXP::add)
1538 AddExp *ae = e->e1->isAddExp ();
1539 if (ae->e1->op == EXP::address
1540 && ae->e2->isConst () && ae->e2->type->isintegral ())
1542 Expression *ex = ae->e1->isAddrExp ()->e1;
1543 tnext = ex->type->toBasetype ();
1544 result = build_expr (ex);
1545 offset = ae->e2->toUInteger ();
1548 else if (e->e1->op == EXP::symbolOffset)
1550 SymOffExp *se = e->e1->isSymOffExp ();
1551 if (!declaration_reference_p (se->var))
1553 tnext = se->var->type->toBasetype ();
1554 result = get_decl_tree (se->var);
1555 offset = se->offset;
1559 /* Produce better code by converting *(#record + n) to
1560 COMPONENT_REFERENCE. Otherwise, the variable will always be
1561 allocated in memory because its address is taken. */
1562 if (tnext && tnext->ty == TY::Tstruct)
1564 StructDeclaration *sd = tnext->isTypeStruct ()->sym;
1566 for (size_t i = 0; i < sd->fields.length; i++)
1568 VarDeclaration *field = sd->fields[i];
1570 if (field->offset == offset
1571 && same_type_p (field->type, e->type))
1573 /* Catch errors, backend will ICE otherwise. */
1574 if (error_operand_p (result))
1575 this->result_ = result;
1576 else
1578 result = component_ref (result, get_symbol_decl (field));
1579 this->result_ = result;
1581 return;
1583 else if (field->offset > offset)
1584 break;
1588 this->result_ = indirect_ref (build_ctype (e->type), build_expr (e->e1));
1591 /* Build an unary address expression. */
1593 void visit (AddrExp *e)
1595 tree type = build_ctype (e->type);
1596 tree exp;
1598 /* The frontend optimizer can convert const symbol into a struct literal.
1599 Taking the address of a struct literal is otherwise illegal. */
1600 if (e->e1->op == EXP::structLiteral)
1602 StructLiteralExp *sle = e->e1->isStructLiteralExp ()->origin;
1603 gcc_assert (sle != NULL);
1605 /* Build the reference symbol, the decl is built first as the
1606 initializer may have recursive references. */
1607 if (!sle->sym)
1609 sle->sym = build_artificial_decl (build_ctype (sle->type),
1610 NULL_TREE, "S");
1611 DECL_INITIAL (sle->sym) = build_expr (sle, true);
1612 d_pushdecl (sle->sym);
1613 rest_of_decl_compilation (sle->sym, 1, 0);
1616 exp = sle->sym;
1618 else
1619 exp = build_expr (e->e1, this->constp_, this->literalp_);
1621 TREE_CONSTANT (exp) = 0;
1622 this->result_ = d_convert (type, build_address (exp));
1625 /* Build a function call expression. */
1627 void visit (CallExp *e)
1629 Type *tb = e->e1->type->toBasetype ();
1630 Expression *e1b = e->e1;
1632 tree callee = NULL_TREE;
1633 tree object = NULL_TREE;
1634 tree cleanup = NULL_TREE;
1635 tree returnvalue = NULL_TREE;
1636 TypeFunction *tf = NULL;
1638 /* Calls to delegates can sometimes look like this. */
1639 if (e1b->op == EXP::comma)
1641 e1b = e1b->isCommaExp ()->e2;
1642 gcc_assert (e1b->op == EXP::variable);
1644 Declaration *var = e1b->isVarExp ()->var;
1645 gcc_assert (var->isFuncDeclaration () && !var->needThis ());
1648 if (e1b->op == EXP::dotVariable && tb->ty != TY::Tdelegate)
1650 DotVarExp *dve = e1b->isDotVarExp ();
1652 /* Don't modify the static initializer for struct literals. */
1653 if (dve->e1->op == EXP::structLiteral)
1655 StructLiteralExp *sle = dve->e1->isStructLiteralExp ();
1656 sle->useStaticInit = false;
1659 FuncDeclaration *fd = dve->var->isFuncDeclaration ();
1660 if (fd != NULL)
1662 /* Get the correct callee from the DotVarExp object. */
1663 tree fndecl = get_symbol_decl (fd);
1664 AggregateDeclaration *ad = fd->isThis ();
1666 /* Static method; ignore the object instance. */
1667 if (!ad)
1668 callee = build_address (fndecl);
1669 else
1671 tree thisexp = build_expr (dve->e1);
1673 /* When constructing temporaries, if the constructor throws,
1674 then the object is destructed even though it is not a fully
1675 constructed object yet. And so this call will need to be
1676 moved inside the TARGET_EXPR_INITIAL slot. */
1677 if (fd->isCtorDeclaration ()
1678 && TREE_CODE (thisexp) == COMPOUND_EXPR
1679 && TREE_CODE (TREE_OPERAND (thisexp, 0)) == TARGET_EXPR
1680 && TARGET_EXPR_CLEANUP (TREE_OPERAND (thisexp, 0)))
1682 cleanup = TREE_OPERAND (thisexp, 0);
1683 thisexp = TREE_OPERAND (thisexp, 1);
1686 if (TREE_CODE (thisexp) == CONSTRUCTOR)
1687 thisexp = force_target_expr (thisexp);
1689 /* Want reference to `this' object. */
1690 if (!POINTER_TYPE_P (TREE_TYPE (thisexp)))
1691 thisexp = build_address (thisexp);
1693 /* Make the callee a virtual call. */
1694 if (fd->isVirtual () && !fd->isFinalFunc () && !e->directcall)
1696 tree fntype = build_pointer_type (TREE_TYPE (fndecl));
1697 tree thistype = build_ctype (ad->handleType ());
1698 thisexp = build_nop (thistype, d_save_expr (thisexp));
1699 fndecl = build_vindex_ref (thisexp, fntype, fd->vtblIndex);
1701 else
1702 fndecl = build_address (fndecl);
1704 /* C++ constructors return void, even though front-end semantic
1705 treats them as implicitly returning `this'. Set returnvalue
1706 to override the result of this expression. */
1707 if (fd->isCtorDeclaration ())
1709 thisexp = d_save_expr (thisexp);
1710 returnvalue = thisexp;
1713 callee = build_method_call (fndecl, thisexp, fd->type);
1718 if (callee == NULL_TREE)
1719 callee = build_expr (e1b);
1721 if (METHOD_CALL_EXPR (callee))
1723 /* This could be a delegate expression (TY == Tdelegate), but not
1724 actually a delegate variable. */
1725 if (e1b->op == EXP::dotVariable)
1727 /* This gets the true function type, getting the function type
1728 from e1->type can sometimes be incorrect, such as when calling
1729 a `ref' return function. */
1730 tf = get_function_type (e1b->isDotVarExp ()->var->type);
1732 else
1733 tf = get_function_type (tb);
1735 extract_from_method_call (callee, callee, object);
1737 else if (tb->ty == TY::Tdelegate)
1739 /* Delegate call, extract .object and .funcptr from var. */
1740 callee = d_save_expr (callee);
1741 tf = get_function_type (tb);
1742 object = delegate_object (callee);
1743 callee = delegate_method (callee);
1745 else if (e1b->op == EXP::variable)
1747 FuncDeclaration *fd = e1b->isVarExp ()->var->isFuncDeclaration ();
1748 gcc_assert (fd != NULL);
1749 tf = get_function_type (fd->type);
1751 if (fd->isNested ())
1753 /* Maybe re-evaluate symbol storage treating `fd' as public. */
1754 if (call_by_alias_p (d_function_chain->function, fd))
1755 TREE_PUBLIC (callee) = 1;
1757 object = get_frame_for_symbol (fd);
1759 else if (fd->needThis ())
1761 error_at (make_location_t (e1b->loc),
1762 "need %<this%> to access member %qs", fd->toChars ());
1763 /* Continue compiling... */
1764 object = null_pointer_node;
1767 else
1769 /* Normal direct function call. */
1770 tf = get_function_type (tb);
1773 gcc_assert (tf != NULL);
1775 /* Now we have the type, callee and maybe object reference,
1776 build the call expression. */
1777 tree exp = d_build_call (tf, callee, object, e->arguments);
1779 if (returnvalue != NULL_TREE)
1780 exp = compound_expr (exp, returnvalue);
1782 if (tf->isref ())
1783 exp = build_deref (exp);
1785 /* Some library calls are defined to return a generic type.
1786 this->type is the real type we want to return. */
1787 if (e->type->isTypeBasic ())
1788 exp = d_convert (build_ctype (e->type), exp);
1790 /* If this call was found to be a constructor for a temporary with a
1791 cleanup, then move the call inside the TARGET_EXPR. */
1792 if (cleanup != NULL_TREE)
1794 tree init = TARGET_EXPR_INITIAL (cleanup);
1795 TARGET_EXPR_INITIAL (cleanup) = compound_expr (init, exp);
1797 /* Keep the return value outside the TARGET_EXPR. */
1798 if (returnvalue != NULL_TREE)
1799 cleanup = compound_expr (cleanup, TREE_OPERAND (exp, 1));
1801 exp = cleanup;
1804 this->result_ = exp;
1807 /* Build a delegate expression. */
1809 void visit (DelegateExp *e)
1811 if (e->func->semanticRun == PASS::semantic3done)
1813 /* Add the function as nested function if it belongs to this module.
1814 ie: it is a member of this module, or it is a template instance. */
1815 Dsymbol *owner = e->func->toParent ();
1816 while (!owner->isTemplateInstance () && owner->toParent ())
1817 owner = owner->toParent ();
1818 if (owner->isTemplateInstance () || owner == d_function_chain->module)
1819 build_decl_tree (e->func);
1822 tree fndecl;
1823 tree object;
1825 if (e->func->isNested () && !e->func->isThis ())
1827 if (e->e1->op == EXP::null_)
1828 object = build_expr (e->e1);
1829 else
1830 object = get_frame_for_symbol (e->func);
1832 fndecl = build_address (get_symbol_decl (e->func));
1834 else
1836 if (!e->func->isThis ())
1838 error ("delegates are only for non-static functions");
1839 this->result_ = error_mark_node;
1840 return;
1843 object = build_expr (e->e1);
1845 /* Want reference to `this' object. */
1846 if (e->e1->type->ty != TY::Tclass && e->e1->type->ty != TY::Tpointer)
1847 object = build_address (object);
1849 /* Object reference could be the outer `this' field of a class or
1850 closure of type `void*'. Cast it to the right type. */
1851 if (e->e1->type->ty == TY::Tclass)
1852 object = d_convert (build_ctype (e->e1->type), object);
1854 fndecl = get_symbol_decl (e->func);
1856 /* Get pointer to function out of the virtual table. */
1857 if (e->func->isVirtual () && !e->func->isFinalFunc ()
1858 && e->e1->op != EXP::super_ && e->e1->op != EXP::dotType)
1860 tree fntype = build_pointer_type (TREE_TYPE (fndecl));
1861 object = d_save_expr (object);
1862 fndecl = build_vindex_ref (object, fntype, e->func->vtblIndex);
1864 else
1865 fndecl = build_address (fndecl);
1868 this->result_ = build_method_call (fndecl, object, e->type);
1871 /* Build a type component expression. */
1873 void visit (DotTypeExp *e)
1875 /* Just a pass through to underlying expression. */
1876 this->result_ = build_expr (e->e1);
1879 /* Build a component reference expression. */
1881 void visit (DotVarExp *e)
1883 VarDeclaration *vd = e->var->isVarDeclaration ();
1885 /* This could also be a function, but relying on that being taken
1886 care of by the visitor interface for CallExp. */
1887 if (vd != NULL)
1889 if (!vd->isField ())
1890 this->result_ = get_decl_tree (vd);
1891 else
1893 tree object = build_expr (e->e1);
1894 Type *tb = e->e1->type->toBasetype ();
1896 if (tb->ty != TY::Tstruct)
1897 object = build_deref (object);
1899 /* __complex is represented as a struct in the front-end, but
1900 underlying is really a complex type. */
1901 if (e->e1->type->ty == TY::Tenum
1902 && e->e1->type->isTypeEnum ()->sym->isSpecial ())
1903 object = build_vconvert (build_ctype (tb), object);
1905 this->result_ = component_ref (object, get_symbol_decl (vd));
1908 else
1910 error ("%qs is not a field, but a %qs",
1911 e->var->toChars (), e->var->kind ());
1912 this->result_ = error_mark_node;
1916 /* Build an assert expression, used to declare conditions that must hold at
1917 that a given point in the program. */
1919 void visit (AssertExp *e)
1921 Type *tb1 = e->e1->type->toBasetype ();
1922 tree arg = build_expr (e->e1);
1923 tree tmsg = NULL_TREE;
1924 tree assert_pass = void_node;
1925 tree assert_fail;
1927 if (global.params.useAssert == CHECKENABLEon && !checkaction_trap_p ())
1929 /* Generate: ((bool) e1 ? (void)0 : _d_assert (...))
1930 or: (e1 != null ? e1._invariant() : _d_assert (...)) */
1931 bool unittest_p = d_function_chain->function->isUnitTestDeclaration ();
1932 libcall_fn libcall;
1934 if (e->msg)
1936 tmsg = build_expr_dtor (e->msg);
1937 libcall = unittest_p ? LIBCALL_UNITTEST_MSG : LIBCALL_ASSERT_MSG;
1939 else
1940 libcall = unittest_p ? LIBCALL_UNITTESTP : LIBCALL_ASSERTP;
1942 /* Build a call to _d_assert(). */
1943 assert_fail = build_assert_call (e->loc, libcall, tmsg);
1945 if (global.params.useInvariants == CHECKENABLEon)
1947 /* If the condition is a D class or struct object with an invariant,
1948 call it if the condition result is true. */
1949 if (tb1->ty == TY::Tclass)
1951 ClassDeclaration *cd = tb1->isClassHandle ();
1952 if (!cd->isInterfaceDeclaration () && !cd->isCPPclass ())
1954 arg = d_save_expr (arg);
1955 assert_pass = build_libcall (LIBCALL_INVARIANT,
1956 Type::tvoid, 1, arg);
1959 else if (tb1->ty == TY::Tpointer
1960 && tb1->nextOf ()->ty == TY::Tstruct)
1962 StructDeclaration *sd = tb1->nextOf ()->isTypeStruct ()->sym;
1963 if (sd->inv != NULL)
1965 Expressions args;
1966 arg = d_save_expr (arg);
1967 assert_pass = d_build_call_expr (sd->inv, arg, &args);
1972 else if (global.params.useAssert == CHECKENABLEon && checkaction_trap_p ())
1974 /* Generate: __builtin_trap() */
1975 tree fn = builtin_decl_explicit (BUILT_IN_TRAP);
1976 assert_fail = build_call_expr (fn, 0);
1978 else
1980 /* Assert contracts are turned off. */
1981 this->result_ = void_node;
1982 return;
1985 /* Build condition that we are asserting in this contract. */
1986 tree condition = convert_for_condition (arg, e->e1->type);
1988 /* We expect the condition to always be true, as what happens if an assert
1989 contract is false is undefined behavior. */
1990 tree fn = builtin_decl_explicit (BUILT_IN_EXPECT);
1991 tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
1992 tree pred_type = TREE_VALUE (arg_types);
1993 tree expected_type = TREE_VALUE (TREE_CHAIN (arg_types));
1995 condition = build_call_expr (fn, 2, d_convert (pred_type, condition),
1996 build_int_cst (expected_type, 1));
1997 condition = d_truthvalue_conversion (condition);
1999 this->result_ = build_vcondition (condition, assert_pass, assert_fail);
2002 /* Build a declaration expression. */
2004 void visit (DeclarationExp *e)
2006 /* Compile the declaration. */
2007 push_stmt_list ();
2008 build_decl_tree (e->declaration);
2009 tree result = pop_stmt_list ();
2011 /* Construction of an array for typesafe-variadic function arguments
2012 can cause an empty STMT_LIST here. This can causes problems
2013 during gimplification. */
2014 if (TREE_CODE (result) == STATEMENT_LIST && !STATEMENT_LIST_HEAD (result))
2015 result = build_empty_stmt (input_location);
2017 this->result_ = result;
2020 /* Build a typeid expression. Returns an instance of class TypeInfo
2021 corresponding to. */
2023 void visit (TypeidExp *e)
2025 if (Type *tid = isType (e->obj))
2027 tree ti = build_typeinfo (e->loc, tid);
2029 /* If the typeinfo is at an offset. */
2030 if (tid->vtinfo->offset)
2031 ti = build_offset (ti, size_int (tid->vtinfo->offset));
2033 this->result_ = build_nop (build_ctype (e->type), ti);
2035 else if (Expression *tid = isExpression (e->obj))
2037 Type *type = tid->type->toBasetype ();
2038 assert (type->ty == TY::Tclass);
2040 /* Generate **classptr to get the classinfo. */
2041 tree ci = build_expr (tid);
2042 ci = indirect_ref (ptr_type_node, ci);
2043 ci = indirect_ref (ptr_type_node, ci);
2045 /* Add extra indirection for interfaces. */
2046 if (type->isTypeClass ()->sym->isInterfaceDeclaration ())
2047 ci = indirect_ref (ptr_type_node, ci);
2049 this->result_ = build_nop (build_ctype (e->type), ci);
2051 else
2052 gcc_unreachable ();
2055 /* Build a function/lambda expression. */
2057 void visit (FuncExp *e)
2059 Type *ftype = e->type->toBasetype ();
2061 /* This check is for lambda's, remove `vthis' as function isn't nested. */
2062 if (e->fd->tok == TOK::reserved && ftype->ty == TY::Tpointer)
2064 e->fd->tok = TOK::function_;
2065 e->fd->vthis = NULL;
2068 /* Compile the function literal body. */
2069 build_decl_tree (e->fd);
2071 /* If nested, this will be a trampoline. */
2072 if (e->fd->isNested ())
2074 tree func = build_address (get_symbol_decl (e->fd));
2075 tree object;
2077 if (this->constp_)
2079 /* Static delegate variables have no context pointer. */
2080 object = null_pointer_node;
2081 this->result_ = build_method_call (func, object, e->fd->type);
2082 TREE_CONSTANT (this->result_) = 1;
2084 else
2086 object = get_frame_for_symbol (e->fd);
2087 this->result_ = build_method_call (func, object, e->fd->type);
2090 else
2092 this->result_ = build_nop (build_ctype (e->type),
2093 build_address (get_symbol_decl (e->fd)));
2097 /* Build a halt expression. */
2099 void visit (HaltExp *)
2101 /* Should we use trap() or abort()? */
2102 tree ttrap = builtin_decl_explicit (BUILT_IN_TRAP);
2103 this->result_ = build_call_expr (ttrap, 0);
2106 /* Build a symbol pointer offset expression. */
2108 void visit (SymOffExp *e)
2110 /* Build the address and offset of the symbol. */
2111 size_t soffset = e->isSymOffExp ()->offset;
2112 tree result = get_decl_tree (e->var);
2113 TREE_USED (result) = 1;
2115 if (declaration_reference_p (e->var))
2116 gcc_assert (POINTER_TYPE_P (TREE_TYPE (result)));
2117 else
2118 result = build_address (result);
2120 if (!soffset)
2121 result = d_convert (build_ctype (e->type), result);
2122 else
2124 tree offset = size_int (soffset);
2125 result = build_nop (build_ctype (e->type),
2126 build_offset (result, offset));
2129 this->result_ = result;
2132 /* Build a variable expression. */
2134 void visit (VarExp *e)
2136 if (e->var->needThis ())
2138 error ("need %<this%> to access member %qs", e->var->ident->toChars ());
2139 this->result_ = error_mark_node;
2140 return;
2142 else if (e->var->ident == Identifier::idPool ("__ctfe"))
2144 /* __ctfe is always false at run-time. */
2145 this->result_ = integer_zero_node;
2146 return;
2149 /* This check is same as is done in FuncExp for lambdas. */
2150 FuncLiteralDeclaration *fld = e->var->isFuncLiteralDeclaration ();
2151 if (fld != NULL)
2153 if (fld->tok == TOK::reserved)
2155 fld->tok = TOK::function_;
2156 fld->vthis = NULL;
2159 /* Compiler the function literal body. */
2160 build_decl_tree (fld);
2163 if (this->constp_)
2165 /* Want the initializer, not the expression. */
2166 VarDeclaration *var = e->var->isVarDeclaration ();
2167 SymbolDeclaration *sdecl = e->var->isSymbolDeclaration ();
2168 tree init = NULL_TREE;
2170 if (var && (var->isConst () || var->isImmutable ())
2171 && e->type->toBasetype ()->ty != TY::Tsarray && var->_init)
2173 if (var->inuse)
2174 error_at (make_location_t (e->loc), "recursive reference %qs",
2175 e->toChars ());
2176 else
2178 var->inuse++;
2179 init = build_expr (initializerToExpression (var->_init), true);
2180 var->inuse--;
2183 else if (sdecl && sdecl->dsym)
2185 if (StructDeclaration *sd = sdecl->dsym->isStructDeclaration ())
2186 init = layout_struct_initializer (sd);
2187 else if (ClassDeclaration *cd = sdecl->dsym->isClassDeclaration ())
2188 init = layout_class_initializer (cd);
2189 else
2190 gcc_unreachable ();
2192 else
2193 error_at (make_location_t (e->loc), "non-constant expression %qs",
2194 e->toChars ());
2196 if (init != NULL_TREE)
2197 this->result_ = init;
2198 else
2199 this->result_ = error_mark_node;
2201 else
2203 tree result = get_decl_tree (e->var);
2204 TREE_USED (result) = 1;
2206 /* The variable expression generated for `__traits(initSymbol)'. */
2207 if (SymbolDeclaration *sd = e->var->isSymbolDeclaration ())
2209 if (e->type->isTypeDArray ())
2211 /* Generate a slice for non-zero initialized aggregates,
2212 otherwise create an empty array. */
2213 gcc_assert (e->type == Type::tvoid->arrayOf ()->constOf ());
2215 tree type = build_ctype (e->type);
2216 tree length = size_int (sd->dsym->structsize);
2217 tree ptr = (sd->dsym->isStructDeclaration ()
2218 && sd->dsym->type->isZeroInit (e->loc))
2219 ? null_pointer_node : build_address (result);
2221 this->result_ = d_array_value (type, length, ptr);
2222 return;
2226 /* For variables that are references - currently only out/inout
2227 arguments; objects don't count - evaluating the variable means
2228 we want what it refers to. */
2229 if (declaration_reference_p (e->var))
2230 result = indirect_ref (build_ctype (e->var->type), result);
2232 this->result_ = result;
2236 /* Build a this variable expression. */
2238 void visit (ThisExp *e)
2240 FuncDeclaration *fd = d_function_chain ? d_function_chain->function : NULL;
2241 tree result = NULL_TREE;
2243 if (e->var)
2244 result = get_decl_tree (e->var);
2245 else
2247 gcc_assert (fd && fd->vthis);
2248 result = get_decl_tree (fd->vthis);
2251 if (e->type->ty == TY::Tstruct)
2252 result = build_deref (result);
2254 this->result_ = result;
2257 /* Build a new expression, which allocates memory either on the garbage
2258 collected heap or by using a class or struct specific allocator. */
2260 void visit (NewExp *e)
2262 Type *tb = e->type->toBasetype ();
2263 tree result;
2265 if (tb->ty == TY::Tclass)
2267 /* Allocating a new class. */
2268 tb = e->newtype->toBasetype ();
2270 ClassDeclaration *cd = tb->isTypeClass ()->sym;
2271 tree type = build_ctype (tb);
2272 tree setup_exp = NULL_TREE;
2273 tree new_call;
2275 if (e->onstack)
2277 /* If being used as an initializer for a local variable with scope
2278 storage class, then the instance is allocated on the stack
2279 rather than the heap or using the class specific allocator. */
2280 tree var = build_local_temp (TREE_TYPE (type));
2281 new_call = build_nop (type, build_address (var));
2282 setup_exp = modify_expr (var, aggregate_initializer_decl (cd));
2284 else
2286 /* Generate: _d_newclass() */
2287 tree arg = build_address (get_classinfo_decl (cd));
2288 libcall_fn libcall = (global.params.ehnogc && e->thrownew)
2289 ? LIBCALL_NEWTHROW : LIBCALL_NEWCLASS;
2290 new_call = build_libcall (libcall, tb, 1, arg);
2293 /* Set the context pointer for nested classes. */
2294 if (cd->isNested ())
2296 tree field = get_symbol_decl (cd->vthis);
2297 tree value = NULL_TREE;
2299 if (e->thisexp)
2301 ClassDeclaration *tcd = e->thisexp->type->isClassHandle ();
2302 /* The class or function we're nested in. */
2303 Dsymbol *outer = cd->toParentLocal ();
2305 value = build_expr (e->thisexp);
2307 if (outer != tcd)
2309 ClassDeclaration *ocd = outer->isClassDeclaration ();
2310 int offset = 0;
2311 gcc_assert (ocd->isBaseOf (tcd, &offset));
2312 /* Could just add offset... */
2313 value = convert_expr (value, e->thisexp->type, ocd->type);
2316 else
2317 value = build_vthis (cd);
2319 if (value != NULL_TREE)
2321 /* Generate: (new())->vthis = this; */
2322 new_call = d_save_expr (new_call);
2323 field = component_ref (build_deref (new_call), field);
2324 setup_exp = compound_expr (setup_exp,
2325 modify_expr (field, value));
2328 new_call = compound_expr (setup_exp, new_call);
2330 /* Call the class constructor. */
2331 if (e->member)
2332 result = d_build_call_expr (e->member, new_call, e->arguments);
2333 else
2334 result = new_call;
2336 if (e->argprefix)
2337 result = compound_expr (build_expr (e->argprefix), result);
2339 else if (tb->ty == TY::Tpointer
2340 && tb->nextOf ()->toBasetype ()->ty == TY::Tstruct)
2342 /* Allocating memory for a new struct. */
2343 Type *htype = e->newtype->toBasetype ();
2344 gcc_assert (!e->onstack);
2346 TypeStruct *stype = htype->isTypeStruct ();
2347 StructDeclaration *sd = stype->sym;
2348 tree new_call;
2350 /* Cannot new an opaque struct. */
2351 if (sd->size (e->loc) == 0)
2353 this->result_ = d_convert (build_ctype (e->type),
2354 integer_zero_node);
2355 return;
2358 /* Generate: _d_newitemT() */
2359 libcall_fn libcall = htype->isZeroInit ()
2360 ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
2361 tree arg = build_typeinfo (e->loc, e->newtype);
2362 new_call = build_libcall (libcall, tb, 1, arg);
2364 if (e->member || !e->arguments)
2366 /* Set the context pointer for nested structs. */
2367 if (sd->isNested ())
2369 tree value = build_vthis (sd);
2370 tree field = get_symbol_decl (sd->vthis);
2371 tree type = build_ctype (stype);
2373 new_call = d_save_expr (new_call);
2374 field = component_ref (indirect_ref (type, new_call), field);
2375 new_call = compound_expr (modify_expr (field, value), new_call);
2378 /* Call the struct constructor. */
2379 if (e->member)
2380 result = d_build_call_expr (e->member, new_call, e->arguments);
2381 else
2382 result = new_call;
2384 else
2386 /* If we have a user supplied initializer, then set-up with a
2387 struct literal. */
2388 if (e->arguments != NULL && sd->fields.length != 0)
2390 StructLiteralExp *se = StructLiteralExp::create (e->loc, sd,
2391 e->arguments,
2392 htype);
2393 new_call = d_save_expr (new_call);
2394 se->type = sd->type;
2395 se->sym = new_call;
2396 result = compound_expr (build_expr (se), new_call);
2398 else
2399 result = new_call;
2402 if (e->argprefix)
2403 result = compound_expr (build_expr (e->argprefix), result);
2405 else if (tb->ty == TY::Tarray)
2407 /* Allocating memory for a new D array. */
2408 tb = e->newtype->toBasetype ();
2409 TypeDArray *tarray = tb->isTypeDArray ();
2411 gcc_assert (e->arguments && e->arguments->length >= 1);
2413 if (e->arguments->length == 1)
2415 /* Single dimension array allocations. */
2416 Expression *arg = (*e->arguments)[0];
2418 if (tarray->next->size () == 0)
2420 /* Array element size is unknown. */
2421 this->result_ = d_array_value (build_ctype (e->type),
2422 size_int (0), null_pointer_node);
2423 return;
2426 libcall_fn libcall = tarray->next->isZeroInit ()
2427 ? LIBCALL_NEWARRAYT : LIBCALL_NEWARRAYIT;
2428 result = build_libcall (libcall, tb, 2,
2429 build_typeinfo (e->loc, e->type),
2430 build_expr (arg));
2432 else
2434 /* Multidimensional array allocations. */
2435 tree tarray = make_array_type (Type::tsize_t, e->arguments->length);
2436 tree var = build_local_temp (tarray);
2437 vec <constructor_elt, va_gc> *elms = NULL;
2439 /* Get the base element type for the array, generating the
2440 initializer for the dims parameter along the way. */
2441 Type *telem = e->newtype->toBasetype ();
2442 for (size_t i = 0; i < e->arguments->length; i++)
2444 Expression *arg = (*e->arguments)[i];
2445 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), build_expr (arg));
2447 gcc_assert (telem->ty == TY::Tarray);
2448 telem = telem->toBasetype ()->nextOf ();
2449 gcc_assert (telem);
2452 /* Initialize the temporary. */
2453 tree init = modify_expr (var, build_constructor (tarray, elms));
2454 var = compound_expr (init, var);
2456 /* Generate: _d_newarraymTX(ti, dims)
2457 or: _d_newarraymiTX(ti, dims) */
2458 libcall_fn libcall = telem->isZeroInit ()
2459 ? LIBCALL_NEWARRAYMTX : LIBCALL_NEWARRAYMITX;
2461 tree tinfo = build_typeinfo (e->loc, e->type);
2462 tree dims = d_array_value (build_ctype (Type::tsize_t->arrayOf ()),
2463 size_int (e->arguments->length),
2464 build_address (var));
2466 result = build_libcall (libcall, tb, 2, tinfo, dims);
2469 if (e->argprefix)
2470 result = compound_expr (build_expr (e->argprefix), result);
2472 else if (tb->ty == TY::Tpointer)
2474 /* Allocating memory for a new pointer. */
2475 TypePointer *tpointer = tb->isTypePointer ();
2477 if (tpointer->next->size () == 0)
2479 /* Pointer element size is unknown. */
2480 this->result_ = d_convert (build_ctype (e->type),
2481 integer_zero_node);
2482 return;
2485 libcall_fn libcall = tpointer->next->isZeroInit (e->loc)
2486 ? LIBCALL_NEWITEMT : LIBCALL_NEWITEMIT;
2488 tree arg = build_typeinfo (e->loc, e->newtype);
2489 result = build_libcall (libcall, tb, 1, arg);
2491 if (e->arguments && e->arguments->length == 1)
2493 result = d_save_expr (result);
2494 tree init = modify_expr (build_deref (result),
2495 build_expr ((*e->arguments)[0]));
2496 result = compound_expr (init, result);
2499 if (e->argprefix)
2500 result = compound_expr (build_expr (e->argprefix), result);
2502 else
2503 gcc_unreachable ();
2505 this->result_ = convert_expr (result, tb, e->type);
2508 /* Build an integer literal. */
2510 void visit (IntegerExp *e)
2512 tree ctype = build_ctype (e->type->toBasetype ());
2513 this->result_ = build_integer_cst (e->value, ctype);
2516 /* Build a floating-point literal. */
2518 void visit (RealExp *e)
2520 this->result_ = build_float_cst (e->value, e->type->toBasetype ());
2523 /* Build a complex literal. */
2525 void visit (ComplexExp *e)
2527 Type *tnext;
2529 switch (e->type->toBasetype ()->ty)
2531 case TY::Tcomplex32:
2532 tnext = (TypeBasic *) Type::tfloat32;
2533 break;
2535 case TY::Tcomplex64:
2536 tnext = (TypeBasic *) Type::tfloat64;
2537 break;
2539 case TY::Tcomplex80:
2540 tnext = (TypeBasic *) Type::tfloat80;
2541 break;
2543 default:
2544 gcc_unreachable ();
2547 this->result_ = build_complex (build_ctype (e->type),
2548 build_float_cst (creall (e->value), tnext),
2549 build_float_cst (cimagl (e->value), tnext));
2552 /* Build a string literal, all strings are null terminated except for
2553 static arrays. */
2555 void visit (StringExp *e)
2557 Type *tb = e->type->toBasetype ();
2558 tree type = build_ctype (e->type);
2560 if (tb->ty == TY::Tsarray)
2562 /* Turn the string into a constructor for the static array. */
2563 vec <constructor_elt, va_gc> *elms = NULL;
2564 vec_safe_reserve (elms, e->len);
2565 tree etype = TREE_TYPE (type);
2567 for (size_t i = 0; i < e->len; i++)
2569 tree value = build_integer_cst (e->getCodeUnit (i), etype);
2570 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
2573 tree ctor = build_constructor (type, elms);
2574 TREE_CONSTANT (ctor) = 1;
2575 this->result_ = ctor;
2577 else
2579 /* Copy the string contents to a null terminated string. */
2580 dinteger_t length = (e->len * e->sz);
2581 char *string = XALLOCAVEC (char, length + 1);
2582 if (length > 0)
2583 memcpy (string, e->string, length);
2584 string[length] = '\0';
2586 /* String value and type includes the null terminator. */
2587 tree value = build_string (length, string);
2588 TREE_TYPE (value) = make_array_type (tb->nextOf (), length + 1);
2589 value = build_address (value);
2591 if (tb->ty == TY::Tarray)
2592 value = d_array_value (type, size_int (e->len), value);
2594 TREE_CONSTANT (value) = 1;
2595 this->result_ = d_convert (type, value);
2599 /* Build a tuple literal. Just an argument list that may have
2600 side effects that need evaluation. */
2602 void visit (TupleExp *e)
2604 tree result = NULL_TREE;
2606 if (e->e0)
2607 result = build_expr (e->e0, this->constp_, true);
2609 for (size_t i = 0; i < e->exps->length; ++i)
2611 Expression *exp = (*e->exps)[i];
2612 result = compound_expr (result, build_expr (exp, this->constp_, true));
2615 if (result == NULL_TREE)
2616 result = void_node;
2618 this->result_ = result;
2621 /* Build an array literal. The common type of the all elements is taken to
2622 be the type of the array element, and all elements are implicitly
2623 converted to that type. */
2625 void visit (ArrayLiteralExp *e)
2627 Type *tb = e->type->toBasetype ();
2629 /* Implicitly convert void[n] to ubyte[n]. */
2630 if (tb->ty == TY::Tsarray && tb->nextOf ()->toBasetype ()->ty == TY::Tvoid)
2631 tb = Type::tuns8->sarrayOf (tb->isTypeSArray ()->dim->toUInteger ());
2633 gcc_assert (tb->ty == TY::Tarray || tb->ty == TY::Tsarray
2634 || tb->ty == TY::Tpointer);
2636 /* Handle empty array literals. */
2637 if (e->elements->length == 0)
2639 if (tb->ty == TY::Tarray)
2640 this->result_ = d_array_value (build_ctype (e->type),
2641 size_int (0), null_pointer_node);
2642 else
2643 this->result_ = build_constructor (make_array_type (tb->nextOf (), 0),
2644 NULL);
2646 return;
2649 /* Build an expression that assigns the expressions in ELEMENTS to
2650 a constructor. */
2651 vec <constructor_elt, va_gc> *elms = NULL;
2652 vec_safe_reserve (elms, e->elements->length);
2653 bool constant_p = true;
2654 tree saved_elems = NULL_TREE;
2656 Type *etype = tb->nextOf ();
2657 tree satype = make_array_type (etype, e->elements->length);
2659 for (size_t i = 0; i < e->elements->length; i++)
2661 Expression *expr = e->getElement (i);
2662 tree value = build_expr (expr, this->constp_, true);
2664 /* Only append nonzero values, the backend will zero out the rest
2665 of the constructor as we don't set CONSTRUCTOR_NO_CLEARING. */
2666 if (!initializer_zerop (value))
2668 if (!TREE_CONSTANT (value))
2669 constant_p = false;
2671 /* Split construction of values out of the constructor if there
2672 may be side effects. */
2673 tree init = stabilize_expr (&value);
2674 if (init != NULL_TREE)
2675 saved_elems = compound_expr (saved_elems, init);
2677 CONSTRUCTOR_APPEND_ELT (elms, size_int (i),
2678 convert_expr (value, expr->type, etype));
2682 /* Now return the constructor as the correct type. For static arrays there
2683 is nothing else to do. For dynamic arrays, return a two field struct.
2684 For pointers, return the address. */
2685 tree ctor = build_constructor (satype, elms);
2686 tree type = build_ctype (e->type);
2688 /* Nothing else to do for static arrays. */
2689 if (tb->ty == TY::Tsarray || this->constp_)
2691 /* Can't take the address of the constructor, so create an anonymous
2692 static symbol, and then refer to it. */
2693 if (tb->ty != TY::Tsarray)
2695 tree decl = build_artificial_decl (TREE_TYPE (ctor), ctor, "A");
2696 ctor = build_address (decl);
2697 if (tb->ty == TY::Tarray)
2698 ctor = d_array_value (type, size_int (e->elements->length), ctor);
2700 d_pushdecl (decl);
2701 rest_of_decl_compilation (decl, 1, 0);
2704 /* If the array literal is readonly or static. */
2705 if (constant_p)
2706 TREE_CONSTANT (ctor) = 1;
2707 if (constant_p && initializer_constant_valid_p (ctor, TREE_TYPE (ctor)))
2708 TREE_STATIC (ctor) = 1;
2710 /* Use memset to fill any alignment holes in the array. */
2711 if (!this->constp_ && !this->literalp_)
2713 TypeStruct *ts = etype->baseElemOf ()->isTypeStruct ();
2715 if (ts != NULL && (!identity_compare_p (ts->sym)
2716 || ts->sym->isUnionDeclaration ()))
2718 tree var = build_local_temp (TREE_TYPE (ctor));
2719 tree init = build_memset_call (var);
2720 /* Evaluate memset() first, then any saved elements. */
2721 saved_elems = compound_expr (init, saved_elems);
2722 ctor = compound_expr (modify_expr (var, ctor), var);
2726 this->result_ = compound_expr (saved_elems, d_convert (type, ctor));
2728 else
2730 /* Allocate space on the memory managed heap. */
2731 tree mem = build_libcall (LIBCALL_ARRAYLITERALTX,
2732 etype->pointerTo (), 2,
2733 build_typeinfo (e->loc, etype->arrayOf ()),
2734 size_int (e->elements->length));
2735 mem = d_save_expr (mem);
2737 /* Now copy the constructor into memory. */
2738 tree size = size_mult_expr (size_int (e->elements->length),
2739 size_int (tb->nextOf ()->size ()));
2741 tree result = build_memcpy_call (mem, build_address (ctor), size);
2743 /* Return the array pointed to by MEM. */
2744 result = compound_expr (result, mem);
2746 if (tb->ty == TY::Tarray)
2747 result = d_array_value (type, size_int (e->elements->length), result);
2749 this->result_ = compound_expr (saved_elems, result);
2753 /* Build an associative array literal. The common type of the all keys is
2754 taken to be the key type, and common type of all values the value type.
2755 All keys and values are then implicitly converted as needed. */
2757 void visit (AssocArrayLiteralExp *e)
2759 /* Want the mutable type for typeinfo reference. */
2760 Type *tb = e->type->toBasetype ()->mutableOf ();
2762 /* Handle empty assoc array literals. */
2763 TypeAArray *ta = tb->isTypeAArray ();
2764 if (e->keys->length == 0)
2766 this->result_ = build_constructor (build_ctype (ta), NULL);
2767 return;
2770 /* Build an expression that assigns all expressions in KEYS
2771 to a constructor. */
2772 tree akeys = build_array_from_exprs (ta->index->sarrayOf (e->keys->length),
2773 e->keys, this->constp_);
2774 tree init = stabilize_expr (&akeys);
2776 /* Do the same with all expressions in VALUES. */
2777 tree avals = build_array_from_exprs (ta->next->sarrayOf (e->values->length),
2778 e->values, this->constp_);
2779 init = compound_expr (init, stabilize_expr (&avals));
2781 /* Generate: _d_assocarrayliteralTX (ti, keys, vals); */
2782 tree keys = d_array_value (build_ctype (ta->index->arrayOf ()),
2783 size_int (e->keys->length),
2784 build_address (akeys));
2785 tree vals = d_array_value (build_ctype (ta->next->arrayOf ()),
2786 size_int (e->values->length),
2787 build_address (avals));
2789 tree mem = build_libcall (LIBCALL_ASSOCARRAYLITERALTX, Type::tvoidptr, 3,
2790 build_typeinfo (e->loc, ta), keys, vals);
2792 /* Return an associative array pointed to by MEM. */
2793 tree aatype = build_ctype (ta);
2794 vec <constructor_elt, va_gc> *ce = NULL;
2795 CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (aatype), mem);
2797 tree result = build_nop (build_ctype (e->type),
2798 build_constructor (aatype, ce));
2799 this->result_ = compound_expr (init, result);
2802 /* Build a struct literal. */
2804 void visit (StructLiteralExp *e)
2806 /* Handle empty struct literals. */
2807 if (e->elements == NULL || e->sd->fields.length == 0)
2809 this->result_ = build_constructor (build_ctype (e->type), NULL);
2810 return;
2813 /* Building sinit trees are delayed until after frontend semantic
2814 processing has complete. Build the static initializer now. */
2815 if (e->useStaticInit && !this->constp_)
2817 tree init = aggregate_initializer_decl (e->sd);
2819 /* If initializing a symbol, don't forget to set it. */
2820 if (e->sym != NULL)
2822 tree var = build_deref (e->sym);
2823 init = compound_expr (modify_expr (var, init), var);
2826 this->result_ = init;
2827 return;
2830 /* Build a constructor that assigns the expressions in ELEMENTS
2831 at each field index that has been filled in. */
2832 vec <constructor_elt, va_gc> *ve = NULL;
2833 tree saved_elems = NULL_TREE;
2835 /* CTFE may fill the hidden pointer by NullExp. */
2836 gcc_assert (e->elements->length <= e->sd->fields.length);
2838 Type *tb = e->type->toBasetype ();
2839 gcc_assert (tb->ty == TY::Tstruct);
2841 for (size_t i = 0; i < e->elements->length; i++)
2843 Expression *exp = (*e->elements)[i];
2844 if (!exp)
2845 continue;
2847 VarDeclaration *field = e->sd->fields[i];
2848 Type *type = exp->type->toBasetype ();
2849 Type *ftype = field->type->toBasetype ();
2850 tree value = NULL_TREE;
2852 if (ftype->ty == TY::Tsarray && !same_type_p (type, ftype))
2854 /* Initialize a static array with a single element. */
2855 tree elem = build_expr (exp, this->constp_, true);
2856 saved_elems = compound_expr (saved_elems, stabilize_expr (&elem));
2857 elem = d_save_expr (elem);
2859 if (initializer_zerop (elem))
2860 value = build_constructor (build_ctype (ftype), NULL);
2861 else
2862 value = build_array_from_val (ftype, elem);
2864 else
2866 value = convert_expr (build_expr (exp, this->constp_, true),
2867 exp->type, field->type);
2870 /* Split construction of values out of the constructor. */
2871 saved_elems = compound_expr (saved_elems, stabilize_expr (&value));
2873 CONSTRUCTOR_APPEND_ELT (ve, get_symbol_decl (field), value);
2876 /* Maybe setup hidden pointer to outer scope context. */
2877 if (e->sd->isNested () && e->elements->length != e->sd->fields.length
2878 && this->constp_ == false)
2880 tree field = get_symbol_decl (e->sd->vthis);
2881 tree value = build_vthis (e->sd);
2882 CONSTRUCTOR_APPEND_ELT (ve, field, value);
2883 gcc_assert (e->useStaticInit == false);
2886 /* Build a constructor in the correct shape of the aggregate type. */
2887 tree ctor = build_struct_literal (build_ctype (e->type), ve);
2889 /* Nothing more to do for constant literals. */
2890 if (this->constp_)
2892 /* If the struct literal is a valid for static data. */
2893 if (TREE_CONSTANT (ctor)
2894 && initializer_constant_valid_p (ctor, TREE_TYPE (ctor)))
2895 TREE_STATIC (ctor) = 1;
2897 this->result_ = compound_expr (saved_elems, ctor);
2898 return;
2901 /* Construct the struct literal for run-time. */
2902 if (e->sym != NULL)
2904 /* Store the result in a symbol to initialize the literal. */
2905 tree var = build_deref (e->sym);
2906 ctor = compound_expr (modify_expr (var, ctor), var);
2908 else if (!this->literalp_)
2910 /* Use memset to fill any alignment holes in the object. */
2911 if (!identity_compare_p (e->sd) || e->sd->isUnionDeclaration ())
2913 tree var = build_local_temp (TREE_TYPE (ctor));
2914 tree init = build_memset_call (var);
2915 /* Evaluate memset() first, then any saved element constructors. */
2916 saved_elems = compound_expr (init, saved_elems);
2917 ctor = compound_expr (modify_expr (var, ctor), var);
2921 this->result_ = compound_expr (saved_elems, ctor);
2924 /* Build a null literal. */
2926 void visit (NullExp *e)
2928 this->result_ = build_typeof_null_value (e->type);
2931 /* Build a vector literal. */
2933 void visit (VectorExp *e)
2935 tree type = build_ctype (e->type);
2937 /* First handle array literal expressions. */
2938 if (e->e1->op == EXP::arrayLiteral)
2940 ArrayLiteralExp *ale = e->e1->isArrayLiteralExp ();
2941 vec <constructor_elt, va_gc> *elms = NULL;
2942 bool constant_p = true;
2944 vec_safe_reserve (elms, ale->elements->length);
2945 for (size_t i = 0; i < ale->elements->length; i++)
2947 Expression *expr = ale->getElement (i);
2948 tree value = d_convert (TREE_TYPE (type),
2949 build_expr (expr, this->constp_, true));
2950 if (!CONSTANT_CLASS_P (value))
2951 constant_p = false;
2953 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
2956 /* Build a VECTOR_CST from a constant vector constructor. */
2957 if (constant_p)
2958 this->result_ = build_vector_from_ctor (type, elms);
2959 else
2960 this->result_ = build_constructor (type, elms);
2962 else
2964 /* Build constructor from single value. */
2965 tree value = d_convert (TREE_TYPE (type),
2966 build_expr (e->e1, this->constp_, true));
2967 this->result_ = build_vector_from_val (type, value);
2971 /* Build a static array representation of a vector expression. */
2973 void visit (VectorArrayExp *e)
2975 this->result_ = convert_expr (build_expr (e->e1, this->constp_, true),
2976 e->e1->type, e->type);
2979 /* Build a static class literal, return its reference. */
2981 void visit (ClassReferenceExp *e)
2983 /* The result of build_new_class_expr is a RECORD_TYPE, we want
2984 the reference. */
2985 tree var = build_address (build_new_class_expr (e));
2987 /* If the type of this literal is an interface, the we must add the
2988 interface offset to symbol. */
2989 if (this->constp_)
2991 TypeClass *tc = e->type->toBasetype ()->isTypeClass ();
2992 InterfaceDeclaration *to = tc->sym->isInterfaceDeclaration ();
2994 if (to != NULL)
2996 ClassDeclaration *from = e->originalClass ();
2997 int offset = 0;
2999 gcc_assert (to->isBaseOf (from, &offset) != 0);
3001 if (offset != 0)
3002 var = build_offset (var, size_int (offset));
3006 this->result_ = var;
3009 /* These expressions are mainly just a placeholders in the frontend.
3010 We shouldn't see them here. */
3012 void visit (ScopeExp *e)
3014 error_at (make_location_t (e->loc), "%qs is not an expression",
3015 e->toChars ());
3016 this->result_ = error_mark_node;
3019 void visit (TypeExp *e)
3021 error_at (make_location_t (e->loc), "type %qs is not an expression",
3022 e->toChars ());
3023 this->result_ = error_mark_node;
3028 /* Main entry point for ExprVisitor interface to generate code for
3029 the Expression AST class E. If CONST_P is true, then E is a
3030 constant expression. If LITERAL_P is true, then E is a value used
3031 in the initialization of another literal. */
3033 tree
3034 build_expr (Expression *e, bool const_p, bool literal_p)
3036 ExprVisitor v = ExprVisitor (const_p, literal_p);
3037 location_t saved_location = input_location;
3039 input_location = make_location_t (e->loc);
3040 e->accept (&v);
3041 tree expr = v.result ();
3042 input_location = saved_location;
3044 /* Check if initializer expression is valid constant. */
3045 if (const_p && !initializer_constant_valid_p (expr, TREE_TYPE (expr)))
3047 error_at (make_location_t (e->loc), "non-constant expression %qs",
3048 e->toChars ());
3049 return error_mark_node;
3052 return expr;
3055 /* Same as build_expr, but also calls destructors on any temporaries. */
3057 tree
3058 build_expr_dtor (Expression *e)
3060 /* Codegen can be improved by determining if no exceptions can be thrown
3061 between the ctor and dtor, and eliminating the ctor and dtor. */
3062 size_t saved_vars = vec_safe_length (d_function_chain->vars_in_scope);
3063 tree result = build_expr (e);
3065 if (saved_vars != vec_safe_length (d_function_chain->vars_in_scope))
3067 result = fold_build_cleanup_point_expr (TREE_TYPE (result), result);
3068 vec_safe_truncate (d_function_chain->vars_in_scope, saved_vars);
3071 return result;
3074 /* Same as build_expr_dtor, but handles the result of E as a return value. */
3076 tree
3077 build_return_dtor (Expression *e, Type *type, TypeFunction *tf)
3079 size_t saved_vars = vec_safe_length (d_function_chain->vars_in_scope);
3080 tree result = build_expr (e);
3082 /* Convert for initializing the DECL_RESULT. */
3083 if (tf->isref ())
3085 /* If we are returning a reference, take the address. */
3086 result = convert_expr (result, e->type, type);
3087 result = build_address (result);
3089 else
3090 result = convert_for_rvalue (result, e->type, type);
3092 /* The decl to store the return expression. */
3093 tree decl = DECL_RESULT (cfun->decl);
3095 /* Split comma expressions, so that the result is returned directly. */
3096 tree expr = stabilize_expr (&result);
3097 result = build_assign (INIT_EXPR, decl, result);
3098 result = compound_expr (expr, return_expr (result));
3100 /* May nest the return expression inside the try/finally expression. */
3101 if (saved_vars != vec_safe_length (d_function_chain->vars_in_scope))
3103 result = fold_build_cleanup_point_expr (TREE_TYPE (result), result);
3104 vec_safe_truncate (d_function_chain->vars_in_scope, saved_vars);
3107 return result;