]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/d-codegen.cc
d: Move private functions out of ExprVisitor into local statics
[thirdparty/gcc.git] / gcc / d / d-codegen.cc
CommitLineData
b4c522fa 1/* d-codegen.cc -- Code generation and routines for manipulation of GCC trees.
8d9254fc 2 Copyright (C) 2006-2020 Free Software Foundation, Inc.
b4c522fa
IB
3
4GCC is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 3, or (at your option)
7any later version.
8
9GCC is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with GCC; see the file COPYING3. If not see
16<http://www.gnu.org/licenses/>. */
17
18#include "config.h"
19#include "system.h"
20#include "coretypes.h"
21
22#include "dmd/aggregate.h"
23#include "dmd/ctfe.h"
24#include "dmd/declaration.h"
25#include "dmd/identifier.h"
26#include "dmd/target.h"
27#include "dmd/template.h"
28
29#include "tree.h"
30#include "tree-iterator.h"
31#include "fold-const.h"
32#include "diagnostic.h"
33#include "langhooks.h"
34#include "target.h"
35#include "stringpool.h"
36#include "varasm.h"
37#include "stor-layout.h"
38#include "attribs.h"
39#include "function.h"
40
41#include "d-tree.h"
42
43
44/* Return the GCC location for the D frontend location LOC. */
45
46location_t
af3c19f0 47make_location_t (const Loc &loc)
b4c522fa
IB
48{
49 location_t gcc_location = input_location;
50
51 if (loc.filename)
52 {
53 linemap_add (line_table, LC_ENTER, 0, loc.filename, loc.linnum);
54 linemap_line_start (line_table, loc.linnum, 0);
55 gcc_location = linemap_position_for_column (line_table, loc.charnum);
56 linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
57 }
58
59 return gcc_location;
60}
61
62/* Return the DECL_CONTEXT for symbol DSYM. */
63
64tree
65d_decl_context (Dsymbol *dsym)
66{
67 Dsymbol *parent = dsym;
68 Declaration *decl = dsym->isDeclaration ();
75f758a7 69 AggregateDeclaration *ad = dsym->isAggregateDeclaration ();
b4c522fa 70
9dddefef 71 while ((parent = parent->toParent2 ()))
b4c522fa
IB
72 {
73 /* We've reached the top-level module namespace.
74 Set DECL_CONTEXT as the NAMESPACE_DECL of the enclosing module,
75 but only for extern(D) symbols. */
76 if (parent->isModule ())
77 {
75f758a7
IB
78 if ((decl != NULL && decl->linkage != LINKd)
79 || (ad != NULL && ad->classKind != ClassKind::d))
b4c522fa
IB
80 return NULL_TREE;
81
82 return build_import_decl (parent);
83 }
84
cdbf48be 85 /* Declarations marked as `static' or `__gshared' are never
b4c522fa
IB
86 part of any context except at module level. */
87 if (decl != NULL && decl->isDataseg ())
88 continue;
89
90 /* Nested functions. */
91 FuncDeclaration *fd = parent->isFuncDeclaration ();
92 if (fd != NULL)
93 return get_symbol_decl (fd);
94
95 /* Methods of classes or structs. */
96 AggregateDeclaration *ad = parent->isAggregateDeclaration ();
97 if (ad != NULL)
98 {
99 tree context = build_ctype (ad->type);
100 /* Want the underlying RECORD_TYPE. */
101 if (ad->isClassDeclaration ())
102 context = TREE_TYPE (context);
103
104 return context;
105 }
b4c522fa
IB
106 }
107
108 return NULL_TREE;
109}
110
111/* Return a copy of record TYPE but safe to modify in any way. */
112
113tree
114copy_aggregate_type (tree type)
115{
116 tree newtype = build_distinct_type_copy (type);
117 TYPE_FIELDS (newtype) = copy_list (TYPE_FIELDS (type));
118
119 for (tree f = TYPE_FIELDS (newtype); f; f = DECL_CHAIN (f))
120 DECL_FIELD_CONTEXT (f) = newtype;
121
122 return newtype;
123}
124
125/* Return TRUE if declaration DECL is a reference type. */
126
127bool
128declaration_reference_p (Declaration *decl)
129{
130 Type *tb = decl->type->toBasetype ();
131
132 /* Declaration is a reference type. */
133 if (tb->ty == Treference || decl->storage_class & (STCout | STCref))
134 return true;
135
136 return false;
137}
138
139/* Returns the real type for declaration DECL. */
140
141tree
142declaration_type (Declaration *decl)
143{
144 /* Lazy declarations are converted to delegates. */
145 if (decl->storage_class & STClazy)
146 {
c3a2ba10
IB
147 TypeFunction *tf = TypeFunction::create (NULL, decl->type,
148 VARARGnone, LINKd);
b4c522fa
IB
149 TypeDelegate *t = TypeDelegate::create (tf);
150 return build_ctype (t->merge2 ());
151 }
152
153 /* Static array va_list have array->pointer conversions applied. */
154 if (decl->isParameter () && valist_array_p (decl->type))
155 {
156 Type *valist = decl->type->nextOf ()->pointerTo ();
157 valist = valist->castMod (decl->type->mod);
158 return build_ctype (valist);
159 }
160
161 tree type = build_ctype (decl->type);
162
163 /* Parameter is passed by reference. */
164 if (declaration_reference_p (decl))
165 return build_reference_type (type);
166
cdbf48be 167 /* The `this' parameter is always const. */
b4c522fa
IB
168 if (decl->isThisDeclaration ())
169 return insert_type_modifiers (type, MODconst);
170
171 return type;
172}
173
174/* These should match the Declaration versions above
175 Return TRUE if parameter ARG is a reference type. */
176
177bool
2370bdbb 178parameter_reference_p (Parameter *arg)
b4c522fa
IB
179{
180 Type *tb = arg->type->toBasetype ();
181
182 /* Parameter is a reference type. */
183 if (tb->ty == Treference || arg->storageClass & (STCout | STCref))
184 return true;
185
b4c522fa
IB
186 return false;
187}
188
189/* Returns the real type for parameter ARG. */
190
191tree
2370bdbb 192parameter_type (Parameter *arg)
b4c522fa
IB
193{
194 /* Lazy parameters are converted to delegates. */
195 if (arg->storageClass & STClazy)
196 {
c3a2ba10
IB
197 TypeFunction *tf = TypeFunction::create (NULL, arg->type,
198 VARARGnone, LINKd);
b4c522fa
IB
199 TypeDelegate *t = TypeDelegate::create (tf);
200 return build_ctype (t->merge2 ());
201 }
202
203 /* Static array va_list have array->pointer conversions applied. */
204 if (valist_array_p (arg->type))
205 {
206 Type *valist = arg->type->nextOf ()->pointerTo ();
207 valist = valist->castMod (arg->type->mod);
208 return build_ctype (valist);
209 }
210
211 tree type = build_ctype (arg->type);
212
213 /* Parameter is passed by reference. */
2370bdbb 214 if (parameter_reference_p (arg))
b4c522fa
IB
215 return build_reference_type (type);
216
2370bdbb
IB
217 /* Pass non-POD structs by invisible reference. */
218 if (TREE_ADDRESSABLE (type))
219 {
220 type = build_reference_type (type);
221 /* There are no other pointer to this temporary. */
222 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
223 }
224
225 /* Front-end has already taken care of type promotions. */
b4c522fa
IB
226 return type;
227}
228
229/* Build INTEGER_CST of type TYPE with the value VALUE. */
230
231tree
232build_integer_cst (dinteger_t value, tree type)
233{
234 /* The type is error_mark_node, we can't do anything. */
235 if (error_operand_p (type))
236 return type;
237
238 return build_int_cst_type (type, value);
239}
240
241/* Build REAL_CST of type TOTYPE with the value VALUE. */
242
243tree
af3c19f0 244build_float_cst (const real_t &value, Type *totype)
b4c522fa
IB
245{
246 real_t new_value;
247 TypeBasic *tb = totype->isTypeBasic ();
248
249 gcc_assert (tb != NULL);
250
251 tree type_node = build_ctype (tb);
252 real_convert (&new_value.rv (), TYPE_MODE (type_node), &value.rv ());
253
254 return build_real (type_node, new_value.rv ());
255}
256
257/* Returns the .length component from the D dynamic array EXP. */
258
259tree
260d_array_length (tree exp)
261{
262 if (error_operand_p (exp))
263 return exp;
264
265 gcc_assert (TYPE_DYNAMIC_ARRAY (TREE_TYPE (exp)));
266
267 /* Get the back-end type for the array and pick out the array
268 length field (assumed to be the first field). */
269 tree len_field = TYPE_FIELDS (TREE_TYPE (exp));
270 return component_ref (exp, len_field);
271}
272
273/* Returns the .ptr component from the D dynamic array EXP. */
274
275tree
276d_array_ptr (tree exp)
277{
278 if (error_operand_p (exp))
279 return exp;
280
281 gcc_assert (TYPE_DYNAMIC_ARRAY (TREE_TYPE (exp)));
282
283 /* Get the back-end type for the array and pick out the array
284 data pointer field (assumed to be the second field). */
285 tree ptr_field = TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (exp)));
286 return component_ref (exp, ptr_field);
287}
288
289/* Returns a constructor for D dynamic array type TYPE of .length LEN
290 and .ptr pointing to DATA. */
291
292tree
293d_array_value (tree type, tree len, tree data)
294{
295 tree len_field, ptr_field;
af3c19f0 296 vec <constructor_elt, va_gc> *ce = NULL;
b4c522fa
IB
297
298 gcc_assert (TYPE_DYNAMIC_ARRAY (type));
299 len_field = TYPE_FIELDS (type);
300 ptr_field = TREE_CHAIN (len_field);
301
302 len = convert (TREE_TYPE (len_field), len);
303 data = convert (TREE_TYPE (ptr_field), data);
304
305 CONSTRUCTOR_APPEND_ELT (ce, len_field, len);
306 CONSTRUCTOR_APPEND_ELT (ce, ptr_field, data);
307
308 return build_constructor (type, ce);
309}
310
311/* Returns value representing the array length of expression EXP.
312 TYPE could be a dynamic or static array. */
313
314tree
315get_array_length (tree exp, Type *type)
316{
317 Type *tb = type->toBasetype ();
318
319 switch (tb->ty)
320 {
321 case Tsarray:
89fdaf5a 322 return size_int (tb->isTypeSArray ()->dim->toUInteger ());
b4c522fa
IB
323
324 case Tarray:
325 return d_array_length (exp);
326
327 default:
a9c697b8 328 error ("cannot determine the length of a %qs", type->toChars ());
b4c522fa
IB
329 return error_mark_node;
330 }
331}
332
333/* Create BINFO for a ClassDeclaration's inheritance tree.
334 InterfaceDeclaration's are not included. */
335
336tree
337build_class_binfo (tree super, ClassDeclaration *cd)
338{
339 tree binfo = make_tree_binfo (1);
340 tree ctype = build_ctype (cd->type);
341
342 /* Want RECORD_TYPE, not POINTER_TYPE. */
343 BINFO_TYPE (binfo) = TREE_TYPE (ctype);
344 BINFO_INHERITANCE_CHAIN (binfo) = super;
345 BINFO_OFFSET (binfo) = integer_zero_node;
346
347 if (cd->baseClass)
348 BINFO_BASE_APPEND (binfo, build_class_binfo (binfo, cd->baseClass));
349
350 return binfo;
351}
352
353/* Create BINFO for an InterfaceDeclaration's inheritance tree.
354 In order to access all inherited methods in the debugger,
355 the entire tree must be described.
356 This function makes assumptions about interface layout. */
357
358tree
af3c19f0 359build_interface_binfo (tree super, ClassDeclaration *cd, unsigned &offset)
b4c522fa 360{
2cbc99d1 361 tree binfo = make_tree_binfo (cd->baseclasses->length);
b4c522fa
IB
362 tree ctype = build_ctype (cd->type);
363
364 /* Want RECORD_TYPE, not POINTER_TYPE. */
365 BINFO_TYPE (binfo) = TREE_TYPE (ctype);
366 BINFO_INHERITANCE_CHAIN (binfo) = super;
5905cbdb 367 BINFO_OFFSET (binfo) = size_int (offset * target.ptrsize);
b4c522fa
IB
368 BINFO_VIRTUAL_P (binfo) = 1;
369
2cbc99d1 370 for (size_t i = 0; i < cd->baseclasses->length; i++, offset++)
b4c522fa
IB
371 {
372 BaseClass *bc = (*cd->baseclasses)[i];
373 BINFO_BASE_APPEND (binfo, build_interface_binfo (binfo, bc->sym, offset));
374 }
375
376 return binfo;
377}
378
379/* Returns the .funcptr component from the D delegate EXP. */
380
381tree
382delegate_method (tree exp)
383{
384 /* Get the back-end type for the delegate and pick out the funcptr field
385 (assumed to be the second field). */
386 gcc_assert (TYPE_DELEGATE (TREE_TYPE (exp)));
387 tree method_field = TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (exp)));
388 return component_ref (exp, method_field);
389}
390
391/* Returns the .object component from the delegate EXP. */
392
393tree
394delegate_object (tree exp)
395{
396 /* Get the back-end type for the delegate and pick out the object field
397 (assumed to be the first field). */
398 gcc_assert (TYPE_DELEGATE (TREE_TYPE (exp)));
399 tree obj_field = TYPE_FIELDS (TREE_TYPE (exp));
400 return component_ref (exp, obj_field);
401}
402
403/* Build a delegate literal of type TYPE whose pointer function is
404 METHOD, and hidden object is OBJECT. */
405
406tree
407build_delegate_cst (tree method, tree object, Type *type)
408{
409 tree ctor = make_node (CONSTRUCTOR);
410 tree ctype;
411
412 Type *tb = type->toBasetype ();
413 if (tb->ty == Tdelegate)
414 ctype = build_ctype (type);
415 else
416 {
417 /* Convert a function method into an anonymous delegate. */
418 ctype = make_struct_type ("delegate()", 2,
419 get_identifier ("object"), TREE_TYPE (object),
420 get_identifier ("func"), TREE_TYPE (method));
421 TYPE_DELEGATE (ctype) = 1;
422 }
423
af3c19f0 424 vec <constructor_elt, va_gc> *ce = NULL;
b4c522fa
IB
425 CONSTRUCTOR_APPEND_ELT (ce, TYPE_FIELDS (ctype), object);
426 CONSTRUCTOR_APPEND_ELT (ce, TREE_CHAIN (TYPE_FIELDS (ctype)), method);
427
428 CONSTRUCTOR_ELTS (ctor) = ce;
429 TREE_TYPE (ctor) = ctype;
430
431 return ctor;
432}
433
434/* Builds a temporary tree to store the CALLEE and OBJECT
435 of a method call expression of type TYPE. */
436
437tree
438build_method_call (tree callee, tree object, Type *type)
439{
440 tree t = build_delegate_cst (callee, object, type);
441 METHOD_CALL_EXPR (t) = 1;
442 return t;
443}
444
445/* Extract callee and object from T and return in to CALLEE and OBJECT. */
446
447void
af3c19f0 448extract_from_method_call (tree t, tree &callee, tree &object)
b4c522fa
IB
449{
450 gcc_assert (METHOD_CALL_EXPR (t));
451 object = CONSTRUCTOR_ELT (t, 0)->value;
452 callee = CONSTRUCTOR_ELT (t, 1)->value;
453}
454
5e95646e
IB
455/* Build a typeof(null) constant of type TYPE. Handles certain special case
456 conversions, where the underlying type is an aggregate with a nullable
457 interior pointer. */
458
459tree
460build_typeof_null_value (Type *type)
461{
462 Type *tb = type->toBasetype ();
463 tree value;
464
465 /* For dynamic arrays, set length and pointer fields to zero. */
466 if (tb->ty == Tarray)
467 value = d_array_value (build_ctype (type), size_int (0), null_pointer_node);
468
469 /* For associative arrays, set the pointer field to null. */
470 else if (tb->ty == Taarray)
471 {
472 tree ctype = build_ctype (type);
473 gcc_assert (TYPE_ASSOCIATIVE_ARRAY (ctype));
474
475 value = build_constructor_single (ctype, TYPE_FIELDS (ctype),
476 null_pointer_node);
477 }
478
479 /* For delegates, set the frame and function pointer fields to null. */
480 else if (tb->ty == Tdelegate)
481 value = build_delegate_cst (null_pointer_node, null_pointer_node, type);
482
483 /* Simple zero constant for all other types. */
484 else
485 value = build_zero_cst (build_ctype (type));
486
487 TREE_CONSTANT (value) = 1;
488 return value;
489}
490
b4c522fa
IB
491/* Build a dereference into the virtual table for OBJECT to retrieve
492 a function pointer of type FNTYPE at position INDEX. */
493
494tree
495build_vindex_ref (tree object, tree fntype, size_t index)
496{
497 /* The vtable is the first field. Interface methods are also in the class's
498 vtable, so we don't need to convert from a class to an interface. */
499 tree result = build_deref (object);
500 result = component_ref (result, TYPE_FIELDS (TREE_TYPE (result)));
501
502 gcc_assert (POINTER_TYPE_P (fntype));
503
5905cbdb 504 return build_memref (fntype, result, size_int (target.ptrsize * index));
b4c522fa
IB
505}
506
507/* Return TRUE if EXP is a valid lvalue. Lvalue references cannot be
508 made into temporaries, otherwise any assignments will be lost. */
509
510static bool
511lvalue_p (tree exp)
512{
513 const enum tree_code code = TREE_CODE (exp);
514
515 switch (code)
516 {
517 case SAVE_EXPR:
518 return false;
519
520 case ARRAY_REF:
521 case INDIRECT_REF:
522 case VAR_DECL:
523 case PARM_DECL:
524 case RESULT_DECL:
525 return !FUNC_OR_METHOD_TYPE_P (TREE_TYPE (exp));
526
527 case IMAGPART_EXPR:
528 case REALPART_EXPR:
529 case COMPONENT_REF:
530 CASE_CONVERT:
531 return lvalue_p (TREE_OPERAND (exp, 0));
532
533 case COND_EXPR:
534 return (lvalue_p (TREE_OPERAND (exp, 1)
535 ? TREE_OPERAND (exp, 1)
536 : TREE_OPERAND (exp, 0))
537 && lvalue_p (TREE_OPERAND (exp, 2)));
538
539 case TARGET_EXPR:
540 return true;
541
542 case COMPOUND_EXPR:
543 return lvalue_p (TREE_OPERAND (exp, 1));
544
545 default:
546 return false;
547 }
548}
549
550/* Create a SAVE_EXPR if EXP might have unwanted side effects if referenced
551 more than once in an expression. */
552
553tree
554d_save_expr (tree exp)
555{
556 if (TREE_SIDE_EFFECTS (exp))
557 {
558 if (lvalue_p (exp))
559 return stabilize_reference (exp);
560
561 return save_expr (exp);
562 }
563
564 return exp;
565}
566
567/* VALUEP is an expression we want to pre-evaluate or perform a computation on.
568 The expression returned by this function is the part whose value we don't
569 care about, storing the value in VALUEP. Callers must ensure that the
570 returned expression is evaluated before VALUEP. */
571
572tree
573stabilize_expr (tree *valuep)
574{
575 tree expr = *valuep;
576 const enum tree_code code = TREE_CODE (expr);
577 tree lhs;
578 tree rhs;
579
580 switch (code)
581 {
582 case COMPOUND_EXPR:
583 /* Given ((e1, ...), eN):
584 Store the last RHS 'eN' expression in VALUEP. */
585 lhs = TREE_OPERAND (expr, 0);
586 rhs = TREE_OPERAND (expr, 1);
587 lhs = compound_expr (lhs, stabilize_expr (&rhs));
588 *valuep = rhs;
589 return lhs;
590
591 default:
592 return NULL_TREE;
593 }
594}
595
596/* Return a TARGET_EXPR, initializing the DECL with EXP. */
597
598tree
599build_target_expr (tree decl, tree exp)
600{
601 tree type = TREE_TYPE (decl);
602 tree result = build4 (TARGET_EXPR, type, decl, exp, NULL_TREE, NULL_TREE);
603
604 if (EXPR_HAS_LOCATION (exp))
605 SET_EXPR_LOCATION (result, EXPR_LOCATION (exp));
606
607 /* If decl must always reside in memory. */
608 if (TREE_ADDRESSABLE (type))
609 d_mark_addressable (decl);
610
611 /* Always set TREE_SIDE_EFFECTS so that expand_expr does not ignore the
612 TARGET_EXPR. If there really turn out to be no side effects, then the
613 optimizer should be able to remove it. */
614 TREE_SIDE_EFFECTS (result) = 1;
615
616 return result;
617}
618
619/* Like the above function, but initializes a new temporary. */
620
621tree
622force_target_expr (tree exp)
623{
0af711e1
IB
624 tree decl = build_decl (input_location, VAR_DECL, NULL_TREE,
625 TREE_TYPE (exp));
626 DECL_CONTEXT (decl) = current_function_decl;
627 DECL_ARTIFICIAL (decl) = 1;
628 DECL_IGNORED_P (decl) = 1;
629 layout_decl (decl, 0);
b4c522fa
IB
630
631 return build_target_expr (decl, exp);
632}
633
634/* Returns the address of the expression EXP. */
635
636tree
637build_address (tree exp)
638{
639 if (error_operand_p (exp))
640 return exp;
641
642 tree ptrtype;
643 tree type = TREE_TYPE (exp);
644
645 if (TREE_CODE (exp) == STRING_CST)
646 {
647 /* Just convert string literals (char[]) to C-style strings (char *),
648 otherwise the latter method (char[]*) causes conversion problems
649 during gimplification. */
650 ptrtype = build_pointer_type (TREE_TYPE (type));
651 }
652 else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (va_list_type_node)
653 && TREE_CODE (TYPE_MAIN_VARIANT (type)) == ARRAY_TYPE)
654 {
655 /* Special case for va_list, allow arrays to decay to a pointer. */
656 ptrtype = build_pointer_type (TREE_TYPE (type));
657 }
658 else
659 ptrtype = build_pointer_type (type);
660
661 /* Maybe rewrite: &(e1, e2) => (e1, &e2). */
662 tree init = stabilize_expr (&exp);
663
664 /* Can't take the address of a manifest constant, instead use its value. */
665 if (TREE_CODE (exp) == CONST_DECL)
666 exp = DECL_INITIAL (exp);
667
884efbd5
IB
668 /* Some expression lowering may request an address of a compile-time constant,
669 or other non-lvalue expression. Make sure it is assigned to a location we
670 can reference. */
671 if ((CONSTANT_CLASS_P (exp) && TREE_CODE (exp) != STRING_CST)
672 || TREE_CODE (exp) == CALL_EXPR)
b4c522fa
IB
673 exp = force_target_expr (exp);
674
675 d_mark_addressable (exp);
676 exp = build_fold_addr_expr_with_type_loc (input_location, exp, ptrtype);
677
678 if (TREE_CODE (exp) == ADDR_EXPR)
679 TREE_NO_TRAMPOLINE (exp) = 1;
680
681 return compound_expr (init, exp);
682}
683
684/* Mark EXP saying that we need to be able to take the
685 address of it; it should not be allocated in a register. */
686
687tree
688d_mark_addressable (tree exp)
689{
690 switch (TREE_CODE (exp))
691 {
692 case ADDR_EXPR:
693 case COMPONENT_REF:
694 case ARRAY_REF:
695 case REALPART_EXPR:
696 case IMAGPART_EXPR:
697 d_mark_addressable (TREE_OPERAND (exp, 0));
698 break;
699
700 case PARM_DECL:
701 case VAR_DECL:
702 case RESULT_DECL:
703 case CONST_DECL:
704 case FUNCTION_DECL:
705 TREE_ADDRESSABLE (exp) = 1;
706 break;
707
708 case CONSTRUCTOR:
709 TREE_ADDRESSABLE (exp) = 1;
710 break;
711
712 case TARGET_EXPR:
713 TREE_ADDRESSABLE (exp) = 1;
714 d_mark_addressable (TREE_OPERAND (exp, 0));
715 break;
716
717 default:
718 break;
719 }
720
721 return exp;
722}
723
724/* Mark EXP as "used" in the program for the benefit of
725 -Wunused warning purposes. */
726
727tree
728d_mark_used (tree exp)
729{
730 switch (TREE_CODE (exp))
731 {
732 case VAR_DECL:
733 case CONST_DECL:
734 case PARM_DECL:
735 case RESULT_DECL:
736 case FUNCTION_DECL:
737 TREE_USED (exp) = 1;
738 break;
739
740 case ARRAY_REF:
741 case COMPONENT_REF:
742 case MODIFY_EXPR:
743 case REALPART_EXPR:
744 case IMAGPART_EXPR:
745 case NOP_EXPR:
746 case CONVERT_EXPR:
747 case ADDR_EXPR:
748 d_mark_used (TREE_OPERAND (exp, 0));
749 break;
750
751 case COMPOUND_EXPR:
752 d_mark_used (TREE_OPERAND (exp, 0));
753 d_mark_used (TREE_OPERAND (exp, 1));
754 break;
755
756 default:
757 break;
758 }
759 return exp;
760}
761
762/* Mark EXP as read, not just set, for set but not used -Wunused
763 warning purposes. */
764
765tree
766d_mark_read (tree exp)
767{
768 switch (TREE_CODE (exp))
769 {
770 case VAR_DECL:
771 case PARM_DECL:
772 TREE_USED (exp) = 1;
773 DECL_READ_P (exp) = 1;
774 break;
775
776 case ARRAY_REF:
777 case COMPONENT_REF:
778 case MODIFY_EXPR:
779 case REALPART_EXPR:
780 case IMAGPART_EXPR:
781 case NOP_EXPR:
782 case CONVERT_EXPR:
783 case ADDR_EXPR:
784 d_mark_read (TREE_OPERAND (exp, 0));
785 break;
786
787 case COMPOUND_EXPR:
788 d_mark_read (TREE_OPERAND (exp, 1));
789 break;
790
791 default:
792 break;
793 }
794 return exp;
795}
796
797/* Return TRUE if the struct SD is suitable for comparison using memcmp.
798 This is because we don't guarantee that padding is zero-initialized for
799 a stack variable, so we can't use memcmp to compare struct values. */
800
801bool
802identity_compare_p (StructDeclaration *sd)
803{
804 if (sd->isUnionDeclaration ())
805 return true;
806
807 unsigned offset = 0;
808
2cbc99d1 809 for (size_t i = 0; i < sd->fields.length; i++)
b4c522fa
IB
810 {
811 VarDeclaration *vd = sd->fields[i];
5bdebb51 812 Type *tb = vd->type->toBasetype ();
b4c522fa
IB
813
814 /* Check inner data structures. */
89fdaf5a 815 if (TypeStruct *ts = tb->isTypeStruct ())
b4c522fa 816 {
b4c522fa
IB
817 if (!identity_compare_p (ts->sym))
818 return false;
819 }
820
5bdebb51
IB
821 /* Check for types that may have padding. */
822 if ((tb->ty == Tcomplex80 || tb->ty == Tfloat80 || tb->ty == Timaginary80)
5905cbdb 823 && target.realpad != 0)
5bdebb51
IB
824 return false;
825
b4c522fa
IB
826 if (offset <= vd->offset)
827 {
828 /* There's a hole in the struct. */
829 if (offset != vd->offset)
830 return false;
831
832 offset += vd->type->size ();
833 }
834 }
835
836 /* Any trailing padding may not be zero. */
837 if (offset < sd->structsize)
838 return false;
839
840 return true;
841}
842
5bdebb51
IB
843/* Build a floating-point identity comparison between T1 and T2, ignoring any
844 excessive padding in the type. CODE is EQ_EXPR or NE_EXPR comparison. */
845
846tree
847build_float_identity (tree_code code, tree t1, tree t2)
848{
849 tree tmemcmp = builtin_decl_explicit (BUILT_IN_MEMCMP);
850 tree size = size_int (TYPE_PRECISION (TREE_TYPE (t1)) / BITS_PER_UNIT);
851
852 tree result = build_call_expr (tmemcmp, 3, build_address (t1),
853 build_address (t2), size);
854 return build_boolop (code, result, integer_zero_node);
855}
856
b4c522fa
IB
857/* Lower a field-by-field equality expression between T1 and T2 of type SD.
858 CODE is the EQ_EXPR or NE_EXPR comparison. */
859
860static tree
861lower_struct_comparison (tree_code code, StructDeclaration *sd,
862 tree t1, tree t2)
863{
864 tree_code tcode = (code == EQ_EXPR) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
865 tree tmemcmp = NULL_TREE;
866
867 /* We can skip the compare if the structs are empty. */
2cbc99d1 868 if (sd->fields.length == 0)
b4c522fa
IB
869 {
870 tmemcmp = build_boolop (code, integer_zero_node, integer_zero_node);
871 if (TREE_SIDE_EFFECTS (t2))
872 tmemcmp = compound_expr (t2, tmemcmp);
873 if (TREE_SIDE_EFFECTS (t1))
874 tmemcmp = compound_expr (t1, tmemcmp);
875
876 return tmemcmp;
877 }
878
879 /* Let back-end take care of union comparisons. */
880 if (sd->isUnionDeclaration ())
881 {
882 tmemcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP), 3,
883 build_address (t1), build_address (t2),
884 size_int (sd->structsize));
885
886 return build_boolop (code, tmemcmp, integer_zero_node);
887 }
888
2cbc99d1 889 for (size_t i = 0; i < sd->fields.length; i++)
b4c522fa
IB
890 {
891 VarDeclaration *vd = sd->fields[i];
5bdebb51 892 Type *type = vd->type->toBasetype ();
b4c522fa
IB
893 tree sfield = get_symbol_decl (vd);
894
895 tree t1ref = component_ref (t1, sfield);
896 tree t2ref = component_ref (t2, sfield);
897 tree tcmp;
898
89fdaf5a 899 if (TypeStruct *ts = type->isTypeStruct ())
b4c522fa
IB
900 {
901 /* Compare inner data structures. */
89fdaf5a 902 tcmp = lower_struct_comparison (code, ts->sym, t1ref, t2ref);
b4c522fa 903 }
5bdebb51
IB
904 else if (type->ty != Tvector && type->isintegral ())
905 {
906 /* Integer comparison, no special handling required. */
907 tcmp = build_boolop (code, t1ref, t2ref);
908 }
909 else if (type->ty != Tvector && type->isfloating ())
910 {
911 /* Floating-point comparison, don't compare padding in type. */
912 if (!type->iscomplex ())
913 tcmp = build_float_identity (code, t1ref, t2ref);
914 else
915 {
916 tree req = build_float_identity (code, real_part (t1ref),
917 real_part (t2ref));
918 tree ieq = build_float_identity (code, imaginary_part (t1ref),
919 imaginary_part (t2ref));
920
921 tcmp = build_boolop (tcode, req, ieq);
922 }
923 }
b4c522fa
IB
924 else
925 {
5bdebb51 926 tree stype = build_ctype (type);
b4c522fa
IB
927 opt_scalar_int_mode mode = int_mode_for_mode (TYPE_MODE (stype));
928
5bdebb51 929 if (mode.exists ())
b4c522fa
IB
930 {
931 /* Compare field bits as their corresponding integer type.
932 *((T*) &t1) == *((T*) &t2) */
933 tree tmode = lang_hooks.types.type_for_mode (mode.require (), 1);
934
935 if (tmode == NULL_TREE)
936 tmode = make_unsigned_type (GET_MODE_BITSIZE (mode.require ()));
937
938 t1ref = build_vconvert (tmode, t1ref);
939 t2ref = build_vconvert (tmode, t2ref);
940
941 tcmp = build_boolop (code, t1ref, t2ref);
942 }
943 else
944 {
945 /* Simple memcmp between types. */
946 tcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP),
947 3, build_address (t1ref),
948 build_address (t2ref),
949 TYPE_SIZE_UNIT (stype));
950
951 tcmp = build_boolop (code, tcmp, integer_zero_node);
952 }
953 }
954
955 tmemcmp = (tmemcmp) ? build_boolop (tcode, tmemcmp, tcmp) : tcmp;
956 }
957
958 return tmemcmp;
959}
960
961
962/* Build an equality expression between two RECORD_TYPES T1 and T2 of type SD.
963 If possible, use memcmp, otherwise field-by-field comparison is done.
964 CODE is the EQ_EXPR or NE_EXPR comparison. */
965
966tree
967build_struct_comparison (tree_code code, StructDeclaration *sd,
968 tree t1, tree t2)
969{
970 /* We can skip the compare if the structs are empty. */
2cbc99d1 971 if (sd->fields.length == 0)
b4c522fa
IB
972 {
973 tree exp = build_boolop (code, integer_zero_node, integer_zero_node);
974 if (TREE_SIDE_EFFECTS (t2))
975 exp = compound_expr (t2, exp);
976 if (TREE_SIDE_EFFECTS (t1))
977 exp = compound_expr (t1, exp);
978
979 return exp;
980 }
981
982 /* Make temporaries to prevent multiple evaluations. */
983 tree t1init = stabilize_expr (&t1);
984 tree t2init = stabilize_expr (&t2);
985 tree result;
986
987 t1 = d_save_expr (t1);
988 t2 = d_save_expr (t2);
989
990 /* Bitwise comparison of structs not returned in memory may not work
991 due to data holes loosing its zero padding upon return.
992 As a heuristic, small structs are not compared using memcmp either. */
993 if (TYPE_MODE (TREE_TYPE (t1)) != BLKmode || !identity_compare_p (sd))
994 result = lower_struct_comparison (code, sd, t1, t2);
995 else
996 {
997 /* Do bit compare of structs. */
998 tree size = size_int (sd->structsize);
999 tree tmemcmp = build_call_expr (builtin_decl_explicit (BUILT_IN_MEMCMP),
1000 3, build_address (t1),
1001 build_address (t2), size);
1002
1003 result = build_boolop (code, tmemcmp, integer_zero_node);
1004 }
1005
1006 return compound_expr (compound_expr (t1init, t2init), result);
1007}
1008
1009/* Build an equality expression between two ARRAY_TYPES of size LENGTH.
1010 The pointer references are T1 and T2, and the element type is SD.
1011 CODE is the EQ_EXPR or NE_EXPR comparison. */
1012
1013tree
1014build_array_struct_comparison (tree_code code, StructDeclaration *sd,
1015 tree length, tree t1, tree t2)
1016{
1017 tree_code tcode = (code == EQ_EXPR) ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
1018
1019 /* Build temporary for the result of the comparison.
1020 Initialize as either 0 or 1 depending on operation. */
1021 tree result = build_local_temp (d_bool_type);
1022 tree init = build_boolop (code, integer_zero_node, integer_zero_node);
1023 add_stmt (build_assign (INIT_EXPR, result, init));
1024
1025 /* Cast pointer-to-array to pointer-to-struct. */
1026 tree ptrtype = build_ctype (sd->type->pointerTo ());
1027 tree lentype = TREE_TYPE (length);
1028
1029 push_binding_level (level_block);
1030 push_stmt_list ();
1031
1032 /* Build temporary locals for length and pointers. */
1033 tree t = build_local_temp (size_type_node);
1034 add_stmt (build_assign (INIT_EXPR, t, length));
1035 length = t;
1036
1037 t = build_local_temp (ptrtype);
1038 add_stmt (build_assign (INIT_EXPR, t, d_convert (ptrtype, t1)));
1039 t1 = t;
1040
1041 t = build_local_temp (ptrtype);
1042 add_stmt (build_assign (INIT_EXPR, t, d_convert (ptrtype, t2)));
1043 t2 = t;
1044
1045 /* Build loop for comparing each element. */
1046 push_stmt_list ();
1047
1048 /* Exit logic for the loop.
1049 if (length == 0 || result OP 0) break; */
1050 t = build_boolop (EQ_EXPR, length, d_convert (lentype, integer_zero_node));
1051 t = build_boolop (TRUTH_ORIF_EXPR, t, build_boolop (code, result,
1052 boolean_false_node));
1053 t = build1 (EXIT_EXPR, void_type_node, t);
1054 add_stmt (t);
1055
1056 /* Do comparison, caching the value.
1057 result = result OP (*t1 == *t2); */
1058 t = build_struct_comparison (code, sd, build_deref (t1), build_deref (t2));
1059 t = build_boolop (tcode, result, t);
1060 t = modify_expr (result, t);
1061 add_stmt (t);
1062
1063 /* Move both pointers to next element position.
1064 t1++, t2++; */
1065 tree size = d_convert (ptrtype, TYPE_SIZE_UNIT (TREE_TYPE (ptrtype)));
1066 t = build2 (POSTINCREMENT_EXPR, ptrtype, t1, size);
1067 add_stmt (t);
1068 t = build2 (POSTINCREMENT_EXPR, ptrtype, t2, size);
1069 add_stmt (t);
1070
1071 /* Decrease loop counter.
1072 length -= 1; */
1073 t = build2 (POSTDECREMENT_EXPR, lentype, length,
1074 d_convert (lentype, integer_one_node));
1075 add_stmt (t);
1076
1077 /* Pop statements and finish loop. */
1078 tree body = pop_stmt_list ();
1079 add_stmt (build1 (LOOP_EXPR, void_type_node, body));
1080
1081 /* Wrap it up into a bind expression. */
1082 tree stmt_list = pop_stmt_list ();
1083 tree block = pop_binding_level ();
1084
1085 body = build3 (BIND_EXPR, void_type_node,
1086 BLOCK_VARS (block), stmt_list, block);
1087
1088 return compound_expr (body, result);
1089}
1090
b4c522fa
IB
1091/* Build a constructor for a variable of aggregate type TYPE using the
1092 initializer INIT, an ordered flat list of fields and values provided
1093 by the frontend. The returned constructor should be a value that
1094 matches the layout of TYPE. */
1095
1096tree
af3c19f0 1097build_struct_literal (tree type, vec <constructor_elt, va_gc> *init)
b4c522fa
IB
1098{
1099 /* If the initializer was empty, use default zero initialization. */
1100 if (vec_safe_is_empty (init))
1101 return build_constructor (type, NULL);
1102
af3c19f0 1103 vec <constructor_elt, va_gc> *ve = NULL;
b4c522fa
IB
1104 HOST_WIDE_INT offset = 0;
1105 bool constant_p = true;
b4c522fa
IB
1106 bool finished = false;
1107
b4c522fa
IB
1108 /* Walk through each field, matching our initializer list. */
1109 for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
1110 {
1111 bool is_initialized = false;
1112 tree value;
1113
1114 if (DECL_NAME (field) == NULL_TREE
1115 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
1116 && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
1117 {
1118 /* Search all nesting aggregates, if nothing is found, then
1119 this will return an empty initializer to fill the hole. */
1120 value = build_struct_literal (TREE_TYPE (field), init);
1121
1122 if (!initializer_zerop (value))
1123 is_initialized = true;
1124 }
1125 else
1126 {
1127 /* Search for the value to initialize the next field. Once found,
1128 pop it from the init list so we don't look at it again. */
1129 unsigned HOST_WIDE_INT idx;
1130 tree index;
1131
1132 FOR_EACH_CONSTRUCTOR_ELT (init, idx, index, value)
1133 {
1134 /* If the index is NULL, then just assign it to the next field.
1135 This comes from layout_typeinfo(), which generates a flat
1136 list of values that we must shape into the record type. */
1137 if (index == field || index == NULL_TREE)
1138 {
1139 init->ordered_remove (idx);
1140 if (!finished)
1141 is_initialized = true;
1142 break;
1143 }
1144 }
1145 }
1146
1147 if (is_initialized)
1148 {
1149 HOST_WIDE_INT fieldpos = int_byte_position (field);
1150 gcc_assert (value != NULL_TREE);
1151
b4c522fa
IB
1152 /* Must not initialize fields that overlap. */
1153 if (fieldpos < offset)
1154 {
1155 /* Find the nearest user defined type and field. */
1156 tree vtype = type;
1157 while (ANON_AGGR_TYPE_P (vtype))
1158 vtype = TYPE_CONTEXT (vtype);
1159
1160 tree vfield = field;
1161 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (vfield))
1162 && ANON_AGGR_TYPE_P (TREE_TYPE (vfield)))
1163 vfield = TYPE_FIELDS (TREE_TYPE (vfield));
1164
1165 /* Must not generate errors for compiler generated fields. */
1166 gcc_assert (TYPE_NAME (vtype) && DECL_NAME (vfield));
1167 error ("overlapping initializer for field %qT.%qD",
1168 TYPE_NAME (vtype), DECL_NAME (vfield));
1169 }
1170
1171 if (!TREE_CONSTANT (value))
1172 constant_p = false;
1173
1174 CONSTRUCTOR_APPEND_ELT (ve, field, value);
1175
1176 /* For unions, only the first field is initialized, any other field
1177 initializers found for this union are drained and ignored. */
1178 if (TREE_CODE (type) == UNION_TYPE)
1179 finished = true;
1180 }
1181
1182 /* Move offset to the next position in the struct. */
1183 if (TREE_CODE (type) == RECORD_TYPE)
1184 {
1185 offset = int_byte_position (field)
1186 + int_size_in_bytes (TREE_TYPE (field));
1187 }
1188
1189 /* If all initializers have been assigned, there's nothing else to do. */
1190 if (vec_safe_is_empty (init))
1191 break;
1192 }
1193
b4c522fa
IB
1194 /* Ensure that we have consumed all values. */
1195 gcc_assert (vec_safe_is_empty (init) || ANON_AGGR_TYPE_P (type));
1196
1197 tree ctor = build_constructor (type, ve);
1198
1199 if (constant_p)
1200 TREE_CONSTANT (ctor) = 1;
1201
1202 return ctor;
1203}
1204
1205/* Given the TYPE of an anonymous field inside T, return the
1206 FIELD_DECL for the field. If not found return NULL_TREE.
1207 Because anonymous types can nest, we must also search all
1208 anonymous fields that are directly reachable. */
1209
1210static tree
1211lookup_anon_field (tree t, tree type)
1212{
1213 t = TYPE_MAIN_VARIANT (t);
1214
1215 for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
1216 {
1217 if (DECL_NAME (field) == NULL_TREE)
1218 {
1219 /* If we find it directly, return the field. */
1220 if (type == TYPE_MAIN_VARIANT (TREE_TYPE (field)))
1221 return field;
1222
1223 /* Otherwise, it could be nested, search harder. */
1224 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (field))
1225 && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
1226 {
1227 tree subfield = lookup_anon_field (TREE_TYPE (field), type);
1228 if (subfield)
1229 return subfield;
1230 }
1231 }
1232 }
1233
1234 return NULL_TREE;
1235}
1236
1237/* Builds OBJECT.FIELD component reference. */
1238
1239tree
1240component_ref (tree object, tree field)
1241{
1242 if (error_operand_p (object) || error_operand_p (field))
1243 return error_mark_node;
1244
1245 gcc_assert (TREE_CODE (field) == FIELD_DECL);
1246
1247 /* Maybe rewrite: (e1, e2).field => (e1, e2.field) */
1248 tree init = stabilize_expr (&object);
1249
1250 /* If the FIELD is from an anonymous aggregate, generate a reference
1251 to the anonymous data member, and recur to find FIELD. */
1252 if (ANON_AGGR_TYPE_P (DECL_CONTEXT (field)))
1253 {
1254 tree anonymous_field = lookup_anon_field (TREE_TYPE (object),
1255 DECL_CONTEXT (field));
1256 object = component_ref (object, anonymous_field);
1257 }
1258
1259 tree result = fold_build3_loc (input_location, COMPONENT_REF,
1260 TREE_TYPE (field), object, field, NULL_TREE);
1261
1262 return compound_expr (init, result);
1263}
1264
1265/* Build an assignment expression of lvalue LHS from value RHS.
1266 CODE is the code for a binary operator that we use to combine
1267 the old value of LHS with RHS to get the new value. */
1268
1269tree
1270build_assign (tree_code code, tree lhs, tree rhs)
1271{
1272 tree init = stabilize_expr (&lhs);
1273 init = compound_expr (init, stabilize_expr (&rhs));
1274
1275 /* If initializing the LHS using a function that returns via NRVO. */
1276 if (code == INIT_EXPR && TREE_CODE (rhs) == CALL_EXPR
1277 && AGGREGATE_TYPE_P (TREE_TYPE (rhs))
1278 && aggregate_value_p (TREE_TYPE (rhs), rhs))
1279 {
1280 /* Mark as addressable here, which should ensure the return slot is the
1281 address of the LHS expression, taken care of by back-end. */
1282 d_mark_addressable (lhs);
1283 CALL_EXPR_RETURN_SLOT_OPT (rhs) = true;
1284 }
1285
1286 /* The LHS assignment replaces the temporary in TARGET_EXPR_SLOT. */
1287 if (TREE_CODE (rhs) == TARGET_EXPR)
1288 {
1289 /* If CODE is not INIT_EXPR, can't initialize LHS directly,
1290 since that would cause the LHS to be constructed twice.
1291 So we force the TARGET_EXPR to be expanded without a target. */
1292 if (code != INIT_EXPR)
1293 rhs = compound_expr (rhs, TARGET_EXPR_SLOT (rhs));
1294 else
1295 {
1296 d_mark_addressable (lhs);
1297 rhs = TARGET_EXPR_INITIAL (rhs);
1298 }
1299 }
1300
1301 tree result = fold_build2_loc (input_location, code,
1302 TREE_TYPE (lhs), lhs, rhs);
1303 return compound_expr (init, result);
1304}
1305
1306/* Build an assignment expression of lvalue LHS from value RHS. */
1307
1308tree
1309modify_expr (tree lhs, tree rhs)
1310{
1311 return build_assign (MODIFY_EXPR, lhs, rhs);
1312}
1313
1314/* Return EXP represented as TYPE. */
1315
1316tree
1317build_nop (tree type, tree exp)
1318{
1319 if (error_operand_p (exp))
1320 return exp;
1321
1322 /* Maybe rewrite: cast(TYPE)(e1, e2) => (e1, cast(TYPE) e2) */
1323 tree init = stabilize_expr (&exp);
1324 exp = fold_build1_loc (input_location, NOP_EXPR, type, exp);
1325
1326 return compound_expr (init, exp);
1327}
1328
1329/* Return EXP to be viewed as being another type TYPE. Same as build_nop,
1330 except that EXP is type-punned, rather than a straight-forward cast. */
1331
1332tree
1333build_vconvert (tree type, tree exp)
1334{
1335 /* Building *(cast(TYPE *)&e1) directly rather then using VIEW_CONVERT_EXPR
1336 makes sure this works for vector-to-array viewing, or if EXP ends up being
1337 used as the LHS of a MODIFY_EXPR. */
1338 return indirect_ref (type, build_address (exp));
1339}
1340
1341/* Maybe warn about ARG being an address that can never be null. */
1342
1343static void
1344warn_for_null_address (tree arg)
1345{
1346 if (TREE_CODE (arg) == ADDR_EXPR
1347 && decl_with_nonnull_addr_p (TREE_OPERAND (arg, 0)))
1348 warning (OPT_Waddress,
1349 "the address of %qD will never be %<null%>",
1350 TREE_OPERAND (arg, 0));
1351}
1352
1353/* Build a boolean ARG0 op ARG1 expression. */
1354
1355tree
1356build_boolop (tree_code code, tree arg0, tree arg1)
1357{
1358 /* Aggregate comparisons may get lowered to a call to builtin memcmp,
1359 so need to remove all side effects incase its address is taken. */
1360 if (AGGREGATE_TYPE_P (TREE_TYPE (arg0)))
1361 arg0 = d_save_expr (arg0);
1362 if (AGGREGATE_TYPE_P (TREE_TYPE (arg1)))
1363 arg1 = d_save_expr (arg1);
1364
1365 if (VECTOR_TYPE_P (TREE_TYPE (arg0)) && VECTOR_TYPE_P (TREE_TYPE (arg1)))
1366 {
1367 /* Build a vector comparison.
1368 VEC_COND_EXPR <e1 op e2, { -1, -1, -1, -1 }, { 0, 0, 0, 0 }>; */
1369 tree type = TREE_TYPE (arg0);
e8738f4e 1370 tree cmptype = truth_type_for (type);
b4c522fa
IB
1371 tree cmp = fold_build2_loc (input_location, code, cmptype, arg0, arg1);
1372
1373 return fold_build3_loc (input_location, VEC_COND_EXPR, type, cmp,
1374 build_minus_one_cst (type),
1375 build_zero_cst (type));
1376 }
1377
1378 if (code == EQ_EXPR || code == NE_EXPR)
1379 {
1380 /* Check if comparing the address of a variable to null. */
1381 if (POINTER_TYPE_P (TREE_TYPE (arg0)) && integer_zerop (arg1))
1382 warn_for_null_address (arg0);
1383 if (POINTER_TYPE_P (TREE_TYPE (arg1)) && integer_zerop (arg0))
1384 warn_for_null_address (arg1);
1385 }
1386
1387 return fold_build2_loc (input_location, code, d_bool_type,
1388 arg0, d_convert (TREE_TYPE (arg0), arg1));
1389}
1390
1391/* Return a COND_EXPR. ARG0, ARG1, and ARG2 are the three
1392 arguments to the conditional expression. */
1393
1394tree
1395build_condition (tree type, tree arg0, tree arg1, tree arg2)
1396{
1397 if (arg1 == void_node)
1398 arg1 = build_empty_stmt (input_location);
1399
1400 if (arg2 == void_node)
1401 arg2 = build_empty_stmt (input_location);
1402
1403 return fold_build3_loc (input_location, COND_EXPR,
1404 type, arg0, arg1, arg2);
1405}
1406
1407tree
1408build_vcondition (tree arg0, tree arg1, tree arg2)
1409{
1410 return build_condition (void_type_node, arg0, arg1, arg2);
1411}
1412
1413/* Build a compound expr to join ARG0 and ARG1 together. */
1414
1415tree
1416compound_expr (tree arg0, tree arg1)
1417{
1418 if (arg1 == NULL_TREE)
1419 return arg0;
1420
1421 if (arg0 == NULL_TREE || !TREE_SIDE_EFFECTS (arg0))
1422 return arg1;
1423
1424 if (TREE_CODE (arg1) == TARGET_EXPR)
1425 {
1426 /* If the rhs is a TARGET_EXPR, then build the compound expression
1427 inside the target_expr's initializer. This helps the compiler
1428 to eliminate unnecessary temporaries. */
1429 tree init = compound_expr (arg0, TARGET_EXPR_INITIAL (arg1));
1430 TARGET_EXPR_INITIAL (arg1) = init;
1431
1432 return arg1;
1433 }
1434
1435 return fold_build2_loc (input_location, COMPOUND_EXPR,
1436 TREE_TYPE (arg1), arg0, arg1);
1437}
1438
1439/* Build a return expression. */
1440
1441tree
1442return_expr (tree ret)
1443{
1444 return fold_build1_loc (input_location, RETURN_EXPR,
1445 void_type_node, ret);
1446}
1447
1448/* Return the product of ARG0 and ARG1 as a size_type_node. */
1449
1450tree
1451size_mult_expr (tree arg0, tree arg1)
1452{
1453 return fold_build2_loc (input_location, MULT_EXPR, size_type_node,
1454 d_convert (size_type_node, arg0),
1455 d_convert (size_type_node, arg1));
1456
1457}
1458
1459/* Return the real part of CE, which should be a complex expression. */
1460
1461tree
1462real_part (tree ce)
1463{
1464 return fold_build1_loc (input_location, REALPART_EXPR,
1465 TREE_TYPE (TREE_TYPE (ce)), ce);
1466}
1467
1468/* Return the imaginary part of CE, which should be a complex expression. */
1469
1470tree
1471imaginary_part (tree ce)
1472{
1473 return fold_build1_loc (input_location, IMAGPART_EXPR,
1474 TREE_TYPE (TREE_TYPE (ce)), ce);
1475}
1476
1477/* Build a complex expression of type TYPE using RE and IM. */
1478
1479tree
1480complex_expr (tree type, tree re, tree im)
1481{
1482 return fold_build2_loc (input_location, COMPLEX_EXPR,
1483 type, re, im);
1484}
1485
1486/* Cast EXP (which should be a pointer) to TYPE* and then indirect.
1487 The back-end requires this cast in many cases. */
1488
1489tree
1490indirect_ref (tree type, tree exp)
1491{
1492 if (error_operand_p (exp))
1493 return exp;
1494
1495 /* Maybe rewrite: *(e1, e2) => (e1, *e2) */
1496 tree init = stabilize_expr (&exp);
1497
1498 if (TREE_CODE (TREE_TYPE (exp)) == REFERENCE_TYPE)
1499 exp = fold_build1 (INDIRECT_REF, type, exp);
1500 else
1501 {
1502 exp = build_nop (build_pointer_type (type), exp);
1503 exp = build_deref (exp);
1504 }
1505
1506 return compound_expr (init, exp);
1507}
1508
1509/* Returns indirect reference of EXP, which must be a pointer type. */
1510
1511tree
1512build_deref (tree exp)
1513{
1514 if (error_operand_p (exp))
1515 return exp;
1516
1517 /* Maybe rewrite: *(e1, e2) => (e1, *e2) */
1518 tree init = stabilize_expr (&exp);
1519
1520 gcc_assert (POINTER_TYPE_P (TREE_TYPE (exp)));
1521
1522 if (TREE_CODE (exp) == ADDR_EXPR)
1523 exp = TREE_OPERAND (exp, 0);
1524 else
1525 exp = build_fold_indirect_ref (exp);
1526
1527 return compound_expr (init, exp);
1528}
1529
1530/* Builds pointer offset expression PTR[INDEX]. */
1531
1532tree
1533build_array_index (tree ptr, tree index)
1534{
1535 if (error_operand_p (ptr) || error_operand_p (index))
1536 return error_mark_node;
1537
1538 tree ptr_type = TREE_TYPE (ptr);
1539 tree target_type = TREE_TYPE (ptr_type);
1540
1541 tree type = lang_hooks.types.type_for_size (TYPE_PRECISION (sizetype),
1542 TYPE_UNSIGNED (sizetype));
1543
1544 /* Array element size. */
1545 tree size_exp = size_in_bytes (target_type);
1546
1547 if (integer_zerop (size_exp))
1548 {
1549 /* Test for array of void. */
1550 if (TYPE_MODE (target_type) == TYPE_MODE (void_type_node))
1551 index = fold_convert (type, index);
1552 else
1553 {
1554 /* Should catch this earlier. */
1555 error ("invalid use of incomplete type %qD", TYPE_NAME (target_type));
1556 ptr_type = error_mark_node;
1557 }
1558 }
1559 else if (integer_onep (size_exp))
1560 {
1561 /* Array of bytes -- No need to multiply. */
1562 index = fold_convert (type, index);
1563 }
1564 else
1565 {
1566 index = d_convert (type, index);
1567 index = fold_build2 (MULT_EXPR, TREE_TYPE (index),
1568 index, d_convert (TREE_TYPE (index), size_exp));
1569 index = fold_convert (type, index);
1570 }
1571
1572 if (integer_zerop (index))
1573 return ptr;
1574
1575 return fold_build2 (POINTER_PLUS_EXPR, ptr_type, ptr, index);
1576}
1577
1578/* Builds pointer offset expression *(PTR OP OFFSET)
1579 OP could be a plus or minus expression. */
1580
1581tree
1582build_offset_op (tree_code op, tree ptr, tree offset)
1583{
1584 gcc_assert (op == MINUS_EXPR || op == PLUS_EXPR);
1585
1586 tree type = lang_hooks.types.type_for_size (TYPE_PRECISION (sizetype),
1587 TYPE_UNSIGNED (sizetype));
1588 offset = fold_convert (type, offset);
1589
1590 if (op == MINUS_EXPR)
1591 offset = fold_build1 (NEGATE_EXPR, type, offset);
1592
1593 return fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (ptr), ptr, offset);
1594}
1595
1596/* Builds pointer offset expression *(PTR + OFFSET). */
1597
1598tree
1599build_offset (tree ptr, tree offset)
1600{
1601 return build_offset_op (PLUS_EXPR, ptr, offset);
1602}
1603
1604tree
1605build_memref (tree type, tree ptr, tree offset)
1606{
1607 return fold_build2 (MEM_REF, type, ptr, fold_convert (type, offset));
1608}
1609
1610/* Create a tree node to set multiple elements to a single value. */
1611
1612tree
1613build_array_set (tree ptr, tree length, tree value)
1614{
1615 tree ptrtype = TREE_TYPE (ptr);
1616 tree lentype = TREE_TYPE (length);
1617
1618 push_binding_level (level_block);
1619 push_stmt_list ();
1620
1621 /* Build temporary locals for length and ptr, and maybe value. */
1622 tree t = build_local_temp (size_type_node);
1623 add_stmt (build_assign (INIT_EXPR, t, length));
1624 length = t;
1625
1626 t = build_local_temp (ptrtype);
1627 add_stmt (build_assign (INIT_EXPR, t, ptr));
1628 ptr = t;
1629
1630 if (TREE_SIDE_EFFECTS (value))
1631 {
1632 t = build_local_temp (TREE_TYPE (value));
1633 add_stmt (build_assign (INIT_EXPR, t, value));
1634 value = t;
1635 }
1636
1637 /* Build loop to initialize { .length=length, .ptr=ptr } with value. */
1638 push_stmt_list ();
1639
1640 /* Exit logic for the loop.
1641 if (length == 0) break; */
1642 t = build_boolop (EQ_EXPR, length, d_convert (lentype, integer_zero_node));
1643 t = build1 (EXIT_EXPR, void_type_node, t);
1644 add_stmt (t);
1645
1646 /* Assign value to the current pointer position.
1647 *ptr = value; */
1648 t = modify_expr (build_deref (ptr), value);
1649 add_stmt (t);
1650
1651 /* Move pointer to next element position.
1652 ptr++; */
1653 tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptrtype));
1654 t = build2 (POSTINCREMENT_EXPR, ptrtype, ptr, d_convert (ptrtype, size));
1655 add_stmt (t);
1656
1657 /* Decrease loop counter.
1658 length -= 1; */
1659 t = build2 (POSTDECREMENT_EXPR, lentype, length,
1660 d_convert (lentype, integer_one_node));
1661 add_stmt (t);
1662
1663 /* Pop statements and finish loop. */
1664 tree loop_body = pop_stmt_list ();
1665 add_stmt (build1 (LOOP_EXPR, void_type_node, loop_body));
1666
1667 /* Wrap it up into a bind expression. */
1668 tree stmt_list = pop_stmt_list ();
1669 tree block = pop_binding_level ();
1670
1671 return build3 (BIND_EXPR, void_type_node,
1672 BLOCK_VARS (block), stmt_list, block);
1673}
1674
1675
1676/* Build an array of type TYPE where all the elements are VAL. */
1677
1678tree
1679build_array_from_val (Type *type, tree val)
1680{
b4c522fa
IB
1681 tree etype = build_ctype (type->nextOf ());
1682
1683 /* Initializing a multidimensional array. */
1684 if (TREE_CODE (etype) == ARRAY_TYPE && TREE_TYPE (val) != etype)
1685 val = build_array_from_val (type->nextOf (), val);
1686
89fdaf5a 1687 size_t dims = type->isTypeSArray ()->dim->toInteger ();
af3c19f0 1688 vec <constructor_elt, va_gc> *elms = NULL;
b4c522fa
IB
1689 vec_safe_reserve (elms, dims);
1690
1691 val = d_convert (etype, val);
1692
1693 for (size_t i = 0; i < dims; i++)
1694 CONSTRUCTOR_APPEND_ELT (elms, size_int (i), val);
1695
1696 return build_constructor (build_ctype (type), elms);
1697}
1698
1699/* Implicitly converts void* T to byte* as D allows { void[] a; &a[3]; } */
1700
1701tree
1702void_okay_p (tree t)
1703{
1704 tree type = TREE_TYPE (t);
1705
1706 if (VOID_TYPE_P (TREE_TYPE (type)))
1707 {
1708 tree totype = build_ctype (Type::tuns8->pointerTo ());
1709 return fold_convert (totype, t);
1710 }
1711
1712 return t;
1713}
1714
f267a310
IB
1715/* Builds a CALL_EXPR at location LOC in the source file to execute when an
1716 array bounds check fails. */
1717
1718tree
1719build_array_bounds_call (const Loc &loc)
1720{
1721 switch (global.params.checkAction)
1722 {
1723 case CHECKACTION_D:
1724 return d_assert_call (loc, LIBCALL_ARRAY_BOUNDS);
1725
1726 case CHECKACTION_C:
1727 case CHECKACTION_halt:
1728 return build_call_expr (builtin_decl_explicit (BUILT_IN_TRAP), 0);
1729
1730 default:
1731 gcc_unreachable ();
1732 }
1733}
1734
b4c522fa
IB
1735/* Builds a bounds condition checking that INDEX is between 0 and LEN.
1736 The condition returns the INDEX if true, or throws a RangeError.
1737 If INCLUSIVE, we allow INDEX == LEN to return true also. */
1738
1739tree
af3c19f0 1740build_bounds_condition (const Loc &loc, tree index, tree len, bool inclusive)
b4c522fa
IB
1741{
1742 if (!array_bounds_check ())
1743 return index;
1744
1745 /* Prevent multiple evaluations of the index. */
1746 index = d_save_expr (index);
1747
1748 /* Generate INDEX >= LEN && throw RangeError.
1749 No need to check whether INDEX >= 0 as the front-end should
1750 have already taken care of implicit casts to unsigned. */
1751 tree condition = fold_build2 (inclusive ? GT_EXPR : GE_EXPR,
1752 d_bool_type, index, len);
c0aebc60 1753 /* Terminate the program with a trap if no D runtime present. */
f267a310 1754 tree boundserr = build_array_bounds_call (loc);
b4c522fa
IB
1755
1756 return build_condition (TREE_TYPE (index), condition, boundserr, index);
1757}
1758
1759/* Returns TRUE if array bounds checking code generation is turned on. */
1760
1761bool
1762array_bounds_check (void)
1763{
1764 FuncDeclaration *fd;
1765
1766 switch (global.params.useArrayBounds)
1767 {
0cdc55f5 1768 case CHECKENABLEoff:
b4c522fa
IB
1769 return false;
1770
0cdc55f5 1771 case CHECKENABLEon:
b4c522fa
IB
1772 return true;
1773
0cdc55f5 1774 case CHECKENABLEsafeonly:
b4c522fa
IB
1775 /* For D2 safe functions only. */
1776 fd = d_function_chain->function;
1777 if (fd && fd->type->ty == Tfunction)
1778 {
89fdaf5a 1779 if (fd->type->isTypeFunction ()->trust == TRUSTsafe)
b4c522fa
IB
1780 return true;
1781 }
1782 return false;
1783
1784 default:
1785 gcc_unreachable ();
1786 }
1787}
1788
b4c522fa
IB
1789/* Returns the TypeFunction class for Type T.
1790 Assumes T is already ->toBasetype(). */
1791
1792TypeFunction *
1793get_function_type (Type *t)
1794{
1795 TypeFunction *tf = NULL;
1796 if (t->ty == Tpointer)
1797 t = t->nextOf ()->toBasetype ();
1798 if (t->ty == Tfunction)
89fdaf5a 1799 tf = t->isTypeFunction ();
b4c522fa 1800 else if (t->ty == Tdelegate)
89fdaf5a 1801 tf = t->isTypeDelegate ()->next->isTypeFunction ();
b4c522fa
IB
1802 return tf;
1803}
1804
1805/* Returns TRUE if CALLEE is a plain nested function outside the scope of
1806 CALLER. In which case, CALLEE is being called through an alias that was
1807 passed to CALLER. */
1808
1809bool
1810call_by_alias_p (FuncDeclaration *caller, FuncDeclaration *callee)
1811{
1812 if (!callee->isNested ())
1813 return false;
1814
1815 if (caller->toParent () == callee->toParent ())
1816 return false;
1817
1818 Dsymbol *dsym = callee;
1819
1820 while (dsym)
1821 {
1822 if (dsym->isTemplateInstance ())
1823 return false;
1824 else if (dsym->isFuncDeclaration () == caller)
1825 return false;
1826 dsym = dsym->toParent ();
1827 }
1828
1829 return true;
1830}
1831
1832/* Entry point for call routines. Builds a function call to FD.
cdbf48be 1833 OBJECT is the `this' reference passed and ARGS are the arguments to FD. */
b4c522fa
IB
1834
1835tree
1836d_build_call_expr (FuncDeclaration *fd, tree object, Expressions *arguments)
1837{
1838 return d_build_call (get_function_type (fd->type),
1839 build_address (get_symbol_decl (fd)), object, arguments);
1840}
1841
cdbf48be 1842/* Builds a CALL_EXPR of type TF to CALLABLE. OBJECT holds the `this' pointer,
b4c522fa
IB
1843 ARGUMENTS are evaluated in left to right order, saved and promoted
1844 before passing. */
1845
1846tree
1847d_build_call (TypeFunction *tf, tree callable, tree object,
1848 Expressions *arguments)
1849{
1850 tree ctype = TREE_TYPE (callable);
1851 tree callee = callable;
1852
1853 if (POINTER_TYPE_P (ctype))
1854 ctype = TREE_TYPE (ctype);
1855 else
1856 callee = build_address (callable);
1857
1858 gcc_assert (FUNC_OR_METHOD_TYPE_P (ctype));
1859 gcc_assert (tf != NULL);
1860 gcc_assert (tf->ty == Tfunction);
1861
1862 if (TREE_CODE (ctype) != FUNCTION_TYPE && object == NULL_TREE)
1863 {
1864 /* Front-end apparently doesn't check this. */
1865 if (TREE_CODE (callable) == FUNCTION_DECL)
1866 {
1867 error ("need %<this%> to access member %qE", DECL_NAME (callable));
1868 return error_mark_node;
1869 }
1870
1871 /* Probably an internal error. */
1872 gcc_unreachable ();
1873 }
1874
1875 /* Build the argument list for the call. */
af3c19f0 1876 vec <tree, va_gc> *args = NULL;
b4c522fa
IB
1877 tree saved_args = NULL_TREE;
1878
1879 /* If this is a delegate call or a nested function being called as
1880 a delegate, the object should not be NULL. */
1881 if (object != NULL_TREE)
1882 vec_safe_push (args, object);
1883
1884 if (arguments)
1885 {
1886 /* First pass, evaluated expanded tuples in function arguments. */
2cbc99d1 1887 for (size_t i = 0; i < arguments->length; ++i)
b4c522fa
IB
1888 {
1889 Lagain:
1890 Expression *arg = (*arguments)[i];
1891 gcc_assert (arg->op != TOKtuple);
1892
1893 if (arg->op == TOKcomma)
1894 {
d873350a 1895 CommaExp *ce = arg->isCommaExp ();
b4c522fa
IB
1896 tree tce = build_expr (ce->e1);
1897 saved_args = compound_expr (saved_args, tce);
1898 (*arguments)[i] = ce->e2;
1899 goto Lagain;
1900 }
1901 }
1902
c3a2ba10 1903 size_t nparams = tf->parameterList.length ();
b4c522fa 1904 /* if _arguments[] is the first argument. */
c3a2ba10 1905 size_t varargs = tf->isDstyleVariadic ();
b4c522fa 1906
2cbc99d1
IB
1907 /* Assumes arguments->length <= formal_args->length if (!tf->varargs). */
1908 for (size_t i = 0; i < arguments->length; ++i)
b4c522fa
IB
1909 {
1910 Expression *arg = (*arguments)[i];
1911 tree targ = build_expr (arg);
1912
1913 if (i - varargs < nparams && i >= varargs)
1914 {
1915 /* Actual arguments for declared formal arguments. */
c3a2ba10 1916 Parameter *parg = tf->parameterList[i - varargs];
b4c522fa
IB
1917 targ = convert_for_argument (targ, parg);
1918 }
1919
1920 /* Don't pass empty aggregates by value. */
1921 if (empty_aggregate_p (TREE_TYPE (targ)) && !TREE_ADDRESSABLE (targ)
1922 && TREE_CODE (targ) != CONSTRUCTOR)
1923 {
1924 tree t = build_constructor (TREE_TYPE (targ), NULL);
1925 targ = build2 (COMPOUND_EXPR, TREE_TYPE (t), targ, t);
1926 }
1927
2370bdbb
IB
1928 /* Parameter is a struct passed by invisible reference. */
1929 if (TREE_ADDRESSABLE (TREE_TYPE (targ)))
1930 {
1931 Type *t = arg->type->toBasetype ();
89fdaf5a 1932 StructDeclaration *sd = t->isTypeStruct ()->sym;
2370bdbb
IB
1933
1934 /* Nested structs also have ADDRESSABLE set, but if the type has
1935 neither a copy constructor nor a destructor available, then we
1936 need to take care of copying its value before passing it. */
1937 if (arg->op == TOKstructliteral || (!sd->postblit && !sd->dtor))
1938 targ = force_target_expr (targ);
1939
1940 targ = convert (build_reference_type (TREE_TYPE (targ)),
1941 build_address (targ));
1942 }
1943
b4c522fa
IB
1944 vec_safe_push (args, targ);
1945 }
1946 }
1947
1948 /* Evaluate the callee before calling it. */
1949 if (TREE_SIDE_EFFECTS (callee))
1950 {
1951 callee = d_save_expr (callee);
1952 saved_args = compound_expr (callee, saved_args);
1953 }
1954
1955 tree result = build_call_vec (TREE_TYPE (ctype), callee, args);
1956
1957 /* Enforce left to right evaluation. */
1958 if (tf->linkage == LINKd)
1959 CALL_EXPR_ARGS_ORDERED (result) = 1;
1960
1961 result = maybe_expand_intrinsic (result);
1962
1963 /* Return the value in a temporary slot so that it can be evaluated
1964 multiple times by the caller. */
1965 if (TREE_CODE (result) == CALL_EXPR
1966 && AGGREGATE_TYPE_P (TREE_TYPE (result))
1967 && TREE_ADDRESSABLE (TREE_TYPE (result)))
1968 {
1969 CALL_EXPR_RETURN_SLOT_OPT (result) = true;
1970 result = force_target_expr (result);
1971 }
1972
1973 return compound_expr (saved_args, result);
1974}
1975
1976/* Builds a call to AssertError or AssertErrorMsg. */
1977
1978tree
af3c19f0 1979d_assert_call (const Loc &loc, libcall_fn libcall, tree msg)
b4c522fa
IB
1980{
1981 tree file;
1982 tree line = size_int (loc.linnum);
1983
1984 /* File location is passed as a D string. */
1985 if (loc.filename)
1986 {
1987 unsigned len = strlen (loc.filename);
1988 tree str = build_string (len, loc.filename);
1989 TREE_TYPE (str) = make_array_type (Type::tchar, len);
1990
1991 file = d_array_value (build_ctype (Type::tchar->arrayOf ()),
1992 size_int (len), build_address (str));
1993 }
1994 else
1995 file = null_array_node;
1996
1997 if (msg != NULL)
1998 return build_libcall (libcall, Type::tvoid, 3, msg, file, line);
1999 else
2000 return build_libcall (libcall, Type::tvoid, 2, file, line);
2001}
2002
2003/* Build and return the correct call to fmod depending on TYPE.
2004 ARG0 and ARG1 are the arguments pass to the function. */
2005
2006tree
2007build_float_modulus (tree type, tree arg0, tree arg1)
2008{
2009 tree fmodfn = NULL_TREE;
2010 tree basetype = type;
2011
2012 if (COMPLEX_FLOAT_TYPE_P (basetype))
2013 basetype = TREE_TYPE (basetype);
2014
2015 if (TYPE_MAIN_VARIANT (basetype) == double_type_node
2016 || TYPE_MAIN_VARIANT (basetype) == idouble_type_node)
2017 fmodfn = builtin_decl_explicit (BUILT_IN_FMOD);
2018 else if (TYPE_MAIN_VARIANT (basetype) == float_type_node
2019 || TYPE_MAIN_VARIANT (basetype) == ifloat_type_node)
2020 fmodfn = builtin_decl_explicit (BUILT_IN_FMODF);
2021 else if (TYPE_MAIN_VARIANT (basetype) == long_double_type_node
2022 || TYPE_MAIN_VARIANT (basetype) == ireal_type_node)
2023 fmodfn = builtin_decl_explicit (BUILT_IN_FMODL);
2024
2025 if (!fmodfn)
2026 {
2027 error ("tried to perform floating-point modulo division on %qT", type);
2028 return error_mark_node;
2029 }
2030
2031 if (COMPLEX_FLOAT_TYPE_P (type))
2032 {
2033 tree re = build_call_expr (fmodfn, 2, real_part (arg0), arg1);
2034 tree im = build_call_expr (fmodfn, 2, imaginary_part (arg0), arg1);
2035
2036 return complex_expr (type, re, im);
2037 }
2038
2039 if (SCALAR_FLOAT_TYPE_P (type))
2040 return build_call_expr (fmodfn, 2, arg0, arg1);
2041
2042 /* Should have caught this above. */
2043 gcc_unreachable ();
2044}
2045
2046/* Build a function type whose first argument is a pointer to BASETYPE,
cdbf48be 2047 which is to be used for the `vthis' context parameter for TYPE.
b4c522fa
IB
2048 The base type may be a record for member functions, or a void for
2049 nested functions and delegates. */
2050
2051tree
2052build_vthis_function (tree basetype, tree type)
2053{
2054 gcc_assert (TREE_CODE (type) == FUNCTION_TYPE);
2055
2056 tree argtypes = tree_cons (NULL_TREE, build_pointer_type (basetype),
2057 TYPE_ARG_TYPES (type));
2058 tree fntype = build_function_type (TREE_TYPE (type), argtypes);
2059
2060 if (RECORD_OR_UNION_TYPE_P (basetype))
2061 TYPE_METHOD_BASETYPE (fntype) = TYPE_MAIN_VARIANT (basetype);
2062 else
2063 gcc_assert (VOID_TYPE_P (basetype));
2064
2065 return fntype;
2066}
2067
2068/* If SYM is a nested function, return the static chain to be
2069 used when calling that function from the current function.
2070
2071 If SYM is a nested class or struct, return the static chain
2072 to be used when creating an instance of the class from CFUN. */
2073
2074tree
2075get_frame_for_symbol (Dsymbol *sym)
2076{
2077 FuncDeclaration *thisfd
2078 = d_function_chain ? d_function_chain->function : NULL;
2079 FuncDeclaration *fd = sym->isFuncDeclaration ();
2080 FuncDeclaration *fdparent = NULL;
2081 FuncDeclaration *fdoverride = NULL;
2082
2083 if (fd != NULL)
2084 {
2085 /* Check that the nested function is properly defined. */
2086 if (!fd->fbody)
2087 {
cdbf48be 2088 /* Should instead error on line that references `fd'. */
b4c522fa
IB
2089 error_at (make_location_t (fd->loc), "nested function missing body");
2090 return null_pointer_node;
2091 }
2092
2093 fdparent = fd->toParent2 ()->isFuncDeclaration ();
2094
2095 /* Special case for __ensure and __require. */
2096 if ((fd->ident == Identifier::idPool ("__ensure")
2097 || fd->ident == Identifier::idPool ("__require"))
2098 && fdparent != thisfd)
2099 {
2100 fdoverride = fdparent;
2101 fdparent = thisfd;
2102 }
2103 }
2104 else
2105 {
2106 /* It's a class (or struct). NewExp codegen has already determined its
2107 outer scope is not another class, so it must be a function. */
2108 while (sym && !sym->isFuncDeclaration ())
2109 sym = sym->toParent2 ();
2110
2111 fdparent = (FuncDeclaration *) sym;
2112 }
2113
9fa5d5de
IB
2114 /* Not a nested function, there is no frame pointer to pass. */
2115 if (fdparent == NULL)
2116 {
2117 /* Only delegate literals report as being nested, even if they are in
2118 global scope. */
2119 gcc_assert (fd && fd->isFuncLiteralDeclaration ());
2120 return null_pointer_node;
2121 }
2122
2123 gcc_assert (thisfd != NULL);
b4c522fa
IB
2124
2125 if (thisfd != fdparent)
2126 {
2127 /* If no frame pointer for this function. */
2128 if (!thisfd->vthis)
2129 {
2130 error_at (make_location_t (sym->loc),
9fa5d5de
IB
2131 "%qs is a nested function and cannot be accessed from %qs",
2132 fd->toPrettyChars (), thisfd->toPrettyChars ());
b4c522fa
IB
2133 return null_pointer_node;
2134 }
2135
2136 /* Make sure we can get the frame pointer to the outer function.
2137 Go up each nesting level until we find the enclosing function. */
2138 Dsymbol *dsym = thisfd;
2139
2140 while (fd != dsym)
2141 {
2142 /* Check if enclosing function is a function. */
2143 FuncDeclaration *fd = dsym->isFuncDeclaration ();
2144
2145 if (fd != NULL)
2146 {
2147 if (fdparent == fd->toParent2 ())
2148 break;
2149
2150 gcc_assert (fd->isNested () || fd->vthis);
2151 dsym = dsym->toParent2 ();
2152 continue;
2153 }
2154
2155 /* Check if enclosed by an aggregate. That means the current
2156 function must be a member function of that aggregate. */
2157 AggregateDeclaration *ad = dsym->isAggregateDeclaration ();
2158
2159 if (ad == NULL)
2160 goto Lnoframe;
2161 if (ad->isClassDeclaration () && fdparent == ad->toParent2 ())
2162 break;
2163 if (ad->isStructDeclaration () && fdparent == ad->toParent2 ())
2164 break;
2165
2166 if (!ad->isNested () || !ad->vthis)
2167 {
2168 Lnoframe:
2169 error_at (make_location_t (thisfd->loc),
2170 "cannot get frame pointer to %qs",
2171 sym->toPrettyChars ());
2172 return null_pointer_node;
2173 }
2174
2175 dsym = dsym->toParent2 ();
2176 }
2177 }
2178
2179 tree ffo = get_frameinfo (fdparent);
2180 if (FRAMEINFO_CREATES_FRAME (ffo) || FRAMEINFO_STATIC_CHAIN (ffo))
2181 {
2182 tree frame_ref = get_framedecl (thisfd, fdparent);
2183
cdbf48be 2184 /* If `thisfd' is a derived member function, then `fdparent' is the
b4c522fa
IB
2185 overridden member function in the base class. Even if there's a
2186 closure environment, we should give the original stack data as the
2187 nested function frame. */
2188 if (fdoverride)
2189 {
2190 ClassDeclaration *cdo = fdoverride->isThis ()->isClassDeclaration ();
2191 ClassDeclaration *cd = thisfd->isThis ()->isClassDeclaration ();
2192 gcc_assert (cdo && cd);
2193
2194 int offset;
2195 if (cdo->isBaseOf (cd, &offset) && offset != 0)
2196 {
2197 /* Generate a new frame to pass to the overriden function that
cdbf48be 2198 has the `this' pointer adjusted. */
b4c522fa
IB
2199 gcc_assert (offset != OFFSET_RUNTIME);
2200
2201 tree type = FRAMEINFO_TYPE (get_frameinfo (fdoverride));
2202 tree fields = TYPE_FIELDS (type);
cdbf48be 2203 /* The `this' field comes immediately after the `__chain'. */
b4c522fa 2204 tree thisfield = chain_index (1, fields);
af3c19f0 2205 vec <constructor_elt, va_gc> *ve = NULL;
b4c522fa
IB
2206
2207 tree framefields = TYPE_FIELDS (FRAMEINFO_TYPE (ffo));
2208 frame_ref = build_deref (frame_ref);
2209
2210 for (tree field = fields; field; field = DECL_CHAIN (field))
2211 {
2212 tree value = component_ref (frame_ref, framefields);
2213 if (field == thisfield)
2214 value = build_offset (value, size_int (offset));
2215
2216 CONSTRUCTOR_APPEND_ELT (ve, field, value);
2217 framefields = DECL_CHAIN (framefields);
2218 }
2219
2220 frame_ref = build_address (build_constructor (type, ve));
2221 }
2222 }
2223
2224 return frame_ref;
2225 }
2226
2227 return null_pointer_node;
2228}
2229
2230/* Return the parent function of a nested class CD. */
2231
2232static FuncDeclaration *
2233d_nested_class (ClassDeclaration *cd)
2234{
2235 FuncDeclaration *fd = NULL;
2236 while (cd && cd->isNested ())
2237 {
2238 Dsymbol *dsym = cd->toParent2 ();
2239 if ((fd = dsym->isFuncDeclaration ()))
2240 return fd;
2241 else
2242 cd = dsym->isClassDeclaration ();
2243 }
2244 return NULL;
2245}
2246
2247/* Return the parent function of a nested struct SD. */
2248
2249static FuncDeclaration *
2250d_nested_struct (StructDeclaration *sd)
2251{
2252 FuncDeclaration *fd = NULL;
2253 while (sd && sd->isNested ())
2254 {
2255 Dsymbol *dsym = sd->toParent2 ();
2256 if ((fd = dsym->isFuncDeclaration ()))
2257 return fd;
2258 else
2259 sd = dsym->isStructDeclaration ();
2260 }
2261 return NULL;
2262}
2263
2264
2265/* Starting from the current function FD, try to find a suitable value of
cdbf48be 2266 `this' in nested function instances. A suitable `this' value is an
b4c522fa
IB
2267 instance of OCD or a class that has OCD as a base. */
2268
2269static tree
2270find_this_tree (ClassDeclaration *ocd)
2271{
2272 FuncDeclaration *fd = d_function_chain ? d_function_chain->function : NULL;
2273
2274 while (fd)
2275 {
2276 AggregateDeclaration *ad = fd->isThis ();
2277 ClassDeclaration *cd = ad ? ad->isClassDeclaration () : NULL;
2278
2279 if (cd != NULL)
2280 {
2281 if (ocd == cd)
2282 return get_decl_tree (fd->vthis);
2283 else if (ocd->isBaseOf (cd, NULL))
2284 return convert_expr (get_decl_tree (fd->vthis),
2285 cd->type, ocd->type);
2286
2287 fd = d_nested_class (cd);
2288 }
2289 else
2290 {
2291 if (fd->isNested ())
2292 {
2293 fd = fd->toParent2 ()->isFuncDeclaration ();
2294 continue;
2295 }
2296
2297 fd = NULL;
2298 }
2299 }
2300
2301 return NULL_TREE;
2302}
2303
cdbf48be 2304/* Retrieve the outer class/struct `this' value of DECL from
b4c522fa
IB
2305 the current function. */
2306
2307tree
2308build_vthis (AggregateDeclaration *decl)
2309{
2310 ClassDeclaration *cd = decl->isClassDeclaration ();
2311 StructDeclaration *sd = decl->isStructDeclaration ();
2312
2313 /* If an aggregate nested in a function has no methods and there are no
2314 other nested functions, any static chain created here will never be
2315 translated. Use a null pointer for the link in this case. */
2316 tree vthis_value = null_pointer_node;
2317
2318 if (cd != NULL || sd != NULL)
2319 {
2320 Dsymbol *outer = decl->toParent2 ();
2321
2322 /* If the parent is a templated struct, the outer context is instead
2323 the enclosing symbol of where the instantiation happened. */
2324 if (outer->isStructDeclaration ())
2325 {
2326 gcc_assert (outer->parent && outer->parent->isTemplateInstance ());
2327 outer = ((TemplateInstance *) outer->parent)->enclosing;
2328 }
2329
cdbf48be 2330 /* For outer classes, get a suitable `this' value.
b4c522fa
IB
2331 For outer functions, get a suitable frame/closure pointer. */
2332 ClassDeclaration *cdo = outer->isClassDeclaration ();
2333 FuncDeclaration *fdo = outer->isFuncDeclaration ();
2334
2335 if (cdo)
2336 {
2337 vthis_value = find_this_tree (cdo);
2338 gcc_assert (vthis_value != NULL_TREE);
2339 }
2340 else if (fdo)
2341 {
2342 tree ffo = get_frameinfo (fdo);
2343 if (FRAMEINFO_CREATES_FRAME (ffo) || FRAMEINFO_STATIC_CHAIN (ffo)
2344 || fdo->hasNestedFrameRefs ())
2345 vthis_value = get_frame_for_symbol (decl);
2346 else if (cd != NULL)
2347 {
2348 /* Classes nested in methods are allowed to access any outer
2349 class fields, use the function chain in this case. */
2350 if (fdo->vthis && fdo->vthis->type != Type::tvoidptr)
2351 vthis_value = get_decl_tree (fdo->vthis);
2352 }
2353 }
2354 else
2355 gcc_unreachable ();
2356 }
2357
2358 return vthis_value;
2359}
2360
2361/* Build the RECORD_TYPE that describes the function frame or closure type for
2362 the function FD. FFI is the tree holding all frame information. */
2363
2364static tree
2365build_frame_type (tree ffi, FuncDeclaration *fd)
2366{
2367 if (FRAMEINFO_TYPE (ffi))
2368 return FRAMEINFO_TYPE (ffi);
2369
2370 tree frame_rec_type = make_node (RECORD_TYPE);
2371 char *name = concat (FRAMEINFO_IS_CLOSURE (ffi) ? "CLOSURE." : "FRAME.",
2372 fd->toPrettyChars (), NULL);
2373 TYPE_NAME (frame_rec_type) = get_identifier (name);
2374 free (name);
2375
2376 tree fields = NULL_TREE;
2377
2378 /* Function is a member or nested, so must have field for outer context. */
2379 if (fd->vthis)
2380 {
2381 tree ptr_field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
2382 get_identifier ("__chain"), ptr_type_node);
2383 DECL_FIELD_CONTEXT (ptr_field) = frame_rec_type;
2384 fields = chainon (NULL_TREE, ptr_field);
2385 DECL_NONADDRESSABLE_P (ptr_field) = 1;
2386 }
2387
2388 /* The __ensure and __require are called directly, so never make the outer
2389 functions closure, but nevertheless could still be referencing parameters
2390 of the calling function non-locally. So we add all parameters with nested
2391 refs to the function frame, this should also mean overriding methods will
2392 have the same frame layout when inheriting a contract. */
0cdc55f5
IB
2393 if ((global.params.useIn == CHECKENABLEon && fd->frequire)
2394 || (global.params.useOut == CHECKENABLEon && fd->fensure))
b4c522fa
IB
2395 {
2396 if (fd->parameters)
2397 {
2cbc99d1 2398 for (size_t i = 0; fd->parameters && i < fd->parameters->length; i++)
b4c522fa
IB
2399 {
2400 VarDeclaration *v = (*fd->parameters)[i];
2401 /* Remove if already in closureVars so can push to front. */
2cbc99d1 2402 for (size_t j = i; j < fd->closureVars.length; j++)
b4c522fa
IB
2403 {
2404 Dsymbol *s = fd->closureVars[j];
2405 if (s == v)
2406 {
2407 fd->closureVars.remove (j);
2408 break;
2409 }
2410 }
2411 fd->closureVars.insert (i, v);
2412 }
2413 }
2414
cdbf48be 2415 /* Also add hidden `this' to outer context. */
b4c522fa
IB
2416 if (fd->vthis)
2417 {
2cbc99d1 2418 for (size_t i = 0; i < fd->closureVars.length; i++)
b4c522fa
IB
2419 {
2420 Dsymbol *s = fd->closureVars[i];
2421 if (s == fd->vthis)
2422 {
2423 fd->closureVars.remove (i);
2424 break;
2425 }
2426 }
2427 fd->closureVars.insert (0, fd->vthis);
2428 }
2429 }
2430
2cbc99d1 2431 for (size_t i = 0; i < fd->closureVars.length; i++)
b4c522fa
IB
2432 {
2433 VarDeclaration *v = fd->closureVars[i];
2434 tree vsym = get_symbol_decl (v);
2435 tree ident = v->ident
2436 ? get_identifier (v->ident->toChars ()) : NULL_TREE;
2437
2438 tree field = build_decl (make_location_t (v->loc), FIELD_DECL, ident,
2439 TREE_TYPE (vsym));
2440 SET_DECL_LANG_FRAME_FIELD (vsym, field);
2441 DECL_FIELD_CONTEXT (field) = frame_rec_type;
2442 fields = chainon (fields, field);
2443 TREE_USED (vsym) = 1;
2444
2445 TREE_ADDRESSABLE (field) = TREE_ADDRESSABLE (vsym);
2446 DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (vsym);
2447 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (vsym);
2448
2449 /* Can't do nrvo if the variable is put in a frame. */
2450 if (fd->nrvo_can && fd->nrvo_var == v)
2451 fd->nrvo_can = 0;
2452
2453 if (FRAMEINFO_IS_CLOSURE (ffi))
2454 {
2455 /* Because the value needs to survive the end of the scope. */
2456 if ((v->edtor && (v->storage_class & STCparameter))
2457 || v->needsScopeDtor ())
2458 error_at (make_location_t (v->loc),
2459 "has scoped destruction, cannot build closure");
2460 }
2461 }
2462
2463 TYPE_FIELDS (frame_rec_type) = fields;
2464 TYPE_READONLY (frame_rec_type) = 1;
2465 layout_type (frame_rec_type);
2466 d_keep (frame_rec_type);
2467
2468 return frame_rec_type;
2469}
2470
2471/* Closures are implemented by taking the local variables that
2472 need to survive the scope of the function, and copying them
2473 into a GC allocated chuck of memory. That chunk, called the
2474 closure here, is inserted into the linked list of stack
2475 frames instead of the usual stack frame.
2476
2477 If a closure is not required, but FD still needs a frame to lower
2478 nested refs, then instead build custom static chain decl on stack. */
2479
2480void
2481build_closure (FuncDeclaration *fd)
2482{
2483 tree ffi = get_frameinfo (fd);
2484
2485 if (!FRAMEINFO_CREATES_FRAME (ffi))
2486 return;
2487
2488 tree type = FRAMEINFO_TYPE (ffi);
2489 gcc_assert (COMPLETE_TYPE_P (type));
2490
2491 tree decl, decl_ref;
2492
2493 if (FRAMEINFO_IS_CLOSURE (ffi))
2494 {
2495 decl = build_local_temp (build_pointer_type (type));
2496 DECL_NAME (decl) = get_identifier ("__closptr");
2497 decl_ref = build_deref (decl);
2498
2499 /* Allocate memory for closure. */
2500 tree arg = convert (build_ctype (Type::tsize_t), TYPE_SIZE_UNIT (type));
2501 tree init = build_libcall (LIBCALL_ALLOCMEMORY, Type::tvoidptr, 1, arg);
2502
2503 tree init_exp = build_assign (INIT_EXPR, decl,
2504 build_nop (TREE_TYPE (decl), init));
2505 add_stmt (init_exp);
2506 }
2507 else
2508 {
2509 decl = build_local_temp (type);
2510 DECL_NAME (decl) = get_identifier ("__frame");
2511 decl_ref = decl;
2512 }
2513
2514 /* Set the first entry to the parent closure/frame, if any. */
2515 if (fd->vthis)
2516 {
2517 tree chain_field = component_ref (decl_ref, TYPE_FIELDS (type));
2518 tree chain_expr = modify_expr (chain_field,
2519 d_function_chain->static_chain);
2520 add_stmt (chain_expr);
2521 }
2522
2523 /* Copy parameters that are referenced nonlocally. */
2cbc99d1 2524 for (size_t i = 0; i < fd->closureVars.length; i++)
b4c522fa
IB
2525 {
2526 VarDeclaration *v = fd->closureVars[i];
2527
2528 if (!v->isParameter ())
2529 continue;
2530
2531 tree vsym = get_symbol_decl (v);
2532
2533 tree field = component_ref (decl_ref, DECL_LANG_FRAME_FIELD (vsym));
2534 tree expr = modify_expr (field, vsym);
2535 add_stmt (expr);
2536 }
2537
2538 if (!FRAMEINFO_IS_CLOSURE (ffi))
2539 decl = build_address (decl);
2540
2541 d_function_chain->static_chain = decl;
2542}
2543
2544/* Return the frame of FD. This could be a static chain or a closure
cdbf48be 2545 passed via the hidden `this' pointer. */
b4c522fa
IB
2546
2547tree
2548get_frameinfo (FuncDeclaration *fd)
2549{
2550 tree fds = get_symbol_decl (fd);
2551 if (DECL_LANG_FRAMEINFO (fds))
2552 return DECL_LANG_FRAMEINFO (fds);
2553
2554 tree ffi = make_node (FUNCFRAME_INFO);
2555
2556 DECL_LANG_FRAMEINFO (fds) = ffi;
2557
2558 if (fd->needsClosure ())
2559 {
2560 /* Set-up a closure frame, this will be allocated on the heap. */
2561 FRAMEINFO_CREATES_FRAME (ffi) = 1;
2562 FRAMEINFO_IS_CLOSURE (ffi) = 1;
2563 }
2564 else if (fd->hasNestedFrameRefs ())
2565 {
2566 /* Functions with nested refs must create a static frame for local
2567 variables to be referenced from. */
2568 FRAMEINFO_CREATES_FRAME (ffi) = 1;
2569 }
2570 else
2571 {
2572 /* For nested functions, default to creating a frame. Even if there are
2573 no fields to populate the frame, create it anyway, as this will be
2574 used as the record type instead of `void*` for the this parameter. */
2575 if (fd->vthis && fd->vthis->type == Type::tvoidptr)
2576 FRAMEINFO_CREATES_FRAME (ffi) = 1;
2577
2578 /* In checkNestedReference, references from contracts are not added to the
2579 closureVars array, so assume all parameters referenced. */
0cdc55f5
IB
2580 if ((global.params.useIn == CHECKENABLEon && fd->frequire)
2581 || (global.params.useOut == CHECKENABLEon && fd->fensure))
b4c522fa
IB
2582 FRAMEINFO_CREATES_FRAME (ffi) = 1;
2583
2584 /* If however `fd` is nested (deeply) in a function that creates a
2585 closure, then `fd` instead inherits that closure via hidden vthis
2586 pointer, and doesn't create a stack frame at all. */
2587 FuncDeclaration *ff = fd;
2588
2589 while (ff)
2590 {
2591 tree ffo = get_frameinfo (ff);
2592
2593 if (ff != fd && FRAMEINFO_CREATES_FRAME (ffo))
2594 {
2595 gcc_assert (FRAMEINFO_TYPE (ffo));
2596 FRAMEINFO_CREATES_FRAME (ffi) = 0;
2597 FRAMEINFO_STATIC_CHAIN (ffi) = 1;
2598 FRAMEINFO_IS_CLOSURE (ffi) = FRAMEINFO_IS_CLOSURE (ffo);
2599 gcc_assert (COMPLETE_TYPE_P (FRAMEINFO_TYPE (ffo)));
2600 FRAMEINFO_TYPE (ffi) = FRAMEINFO_TYPE (ffo);
2601 break;
2602 }
2603
2604 /* Stop looking if no frame pointer for this function. */
2605 if (ff->vthis == NULL)
2606 break;
2607
2608 AggregateDeclaration *ad = ff->isThis ();
2609 if (ad && ad->isNested ())
2610 {
2611 while (ad->isNested ())
2612 {
2613 Dsymbol *d = ad->toParent2 ();
2614 ad = d->isAggregateDeclaration ();
2615 ff = d->isFuncDeclaration ();
2616
2617 if (ad == NULL)
2618 break;
2619 }
2620 }
2621 else
2622 ff = ff->toParent2 ()->isFuncDeclaration ();
2623 }
2624 }
2625
2626 /* Build type now as may be referenced from another module. */
2627 if (FRAMEINFO_CREATES_FRAME (ffi))
2628 FRAMEINFO_TYPE (ffi) = build_frame_type (ffi, fd);
2629
2630 return ffi;
2631}
2632
2633/* Return a pointer to the frame/closure block of OUTER
2634 so can be accessed from the function INNER. */
2635
2636tree
2637get_framedecl (FuncDeclaration *inner, FuncDeclaration *outer)
2638{
2639 tree result = d_function_chain->static_chain;
2640 FuncDeclaration *fd = inner;
2641
2642 while (fd && fd != outer)
2643 {
2644 AggregateDeclaration *ad;
2645 ClassDeclaration *cd;
2646 StructDeclaration *sd;
2647
2648 /* Parent frame link is the first field. */
2649 if (FRAMEINFO_CREATES_FRAME (get_frameinfo (fd)))
2650 result = indirect_ref (ptr_type_node, result);
2651
2652 if (fd->isNested ())
2653 fd = fd->toParent2 ()->isFuncDeclaration ();
2654 /* The frame/closure record always points to the outer function's
2655 frame, even if there are intervening nested classes or structs.
2656 So, we can just skip over these. */
2657 else if ((ad = fd->isThis ()) && (cd = ad->isClassDeclaration ()))
2658 fd = d_nested_class (cd);
2659 else if ((ad = fd->isThis ()) && (sd = ad->isStructDeclaration ()))
2660 fd = d_nested_struct (sd);
2661 else
2662 break;
2663 }
2664
2665 /* Go get our frame record. */
2666 gcc_assert (fd == outer);
2667 tree frame_type = FRAMEINFO_TYPE (get_frameinfo (outer));
2668
2669 if (frame_type != NULL_TREE)
2670 {
2671 result = build_nop (build_pointer_type (frame_type), result);
2672 return result;
2673 }
2674 else
2675 {
2676 error_at (make_location_t (inner->loc),
2677 "forward reference to frame of %qs", outer->toChars ());
2678 return null_pointer_node;
2679 }
2680}