]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/dmd/mtype.c
PR d/90603
[thirdparty/gcc.git] / gcc / d / dmd / mtype.c
CommitLineData
03385ed3 1
2/* Compiler implementation of the D programming language
456185c9 3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
03385ed3 4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/mtype.c
9 */
10
efc08a8f 11#include "root/dsystem.h"
12#include "root/checkedint.h"
03385ed3 13#include "root/rmem.h"
14
15#include "mars.h"
16#include "mangle.h"
17#include "dsymbol.h"
18#include "mtype.h"
19#include "scope.h"
20#include "init.h"
21#include "expression.h"
22#include "statement.h"
23#include "attrib.h"
24#include "declaration.h"
25#include "template.h"
26#include "id.h"
27#include "enum.h"
28#include "module.h"
29#include "import.h"
30#include "aggregate.h"
31#include "hdrgen.h"
32#include "target.h"
33
34bool symbolIsVisible(Scope *sc, Dsymbol *s);
35typedef int (*ForeachDg)(void *ctx, size_t paramidx, Parameter *param);
36int Parameter_foreach(Parameters *parameters, ForeachDg dg, void *ctx, size_t *pn = NULL);
37FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL);
38Expression *extractSideEffect(Scope *sc, const char *name, Expression **e0, Expression *e, bool alwaysCopy = false);
39Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
40Expression *semantic(Expression *e, Scope *sc);
41Expression *semanticY(DotIdExp *exp, Scope *sc, int flag);
42Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag);
43Expression *typeToExpression(Type *t);
44Expression *typeToExpressionHelper(TypeQualified *t, Expression *e, size_t i = 0);
45Initializer *semantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret);
46
47int Tsize_t = Tuns32;
48int Tptrdiff_t = Tint32;
49
50/***************************** Type *****************************/
51
52ClassDeclaration *Type::dtypeinfo;
53ClassDeclaration *Type::typeinfoclass;
54ClassDeclaration *Type::typeinfointerface;
55ClassDeclaration *Type::typeinfostruct;
56ClassDeclaration *Type::typeinfopointer;
57ClassDeclaration *Type::typeinfoarray;
58ClassDeclaration *Type::typeinfostaticarray;
59ClassDeclaration *Type::typeinfoassociativearray;
60ClassDeclaration *Type::typeinfovector;
61ClassDeclaration *Type::typeinfoenum;
62ClassDeclaration *Type::typeinfofunction;
63ClassDeclaration *Type::typeinfodelegate;
64ClassDeclaration *Type::typeinfotypelist;
65ClassDeclaration *Type::typeinfoconst;
66ClassDeclaration *Type::typeinfoinvariant;
67ClassDeclaration *Type::typeinfoshared;
68ClassDeclaration *Type::typeinfowild;
69
70TemplateDeclaration *Type::rtinfo;
71
72Type *Type::tvoid;
73Type *Type::tint8;
74Type *Type::tuns8;
75Type *Type::tint16;
76Type *Type::tuns16;
77Type *Type::tint32;
78Type *Type::tuns32;
79Type *Type::tint64;
80Type *Type::tuns64;
81Type *Type::tint128;
82Type *Type::tuns128;
83Type *Type::tfloat32;
84Type *Type::tfloat64;
85Type *Type::tfloat80;
86
87Type *Type::timaginary32;
88Type *Type::timaginary64;
89Type *Type::timaginary80;
90
91Type *Type::tcomplex32;
92Type *Type::tcomplex64;
93Type *Type::tcomplex80;
94
95Type *Type::tbool;
96Type *Type::tchar;
97Type *Type::twchar;
98Type *Type::tdchar;
99
100Type *Type::tshiftcnt;
101Type *Type::terror;
102Type *Type::tnull;
103
104Type *Type::tsize_t;
105Type *Type::tptrdiff_t;
106Type *Type::thash_t;
107
108Type *Type::tvoidptr;
109Type *Type::tstring;
110Type *Type::twstring;
111Type *Type::tdstring;
112Type *Type::tvalist;
113Type *Type::basic[TMAX];
114unsigned char Type::sizeTy[TMAX];
115StringTable Type::stringtable;
116
117void initTypeMangle();
118
119Type::Type(TY ty)
120{
121 this->ty = ty;
122 this->mod = 0;
123 this->deco = NULL;
124 this->cto = NULL;
125 this->ito = NULL;
126 this->sto = NULL;
127 this->scto = NULL;
128 this->wto = NULL;
129 this->wcto = NULL;
130 this->swto = NULL;
131 this->swcto = NULL;
132 this->pto = NULL;
133 this->rto = NULL;
134 this->arrayof = NULL;
135 this->vtinfo = NULL;
136 this->ctype = NULL;
137}
138
139const char *Type::kind()
140{
141 assert(false); // should be overridden
142 return NULL;
143}
144
145Type *Type::copy()
146{
147 void *pt = mem.xmalloc(sizeTy[ty]);
148 Type *t = (Type *)memcpy(pt, (void *)this, sizeTy[ty]);
149 return t;
150}
151
152Type *Type::syntaxCopy()
153{
154 print();
155 fprintf(stderr, "ty = %d\n", ty);
156 assert(0);
157 return this;
158}
159
160bool Type::equals(RootObject *o)
161{
162 Type *t = (Type *)o;
163 //printf("Type::equals(%s, %s)\n", toChars(), t->toChars());
164 // deco strings are unique
165 // and semantic() has been run
166 if (this == o || ((t && deco == t->deco) && deco != NULL))
167 {
168 //printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
169 return true;
170 }
171 //if (deco && t && t->deco) printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
172 return false;
173}
174
175bool Type::equivalent(Type *t)
176{
177 return immutableOf()->equals(t->immutableOf());
178}
179
180void Type::_init()
181{
182 stringtable._init(14000);
183
184 for (size_t i = 0; i < TMAX; i++)
185 sizeTy[i] = sizeof(TypeBasic);
186 sizeTy[Tsarray] = sizeof(TypeSArray);
187 sizeTy[Tarray] = sizeof(TypeDArray);
188 sizeTy[Taarray] = sizeof(TypeAArray);
189 sizeTy[Tpointer] = sizeof(TypePointer);
190 sizeTy[Treference] = sizeof(TypeReference);
191 sizeTy[Tfunction] = sizeof(TypeFunction);
192 sizeTy[Tdelegate] = sizeof(TypeDelegate);
193 sizeTy[Tident] = sizeof(TypeIdentifier);
194 sizeTy[Tinstance] = sizeof(TypeInstance);
195 sizeTy[Ttypeof] = sizeof(TypeTypeof);
196 sizeTy[Tenum] = sizeof(TypeEnum);
197 sizeTy[Tstruct] = sizeof(TypeStruct);
198 sizeTy[Tclass] = sizeof(TypeClass);
199 sizeTy[Ttuple] = sizeof(TypeTuple);
200 sizeTy[Tslice] = sizeof(TypeSlice);
201 sizeTy[Treturn] = sizeof(TypeReturn);
202 sizeTy[Terror] = sizeof(TypeError);
203 sizeTy[Tnull] = sizeof(TypeNull);
204 sizeTy[Tvector] = sizeof(TypeVector);
205
206 initTypeMangle();
207
208 // Set basic types
209 static TY basetab[] =
210 { Tvoid, Tint8, Tuns8, Tint16, Tuns16, Tint32, Tuns32, Tint64, Tuns64,
211 Tint128, Tuns128,
212 Tfloat32, Tfloat64, Tfloat80,
213 Timaginary32, Timaginary64, Timaginary80,
214 Tcomplex32, Tcomplex64, Tcomplex80,
215 Tbool,
216 Tchar, Twchar, Tdchar, Terror };
217
218 for (size_t i = 0; basetab[i] != Terror; i++)
219 {
220 Type *t = new TypeBasic(basetab[i]);
221 t = t->merge();
222 basic[basetab[i]] = t;
223 }
224 basic[Terror] = new TypeError();
225
226 tvoid = basic[Tvoid];
227 tint8 = basic[Tint8];
228 tuns8 = basic[Tuns8];
229 tint16 = basic[Tint16];
230 tuns16 = basic[Tuns16];
231 tint32 = basic[Tint32];
232 tuns32 = basic[Tuns32];
233 tint64 = basic[Tint64];
234 tuns64 = basic[Tuns64];
235 tint128 = basic[Tint128];
236 tuns128 = basic[Tuns128];
237 tfloat32 = basic[Tfloat32];
238 tfloat64 = basic[Tfloat64];
239 tfloat80 = basic[Tfloat80];
240
241 timaginary32 = basic[Timaginary32];
242 timaginary64 = basic[Timaginary64];
243 timaginary80 = basic[Timaginary80];
244
245 tcomplex32 = basic[Tcomplex32];
246 tcomplex64 = basic[Tcomplex64];
247 tcomplex80 = basic[Tcomplex80];
248
249 tbool = basic[Tbool];
250 tchar = basic[Tchar];
251 twchar = basic[Twchar];
252 tdchar = basic[Tdchar];
253
254 tshiftcnt = tint32;
255 terror = basic[Terror];
256 tnull = basic[Tnull];
257 tnull = new TypeNull();
258 tnull->deco = tnull->merge()->deco;
259
260 tvoidptr = tvoid->pointerTo();
261 tstring = tchar->immutableOf()->arrayOf();
262 twstring = twchar->immutableOf()->arrayOf();
263 tdstring = tdchar->immutableOf()->arrayOf();
264 tvalist = Target::va_listType();
265
266 if (global.params.isLP64)
267 {
268 Tsize_t = Tuns64;
269 Tptrdiff_t = Tint64;
270 }
271 else
272 {
273 Tsize_t = Tuns32;
274 Tptrdiff_t = Tint32;
275 }
276
277 tsize_t = basic[Tsize_t];
278 tptrdiff_t = basic[Tptrdiff_t];
279 thash_t = tsize_t;
280}
281
282d_uns64 Type::size()
283{
284 return size(Loc());
285}
286
287d_uns64 Type::size(Loc loc)
288{
289 error(loc, "no size for type %s", toChars());
290 return SIZE_INVALID;
291}
292
293unsigned Type::alignsize()
294{
295 return (unsigned)size(Loc());
296}
297
298Type *Type::semantic(Loc loc, Scope *)
299{
300 if (ty == Tint128 || ty == Tuns128)
301 {
302 error(loc, "cent and ucent types not implemented");
303 return terror;
304 }
305
306 return merge();
307}
308
309Type *Type::trySemantic(Loc loc, Scope *sc)
310{
311 //printf("+trySemantic(%s) %d\n", toChars(), global.errors);
312 unsigned errors = global.startGagging();
313 Type *t = semantic(loc, sc);
314 if (global.endGagging(errors) || t->ty == Terror) // if any errors happened
315 {
316 t = NULL;
317 }
318 //printf("-trySemantic(%s) %d\n", toChars(), global.errors);
319 return t;
320}
321
322/********************************
323 * Return a copy of this type with all attributes null-initialized.
324 * Useful for creating a type with different modifiers.
325 */
326
327Type *Type::nullAttributes()
328{
329 unsigned sz = sizeTy[ty];
330 void *pt = mem.xmalloc(sz);
331 Type *t = (Type *)memcpy(pt, (void *)this, sz);
332 t->deco = NULL;
333 t->arrayof = NULL;
334 t->pto = NULL;
335 t->rto = NULL;
336 t->cto = NULL;
337 t->ito = NULL;
338 t->sto = NULL;
339 t->scto = NULL;
340 t->wto = NULL;
341 t->wcto = NULL;
342 t->swto = NULL;
343 t->swcto = NULL;
344 t->vtinfo = NULL;
345 t->ctype = NULL;
346 if (t->ty == Tstruct) ((TypeStruct *)t)->att = RECfwdref;
347 if (t->ty == Tclass) ((TypeClass *)t)->att = RECfwdref;
348 return t;
349}
350
351/********************************
352 * Convert to 'const'.
353 */
354
355Type *Type::constOf()
356{
357 //printf("Type::constOf() %p %s\n", this, toChars());
358 if (mod == MODconst)
359 return this;
360 if (cto)
361 {
362 assert(cto->mod == MODconst);
363 return cto;
364 }
365 Type *t = makeConst();
366 t = t->merge();
367 t->fixTo(this);
368 //printf("-Type::constOf() %p %s\n", t, t->toChars());
369 return t;
370}
371
372/********************************
373 * Convert to 'immutable'.
374 */
375
376Type *Type::immutableOf()
377{
378 //printf("Type::immutableOf() %p %s\n", this, toChars());
379 if (isImmutable())
380 return this;
381 if (ito)
382 {
383 assert(ito->isImmutable());
384 return ito;
385 }
386 Type *t = makeImmutable();
387 t = t->merge();
388 t->fixTo(this);
389 //printf("\t%p\n", t);
390 return t;
391}
392
393/********************************
394 * Make type mutable.
395 */
396
397Type *Type::mutableOf()
398{
399 //printf("Type::mutableOf() %p, %s\n", this, toChars());
400 Type *t = this;
401 if (isImmutable())
402 {
403 t = ito; // immutable => naked
404 assert(!t || (t->isMutable() && !t->isShared()));
405 }
406 else if (isConst())
407 {
408 if (isShared())
409 {
410 if (isWild())
411 t = swcto; // shared wild const -> shared
412 else
413 t = sto; // shared const => shared
414 }
415 else
416 {
417 if (isWild())
418 t = wcto; // wild const -> naked
419 else
420 t = cto; // const => naked
421 }
422 assert(!t || t->isMutable());
423 }
424 else if (isWild())
425 {
426 if (isShared())
427 t = sto; // shared wild => shared
428 else
429 t = wto; // wild => naked
430 assert(!t || t->isMutable());
431 }
432 if (!t)
433 {
434 t = makeMutable();
435 t = t->merge();
436 t->fixTo(this);
437 }
438 else
439 t = t->merge();
440 assert(t->isMutable());
441 return t;
442}
443
444Type *Type::sharedOf()
445{
446 //printf("Type::sharedOf() %p, %s\n", this, toChars());
447 if (mod == MODshared)
448 return this;
449 if (sto)
450 {
451 assert(sto->mod == MODshared);
452 return sto;
453 }
454 Type *t = makeShared();
455 t = t->merge();
456 t->fixTo(this);
457 //printf("\t%p\n", t);
458 return t;
459}
460
461Type *Type::sharedConstOf()
462{
463 //printf("Type::sharedConstOf() %p, %s\n", this, toChars());
464 if (mod == (MODshared | MODconst))
465 return this;
466 if (scto)
467 {
468 assert(scto->mod == (MODshared | MODconst));
469 return scto;
470 }
471 Type *t = makeSharedConst();
472 t = t->merge();
473 t->fixTo(this);
474 //printf("\t%p\n", t);
475 return t;
476}
477
478
479/********************************
480 * Make type unshared.
481 * 0 => 0
482 * const => const
483 * immutable => immutable
484 * shared => 0
485 * shared const => const
486 * wild => wild
487 * wild const => wild const
488 * shared wild => wild
489 * shared wild const => wild const
490 */
491
492Type *Type::unSharedOf()
493{
494 //printf("Type::unSharedOf() %p, %s\n", this, toChars());
495 Type *t = this;
496
497 if (isShared())
498 {
499 if (isWild())
500 {
501 if (isConst())
502 t = wcto; // shared wild const => wild const
503 else
504 t = wto; // shared wild => wild
505 }
506 else
507 {
508 if (isConst())
509 t = cto; // shared const => const
510 else
511 t = sto; // shared => naked
512 }
513 assert(!t || !t->isShared());
514 }
515
516 if (!t)
517 {
518 t = this->nullAttributes();
519 t->mod = mod & ~MODshared;
520 t->ctype = ctype;
521 t = t->merge();
522
523 t->fixTo(this);
524 }
525 else
526 t = t->merge();
527 assert(!t->isShared());
528 return t;
529}
530
531/********************************
532 * Convert to 'wild'.
533 */
534
535Type *Type::wildOf()
536{
537 //printf("Type::wildOf() %p %s\n", this, toChars());
538 if (mod == MODwild)
539 return this;
540 if (wto)
541 {
542 assert(wto->mod == MODwild);
543 return wto;
544 }
545 Type *t = makeWild();
546 t = t->merge();
547 t->fixTo(this);
548 //printf("\t%p %s\n", t, t->toChars());
549 return t;
550}
551
552Type *Type::wildConstOf()
553{
554 //printf("Type::wildConstOf() %p %s\n", this, toChars());
555 if (mod == MODwildconst)
556 return this;
557 if (wcto)
558 {
559 assert(wcto->mod == MODwildconst);
560 return wcto;
561 }
562 Type *t = makeWildConst();
563 t = t->merge();
564 t->fixTo(this);
565 //printf("\t%p %s\n", t, t->toChars());
566 return t;
567}
568
569Type *Type::sharedWildOf()
570{
571 //printf("Type::sharedWildOf() %p, %s\n", this, toChars());
572 if (mod == (MODshared | MODwild))
573 return this;
574 if (swto)
575 {
576 assert(swto->mod == (MODshared | MODwild));
577 return swto;
578 }
579 Type *t = makeSharedWild();
580 t = t->merge();
581 t->fixTo(this);
582 //printf("\t%p %s\n", t, t->toChars());
583 return t;
584}
585
586Type *Type::sharedWildConstOf()
587{
588 //printf("Type::sharedWildConstOf() %p, %s\n", this, toChars());
589 if (mod == (MODshared | MODwildconst))
590 return this;
591 if (swcto)
592 {
593 assert(swcto->mod == (MODshared | MODwildconst));
594 return swcto;
595 }
596 Type *t = makeSharedWildConst();
597 t = t->merge();
598 t->fixTo(this);
599 //printf("\t%p %s\n", t, t->toChars());
600 return t;
601}
602
603/**********************************
604 * For our new type 'this', which is type-constructed from t,
605 * fill in the cto, ito, sto, scto, wto shortcuts.
606 */
607
608void Type::fixTo(Type *t)
609{
610 // If fixing this: immutable(T*) by t: immutable(T)*,
611 // cache t to this->xto won't break transitivity.
612 Type *mto = NULL;
613 Type *tn = nextOf();
614 if (!tn || (ty != Tsarray && tn->mod == t->nextOf()->mod))
615 {
616 switch (t->mod)
617 {
618 case 0: mto = t; break;
619 case MODconst: cto = t; break;
620 case MODwild: wto = t; break;
621 case MODwildconst: wcto = t; break;
622 case MODshared: sto = t; break;
623 case MODshared | MODconst: scto = t; break;
624 case MODshared | MODwild: swto = t; break;
625 case MODshared | MODwildconst: swcto = t; break;
626 case MODimmutable: ito = t; break;
627 }
628 }
629
630 assert(mod != t->mod);
631#define X(m, n) (((m) << 4) | (n))
632 switch (mod)
633 {
634 case 0:
635 break;
636
637 case MODconst:
638 cto = mto;
639 t->cto = this;
640 break;
641
642 case MODwild:
643 wto = mto;
644 t->wto = this;
645 break;
646
647 case MODwildconst:
648 wcto = mto;
649 t->wcto = this;
650 break;
651
652 case MODshared:
653 sto = mto;
654 t->sto = this;
655 break;
656
657 case MODshared | MODconst:
658 scto = mto;
659 t->scto = this;
660 break;
661
662 case MODshared | MODwild:
663 swto = mto;
664 t->swto = this;
665 break;
666
667 case MODshared | MODwildconst:
668 swcto = mto;
669 t->swcto = this;
670 break;
671
672 case MODimmutable:
673 t->ito = this;
674 if (t-> cto) t-> cto->ito = this;
675 if (t-> sto) t-> sto->ito = this;
676 if (t-> scto) t-> scto->ito = this;
677 if (t-> wto) t-> wto->ito = this;
678 if (t-> wcto) t-> wcto->ito = this;
679 if (t-> swto) t-> swto->ito = this;
680 if (t->swcto) t->swcto->ito = this;
681 break;
682
683 default:
684 assert(0);
685 }
686#undef X
687
688 check();
689 t->check();
690 //printf("fixTo: %s, %s\n", toChars(), t->toChars());
691}
692
693/***************************
694 * Look for bugs in constructing types.
695 */
696
697void Type::check()
698{
699 switch (mod)
700 {
701 case 0:
702 if (cto) assert(cto->mod == MODconst);
703 if (ito) assert(ito->mod == MODimmutable);
704 if (sto) assert(sto->mod == MODshared);
705 if (scto) assert(scto->mod == (MODshared | MODconst));
706 if (wto) assert(wto->mod == MODwild);
707 if (wcto) assert(wcto->mod == MODwildconst);
708 if (swto) assert(swto->mod == (MODshared | MODwild));
709 if (swcto) assert(swcto->mod == (MODshared | MODwildconst));
710 break;
711
712 case MODconst:
713 if (cto) assert(cto->mod == 0);
714 if (ito) assert(ito->mod == MODimmutable);
715 if (sto) assert(sto->mod == MODshared);
716 if (scto) assert(scto->mod == (MODshared | MODconst));
717 if (wto) assert(wto->mod == MODwild);
718 if (wcto) assert(wcto->mod == MODwildconst);
719 if (swto) assert(swto->mod == (MODshared | MODwild));
720 if (swcto) assert(swcto->mod == (MODshared | MODwildconst));
721 break;
722
723 case MODwild:
724 if (cto) assert(cto->mod == MODconst);
725 if (ito) assert(ito->mod == MODimmutable);
726 if (sto) assert(sto->mod == MODshared);
727 if (scto) assert(scto->mod == (MODshared | MODconst));
728 if (wto) assert(wto->mod == 0);
729 if (wcto) assert(wcto->mod == MODwildconst);
730 if (swto) assert(swto->mod == (MODshared | MODwild));
731 if (swcto) assert(swcto->mod == (MODshared | MODwildconst));
732 break;
733
734 case MODwildconst:
735 assert(! cto || cto->mod == MODconst);
736 assert(! ito || ito->mod == MODimmutable);
737 assert(! sto || sto->mod == MODshared);
738 assert(! scto || scto->mod == (MODshared | MODconst));
739 assert(! wto || wto->mod == MODwild);
740 assert(! wcto || wcto->mod == 0);
741 assert(! swto || swto->mod == (MODshared | MODwild));
742 assert(!swcto || swcto->mod == (MODshared | MODwildconst));
743 break;
744
745 case MODshared:
746 if (cto) assert(cto->mod == MODconst);
747 if (ito) assert(ito->mod == MODimmutable);
748 if (sto) assert(sto->mod == 0);
749 if (scto) assert(scto->mod == (MODshared | MODconst));
750 if (wto) assert(wto->mod == MODwild);
751 if (wcto) assert(wcto->mod == MODwildconst);
752 if (swto) assert(swto->mod == (MODshared | MODwild));
753 if (swcto) assert(swcto->mod == (MODshared | MODwildconst));
754 break;
755
756 case MODshared | MODconst:
757 if (cto) assert(cto->mod == MODconst);
758 if (ito) assert(ito->mod == MODimmutable);
759 if (sto) assert(sto->mod == MODshared);
760 if (scto) assert(scto->mod == 0);
761 if (wto) assert(wto->mod == MODwild);
762 if (wcto) assert(wcto->mod == MODwildconst);
763 if (swto) assert(swto->mod == (MODshared | MODwild));
764 if (swcto) assert(swcto->mod == (MODshared | MODwildconst));
765 break;
766
767 case MODshared | MODwild:
768 if (cto) assert(cto->mod == MODconst);
769 if (ito) assert(ito->mod == MODimmutable);
770 if (sto) assert(sto->mod == MODshared);
771 if (scto) assert(scto->mod == (MODshared | MODconst));
772 if (wto) assert(wto->mod == MODwild);
773 if (wcto) assert(wcto->mod == MODwildconst);
774 if (swto) assert(swto->mod == 0);
775 if (swcto) assert(swcto->mod == (MODshared | MODwildconst));
776 break;
777
778 case MODshared | MODwildconst:
779 assert(! cto || cto->mod == MODconst);
780 assert(! ito || ito->mod == MODimmutable);
781 assert(! sto || sto->mod == MODshared);
782 assert(! scto || scto->mod == (MODshared | MODconst));
783 assert(! wto || wto->mod == MODwild);
784 assert(! wcto || wcto->mod == MODwildconst);
785 assert(! swto || swto->mod == (MODshared | MODwild));
786 assert(!swcto || swcto->mod == 0);
787 break;
788
789 case MODimmutable:
790 if (cto) assert(cto->mod == MODconst);
791 if (ito) assert(ito->mod == 0);
792 if (sto) assert(sto->mod == MODshared);
793 if (scto) assert(scto->mod == (MODshared | MODconst));
794 if (wto) assert(wto->mod == MODwild);
795 if (wcto) assert(wcto->mod == MODwildconst);
796 if (swto) assert(swto->mod == (MODshared | MODwild));
797 if (swcto) assert(swcto->mod == (MODshared | MODwildconst));
798 break;
799
800 default:
801 assert(0);
802 }
803
804 Type *tn = nextOf();
805 if (tn && ty != Tfunction && tn->ty != Tfunction && ty != Tenum)
806 {
807 // Verify transitivity
808 switch (mod)
809 {
810 case 0:
811 case MODconst:
812 case MODwild:
813 case MODwildconst:
814 case MODshared:
815 case MODshared | MODconst:
816 case MODshared | MODwild:
817 case MODshared | MODwildconst:
818 case MODimmutable:
819 assert(tn->mod == MODimmutable || (tn->mod & mod) == mod);
820 break;
821
822 default:
823 assert(0);
824 }
825 tn->check();
826 }
827}
828
829Type *Type::makeConst()
830{
831 //printf("Type::makeConst() %p, %s\n", this, toChars());
832 if (cto) return cto;
833 Type *t = this->nullAttributes();
834 t->mod = MODconst;
835 //printf("-Type::makeConst() %p, %s\n", t, toChars());
836 return t;
837}
838
839Type *Type::makeImmutable()
840{
841 if (ito) return ito;
842 Type *t = this->nullAttributes();
843 t->mod = MODimmutable;
844 return t;
845}
846
847Type *Type::makeShared()
848{
849 if (sto) return sto;
850 Type *t = this->nullAttributes();
851 t->mod = MODshared;
852 return t;
853}
854
855Type *Type::makeSharedConst()
856{
857 if (scto) return scto;
858 Type *t = this->nullAttributes();
859 t->mod = MODshared | MODconst;
860 return t;
861}
862
863Type *Type::makeWild()
864{
865 if (wto) return wto;
866 Type *t = this->nullAttributes();
867 t->mod = MODwild;
868 return t;
869}
870
871Type *Type::makeWildConst()
872{
873 if (wcto) return wcto;
874 Type *t = this->nullAttributes();
875 t->mod = MODwildconst;
876 return t;
877}
878
879Type *Type::makeSharedWild()
880{
881 if (swto) return swto;
882 Type *t = this->nullAttributes();
883 t->mod = MODshared | MODwild;
884 return t;
885}
886
887Type *Type::makeSharedWildConst()
888{
889 if (swcto) return swcto;
890 Type *t = this->nullAttributes();
891 t->mod = MODshared | MODwildconst;
892 return t;
893}
894
895Type *Type::makeMutable()
896{
897 Type *t = this->nullAttributes();
898 t->mod = mod & MODshared;
899 return t;
900}
901
902/*************************************
903 * Apply STCxxxx bits to existing type.
904 * Use *before* semantic analysis is run.
905 */
906
907Type *Type::addSTC(StorageClass stc)
908{
909 Type *t = this;
910 if (t->isImmutable())
911 ;
912 else if (stc & STCimmutable)
913 {
914 t = t->makeImmutable();
915 }
916 else
917 {
918 if ((stc & STCshared) && !t->isShared())
919 {
920 if (t->isWild())
921 {
922 if (t->isConst())
923 t = t->makeSharedWildConst();
924 else
925 t = t->makeSharedWild();
926 }
927 else
928 {
929 if (t->isConst())
930 t = t->makeSharedConst();
931 else
932 t = t->makeShared();
933 }
934 }
935 if ((stc & STCconst) && !t->isConst())
936 {
937 if (t->isShared())
938 {
939 if (t->isWild())
940 t = t->makeSharedWildConst();
941 else
942 t = t->makeSharedConst();
943 }
944 else
945 {
946 if (t->isWild())
947 t = t->makeWildConst();
948 else
949 t = t->makeConst();
950 }
951 }
952 if ((stc & STCwild) && !t->isWild())
953 {
954 if (t->isShared())
955 {
956 if (t->isConst())
957 t = t->makeSharedWildConst();
958 else
959 t = t->makeSharedWild();
960 }
961 else
962 {
963 if (t->isConst())
964 t = t->makeWildConst();
965 else
966 t = t->makeWild();
967 }
968 }
969 }
970 return t;
971}
972
973/************************************
974 * Convert MODxxxx to STCxxx
975 */
976
977StorageClass ModToStc(unsigned mod)
978{
979 StorageClass stc = 0;
980 if (mod & MODimmutable) stc |= STCimmutable;
981 if (mod & MODconst) stc |= STCconst;
982 if (mod & MODwild) stc |= STCwild;
983 if (mod & MODshared) stc |= STCshared;
984 return stc;
985}
986
987/************************************
988 * Apply MODxxxx bits to existing type.
989 */
990
991Type *Type::castMod(MOD mod)
992{ Type *t;
993
994 switch (mod)
995 {
996 case 0:
997 t = unSharedOf()->mutableOf();
998 break;
999
1000 case MODconst:
1001 t = unSharedOf()->constOf();
1002 break;
1003
1004 case MODwild:
1005 t = unSharedOf()->wildOf();
1006 break;
1007
1008 case MODwildconst:
1009 t = unSharedOf()->wildConstOf();
1010 break;
1011
1012 case MODshared:
1013 t = mutableOf()->sharedOf();
1014 break;
1015
1016 case MODshared | MODconst:
1017 t = sharedConstOf();
1018 break;
1019
1020 case MODshared | MODwild:
1021 t = sharedWildOf();
1022 break;
1023
1024 case MODshared | MODwildconst:
1025 t = sharedWildConstOf();
1026 break;
1027
1028 case MODimmutable:
1029 t = immutableOf();
1030 break;
1031
1032 default:
1033 assert(0);
1034 }
1035 return t;
1036}
1037
1038/************************************
1039 * Add MODxxxx bits to existing type.
1040 * We're adding, not replacing, so adding const to
1041 * a shared type => "shared const"
1042 */
1043
1044Type *Type::addMod(MOD mod)
1045{
1046 /* Add anything to immutable, and it remains immutable
1047 */
1048 Type *t = this;
1049 if (!t->isImmutable())
1050 {
1051 //printf("addMod(%x) %s\n", mod, toChars());
1052 switch (mod)
1053 {
1054 case 0:
1055 break;
1056
1057 case MODconst:
1058 if (isShared())
1059 {
1060 if (isWild())
1061 t = sharedWildConstOf();
1062 else
1063 t = sharedConstOf();
1064 }
1065 else
1066 {
1067 if (isWild())
1068 t = wildConstOf();
1069 else
1070 t = constOf();
1071 }
1072 break;
1073
1074 case MODwild:
1075 if (isShared())
1076 {
1077 if (isConst())
1078 t = sharedWildConstOf();
1079 else
1080 t = sharedWildOf();
1081 }
1082 else
1083 {
1084 if (isConst())
1085 t = wildConstOf();
1086 else
1087 t = wildOf();
1088 }
1089 break;
1090
1091 case MODwildconst:
1092 if (isShared())
1093 t = sharedWildConstOf();
1094 else
1095 t = wildConstOf();
1096 break;
1097
1098 case MODshared:
1099 if (isWild())
1100 {
1101 if (isConst())
1102 t = sharedWildConstOf();
1103 else
1104 t = sharedWildOf();
1105 }
1106 else
1107 {
1108 if (isConst())
1109 t = sharedConstOf();
1110 else
1111 t = sharedOf();
1112 }
1113 break;
1114
1115 case MODshared | MODconst:
1116 if (isWild())
1117 t = sharedWildConstOf();
1118 else
1119 t = sharedConstOf();
1120 break;
1121
1122 case MODshared | MODwild:
1123 if (isConst())
1124 t = sharedWildConstOf();
1125 else
1126 t = sharedWildOf();
1127 break;
1128
1129 case MODshared | MODwildconst:
1130 t = sharedWildConstOf();
1131 break;
1132
1133 case MODimmutable:
1134 t = immutableOf();
1135 break;
1136
1137 default:
1138 assert(0);
1139 }
1140 }
1141 return t;
1142}
1143
1144/************************************
1145 * Add storage class modifiers to type.
1146 */
1147
1148Type *Type::addStorageClass(StorageClass stc)
1149{
1150 /* Just translate to MOD bits and let addMod() do the work
1151 */
1152 MOD mod = 0;
1153
1154 if (stc & STCimmutable)
1155 mod = MODimmutable;
1156 else
1157 {
1158 if (stc & (STCconst | STCin))
1159 mod |= MODconst;
1160 if (stc & STCwild)
1161 mod |= MODwild;
1162 if (stc & STCshared)
1163 mod |= MODshared;
1164 }
1165 return addMod(mod);
1166}
1167
1168Type *Type::pointerTo()
1169{
1170 if (ty == Terror)
1171 return this;
1172 if (!pto)
1173 {
1174 Type *t = new TypePointer(this);
1175 if (ty == Tfunction)
1176 {
1177 t->deco = t->merge()->deco;
1178 pto = t;
1179 }
1180 else
1181 pto = t->merge();
1182 }
1183 return pto;
1184}
1185
1186Type *Type::referenceTo()
1187{
1188 if (ty == Terror)
1189 return this;
1190 if (!rto)
1191 {
1192 Type *t = new TypeReference(this);
1193 rto = t->merge();
1194 }
1195 return rto;
1196}
1197
1198Type *Type::arrayOf()
1199{
1200 if (ty == Terror)
1201 return this;
1202 if (!arrayof)
1203 {
1204 Type *t = new TypeDArray(this);
1205 arrayof = t->merge();
1206 }
1207 return arrayof;
1208}
1209
1210// Make corresponding static array type without semantic
1211Type *Type::sarrayOf(dinteger_t dim)
1212{
1213 assert(deco);
1214 Type *t = new TypeSArray(this, new IntegerExp(Loc(), dim, Type::tsize_t));
1215
1216 // according to TypeSArray::semantic()
1217 t = t->addMod(mod);
1218 t = t->merge();
1219
1220 return t;
1221}
1222
1223Type *Type::aliasthisOf()
1224{
1225 AggregateDeclaration *ad = isAggregate(this);
1226 if (ad && ad->aliasthis)
1227 {
1228 Dsymbol *s = ad->aliasthis;
1229 if (s->isAliasDeclaration())
1230 s = s->toAlias();
1231 Declaration *d = s->isDeclaration();
1232 if (d && !d->isTupleDeclaration())
1233 {
1234 assert(d->type);
1235 Type *t = d->type;
1236 if (d->isVarDeclaration() && d->needThis())
1237 {
1238 t = t->addMod(this->mod);
1239 }
1240 else if (d->isFuncDeclaration())
1241 {
1242 FuncDeclaration *fd = resolveFuncCall(Loc(), NULL, d, NULL, this, NULL, 1);
1243 if (fd && fd->errors)
1244 return Type::terror;
1245 if (fd && !fd->type->nextOf() && !fd->functionSemantic())
1246 fd = NULL;
1247 if (fd)
1248 {
1249 t = fd->type->nextOf();
1250 if (!t) // issue 14185
1251 return Type::terror;
1252 t = t->substWildTo(mod == 0 ? MODmutable : (MODFlags)mod);
1253 }
1254 else
1255 return Type::terror;
1256 }
1257 return t;
1258 }
1259 EnumDeclaration *ed = s->isEnumDeclaration();
1260 if (ed)
1261 {
1262 Type *t = ed->type;
1263 return t;
1264 }
1265 TemplateDeclaration *td = s->isTemplateDeclaration();
1266 if (td)
1267 {
1268 assert(td->_scope);
1269 FuncDeclaration *fd = resolveFuncCall(Loc(), NULL, td, NULL, this, NULL, 1);
1270 if (fd && fd->errors)
1271 return Type::terror;
1272 if (fd && fd->functionSemantic())
1273 {
1274 Type *t = fd->type->nextOf();
1275 t = t->substWildTo(mod == 0 ? MODmutable : (MODFlags)mod);
1276 return t;
1277 }
1278 else
1279 return Type::terror;
1280 }
1281 //printf("%s\n", s->kind());
1282 }
1283 return NULL;
1284}
1285
1286bool Type::checkAliasThisRec()
1287{
1288 Type *tb = toBasetype();
1289 AliasThisRec* pflag;
1290 if (tb->ty == Tstruct)
1291 pflag = &((TypeStruct *)tb)->att;
1292 else if (tb->ty == Tclass)
1293 pflag = &((TypeClass *)tb)->att;
1294 else
1295 return false;
1296
1297 AliasThisRec flag = (AliasThisRec)(*pflag & RECtypeMask);
1298 if (flag == RECfwdref)
1299 {
1300 Type *att = aliasthisOf();
1301 flag = att && att->implicitConvTo(this) ? RECyes : RECno;
1302 }
1303 *pflag = (AliasThisRec)(flag | (*pflag & ~RECtypeMask));
1304 return flag == RECyes;
1305}
1306
1307Dsymbol *Type::toDsymbol(Scope *)
1308{
1309 return NULL;
1310}
1311
1312/*******************************
1313 * If this is a shell around another type,
1314 * get that other type.
1315 */
1316
1317Type *Type::toBasetype()
1318{
1319 return this;
1320}
1321
1322/***************************
1323 * Return !=0 if modfrom can be implicitly converted to modto
1324 */
1325bool MODimplicitConv(MOD modfrom, MOD modto)
1326{
1327 if (modfrom == modto)
1328 return true;
1329
1330 //printf("MODimplicitConv(from = %x, to = %x)\n", modfrom, modto);
1331 #define X(m, n) (((m) << 4) | (n))
1332 switch (X(modfrom & ~MODshared, modto & ~MODshared))
1333 {
1334 case X(0, MODconst):
1335 case X(MODwild, MODconst):
1336 case X(MODwild, MODwildconst):
1337 case X(MODwildconst, MODconst):
1338 return (modfrom & MODshared) == (modto & MODshared);
1339
1340 case X(MODimmutable, MODconst):
1341 case X(MODimmutable, MODwildconst):
1342 return true;
1343
1344 default:
1345 return false;
1346 }
1347 #undef X
1348}
1349
1350/***************************
1351 * Return MATCHexact or MATCHconst if a method of type '() modfrom' can call a method of type '() modto'.
1352 */
1353MATCH MODmethodConv(MOD modfrom, MOD modto)
1354{
1355 if (modfrom == modto)
1356 return MATCHexact;
1357 if (MODimplicitConv(modfrom, modto))
1358 return MATCHconst;
1359
1360 #define X(m, n) (((m) << 4) | (n))
1361 switch (X(modfrom, modto))
1362 {
1363 case X(0, MODwild):
1364 case X(MODimmutable, MODwild):
1365 case X(MODconst, MODwild):
1366 case X(MODwildconst, MODwild):
1367 case X(MODshared, MODshared|MODwild):
1368 case X(MODshared|MODimmutable, MODshared|MODwild):
1369 case X(MODshared|MODconst, MODshared|MODwild):
1370 case X(MODshared|MODwildconst, MODshared|MODwild):
1371 return MATCHconst;
1372
1373 default:
1374 return MATCHnomatch;
1375 }
1376 #undef X
1377}
1378
1379/***************************
1380 * Merge mod bits to form common mod.
1381 */
1382MOD MODmerge(MOD mod1, MOD mod2)
1383{
1384 if (mod1 == mod2)
1385 return mod1;
1386
1387 //printf("MODmerge(1 = %x, 2 = %x)\n", mod1, mod2);
1388 MOD result = 0;
1389 if ((mod1 | mod2) & MODshared)
1390 {
1391 // If either type is shared, the result will be shared
1392 result |= MODshared;
1393 mod1 &= ~MODshared;
1394 mod2 &= ~MODshared;
1395 }
1396 if (mod1 == 0 || mod1 == MODmutable || mod1 == MODconst ||
1397 mod2 == 0 || mod2 == MODmutable || mod2 == MODconst)
1398 {
1399 // If either type is mutable or const, the result will be const.
1400 result |= MODconst;
1401 }
1402 else
1403 {
1404 // MODimmutable vs MODwild
1405 // MODimmutable vs MODwildconst
1406 // MODwild vs MODwildconst
1407 assert(mod1 & MODwild || mod2 & MODwild);
1408 result |= MODwildconst;
1409 }
1410 return result;
1411}
1412
1413/*********************************
1414 * Store modifier name into buf.
1415 */
1416void MODtoBuffer(OutBuffer *buf, MOD mod)
1417{
1418 switch (mod)
1419 {
1420 case 0:
1421 break;
1422
1423 case MODimmutable:
1424 buf->writestring(Token::tochars[TOKimmutable]);
1425 break;
1426
1427 case MODshared:
1428 buf->writestring(Token::tochars[TOKshared]);
1429 break;
1430
1431 case MODshared | MODconst:
1432 buf->writestring(Token::tochars[TOKshared]);
1433 buf->writeByte(' ');
1434 /* fall through */
1435 case MODconst:
1436 buf->writestring(Token::tochars[TOKconst]);
1437 break;
1438
1439 case MODshared | MODwild:
1440 buf->writestring(Token::tochars[TOKshared]);
1441 buf->writeByte(' ');
1442 /* fall through */
1443 case MODwild:
1444 buf->writestring(Token::tochars[TOKwild]);
1445 break;
1446
1447 case MODshared | MODwildconst:
1448 buf->writestring(Token::tochars[TOKshared]);
1449 buf->writeByte(' ');
1450 /* fall through */
1451 case MODwildconst:
1452 buf->writestring(Token::tochars[TOKwild]);
1453 buf->writeByte(' ');
1454 buf->writestring(Token::tochars[TOKconst]);
1455 break;
1456
1457 default:
1458 assert(0);
1459 }
1460}
1461
1462
1463/*********************************
1464 * Return modifier name.
1465 */
1466char *MODtoChars(MOD mod)
1467{
1468 OutBuffer buf;
1469 buf.reserve(16);
1470 MODtoBuffer(&buf, mod);
1471 return buf.extractString();
1472}
1473
1474/********************************
1475 * For pretty-printing a type.
1476 */
1477
1478const char *Type::toChars()
1479{
1480 OutBuffer buf;
1481 buf.reserve(16);
1482 HdrGenState hgs;
1483 hgs.fullQual = (ty == Tclass && !mod);
1484
1485 ::toCBuffer(this, &buf, NULL, &hgs);
1486 return buf.extractString();
1487}
1488
1489char *Type::toPrettyChars(bool QualifyTypes)
1490{
1491 OutBuffer buf;
1492 buf.reserve(16);
1493 HdrGenState hgs;
1494 hgs.fullQual = QualifyTypes;
1495
1496 ::toCBuffer(this, &buf, NULL, &hgs);
1497 return buf.extractString();
1498}
1499
1500/*********************************
1501 * Store this type's modifier name into buf.
1502 */
1503void Type::modToBuffer(OutBuffer *buf)
1504{
1505 if (mod)
1506 {
1507 buf->writeByte(' ');
1508 MODtoBuffer(buf, mod);
1509 }
1510}
1511
1512/*********************************
1513 * Return this type's modifier name.
1514 */
1515char *Type::modToChars()
1516{
1517 OutBuffer buf;
1518 buf.reserve(16);
1519 modToBuffer(&buf);
1520 return buf.extractString();
1521}
1522
1523/** For each active modifier (MODconst, MODimmutable, etc) call fp with a
1524void* for the work param and a string representation of the attribute. */
1525int Type::modifiersApply(void *param, int (*fp)(void *, const char *))
1526{
1527 static unsigned char modsArr[] = { MODconst, MODimmutable, MODwild, MODshared };
1528
1529 for (size_t idx = 0; idx < 4; ++idx)
1530 {
1531 if (mod & modsArr[idx])
1532 {
1533 if (int res = fp(param, MODtoChars(modsArr[idx])))
1534 return res;
1535 }
1536 }
1537 return 0;
1538}
1539
1540/************************************
1541 * Strip all parameter's idenfiers and their default arguments for merging types.
1542 * If some of parameter types or return type are function pointer, delegate, or
1543 * the types which contains either, then strip also from them.
1544 */
1545
1546Type *stripDefaultArgs(Type *t)
1547{
1548 struct N
1549 {
1550 static Parameters *stripParams(Parameters *parameters)
1551 {
1552 Parameters *params = parameters;
1553 if (params && params->dim > 0)
1554 {
1555 for (size_t i = 0; i < params->dim; i++)
1556 {
1557 Parameter *p = (*params)[i];
1558 Type *ta = stripDefaultArgs(p->type);
1559 if (ta != p->type || p->defaultArg || p->ident)
1560 {
1561 if (params == parameters)
1562 {
1563 params = new Parameters();
1564 params->setDim(parameters->dim);
1565 for (size_t j = 0; j < params->dim; j++)
1566 (*params)[j] = (*parameters)[j];
1567 }
1568 (*params)[i] = new Parameter(p->storageClass, ta, NULL, NULL);
1569 }
1570 }
1571 }
1572 return params;
1573 }
1574 };
1575
1576 if (t == NULL)
1577 return t;
1578
1579 if (t->ty == Tfunction)
1580 {
1581 TypeFunction *tf = (TypeFunction *)t;
1582 Type *tret = stripDefaultArgs(tf->next);
1583 Parameters *params = N::stripParams(tf->parameters);
1584 if (tret == tf->next && params == tf->parameters)
1585 goto Lnot;
1586 tf = (TypeFunction *)tf->copy();
1587 tf->parameters = params;
1588 tf->next = tret;
1589 //printf("strip %s\n <- %s\n", tf->toChars(), t->toChars());
1590 t = tf;
1591 }
1592 else if (t->ty == Ttuple)
1593 {
1594 TypeTuple *tt = (TypeTuple *)t;
1595 Parameters *args = N::stripParams(tt->arguments);
1596 if (args == tt->arguments)
1597 goto Lnot;
1598 t = t->copy();
1599 ((TypeTuple *)t)->arguments = args;
1600 }
1601 else if (t->ty == Tenum)
1602 {
1603 // TypeEnum::nextOf() may be != NULL, but it's not necessary here.
1604 goto Lnot;
1605 }
1606 else
1607 {
1608 Type *tn = t->nextOf();
1609 Type *n = stripDefaultArgs(tn);
1610 if (n == tn)
1611 goto Lnot;
1612 t = t->copy();
1613 ((TypeNext *)t)->next = n;
1614 }
1615 //printf("strip %s\n", t->toChars());
1616Lnot:
1617 return t;
1618}
1619
1620/************************************
1621 */
1622
1623Type *Type::merge()
1624{
1625 if (ty == Terror) return this;
1626 if (ty == Ttypeof) return this;
1627 if (ty == Tident) return this;
1628 if (ty == Tinstance) return this;
1629 if (ty == Taarray && !((TypeAArray *)this)->index->merge()->deco)
1630 return this;
1631 if (ty != Tenum && nextOf() && !nextOf()->deco)
1632 return this;
1633
1634 //printf("merge(%s)\n", toChars());
1635 Type *t = this;
1636 assert(t);
1637 if (!deco)
1638 {
1639 OutBuffer buf;
1640 buf.reserve(32);
1641
1642 mangleToBuffer(this, &buf);
1643
1644 StringValue *sv = stringtable.update((char *)buf.data, buf.offset);
1645 if (sv->ptrvalue)
1646 {
1647 t = (Type *) sv->ptrvalue;
1648 assert(t->deco);
1649 //printf("old value, deco = '%s' %p\n", t->deco, t->deco);
1650 }
1651 else
1652 {
1653 sv->ptrvalue = (char *)(t = stripDefaultArgs(t));
1654 deco = t->deco = const_cast<char *>(sv->toDchars());
1655 //printf("new value, deco = '%s' %p\n", t->deco, t->deco);
1656 }
1657 }
1658 return t;
1659}
1660
1661/*************************************
1662 * This version does a merge even if the deco is already computed.
1663 * Necessary for types that have a deco, but are not merged.
1664 */
1665Type *Type::merge2()
1666{
1667 //printf("merge2(%s)\n", toChars());
1668 Type *t = this;
1669 assert(t);
1670 if (!t->deco)
1671 return t->merge();
1672
1673 StringValue *sv = stringtable.lookup((char *)t->deco, strlen(t->deco));
1674 if (sv && sv->ptrvalue)
1675 { t = (Type *) sv->ptrvalue;
1676 assert(t->deco);
1677 }
1678 else
1679 assert(0);
1680 return t;
1681}
1682
1683bool Type::isintegral()
1684{
1685 return false;
1686}
1687
1688bool Type::isfloating()
1689{
1690 return false;
1691}
1692
1693bool Type::isreal()
1694{
1695 return false;
1696}
1697
1698bool Type::isimaginary()
1699{
1700 return false;
1701}
1702
1703bool Type::iscomplex()
1704{
1705 return false;
1706}
1707
1708bool Type::isscalar()
1709{
1710 return false;
1711}
1712
1713bool Type::isunsigned()
1714{
1715 return false;
1716}
1717
1718ClassDeclaration *Type::isClassHandle()
1719{
1720 return NULL;
1721}
1722
1723bool Type::isscope()
1724{
1725 return false;
1726}
1727
1728bool Type::isString()
1729{
1730 return false;
1731}
1732
1733/**************************
1734 * When T is mutable,
1735 * Given:
1736 * T a, b;
1737 * Can we bitwise assign:
1738 * a = b;
1739 * ?
1740 */
1741bool Type::isAssignable()
1742{
1743 return true;
1744}
1745
1746/**************************
1747 * Returns true if T can be converted to boolean value.
1748 */
1749bool Type::isBoolean()
1750{
1751 return isscalar();
1752}
1753
1754/********************************
1755 * true if when type goes out of scope, it needs a destructor applied.
1756 * Only applies to value types, not ref types.
1757 */
1758bool Type::needsDestruction()
1759{
1760 return false;
1761}
1762
1763/*********************************
1764 *
1765 */
1766
1767bool Type::needsNested()
1768{
1769 return false;
1770}
1771
1772/*********************************
1773 * Check type to see if it is based on a deprecated symbol.
1774 */
1775
1776void Type::checkDeprecated(Loc loc, Scope *sc)
1777{
1778 Dsymbol *s = toDsymbol(sc);
1779
1780 if (s)
1781 s->checkDeprecated(loc, sc);
1782}
1783
1784
1785Expression *Type::defaultInit(Loc)
1786{
1787 return NULL;
1788}
1789
1790/***************************************
1791 * Use when we prefer the default initializer to be a literal,
1792 * rather than a global immutable variable.
1793 */
1794Expression *Type::defaultInitLiteral(Loc loc)
1795{
1796 return defaultInit(loc);
1797}
1798
1799bool Type::isZeroInit(Loc)
1800{
1801 return false; // assume not
1802}
1803
1804bool Type::isBaseOf(Type *, int *)
1805{
1806 return 0; // assume not
1807}
1808
1809/********************************
1810 * Determine if 'this' can be implicitly converted
1811 * to type 'to'.
1812 * Returns:
1813 * MATCHnomatch, MATCHconvert, MATCHconst, MATCHexact
1814 */
1815
1816MATCH Type::implicitConvTo(Type *to)
1817{
1818 //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to);
1819 //printf("from: %s\n", toChars());
1820 //printf("to : %s\n", to->toChars());
1821 if (this->equals(to))
1822 return MATCHexact;
1823 return MATCHnomatch;
1824}
1825
1826/*******************************
1827 * Determine if converting 'this' to 'to' is an identity operation,
1828 * a conversion to const operation, or the types aren't the same.
1829 * Returns:
1830 * MATCHexact 'this' == 'to'
1831 * MATCHconst 'to' is const
1832 * MATCHnomatch conversion to mutable or invariant
1833 */
1834
1835MATCH Type::constConv(Type *to)
1836{
1837 //printf("Type::constConv(this = %s, to = %s)\n", toChars(), to->toChars());
1838 if (equals(to))
1839 return MATCHexact;
1840 if (ty == to->ty && MODimplicitConv(mod, to->mod))
1841 return MATCHconst;
1842 return MATCHnomatch;
1843}
1844
1845/***************************************
1846 * Return MOD bits matching this type to wild parameter type (tprm).
1847 */
1848
1849unsigned char Type::deduceWild(Type *t, bool)
1850{
1851 //printf("Type::deduceWild this = '%s', tprm = '%s'\n", toChars(), tprm->toChars());
1852
1853 if (t->isWild())
1854 {
1855 if (isImmutable())
1856 return MODimmutable;
1857 else if (isWildConst())
1858 {
1859 if (t->isWildConst())
1860 return MODwild;
1861 else
1862 return MODwildconst;
1863 }
1864 else if (isWild())
1865 return MODwild;
1866 else if (isConst())
1867 return MODconst;
1868 else if (isMutable())
1869 return MODmutable;
1870 else
1871 assert(0);
1872 }
1873 return 0;
1874}
1875
1876Type *Type::unqualify(unsigned m)
1877{
1878 Type *t = mutableOf()->unSharedOf();
1879
1880 Type *tn = ty == Tenum ? NULL : nextOf();
1881 if (tn && tn->ty != Tfunction)
1882 {
1883 Type *utn = tn->unqualify(m);
1884 if (utn != tn)
1885 {
1886 if (ty == Tpointer)
1887 t = utn->pointerTo();
1888 else if (ty == Tarray)
1889 t = utn->arrayOf();
1890 else if (ty == Tsarray)
1891 t = new TypeSArray(utn, ((TypeSArray *)this)->dim);
1892 else if (ty == Taarray)
1893 {
1894 t = new TypeAArray(utn, ((TypeAArray *)this)->index);
1895 ((TypeAArray *)t)->sc = ((TypeAArray *)this)->sc; // duplicate scope
1896 }
1897 else
1898 assert(0);
1899
1900 t = t->merge();
1901 }
1902 }
1903 t = t->addMod(mod & ~m);
1904 return t;
1905}
1906
1907Type *Type::substWildTo(unsigned mod)
1908{
1909 //printf("+Type::substWildTo this = %s, mod = x%x\n", toChars(), mod);
1910 Type *t;
1911
1912 if (Type *tn = nextOf())
1913 {
1914 // substitution has no effect on function pointer type.
1915 if (ty == Tpointer && tn->ty == Tfunction)
1916 {
1917 t = this;
1918 goto L1;
1919 }
1920
1921 t = tn->substWildTo(mod);
1922 if (t == tn)
1923 t = this;
1924 else
1925 {
1926 if (ty == Tpointer)
1927 t = t->pointerTo();
1928 else if (ty == Tarray)
1929 t = t->arrayOf();
1930 else if (ty == Tsarray)
1931 t = new TypeSArray(t, ((TypeSArray *)this)->dim->syntaxCopy());
1932 else if (ty == Taarray)
1933 {
1934 t = new TypeAArray(t, ((TypeAArray *)this)->index->syntaxCopy());
1935 ((TypeAArray *)t)->sc = ((TypeAArray *)this)->sc; // duplicate scope
1936 }
1937 else if (ty == Tdelegate)
1938 {
1939 t = new TypeDelegate(t);
1940 }
1941 else
1942 assert(0);
1943
1944 t = t->merge();
1945 }
1946 }
1947 else
1948 t = this;
1949
1950L1:
1951 if (isWild())
1952 {
1953 if (mod == MODimmutable)
1954 {
1955 t = t->immutableOf();
1956 }
1957 else if (mod == MODwildconst)
1958 {
1959 t = t->wildConstOf();
1960 }
1961 else if (mod == MODwild)
1962 {
1963 if (isWildConst())
1964 t = t->wildConstOf();
1965 else
1966 t = t->wildOf();
1967 }
1968 else if (mod == MODconst)
1969 {
1970 t = t->constOf();
1971 }
1972 else
1973 {
1974 if (isWildConst())
1975 t = t->constOf();
1976 else
1977 t = t->mutableOf();
1978 }
1979 }
1980 if (isConst())
1981 t = t->addMod(MODconst);
1982 if (isShared())
1983 t = t->addMod(MODshared);
1984
1985 //printf("-Type::substWildTo t = %s\n", t->toChars());
1986 return t;
1987}
1988
1989Type *TypeFunction::substWildTo(unsigned)
1990{
1991 if (!iswild && !(mod & MODwild))
1992 return this;
1993
1994 // Substitude inout qualifier of function type to mutable or immutable
1995 // would break type system. Instead substitude inout to the most weak
1996 // qualifer - const.
1997 unsigned m = MODconst;
1998
1999 assert(next);
2000 Type *tret = next->substWildTo(m);
2001 Parameters *params = parameters;
2002 if (mod & MODwild)
2003 params = parameters->copy();
2004 for (size_t i = 0; i < params->dim; i++)
2005 {
2006 Parameter *p = (*params)[i];
2007 Type *t = p->type->substWildTo(m);
2008 if (t == p->type)
2009 continue;
2010 if (params == parameters)
2011 params = parameters->copy();
2012 (*params)[i] = new Parameter(p->storageClass, t, NULL, NULL);
2013 }
2014 if (next == tret && params == parameters)
2015 return this;
2016
2017 // Similar to TypeFunction::syntaxCopy;
2018 TypeFunction *t = new TypeFunction(params, tret, varargs, linkage);
2019 t->mod = ((mod & MODwild) ? (mod & ~MODwild) | MODconst : mod);
2020 t->isnothrow = isnothrow;
2021 t->isnogc = isnogc;
2022 t->purity = purity;
2023 t->isproperty = isproperty;
2024 t->isref = isref;
2025 t->isreturn = isreturn;
2026 t->isscope = isscope;
2027 t->isscopeinferred = isscopeinferred;
2028 t->iswild = 0;
2029 t->trust = trust;
2030 t->fargs = fargs;
2031 return t->merge();
2032}
2033
2034/**************************
2035 * Return type with the top level of it being mutable.
2036 */
2037Type *Type::toHeadMutable()
2038{
2039 if (!mod)
2040 return this;
2041 return mutableOf();
2042}
2043
2044/***************************************
2045 * Calculate built-in properties which just the type is necessary.
2046 *
2047 * If flag & 1, don't report "not a property" error and just return NULL.
2048 */
2049Expression *Type::getProperty(Loc loc, Identifier *ident, int flag)
2050{
2051 Expression *e;
2052
2053 if (ident == Id::__sizeof)
2054 {
2055 d_uns64 sz = size(loc);
2056 if (sz == SIZE_INVALID)
2057 return new ErrorExp();
2058 e = new IntegerExp(loc, sz, Type::tsize_t);
2059 }
2060 else if (ident == Id::__xalignof)
2061 {
2062 e = new IntegerExp(loc, alignsize(), Type::tsize_t);
2063 }
2064 else if (ident == Id::_init)
2065 {
2066 Type *tb = toBasetype();
2067 e = defaultInitLiteral(loc);
2068 if (tb->ty == Tstruct && tb->needsNested())
2069 {
2070 StructLiteralExp *se = (StructLiteralExp *)e;
2071 se->useStaticInit = true;
2072 }
2073 }
2074 else if (ident == Id::_mangleof)
2075 {
2076 if (!deco)
2077 {
2078 error(loc, "forward reference of type %s.mangleof", toChars());
2079 e = new ErrorExp();
2080 }
2081 else
2082 {
2083 e = new StringExp(loc, (char *)deco, strlen(deco));
2084 Scope sc;
2085 e = ::semantic(e, &sc);
2086 }
2087 }
2088 else if (ident == Id::stringof)
2089 {
2090 const char *s = toChars();
2091 e = new StringExp(loc, const_cast<char *>(s), strlen(s));
2092 Scope sc;
2093 e = ::semantic(e, &sc);
2094 }
2095 else if (flag && this != Type::terror)
2096 {
2097 return NULL;
2098 }
2099 else
2100 {
2101 Dsymbol *s = NULL;
2102 if (ty == Tstruct || ty == Tclass || ty == Tenum)
2103 s = toDsymbol(NULL);
2104 if (s)
2105 s = s->search_correct(ident);
2106 if (this != Type::terror)
2107 {
2108 if (s)
2109 error(loc, "no property '%s' for type '%s', did you mean '%s'?", ident->toChars(), toChars(), s->toChars());
2110 else
2111 error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars());
2112 }
2113 e = new ErrorExp();
2114 }
2115 return e;
2116}
2117
2118/***************************************
2119 * Access the members of the object e. This type is same as e->type.
2120 *
2121 * If flag & 1, don't report "not a property" error and just return NULL.
2122 */
2123Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
2124{
2125 VarDeclaration *v = NULL;
2126
2127 Expression *ex = e;
2128 while (ex->op == TOKcomma)
2129 ex = ((CommaExp *)ex)->e2;
2130 if (ex->op == TOKdotvar)
2131 {
2132 DotVarExp *dv = (DotVarExp *)ex;
2133 v = dv->var->isVarDeclaration();
2134 }
2135 else if (ex->op == TOKvar)
2136 {
2137 VarExp *ve = (VarExp *)ex;
2138 v = ve->var->isVarDeclaration();
2139 }
2140 if (v)
2141 {
2142 if (ident == Id::offsetof)
2143 {
2144 if (v->isField())
2145 {
2146 AggregateDeclaration *ad = v->toParent()->isAggregateDeclaration();
2147 ad->size(e->loc);
2148 if (ad->sizeok != SIZEOKdone)
2149 return new ErrorExp();
2150 e = new IntegerExp(e->loc, v->offset, Type::tsize_t);
2151 return e;
2152 }
2153 }
2154 else if (ident == Id::_init)
2155 {
2156 Type *tb = toBasetype();
2157 e = defaultInitLiteral(e->loc);
2158 if (tb->ty == Tstruct && tb->needsNested())
2159 {
2160 StructLiteralExp *se = (StructLiteralExp *)e;
2161 se->useStaticInit = true;
2162 }
2163 goto Lreturn;
2164 }
2165 }
2166 if (ident == Id::stringof)
2167 {
2168 /* Bugzilla 3796: this should demangle e->type->deco rather than
2169 * pretty-printing the type.
2170 */
2171 const char *s = e->toChars();
2172 e = new StringExp(e->loc, const_cast<char *>(s), strlen(s));
2173 }
2174 else
2175 e = getProperty(e->loc, ident, flag & 1);
2176
2177Lreturn:
2178 if (e)
2179 e = ::semantic(e, sc);
2180 return e;
2181}
2182
2183/************************************
2184 * Return alignment to use for this type.
2185 */
2186
2187structalign_t Type::alignment()
2188{
2189 return STRUCTALIGN_DEFAULT;
2190}
2191
2192/***************************************
2193 * Figures out what to do with an undefined member reference
2194 * for classes and structs.
2195 *
2196 * If flag & 1, don't report "not a property" error and just return NULL.
2197 */
2198Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident, int flag)
2199{
2200 //printf("Type::noMember(e: %s ident: %s flag: %d)\n", e->toChars(), ident->toChars(), flag);
2201
2202 static int nest; // https://issues.dlang.org/show_bug.cgi?id=17380
2203
2204 if (++nest > 500)
2205 {
2206 ::error(e->loc, "cannot resolve identifier `%s`", ident->toChars());
2207 --nest;
2208 return (flag & 1) ? NULL : new ErrorExp();
2209 }
2210
2211 assert(ty == Tstruct || ty == Tclass);
2212 AggregateDeclaration *sym = toDsymbol(sc)->isAggregateDeclaration();
2213 assert(sym);
2214
2215 if (ident != Id::__sizeof &&
2216 ident != Id::__xalignof &&
2217 ident != Id::_init &&
2218 ident != Id::_mangleof &&
2219 ident != Id::stringof &&
2220 ident != Id::offsetof &&
2221 // Bugzilla 15045: Don't forward special built-in member functions.
2222 ident != Id::ctor &&
2223 ident != Id::dtor &&
2224 ident != Id::__xdtor &&
2225 ident != Id::postblit &&
2226 ident != Id::__xpostblit)
2227 {
2228 /* Look for overloaded opDot() to see if we should forward request
2229 * to it.
2230 */
2231 if (Dsymbol *fd = search_function(sym, Id::opDot))
2232 {
2233 /* Rewrite e.ident as:
2234 * e.opDot().ident
2235 */
2236 e = build_overload(e->loc, sc, e, NULL, fd);
2237 e = new DotIdExp(e->loc, e, ident);
2238 e = ::semantic(e, sc);
2239 --nest;
2240 return e;
2241 }
2242
2243 /* Look for overloaded opDispatch to see if we should forward request
2244 * to it.
2245 */
2246 if (Dsymbol *fd = search_function(sym, Id::opDispatch))
2247 {
2248 /* Rewrite e.ident as:
2249 * e.opDispatch!("ident")
2250 */
2251 TemplateDeclaration *td = fd->isTemplateDeclaration();
2252 if (!td)
2253 {
2254 fd->error("must be a template opDispatch(string s), not a %s", fd->kind());
2255 --nest;
2256 return new ErrorExp();
2257 }
2258 StringExp *se = new StringExp(e->loc, const_cast<char *>(ident->toChars()));
2259 Objects *tiargs = new Objects();
2260 tiargs->push(se);
2261 DotTemplateInstanceExp *dti = new DotTemplateInstanceExp(e->loc, e, Id::opDispatch, tiargs);
2262 dti->ti->tempdecl = td;
2263
2264 /* opDispatch, which doesn't need IFTI, may occur instantiate error.
2265 * It should be gagged if flag & 1.
2266 * e.g.
2267 * template opDispatch(name) if (isValid!name) { ... }
2268 */
2269 unsigned errors = flag & 1 ? global.startGagging() : 0;
2270 e = semanticY(dti, sc, 0);
2271 if (flag & 1 && global.endGagging(errors))
2272 e = NULL;
2273 --nest;
2274 return e;
2275 }
2276
2277 /* See if we should forward to the alias this.
2278 */
2279 if (sym->aliasthis)
2280 { /* Rewrite e.ident as:
2281 * e.aliasthis.ident
2282 */
2283 e = resolveAliasThis(sc, e);
2284 DotIdExp *die = new DotIdExp(e->loc, e, ident);
2285 e = semanticY(die, sc, flag & 1);
2286 --nest;
2287 return e;
2288 }
2289 }
2290
2291 e = Type::dotExp(sc, e, ident, flag);
2292 --nest;
2293 return e;
2294}
2295
2296void Type::error(Loc loc, const char *format, ...)
2297{
2298 va_list ap;
2299 va_start(ap, format);
2300 ::verror(loc, format, ap);
2301 va_end( ap );
2302}
2303
2304void Type::warning(Loc loc, const char *format, ...)
2305{
2306 va_list ap;
2307 va_start(ap, format);
2308 ::vwarning(loc, format, ap);
2309 va_end( ap );
2310}
2311
2312Identifier *Type::getTypeInfoIdent()
2313{
2314 // _init_10TypeInfo_%s
2315 OutBuffer buf;
2316 buf.reserve(32);
2317 mangleToBuffer(this, &buf);
2318
2319 size_t len = buf.offset;
2320 buf.writeByte(0);
2321
2322 // Allocate buffer on stack, fail over to using malloc()
2323 char namebuf[128];
2324 size_t namelen = 19 + sizeof(len) * 3 + len + 1;
efc08a8f 2325 char *name = namelen <= sizeof(namebuf) ? namebuf : (char *)mem.xmalloc(namelen);
03385ed3 2326
d2aef8c0 2327 int length = sprintf(name, "_D%lluTypeInfo_%s6__initZ", (unsigned long long) 9 + len, buf.data);
03385ed3 2328 //printf("%p, deco = %s, name = %s\n", this, deco, name);
e823a10e 2329 assert(0 < length && (size_t)length < namelen); // don't overflow the buffer
03385ed3 2330
d2aef8c0 2331 Identifier *id = Identifier::idPool(name, length);
03385ed3 2332
2333 if (name != namebuf)
2334 free(name);
2335 return id;
2336}
2337
2338TypeBasic *Type::isTypeBasic()
2339{
2340 return NULL;
2341}
2342
2feebf42 2343TypeFunction *Type::toTypeFunction()
2344{
2345 if (ty != Tfunction)
2346 assert(0);
2347 return (TypeFunction *)this;
2348}
03385ed3 2349
2350/***************************************
2351 * Resolve 'this' type to either type, symbol, or expression.
2352 * If errors happened, resolved to Type.terror.
2353 */
2354void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool)
2355{
2356 //printf("Type::resolve() %s, %d\n", toChars(), ty);
2357 Type *t = semantic(loc, sc);
2358 *pt = t;
2359 *pe = NULL;
2360 *ps = NULL;
2361}
2362
2363/***************************************
2364 * Normalize `e` as the result of Type::resolve() process.
2365 */
2366void Type::resolveExp(Expression *e, Type **pt, Expression **pe, Dsymbol **ps)
2367{
2368 *pt = NULL;
2369 *pe = NULL;
2370 *ps = NULL;
2371
2372 Dsymbol *s;
2373 switch (e->op)
2374 {
2375 case TOKerror:
2376 *pt = Type::terror;
2377 return;
2378
2379 case TOKtype:
2380 *pt = e->type;
2381 return;
2382
2383 case TOKvar:
2384 s = ((VarExp *)e)->var;
2385 if (s->isVarDeclaration())
2386 goto Ldefault;
2387 //if (s->isOverDeclaration())
2388 // todo;
2389 break;
2390
2391 case TOKtemplate:
2392 // TemplateDeclaration
2393 s = ((TemplateExp *)e)->td;
2394 break;
2395
2396 case TOKimport:
2397 s = ((ScopeExp *)e)->sds;
2398 // TemplateDeclaration, TemplateInstance, Import, Package, Module
2399 break;
2400
2401 case TOKfunction:
2402 s = getDsymbol(e);
2403 break;
2404
2405 //case TOKthis:
2406 //case TOKsuper:
2407
2408 //case TOKtuple:
2409
2410 //case TOKoverloadset:
2411
2412 //case TOKdotvar:
2413 //case TOKdottd:
2414 //case TOKdotti:
2415 //case TOKdottype:
2416 //case TOKdot:
2417
2418 default:
2419 Ldefault:
2420 *pe = e;
2421 return;
2422 }
2423
2424 *ps = s;
2425}
2426
2427/***************************************
2428 * Return !=0 if the type or any of its subtypes is wild.
2429 */
2430
2431int Type::hasWild() const
2432{
2433 return mod & MODwild;
2434}
2435
2436/***************************************
2437 * Return !=0 if type has pointers that need to
2438 * be scanned by the GC during a collection cycle.
2439 */
2440bool Type::hasPointers()
2441{
2442 //printf("Type::hasPointers() %s, %d\n", toChars(), ty);
2443 return false;
2444}
2445
2446/*************************************
2447 * Detect if type has pointer fields that are initialized to void.
2448 * Local stack variables with such void fields can remain uninitialized,
2449 * leading to pointer bugs.
2450 * Returns:
2451 * true if so
2452 */
2453bool Type::hasVoidInitPointers()
2454{
2455 return false;
2456}
2457
2458/*************************************
2459 * If this is a type of something, return that something.
2460 */
2461
2462Type *Type::nextOf()
2463{
2464 return NULL;
2465}
2466
2467/*************************************
2468 * If this is a type of static array, return its base element type.
2469 */
2470
2471Type *Type::baseElemOf()
2472{
2473 Type *t = toBasetype();
2474 while (t->ty == Tsarray)
2475 t = ((TypeSArray *)t)->next->toBasetype();
2476 return t;
2477}
2478
2479/*************************************
2480 * Bugzilla 14488: Check if the inner most base type is complex or imaginary.
2481 * Should only give alerts when set to emit transitional messages.
2482 */
2483
2484void Type::checkComplexTransition(Loc loc)
2485{
2486 Type *t = baseElemOf();
2487 while (t->ty == Tpointer || t->ty == Tarray)
2488 t = t->nextOf()->baseElemOf();
2489
2490 if (t->isimaginary() || t->iscomplex())
2491 {
2492 Type *rt;
2493 switch (t->ty)
2494 {
2495 case Tcomplex32:
2496 case Timaginary32:
2497 rt = Type::tfloat32; break;
2498 case Tcomplex64:
2499 case Timaginary64:
2500 rt = Type::tfloat64; break;
2501 case Tcomplex80:
2502 case Timaginary80:
2503 rt = Type::tfloat80; break;
2504 default:
2505 assert(0);
2506 }
2507 if (t->iscomplex())
2508 {
2509 message(loc, "use of complex type `%s` is scheduled for deprecation, "
2510 "use `std.complex.Complex!(%s)` instead", toChars(), rt->toChars());
2511 }
2512 else
2513 {
2514 message(loc, "use of imaginary type `%s` is scheduled for deprecation, "
2515 "use `%s` instead\n", toChars(), rt->toChars());
2516 }
2517 }
2518}
2519
960d7913 2520/*******************************************
2521 * Compute number of elements for a (possibly multidimensional) static array,
2522 * or 1 for other types.
2523 * Params:
2524 * loc = for error message
2525 * Returns:
2526 * number of elements, uint.max on overflow
2527 */
2528unsigned Type::numberOfElems(const Loc &loc)
2529{
2530 //printf("Type::numberOfElems()\n");
2531 uinteger_t n = 1;
2532 Type *tb = this;
2533 while ((tb = tb->toBasetype())->ty == Tsarray)
2534 {
2535 bool overflow = false;
2536 n = mulu(n, ((TypeSArray *)tb)->dim->toUInteger(), overflow);
2537 if (overflow || n >= UINT32_MAX)
2538 {
2539 error(loc, "static array `%s` size overflowed to %llu", toChars(), (unsigned long long)n);
2540 return UINT32_MAX;
2541 }
2542 tb = ((TypeSArray *)tb)->next;
2543 }
2544 return (unsigned)n;
2545}
2546
03385ed3 2547/****************************************
2548 * Return the mask that an integral type will
2549 * fit into.
2550 */
2551uinteger_t Type::sizemask()
2552{ uinteger_t m;
2553
2554 switch (toBasetype()->ty)
2555 {
2556 case Tbool: m = 1; break;
2557 case Tchar:
2558 case Tint8:
2559 case Tuns8: m = 0xFF; break;
2560 case Twchar:
2561 case Tint16:
2562 case Tuns16: m = 0xFFFFUL; break;
2563 case Tdchar:
2564 case Tint32:
2565 case Tuns32: m = 0xFFFFFFFFUL; break;
2566 case Tint64:
2567 case Tuns64: m = 0xFFFFFFFFFFFFFFFFULL; break;
2568 default:
2569 assert(0);
2570 }
2571 return m;
2572}
2573
2574/* ============================= TypeError =========================== */
2575
2576TypeError::TypeError()
2577 : Type(Terror)
2578{
2579}
2580
2581Type *TypeError::syntaxCopy()
2582{
2583 // No semantic analysis done, no need to copy
2584 return this;
2585}
2586
2587d_uns64 TypeError::size(Loc) { return SIZE_INVALID; }
2588Expression *TypeError::getProperty(Loc, Identifier *, int) { return new ErrorExp(); }
2589Expression *TypeError::dotExp(Scope *, Expression *, Identifier *, int) { return new ErrorExp(); }
2590Expression *TypeError::defaultInit(Loc) { return new ErrorExp(); }
2591Expression *TypeError::defaultInitLiteral(Loc) { return new ErrorExp(); }
2592
2593/* ============================= TypeNext =========================== */
2594
2595TypeNext::TypeNext(TY ty, Type *next)
2596 : Type(ty)
2597{
2598 this->next = next;
2599}
2600
2601void TypeNext::checkDeprecated(Loc loc, Scope *sc)
2602{
2603 Type::checkDeprecated(loc, sc);
2604 if (next) // next can be NULL if TypeFunction and auto return type
2605 next->checkDeprecated(loc, sc);
2606}
2607
2608int TypeNext::hasWild() const
2609{
2610 if (ty == Tfunction)
2611 return 0;
2612 if (ty == Tdelegate)
2613 return Type::hasWild();
2614 return mod & MODwild || (next && next->hasWild());
2615}
2616
2617
2618/*******************************
2619 * For TypeFunction, nextOf() can return NULL if the function return
2620 * type is meant to be inferred, and semantic() hasn't yet ben run
2621 * on the function. After semantic(), it must no longer be NULL.
2622 */
2623
2624Type *TypeNext::nextOf()
2625{
2626 return next;
2627}
2628
2629Type *TypeNext::makeConst()
2630{
2631 //printf("TypeNext::makeConst() %p, %s\n", this, toChars());
2632 if (cto)
2633 {
2634 assert(cto->mod == MODconst);
2635 return cto;
2636 }
2637 TypeNext *t = (TypeNext *)Type::makeConst();
2638 if (ty != Tfunction && next->ty != Tfunction &&
2639 !next->isImmutable())
2640 {
2641 if (next->isShared())
2642 {
2643 if (next->isWild())
2644 t->next = next->sharedWildConstOf();
2645 else
2646 t->next = next->sharedConstOf();
2647 }
2648 else
2649 {
2650 if (next->isWild())
2651 t->next = next->wildConstOf();
2652 else
2653 t->next = next->constOf();
2654 }
2655 }
2656 //printf("TypeNext::makeConst() returns %p, %s\n", t, t->toChars());
2657 return t;
2658}
2659
2660Type *TypeNext::makeImmutable()
2661{
2662 //printf("TypeNext::makeImmutable() %s\n", toChars());
2663 if (ito)
2664 {
2665 assert(ito->isImmutable());
2666 return ito;
2667 }
2668 TypeNext *t = (TypeNext *)Type::makeImmutable();
2669 if (ty != Tfunction && next->ty != Tfunction &&
2670 !next->isImmutable())
2671 {
2672 t->next = next->immutableOf();
2673 }
2674 return t;
2675}
2676
2677Type *TypeNext::makeShared()
2678{
2679 //printf("TypeNext::makeShared() %s\n", toChars());
2680 if (sto)
2681 {
2682 assert(sto->mod == MODshared);
2683 return sto;
2684 }
2685 TypeNext *t = (TypeNext *)Type::makeShared();
2686 if (ty != Tfunction && next->ty != Tfunction &&
2687 !next->isImmutable())
2688 {
2689 if (next->isWild())
2690 {
2691 if (next->isConst())
2692 t->next = next->sharedWildConstOf();
2693 else
2694 t->next = next->sharedWildOf();
2695 }
2696 else
2697 {
2698 if (next->isConst())
2699 t->next = next->sharedConstOf();
2700 else
2701 t->next = next->sharedOf();
2702 }
2703 }
2704 //printf("TypeNext::makeShared() returns %p, %s\n", t, t->toChars());
2705 return t;
2706}
2707
2708Type *TypeNext::makeSharedConst()
2709{
2710 //printf("TypeNext::makeSharedConst() %s\n", toChars());
2711 if (scto)
2712 {
2713 assert(scto->mod == (MODshared | MODconst));
2714 return scto;
2715 }
2716 TypeNext *t = (TypeNext *)Type::makeSharedConst();
2717 if (ty != Tfunction && next->ty != Tfunction &&
2718 !next->isImmutable())
2719 {
2720 if (next->isWild())
2721 t->next = next->sharedWildConstOf();
2722 else
2723 t->next = next->sharedConstOf();
2724 }
2725 //printf("TypeNext::makeSharedConst() returns %p, %s\n", t, t->toChars());
2726 return t;
2727}
2728
2729Type *TypeNext::makeWild()
2730{
2731 //printf("TypeNext::makeWild() %s\n", toChars());
2732 if (wto)
2733 {
2734 assert(wto->mod == MODwild);
2735 return wto;
2736 }
2737 TypeNext *t = (TypeNext *)Type::makeWild();
2738 if (ty != Tfunction && next->ty != Tfunction &&
2739 !next->isImmutable())
2740 {
2741 if (next->isShared())
2742 {
2743 if (next->isConst())
2744 t->next = next->sharedWildConstOf();
2745 else
2746 t->next = next->sharedWildOf();
2747 }
2748 else
2749 {
2750 if (next->isConst())
2751 t->next = next->wildConstOf();
2752 else
2753 t->next = next->wildOf();
2754 }
2755 }
2756 //printf("TypeNext::makeWild() returns %p, %s\n", t, t->toChars());
2757 return t;
2758}
2759
2760Type *TypeNext::makeWildConst()
2761{
2762 //printf("TypeNext::makeWildConst() %s\n", toChars());
2763 if (wcto)
2764 {
2765 assert(wcto->mod == MODwildconst);
2766 return wcto;
2767 }
2768 TypeNext *t = (TypeNext *)Type::makeWildConst();
2769 if (ty != Tfunction && next->ty != Tfunction &&
2770 !next->isImmutable())
2771 {
2772 if (next->isShared())
2773 t->next = next->sharedWildConstOf();
2774 else
2775 t->next = next->wildConstOf();
2776 }
2777 //printf("TypeNext::makeWildConst() returns %p, %s\n", t, t->toChars());
2778 return t;
2779}
2780
2781Type *TypeNext::makeSharedWild()
2782{
2783 //printf("TypeNext::makeSharedWild() %s\n", toChars());
2784 if (swto)
2785 {
2786 assert(swto->isSharedWild());
2787 return swto;
2788 }
2789 TypeNext *t = (TypeNext *)Type::makeSharedWild();
2790 if (ty != Tfunction && next->ty != Tfunction &&
2791 !next->isImmutable())
2792 {
2793 if (next->isConst())
2794 t->next = next->sharedWildConstOf();
2795 else
2796 t->next = next->sharedWildOf();
2797 }
2798 //printf("TypeNext::makeSharedWild() returns %p, %s\n", t, t->toChars());
2799 return t;
2800}
2801
2802Type *TypeNext::makeSharedWildConst()
2803{
2804 //printf("TypeNext::makeSharedWildConst() %s\n", toChars());
2805 if (swcto)
2806 {
2807 assert(swcto->mod == (MODshared | MODwildconst));
2808 return swcto;
2809 }
2810 TypeNext *t = (TypeNext *)Type::makeSharedWildConst();
2811 if (ty != Tfunction && next->ty != Tfunction &&
2812 !next->isImmutable())
2813 {
2814 t->next = next->sharedWildConstOf();
2815 }
2816 //printf("TypeNext::makeSharedWildConst() returns %p, %s\n", t, t->toChars());
2817 return t;
2818}
2819
2820Type *TypeNext::makeMutable()
2821{
2822 //printf("TypeNext::makeMutable() %p, %s\n", this, toChars());
2823 TypeNext *t = (TypeNext *)Type::makeMutable();
2824 if (ty == Tsarray)
2825 {
2826 t->next = next->mutableOf();
2827 }
2828 //printf("TypeNext::makeMutable() returns %p, %s\n", t, t->toChars());
2829 return t;
2830}
2831
2832MATCH TypeNext::constConv(Type *to)
2833{
2834 //printf("TypeNext::constConv from = %s, to = %s\n", toChars(), to->toChars());
2835 if (equals(to))
2836 return MATCHexact;
2837
2838 if (!(ty == to->ty && MODimplicitConv(mod, to->mod)))
2839 return MATCHnomatch;
2840
2841 Type *tn = to->nextOf();
2842 if (!(tn && next->ty == tn->ty))
2843 return MATCHnomatch;
2844
2845 MATCH m;
2846 if (to->isConst()) // whole tail const conversion
2847 { // Recursive shared level check
2848 m = next->constConv(tn);
2849 if (m == MATCHexact)
2850 m = MATCHconst;
2851 }
2852 else
2853 { //printf("\tnext => %s, to->next => %s\n", next->toChars(), tn->toChars());
2854 m = next->equals(tn) ? MATCHconst : MATCHnomatch;
2855 }
2856 return m;
2857}
2858
2859unsigned char TypeNext::deduceWild(Type *t, bool isRef)
2860{
2861 if (ty == Tfunction)
2862 return 0;
2863
2864 unsigned char wm;
2865
2866 Type *tn = t->nextOf();
2867 if (!isRef && (ty == Tarray || ty == Tpointer) && tn)
2868 {
2869 wm = next->deduceWild(tn, true);
2870 if (!wm)
2871 wm = Type::deduceWild(t, true);
2872 }
2873 else
2874 {
2875 wm = Type::deduceWild(t, isRef);
2876 if (!wm && tn)
2877 wm = next->deduceWild(tn, true);
2878 }
2879
2880 return wm;
2881}
2882
2883
2884void TypeNext::transitive()
2885{
2886 /* Invoke transitivity of type attributes
2887 */
2888 next = next->addMod(mod);
2889}
2890
2891/* ============================= TypeBasic =========================== */
2892
2893#define TFLAGSintegral 1
2894#define TFLAGSfloating 2
2895#define TFLAGSunsigned 4
2896#define TFLAGSreal 8
2897#define TFLAGSimaginary 0x10
2898#define TFLAGScomplex 0x20
2899
2900TypeBasic::TypeBasic(TY ty)
2901 : Type(ty)
2902{ const char *d;
2903 unsigned flags;
2904
2905 flags = 0;
2906 switch (ty)
2907 {
2908 case Tvoid: d = Token::toChars(TOKvoid);
2909 break;
2910
2911 case Tint8: d = Token::toChars(TOKint8);
2912 flags |= TFLAGSintegral;
2913 break;
2914
2915 case Tuns8: d = Token::toChars(TOKuns8);
2916 flags |= TFLAGSintegral | TFLAGSunsigned;
2917 break;
2918
2919 case Tint16: d = Token::toChars(TOKint16);
2920 flags |= TFLAGSintegral;
2921 break;
2922
2923 case Tuns16: d = Token::toChars(TOKuns16);
2924 flags |= TFLAGSintegral | TFLAGSunsigned;
2925 break;
2926
2927 case Tint32: d = Token::toChars(TOKint32);
2928 flags |= TFLAGSintegral;
2929 break;
2930
2931 case Tuns32: d = Token::toChars(TOKuns32);
2932 flags |= TFLAGSintegral | TFLAGSunsigned;
2933 break;
2934
2935 case Tfloat32: d = Token::toChars(TOKfloat32);
2936 flags |= TFLAGSfloating | TFLAGSreal;
2937 break;
2938
2939 case Tint64: d = Token::toChars(TOKint64);
2940 flags |= TFLAGSintegral;
2941 break;
2942
2943 case Tuns64: d = Token::toChars(TOKuns64);
2944 flags |= TFLAGSintegral | TFLAGSunsigned;
2945 break;
2946
2947 case Tint128: d = Token::toChars(TOKint128);
2948 flags |= TFLAGSintegral;
2949 break;
2950
2951 case Tuns128: d = Token::toChars(TOKuns128);
2952 flags |= TFLAGSintegral | TFLAGSunsigned;
2953 break;
2954
2955 case Tfloat64: d = Token::toChars(TOKfloat64);
2956 flags |= TFLAGSfloating | TFLAGSreal;
2957 break;
2958
2959 case Tfloat80: d = Token::toChars(TOKfloat80);
2960 flags |= TFLAGSfloating | TFLAGSreal;
2961 break;
2962
2963 case Timaginary32: d = Token::toChars(TOKimaginary32);
2964 flags |= TFLAGSfloating | TFLAGSimaginary;
2965 break;
2966
2967 case Timaginary64: d = Token::toChars(TOKimaginary64);
2968 flags |= TFLAGSfloating | TFLAGSimaginary;
2969 break;
2970
2971 case Timaginary80: d = Token::toChars(TOKimaginary80);
2972 flags |= TFLAGSfloating | TFLAGSimaginary;
2973 break;
2974
2975 case Tcomplex32: d = Token::toChars(TOKcomplex32);
2976 flags |= TFLAGSfloating | TFLAGScomplex;
2977 break;
2978
2979 case Tcomplex64: d = Token::toChars(TOKcomplex64);
2980 flags |= TFLAGSfloating | TFLAGScomplex;
2981 break;
2982
2983 case Tcomplex80: d = Token::toChars(TOKcomplex80);
2984 flags |= TFLAGSfloating | TFLAGScomplex;
2985 break;
2986
2987 case Tbool: d = "bool";
2988 flags |= TFLAGSintegral | TFLAGSunsigned;
2989 break;
2990
2991 case Tchar: d = Token::toChars(TOKchar);
2992 flags |= TFLAGSintegral | TFLAGSunsigned;
2993 break;
2994
2995 case Twchar: d = Token::toChars(TOKwchar);
2996 flags |= TFLAGSintegral | TFLAGSunsigned;
2997 break;
2998
2999 case Tdchar: d = Token::toChars(TOKdchar);
3000 flags |= TFLAGSintegral | TFLAGSunsigned;
3001 break;
3002
3003 default: assert(0);
3004 }
3005 this->dstring = d;
3006 this->flags = flags;
3007 merge();
3008}
3009
3010const char *TypeBasic::kind()
3011{
3012 return dstring;
3013}
3014
3015Type *TypeBasic::syntaxCopy()
3016{
3017 // No semantic analysis done on basic types, no need to copy
3018 return this;
3019}
3020
3021d_uns64 TypeBasic::size(Loc)
3022{ unsigned size;
3023
3024 //printf("TypeBasic::size()\n");
3025 switch (ty)
3026 {
3027 case Tint8:
3028 case Tuns8: size = 1; break;
3029 case Tint16:
3030 case Tuns16: size = 2; break;
3031 case Tint32:
3032 case Tuns32:
3033 case Tfloat32:
3034 case Timaginary32:
3035 size = 4; break;
3036 case Tint64:
3037 case Tuns64:
3038 case Tfloat64:
3039 case Timaginary64:
3040 size = 8; break;
3041 case Tfloat80:
3042 case Timaginary80:
3043 size = Target::realsize; break;
3044 case Tcomplex32:
3045 size = 8; break;
3046 case Tcomplex64:
3047 case Tint128:
3048 case Tuns128:
3049 size = 16; break;
3050 case Tcomplex80:
3051 size = Target::realsize * 2; break;
3052
3053 case Tvoid:
3054 //size = Type::size(); // error message
3055 size = 1;
3056 break;
3057
3058 case Tbool: size = 1; break;
3059 case Tchar: size = 1; break;
3060 case Twchar: size = 2; break;
3061 case Tdchar: size = 4; break;
3062
3063 default:
3064 assert(0);
3065 break;
3066 }
3067 //printf("TypeBasic::size() = %d\n", size);
3068 return size;
3069}
3070
3071unsigned TypeBasic::alignsize()
3072{
3073 return Target::alignsize(this);
3074}
3075
3076
3077Expression *TypeBasic::getProperty(Loc loc, Identifier *ident, int flag)
3078{
3079 Expression *e;
3080 dinteger_t ivalue;
3081 real_t fvalue;
3082
3083 //printf("TypeBasic::getProperty('%s')\n", ident->toChars());
3084 if (ident == Id::max)
3085 {
3086 switch (ty)
3087 {
3088 case Tint8:
3089 ivalue = 0x7F;
3090 goto Livalue;
3091 case Tuns8:
3092 ivalue = 0xFF;
3093 goto Livalue;
3094 case Tint16:
3095 ivalue = 0x7FFFUL;
3096 goto Livalue;
3097 case Tuns16:
3098 ivalue = 0xFFFFUL;
3099 goto Livalue;
3100 case Tint32:
3101 ivalue = 0x7FFFFFFFUL;
3102 goto Livalue;
3103 case Tuns32:
3104 ivalue = 0xFFFFFFFFUL;
3105 goto Livalue;
3106 case Tint64:
3107 ivalue = 0x7FFFFFFFFFFFFFFFLL;
3108 goto Livalue;
3109 case Tuns64:
3110 ivalue = 0xFFFFFFFFFFFFFFFFULL;
3111 goto Livalue;
3112 case Tbool:
3113 ivalue = 1;
3114 goto Livalue;
3115 case Tchar:
3116 ivalue = 0xFF;
3117 goto Livalue;
3118 case Twchar:
3119 ivalue = 0xFFFFUL;
3120 goto Livalue;
3121 case Tdchar:
3122 ivalue = 0x10FFFFUL;
3123 goto Livalue;
3124 case Tcomplex32:
3125 case Timaginary32:
3126 case Tfloat32:
3127 fvalue = Target::FloatProperties::max;
3128 goto Lfvalue;
3129 case Tcomplex64:
3130 case Timaginary64:
3131 case Tfloat64:
3132 fvalue = Target::DoubleProperties::max;
3133 goto Lfvalue;
3134 case Tcomplex80:
3135 case Timaginary80:
3136 case Tfloat80:
3137 fvalue = Target::RealProperties::max;
3138 goto Lfvalue;
3139 }
3140 }
3141 else if (ident == Id::min)
3142 {
3143 switch (ty)
3144 {
3145 case Tint8:
3146 ivalue = -128;
3147 goto Livalue;
3148 case Tuns8:
3149 ivalue = 0;
3150 goto Livalue;
3151 case Tint16:
3152 ivalue = -32768;
3153 goto Livalue;
3154 case Tuns16:
3155 ivalue = 0;
3156 goto Livalue;
3157 case Tint32:
3158 ivalue = -2147483647L - 1;
3159 goto Livalue;
3160 case Tuns32:
3161 ivalue = 0;
3162 goto Livalue;
3163 case Tint64:
3164 ivalue = (-9223372036854775807LL-1LL);
3165 goto Livalue;
3166 case Tuns64:
3167 ivalue = 0;
3168 goto Livalue;
3169 case Tbool:
3170 ivalue = 0;
3171 goto Livalue;
3172 case Tchar:
3173 ivalue = 0;
3174 goto Livalue;
3175 case Twchar:
3176 ivalue = 0;
3177 goto Livalue;
3178 case Tdchar:
3179 ivalue = 0;
3180 goto Livalue;
3181
3182 case Tcomplex32:
3183 case Timaginary32:
3184 case Tfloat32:
3185 case Tcomplex64:
3186 case Timaginary64:
3187 case Tfloat64:
3188 case Tcomplex80:
3189 case Timaginary80:
3190 case Tfloat80:
3191 error(loc, "use .min_normal property instead of .min");
3192 return new ErrorExp();
3193 }
3194 }
3195 else if (ident == Id::min_normal)
3196 {
3197 switch (ty)
3198 {
3199 case Tcomplex32:
3200 case Timaginary32:
3201 case Tfloat32:
3202 fvalue = Target::FloatProperties::min_normal;
3203 goto Lfvalue;
3204 case Tcomplex64:
3205 case Timaginary64:
3206 case Tfloat64:
3207 fvalue = Target::DoubleProperties::min_normal;
3208 goto Lfvalue;
3209 case Tcomplex80:
3210 case Timaginary80:
3211 case Tfloat80:
3212 fvalue = Target::RealProperties::min_normal;
3213 goto Lfvalue;
3214 }
3215 }
3216 else if (ident == Id::nan)
3217 {
3218 switch (ty)
3219 {
3220 case Tcomplex32:
3221 case Tcomplex64:
3222 case Tcomplex80:
3223 case Timaginary32:
3224 case Timaginary64:
3225 case Timaginary80:
3226 case Tfloat32:
3227 case Tfloat64:
3228 case Tfloat80:
3229 fvalue = Target::RealProperties::nan;
3230 goto Lfvalue;
3231 }
3232 }
3233 else if (ident == Id::infinity)
3234 {
3235 switch (ty)
3236 {
3237 case Tcomplex32:
3238 case Tcomplex64:
3239 case Tcomplex80:
3240 case Timaginary32:
3241 case Timaginary64:
3242 case Timaginary80:
3243 case Tfloat32:
3244 case Tfloat64:
3245 case Tfloat80:
3246 fvalue = Target::RealProperties::infinity;
3247 goto Lfvalue;
3248 }
3249 }
3250 else if (ident == Id::dig)
3251 {
3252 switch (ty)
3253 {
3254 case Tcomplex32:
3255 case Timaginary32:
3256 case Tfloat32:
3257 ivalue = Target::FloatProperties::dig;
3258 goto Lint;
3259 case Tcomplex64:
3260 case Timaginary64:
3261 case Tfloat64:
3262 ivalue = Target::DoubleProperties::dig;
3263 goto Lint;
3264 case Tcomplex80:
3265 case Timaginary80:
3266 case Tfloat80:
3267 ivalue = Target::RealProperties::dig;
3268 goto Lint;
3269 }
3270 }
3271 else if (ident == Id::epsilon)
3272 {
3273 switch (ty)
3274 {
3275 case Tcomplex32:
3276 case Timaginary32:
3277 case Tfloat32:
3278 fvalue = Target::FloatProperties::epsilon;
3279 goto Lfvalue;
3280 case Tcomplex64:
3281 case Timaginary64:
3282 case Tfloat64:
3283 fvalue = Target::DoubleProperties::epsilon;
3284 goto Lfvalue;
3285 case Tcomplex80:
3286 case Timaginary80:
3287 case Tfloat80:
3288 fvalue = Target::RealProperties::epsilon;
3289 goto Lfvalue;
3290 }
3291 }
3292 else if (ident == Id::mant_dig)
3293 {
3294 switch (ty)
3295 {
3296 case Tcomplex32:
3297 case Timaginary32:
3298 case Tfloat32:
3299 ivalue = Target::FloatProperties::mant_dig;
3300 goto Lint;
3301 case Tcomplex64:
3302 case Timaginary64:
3303 case Tfloat64:
3304 ivalue = Target::DoubleProperties::mant_dig;
3305 goto Lint;
3306 case Tcomplex80:
3307 case Timaginary80:
3308 case Tfloat80:
3309 ivalue = Target::RealProperties::mant_dig;
3310 goto Lint;
3311 }
3312 }
3313 else if (ident == Id::max_10_exp)
3314 {
3315 switch (ty)
3316 {
3317 case Tcomplex32:
3318 case Timaginary32:
3319 case Tfloat32:
3320 ivalue = Target::FloatProperties::max_10_exp;
3321 goto Lint;
3322 case Tcomplex64:
3323 case Timaginary64:
3324 case Tfloat64:
3325 ivalue = Target::DoubleProperties::max_10_exp;
3326 goto Lint;
3327 case Tcomplex80:
3328 case Timaginary80:
3329 case Tfloat80:
3330 ivalue = Target::RealProperties::max_10_exp;
3331 goto Lint;
3332 }
3333 }
3334 else if (ident == Id::max_exp)
3335 {
3336 switch (ty)
3337 {
3338 case Tcomplex32:
3339 case Timaginary32:
3340 case Tfloat32:
3341 ivalue = Target::FloatProperties::max_exp;
3342 goto Lint;
3343 case Tcomplex64:
3344 case Timaginary64:
3345 case Tfloat64:
3346 ivalue = Target::DoubleProperties::max_exp;
3347 goto Lint;
3348 case Tcomplex80:
3349 case Timaginary80:
3350 case Tfloat80:
3351 ivalue = Target::RealProperties::max_exp;
3352 goto Lint;
3353 }
3354 }
3355 else if (ident == Id::min_10_exp)
3356 {
3357 switch (ty)
3358 {
3359 case Tcomplex32:
3360 case Timaginary32:
3361 case Tfloat32:
3362 ivalue = Target::FloatProperties::min_10_exp;
3363 goto Lint;
3364 case Tcomplex64:
3365 case Timaginary64:
3366 case Tfloat64:
3367 ivalue = Target::DoubleProperties::min_10_exp;
3368 goto Lint;
3369 case Tcomplex80:
3370 case Timaginary80:
3371 case Tfloat80:
3372 ivalue = Target::RealProperties::min_10_exp;
3373 goto Lint;
3374 }
3375 }
3376 else if (ident == Id::min_exp)
3377 {
3378 switch (ty)
3379 {
3380 case Tcomplex32:
3381 case Timaginary32:
3382 case Tfloat32:
3383 ivalue = Target::FloatProperties::min_exp;
3384 goto Lint;
3385 case Tcomplex64:
3386 case Timaginary64:
3387 case Tfloat64:
3388 ivalue = Target::DoubleProperties::min_exp;
3389 goto Lint;
3390 case Tcomplex80:
3391 case Timaginary80:
3392 case Tfloat80:
3393 ivalue = Target::RealProperties::min_exp;
3394 goto Lint;
3395 }
3396 }
3397
3398 return Type::getProperty(loc, ident, flag);
3399
3400Livalue:
3401 e = new IntegerExp(loc, ivalue, this);
3402 return e;
3403
3404Lfvalue:
3405 if (isreal() || isimaginary())
3406 e = new RealExp(loc, fvalue, this);
3407 else
3408 {
3409 complex_t cvalue = complex_t(fvalue, fvalue);
3410 //for (int i = 0; i < 20; i++)
3411 // printf("%02x ", ((unsigned char *)&cvalue)[i]);
3412 //printf("\n");
3413 e = new ComplexExp(loc, cvalue, this);
3414 }
3415 return e;
3416
3417Lint:
3418 e = new IntegerExp(loc, ivalue, Type::tint32);
3419 return e;
3420}
3421
3422Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
3423{
3424 Type *t;
3425
3426 if (ident == Id::re)
3427 {
3428 switch (ty)
3429 {
3430 case Tcomplex32: t = tfloat32; goto L1;
3431 case Tcomplex64: t = tfloat64; goto L1;
3432 case Tcomplex80: t = tfloat80; goto L1;
3433 L1:
3434 e = e->castTo(sc, t);
3435 break;
3436
3437 case Tfloat32:
3438 case Tfloat64:
3439 case Tfloat80:
3440 break;
3441
3442 case Timaginary32: t = tfloat32; goto L2;
3443 case Timaginary64: t = tfloat64; goto L2;
3444 case Timaginary80: t = tfloat80; goto L2;
3445 L2:
3446 e = new RealExp(e->loc, CTFloat::zero, t);
3447 break;
3448
3449 default:
3450 e = Type::getProperty(e->loc, ident, flag);
3451 break;
3452 }
3453 }
3454 else if (ident == Id::im)
3455 { Type *t2;
3456
3457 switch (ty)
3458 {
3459 case Tcomplex32: t = timaginary32; t2 = tfloat32; goto L3;
3460 case Tcomplex64: t = timaginary64; t2 = tfloat64; goto L3;
3461 case Tcomplex80: t = timaginary80; t2 = tfloat80; goto L3;
3462 L3:
3463 e = e->castTo(sc, t);
3464 e->type = t2;
3465 break;
3466
3467 case Timaginary32: t = tfloat32; goto L4;
3468 case Timaginary64: t = tfloat64; goto L4;
3469 case Timaginary80: t = tfloat80; goto L4;
3470 L4:
3471 e = e->copy();
3472 e->type = t;
3473 break;
3474
3475 case Tfloat32:
3476 case Tfloat64:
3477 case Tfloat80:
3478 e = new RealExp(e->loc, CTFloat::zero, this);
3479 break;
3480
3481 default:
3482 e = Type::getProperty(e->loc, ident, flag);
3483 break;
3484 }
3485 }
3486 else
3487 {
3488 return Type::dotExp(sc, e, ident, flag);
3489 }
3490 if (!(flag & 1) || e)
3491 e = ::semantic(e, sc);
3492 return e;
3493}
3494
3495Expression *TypeBasic::defaultInit(Loc loc)
3496{
3497 dinteger_t value = 0;
3498
3499 switch (ty)
3500 {
3501 case Tchar:
3502 value = 0xFF;
3503 break;
3504
3505 case Twchar:
3506 case Tdchar:
3507 value = 0xFFFF;
3508 break;
3509
3510 case Timaginary32:
3511 case Timaginary64:
3512 case Timaginary80:
3513 case Tfloat32:
3514 case Tfloat64:
3515 case Tfloat80:
3516 return new RealExp(loc, Target::RealProperties::snan, this);
3517
3518 case Tcomplex32:
3519 case Tcomplex64:
3520 case Tcomplex80:
3521 { // Can't use fvalue + I*fvalue (the im part becomes a quiet NaN).
3522 complex_t cvalue = complex_t(Target::RealProperties::snan, Target::RealProperties::snan);
3523 return new ComplexExp(loc, cvalue, this);
3524 }
3525
3526 case Tvoid:
3527 error(loc, "void does not have a default initializer");
3528 return new ErrorExp();
3529 }
3530 return new IntegerExp(loc, value, this);
3531}
3532
3533bool TypeBasic::isZeroInit(Loc)
3534{
3535 switch (ty)
3536 {
3537 case Tchar:
3538 case Twchar:
3539 case Tdchar:
3540 case Timaginary32:
3541 case Timaginary64:
3542 case Timaginary80:
3543 case Tfloat32:
3544 case Tfloat64:
3545 case Tfloat80:
3546 case Tcomplex32:
3547 case Tcomplex64:
3548 case Tcomplex80:
3549 return false; // no
3550 default:
3551 return true; // yes
3552 }
3553}
3554
3555bool TypeBasic::isintegral()
3556{
3557 //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags);
3558 return (flags & TFLAGSintegral) != 0;
3559}
3560
3561bool TypeBasic::isfloating()
3562{
3563 return (flags & TFLAGSfloating) != 0;
3564}
3565
3566bool TypeBasic::isreal()
3567{
3568 return (flags & TFLAGSreal) != 0;
3569}
3570
3571bool TypeBasic::isimaginary()
3572{
3573 return (flags & TFLAGSimaginary) != 0;
3574}
3575
3576bool TypeBasic::iscomplex()
3577{
3578 return (flags & TFLAGScomplex) != 0;
3579}
3580
3581bool TypeBasic::isunsigned()
3582{
3583 return (flags & TFLAGSunsigned) != 0;
3584}
3585
3586bool TypeBasic::isscalar()
3587{
3588 return (flags & (TFLAGSintegral | TFLAGSfloating)) != 0;
3589}
3590
3591MATCH TypeBasic::implicitConvTo(Type *to)
3592{
3593 //printf("TypeBasic::implicitConvTo(%s) from %s\n", to->toChars(), toChars());
3594 if (this == to)
3595 return MATCHexact;
3596
3597 if (ty == to->ty)
3598 {
3599 if (mod == to->mod)
3600 return MATCHexact;
3601 else if (MODimplicitConv(mod, to->mod))
3602 return MATCHconst;
3603 else if (!((mod ^ to->mod) & MODshared)) // for wild matching
3604 return MATCHconst;
3605 else
3606 return MATCHconvert;
3607 }
3608
3609 if (ty == Tvoid || to->ty == Tvoid)
3610 return MATCHnomatch;
3611 if (to->ty == Tbool)
3612 return MATCHnomatch;
3613
3614 TypeBasic *tob;
3615 if (to->ty == Tvector && to->deco)
3616 {
3617 TypeVector *tv = (TypeVector *)to;
3618 tob = tv->elementType();
3619 }
3620 else if (to->ty == Tenum)
3621 {
3622 EnumDeclaration *ed = ((TypeEnum *)to)->sym;
3623 if (ed->isSpecial())
3624 {
3625 /* Special enums that allow implicit conversions to them. */
3626 tob = to->toBasetype()->isTypeBasic();
3627 if (tob)
3628 return implicitConvTo(tob);
3629 }
3630 else
3631 return MATCHnomatch;
3632 }
3633 else
3634 tob = to->isTypeBasic();
3635 if (!tob)
3636 return MATCHnomatch;
3637
3638 if (flags & TFLAGSintegral)
3639 {
3640 // Disallow implicit conversion of integers to imaginary or complex
3641 if (tob->flags & (TFLAGSimaginary | TFLAGScomplex))
3642 return MATCHnomatch;
3643
3644 // If converting from integral to integral
3645 if (tob->flags & TFLAGSintegral)
3646 { d_uns64 sz = size(Loc());
3647 d_uns64 tosz = tob->size(Loc());
3648
3649 /* Can't convert to smaller size
3650 */
3651 if (sz > tosz)
3652 return MATCHnomatch;
3653
3654 /* Can't change sign if same size
3655 */
3656 /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned)
3657 return MATCHnomatch;*/
3658 }
3659 }
3660 else if (flags & TFLAGSfloating)
3661 {
3662 // Disallow implicit conversion of floating point to integer
3663 if (tob->flags & TFLAGSintegral)
3664 return MATCHnomatch;
3665
3666 assert(tob->flags & TFLAGSfloating || to->ty == Tvector);
3667
3668 // Disallow implicit conversion from complex to non-complex
3669 if (flags & TFLAGScomplex && !(tob->flags & TFLAGScomplex))
3670 return MATCHnomatch;
3671
3672 // Disallow implicit conversion of real or imaginary to complex
3673 if (flags & (TFLAGSreal | TFLAGSimaginary) &&
3674 tob->flags & TFLAGScomplex)
3675 return MATCHnomatch;
3676
3677 // Disallow implicit conversion to-from real and imaginary
3678 if ((flags & (TFLAGSreal | TFLAGSimaginary)) !=
3679 (tob->flags & (TFLAGSreal | TFLAGSimaginary)))
3680 return MATCHnomatch;
3681 }
3682 return MATCHconvert;
3683}
3684
3685TypeBasic *TypeBasic::isTypeBasic()
3686{
3687 return (TypeBasic *)this;
3688}
3689
3690/* ============================= TypeVector =========================== */
3691
3692/* The basetype must be one of:
3693 * byte[16],ubyte[16],short[8],ushort[8],int[4],uint[4],long[2],ulong[2],float[4],double[2]
3694 * For AVX:
3695 * byte[32],ubyte[32],short[16],ushort[16],int[8],uint[8],long[4],ulong[4],float[8],double[4]
3696 */
3697TypeVector::TypeVector(Type *basetype)
3698 : Type(Tvector)
3699{
3700 this->basetype = basetype;
3701}
3702
3703TypeVector *TypeVector::create(Loc, Type *basetype)
3704{
3705 return new TypeVector(basetype);
3706}
3707
3708const char *TypeVector::kind()
3709{
3710 return "vector";
3711}
3712
3713Type *TypeVector::syntaxCopy()
3714{
3715 return new TypeVector(basetype->syntaxCopy());
3716}
3717
3718Type *TypeVector::semantic(Loc loc, Scope *sc)
3719{
3720 unsigned int errors = global.errors;
3721 basetype = basetype->semantic(loc, sc);
3722 if (errors != global.errors)
3723 return terror;
3724 basetype = basetype->toBasetype()->mutableOf();
3725 if (basetype->ty != Tsarray)
3726 {
3727 error(loc, "T in __vector(T) must be a static array, not %s", basetype->toChars());
3728 return terror;
3729 }
3730 TypeSArray *t = (TypeSArray *)basetype;
3731 int sz = (int)t->size(loc);
3732 switch (Target::isVectorTypeSupported(sz, t->nextOf()))
3733 {
3734 case 0: // valid
3735 break;
3736 case 1: // no support at all
3737 error(loc, "SIMD vector types not supported on this platform");
3738 return terror;
3739 case 2: // invalid size
3740 error(loc, "%d byte vector type %s is not supported on this platform", sz, toChars());
3741 return terror;
3742 case 3: // invalid base type
3743 error(loc, "vector type %s is not supported on this platform", toChars());
3744 return terror;
3745 default:
3746 assert(0);
3747 }
3748 return merge();
3749}
3750
3751TypeBasic *TypeVector::elementType()
3752{
3753 assert(basetype->ty == Tsarray);
3754 TypeSArray *t = (TypeSArray *)basetype;
3755 TypeBasic *tb = t->nextOf()->isTypeBasic();
3756 assert(tb);
3757 return tb;
3758}
3759
3760bool TypeVector::isBoolean()
3761{
3762 return false;
3763}
3764
3765d_uns64 TypeVector::size(Loc)
3766{
3767 return basetype->size();
3768}
3769
3770unsigned TypeVector::alignsize()
3771{
3772 return (unsigned)basetype->size();
3773}
3774
3775Expression *TypeVector::getProperty(Loc loc, Identifier *ident, int flag)
3776{
3777 return Type::getProperty(loc, ident, flag);
3778}
3779
3780Expression *TypeVector::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
3781{
3782 if (ident == Id::ptr && e->op == TOKcall)
3783 {
3784 /* The trouble with TOKcall is the return ABI for float[4] is different from
3785 * __vector(float[4]), and a type paint won't do.
3786 */
3787 e = new AddrExp(e->loc, e);
3788 e = ::semantic(e, sc);
3789 e = e->castTo(sc, basetype->nextOf()->pointerTo());
3790 return e;
3791 }
3792 if (ident == Id::array)
3793 {
3794 //e = e->castTo(sc, basetype);
3795 // Keep lvalue-ness
3627cdbc 3796 e = new VectorArrayExp(e->loc, e);
3797 e = ::semantic(e, sc);
03385ed3 3798 return e;
3799 }
3800 if (ident == Id::_init || ident == Id::offsetof || ident == Id::stringof || ident == Id::__xalignof)
3801 {
3802 // init should return a new VectorExp (Bugzilla 12776)
3803 // offsetof does not work on a cast expression, so use e directly
3804 // stringof should not add a cast to the output
3805 return Type::dotExp(sc, e, ident, flag);
3806 }
3807 return basetype->dotExp(sc, e->castTo(sc, basetype), ident, flag);
3808}
3809
3810Expression *TypeVector::defaultInit(Loc loc)
3811{
3812 //printf("TypeVector::defaultInit()\n");
3813 assert(basetype->ty == Tsarray);
3814 Expression *e = basetype->defaultInit(loc);
3815 VectorExp *ve = new VectorExp(loc, e, this);
3816 ve->type = this;
3817 ve->dim = (int)(basetype->size(loc) / elementType()->size(loc));
3818 return ve;
3819}
3820
3821Expression *TypeVector::defaultInitLiteral(Loc loc)
3822{
3823 //printf("TypeVector::defaultInitLiteral()\n");
3824 assert(basetype->ty == Tsarray);
3825 Expression *e = basetype->defaultInitLiteral(loc);
3826 VectorExp *ve = new VectorExp(loc, e, this);
3827 ve->type = this;
3828 ve->dim = (int)(basetype->size(loc) / elementType()->size(loc));
3829 return ve;
3830}
3831
3832bool TypeVector::isZeroInit(Loc loc)
3833{
3834 return basetype->isZeroInit(loc);
3835}
3836
3837bool TypeVector::isintegral()
3838{
3839 //printf("TypeVector::isintegral('%s') x%x\n", toChars(), flags);
3840 return basetype->nextOf()->isintegral();
3841}
3842
3843bool TypeVector::isfloating()
3844{
3845 return basetype->nextOf()->isfloating();
3846}
3847
3848bool TypeVector::isunsigned()
3849{
3850 return basetype->nextOf()->isunsigned();
3851}
3852
3853bool TypeVector::isscalar()
3854{
3855 return basetype->nextOf()->isscalar();
3856}
3857
3858MATCH TypeVector::implicitConvTo(Type *to)
3859{
3860 //printf("TypeVector::implicitConvTo(%s) from %s\n", to->toChars(), toChars());
3861 if (this == to)
3862 return MATCHexact;
1710a063 3863#ifdef IN_GCC
03385ed3 3864 if (to->ty == Tvector)
3865 {
3866 TypeVector *tv = (TypeVector *)to;
3867 assert(basetype->ty == Tsarray && tv->basetype->ty == Tsarray);
3868
3869 // Can't convert to a vector which has different size.
3870 if (basetype->size() != tv->basetype->size())
3871 return MATCHnomatch;
3872
3873 // Allow conversion to void[]
3874 if (tv->basetype->nextOf()->ty == Tvoid)
3875 return MATCHconvert;
3876
3877 // Otherwise implicitly convertible only if basetypes are.
3878 return basetype->implicitConvTo(tv->basetype);
3879 }
1710a063 3880#else
3881 if (ty == to->ty)
3882 return MATCHconvert;
3883#endif
03385ed3 3884 return MATCHnomatch;
3885}
3886
3887/***************************** TypeArray *****************************/
3888
3889TypeArray::TypeArray(TY ty, Type *next)
3890 : TypeNext(ty, next)
3891{
3892}
3893
3894Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
3895{
3896 e = Type::dotExp(sc, e, ident, flag);
3897
3898 if (!(flag & 1) || e)
3899 e = ::semantic(e, sc);
3900 return e;
3901}
3902
3903
3904/***************************** TypeSArray *****************************/
3905
3906TypeSArray::TypeSArray(Type *t, Expression *dim)
3907 : TypeArray(Tsarray, t)
3908{
3909 //printf("TypeSArray(%s)\n", dim->toChars());
3910 this->dim = dim;
3911}
3912
3913const char *TypeSArray::kind()
3914{
3915 return "sarray";
3916}
3917
3918Type *TypeSArray::syntaxCopy()
3919{
3920 Type *t = next->syntaxCopy();
3921 Expression *e = dim->syntaxCopy();
3922 t = new TypeSArray(t, e);
3923 t->mod = mod;
3924 return t;
3925}
3926
3927d_uns64 TypeSArray::size(Loc loc)
3928{
3929 //printf("TypeSArray::size()\n");
960d7913 3930 uinteger_t n = numberOfElems(loc);
3931 uinteger_t elemsize = baseElemOf()->size();
3932 bool overflow = false;
3933 uinteger_t sz = mulu(n, elemsize, overflow);
3934 if (overflow || sz >= UINT32_MAX)
03385ed3 3935 {
960d7913 3936 if (elemsize != SIZE_INVALID && n != UINT32_MAX)
3937 error(loc, "static array `%s` size overflowed to %lld", toChars(), (long long)sz);
3938 return SIZE_INVALID;
03385ed3 3939 }
03385ed3 3940 return sz;
03385ed3 3941}
3942
3943unsigned TypeSArray::alignsize()
3944{
3945 return next->alignsize();
3946}
3947
3948/**************************
3949 * This evaluates exp while setting length to be the number
3950 * of elements in the tuple t.
3951 */
3952Expression *semanticLength(Scope *sc, Type *t, Expression *exp)
3953{
3954 if (t->ty == Ttuple)
3955 {
3956 ScopeDsymbol *sym = new ArrayScopeSymbol(sc, (TypeTuple *)t);
3957 sym->parent = sc->scopesym;
3958 sc = sc->push(sym);
3959
3960 sc = sc->startCTFE();
3961 exp = ::semantic(exp, sc);
3962 sc = sc->endCTFE();
3963
3964 sc->pop();
3965 }
3966 else
3967 {
3968 sc = sc->startCTFE();
3969 exp = ::semantic(exp, sc);
3970 sc = sc->endCTFE();
3971 }
3972
3973 return exp;
3974}
3975
3976Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp)
3977{
3978 ScopeDsymbol *sym = new ArrayScopeSymbol(sc, s);
3979 sym->parent = sc->scopesym;
3980 sc = sc->push(sym);
3981
3982 sc = sc->startCTFE();
3983 exp = ::semantic(exp, sc);
3984 sc = sc->endCTFE();
3985
3986 sc->pop();
3987 return exp;
3988}
3989
3990void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
3991{
3992 //printf("TypeSArray::resolve() %s\n", toChars());
3993 next->resolve(loc, sc, pe, pt, ps, intypeid);
3994 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
3995 if (*pe)
3996 {
3997 // It's really an index expression
3998 if (Dsymbol *s = getDsymbol(*pe))
3999 *pe = new DsymbolExp(loc, s);
4000 *pe = new ArrayExp(loc, *pe, dim);
4001 }
4002 else if (*ps)
4003 {
4004 Dsymbol *s = *ps;
4005 TupleDeclaration *td = s->isTupleDeclaration();
4006 if (td)
4007 {
4008 ScopeDsymbol *sym = new ArrayScopeSymbol(sc, td);
4009 sym->parent = sc->scopesym;
4010 sc = sc->push(sym);
4011 sc = sc->startCTFE();
4012 dim = ::semantic(dim, sc);
4013 sc = sc->endCTFE();
4014 sc = sc->pop();
4015
4016 dim = dim->ctfeInterpret();
4017 uinteger_t d = dim->toUInteger();
4018
4019 if (d >= td->objects->dim)
4020 {
4021 error(loc, "tuple index %llu exceeds length %u", d, td->objects->dim);
4022 *ps = NULL;
4023 *pt = Type::terror;
4024 return;
4025 }
4026 RootObject *o = (*td->objects)[(size_t)d];
4027 if (o->dyncast() == DYNCAST_DSYMBOL)
4028 {
4029 *ps = (Dsymbol *)o;
4030 return;
4031 }
4032 if (o->dyncast() == DYNCAST_EXPRESSION)
4033 {
4034 Expression *e = (Expression *)o;
4035 if (e->op == TOKdsymbol)
4036 {
4037 *ps = ((DsymbolExp *)e)->s;
4038 *pe = NULL;
4039 }
4040 else
4041 {
4042 *ps = NULL;
4043 *pe = e;
4044 }
4045 return;
4046 }
4047 if (o->dyncast() == DYNCAST_TYPE)
4048 {
4049 *ps = NULL;
4050 *pt = ((Type *)o)->addMod(this->mod);
4051 return;
4052 }
4053
4054 /* Create a new TupleDeclaration which
4055 * is a slice [d..d+1] out of the old one.
4056 * Do it this way because TemplateInstance::semanticTiargs()
4057 * can handle unresolved Objects this way.
4058 */
4059 Objects *objects = new Objects;
4060 objects->setDim(1);
4061 (*objects)[0] = o;
4062
4063 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
4064 *ps = tds;
4065 }
4066 else
4067 goto Ldefault;
4068 }
4069 else
4070 {
4071 if ((*pt)->ty != Terror)
4072 next = *pt; // prevent re-running semantic() on 'next'
4073 Ldefault:
4074 Type::resolve(loc, sc, pe, pt, ps, intypeid);
4075 }
4076}
4077
4078Type *TypeSArray::semantic(Loc loc, Scope *sc)
4079{
4080 //printf("TypeSArray::semantic() %s\n", toChars());
4081
4082 Type *t;
4083 Expression *e;
4084 Dsymbol *s;
4085 next->resolve(loc, sc, &e, &t, &s);
4086 if (dim && s && s->isTupleDeclaration())
4087 { TupleDeclaration *sd = s->isTupleDeclaration();
4088
4089 dim = semanticLength(sc, sd, dim);
4090 dim = dim->ctfeInterpret();
4091 uinteger_t d = dim->toUInteger();
4092
4093 if (d >= sd->objects->dim)
4094 { error(loc, "tuple index %llu exceeds %u", d, sd->objects->dim);
4095 return Type::terror;
4096 }
4097 RootObject *o = (*sd->objects)[(size_t)d];
4098 if (o->dyncast() != DYNCAST_TYPE)
4099 { error(loc, "%s is not a type", toChars());
4100 return Type::terror;
4101 }
4102 t = ((Type *)o)->addMod(this->mod);
4103 return t;
4104 }
4105
4106 Type *tn = next->semantic(loc, sc);
4107 if (tn->ty == Terror)
4108 return terror;
4109
4110 Type *tbn = tn->toBasetype();
4111
4112 if (dim)
4113 {
4114 unsigned int errors = global.errors;
4115 dim = semanticLength(sc, tbn, dim);
4116 if (errors != global.errors)
4117 goto Lerror;
4118
4119 dim = dim->optimize(WANTvalue);
4120 dim = dim->ctfeInterpret();
4121 if (dim->op == TOKerror)
4122 goto Lerror;
4123 errors = global.errors;
4124 dinteger_t d1 = dim->toInteger();
4125 if (errors != global.errors)
4126 goto Lerror;
4127
4128 dim = dim->implicitCastTo(sc, tsize_t);
4129 dim = dim->optimize(WANTvalue);
4130 if (dim->op == TOKerror)
4131 goto Lerror;
4132 errors = global.errors;
4133 dinteger_t d2 = dim->toInteger();
4134 if (errors != global.errors)
4135 goto Lerror;
4136
4137 if (dim->op == TOKerror)
4138 goto Lerror;
4139
4140 if (d1 != d2)
4141 {
4142 Loverflow:
4143 error(loc, "%s size %llu * %llu exceeds 0x%llx size limit for static array",
4144 toChars(), (unsigned long long)tbn->size(loc), (unsigned long long)d1, Target::maxStaticDataSize);
4145 goto Lerror;
4146 }
4147
4148 Type *tbx = tbn->baseElemOf();
4149 if ((tbx->ty == Tstruct && !((TypeStruct *)tbx)->sym->members) ||
4150 (tbx->ty == Tenum && !((TypeEnum *)tbx)->sym->members))
4151 {
4152 /* To avoid meaningless error message, skip the total size limit check
4153 * when the bottom of element type is opaque.
4154 */
4155 }
29114029 4156 else if (tbn->isTypeBasic() ||
03385ed3 4157 tbn->ty == Tpointer ||
4158 tbn->ty == Tarray ||
4159 tbn->ty == Tsarray ||
4160 tbn->ty == Taarray ||
4161 (tbn->ty == Tstruct && (((TypeStruct *)tbn)->sym->sizeok == SIZEOKdone)) ||
4162 tbn->ty == Tclass)
4163 {
4164 /* Only do this for types that don't need to have semantic()
4165 * run on them for the size, since they may be forward referenced.
4166 */
4167 bool overflow = false;
4168 if (mulu(tbn->size(loc), d2, overflow) >= Target::maxStaticDataSize || overflow)
4169 goto Loverflow;
4170 }
4171 }
4172 switch (tbn->ty)
4173 {
4174 case Ttuple:
4175 { // Index the tuple to get the type
4176 assert(dim);
4177 TypeTuple *tt = (TypeTuple *)tbn;
4178 uinteger_t d = dim->toUInteger();
4179
4180 if (d >= tt->arguments->dim)
4181 { error(loc, "tuple index %llu exceeds %u", d, tt->arguments->dim);
4182 goto Lerror;
4183 }
4184 Type *telem = (*tt->arguments)[(size_t)d]->type;
4185 return telem->addMod(this->mod);
4186 }
4187 case Tfunction:
4188 case Tnone:
4189 error(loc, "can't have array of %s", tbn->toChars());
4190 goto Lerror;
4191 default:
4192 break;
4193 }
4194 if (tbn->isscope())
4195 { error(loc, "cannot have array of scope %s", tbn->toChars());
4196 goto Lerror;
4197 }
4198
4199 /* Ensure things like const(immutable(T)[3]) become immutable(T[3])
4200 * and const(T)[3] become const(T[3])
4201 */
4202 next = tn;
4203 transitive();
4204 t = addMod(tn->mod);
4205
4206 return t->merge();
4207
4208Lerror:
4209 return Type::terror;
4210}
4211
4212Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
4213{
4214 if (ident == Id::length)
4215 {
4216 Loc oldLoc = e->loc;
4217 e = dim->copy();
4218 e->loc = oldLoc;
4219 }
4220 else if (ident == Id::ptr)
4221 {
4222 if (e->op == TOKtype)
4223 {
4224 e->error("%s is not an expression", e->toChars());
4225 return new ErrorExp();
4226 }
4227 else if (!(flag & 2) && sc->func && !sc->intypeof && sc->func->setUnsafe())
4228 {
4229 e->deprecation("%s.ptr cannot be used in @safe code, use &%s[0] instead", e->toChars(), e->toChars());
4230 // return new ErrorExp();
4231 }
4232 e = e->castTo(sc, e->type->nextOf()->pointerTo());
4233 }
4234 else
4235 {
4236 e = TypeArray::dotExp(sc, e, ident, flag);
4237 }
4238 if (!(flag & 1) || e)
4239 e = ::semantic(e, sc);
4240 return e;
4241}
4242
4243structalign_t TypeSArray::alignment()
4244{
4245 return next->alignment();
4246}
4247
4248bool TypeSArray::isString()
4249{
4250 TY nty = next->toBasetype()->ty;
4251 return nty == Tchar || nty == Twchar || nty == Tdchar;
4252}
4253
4254MATCH TypeSArray::constConv(Type *to)
4255{
4256 if (to->ty == Tsarray)
4257 {
4258 TypeSArray *tsa = (TypeSArray *)to;
4259 if (!dim->equals(tsa->dim))
4260 return MATCHnomatch;
4261 }
4262 return TypeNext::constConv(to);
4263}
4264
4265MATCH TypeSArray::implicitConvTo(Type *to)
4266{
4267 //printf("TypeSArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars());
4268
4269 if (to->ty == Tarray)
4270 {
4271 TypeDArray *ta = (TypeDArray *)to;
4272
4273 if (!MODimplicitConv(next->mod, ta->next->mod))
4274 return MATCHnomatch;
4275
4276 /* Allow conversion to void[]
4277 */
4278 if (ta->next->ty == Tvoid)
4279 {
4280 return MATCHconvert;
4281 }
4282
4283 MATCH m = next->constConv(ta->next);
4284 if (m > MATCHnomatch)
4285 {
4286 return MATCHconvert;
4287 }
4288 return MATCHnomatch;
4289 }
4290
4291 if (to->ty == Tsarray)
4292 {
4293 if (this == to)
4294 return MATCHexact;
4295
4296 TypeSArray *tsa = (TypeSArray *)to;
4297
4298 if (dim->equals(tsa->dim))
4299 {
4300 /* Since static arrays are value types, allow
4301 * conversions from const elements to non-const
4302 * ones, just like we allow conversion from const int
4303 * to int.
4304 */
4305 MATCH m = next->implicitConvTo(tsa->next);
4306 if (m >= MATCHconst)
4307 {
4308 if (mod != to->mod)
4309 m = MATCHconst;
4310 return m;
4311 }
4312 }
4313 }
4314 return MATCHnomatch;
4315}
4316
4317Expression *TypeSArray::defaultInit(Loc loc)
4318{
4319 if (next->ty == Tvoid)
4320 return tuns8->defaultInit(loc);
4321 else
4322 return next->defaultInit(loc);
4323}
4324
4325bool TypeSArray::isZeroInit(Loc loc)
4326{
4327 return next->isZeroInit(loc);
4328}
4329
4330bool TypeSArray::needsDestruction()
4331{
4332 return next->needsDestruction();
4333}
4334
4335/*********************************
4336 *
4337 */
4338
4339bool TypeSArray::needsNested()
4340{
4341 return next->needsNested();
4342}
4343
4344Expression *TypeSArray::defaultInitLiteral(Loc loc)
4345{
4346 size_t d = (size_t)dim->toInteger();
4347 Expression *elementinit;
4348 if (next->ty == Tvoid)
4349 elementinit = tuns8->defaultInitLiteral(loc);
4350 else
4351 elementinit = next->defaultInitLiteral(loc);
4352 Expressions *elements = new Expressions();
4353 elements->setDim(d);
4354 for (size_t i = 0; i < d; i++)
4355 (*elements)[i] = NULL;
d2aef8c0 4356 ArrayLiteralExp *ae = new ArrayLiteralExp(Loc(), this, elementinit, elements);
03385ed3 4357 return ae;
4358}
4359
4360bool TypeSArray::hasPointers()
4361{
4362 /* Don't want to do this, because:
4363 * struct S { T* array[0]; }
4364 * may be a variable length struct.
4365 */
4366 //if (dim->toInteger() == 0)
4367 // return false;
4368
4369 if (next->ty == Tvoid)
4370 {
4371 // Arrays of void contain arbitrary data, which may include pointers
4372 return true;
4373 }
4374 else
4375 return next->hasPointers();
4376}
4377
4378/***************************** TypeDArray *****************************/
4379
4380TypeDArray::TypeDArray(Type *t)
4381 : TypeArray(Tarray, t)
4382{
4383 //printf("TypeDArray(t = %p)\n", t);
4384}
4385
4386const char *TypeDArray::kind()
4387{
4388 return "darray";
4389}
4390
4391Type *TypeDArray::syntaxCopy()
4392{
4393 Type *t = next->syntaxCopy();
4394 if (t == next)
4395 t = this;
4396 else
4397 {
4398 t = new TypeDArray(t);
4399 t->mod = mod;
4400 }
4401 return t;
4402}
4403
4404d_uns64 TypeDArray::size(Loc)
4405{
4406 //printf("TypeDArray::size()\n");
4407 return Target::ptrsize * 2;
4408}
4409
4410unsigned TypeDArray::alignsize()
4411{
4412 // A DArray consists of two ptr-sized values, so align it on pointer size
4413 // boundary
4414 return Target::ptrsize;
4415}
4416
4417Type *TypeDArray::semantic(Loc loc, Scope *sc)
4418{
4419 Type *tn = next->semantic(loc,sc);
4420 Type *tbn = tn->toBasetype();
4421 switch (tbn->ty)
4422 {
4423 case Ttuple:
4424 return tbn;
4425 case Tfunction:
4426 case Tnone:
4427 error(loc, "can't have array of %s", tbn->toChars());
4428 return Type::terror;
4429 case Terror:
4430 return Type::terror;
4431 default:
4432 break;
4433 }
4434 if (tn->isscope())
4435 { error(loc, "cannot have array of scope %s", tn->toChars());
4436 return Type::terror;
4437 }
4438 next = tn;
4439 transitive();
4440 return merge();
4441}
4442
4443void TypeDArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
4444{
4445 //printf("TypeDArray::resolve() %s\n", toChars());
4446 next->resolve(loc, sc, pe, pt, ps, intypeid);
4447 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
4448 if (*pe)
4449 {
4450 // It's really a slice expression
4451 if (Dsymbol *s = getDsymbol(*pe))
4452 *pe = new DsymbolExp(loc, s);
4453 *pe = new ArrayExp(loc, *pe);
4454 }
4455 else if (*ps)
4456 {
4457 TupleDeclaration *td = (*ps)->isTupleDeclaration();
4458 if (td)
4459 ; // keep *ps
4460 else
4461 goto Ldefault;
4462 }
4463 else
4464 {
4465 if ((*pt)->ty != Terror)
4466 next = *pt; // prevent re-running semantic() on 'next'
4467 Ldefault:
4468 Type::resolve(loc, sc, pe, pt, ps, intypeid);
4469 }
4470}
4471
4472Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
4473{
4474 if (e->op == TOKtype &&
4475 (ident == Id::length || ident == Id::ptr))
4476 {
4477 e->error("%s is not an expression", e->toChars());
4478 return new ErrorExp();
4479 }
4480 if (ident == Id::length)
4481 {
4482 if (e->op == TOKstring)
4483 {
4484 StringExp *se = (StringExp *)e;
4485 return new IntegerExp(se->loc, se->len, Type::tsize_t);
4486 }
4487 if (e->op == TOKnull)
4488 return new IntegerExp(e->loc, 0, Type::tsize_t);
89331863 4489 if (checkNonAssignmentArrayOp(e))
4490 return new ErrorExp();
03385ed3 4491 e = new ArrayLengthExp(e->loc, e);
4492 e->type = Type::tsize_t;
4493 return e;
4494 }
4495 else if (ident == Id::ptr)
4496 {
4497 if (!(flag & 2) && sc->func && !sc->intypeof && sc->func->setUnsafe())
4498 {
4499 e->deprecation("%s.ptr cannot be used in @safe code, use &%s[0] instead", e->toChars(), e->toChars());
4500 // return new ErrorExp();
4501 }
4502 e = e->castTo(sc, next->pointerTo());
4503 return e;
4504 }
4505 else
4506 {
4507 e = TypeArray::dotExp(sc, e, ident, flag);
4508 }
4509 return e;
4510}
4511
4512bool TypeDArray::isString()
4513{
4514 TY nty = next->toBasetype()->ty;
4515 return nty == Tchar || nty == Twchar || nty == Tdchar;
4516}
4517
4518MATCH TypeDArray::implicitConvTo(Type *to)
4519{
4520 //printf("TypeDArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars());
4521 if (equals(to))
4522 return MATCHexact;
4523
4524 if (to->ty == Tarray)
4525 {
4526 TypeDArray *ta = (TypeDArray *)to;
4527
4528 if (!MODimplicitConv(next->mod, ta->next->mod))
4529 return MATCHnomatch; // not const-compatible
4530
4531 /* Allow conversion to void[]
4532 */
4533 if (next->ty != Tvoid && ta->next->ty == Tvoid)
4534 {
4535 return MATCHconvert;
4536 }
4537
4538 MATCH m = next->constConv(ta->next);
4539 if (m > MATCHnomatch)
4540 {
4541 if (m == MATCHexact && mod != to->mod)
4542 m = MATCHconst;
4543 return m;
4544 }
4545 }
4546 return Type::implicitConvTo(to);
4547}
4548
4549Expression *TypeDArray::defaultInit(Loc loc)
4550{
4551 return new NullExp(loc, this);
4552}
4553
4554bool TypeDArray::isZeroInit(Loc)
4555{
4556 return true;
4557}
4558
4559bool TypeDArray::isBoolean()
4560{
4561 return true;
4562}
4563
4564bool TypeDArray::hasPointers()
4565{
4566 return true;
4567}
4568
4569
4570/***************************** TypeAArray *****************************/
4571
4572TypeAArray::TypeAArray(Type *t, Type *index)
4573 : TypeArray(Taarray, t)
4574{
4575 this->index = index;
4576 this->loc = Loc();
4577 this->sc = NULL;
4578}
4579
4580TypeAArray *TypeAArray::create(Type *t, Type *index)
4581{
4582 return new TypeAArray(t, index);
4583}
4584
4585const char *TypeAArray::kind()
4586{
4587 return "aarray";
4588}
4589
4590Type *TypeAArray::syntaxCopy()
4591{
4592 Type *t = next->syntaxCopy();
4593 Type *ti = index->syntaxCopy();
4594 if (t == next && ti == index)
4595 t = this;
4596 else
4597 {
4598 t = new TypeAArray(t, ti);
4599 t->mod = mod;
4600 }
4601 return t;
4602}
4603
4604d_uns64 TypeAArray::size(Loc)
4605{
4606 return Target::ptrsize;
4607}
4608
4609Type *TypeAArray::semantic(Loc loc, Scope *sc)
4610{
4611 //printf("TypeAArray::semantic() %s index->ty = %d\n", toChars(), index->ty);
4612 if (deco)
4613 return this;
4614
4615 this->loc = loc;
4616 this->sc = sc;
4617 if (sc)
4618 sc->setNoFree();
4619
4620 // Deal with the case where we thought the index was a type, but
4621 // in reality it was an expression.
4622 if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray ||
4623 index->ty == Ttypeof || index->ty == Treturn)
4624 {
4625 Expression *e;
4626 Type *t;
4627 Dsymbol *s;
4628
4629 index->resolve(loc, sc, &e, &t, &s);
4630 if (e)
4631 {
4632 // It was an expression -
4633 // Rewrite as a static array
4634 TypeSArray *tsa = new TypeSArray(next, e);
4635 return tsa->semantic(loc, sc);
4636 }
4637 else if (t)
4638 index = t->semantic(loc, sc);
4639 else
4640 {
4641 index->error(loc, "index is not a type or an expression");
4642 return Type::terror;
4643 }
4644 }
4645 else
4646 index = index->semantic(loc,sc);
4647 index = index->merge2();
4648
4649 if (index->nextOf() && !index->nextOf()->isImmutable())
4650 {
4651 index = index->constOf()->mutableOf();
4652 }
4653
4654 switch (index->toBasetype()->ty)
4655 {
4656 case Tfunction:
4657 case Tvoid:
4658 case Tnone:
4659 case Ttuple:
4660 error(loc, "can't have associative array key of %s", index->toBasetype()->toChars());
4661 /* fall through */
4662 case Terror:
4663 return Type::terror;
4664 default:
4665 break;
4666 }
4667 Type *tbase = index->baseElemOf();
4668 while (tbase->ty == Tarray)
4669 tbase = tbase->nextOf()->baseElemOf();
4670 if (tbase->ty == Tstruct)
4671 {
4672 /* AA's need typeid(index).equals() and getHash(). Issue error if not correctly set up.
4673 */
4674 StructDeclaration *sd = ((TypeStruct *)tbase)->sym;
081f759d 4675 if (sd->semanticRun < PASSsemanticdone)
03385ed3 4676 sd->semantic(NULL);
4677
4678 // duplicate a part of StructDeclaration::semanticTypeInfoMembers
4679 //printf("AA = %s, key: xeq = %p, xerreq = %p xhash = %p\n", toChars(), sd->xeq, sd->xerreq, sd->xhash);
4680 if (sd->xeq &&
4681 sd->xeq->_scope &&
4682 sd->xeq->semanticRun < PASSsemantic3done)
4683 {
4684 unsigned errors = global.startGagging();
4685 sd->xeq->semantic3(sd->xeq->_scope);
4686 if (global.endGagging(errors))
4687 sd->xeq = sd->xerreq;
4688 }
4689
4690 const char *s = (index->toBasetype()->ty != Tstruct) ? "bottom of " : "";
4691 if (!sd->xeq)
4692 {
4693 // If sd->xhash != NULL:
4694 // sd or its fields have user-defined toHash.
4695 // AA assumes that its result is consistent with bitwise equality.
4696 // else:
4697 // bitwise equality & hashing
4698 }
4699 else if (sd->xeq == sd->xerreq)
4700 {
4701 if (search_function(sd, Id::eq))
4702 {
4703 error(loc, "%sAA key type %s does not have 'bool opEquals(ref const %s) const'",
4704 s, sd->toChars(), sd->toChars());
4705 }
4706 else
4707 {
4708 error(loc, "%sAA key type %s does not support const equality",
4709 s, sd->toChars());
4710 }
4711 return Type::terror;
4712 }
4713 else if (!sd->xhash)
4714 {
4715 if (search_function(sd, Id::eq))
4716 {
4717 error(loc, "%sAA key type %s should have 'size_t toHash() const nothrow @safe' if opEquals defined",
4718 s, sd->toChars());
4719 }
4720 else
4721 {
4722 error(loc, "%sAA key type %s supports const equality but doesn't support const hashing",
4723 s, sd->toChars());
4724 }
4725 return Type::terror;
4726 }
4727 else
4728 {
4729 // defined equality & hashing
4730 assert(sd->xeq && sd->xhash);
4731
4732 /* xeq and xhash may be implicitly defined by compiler. For example:
4733 * struct S { int[] arr; }
4734 * With 'arr' field equality and hashing, compiler will implicitly
4735 * generate functions for xopEquals and xtoHash in TypeInfo_Struct.
4736 */
4737 }
4738 }
4739 else if (tbase->ty == Tclass && !((TypeClass *)tbase)->sym->isInterfaceDeclaration())
4740 {
4741 ClassDeclaration *cd = ((TypeClass *)tbase)->sym;
081f759d 4742 if (cd->semanticRun < PASSsemanticdone)
03385ed3 4743 cd->semantic(NULL);
4744
4745 if (!ClassDeclaration::object)
4746 {
4747 error(Loc(), "missing or corrupt object.d");
4748 fatal();
4749 }
4750
4751 static FuncDeclaration *feq = NULL;
4752 static FuncDeclaration *fcmp = NULL;
4753 static FuncDeclaration *fhash = NULL;
4754 if (!feq) feq = search_function(ClassDeclaration::object, Id::eq)->isFuncDeclaration();
4755 if (!fcmp) fcmp = search_function(ClassDeclaration::object, Id::cmp)->isFuncDeclaration();
4756 if (!fhash) fhash = search_function(ClassDeclaration::object, Id::tohash)->isFuncDeclaration();
4757 assert(fcmp && feq && fhash);
4758
4759 if (feq->vtblIndex < (int)cd->vtbl.dim && cd->vtbl[feq ->vtblIndex] == feq)
4760 {
4761 if (fcmp->vtblIndex < (int)cd->vtbl.dim && cd->vtbl[fcmp->vtblIndex] != fcmp)
4762 {
4763 const char *s = (index->toBasetype()->ty != Tclass) ? "bottom of " : "";
4764 error(loc, "%sAA key type %s now requires equality rather than comparison",
4765 s, cd->toChars());
4766 errorSupplemental(loc, "Please override Object.opEquals and toHash.");
4767 }
4768 }
4769 }
4770 next = next->semantic(loc,sc)->merge2();
4771 transitive();
4772
4773 switch (next->toBasetype()->ty)
4774 {
4775 case Tfunction:
4776 case Tvoid:
4777 case Tnone:
4778 case Ttuple:
4779 error(loc, "can't have associative array of %s", next->toChars());
4780 /* fall through */
4781 case Terror:
4782 return Type::terror;
4783 }
4784 if (next->isscope())
4785 { error(loc, "cannot have array of scope %s", next->toChars());
4786 return Type::terror;
4787 }
4788 return merge();
4789}
4790
4791void TypeAArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
4792{
4793 //printf("TypeAArray::resolve() %s\n", toChars());
4794
4795 // Deal with the case where we thought the index was a type, but
4796 // in reality it was an expression.
4797 if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray)
4798 {
4799 Expression *e;
4800 Type *t;
4801 Dsymbol *s;
4802
4803 index->resolve(loc, sc, &e, &t, &s, intypeid);
4804 if (e)
4805 {
4806 // It was an expression -
4807 // Rewrite as a static array
4808 TypeSArray *tsa = new TypeSArray(next, e);
4809 tsa->mod = this->mod; // just copy mod field so tsa's semantic is not yet done
4810 return tsa->resolve(loc, sc, pe, pt, ps, intypeid);
4811 }
4812 else if (t)
4813 index = t;
4814 else
4815 index->error(loc, "index is not a type or an expression");
4816 }
4817 Type::resolve(loc, sc, pe, pt, ps, intypeid);
4818}
4819
4820
4821Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
4822{
4823 if (ident == Id::length)
4824 {
4825 static FuncDeclaration *fd_aaLen = NULL;
4826 if (fd_aaLen == NULL)
4827 {
4828 Parameters *fparams = new Parameters();
4829 fparams->push(new Parameter(STCin, this, NULL, NULL));
4830 fd_aaLen = FuncDeclaration::genCfunc(fparams, Type::tsize_t, Id::aaLen);
2feebf42 4831 TypeFunction *tf = fd_aaLen->type->toTypeFunction();
03385ed3 4832 tf->purity = PUREconst;
4833 tf->isnothrow = true;
4834 tf->isnogc = false;
4835 }
4836 Expression *ev = new VarExp(e->loc, fd_aaLen, false);
4837 e = new CallExp(e->loc, ev, e);
2feebf42 4838 e->type = fd_aaLen->type->toTypeFunction()->next;
03385ed3 4839 }
4840 else
4841 e = Type::dotExp(sc, e, ident, flag);
4842 return e;
4843}
4844
4845Expression *TypeAArray::defaultInit(Loc loc)
4846{
4847 return new NullExp(loc, this);
4848}
4849
4850bool TypeAArray::isZeroInit(Loc)
4851{
4852 return true;
4853}
4854
4855bool TypeAArray::isBoolean()
4856{
4857 return true;
4858}
4859
4860bool TypeAArray::hasPointers()
4861{
4862 return true;
4863}
4864
4865MATCH TypeAArray::implicitConvTo(Type *to)
4866{
4867 //printf("TypeAArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars());
4868 if (equals(to))
4869 return MATCHexact;
4870
4871 if (to->ty == Taarray)
4872 { TypeAArray *ta = (TypeAArray *)to;
4873
4874 if (!MODimplicitConv(next->mod, ta->next->mod))
4875 return MATCHnomatch; // not const-compatible
4876
4877 if (!MODimplicitConv(index->mod, ta->index->mod))
4878 return MATCHnomatch; // not const-compatible
4879
4880 MATCH m = next->constConv(ta->next);
4881 MATCH mi = index->constConv(ta->index);
4882 if (m > MATCHnomatch && mi > MATCHnomatch)
4883 {
4884 return MODimplicitConv(mod, to->mod) ? MATCHconst : MATCHnomatch;
4885 }
4886 }
4887 return Type::implicitConvTo(to);
4888}
4889
4890MATCH TypeAArray::constConv(Type *to)
4891{
4892 if (to->ty == Taarray)
4893 {
4894 TypeAArray *taa = (TypeAArray *)to;
4895 MATCH mindex = index->constConv(taa->index);
4896 MATCH mkey = next->constConv(taa->next);
4897 // Pick the worst match
4898 return mkey < mindex ? mkey : mindex;
4899 }
4900 return Type::constConv(to);
4901}
4902
4903/***************************** TypePointer *****************************/
4904
4905TypePointer::TypePointer(Type *t)
4906 : TypeNext(Tpointer, t)
4907{
4908}
4909
4910TypePointer *TypePointer::create(Type *t)
4911{
4912 return new TypePointer(t);
4913}
4914
4915const char *TypePointer::kind()
4916{
4917 return "pointer";
4918}
4919
4920Type *TypePointer::syntaxCopy()
4921{
4922 Type *t = next->syntaxCopy();
4923 if (t == next)
4924 t = this;
4925 else
4926 {
4927 t = new TypePointer(t);
4928 t->mod = mod;
4929 }
4930 return t;
4931}
4932
4933Type *TypePointer::semantic(Loc loc, Scope *sc)
4934{
4935 //printf("TypePointer::semantic() %s\n", toChars());
4936 if (deco)
4937 return this;
4938 Type *n = next->semantic(loc, sc);
4939 switch (n->toBasetype()->ty)
4940 {
4941 case Ttuple:
4942 error(loc, "can't have pointer to %s", n->toChars());
4943 /* fall through */
4944 case Terror:
4945 return Type::terror;
4946 default:
4947 break;
4948 }
4949 if (n != next)
4950 {
4951 deco = NULL;
4952 }
4953 next = n;
4954 if (next->ty != Tfunction)
4955 { transitive();
4956 return merge();
4957 }
4958 deco = merge()->deco;
4959 /* Don't return merge(), because arg identifiers and default args
4960 * can be different
4961 * even though the types match
4962 */
4963 return this;
4964}
4965
4966
4967d_uns64 TypePointer::size(Loc)
4968{
4969 return Target::ptrsize;
4970}
4971
4972MATCH TypePointer::implicitConvTo(Type *to)
4973{
4974 //printf("TypePointer::implicitConvTo(to = %s) %s\n", to->toChars(), toChars());
4975
4976 if (equals(to))
4977 return MATCHexact;
4978 if (next->ty == Tfunction)
4979 {
4980 if (to->ty == Tpointer)
4981 {
4982 TypePointer *tp = (TypePointer *)to;
4983 if (tp->next->ty == Tfunction)
4984 {
4985 if (next->equals(tp->next))
4986 return MATCHconst;
4987
4988 if (next->covariant(tp->next) == 1)
4989 {
4990 Type *tret = this->next->nextOf();
4991 Type *toret = tp->next->nextOf();
4992 if (tret->ty == Tclass && toret->ty == Tclass)
4993 {
4994 /* Bugzilla 10219: Check covariant interface return with offset tweaking.
4995 * interface I {}
4996 * class C : Object, I {}
4997 * I function() dg = function C() {} // should be error
4998 */
4999 int offset = 0;
5000 if (toret->isBaseOf(tret, &offset) && offset != 0)
5001 return MATCHnomatch;
5002 }
5003 return MATCHconvert;
5004 }
5005 }
5006 else if (tp->next->ty == Tvoid)
5007 {
5008 // Allow conversions to void*
5009 return MATCHconvert;
5010 }
5011 }
5012 return MATCHnomatch;
5013 }
5014 else if (to->ty == Tpointer)
5015 {
5016 TypePointer *tp = (TypePointer *)to;
5017 assert(tp->next);
5018
5019 if (!MODimplicitConv(next->mod, tp->next->mod))
5020 return MATCHnomatch; // not const-compatible
5021
5022 /* Alloc conversion to void*
5023 */
5024 if (next->ty != Tvoid && tp->next->ty == Tvoid)
5025 {
5026 return MATCHconvert;
5027 }
5028
5029 MATCH m = next->constConv(tp->next);
5030 if (m > MATCHnomatch)
5031 {
5032 if (m == MATCHexact && mod != to->mod)
5033 m = MATCHconst;
5034 return m;
5035 }
5036 }
5037 return MATCHnomatch;
5038}
5039
5040MATCH TypePointer::constConv(Type *to)
5041{
5042 if (next->ty == Tfunction)
5043 {
5044 if (to->nextOf() && next->equals(((TypeNext *)to)->next))
5045 return Type::constConv(to);
5046 else
5047 return MATCHnomatch;
5048 }
5049 return TypeNext::constConv(to);
5050}
5051
5052bool TypePointer::isscalar()
5053{
5054 return true;
5055}
5056
5057Expression *TypePointer::defaultInit(Loc loc)
5058{
5059 return new NullExp(loc, this);
5060}
5061
5062bool TypePointer::isZeroInit(Loc)
5063{
5064 return true;
5065}
5066
5067bool TypePointer::hasPointers()
5068{
5069 return true;
5070}
5071
5072
5073/***************************** TypeReference *****************************/
5074
5075TypeReference::TypeReference(Type *t)
5076 : TypeNext(Treference, t)
5077{
5078 // BUG: what about references to static arrays?
5079}
5080
5081const char *TypeReference::kind()
5082{
5083 return "reference";
5084}
5085
5086Type *TypeReference::syntaxCopy()
5087{
5088 Type *t = next->syntaxCopy();
5089 if (t == next)
5090 t = this;
5091 else
5092 {
5093 t = new TypeReference(t);
5094 t->mod = mod;
5095 }
5096 return t;
5097}
5098
5099Type *TypeReference::semantic(Loc loc, Scope *sc)
5100{
5101 //printf("TypeReference::semantic()\n");
5102 Type *n = next->semantic(loc, sc);
5103 if (n != next)
5104 deco = NULL;
5105 next = n;
5106 transitive();
5107 return merge();
5108}
5109
5110
5111d_uns64 TypeReference::size(Loc)
5112{
5113 return Target::ptrsize;
5114}
5115
5116Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
5117{
5118 // References just forward things along
5119 return next->dotExp(sc, e, ident, flag);
5120}
5121
5122Expression *TypeReference::defaultInit(Loc loc)
5123{
5124 return new NullExp(loc, this);
5125}
5126
5127bool TypeReference::isZeroInit(Loc)
5128{
5129 return true;
5130}
5131
5132
5133/***************************** TypeFunction *****************************/
5134
5135TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, LINK linkage, StorageClass stc)
5136 : TypeNext(Tfunction, treturn)
5137{
5138//if (!treturn) *(char*)0=0;
5139// assert(treturn);
5140 assert(0 <= varargs && varargs <= 2);
5141 this->parameters = parameters;
5142 this->varargs = varargs;
5143 this->linkage = linkage;
5144 this->inuse = 0;
5145 this->isnothrow = false;
5146 this->isnogc = false;
5147 this->purity = PUREimpure;
5148 this->isproperty = false;
5149 this->isref = false;
5150 this->isreturn = false;
5151 this->isscope = false;
5152 this->isscopeinferred = false;
5153 this->iswild = 0;
5154 this->fargs = NULL;
5155
5156 if (stc & STCpure)
5157 this->purity = PUREfwdref;
5158 if (stc & STCnothrow)
5159 this->isnothrow = true;
5160 if (stc & STCnogc)
5161 this->isnogc = true;
5162 if (stc & STCproperty)
5163 this->isproperty = true;
5164
5165 if (stc & STCref)
5166 this->isref = true;
5167 if (stc & STCreturn)
5168 this->isreturn = true;
5169 if (stc & STCscope)
5170 this->isscope = true;
5171 if (stc & STCscopeinferred)
5172 this->isscopeinferred = true;
5173
5174 this->trust = TRUSTdefault;
5175 if (stc & STCsafe)
5176 this->trust = TRUSTsafe;
5177 if (stc & STCsystem)
5178 this->trust = TRUSTsystem;
5179 if (stc & STCtrusted)
5180 this->trust = TRUSTtrusted;
5181}
5182
5183TypeFunction *TypeFunction::create(Parameters *parameters, Type *treturn, int varargs, LINK linkage, StorageClass stc)
5184{
5185 return new TypeFunction(parameters, treturn, varargs, linkage, stc);
5186}
5187
5188const char *TypeFunction::kind()
5189{
5190 return "function";
5191}
5192
5193Type *TypeFunction::syntaxCopy()
5194{
5195 Type *treturn = next ? next->syntaxCopy() : NULL;
5196 Parameters *params = Parameter::arraySyntaxCopy(parameters);
5197 TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage);
5198 t->mod = mod;
5199 t->isnothrow = isnothrow;
5200 t->isnogc = isnogc;
5201 t->purity = purity;
5202 t->isproperty = isproperty;
5203 t->isref = isref;
5204 t->isreturn = isreturn;
5205 t->isscope = isscope;
5206 t->isscopeinferred = isscopeinferred;
5207 t->iswild = iswild;
5208 t->trust = trust;
5209 t->fargs = fargs;
5210 return t;
5211}
5212
5213/*******************************
5214 * Covariant means that 'this' can substitute for 't',
5215 * i.e. a pure function is a match for an impure type.
5216 * Params:
5217 * t = type 'this' is covariant with
5218 * pstc = if not null, store STCxxxx which would make it covariant
5219 * fix17349 = enable fix https://issues.dlang.org/show_bug.cgi?id=17349
5220 * Returns:
5221 * 0 types are distinct
5222 * 1 this is covariant with t
5223 * 2 arguments match as far as overloading goes,
5224 * but types are not covariant
5225 * 3 cannot determine covariance because of forward references
5226 * *pstc STCxxxx which would make it covariant
5227 */
5228
5229int Type::covariant(Type *t, StorageClass *pstc, bool fix17349)
5230{
5231 if (pstc)
5232 *pstc = 0;
5233 StorageClass stc = 0;
5234
5235 bool notcovariant = false;
5236
5237 TypeFunction *t1;
5238 TypeFunction *t2;
5239
5240 if (equals(t))
5241 return 1; // covariant
5242
5243 if (ty != Tfunction || t->ty != Tfunction)
5244 goto Ldistinct;
5245
5246 t1 = (TypeFunction *)this;
5247 t2 = (TypeFunction *)t;
5248
5249 if (t1->varargs != t2->varargs)
5250 goto Ldistinct;
5251
5252 if (t1->parameters && t2->parameters)
5253 {
5254 size_t dim = Parameter::dim(t1->parameters);
5255 if (dim != Parameter::dim(t2->parameters))
5256 goto Ldistinct;
5257
5258 for (size_t i = 0; i < dim; i++)
5259 {
5260 Parameter *fparam1 = Parameter::getNth(t1->parameters, i);
5261 Parameter *fparam2 = Parameter::getNth(t2->parameters, i);
5262
5263 if (!fparam1->type->equals(fparam2->type))
5264 {
5265 if (!fix17349)
5266 goto Ldistinct;
5267 Type *tp1 = fparam1->type;
5268 Type *tp2 = fparam2->type;
5269 if (tp1->ty == tp2->ty)
5270 {
5271 if (tp1->ty == Tclass)
5272 {
5273 if (((TypeClass *)tp1)->sym == ((TypeClass *)tp2)->sym && MODimplicitConv(tp2->mod, tp1->mod))
5274 goto Lcov;
5275 }
5276 else if (tp1->ty == Tstruct)
5277 {
5278 if (((TypeStruct *)tp1)->sym == ((TypeStruct *)tp2)->sym && MODimplicitConv(tp2->mod, tp1->mod))
5279 goto Lcov;
5280 }
5281 else if (tp1->ty == Tpointer)
5282 {
5283 if (tp2->implicitConvTo(tp1))
5284 goto Lcov;
5285 }
5286 else if (tp1->ty == Tarray)
5287 {
5288 if (tp2->implicitConvTo(tp1))
5289 goto Lcov;
5290 }
5291 else if (tp1->ty == Tdelegate)
5292 {
5293 if (tp1->implicitConvTo(tp2))
5294 goto Lcov;
5295 }
5296 }
5297 goto Ldistinct;
5298 }
5299 Lcov:
5300 notcovariant |= !fparam1->isCovariant(t1->isref, fparam2);
5301 }
5302 }
5303 else if (t1->parameters != t2->parameters)
5304 {
5305 size_t dim1 = !t1->parameters ? 0 : t1->parameters->dim;
5306 size_t dim2 = !t2->parameters ? 0 : t2->parameters->dim;
5307 if (dim1 || dim2)
5308 goto Ldistinct;
5309 }
5310
5311 // The argument lists match
5312 if (notcovariant)
5313 goto Lnotcovariant;
5314 if (t1->linkage != t2->linkage)
5315 goto Lnotcovariant;
5316
5317 {
5318 // Return types
5319 Type *t1n = t1->next;
5320 Type *t2n = t2->next;
5321
5322 if (!t1n || !t2n) // happens with return type inference
5323 goto Lnotcovariant;
5324
5325 if (t1n->equals(t2n))
5326 goto Lcovariant;
5327 if (t1n->ty == Tclass && t2n->ty == Tclass)
5328 {
5329 /* If same class type, but t2n is const, then it's
5330 * covariant. Do this test first because it can work on
5331 * forward references.
5332 */
5333 if (((TypeClass *)t1n)->sym == ((TypeClass *)t2n)->sym &&
5334 MODimplicitConv(t1n->mod, t2n->mod))
5335 goto Lcovariant;
5336
5337 // If t1n is forward referenced:
5338 ClassDeclaration *cd = ((TypeClass *)t1n)->sym;
081f759d 5339 if (cd->semanticRun < PASSsemanticdone && !cd->isBaseInfoComplete())
03385ed3 5340 cd->semantic(NULL);
5341 if (!cd->isBaseInfoComplete())
5342 {
5343 return 3; // forward references
5344 }
5345 }
5346 if (t1n->ty == Tstruct && t2n->ty == Tstruct)
5347 {
5348 if (((TypeStruct *)t1n)->sym == ((TypeStruct *)t2n)->sym &&
5349 MODimplicitConv(t1n->mod, t2n->mod))
5350 goto Lcovariant;
5351 }
5352 else if (t1n->ty == t2n->ty && t1n->implicitConvTo(t2n))
5353 goto Lcovariant;
0bdb86c9 5354 else if (t1n->ty == Tnull)
5355 {
5356 // NULL is covariant with any pointer type, but not with any
5357 // dynamic arrays, associative arrays or delegates.
5358 // https://issues.dlang.org/show_bug.cgi?id=8589
5359 // https://issues.dlang.org/show_bug.cgi?id=19618
5360 Type *t2bn = t2n->toBasetype();
5361 if (t2bn->ty == Tnull || t2bn->ty == Tpointer || t2bn->ty == Tclass)
5362 goto Lcovariant;
5363 }
03385ed3 5364 }
5365 goto Lnotcovariant;
5366
5367Lcovariant:
5368 if (t1->isref != t2->isref)
5369 goto Lnotcovariant;
5370
5371 if (!t1->isref && (t1->isscope || t2->isscope))
5372 {
5373 StorageClass stc1 = t1->isscope ? STCscope : 0;
5374 StorageClass stc2 = t2->isscope ? STCscope : 0;
5375 if (t1->isreturn)
5376 {
5377 stc1 |= STCreturn;
5378 if (!t1->isscope)
5379 stc1 |= STCref;
5380 }
5381 if (t2->isreturn)
5382 {
5383 stc2 |= STCreturn;
5384 if (!t2->isscope)
5385 stc2 |= STCref;
5386 }
5387 if (!Parameter::isCovariantScope(t1->isref, stc1, stc2))
5388 goto Lnotcovariant;
5389 }
5390
5391 // We can subtract 'return ref' from 'this', but cannot add it
5392 else if (t1->isreturn && !t2->isreturn)
5393 goto Lnotcovariant;
5394
5395 /* Can convert mutable to const
5396 */
5397 if (!MODimplicitConv(t2->mod, t1->mod))
5398 {
5399 goto Ldistinct;
5400 }
5401
5402 /* Can convert pure to impure, nothrow to throw, and nogc to gc
5403 */
5404 if (!t1->purity && t2->purity)
5405 stc |= STCpure;
5406
5407 if (!t1->isnothrow && t2->isnothrow)
5408 stc |= STCnothrow;
5409
5410 if (!t1->isnogc && t2->isnogc)
5411 stc |= STCnogc;
5412
5413 /* Can convert safe/trusted to system
5414 */
5415 if (t1->trust <= TRUSTsystem && t2->trust >= TRUSTtrusted)
5416 {
5417 // Should we infer trusted or safe? Go with safe.
5418 stc |= STCsafe;
5419 }
5420
5421 if (stc)
5422 { if (pstc)
5423 *pstc = stc;
5424 goto Lnotcovariant;
5425 }
5426
5427 //printf("\tcovaraint: 1\n");
5428 return 1;
5429
5430Ldistinct:
5431 //printf("\tcovaraint: 0\n");
5432 return 0;
5433
5434Lnotcovariant:
5435 //printf("\tcovaraint: 2\n");
5436 return 2;
5437}
5438
5439Type *TypeFunction::semantic(Loc loc, Scope *sc)
5440{
5441 if (deco) // if semantic() already run
5442 {
5443 //printf("already done\n");
5444 return this;
5445 }
5446 //printf("TypeFunction::semantic() this = %p\n", this);
5447 //printf("TypeFunction::semantic() %s, sc->stc = %llx, fargs = %p\n", toChars(), sc->stc, fargs);
5448
5449 bool errors = false;
5450
081f759d 5451 if (inuse > 500)
5452 {
5453 inuse = 0;
5454 ::error(loc, "recursive type");
5455 return Type::terror;
5456 }
5457
03385ed3 5458 /* Copy in order to not mess up original.
5459 * This can produce redundant copies if inferring return type,
5460 * as semantic() will get called again on this.
5461 */
2feebf42 5462 TypeFunction *tf = copy()->toTypeFunction();
03385ed3 5463 if (parameters)
5464 {
5465 tf->parameters = parameters->copy();
5466 for (size_t i = 0; i < parameters->dim; i++)
5467 {
5468 void *pp = mem.xmalloc(sizeof(Parameter));
5469 Parameter *p = (Parameter *)memcpy(pp, (void *)(*parameters)[i], sizeof(Parameter));
5470 (*tf->parameters)[i] = p;
5471 }
5472 }
5473
5474 if (sc->stc & STCpure)
5475 tf->purity = PUREfwdref;
5476 if (sc->stc & STCnothrow)
5477 tf->isnothrow = true;
5478 if (sc->stc & STCnogc)
5479 tf->isnogc = true;
5480 if (sc->stc & STCref)
5481 tf->isref = true;
5482 if (sc->stc & STCreturn)
5483 tf->isreturn = true;
5484 if (sc->stc & STCscope)
5485 tf->isscope = true;
5486 if (sc->stc & STCscopeinferred)
5487 tf->isscopeinferred = true;
5488
5489// if ((sc->stc & (STCreturn | STCref)) == STCreturn)
5490// tf->isscope = true; // return by itself means 'return scope'
5491
5492 if (tf->trust == TRUSTdefault)
5493 {
5494 if (sc->stc & STCsafe)
5495 tf->trust = TRUSTsafe;
5496 if (sc->stc & STCsystem)
5497 tf->trust = TRUSTsystem;
5498 if (sc->stc & STCtrusted)
5499 tf->trust = TRUSTtrusted;
5500 }
5501
5502 if (sc->stc & STCproperty)
5503 tf->isproperty = true;
5504
5505 tf->linkage = sc->linkage;
5506 bool wildreturn = false;
5507 if (tf->next)
5508 {
5509 sc = sc->push();
5510 sc->stc &= ~(STC_TYPECTOR | STC_FUNCATTR);
5511 tf->next = tf->next->semantic(loc, sc);
5512 sc = sc->pop();
5513 errors |= tf->checkRetType(loc);
5514 if (tf->next->isscope() && !(sc->flags & SCOPEctor))
5515 {
5516 error(loc, "functions cannot return scope %s", tf->next->toChars());
5517 errors = true;
5518 }
5519 if (tf->next->hasWild())
5520 wildreturn = true;
5521
5522 if (tf->isreturn && !tf->isref && !tf->next->hasPointers())
5523 {
5524 error(loc, "function type '%s' has 'return' but does not return any indirections", tf->toChars());
5525 }
5526 }
5527
5528 unsigned char wildparams = 0;
5529 if (tf->parameters)
5530 {
5531 /* Create a scope for evaluating the default arguments for the parameters
5532 */
5533 Scope *argsc = sc->push();
5534 argsc->stc = 0; // don't inherit storage class
5535 argsc->protection = Prot(PROTpublic);
5536 argsc->func = NULL;
5537
5538 size_t dim = Parameter::dim(tf->parameters);
5539 for (size_t i = 0; i < dim; i++)
5540 {
5541 Parameter *fparam = Parameter::getNth(tf->parameters, i);
081f759d 5542 inuse++;
03385ed3 5543 fparam->type = fparam->type->semantic(loc, argsc);
081f759d 5544 inuse--;
03385ed3 5545
5546 if (fparam->type->ty == Terror)
5547 {
5548 errors = true;
5549 continue;
5550 }
5551
5552 fparam->type = fparam->type->addStorageClass(fparam->storageClass);
5553
5554 if (fparam->storageClass & (STCauto | STCalias | STCstatic))
5555 {
5556 if (!fparam->type)
5557 continue;
5558 }
5559
5560 Type *t = fparam->type->toBasetype();
5561
5562 if (t->ty == Tfunction)
5563 {
5564 error(loc, "cannot have parameter of function type %s", fparam->type->toChars());
5565 errors = true;
5566 }
5567 else if (!(fparam->storageClass & (STCref | STCout)) &&
5568 (t->ty == Tstruct || t->ty == Tsarray || t->ty == Tenum))
5569 {
5570 Type *tb2 = t->baseElemOf();
5571 if ((tb2->ty == Tstruct && !((TypeStruct *)tb2)->sym->members) ||
5572 (tb2->ty == Tenum && !((TypeEnum *)tb2)->sym->memtype))
5573 {
5574 error(loc, "cannot have parameter of opaque type %s by value", fparam->type->toChars());
5575 errors = true;
5576 }
5577 }
5578 else if (!(fparam->storageClass & STClazy) && t->ty == Tvoid)
5579 {
5580 error(loc, "cannot have parameter of type %s", fparam->type->toChars());
5581 errors = true;
5582 }
5583
5584 if ((fparam->storageClass & (STCref | STCwild)) == (STCref | STCwild))
5585 {
5586 // 'ref inout' implies 'return'
5587 fparam->storageClass |= STCreturn;
5588 }
5589
5590 if (fparam->storageClass & STCreturn)
5591 {
5592 if (fparam->storageClass & (STCref | STCout))
5593 {
5594 // Disabled for the moment awaiting improvement to allow return by ref
5595 // to be transformed into return by scope.
5596 if (0 && !tf->isref)
5597 {
5598 StorageClass stc = fparam->storageClass & (STCref | STCout);
5599 error(loc, "parameter %s is 'return %s' but function does not return by ref",
5600 fparam->ident ? fparam->ident->toChars() : "",
5601 stcToChars(stc));
5602 errors = true;
5603 }
5604 }
5605 else
5606 {
5607 fparam->storageClass |= STCscope; // 'return' implies 'scope'
5608 if (tf->isref)
5609 {
5610 }
5611 else if (!tf->isref && tf->next && !tf->next->hasPointers())
5612 {
5613 error(loc, "parameter %s is 'return' but function does not return any indirections",
5614 fparam->ident ? fparam->ident->toChars() : "");
5615 errors = true;
5616 }
5617 }
5618 }
5619
5620 if (fparam->storageClass & (STCref | STClazy))
5621 {
5622 }
5623 else if (fparam->storageClass & STCout)
5624 {
5625 if (unsigned char m = fparam->type->mod & (MODimmutable | MODconst | MODwild))
5626 {
5627 error(loc, "cannot have %s out parameter of type %s", MODtoChars(m), t->toChars());
5628 errors = true;
5629 }
5630 else
5631 {
5632 Type *tv = t;
5633 while (tv->ty == Tsarray)
5634 tv = tv->nextOf()->toBasetype();
5635 if (tv->ty == Tstruct && ((TypeStruct *)tv)->sym->noDefaultCtor)
5636 {
5637 error(loc, "cannot have out parameter of type %s because the default construction is disabled",
5638 fparam->type->toChars());
5639 errors = true;
5640 }
5641 }
5642 }
5643
5644 if (fparam->storageClass & STCscope && !fparam->type->hasPointers() && fparam->type->ty != Ttuple)
5645 {
5646 fparam->storageClass &= ~STCscope;
5647 if (!(fparam->storageClass & STCref))
5648 fparam->storageClass &= ~STCreturn;
5649 }
5650
5651 if (t->hasWild())
5652 {
5653 wildparams |= 1;
5654 //if (tf->next && !wildreturn)
5655 // error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')");
5656 }
5657
5658 if (fparam->defaultArg)
5659 {
5660 Expression *e = fparam->defaultArg;
5661 if (fparam->storageClass & (STCref | STCout))
5662 {
5663 e = ::semantic(e, argsc);
5664 e = resolveProperties(argsc, e);
5665 }
5666 else
5667 {
5668 e = inferType(e, fparam->type);
5669 Initializer *iz = new ExpInitializer(e->loc, e);
5670 iz = ::semantic(iz, argsc, fparam->type, INITnointerpret);
5671 e = initializerToExpression(iz);
5672 }
5673 if (e->op == TOKfunction) // see Bugzilla 4820
5674 {
5675 FuncExp *fe = (FuncExp *)e;
5676 // Replace function literal with a function symbol,
5677 // since default arg expression must be copied when used
5678 // and copying the literal itself is wrong.
5679 e = new VarExp(e->loc, fe->fd, false);
5680 e = new AddrExp(e->loc, e);
5681 e = ::semantic(e, argsc);
5682 }
5683 e = e->implicitCastTo(argsc, fparam->type);
5684
5685 // default arg must be an lvalue
5686 if (fparam->storageClass & (STCout | STCref))
5687 e = e->toLvalue(argsc, e);
5688
5689 fparam->defaultArg = e;
5690 if (e->op == TOKerror)
5691 errors = true;
5692 }
5693
5694 /* If fparam after semantic() turns out to be a tuple, the number of parameters may
5695 * change.
5696 */
5697 if (t->ty == Ttuple)
5698 {
5699 /* TypeFunction::parameter also is used as the storage of
5700 * Parameter objects for FuncDeclaration. So we should copy
5701 * the elements of TypeTuple::arguments to avoid unintended
5702 * sharing of Parameter object among other functions.
5703 */
5704 TypeTuple *tt = (TypeTuple *)t;
5705 if (tt->arguments && tt->arguments->dim)
5706 {
5707 /* Propagate additional storage class from tuple parameters to their
5708 * element-parameters.
5709 * Make a copy, as original may be referenced elsewhere.
5710 */
5711 size_t tdim = tt->arguments->dim;
5712 Parameters *newparams = new Parameters();
5713 newparams->setDim(tdim);
5714 for (size_t j = 0; j < tdim; j++)
5715 {
5716 Parameter *narg = (*tt->arguments)[j];
5717
5718 // Bugzilla 12744: If the storage classes of narg
5719 // conflict with the ones in fparam, it's ignored.
5720 StorageClass stc = fparam->storageClass | narg->storageClass;
5721 StorageClass stc1 = fparam->storageClass & (STCref | STCout | STClazy);
5722 StorageClass stc2 = narg->storageClass & (STCref | STCout | STClazy);
5723 if (stc1 && stc2 && stc1 != stc2)
5724 {
5725 OutBuffer buf1; stcToBuffer(&buf1, stc1 | ((stc1 & STCref) ? (fparam->storageClass & STCauto) : 0));
5726 OutBuffer buf2; stcToBuffer(&buf2, stc2);
5727
5728 error(loc, "incompatible parameter storage classes '%s' and '%s'",
5729 buf1.peekString(), buf2.peekString());
5730 errors = true;
5731 stc = stc1 | (stc & ~(STCref | STCout | STClazy));
5732 }
5733
5734 (*newparams)[j] = new Parameter(
5735 stc, narg->type, narg->ident, narg->defaultArg);
5736 }
5737 fparam->type = new TypeTuple(newparams);
5738 }
5739 fparam->storageClass = 0;
5740
5741 /* Reset number of parameters, and back up one to do this fparam again,
5742 * now that it is a tuple
5743 */
5744 dim = Parameter::dim(tf->parameters);
5745 i--;
5746 continue;
5747 }
5748
5749 /* Resolve "auto ref" storage class to be either ref or value,
5750 * based on the argument matching the parameter
5751 */
5752 if (fparam->storageClass & STCauto)
5753 {
5754 if (fargs && i < fargs->dim && (fparam->storageClass & STCref))
5755 {
5756 Expression *farg = (*fargs)[i];
5757 if (farg->isLvalue())
5758 ; // ref parameter
5759 else
5760 fparam->storageClass &= ~STCref; // value parameter
5761 fparam->storageClass &= ~STCauto; // Bugzilla 14656
5762 fparam->storageClass |= STCautoref;
5763 }
5764 else
5765 {
5766 error(loc, "'auto' can only be used as part of 'auto ref' for template function parameters");
5767 errors = true;
5768 }
5769 }
5770
5771 // Remove redundant storage classes for type, they are already applied
5772 fparam->storageClass &= ~(STC_TYPECTOR | STCin);
5773 }
5774 argsc->pop();
5775 }
5776 if (tf->isWild())
5777 wildparams |= 2;
5778
5779 if (wildreturn && !wildparams)
5780 {
5781 error(loc, "inout on return means inout must be on a parameter as well for %s", toChars());
5782 errors = true;
5783 }
5784 tf->iswild = wildparams;
5785
03385ed3 5786 if (tf->isproperty && (tf->varargs || Parameter::dim(tf->parameters) > 2))
5787 {
5788 error(loc, "properties can only have zero, one, or two parameter");
5789 errors = true;
5790 }
5791
5792 if (tf->varargs == 1 && tf->linkage != LINKd && Parameter::dim(tf->parameters) == 0)
5793 {
5794 error(loc, "variadic functions with non-D linkage must have at least one parameter");
5795 errors = true;
5796 }
5797
5798 if (errors)
5799 return terror;
5800
5801 if (tf->next)
5802 tf->deco = tf->merge()->deco;
5803
5804 /* Don't return merge(), because arg identifiers and default args
5805 * can be different
5806 * even though the types match
5807 */
5808 return tf;
5809}
5810
5811bool TypeFunction::checkRetType(Loc loc)
5812{
5813 Type *tb = next->toBasetype();
5814 if (tb->ty == Tfunction)
5815 {
5816 error(loc, "functions cannot return a function");
5817 next = Type::terror;
5818 }
5819 if (tb->ty == Ttuple)
5820 {
5821 error(loc, "functions cannot return a tuple");
5822 next = Type::terror;
5823 }
5824 if (!isref && (tb->ty == Tstruct || tb->ty == Tsarray))
5825 {
5826 Type *tb2 = tb->baseElemOf();
5827 if (tb2->ty == Tstruct && !((TypeStruct *)tb2)->sym->members)
5828 {
5829 error(loc, "functions cannot return opaque type %s by value", tb->toChars());
5830 next = Type::terror;
5831 }
5832 }
5833 if (tb->ty == Terror)
5834 return true;
5835
5836 return false;
5837}
5838
5839/* Determine purity level based on mutability of t
5840 * and whether it is a 'ref' type or not.
5841 */
5842static PURE purityOfType(bool isref, Type *t)
5843{
5844 if (isref)
5845 {
5846 if (t->mod & MODimmutable)
5847 return PUREstrong;
5848 if (t->mod & (MODconst | MODwild))
5849 return PUREconst;
5850 return PUREweak;
5851 }
5852
5853 t = t->baseElemOf();
5854
5855 if (!t->hasPointers() || t->mod & MODimmutable)
5856 return PUREstrong;
5857
5858 /* Accept immutable(T)[] and immutable(T)* as being strongly pure
5859 */
5860 if (t->ty == Tarray || t->ty == Tpointer)
5861 {
5862 Type *tn = t->nextOf()->toBasetype();
5863 if (tn->mod & MODimmutable)
5864 return PUREstrong;
5865 if (tn->mod & (MODconst | MODwild))
5866 return PUREconst;
5867 }
5868
5869 /* The rest of this is too strict; fix later.
5870 * For example, the only pointer members of a struct may be immutable,
5871 * which would maintain strong purity.
5872 * (Just like for dynamic arrays and pointers above.)
5873 */
5874 if (t->mod & (MODconst | MODwild))
5875 return PUREconst;
5876
5877 /* Should catch delegates and function pointers, and fold in their purity
5878 */
5879 return PUREweak;
5880}
5881
5882/********************************************
5883 * Set 'purity' field of 'this'.
5884 * Do this lazily, as the parameter types might be forward referenced.
5885 */
5886void TypeFunction::purityLevel()
5887{
5888 TypeFunction *tf = this;
5889 if (tf->purity != PUREfwdref)
5890 return;
5891
5892 purity = PUREstrong; // assume strong until something weakens it
5893
5894 /* Evaluate what kind of purity based on the modifiers for the parameters
5895 */
5896 const size_t dim = Parameter::dim(tf->parameters);
5897 for (size_t i = 0; i < dim; i++)
5898 {
5899 Parameter *fparam = Parameter::getNth(tf->parameters, i);
5900 Type *t = fparam->type;
5901 if (!t)
5902 continue;
5903
5904 if (fparam->storageClass & (STClazy | STCout))
5905 {
5906 purity = PUREweak;
5907 break;
5908 }
5909 switch (purityOfType((fparam->storageClass & STCref) != 0, t))
5910 {
5911 case PUREweak:
5912 purity = PUREweak;
5913 break;
5914
5915 case PUREconst:
5916 purity = PUREconst;
5917 continue;
5918
5919 case PUREstrong:
5920 continue;
5921
5922 default:
5923 assert(0);
5924 }
5925 break; // since PUREweak, no need to check further
5926 }
5927
5928 if (purity > PUREweak && tf->nextOf())
5929 {
5930 /* Adjust purity based on mutability of return type.
5931 * https://issues.dlang.org/show_bug.cgi?id=15862
5932 */
5933 const PURE purity2 = purityOfType(tf->isref, tf->nextOf());
5934 if (purity2 < purity)
5935 purity = purity2;
5936 }
5937 tf->purity = purity;
5938}
5939
5940/********************************
5941 * 'args' are being matched to function 'this'
5942 * Determine match level.
5943 * Input:
5944 * flag 1 performing a partial ordering match
5945 * Returns:
5946 * MATCHxxxx
5947 */
5948
5949MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag)
5950{
5951 //printf("TypeFunction::callMatch() %s\n", toChars());
5952 MATCH match = MATCHexact; // assume exact match
5953 unsigned char wildmatch = 0;
5954
5955 if (tthis)
5956 {
5957 Type *t = tthis;
5958 if (t->toBasetype()->ty == Tpointer)
5959 t = t->toBasetype()->nextOf(); // change struct* to struct
5960 if (t->mod != mod)
5961 {
5962 if (MODimplicitConv(t->mod, mod))
5963 match = MATCHconst;
5964 else if ((mod & MODwild) && MODimplicitConv(t->mod, (mod & ~MODwild) | MODconst))
5965 {
5966 match = MATCHconst;
5967 }
5968 else
5969 return MATCHnomatch;
5970 }
5971 if (isWild())
5972 {
5973 if (t->isWild())
5974 wildmatch |= MODwild;
5975 else if (t->isConst())
5976 wildmatch |= MODconst;
5977 else if (t->isImmutable())
5978 wildmatch |= MODimmutable;
5979 else
5980 wildmatch |= MODmutable;
5981 }
5982 }
5983
5984 size_t nparams = Parameter::dim(parameters);
5985 size_t nargs = args ? args->dim : 0;
5986 if (nparams == nargs)
5987 ;
5988 else if (nargs > nparams)
5989 {
5990 if (varargs == 0)
5991 goto Nomatch; // too many args; no match
5992 match = MATCHconvert; // match ... with a "conversion" match level
5993 }
5994
5995 for (size_t u = 0; u < nargs; u++)
5996 {
5997 if (u >= nparams)
5998 break;
5999 Parameter *p = Parameter::getNth(parameters, u);
6000 Expression *arg = (*args)[u];
6001 assert(arg);
6002 Type *tprm = p->type;
6003 Type *targ = arg->type;
6004
6005 if (!(p->storageClass & STClazy && tprm->ty == Tvoid && targ->ty != Tvoid))
6006 {
6007 bool isRef = (p->storageClass & (STCref | STCout)) != 0;
6008 wildmatch |= targ->deduceWild(tprm, isRef);
6009 }
6010 }
6011 if (wildmatch)
6012 {
6013 /* Calculate wild matching modifier
6014 */
6015 if (wildmatch & MODconst || wildmatch & (wildmatch - 1))
6016 wildmatch = MODconst;
6017 else if (wildmatch & MODimmutable)
6018 wildmatch = MODimmutable;
6019 else if (wildmatch & MODwild)
6020 wildmatch = MODwild;
6021 else
6022 {
6023 assert(wildmatch & MODmutable);
6024 wildmatch = MODmutable;
6025 }
6026 }
6027
6028 for (size_t u = 0; u < nparams; u++)
6029 {
6030 MATCH m;
6031
6032 Parameter *p = Parameter::getNth(parameters, u);
6033 assert(p);
6034 if (u >= nargs)
6035 {
6036 if (p->defaultArg)
6037 continue;
6038 goto L1; // try typesafe variadics
6039 }
6040 {
6041 Expression *arg = (*args)[u];
6042 assert(arg);
6043 //printf("arg: %s, type: %s\n", arg->toChars(), arg->type->toChars());
6044
6045 Type *targ = arg->type;
6046 Type *tprm = wildmatch ? p->type->substWildTo(wildmatch) : p->type;
6047
6048 if (p->storageClass & STClazy && tprm->ty == Tvoid && targ->ty != Tvoid)
6049 m = MATCHconvert;
6050 else
6051 {
6052 //printf("%s of type %s implicitConvTo %s\n", arg->toChars(), targ->toChars(), tprm->toChars());
6053 if (flag)
6054 {
6055 // for partial ordering, value is an irrelevant mockup, just look at the type
6056 m = targ->implicitConvTo(tprm);
6057 }
6058 else
6059 m = arg->implicitConvTo(tprm);
6060 //printf("match %d\n", m);
6061 }
6062
6063 // Non-lvalues do not match ref or out parameters
6064 if (p->storageClass & (STCref | STCout))
6065 {
6066 // Bugzilla 13783: Don't use toBasetype() to handle enum types.
6067 Type *ta = targ;
6068 Type *tp = tprm;
6069 //printf("fparam[%d] ta = %s, tp = %s\n", u, ta->toChars(), tp->toChars());
6070
6071 if (m && !arg->isLvalue())
6072 {
6073 if (p->storageClass & STCout)
6074 goto Nomatch;
6075
6076 if (arg->op == TOKstring && tp->ty == Tsarray)
6077 {
6078 if (ta->ty != Tsarray)
6079 {
6080 Type *tn = tp->nextOf()->castMod(ta->nextOf()->mod);
6081 dinteger_t dim = ((StringExp *)arg)->len;
6082 ta = tn->sarrayOf(dim);
6083 }
6084 }
6085 else if (arg->op == TOKslice && tp->ty == Tsarray)
6086 {
6087 // Allow conversion from T[lwr .. upr] to ref T[upr-lwr]
6088 if (ta->ty != Tsarray)
6089 {
6090 Type *tn = ta->nextOf();
6091 dinteger_t dim = ((TypeSArray *)tp)->dim->toUInteger();
6092 ta = tn->sarrayOf(dim);
6093 }
6094 }
6095 else
6096 goto Nomatch;
6097 }
6098
6099 /* Find most derived alias this type being matched.
6100 * Bugzilla 15674: Allow on both ref and out parameters.
6101 */
6102 while (1)
6103 {
6104 Type *tat = ta->toBasetype()->aliasthisOf();
6105 if (!tat || !tat->implicitConvTo(tprm))
6106 break;
6107 ta = tat;
6108 }
6109
6110 /* A ref variable should work like a head-const reference.
6111 * e.g. disallows:
6112 * ref T <- an lvalue of const(T) argument
6113 * ref T[dim] <- an lvalue of const(T[dim]) argument
6114 */
6115 if (!ta->constConv(tp))
6116 goto Nomatch;
6117 }
6118 }
6119
6120 /* prefer matching the element type rather than the array
6121 * type when more arguments are present with T[]...
6122 */
6123 if (varargs == 2 && u + 1 == nparams && nargs > nparams)
6124 goto L1;
6125
6126 //printf("\tm = %d\n", m);
6127 if (m == MATCHnomatch) // if no match
6128 {
6129 L1:
6130 if (varargs == 2 && u + 1 == nparams) // if last varargs param
6131 {
6132 Type *tb = p->type->toBasetype();
6133 TypeSArray *tsa;
6134 dinteger_t sz;
6135
6136 switch (tb->ty)
6137 {
6138 case Tsarray:
6139 tsa = (TypeSArray *)tb;
6140 sz = tsa->dim->toInteger();
6141 if (sz != nargs - u)
6142 goto Nomatch;
6143 /* fall through */
6144 case Tarray:
6145 {
6146 TypeArray *ta = (TypeArray *)tb;
6147 for (; u < nargs; u++)
6148 {
6149 Expression *arg = (*args)[u];
6150 assert(arg);
6151
6152 /* If lazy array of delegates,
6153 * convert arg(s) to delegate(s)
6154 */
6155 Type *tret = p->isLazyArray();
6156 if (tret)
6157 {
6158 if (ta->next->equals(arg->type))
6159 m = MATCHexact;
6160 else if (tret->toBasetype()->ty == Tvoid)
6161 m = MATCHconvert;
6162 else
6163 {
6164 m = arg->implicitConvTo(tret);
6165 if (m == MATCHnomatch)
6166 m = arg->implicitConvTo(ta->next);
6167 }
6168 }
6169 else
6170 m = arg->implicitConvTo(ta->next);
6171
6172 if (m == MATCHnomatch)
6173 goto Nomatch;
6174 if (m < match)
6175 match = m;
6176 }
6177 goto Ldone;
6178 }
6179 case Tclass:
6180 // Should see if there's a constructor match?
6181 // Or just leave it ambiguous?
6182 goto Ldone;
6183
6184 default:
6185 goto Nomatch;
6186 }
6187 }
6188 goto Nomatch;
6189 }
6190 if (m < match)
6191 match = m; // pick worst match
6192 }
6193
6194Ldone:
6195 //printf("match = %d\n", match);
6196 return match;
6197
6198Nomatch:
6199 //printf("no match\n");
6200 return MATCHnomatch;
6201}
6202
6203/********************************************
6204 * Return true if there are lazy parameters.
6205 */
6206bool TypeFunction::hasLazyParameters()
6207{
6208 size_t dim = Parameter::dim(parameters);
6209 for (size_t i = 0; i < dim; i++)
6210 {
6211 Parameter *fparam = Parameter::getNth(parameters, i);
6212 if (fparam->storageClass & STClazy)
6213 return true;
6214 }
6215 return false;
6216}
6217
6218/***************************
6219 * Examine function signature for parameter p and see if
6220 * the value of p can 'escape' the scope of the function.
6221 * This is useful to minimize the needed annotations for the parameters.
6222 * Params:
6223 * p = parameter to this function
6224 * Returns:
6225 * true if escapes via assignment to global or through a parameter
6226 */
6227
6228bool TypeFunction::parameterEscapes(Parameter *p)
6229{
6230 /* Scope parameters do not escape.
6231 * Allow 'lazy' to imply 'scope' -
6232 * lazy parameters can be passed along
6233 * as lazy parameters to the next function, but that isn't
6234 * escaping.
6235 */
6236 if (parameterStorageClass(p) & (STCscope | STClazy))
6237 return false;
6238 return true;
6239}
6240
6241/************************************
6242 * Take the specified storage class for p,
6243 * and use the function signature to infer whether
6244 * STCscope and STCreturn should be OR'd in.
6245 * (This will not affect the name mangling.)
6246 * Params:
6247 * p = one of the parameters to 'this'
6248 * Returns:
6249 * storage class with STCscope or STCreturn OR'd in
6250 */
6251StorageClass TypeFunction::parameterStorageClass(Parameter *p)
6252{
6253 StorageClass stc = p->storageClass;
6254 if (!global.params.vsafe)
6255 return stc;
6256
6257 if (stc & (STCscope | STCreturn | STClazy) || purity == PUREimpure)
6258 return stc;
6259
6260 /* If haven't inferred the return type yet, can't infer storage classes
6261 */
6262 if (!nextOf())
6263 return stc;
6264
6265 purityLevel();
6266
6267 // See if p can escape via any of the other parameters
6268 if (purity == PUREweak)
6269 {
6270 const size_t dim = Parameter::dim(parameters);
6271 for (size_t i = 0; i < dim; i++)
6272 {
6273 Parameter *fparam = Parameter::getNth(parameters, i);
6274 Type *t = fparam->type;
6275 if (!t)
6276 continue;
6277 t = t->baseElemOf();
6278 if (t->isMutable() && t->hasPointers())
6279 {
6280 if (fparam->storageClass & (STCref | STCout))
6281 {
6282 }
6283 else if (t->ty == Tarray || t->ty == Tpointer)
6284 {
6285 Type *tn = t->nextOf()->toBasetype();
6286 if (!(tn->isMutable() && tn->hasPointers()))
6287 continue;
6288 }
6289 return stc;
6290 }
6291 }
6292 }
6293
6294 stc |= STCscope;
6295
6296 /* Inferring STCreturn here has false positives
6297 * for pure functions, producing spurious error messages
6298 * about escaping references.
6299 * Give up on it for now.
6300 */
6301 return stc;
6302}
6303
6304Expression *TypeFunction::defaultInit(Loc loc)
6305{
6306 error(loc, "function does not have a default initializer");
6307 return new ErrorExp();
6308}
6309
6310Type *TypeFunction::addStorageClass(StorageClass stc)
6311{
6312 //printf("addStorageClass(%llx) %d\n", stc, (stc & STCscope) != 0);
2feebf42 6313 TypeFunction *t = Type::addStorageClass(stc)->toTypeFunction();
03385ed3 6314 if ((stc & STCpure && !t->purity) ||
6315 (stc & STCnothrow && !t->isnothrow) ||
6316 (stc & STCnogc && !t->isnogc) ||
6317 (stc & STCscope && !t->isscope) ||
6318 (stc & STCsafe && t->trust < TRUSTtrusted))
6319 {
6320 // Klunky to change these
6321 TypeFunction *tf = new TypeFunction(t->parameters, t->next, t->varargs, t->linkage, 0);
6322 tf->mod = t->mod;
6323 tf->fargs = fargs;
6324 tf->purity = t->purity;
6325 tf->isnothrow = t->isnothrow;
6326 tf->isnogc = t->isnogc;
6327 tf->isproperty = t->isproperty;
6328 tf->isref = t->isref;
6329 tf->isreturn = t->isreturn;
6330 tf->isscope = t->isscope;
6331 tf->isscopeinferred = t->isscopeinferred;
6332 tf->trust = t->trust;
6333 tf->iswild = t->iswild;
6334
6335 if (stc & STCpure)
6336 tf->purity = PUREfwdref;
6337 if (stc & STCnothrow)
6338 tf->isnothrow = true;
6339 if (stc & STCnogc)
6340 tf->isnogc = true;
6341 if (stc & STCsafe)
6342 tf->trust = TRUSTsafe;
6343 if (stc & STCscope)
6344 {
6345 tf->isscope = true;
6346 if (stc & STCscopeinferred)
6347 tf->isscopeinferred = true;
6348 }
6349
6350 tf->deco = tf->merge()->deco;
6351 t = tf;
6352 }
6353 return t;
6354}
6355
6356/** For each active attribute (ref/const/nogc/etc) call fp with a void* for the
6357work param and a string representation of the attribute. */
6358int TypeFunction::attributesApply(void *param, int (*fp)(void *, const char *), TRUSTformat trustFormat)
6359{
6360 int res = 0;
6361
6362 if (purity) res = fp(param, "pure");
6363 if (res) return res;
6364
6365 if (isnothrow) res = fp(param, "nothrow");
6366 if (res) return res;
6367
6368 if (isnogc) res = fp(param, "@nogc");
6369 if (res) return res;
6370
6371 if (isproperty) res = fp(param, "@property");
6372 if (res) return res;
6373
6374 if (isref) res = fp(param, "ref");
6375 if (res) return res;
6376
6377 if (isreturn) res = fp(param, "return");
6378 if (res) return res;
6379
6380 if (isscope && !isscopeinferred) res = fp(param, "scope");
6381 if (res) return res;
6382
6383 TRUST trustAttrib = trust;
6384
6385 if (trustAttrib == TRUSTdefault)
6386 {
6387 // Print out "@system" when trust equals TRUSTdefault (if desired).
6388 if (trustFormat == TRUSTformatSystem)
6389 trustAttrib = TRUSTsystem;
6390 else
6391 return res; // avoid calling with an empty string
6392 }
6393
6394 return fp(param, trustToChars(trustAttrib));
6395}
6396
6397/***************************** TypeDelegate *****************************/
6398
6399TypeDelegate::TypeDelegate(Type *t)
6400 : TypeNext(Tfunction, t)
6401{
6402 ty = Tdelegate;
6403}
6404
6405TypeDelegate *TypeDelegate::create(Type *t)
6406{
6407 return new TypeDelegate(t);
6408}
6409
6410const char *TypeDelegate::kind()
6411{
6412 return "delegate";
6413}
6414
6415Type *TypeDelegate::syntaxCopy()
6416{
6417 Type *t = next->syntaxCopy();
6418 if (t == next)
6419 t = this;
6420 else
6421 {
6422 t = new TypeDelegate(t);
6423 t->mod = mod;
6424 }
6425 return t;
6426}
6427
6428Type *TypeDelegate::semantic(Loc loc, Scope *sc)
6429{
6430 //printf("TypeDelegate::semantic() %s\n", toChars());
6431 if (deco) // if semantic() already run
6432 {
6433 //printf("already done\n");
6434 return this;
6435 }
6436 next = next->semantic(loc,sc);
6437 if (next->ty != Tfunction)
6438 return terror;
6439
6440 /* In order to deal with Bugzilla 4028, perhaps default arguments should
6441 * be removed from next before the merge.
6442 */
6443
6444 /* Don't return merge(), because arg identifiers and default args
6445 * can be different
6446 * even though the types match
6447 */
6448 deco = merge()->deco;
6449 return this;
6450}
6451
6452Type *TypeDelegate::addStorageClass(StorageClass stc)
6453{
6454 TypeDelegate *t = (TypeDelegate*)Type::addStorageClass(stc);
6455 if (!global.params.vsafe)
6456 return t;
6457
6458 /* The rest is meant to add 'scope' to a delegate declaration if it is of the form:
6459 * alias dg_t = void* delegate();
6460 * scope dg_t dg = ...;
6461 */
6462 if(stc & STCscope)
6463 {
6464 Type *n = t->next->addStorageClass(STCscope | STCscopeinferred);
6465 if (n != t->next)
6466 {
6467 t->next = n;
6468 t->deco = t->merge()->deco; // mangling supposed to not be changed due to STCscopeinferrred
6469 }
6470 }
6471 return t;
6472}
6473
6474d_uns64 TypeDelegate::size(Loc)
6475{
6476 return Target::ptrsize * 2;
6477}
6478
6479unsigned TypeDelegate::alignsize()
6480{
6481 return Target::ptrsize;
6482}
6483
6484MATCH TypeDelegate::implicitConvTo(Type *to)
6485{
6486 //printf("TypeDelegate::implicitConvTo(this=%p, to=%p)\n", this, to);
6487 //printf("from: %s\n", toChars());
6488 //printf("to : %s\n", to->toChars());
6489 if (this == to)
6490 return MATCHexact;
6491#if 1 // not allowing covariant conversions because it interferes with overriding
6492 if (to->ty == Tdelegate && this->nextOf()->covariant(to->nextOf()) == 1)
6493 {
6494 Type *tret = this->next->nextOf();
6495 Type *toret = ((TypeDelegate *)to)->next->nextOf();
6496 if (tret->ty == Tclass && toret->ty == Tclass)
6497 {
6498 /* Bugzilla 10219: Check covariant interface return with offset tweaking.
6499 * interface I {}
6500 * class C : Object, I {}
6501 * I delegate() dg = delegate C() {} // should be error
6502 */
6503 int offset = 0;
6504 if (toret->isBaseOf(tret, &offset) && offset != 0)
6505 return MATCHnomatch;
6506 }
6507 return MATCHconvert;
6508 }
6509#endif
6510 return MATCHnomatch;
6511}
6512
6513Expression *TypeDelegate::defaultInit(Loc loc)
6514{
6515 return new NullExp(loc, this);
6516}
6517
6518bool TypeDelegate::isZeroInit(Loc)
6519{
6520 return true;
6521}
6522
6523bool TypeDelegate::isBoolean()
6524{
6525 return true;
6526}
6527
6528Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
6529{
6530 if (ident == Id::ptr)
6531 {
6532 e = new DelegatePtrExp(e->loc, e);
6533 e = ::semantic(e, sc);
6534 }
6535 else if (ident == Id::funcptr)
6536 {
6537 if (!(flag & 2) && sc->func && !sc->intypeof && sc->func->setUnsafe())
6538 {
6539 e->error("%s.funcptr cannot be used in @safe code", e->toChars());
6540 return new ErrorExp();
6541 }
6542 e = new DelegateFuncptrExp(e->loc, e);
6543 e = ::semantic(e, sc);
6544 }
6545 else
6546 {
6547 e = Type::dotExp(sc, e, ident, flag);
6548 }
6549 return e;
6550}
6551
6552bool TypeDelegate::hasPointers()
6553{
6554 return true;
6555}
6556
6557
6558
6559/***************************** TypeQualified *****************************/
6560
6561TypeQualified::TypeQualified(TY ty, Loc loc)
6562 : Type(ty)
6563{
6564 this->loc = loc;
6565}
6566
6567void TypeQualified::syntaxCopyHelper(TypeQualified *t)
6568{
6569 //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t->toChars(), toChars());
6570 idents.setDim(t->idents.dim);
6571 for (size_t i = 0; i < idents.dim; i++)
6572 {
6573 RootObject *id = t->idents[i];
6574 if (id->dyncast() == DYNCAST_DSYMBOL)
6575 {
6576 TemplateInstance *ti = (TemplateInstance *)id;
6577
6578 ti = (TemplateInstance *)ti->syntaxCopy(NULL);
6579 id = ti;
6580 }
6581 else if (id->dyncast() == DYNCAST_EXPRESSION)
6582 {
6583 Expression *e = (Expression *)id;
6584 e = e->syntaxCopy();
6585 id = e;
6586 }
6587 else if (id->dyncast() == DYNCAST_TYPE)
6588 {
6589 Type *tx = (Type *)id;
6590 tx = tx->syntaxCopy();
6591 id = tx;
6592 }
6593 idents[i] = id;
6594 }
6595}
6596
6597void TypeQualified::addIdent(Identifier *ident)
6598{
6599 idents.push(ident);
6600}
6601
6602void TypeQualified::addInst(TemplateInstance *inst)
6603{
6604 idents.push(inst);
6605}
6606
6607void TypeQualified::addIndex(RootObject *e)
6608{
6609 idents.push(e);
6610}
6611
6612d_uns64 TypeQualified::size(Loc)
6613{
6614 error(this->loc, "size of type %s is not known", toChars());
6615 return SIZE_INVALID;
6616}
6617
6618/*************************************
6619 * Resolve a tuple index.
6620 */
6621void TypeQualified::resolveTupleIndex(Loc loc, Scope *sc, Dsymbol *s,
6622 Expression **pe, Type **pt, Dsymbol **ps, RootObject *oindex)
6623{
6624 *pt = NULL;
6625 *ps = NULL;
6626 *pe = NULL;
6627
6628 TupleDeclaration *td = s->isTupleDeclaration();
6629
6630 Expression *eindex = isExpression(oindex);
6631 Type *tindex = isType(oindex);
6632 Dsymbol *sindex = isDsymbol(oindex);
6633
6634 if (!td)
6635 {
6636 // It's really an index expression
6637 if (tindex)
6638 eindex = new TypeExp(loc, tindex);
6639 else if (sindex)
6640 eindex = ::resolve(loc, sc, sindex, false);
6641 Expression *e = new IndexExp(loc, ::resolve(loc, sc, s, false), eindex);
6642 e = ::semantic(e, sc);
6643 resolveExp(e, pt, pe, ps);
6644 return;
6645 }
6646
6647 // Convert oindex to Expression, then try to resolve to constant.
6648 if (tindex)
6649 tindex->resolve(loc, sc, &eindex, &tindex, &sindex);
6650 if (sindex)
6651 eindex = ::resolve(loc, sc, sindex, false);
6652 if (!eindex)
6653 {
6654 ::error(loc, "index is %s not an expression", oindex->toChars());
6655 *pt = Type::terror;
6656 return;
6657 }
6658 sc = sc->startCTFE();
6659 eindex = ::semantic(eindex, sc);
6660 sc = sc->endCTFE();
6661
6662 eindex = eindex->ctfeInterpret();
6663 if (eindex->op == TOKerror)
6664 {
6665 *pt = Type::terror;
6666 return;
6667 }
6668
6669 const uinteger_t d = eindex->toUInteger();
6670 if (d >= td->objects->dim)
6671 {
6672 ::error(loc, "tuple index %llu exceeds length %u", (ulonglong)d, (unsigned)td->objects->dim);
6673 *pt = Type::terror;
6674 return;
6675 }
6676
6677 RootObject *o = (*td->objects)[(size_t)d];
6678 *pt = isType(o);
6679 *ps = isDsymbol(o);
6680 *pe = isExpression(o);
6681
6682 if (*pt)
6683 *pt = (*pt)->semantic(loc, sc);
6684 if (*pe)
6685 resolveExp(*pe, pt, pe, ps);
6686}
6687
6688/*************************************
6689 * Takes an array of Identifiers and figures out if
6690 * it represents a Type or an Expression.
6691 * Output:
6692 * if expression, *pe is set
6693 * if type, *pt is set
6694 */
6695void TypeQualified::resolveHelper(Loc loc, Scope *sc,
6696 Dsymbol *s, Dsymbol *,
6697 Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
6698{
6699 *pe = NULL;
6700 *pt = NULL;
6701 *ps = NULL;
6702 if (s)
6703 {
6704 //printf("\t1: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
6705 Declaration *d = s->isDeclaration();
6706 if (d && (d->storage_class & STCtemplateparameter))
6707 s = s->toAlias();
6708 else
6709 s->checkDeprecated(loc, sc); // check for deprecated aliases
6710
6711 s = s->toAlias();
6712 //printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
6713 for (size_t i = 0; i < idents.dim; i++)
6714 {
6715 RootObject *id = idents[i];
6716
6717 if (id->dyncast() == DYNCAST_EXPRESSION ||
6718 id->dyncast() == DYNCAST_TYPE)
6719 {
6720 Type *tx;
6721 Expression *ex;
6722 Dsymbol *sx;
6723 resolveTupleIndex(loc, sc, s, &ex, &tx, &sx, id);
6724 if (sx)
6725 {
6726 s = sx->toAlias();
6727 continue;
6728 }
6729 if (tx)
6730 ex = new TypeExp(loc, tx);
6731 assert(ex);
6732
6733 ex = typeToExpressionHelper(this, ex, i + 1);
6734 ex = ::semantic(ex, sc);
6735 resolveExp(ex, pt, pe, ps);
6736 return;
6737 }
6738
6739 Type *t = s->getType(); // type symbol, type alias, or type tuple?
6740 unsigned errorsave = global.errors;
6741 Dsymbol *sm = s->searchX(loc, sc, id);
6742 if (sm && !(sc->flags & SCOPEignoresymbolvisibility) && !symbolIsVisible(sc, sm))
6743 {
6744 ::deprecation(loc, "%s is not visible from module %s", sm->toPrettyChars(), sc->_module->toChars());
6745 // sm = NULL;
6746 }
6747 if (global.errors != errorsave)
6748 {
6749 *pt = Type::terror;
6750 return;
6751 }
6752 //printf("\t3: s = %p %s %s, sm = %p\n", s, s->kind(), s->toChars(), sm);
6753 if (intypeid && !t && sm && sm->needThis())
6754 goto L3;
6755 if (VarDeclaration *v = s->isVarDeclaration())
6756 {
feb0e6d0 6757 // https://issues.dlang.org/show_bug.cgi?id=19913
6758 // v->type would be null if it is a forward referenced member.
6759 if (v->type == NULL)
6760 v->semantic(sc);
03385ed3 6761 if (v->storage_class & (STCconst | STCimmutable | STCmanifest) ||
6762 v->type->isConst() || v->type->isImmutable())
6763 {
6764 // Bugzilla 13087: this.field is not constant always
6765 if (!v->isThisDeclaration())
6766 goto L3;
6767 }
6768 }
6769 if (!sm)
6770 {
6771 if (!t)
6772 {
6773 if (s->isDeclaration()) // var, func, or tuple declaration?
6774 {
6775 t = s->isDeclaration()->type;
6776 if (!t && s->isTupleDeclaration()) // expression tuple?
6777 goto L3;
6778 }
6779 else if (s->isTemplateInstance() ||
6780 s->isImport() || s->isPackage() || s->isModule())
6781 {
6782 goto L3;
6783 }
6784 }
6785 if (t)
6786 {
6787 sm = t->toDsymbol(sc);
6788 if (sm && id->dyncast() == DYNCAST_IDENTIFIER)
6789 {
6790 sm = sm->search(loc, (Identifier *)id);
6791 if (sm)
6792 goto L2;
6793 }
6794 L3:
6795 Expression *e;
6796 VarDeclaration *v = s->isVarDeclaration();
6797 FuncDeclaration *f = s->isFuncDeclaration();
6798 if (intypeid || (!v && !f))
6799 e = ::resolve(loc, sc, s, true);
6800 else
6801 e = new VarExp(loc, s->isDeclaration(), true);
6802
6803 e = typeToExpressionHelper(this, e, i);
6804 e = ::semantic(e, sc);
6805 resolveExp(e, pt, pe, ps);
6806 return;
6807 }
6808 else
6809 {
6810 if (id->dyncast() == DYNCAST_DSYMBOL)
6811 {
6812 // searchX already handles errors for template instances
6813 assert(global.errors);
6814 }
6815 else
6816 {
6817 assert(id->dyncast() == DYNCAST_IDENTIFIER);
6818 sm = s->search_correct((Identifier *)id);
6819 if (sm)
6820 error(loc, "identifier '%s' of '%s' is not defined, did you mean %s '%s'?",
6821 id->toChars(), toChars(), sm->kind(), sm->toChars());
6822 else
6823 error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
6824 }
6825 *pe = new ErrorExp();
6826 }
6827 return;
6828 }
6829 L2:
6830 s = sm->toAlias();
6831 }
6832
6833 if (EnumMember *em = s->isEnumMember())
6834 {
6835 // It's not a type, it's an expression
6836 *pe = em->getVarExp(loc, sc);
6837 return;
6838 }
6839 if (VarDeclaration *v = s->isVarDeclaration())
6840 {
6841 /* This is mostly same with DsymbolExp::semantic(), but we cannot use it
6842 * because some variables used in type context need to prevent lowering
6843 * to a literal or contextful expression. For example:
6844 *
6845 * enum a = 1; alias b = a;
6846 * template X(alias e){ alias v = e; } alias x = X!(1);
6847 * struct S { int v; alias w = v; }
6848 * // TypeIdentifier 'a', 'e', and 'v' should be TOKvar,
6849 * // because getDsymbol() need to work in AliasDeclaration::semantic().
6850 */
6851 if (!v->type ||
6852 (!v->type->deco && v->inuse))
6853 {
6854 if (v->inuse) // Bugzilla 9494
6855 error(loc, "circular reference to %s '%s'", v->kind(), v->toPrettyChars());
6856 else
6857 error(loc, "forward reference to %s '%s'", v->kind(), v->toPrettyChars());
6858 *pt = Type::terror;
6859 return;
6860 }
6861 if (v->type->ty == Terror)
6862 *pt = Type::terror;
6863 else
6864 *pe = new VarExp(loc, v);
6865 return;
6866 }
6867 if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration())
6868 {
6869 //printf("'%s' is a function literal\n", fld->toChars());
6870 *pe = new FuncExp(loc, fld);
6871 *pe = ::semantic(*pe, sc);
6872 return;
6873 }
6874L1:
6875 Type *t = s->getType();
6876 if (!t)
6877 {
6878 // If the symbol is an import, try looking inside the import
6879 if (Import *si = s->isImport())
6880 {
6881 s = si->search(loc, s->ident);
6882 if (s && s != si)
6883 goto L1;
6884 s = si;
6885 }
6886 *ps = s;
6887 return;
6888 }
6889 if (t->ty == Tinstance && t != this && !t->deco)
6890 {
6891 if (!((TypeInstance *)t)->tempinst->errors)
6892 error(loc, "forward reference to '%s'", t->toChars());
6893 *pt = Type::terror;
6894 return;
6895 }
6896
6897 if (t->ty == Ttuple)
6898 *pt = t;
6899 else
6900 *pt = t->merge();
6901 }
6902 if (!s)
6903 {
6904 /* Look for what user might have intended
6905 */
6906 const char *p = mutableOf()->unSharedOf()->toChars();
6907 Identifier *id = Identifier::idPool(p, strlen(p));
6908 if (const char *n = importHint(p))
6909 error(loc, "`%s` is not defined, perhaps `import %s;` ?", p, n);
6910 else if (Dsymbol *s2 = sc->search_correct(id))
6911 error(loc, "undefined identifier `%s`, did you mean %s `%s`?", p, s2->kind(), s2->toChars());
6912 else if (const char *q = Scope::search_correct_C(id))
6913 error(loc, "undefined identifier `%s`, did you mean `%s`?", p, q);
6914 else
6915 error(loc, "undefined identifier `%s`", p);
6916
6917 *pt = Type::terror;
6918 }
6919}
6920
6921/***************************** TypeIdentifier *****************************/
6922
6923TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident)
6924 : TypeQualified(Tident, loc)
6925{
6926 this->ident = ident;
6927}
6928
6929const char *TypeIdentifier::kind()
6930{
6931 return "identifier";
6932}
6933
6934Type *TypeIdentifier::syntaxCopy()
6935{
6936 TypeIdentifier *t = new TypeIdentifier(loc, ident);
6937 t->syntaxCopyHelper(this);
6938 t->mod = mod;
6939 return t;
6940}
6941
6942/*************************************
6943 * Takes an array of Identifiers and figures out if
6944 * it represents a Type or an Expression.
6945 * Output:
6946 * if expression, *pe is set
6947 * if type, *pt is set
6948 */
6949
6950void TypeIdentifier::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
6951{
6952 //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars());
6953
6954 if ((ident->equals(Id::_super) || ident->equals(Id::This)) && !hasThis(sc))
6955 {
6956 AggregateDeclaration *ad = sc->getStructClassScope();
6957 if (ad)
6958 {
6959 ClassDeclaration *cd = ad->isClassDeclaration();
6960 if (cd)
6961 {
6962 if (ident->equals(Id::This))
6963 ident = cd->ident;
6964 else if (cd->baseClass && ident->equals(Id::_super))
6965 ident = cd->baseClass->ident;
6966 }
6967 else
6968 {
6969 StructDeclaration *sd = ad->isStructDeclaration();
6970 if (sd && ident->equals(Id::This))
6971 ident = sd->ident;
6972 }
6973 }
6974 }
6975 if (ident == Id::ctfe)
6976 {
6977 error(loc, "variable __ctfe cannot be read at compile time");
6978 *pe = NULL;
6979 *ps = NULL;
6980 *pt = Type::terror;
6981 return;
6982 }
6983
6984 Dsymbol *scopesym;
6985 Dsymbol *s = sc->search(loc, ident, &scopesym);
6986 resolveHelper(loc, sc, s, scopesym, pe, pt, ps, intypeid);
6987 if (*pt)
6988 (*pt) = (*pt)->addMod(mod);
6989}
6990
6991/*****************************************
6992 * See if type resolves to a symbol, if so,
6993 * return that symbol.
6994 */
6995
6996Dsymbol *TypeIdentifier::toDsymbol(Scope *sc)
6997{
6998 //printf("TypeIdentifier::toDsymbol('%s')\n", toChars());
6999 if (!sc)
7000 return NULL;
7001
7002 Type *t;
7003 Expression *e;
7004 Dsymbol *s;
7005
7006 resolve(loc, sc, &e, &t, &s);
7007 if (t && t->ty != Tident)
7008 s = t->toDsymbol(sc);
7009 if (e)
7010 s = getDsymbol(e);
7011
7012 return s;
7013}
7014
7015Type *TypeIdentifier::semantic(Loc loc, Scope *sc)
7016{
7017 Type *t;
7018 Expression *e;
7019 Dsymbol *s;
7020
7021 //printf("TypeIdentifier::semantic(%s)\n", toChars());
7022 resolve(loc, sc, &e, &t, &s);
7023 if (t)
7024 {
7025 //printf("\tit's a type %d, %s, %s\n", t->ty, t->toChars(), t->deco);
7026 t = t->addMod(mod);
7027 }
7028 else
7029 {
7030 if (s)
7031 {
7032 s->error(loc, "is used as a type");
7033 //halt();
7034 }
7035 else
7036 error(loc, "%s is used as a type", toChars());
7037 t = terror;
7038 }
7039 //t->print();
7040 return t;
7041}
7042
7043/***************************** TypeInstance *****************************/
7044
7045TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst)
7046 : TypeQualified(Tinstance, loc)
7047{
7048 this->tempinst = tempinst;
7049}
7050
7051const char *TypeInstance::kind()
7052{
7053 return "instance";
7054}
7055
7056Type *TypeInstance::syntaxCopy()
7057{
7058 //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim);
7059 TypeInstance *t = new TypeInstance(loc, (TemplateInstance *)tempinst->syntaxCopy(NULL));
7060 t->syntaxCopyHelper(this);
7061 t->mod = mod;
7062 return t;
7063}
7064
7065void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
7066{
7067 // Note close similarity to TypeIdentifier::resolve()
7068 *pe = NULL;
7069 *pt = NULL;
7070 *ps = NULL;
7071 //printf("TypeInstance::resolve(sc = %p, tempinst = '%s')\n", sc, tempinst->toChars());
7072 tempinst->semantic(sc);
7073 if (!global.gag && tempinst->errors)
7074 {
7075 *pt = terror;
7076 return;
7077 }
7078
7079 resolveHelper(loc, sc, tempinst, NULL, pe, pt, ps, intypeid);
7080 if (*pt)
7081 *pt = (*pt)->addMod(mod);
7082 //if (*pt) printf("pt = '%s'\n", (*pt)->toChars());
7083}
7084
7085Type *TypeInstance::semantic(Loc loc, Scope *sc)
7086{
7087 Type *t;
7088 Expression *e;
7089 Dsymbol *s;
7090
7091 //printf("TypeInstance::semantic(%p, %s)\n", this, toChars());
7092 {
7093 unsigned errors = global.errors;
7094 resolve(loc, sc, &e, &t, &s);
7095 // if we had an error evaluating the symbol, suppress further errors
7096 if (!t && errors != global.errors)
7097 return terror;
7098 }
7099
7100 if (!t)
7101 {
7102 if (!e && s && s->errors)
7103 {
7104 // if there was an error evaluating the symbol, it might actually
7105 // be a type. Avoid misleading error messages.
7106 error(loc, "%s had previous errors", toChars());
7107 }
7108 else
7109 error(loc, "%s is used as a type", toChars());
7110 t = terror;
7111 }
7112 return t;
7113}
7114
7115Dsymbol *TypeInstance::toDsymbol(Scope *sc)
7116{
7117 Type *t;
7118 Expression *e;
7119 Dsymbol *s;
7120
7121 //printf("TypeInstance::semantic(%s)\n", toChars());
7122 resolve(loc, sc, &e, &t, &s);
7123 if (t && t->ty != Tinstance)
7124 s = t->toDsymbol(sc);
7125
7126 return s;
7127}
7128
7129
7130/***************************** TypeTypeof *****************************/
7131
7132TypeTypeof::TypeTypeof(Loc loc, Expression *exp)
7133 : TypeQualified(Ttypeof, loc)
7134{
7135 this->exp = exp;
7136 inuse = 0;
7137}
7138
7139const char *TypeTypeof::kind()
7140{
7141 return "typeof";
7142}
7143
7144Type *TypeTypeof::syntaxCopy()
7145{
7146 //printf("TypeTypeof::syntaxCopy() %s\n", toChars());
7147 TypeTypeof *t = new TypeTypeof(loc, exp->syntaxCopy());
7148 t->syntaxCopyHelper(this);
7149 t->mod = mod;
7150 return t;
7151}
7152
7153Dsymbol *TypeTypeof::toDsymbol(Scope *sc)
7154{
7155 //printf("TypeTypeof::toDsymbol('%s')\n", toChars());
7156 Expression *e;
7157 Type *t;
7158 Dsymbol *s;
7159 resolve(loc, sc, &e, &t, &s);
7160
7161 return s;
7162}
7163
7164void TypeTypeof::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
7165{
7166 *pe = NULL;
7167 *pt = NULL;
7168 *ps = NULL;
7169
7170 //printf("TypeTypeof::resolve(sc = %p, idents = '%s')\n", sc, toChars());
7171 //static int nest; if (++nest == 50) *(char*)0=0;
7172 if (inuse)
7173 {
7174 inuse = 2;
7175 error(loc, "circular typeof definition");
7176 Lerr:
7177 *pt = Type::terror;
7178 inuse--;
7179 return;
7180 }
7181 inuse++;
7182
7183 Type *t;
7184 {
7185 /* Currently we cannot evalute 'exp' in speculative context, because
7186 * the type implementation may leak to the final execution. Consider:
7187 *
7188 * struct S(T) {
7189 * string toString() const { return "x"; }
7190 * }
7191 * void main() {
7192 * alias X = typeof(S!int());
7193 * assert(typeid(X).xtoString(null) == "x");
7194 * }
7195 */
7196 Scope *sc2 = sc->push();
7197 sc2->intypeof = 1;
7198 Expression *exp2 = ::semantic(exp, sc2);
7199 exp2 = resolvePropertiesOnly(sc2, exp2);
7200 sc2->pop();
7201
7202 if (exp2->op == TOKerror)
7203 {
7204 if (!global.gag)
7205 exp = exp2;
7206 goto Lerr;
7207 }
7208 exp = exp2;
7209
7210 if (exp->op == TOKtype ||
7211 exp->op == TOKscope)
7212 {
7213 if (exp->checkType())
7214 goto Lerr;
7215
7216 /* Today, 'typeof(func)' returns void if func is a
7217 * function template (TemplateExp), or
7218 * template lambda (FuncExp).
7219 * It's actually used in Phobos as an idiom, to branch code for
7220 * template functions.
7221 */
7222 }
7223 if (FuncDeclaration *f = exp->op == TOKvar ? (( VarExp *)exp)->var->isFuncDeclaration()
7224 : exp->op == TOKdotvar ? ((DotVarExp *)exp)->var->isFuncDeclaration() : NULL)
7225 {
7226 if (f->checkForwardRef(loc))
7227 goto Lerr;
7228 }
7229 if (FuncDeclaration *f = isFuncAddress(exp))
7230 {
7231 if (f->checkForwardRef(loc))
7232 goto Lerr;
7233 }
7234
7235 t = exp->type;
7236 if (!t)
7237 {
7238 error(loc, "expression (%s) has no type", exp->toChars());
7239 goto Lerr;
7240 }
7241 if (t->ty == Ttypeof)
7242 {
7243 error(loc, "forward reference to %s", toChars());
7244 goto Lerr;
7245 }
7246 }
7247 if (idents.dim == 0)
7248 *pt = t;
7249 else
7250 {
7251 if (Dsymbol *s = t->toDsymbol(sc))
7252 resolveHelper(loc, sc, s, NULL, pe, pt, ps, intypeid);
7253 else
7254 {
7255 Expression *e = typeToExpressionHelper(this, new TypeExp(loc, t));
7256 e = ::semantic(e, sc);
7257 resolveExp(e, pt, pe, ps);
7258 }
7259 }
7260 if (*pt)
7261 (*pt) = (*pt)->addMod(mod);
7262 inuse--;
7263 return;
7264}
7265
7266Type *TypeTypeof::semantic(Loc loc, Scope *sc)
7267{
7268 //printf("TypeTypeof::semantic() %s\n", toChars());
7269
7270 Expression *e;
7271 Type *t;
7272 Dsymbol *s;
7273 resolve(loc, sc, &e, &t, &s);
7274 if (s && (t = s->getType()) != NULL)
7275 t = t->addMod(mod);
7276 if (!t)
7277 {
7278 error(loc, "%s is used as a type", toChars());
7279 t = Type::terror;
7280 }
7281 return t;
7282}
7283
7284d_uns64 TypeTypeof::size(Loc loc)
7285{
7286 if (exp->type)
7287 return exp->type->size(loc);
7288 else
7289 return TypeQualified::size(loc);
7290}
7291
7292
7293
7294/***************************** TypeReturn *****************************/
7295
7296TypeReturn::TypeReturn(Loc loc)
7297 : TypeQualified(Treturn, loc)
7298{
7299}
7300
7301const char *TypeReturn::kind()
7302{
7303 return "return";
7304}
7305
7306Type *TypeReturn::syntaxCopy()
7307{
7308 TypeReturn *t = new TypeReturn(loc);
7309 t->syntaxCopyHelper(this);
7310 t->mod = mod;
7311 return t;
7312}
7313
7314Dsymbol *TypeReturn::toDsymbol(Scope *sc)
7315{
7316 Expression *e;
7317 Type *t;
7318 Dsymbol *s;
7319 resolve(loc, sc, &e, &t, &s);
7320
7321 return s;
7322}
7323
7324void TypeReturn::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
7325{
7326 *pe = NULL;
7327 *pt = NULL;
7328 *ps = NULL;
7329
7330 //printf("TypeReturn::resolve(sc = %p, idents = '%s')\n", sc, toChars());
7331 Type *t;
7332 {
7333 FuncDeclaration *func = sc->func;
7334 if (!func)
7335 {
7336 error(loc, "typeof(return) must be inside function");
7337 goto Lerr;
7338 }
7339 if (func->fes)
7340 func = func->fes->func;
7341
7342 t = func->type->nextOf();
7343 if (!t)
7344 {
7345 error(loc, "cannot use typeof(return) inside function %s with inferred return type", sc->func->toChars());
7346 goto Lerr;
7347 }
7348 }
7349 if (idents.dim == 0)
7350 *pt = t;
7351 else
7352 {
7353 if (Dsymbol *s = t->toDsymbol(sc))
7354 resolveHelper(loc, sc, s, NULL, pe, pt, ps, intypeid);
7355 else
7356 {
7357 Expression *e = typeToExpressionHelper(this, new TypeExp(loc, t));
7358 e = ::semantic(e, sc);
7359 resolveExp(e, pt, pe, ps);
7360 }
7361 }
7362 if (*pt)
7363 (*pt) = (*pt)->addMod(mod);
7364 return;
7365
7366Lerr:
7367 *pt = Type::terror;
7368 return;
7369}
7370
7371Type *TypeReturn::semantic(Loc loc, Scope *sc)
7372{
7373 //printf("TypeReturn::semantic() %s\n", toChars());
7374
7375 Expression *e;
7376 Type *t;
7377 Dsymbol *s;
7378 resolve(loc, sc, &e, &t, &s);
7379 if (s && (t = s->getType()) != NULL)
7380 t = t->addMod(mod);
7381 if (!t)
7382 {
7383 error(loc, "%s is used as a type", toChars());
7384 t = Type::terror;
7385 }
7386 return t;
7387}
7388
7389/***************************** TypeEnum *****************************/
7390
7391TypeEnum::TypeEnum(EnumDeclaration *sym)
7392 : Type(Tenum)
7393{
7394 this->sym = sym;
7395}
7396
7397const char *TypeEnum::kind()
7398{
7399 return "enum";
7400}
7401
7402Type *TypeEnum::syntaxCopy()
7403{
7404 return this;
7405}
7406
7407Type *TypeEnum::semantic(Loc, Scope *)
7408{
7409 //printf("TypeEnum::semantic() %s\n", toChars());
7410 if (deco)
7411 return this;
7412 return merge();
7413}
7414
7415d_uns64 TypeEnum::size(Loc loc)
7416{
7417 return sym->getMemtype(loc)->size(loc);
7418}
7419
7420unsigned TypeEnum::alignsize()
7421{
7422 Type *t = sym->getMemtype(Loc());
7423 if (t->ty == Terror)
7424 return 4;
7425 return t->alignsize();
7426}
7427
7428Dsymbol *TypeEnum::toDsymbol(Scope *)
7429{
7430 return sym;
7431}
7432
7433Type *TypeEnum::toBasetype()
7434{
7435 if (!sym->members && !sym->memtype)
7436 return this;
7437 Type *tb = sym->getMemtype(Loc())->toBasetype();
7438 return tb->castMod(mod); // retain modifier bits from 'this'
7439}
7440
7441Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
7442{
7443 // Bugzilla 14010
7444 if (ident == Id::_mangleof)
7445 return getProperty(e->loc, ident, flag & 1);
7446
081f759d 7447 if (sym->semanticRun < PASSsemanticdone)
7448 sym->semantic(NULL);
03385ed3 7449 if (!sym->members)
7450 {
7451 if (sym->isSpecial())
7452 {
7453 /* Special enums forward to the base type
7454 */
7455 e = sym->memtype->dotExp(sc, e, ident, flag);
7456 }
7457 else if (!(flag & 1))
7458 {
7459 sym->error("is forward referenced when looking for '%s'", ident->toChars());
7460 e = new ErrorExp();
7461 }
7462 else
7463 e = NULL;
7464 return e;
7465 }
7466
7467 Dsymbol *s = sym->search(e->loc, ident);
7468 if (!s)
7469 {
7470 if (ident == Id::max ||
7471 ident == Id::min ||
7472 ident == Id::_init)
7473 {
7474 return getProperty(e->loc, ident, flag & 1);
7475 }
7476 Expression *res = sym->getMemtype(Loc())->dotExp(sc, e, ident, 1);
7477 if (!(flag & 1) && !res)
7478 {
7479 if (Dsymbol *ns = sym->search_correct(ident))
7480 e->error("no property '%s' for type '%s'. Did you mean '%s.%s' ?",
7481 ident->toChars(), toChars(), toChars(), ns->toChars());
7482 else
7483 e->error("no property '%s' for type '%s'",
7484 ident->toChars(), toChars());
7485
7486 return new ErrorExp();
7487 }
7488 return res;
7489 }
7490 EnumMember *m = s->isEnumMember();
7491 return m->getVarExp(e->loc, sc);
7492}
7493
7494Expression *TypeEnum::getProperty(Loc loc, Identifier *ident, int flag)
7495{
7496 Expression *e;
7497 if (ident == Id::max || ident == Id::min)
7498 {
7499 return sym->getMaxMinValue(loc, ident);
7500 }
7501 else if (ident == Id::_init)
7502 {
7503 e = defaultInitLiteral(loc);
7504 }
7505 else if (ident == Id::stringof)
7506 {
7507 const char *s = toChars();
7508 e = new StringExp(loc, const_cast<char *>(s), strlen(s));
7509 Scope sc;
7510 e = ::semantic(e, &sc);
7511 }
7512 else if (ident == Id::_mangleof)
7513 {
7514 e = Type::getProperty(loc, ident, flag);
7515 }
7516 else
7517 {
7518 e = toBasetype()->getProperty(loc, ident, flag);
7519 }
7520 return e;
7521}
7522
7523bool TypeEnum::isintegral()
7524{
7525 return sym->getMemtype(Loc())->isintegral();
7526}
7527
7528bool TypeEnum::isfloating()
7529{
7530 return sym->getMemtype(Loc())->isfloating();
7531}
7532
7533bool TypeEnum::isreal()
7534{
7535 return sym->getMemtype(Loc())->isreal();
7536}
7537
7538bool TypeEnum::isimaginary()
7539{
7540 return sym->getMemtype(Loc())->isimaginary();
7541}
7542
7543bool TypeEnum::iscomplex()
7544{
7545 return sym->getMemtype(Loc())->iscomplex();
7546}
7547
7548bool TypeEnum::isunsigned()
7549{
7550 return sym->getMemtype(Loc())->isunsigned();
7551}
7552
7553bool TypeEnum::isscalar()
7554{
7555 return sym->getMemtype(Loc())->isscalar();
7556}
7557
7558bool TypeEnum::isString()
7559{
7560 return sym->getMemtype(Loc())->isString();
7561}
7562
7563bool TypeEnum::isAssignable()
7564{
7565 return sym->getMemtype(Loc())->isAssignable();
7566}
7567
7568bool TypeEnum::isBoolean()
7569{
7570 return sym->getMemtype(Loc())->isBoolean();
7571}
7572
7573bool TypeEnum::needsDestruction()
7574{
7575 return sym->getMemtype(Loc())->needsDestruction();
7576}
7577
7578bool TypeEnum::needsNested()
7579{
7580 return sym->getMemtype(Loc())->needsNested();
7581}
7582
7583MATCH TypeEnum::implicitConvTo(Type *to)
7584{
7585 MATCH m;
7586
7587 //printf("TypeEnum::implicitConvTo()\n");
7588 if (ty == to->ty && sym == ((TypeEnum *)to)->sym)
7589 m = (mod == to->mod) ? MATCHexact : MATCHconst;
7590 else if (sym->getMemtype(Loc())->implicitConvTo(to))
7591 m = MATCHconvert; // match with conversions
7592 else
7593 m = MATCHnomatch; // no match
7594 return m;
7595}
7596
7597MATCH TypeEnum::constConv(Type *to)
7598{
7599 if (equals(to))
7600 return MATCHexact;
7601 if (ty == to->ty && sym == ((TypeEnum *)to)->sym &&
7602 MODimplicitConv(mod, to->mod))
7603 return MATCHconst;
7604 return MATCHnomatch;
7605}
7606
7607
7608Expression *TypeEnum::defaultInit(Loc loc)
7609{
7610 // Initialize to first member of enum
7611 Expression *e = sym->getDefaultValue(loc);
7612 e = e->copy();
7613 e->loc = loc;
7614 e->type = this; // to deal with const, immutable, etc., variants
7615 return e;
7616}
7617
7618bool TypeEnum::isZeroInit(Loc loc)
7619{
7620 return sym->getDefaultValue(loc)->isBool(false);
7621}
7622
7623bool TypeEnum::hasPointers()
7624{
7625 return sym->getMemtype(Loc())->hasPointers();
7626}
7627
7628bool TypeEnum::hasVoidInitPointers()
7629{
7630 return sym->getMemtype(Loc())->hasVoidInitPointers();
7631}
7632
7633Type *TypeEnum::nextOf()
7634{
7635 return sym->getMemtype(Loc())->nextOf();
7636}
7637
7638/***************************** TypeStruct *****************************/
7639
7640TypeStruct::TypeStruct(StructDeclaration *sym)
7641 : Type(Tstruct)
7642{
7643 this->sym = sym;
7644 this->att = RECfwdref;
7645 this->cppmangle = CPPMANGLEdefault;
7646}
7647
7648TypeStruct *TypeStruct::create(StructDeclaration *sym)
7649{
7650 return new TypeStruct(sym);
7651}
7652
7653const char *TypeStruct::kind()
7654{
7655 return "struct";
7656}
7657
7658Type *TypeStruct::syntaxCopy()
7659{
7660 return this;
7661}
7662
7663Type *TypeStruct::semantic(Loc, Scope *sc)
7664{
7665 //printf("TypeStruct::semantic('%s')\n", sym->toChars());
7666 if (deco)
7667 {
7668 if (sc && sc->cppmangle != CPPMANGLEdefault)
7669 {
7670 if (this->cppmangle == CPPMANGLEdefault)
7671 this->cppmangle = sc->cppmangle;
7672 else
7673 assert(this->cppmangle == sc->cppmangle);
7674 }
7675 return this;
7676 }
7677
7678 /* Don't semantic for sym because it should be deferred until
7679 * sizeof needed or its members accessed.
7680 */
7681 // instead, parent should be set correctly
7682 assert(sym->parent);
7683
7684 if (sym->type->ty == Terror)
7685 return Type::terror;
7686 if (sc)
7687 this->cppmangle = sc->cppmangle;
7688 return merge();
7689}
7690
7691d_uns64 TypeStruct::size(Loc loc)
7692{
7693 return sym->size(loc);
7694}
7695
7696unsigned TypeStruct::alignsize()
7697{
7698 sym->size(Loc()); // give error for forward references
7699 return sym->alignsize;
7700}
7701
7702Dsymbol *TypeStruct::toDsymbol(Scope *)
7703{
7704 return sym;
7705}
7706
7707static Dsymbol *searchSymStruct(Scope *sc, Dsymbol *sym, Expression *e, Identifier *ident)
7708{
7709 int flags = sc->flags & SCOPEignoresymbolvisibility ? IgnoreSymbolVisibility : 0;
7710 Dsymbol *sold = NULL;
7711 if (global.params.bug10378 || global.params.check10378)
7712 {
7713 sold = sym->search(e->loc, ident, flags);
7714 if (!global.params.check10378)
7715 return sold;
7716 }
7717
7718 Dsymbol *s = sym->search(e->loc, ident, flags | SearchLocalsOnly);
7719 if (global.params.check10378)
7720 {
7721 Dsymbol *snew = s;
7722 if (sold != snew)
7723 Scope::deprecation10378(e->loc, sold, snew);
7724 if (global.params.bug10378)
7725 s = sold;
7726 }
7727 return s;
7728}
7729
7730Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
7731{
7732 Dsymbol *s;
7733
7734 assert(e->op != TOKdot);
7735
7736 // Bugzilla 14010
7737 if (ident == Id::_mangleof)
7738 return getProperty(e->loc, ident, flag & 1);
7739
7740 /* If e.tupleof
7741 */
7742 if (ident == Id::_tupleof)
7743 {
7744 /* Create a TupleExp out of the fields of the struct e:
7745 * (e.field0, e.field1, e.field2, ...)
7746 */
7747 e = ::semantic(e, sc); // do this before turning on noaccesscheck
7748
7749 sym->size(e->loc); // do semantic of type
7750
7751 Expression *e0 = NULL;
7752 Expression *ev = e->op == TOKtype ? NULL : e;
7753 if (ev)
7754 ev = extractSideEffect(sc, "__tup", &e0, ev);
7755
7756 Expressions *exps = new Expressions;
7757 exps->reserve(sym->fields.dim);
7758 for (size_t i = 0; i < sym->fields.dim; i++)
7759 {
7760 VarDeclaration *v = sym->fields[i];
7761 Expression *ex;
7762 if (ev)
7763 ex = new DotVarExp(e->loc, ev, v);
7764 else
7765 {
7766 ex = new VarExp(e->loc, v);
7767 ex->type = ex->type->addMod(e->type->mod);
7768 }
7769 exps->push(ex);
7770 }
7771
7772 e = new TupleExp(e->loc, e0, exps);
7773 Scope *sc2 = sc->push();
7774 sc2->flags = sc->flags | SCOPEnoaccesscheck;
7775 e = ::semantic(e, sc2);
7776 sc2->pop();
7777 return e;
7778 }
7779
7780 s = searchSymStruct(sc, sym, e, ident);
7781L1:
7782 if (!s)
7783 {
7784 return noMember(sc, e, ident, flag);
7785 }
7786 if (!(sc->flags & SCOPEignoresymbolvisibility) && !symbolIsVisible(sc, s))
7787 {
7788 ::deprecation(e->loc, "%s is not visible from module %s", s->toPrettyChars(), sc->_module->toPrettyChars());
7789 // return noMember(sc, e, ident, flag);
7790 }
7791 if (!s->isFuncDeclaration()) // because of overloading
7792 s->checkDeprecated(e->loc, sc);
7793 s = s->toAlias();
7794
7795 EnumMember *em = s->isEnumMember();
7796 if (em)
7797 {
7798 return em->getVarExp(e->loc, sc);
7799 }
7800
7801 if (VarDeclaration *v = s->isVarDeclaration())
7802 {
7803 if (!v->type ||
7804 (!v->type->deco && v->inuse))
7805 {
7806 if (v->inuse) // Bugzilla 9494
7807 e->error("circular reference to %s '%s'", v->kind(), v->toPrettyChars());
7808 else
7809 e->error("forward reference to %s '%s'", v->kind(), v->toPrettyChars());
7810 return new ErrorExp();
7811 }
7812 if (v->type->ty == Terror)
7813 return new ErrorExp();
7814
7815 if ((v->storage_class & STCmanifest) && v->_init)
7816 {
7817 if (v->inuse)
7818 {
7819 e->error("circular initialization of %s '%s'", v->kind(), v->toPrettyChars());
7820 return new ErrorExp();
7821 }
7822 checkAccess(e->loc, sc, NULL, v);
7823 Expression *ve = new VarExp(e->loc, v);
7824 ve = ::semantic(ve, sc);
7825 return ve;
7826 }
7827 }
7828
7829 if (Type *t = s->getType())
7830 {
7831 return ::semantic(new TypeExp(e->loc, t), sc);
7832 }
7833
7834 TemplateMixin *tm = s->isTemplateMixin();
7835 if (tm)
7836 {
7837 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
7838 de->type = e->type;
7839 return de;
7840 }
7841
7842 TemplateDeclaration *td = s->isTemplateDeclaration();
7843 if (td)
7844 {
7845 if (e->op == TOKtype)
7846 e = new TemplateExp(e->loc, td);
7847 else
7848 e = new DotTemplateExp(e->loc, e, td);
7849 e = ::semantic(e, sc);
7850 return e;
7851 }
7852
7853 TemplateInstance *ti = s->isTemplateInstance();
7854 if (ti)
7855 {
7856 if (!ti->semanticRun)
7857 {
7858 ti->semantic(sc);
7859 if (!ti->inst || ti->errors) // if template failed to expand
7860 return new ErrorExp();
7861 }
7862 s = ti->inst->toAlias();
7863 if (!s->isTemplateInstance())
7864 goto L1;
7865 if (e->op == TOKtype)
7866 e = new ScopeExp(e->loc, ti);
7867 else
7868 e = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
7869 return ::semantic(e, sc);
7870 }
7871
7872 if (s->isImport() || s->isModule() || s->isPackage())
7873 {
7874 e = ::resolve(e->loc, sc, s, false);
7875 return e;
7876 }
7877
7878 OverloadSet *o = s->isOverloadSet();
7879 if (o)
7880 {
7881 OverExp *oe = new OverExp(e->loc, o);
7882 if (e->op == TOKtype)
7883 return oe;
7884 return new DotExp(e->loc, e, oe);
7885 }
7886
7887 Declaration *d = s->isDeclaration();
7888 if (!d)
7889 {
7890 e->error("%s.%s is not a declaration", e->toChars(), ident->toChars());
7891 return new ErrorExp();
7892 }
7893
7894 if (e->op == TOKtype)
7895 {
7896 /* It's:
7897 * Struct.d
7898 */
7899 if (TupleDeclaration *tup = d->isTupleDeclaration())
7900 {
7901 e = new TupleExp(e->loc, tup);
7902 e = ::semantic(e, sc);
7903 return e;
7904 }
7905 if (d->needThis() && sc->intypeof != 1)
7906 {
7907 /* Rewrite as:
7908 * this.d
7909 */
7910 if (hasThis(sc))
7911 {
7912 e = new DotVarExp(e->loc, new ThisExp(e->loc), d);
7913 e = ::semantic(e, sc);
7914 return e;
7915 }
7916 }
081f759d 7917 if (d->semanticRun == PASSinit)
7918 d->semantic(NULL);
03385ed3 7919 checkAccess(e->loc, sc, e, d);
7920 VarExp *ve = new VarExp(e->loc, d);
7921 if (d->isVarDeclaration() && d->needThis())
7922 ve->type = d->type->addMod(e->type->mod);
7923 return ve;
7924 }
7925
7926 bool unreal = e->op == TOKvar && ((VarExp *)e)->var->isField();
7927 if (d->isDataseg() || (unreal && d->isField()))
7928 {
7929 // (e, d)
7930 checkAccess(e->loc, sc, e, d);
7931 Expression *ve = new VarExp(e->loc, d);
7932 e = unreal ? ve : new CommaExp(e->loc, e, ve);
7933 e = ::semantic(e, sc);
7934 return e;
7935 }
7936
7937 e = new DotVarExp(e->loc, e, d);
7938 e = ::semantic(e, sc);
7939 return e;
7940}
7941
7942structalign_t TypeStruct::alignment()
7943{
7944 if (sym->alignment == 0)
7945 sym->size(sym->loc);
7946 return sym->alignment;
7947}
7948
7949Expression *TypeStruct::defaultInit(Loc)
7950{
7951 Declaration *d = new SymbolDeclaration(sym->loc, sym);
7952 assert(d);
7953 d->type = this;
7954 d->storage_class |= STCrvalue; // Bugzilla 14398
7955 return new VarExp(sym->loc, d);
7956}
7957
7958/***************************************
7959 * Use when we prefer the default initializer to be a literal,
7960 * rather than a global immutable variable.
7961 */
7962Expression *TypeStruct::defaultInitLiteral(Loc loc)
7963{
7964 sym->size(loc);
7965 if (sym->sizeok != SIZEOKdone)
7966 return new ErrorExp();
7967 Expressions *structelems = new Expressions();
7968 structelems->setDim(sym->fields.dim - sym->isNested());
7969 unsigned offset = 0;
7970 for (size_t j = 0; j < structelems->dim; j++)
7971 {
7972 VarDeclaration *vd = sym->fields[j];
7973 Expression *e;
7974 if (vd->inuse)
7975 {
7976 error(loc, "circular reference to '%s'", vd->toPrettyChars());
7977 return new ErrorExp();
7978 }
7979 if (vd->offset < offset || vd->type->size() == 0)
7980 e = NULL;
7981 else if (vd->_init)
7982 {
7983 if (vd->_init->isVoidInitializer())
7984 e = NULL;
7985 else
7986 e = vd->getConstInitializer(false);
7987 }
7988 else
7989 e = vd->type->defaultInitLiteral(loc);
7990 if (e && e->op == TOKerror)
7991 return e;
7992 if (e)
7993 offset = vd->offset + (unsigned)vd->type->size();
7994 (*structelems)[j] = e;
7995 }
7996 StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems);
7997
7998 /* Copy from the initializer symbol for larger symbols,
7999 * otherwise the literals expressed as code get excessively large.
8000 */
8001 if (size(loc) > Target::ptrsize * 4U && !needsNested())
8002 structinit->useStaticInit = true;
8003
8004 structinit->type = this;
8005 return structinit;
8006}
8007
8008
8009bool TypeStruct::isZeroInit(Loc)
8010{
8011 return sym->zeroInit != 0;
8012}
8013
8014bool TypeStruct::isBoolean()
8015{
8016 return false;
8017}
8018
8019bool TypeStruct::needsDestruction()
8020{
8021 return sym->dtor != NULL;
8022}
8023
8024bool TypeStruct::needsNested()
8025{
8026 if (sym->isNested())
8027 return true;
8028
8029 for (size_t i = 0; i < sym->fields.dim; i++)
8030 {
8031 VarDeclaration *v = sym->fields[i];
8032 if (!v->isDataseg() && v->type->needsNested())
8033 return true;
8034 }
8035 return false;
8036}
8037
8038bool TypeStruct::isAssignable()
8039{
8040 bool assignable = true;
8041 unsigned offset = ~0; // dead-store initialize to prevent spurious warning
8042
8043 /* If any of the fields are const or immutable,
8044 * then one cannot assign this struct.
8045 */
8046 for (size_t i = 0; i < sym->fields.dim; i++)
8047 {
8048 VarDeclaration *v = sym->fields[i];
8049 //printf("%s [%d] v = (%s) %s, v->offset = %d, v->parent = %s", sym->toChars(), i, v->kind(), v->toChars(), v->offset, v->parent->kind());
8050 if (i == 0)
8051 ;
8052 else if (v->offset == offset)
8053 {
8054 /* If any fields of anonymous union are assignable,
8055 * then regard union as assignable.
8056 * This is to support unsafe things like Rebindable templates.
8057 */
8058 if (assignable)
8059 continue;
8060 }
8061 else
8062 {
8063 if (!assignable)
8064 return false;
8065 }
8066 assignable = v->type->isMutable() && v->type->isAssignable();
8067 offset = v->offset;
8068 //printf(" -> assignable = %d\n", assignable);
8069 }
8070
8071 return assignable;
8072}
8073
8074bool TypeStruct::hasPointers()
8075{
8076 // Probably should cache this information in sym rather than recompute
8077 StructDeclaration *s = sym;
8078
8079 sym->size(Loc()); // give error for forward references
8080 for (size_t i = 0; i < s->fields.dim; i++)
8081 {
8082 Declaration *d = s->fields[i];
8083 if (d->storage_class & STCref || d->hasPointers())
8084 return true;
8085 }
8086 return false;
8087}
8088
8089bool TypeStruct::hasVoidInitPointers()
8090{
8091 // Probably should cache this information in sym rather than recompute
8092 StructDeclaration *s = sym;
8093
8094 sym->size(Loc()); // give error for forward references
8095 for (size_t i = 0; i < s->fields.dim; i++)
8096 {
8097 VarDeclaration *v = s->fields[i];
8098 if (v->_init && v->_init->isVoidInitializer() && v->type->hasPointers())
8099 return true;
8100 if (!v->_init && v->type->hasVoidInitPointers())
8101 return true;
8102 }
8103 return false;
8104}
8105
8106MATCH TypeStruct::implicitConvTo(Type *to)
8107{ MATCH m;
8108
8109 //printf("TypeStruct::implicitConvTo(%s => %s)\n", toChars(), to->toChars());
8110
8111 if (ty == to->ty && sym == ((TypeStruct *)to)->sym)
8112 {
8113 m = MATCHexact; // exact match
8114 if (mod != to->mod)
8115 {
8116 m = MATCHconst;
8117 if (MODimplicitConv(mod, to->mod))
8118 ;
8119 else
8120 {
8121 /* Check all the fields. If they can all be converted,
8122 * allow the conversion.
8123 */
8124 unsigned offset = ~0; // dead-store to prevent spurious warning
8125 for (size_t i = 0; i < sym->fields.dim; i++)
8126 {
8127 VarDeclaration *v = sym->fields[i];
8128 if (i == 0)
8129 ;
8130 else if (v->offset == offset)
8131 {
8132 if (m > MATCHnomatch)
8133 continue;
8134 }
8135 else
8136 {
8137 if (m <= MATCHnomatch)
8138 return m;
8139 }
8140
8141 // 'from' type
8142 Type *tvf = v->type->addMod(mod);
8143
8144 // 'to' type
8145 Type *tv = v->type->addMod(to->mod);
8146
8147 // field match
8148 MATCH mf = tvf->implicitConvTo(tv);
8149 //printf("\t%s => %s, match = %d\n", v->type->toChars(), tv->toChars(), mf);
8150
8151 if (mf <= MATCHnomatch)
8152 return mf;
8153 if (mf < m) // if field match is worse
8154 m = mf;
8155 offset = v->offset;
8156 }
8157 }
8158 }
8159 }
8160 else if (sym->aliasthis && !(att & RECtracing))
8161 {
8162 att = (AliasThisRec)(att | RECtracing);
8163 m = aliasthisOf()->implicitConvTo(to);
8164 att = (AliasThisRec)(att & ~RECtracing);
8165 }
8166 else
8167 m = MATCHnomatch; // no match
8168 return m;
8169}
8170
8171MATCH TypeStruct::constConv(Type *to)
8172{
8173 if (equals(to))
8174 return MATCHexact;
8175 if (ty == to->ty && sym == ((TypeStruct *)to)->sym &&
8176 MODimplicitConv(mod, to->mod))
8177 return MATCHconst;
8178 return MATCHnomatch;
8179}
8180
8181unsigned char TypeStruct::deduceWild(Type *t, bool isRef)
8182{
8183 if (ty == t->ty && sym == ((TypeStruct *)t)->sym)
8184 return Type::deduceWild(t, isRef);
8185
8186 unsigned char wm = 0;
8187
8188 if (t->hasWild() && sym->aliasthis && !(att & RECtracing))
8189 {
8190 att = (AliasThisRec)(att | RECtracing);
8191 wm = aliasthisOf()->deduceWild(t, isRef);
8192 att = (AliasThisRec)(att & ~RECtracing);
8193 }
8194
8195 return wm;
8196}
8197
8198Type *TypeStruct::toHeadMutable()
8199{
8200 return this;
8201}
8202
8203
8204/***************************** TypeClass *****************************/
8205
8206TypeClass::TypeClass(ClassDeclaration *sym)
8207 : Type(Tclass)
8208{
8209 this->sym = sym;
8210 this->att = RECfwdref;
8211 this->cppmangle = CPPMANGLEdefault;
8212}
8213
8214const char *TypeClass::kind()
8215{
8216 return "class";
8217}
8218
8219Type *TypeClass::syntaxCopy()
8220{
8221 return this;
8222}
8223
8224Type *TypeClass::semantic(Loc, Scope *sc)
8225{
8226 //printf("TypeClass::semantic(%s)\n", sym->toChars());
8227 if (deco)
8228 {
8229 if (sc && sc->cppmangle != CPPMANGLEdefault)
8230 {
8231 if (this->cppmangle == CPPMANGLEdefault)
8232 this->cppmangle = sc->cppmangle;
8233 else
8234 assert(this->cppmangle == sc->cppmangle);
8235 }
8236 return this;
8237 }
8238
8239 /* Don't semantic for sym because it should be deferred until
8240 * sizeof needed or its members accessed.
8241 */
8242 // instead, parent should be set correctly
8243 assert(sym->parent);
8244
8245 if (sym->type->ty == Terror)
8246 return Type::terror;
8247 if (sc)
8248 this->cppmangle = sc->cppmangle;
8249 return merge();
8250}
8251
8252d_uns64 TypeClass::size(Loc)
8253{
8254 return Target::ptrsize;
8255}
8256
8257Dsymbol *TypeClass::toDsymbol(Scope *)
8258{
8259 return sym;
8260}
8261
8262static Dsymbol *searchSymClass(Scope *sc, Dsymbol *sym, Expression *e, Identifier *ident)
8263{
8264 int flags = sc->flags & SCOPEignoresymbolvisibility ? IgnoreSymbolVisibility : 0;
8265 Dsymbol *sold = NULL;
8266 if (global.params.bug10378 || global.params.check10378)
8267 {
8268 sold = sym->search(e->loc, ident, flags | IgnoreSymbolVisibility);
8269 if (!global.params.check10378)
8270 return sold;
8271 }
8272
8273 Dsymbol *s = sym->search(e->loc, ident, flags | SearchLocalsOnly);
8274 if (!s && !(flags & IgnoreSymbolVisibility))
8275 {
8276 s = sym->search(e->loc, ident, flags | SearchLocalsOnly | IgnoreSymbolVisibility);
8277 if (s && !(flags & IgnoreErrors))
8278 ::deprecation(e->loc, "%s is not visible from class %s", s->toPrettyChars(), sym->toChars());
8279 }
8280 if (global.params.check10378)
8281 {
8282 Dsymbol *snew = s;
8283 if (sold != snew)
8284 Scope::deprecation10378(e->loc, sold, snew);
8285 if (global.params.bug10378)
8286 s = sold;
8287 }
8288 return s;
8289}
8290
8291Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident, int flag)
8292{
8293 Dsymbol *s;
8294 assert(e->op != TOKdot);
8295
8296 // Bugzilla 12543
8297 if (ident == Id::__sizeof || ident == Id::__xalignof || ident == Id::_mangleof)
8298 {
8299 return Type::getProperty(e->loc, ident, 0);
8300 }
8301
8302 /* If e.tupleof
8303 */
8304 if (ident == Id::_tupleof)
8305 {
8306 /* Create a TupleExp
8307 */
8308 e = ::semantic(e, sc); // do this before turning on noaccesscheck
8309
8310 sym->size(e->loc); // do semantic of type
8311
8312 Expression *e0 = NULL;
8313 Expression *ev = e->op == TOKtype ? NULL : e;
8314 if (ev)
8315 ev = extractSideEffect(sc, "__tup", &e0, ev);
8316
8317 Expressions *exps = new Expressions;
8318 exps->reserve(sym->fields.dim);
8319 for (size_t i = 0; i < sym->fields.dim; i++)
8320 {
8321 VarDeclaration *v = sym->fields[i];
8322 // Don't include hidden 'this' pointer
8323 if (v->isThisDeclaration())
8324 continue;
8325 Expression *ex;
8326 if (ev)
8327 ex = new DotVarExp(e->loc, ev, v);
8328 else
8329 {
8330 ex = new VarExp(e->loc, v);
8331 ex->type = ex->type->addMod(e->type->mod);
8332 }
8333 exps->push(ex);
8334 }
8335
8336 e = new TupleExp(e->loc, e0, exps);
8337 Scope *sc2 = sc->push();
8338 sc2->flags = sc->flags | SCOPEnoaccesscheck;
8339 e = ::semantic(e, sc2);
8340 sc2->pop();
8341 return e;
8342 }
8343
8344 s = searchSymClass(sc, sym, e, ident);
8345L1:
8346 if (!s)
8347 {
8348 // See if it's 'this' class or a base class
8349 if (sym->ident == ident)
8350 {
8351 if (e->op == TOKtype)
8352 return Type::getProperty(e->loc, ident, 0);
8353 e = new DotTypeExp(e->loc, e, sym);
8354 e = ::semantic(e, sc);
8355 return e;
8356 }
8357 if (ClassDeclaration *cbase = sym->searchBase(ident))
8358 {
8359 if (e->op == TOKtype)
8360 return Type::getProperty(e->loc, ident, 0);
8361 if (InterfaceDeclaration *ifbase = cbase->isInterfaceDeclaration())
8362 e = new CastExp(e->loc, e, ifbase->type);
8363 else
8364 e = new DotTypeExp(e->loc, e, cbase);
8365 e = ::semantic(e, sc);
8366 return e;
8367 }
8368
8369 if (ident == Id::classinfo)
8370 {
985afcab 8371 if (!Type::typeinfoclass)
8372 {
8373 error(e->loc, "`object.TypeInfo_Class` could not be found, but is implicitly used");
8374 return new ErrorExp();
8375 }
8376
03385ed3 8377 Type *t = Type::typeinfoclass->type;
8378 if (e->op == TOKtype || e->op == TOKdottype)
8379 {
8380 /* For type.classinfo, we know the classinfo
8381 * at compile time.
8382 */
8383 if (!sym->vclassinfo)
8384 sym->vclassinfo = new TypeInfoClassDeclaration(sym->type);
8385 e = new VarExp(e->loc, sym->vclassinfo);
8386 e = e->addressOf();
8387 e->type = t; // do this so we don't get redundant dereference
8388 }
8389 else
8390 {
8391 /* For class objects, the classinfo reference is the first
8392 * entry in the vtbl[]
8393 */
8394 e = new PtrExp(e->loc, e);
8395 e->type = t->pointerTo();
8396 if (sym->isInterfaceDeclaration())
8397 {
8398 if (sym->isCPPinterface())
8399 {
8400 /* C++ interface vtbl[]s are different in that the
8401 * first entry is always pointer to the first virtual
8402 * function, not classinfo.
8403 * We can't get a .classinfo for it.
8404 */
8405 error(e->loc, "no .classinfo for C++ interface objects");
8406 }
8407 /* For an interface, the first entry in the vtbl[]
8408 * is actually a pointer to an instance of struct Interface.
8409 * The first member of Interface is the .classinfo,
8410 * so add an extra pointer indirection.
8411 */
8412 e->type = e->type->pointerTo();
8413 e = new PtrExp(e->loc, e);
8414 e->type = t->pointerTo();
8415 }
8416 e = new PtrExp(e->loc, e, t);
8417 }
8418 return e;
8419 }
8420
8421 if (ident == Id::__vptr)
8422 {
8423 /* The pointer to the vtbl[]
8424 * *cast(immutable(void*)**)e
8425 */
8426 e = e->castTo(sc, tvoidptr->immutableOf()->pointerTo()->pointerTo());
8427 e = new PtrExp(e->loc, e);
8428 e = ::semantic(e, sc);
8429 return e;
8430 }
8431
8432 if (ident == Id::__monitor)
8433 {
8434 /* The handle to the monitor (call it a void*)
8435 * *(cast(void**)e + 1)
8436 */
8437 e = e->castTo(sc, tvoidptr->pointerTo());
8438 e = new AddExp(e->loc, e, new IntegerExp(1));
8439 e = new PtrExp(e->loc, e);
8440 e = ::semantic(e, sc);
8441 return e;
8442 }
8443
8444 if (ident == Id::outer && sym->vthis)
8445 {
081f759d 8446 if (sym->vthis->semanticRun == PASSinit)
03385ed3 8447 sym->vthis->semantic(NULL);
8448
8449 if (ClassDeclaration *cdp = sym->toParent2()->isClassDeclaration())
8450 {
8451 DotVarExp *dve = new DotVarExp(e->loc, e, sym->vthis);
8452 dve->type = cdp->type->addMod(e->type->mod);
8453 return dve;
8454 }
8455
8456 /* Bugzilla 15839: Find closest parent class through nested functions.
8457 */
8458 for (Dsymbol *p = sym->toParent2(); p; p = p->toParent2())
8459 {
8460 FuncDeclaration *fd = p->isFuncDeclaration();
8461 if (!fd)
8462 break;
8463 if (fd->isNested())
8464 continue;
8465 AggregateDeclaration *ad = fd->isThis();
8466 if (!ad)
8467 break;
8468 if (ad->isClassDeclaration())
8469 {
8470 ThisExp *ve = new ThisExp(e->loc);
8471
8472 ve->var = fd->vthis;
8473 const bool nestedError = fd->vthis->checkNestedReference(sc, e->loc);
8474 assert(!nestedError);
8475
8476 ve->type = fd->vthis->type->addMod(e->type->mod);
8477 return ve;
8478 }
8479 break;
8480 }
8481
8482 // Continue to show enclosing function's frame (stack or closure).
8483 DotVarExp *dve = new DotVarExp(e->loc, e, sym->vthis);
8484 dve->type = sym->vthis->type->addMod(e->type->mod);
8485 return dve;
8486 }
8487
8488 return noMember(sc, e, ident, flag & 1);
8489 }
8490 if (!(sc->flags & SCOPEignoresymbolvisibility) && !symbolIsVisible(sc, s))
8491 {
8492 ::deprecation(e->loc, "%s is not visible from module %s", s->toPrettyChars(), sc->_module->toPrettyChars());
8493 // return noMember(sc, e, ident, flag);
8494 }
8495 if (!s->isFuncDeclaration()) // because of overloading
8496 s->checkDeprecated(e->loc, sc);
8497 s = s->toAlias();
8498
8499 EnumMember *em = s->isEnumMember();
8500 if (em)
8501 {
8502 return em->getVarExp(e->loc, sc);
8503 }
8504
8505 if (VarDeclaration *v = s->isVarDeclaration())
8506 {
8507 if (!v->type ||
8508 (!v->type->deco && v->inuse))
8509 {
8510 if (v->inuse) // Bugzilla 9494
8511 e->error("circular reference to %s '%s'", v->kind(), v->toPrettyChars());
8512 else
8513 e->error("forward reference to %s '%s'", v->kind(), v->toPrettyChars());
8514 return new ErrorExp();
8515 }
8516 if (v->type->ty == Terror)
8517 return new ErrorExp();
8518
8519 if ((v->storage_class & STCmanifest) && v->_init)
8520 {
8521 if (v->inuse)
8522 {
8523 e->error("circular initialization of %s '%s'", v->kind(), v->toPrettyChars());
8524 return new ErrorExp();
8525 }
8526 checkAccess(e->loc, sc, NULL, v);
8527 Expression *ve = new VarExp(e->loc, v);
8528 ve = ::semantic(ve, sc);
8529 return ve;
8530 }
8531 }
8532
8533 if (Type *t = s->getType())
8534 {
8535 return ::semantic(new TypeExp(e->loc, t), sc);
8536 }
8537
8538 TemplateMixin *tm = s->isTemplateMixin();
8539 if (tm)
8540 {
8541 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
8542 de->type = e->type;
8543 return de;
8544 }
8545
8546 TemplateDeclaration *td = s->isTemplateDeclaration();
8547 if (td)
8548 {
8549 if (e->op == TOKtype)
8550 e = new TemplateExp(e->loc, td);
8551 else
8552 e = new DotTemplateExp(e->loc, e, td);
8553 e = ::semantic(e, sc);
8554 return e;
8555 }
8556
8557 TemplateInstance *ti = s->isTemplateInstance();
8558 if (ti)
8559 {
8560 if (!ti->semanticRun)
8561 {
8562 ti->semantic(sc);
8563 if (!ti->inst || ti->errors) // if template failed to expand
8564 return new ErrorExp();
8565 }
8566 s = ti->inst->toAlias();
8567 if (!s->isTemplateInstance())
8568 goto L1;
8569 if (e->op == TOKtype)
8570 e = new ScopeExp(e->loc, ti);
8571 else
8572 e = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
8573 return ::semantic(e, sc);
8574 }
8575
8576 if (s->isImport() || s->isModule() || s->isPackage())
8577 {
8578 e = ::resolve(e->loc, sc, s, false);
8579 return e;
8580 }
8581
8582 OverloadSet *o = s->isOverloadSet();
8583 if (o)
8584 {
8585 OverExp *oe = new OverExp(e->loc, o);
8586 if (e->op == TOKtype)
8587 return oe;
8588 return new DotExp(e->loc, e, oe);
8589 }
8590
8591 Declaration *d = s->isDeclaration();
8592 if (!d)
8593 {
8594 e->error("%s.%s is not a declaration", e->toChars(), ident->toChars());
8595 return new ErrorExp();
8596 }
8597
8598 if (e->op == TOKtype)
8599 {
8600 /* It's:
8601 * Class.d
8602 */
8603 if (TupleDeclaration *tup = d->isTupleDeclaration())
8604 {
8605 e = new TupleExp(e->loc, tup);
8606 e = ::semantic(e, sc);
8607 return e;
8608 }
8609 if (d->needThis() && sc->intypeof != 1)
8610 {
8611 /* Rewrite as:
8612 * this.d
8613 */
8614 if (hasThis(sc))
8615 {
8616 // This is almost same as getRightThis() in expression.c
8617 Expression *e1 = new ThisExp(e->loc);
8618 e1 = ::semantic(e1, sc);
8619 L2:
8620 Type *t = e1->type->toBasetype();
8621 ClassDeclaration *cd = e->type->isClassHandle();
8622 ClassDeclaration *tcd = t->isClassHandle();
8623 if (cd && tcd && (tcd == cd || cd->isBaseOf(tcd, NULL)))
8624 {
8625 e = new DotTypeExp(e1->loc, e1, cd);
8626 e = new DotVarExp(e->loc, e, d);
8627 e = ::semantic(e, sc);
8628 return e;
8629 }
8630 if (tcd && tcd->isNested())
8631 { /* e1 is the 'this' pointer for an inner class: tcd.
8632 * Rewrite it as the 'this' pointer for the outer class.
8633 */
8634
8635 e1 = new DotVarExp(e->loc, e1, tcd->vthis);
8636 e1->type = tcd->vthis->type;
8637 e1->type = e1->type->addMod(t->mod);
8638 // Do not call checkNestedRef()
8639 //e1 = ::semantic(e1, sc);
8640
8641 // Skip up over nested functions, and get the enclosing
8642 // class type.
8643 int n = 0;
8644 for (s = tcd->toParent();
8645 s && s->isFuncDeclaration();
8646 s = s->toParent())
8647 { FuncDeclaration *f = s->isFuncDeclaration();
8648 if (f->vthis)
8649 {
8650 //printf("rewriting e1 to %s's this\n", f->toChars());
8651 n++;
8652 e1 = new VarExp(e->loc, f->vthis);
8653 }
8654 else
8655 {
8656 e = new VarExp(e->loc, d);
8657 return e;
8658 }
8659 }
8660 if (s && s->isClassDeclaration())
8661 { e1->type = s->isClassDeclaration()->type;
8662 e1->type = e1->type->addMod(t->mod);
8663 if (n > 1)
8664 e1 = ::semantic(e1, sc);
8665 }
8666 else
8667 e1 = ::semantic(e1, sc);
8668 goto L2;
8669 }
8670 }
8671 }
8672 //printf("e = %s, d = %s\n", e->toChars(), d->toChars());
081f759d 8673 if (d->semanticRun == PASSinit)
8674 d->semantic(NULL);
03385ed3 8675 checkAccess(e->loc, sc, e, d);
8676 VarExp *ve = new VarExp(e->loc, d);
8677 if (d->isVarDeclaration() && d->needThis())
8678 ve->type = d->type->addMod(e->type->mod);
8679 return ve;
8680 }
8681
8682 bool unreal = e->op == TOKvar && ((VarExp *)e)->var->isField();
8683 if (d->isDataseg() || (unreal && d->isField()))
8684 {
8685 // (e, d)
8686 checkAccess(e->loc, sc, e, d);
8687 Expression *ve = new VarExp(e->loc, d);
8688 e = unreal ? ve : new CommaExp(e->loc, e, ve);
8689 e = ::semantic(e, sc);
8690 return e;
8691 }
8692
8693 e = new DotVarExp(e->loc, e, d);
8694 e = ::semantic(e, sc);
8695 return e;
8696}
8697
8698ClassDeclaration *TypeClass::isClassHandle()
8699{
8700 return sym;
8701}
8702
8703bool TypeClass::isscope()
8704{
8705 return sym->isscope;
8706}
8707
8708bool TypeClass::isBaseOf(Type *t, int *poffset)
8709{
8710 if (t && t->ty == Tclass)
8711 {
8712 ClassDeclaration *cd = ((TypeClass *)t)->sym;
8713 if (sym->isBaseOf(cd, poffset))
8714 return true;
8715 }
8716 return false;
8717}
8718
8719MATCH TypeClass::implicitConvTo(Type *to)
8720{
8721 //printf("TypeClass::implicitConvTo(to = '%s') %s\n", to->toChars(), toChars());
8722 MATCH m = constConv(to);
8723 if (m > MATCHnomatch)
8724 return m;
8725
8726 ClassDeclaration *cdto = to->isClassHandle();
8727 if (cdto)
8728 {
8729 //printf("TypeClass::implicitConvTo(to = '%s') %s, isbase = %d %d\n", to->toChars(), toChars(), cdto->isBaseInfoComplete(), sym->isBaseInfoComplete());
081f759d 8730 if (cdto->semanticRun < PASSsemanticdone && !cdto->isBaseInfoComplete())
03385ed3 8731 cdto->semantic(NULL);
081f759d 8732 if (sym->semanticRun < PASSsemanticdone && !sym->isBaseInfoComplete())
03385ed3 8733 sym->semantic(NULL);
8734 if (cdto->isBaseOf(sym, NULL) && MODimplicitConv(mod, to->mod))
8735 {
8736 //printf("'to' is base\n");
8737 return MATCHconvert;
8738 }
8739 }
8740
8741 m = MATCHnomatch;
8742 if (sym->aliasthis && !(att & RECtracing))
8743 {
8744 att = (AliasThisRec)(att | RECtracing);
8745 m = aliasthisOf()->implicitConvTo(to);
8746 att = (AliasThisRec)(att & ~RECtracing);
8747 }
8748
8749 return m;
8750}
8751
8752MATCH TypeClass::constConv(Type *to)
8753{
8754 if (equals(to))
8755 return MATCHexact;
8756 if (ty == to->ty && sym == ((TypeClass *)to)->sym &&
8757 MODimplicitConv(mod, to->mod))
8758 return MATCHconst;
8759
8760 /* Conversion derived to const(base)
8761 */
8762 int offset = 0;
8763 if (to->isBaseOf(this, &offset) && offset == 0 &&
8764 MODimplicitConv(mod, to->mod))
8765 {
8766 // Disallow:
8767 // derived to base
8768 // inout(derived) to inout(base)
8769 if (!to->isMutable() && !to->isWild())
8770 return MATCHconvert;
8771 }
8772
8773 return MATCHnomatch;
8774}
8775
8776unsigned char TypeClass::deduceWild(Type *t, bool isRef)
8777{
8778 ClassDeclaration *cd = t->isClassHandle();
8779 if (cd && (sym == cd || cd->isBaseOf(sym, NULL)))
8780 return Type::deduceWild(t, isRef);
8781
8782 unsigned char wm = 0;
8783
8784 if (t->hasWild() && sym->aliasthis && !(att & RECtracing))
8785 {
8786 att = (AliasThisRec)(att | RECtracing);
8787 wm = aliasthisOf()->deduceWild(t, isRef);
8788 att = (AliasThisRec)(att & ~RECtracing);
8789 }
8790
8791 return wm;
8792}
8793
8794Type *TypeClass::toHeadMutable()
8795{
8796 return this;
8797}
8798
8799Expression *TypeClass::defaultInit(Loc loc)
8800{
8801 return new NullExp(loc, this);
8802}
8803
8804bool TypeClass::isZeroInit(Loc)
8805{
8806 return true;
8807}
8808
8809bool TypeClass::isBoolean()
8810{
8811 return true;
8812}
8813
8814bool TypeClass::hasPointers()
8815{
8816 return true;
8817}
8818
8819/***************************** TypeTuple *****************************/
8820
8821TypeTuple::TypeTuple(Parameters *arguments)
8822 : Type(Ttuple)
8823{
8824 //printf("TypeTuple(this = %p)\n", this);
8825 this->arguments = arguments;
8826 //printf("TypeTuple() %p, %s\n", this, toChars());
8827}
8828
8829/****************
8830 * Form TypeTuple from the types of the expressions.
8831 * Assume exps[] is already tuple expanded.
8832 */
8833
8834TypeTuple::TypeTuple(Expressions *exps)
8835 : Type(Ttuple)
8836{
8837 Parameters *arguments = new Parameters;
8838 if (exps)
8839 {
8840 arguments->setDim(exps->dim);
8841 for (size_t i = 0; i < exps->dim; i++)
8842 { Expression *e = (*exps)[i];
8843 if (e->type->ty == Ttuple)
8844 e->error("cannot form tuple of tuples");
8845 Parameter *arg = new Parameter(STCundefined, e->type, NULL, NULL);
8846 (*arguments)[i] = arg;
8847 }
8848 }
8849 this->arguments = arguments;
8850 //printf("TypeTuple() %p, %s\n", this, toChars());
8851}
8852
8853TypeTuple *TypeTuple::create(Parameters *arguments)
8854{
8855 return new TypeTuple(arguments);
8856}
8857
8858/*******************************************
8859 * Type tuple with 0, 1 or 2 types in it.
8860 */
8861TypeTuple::TypeTuple()
8862 : Type(Ttuple)
8863{
8864 arguments = new Parameters();
8865}
8866
8867TypeTuple::TypeTuple(Type *t1)
8868 : Type(Ttuple)
8869{
8870 arguments = new Parameters();
8871 arguments->push(new Parameter(0, t1, NULL, NULL));
8872}
8873
8874TypeTuple::TypeTuple(Type *t1, Type *t2)
8875 : Type(Ttuple)
8876{
8877 arguments = new Parameters();
8878 arguments->push(new Parameter(0, t1, NULL, NULL));
8879 arguments->push(new Parameter(0, t2, NULL, NULL));
8880}
8881
8882const char *TypeTuple::kind()
8883{
8884 return "tuple";
8885}
8886
8887Type *TypeTuple::syntaxCopy()
8888{
8889 Parameters *args = Parameter::arraySyntaxCopy(arguments);
8890 Type *t = new TypeTuple(args);
8891 t->mod = mod;
8892 return t;
8893}
8894
8895Type *TypeTuple::semantic(Loc, Scope *)
8896{
8897 //printf("TypeTuple::semantic(this = %p)\n", this);
8898 //printf("TypeTuple::semantic() %p, %s\n", this, toChars());
8899 if (!deco)
8900 deco = merge()->deco;
8901
8902 /* Don't return merge(), because a tuple with one type has the
8903 * same deco as that type.
8904 */
8905 return this;
8906}
8907
8908bool TypeTuple::equals(RootObject *o)
8909{
8910 Type *t = (Type *)o;
8911 //printf("TypeTuple::equals(%s, %s)\n", toChars(), t->toChars());
8912 if (this == t)
8913 return true;
8914 if (t->ty == Ttuple)
8915 {
8916 TypeTuple *tt = (TypeTuple *)t;
8917 if (arguments->dim == tt->arguments->dim)
8918 {
8919 for (size_t i = 0; i < tt->arguments->dim; i++)
8920 {
8921 Parameter *arg1 = (*arguments)[i];
8922 Parameter *arg2 = (*tt->arguments)[i];
8923 if (!arg1->type->equals(arg2->type))
8924 return false;
8925 }
8926 return true;
8927 }
8928 }
8929 return false;
8930}
8931
8932Expression *TypeTuple::getProperty(Loc loc, Identifier *ident, int flag)
8933{
8934 Expression *e;
8935
8936 if (ident == Id::length)
8937 {
8938 e = new IntegerExp(loc, arguments->dim, Type::tsize_t);
8939 }
8940 else if (ident == Id::_init)
8941 {
8942 e = defaultInitLiteral(loc);
8943 }
8944 else if (flag)
8945 {
8946 e = NULL;
8947 }
8948 else
8949 {
8950 error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars());
8951 e = new ErrorExp();
8952 }
8953 return e;
8954}
8955
8956Expression *TypeTuple::defaultInit(Loc loc)
8957{
8958 Expressions *exps = new Expressions();
8959 exps->setDim(arguments->dim);
8960 for (size_t i = 0; i < arguments->dim; i++)
8961 {
8962 Parameter *p = (*arguments)[i];
8963 assert(p->type);
8964 Expression *e = p->type->defaultInitLiteral(loc);
8965 if (e->op == TOKerror)
8966 return e;
8967 (*exps)[i] = e;
8968 }
8969 return new TupleExp(loc, exps);
8970}
8971
8972/***************************** TypeSlice *****************************/
8973
8974/* This is so we can slice a TypeTuple */
8975
8976TypeSlice::TypeSlice(Type *next, Expression *lwr, Expression *upr)
8977 : TypeNext(Tslice, next)
8978{
8979 //printf("TypeSlice[%s .. %s]\n", lwr->toChars(), upr->toChars());
8980 this->lwr = lwr;
8981 this->upr = upr;
8982}
8983
8984const char *TypeSlice::kind()
8985{
8986 return "slice";
8987}
8988
8989Type *TypeSlice::syntaxCopy()
8990{
8991 Type *t = new TypeSlice(next->syntaxCopy(), lwr->syntaxCopy(), upr->syntaxCopy());
8992 t->mod = mod;
8993 return t;
8994}
8995
8996Type *TypeSlice::semantic(Loc loc, Scope *sc)
8997{
8998 //printf("TypeSlice::semantic() %s\n", toChars());
8999 Type *tn = next->semantic(loc, sc);
9000 //printf("next: %s\n", tn->toChars());
9001
9002 Type *tbn = tn->toBasetype();
9003 if (tbn->ty != Ttuple)
9004 {
9005 error(loc, "can only slice tuple types, not %s", tbn->toChars());
9006 return Type::terror;
9007 }
9008 TypeTuple *tt = (TypeTuple *)tbn;
9009
9010 lwr = semanticLength(sc, tbn, lwr);
9011 lwr = lwr->ctfeInterpret();
9012 uinteger_t i1 = lwr->toUInteger();
9013
9014 upr = semanticLength(sc, tbn, upr);
9015 upr = upr->ctfeInterpret();
9016 uinteger_t i2 = upr->toUInteger();
9017
9018 if (!(i1 <= i2 && i2 <= tt->arguments->dim))
9019 {
9020 error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, tt->arguments->dim);
9021 return Type::terror;
9022 }
9023
9024 next = tn;
9025 transitive();
9026
9027 Parameters *args = new Parameters;
9028 args->reserve((size_t)(i2 - i1));
9029 for (size_t i = (size_t)i1; i < (size_t)i2; i++)
9030 {
9031 Parameter *arg = (*tt->arguments)[i];
9032 args->push(arg);
9033 }
9034 Type *t = new TypeTuple(args);
9035 return t->semantic(loc, sc);
9036}
9037
9038void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps, bool intypeid)
9039{
9040 next->resolve(loc, sc, pe, pt, ps, intypeid);
9041 if (*pe)
9042 {
9043 // It's really a slice expression
9044 if (Dsymbol *s = getDsymbol(*pe))
9045 *pe = new DsymbolExp(loc, s);
9046 *pe = new ArrayExp(loc, *pe, new IntervalExp(loc, lwr, upr));
9047 }
9048 else if (*ps)
9049 {
9050 Dsymbol *s = *ps;
9051 TupleDeclaration *td = s->isTupleDeclaration();
9052 if (td)
9053 {
9054 /* It's a slice of a TupleDeclaration
9055 */
9056 ScopeDsymbol *sym = new ArrayScopeSymbol(sc, td);
9057 sym->parent = sc->scopesym;
9058 sc = sc->push(sym);
9059 sc = sc->startCTFE();
9060 lwr = ::semantic(lwr, sc);
9061 upr = ::semantic(upr, sc);
9062 sc = sc->endCTFE();
9063 sc = sc->pop();
9064
9065 lwr = lwr->ctfeInterpret();
9066 upr = upr->ctfeInterpret();
9067 uinteger_t i1 = lwr->toUInteger();
9068 uinteger_t i2 = upr->toUInteger();
9069
9070 if (!(i1 <= i2 && i2 <= td->objects->dim))
9071 {
9072 error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, td->objects->dim);
9073 *ps = NULL;
9074 *pt = Type::terror;
9075 return;
9076 }
9077
9078 if (i1 == 0 && i2 == td->objects->dim)
9079 {
9080 *ps = td;
9081 return;
9082 }
9083
9084 /* Create a new TupleDeclaration which
9085 * is a slice [i1..i2] out of the old one.
9086 */
9087 Objects *objects = new Objects;
9088 objects->setDim((size_t)(i2 - i1));
9089 for (size_t i = 0; i < objects->dim; i++)
9090 {
9091 (*objects)[i] = (*td->objects)[(size_t)i1 + i];
9092 }
9093
9094 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
9095 *ps = tds;
9096 }
9097 else
9098 goto Ldefault;
9099 }
9100 else
9101 {
9102 if ((*pt)->ty != Terror)
9103 next = *pt; // prevent re-running semantic() on 'next'
9104 Ldefault:
9105 Type::resolve(loc, sc, pe, pt, ps, intypeid);
9106 }
9107}
9108
9109/***************************** TypeNull *****************************/
9110
9111TypeNull::TypeNull()
9112 : Type(Tnull)
9113{
9114}
9115
9116const char *TypeNull::kind()
9117{
9118 return "null";
9119}
9120
9121Type *TypeNull::syntaxCopy()
9122{
9123 // No semantic analysis done, no need to copy
9124 return this;
9125}
9126
9127MATCH TypeNull::implicitConvTo(Type *to)
9128{
9129 //printf("TypeNull::implicitConvTo(this=%p, to=%p)\n", this, to);
9130 //printf("from: %s\n", toChars());
9131 //printf("to : %s\n", to->toChars());
9132 MATCH m = Type::implicitConvTo(to);
9133 if (m != MATCHnomatch)
9134 return m;
9135
9136 // NULL implicitly converts to any pointer type or dynamic array
9137 //if (type->ty == Tpointer && type->nextOf()->ty == Tvoid)
9138 {
9139 Type *tb = to->toBasetype();
9140 if (tb->ty == Tnull ||
9141 tb->ty == Tpointer || tb->ty == Tarray ||
9142 tb->ty == Taarray || tb->ty == Tclass ||
9143 tb->ty == Tdelegate)
9144 return MATCHconst;
9145 }
9146
9147 return MATCHnomatch;
9148}
9149
9150bool TypeNull::isBoolean()
9151{
9152 return true;
9153}
9154
9155d_uns64 TypeNull::size(Loc loc)
9156{
9157 return tvoidptr->size(loc);
9158}
9159
9160Expression *TypeNull::defaultInit(Loc)
9161{
9162 return new NullExp(Loc(), Type::tnull);
9163}
9164
9165/***************************** Parameter *****************************/
9166
9167Parameter::Parameter(StorageClass storageClass, Type *type, Identifier *ident, Expression *defaultArg)
9168{
9169 this->type = type;
9170 this->ident = ident;
9171 this->storageClass = storageClass;
9172 this->defaultArg = defaultArg;
9173}
9174
9175Parameter *Parameter::create(StorageClass storageClass, Type *type, Identifier *ident, Expression *defaultArg)
9176{
9177 return new Parameter(storageClass, type, ident, defaultArg);
9178}
9179
9180Parameter *Parameter::syntaxCopy()
9181{
9182 return new Parameter(storageClass,
9183 type ? type->syntaxCopy() : NULL,
9184 ident,
9185 defaultArg ? defaultArg->syntaxCopy() : NULL);
9186}
9187
9188Parameters *Parameter::arraySyntaxCopy(Parameters *parameters)
9189{
9190 Parameters *params = NULL;
9191 if (parameters)
9192 {
9193 params = new Parameters();
9194 params->setDim(parameters->dim);
9195 for (size_t i = 0; i < params->dim; i++)
9196 (*params)[i] = (*parameters)[i]->syntaxCopy();
9197 }
9198 return params;
9199}
9200
9201/****************************************************
9202 * Determine if parameter is a lazy array of delegates.
9203 * If so, return the return type of those delegates.
9204 * If not, return NULL.
9205 *
9206 * Returns T if the type is one of the following forms:
9207 * T delegate()[]
9208 * T delegate()[dim]
9209 */
9210
9211Type *Parameter::isLazyArray()
9212{
9213 Type *tb = type->toBasetype();
9214 if (tb->ty == Tsarray || tb->ty == Tarray)
9215 {
9216 Type *tel = ((TypeArray *)tb)->next->toBasetype();
9217 if (tel->ty == Tdelegate)
9218 {
9219 TypeDelegate *td = (TypeDelegate *)tel;
2feebf42 9220 TypeFunction *tf = td->next->toTypeFunction();
03385ed3 9221
9222 if (!tf->varargs && Parameter::dim(tf->parameters) == 0)
9223 {
9224 return tf->next; // return type of delegate
9225 }
9226 }
9227 }
9228 return NULL;
9229}
9230
9231/***************************************
9232 * Determine number of arguments, folding in tuples.
9233 */
9234
9235static int dimDg(void *ctx, size_t, Parameter *)
9236{
9237 ++*(size_t *)ctx;
9238 return 0;
9239}
9240
9241size_t Parameter::dim(Parameters *parameters)
9242{
9243 size_t n = 0;
9244 Parameter_foreach(parameters, &dimDg, &n);
9245 return n;
9246}
9247
9248/***************************************
9249 * Get nth Parameter, folding in tuples.
9250 * Returns:
9251 * Parameter* nth Parameter
9252 * NULL not found, *pn gets incremented by the number
9253 * of Parameters
9254 */
9255
9256struct GetNthParamCtx
9257{
9258 size_t nth;
9259 Parameter *param;
9260};
9261
9262static int getNthParamDg(void *ctx, size_t n, Parameter *p)
9263{
9264 GetNthParamCtx *c = (GetNthParamCtx *)ctx;
9265 if (n == c->nth)
9266 {
9267 c->param = p;
9268 return 1;
9269 }
9270 return 0;
9271}
9272
9273Parameter *Parameter::getNth(Parameters *parameters, size_t nth, size_t *)
9274{
9275 GetNthParamCtx ctx = { nth, NULL };
9276 int res = Parameter_foreach(parameters, &getNthParamDg, &ctx);
9277 return res ? ctx.param : NULL;
9278}
9279
9280/***************************************
9281 * Expands tuples in args in depth first order. Calls
9282 * dg(void *ctx, size_t argidx, Parameter *arg) for each Parameter.
9283 * If dg returns !=0, stops and returns that value else returns 0.
9284 * Use this function to avoid the O(N + N^2/2) complexity of
9285 * calculating dim and calling N times getNth.
9286 */
9287
9288int Parameter_foreach(Parameters *parameters, ForeachDg dg, void *ctx, size_t *pn)
9289{
9290 assert(dg);
9291 if (!parameters)
9292 return 0;
9293
9294 size_t n = pn ? *pn : 0; // take over index
9295 int result = 0;
9296 for (size_t i = 0; i < parameters->dim; i++)
9297 {
9298 Parameter *p = (*parameters)[i];
9299 Type *t = p->type->toBasetype();
9300
9301 if (t->ty == Ttuple)
9302 {
9303 TypeTuple *tu = (TypeTuple *)t;
9304 result = Parameter_foreach(tu->arguments, dg, ctx, &n);
9305 }
9306 else
9307 result = dg(ctx, n++, p);
9308
9309 if (result)
9310 break;
9311 }
9312
9313 if (pn)
9314 *pn = n; // update index
9315 return result;
9316}
9317
9318
9319const char *Parameter::toChars()
9320{
9321 return ident ? ident->toChars() : "__anonymous_param";
9322}
9323
9324/*********************************
9325 * Compute covariance of parameters `this` and `p`
9326 * as determined by the storage classes of both.
9327 * Params:
9328 * p = Parameter to compare with
9329 * Returns:
9330 * true = `this` can be used in place of `p`
9331 * false = nope
9332 */
9333bool Parameter::isCovariant(bool returnByRef, const Parameter *p) const
9334{
9335 const StorageClass stc = STCref | STCin | STCout | STClazy;
9336 if ((this->storageClass & stc) != (p->storageClass & stc))
9337 return false;
9338
9339 return isCovariantScope(returnByRef, this->storageClass, p->storageClass);
9340}
9341
9342bool Parameter::isCovariantScope(bool returnByRef, StorageClass from, StorageClass to)
9343{
9344 if (from == to)
9345 return true;
9346
9347 struct SR
9348 {
9349 /* Classification of 'scope-return-ref' possibilities
9350 */
9351 enum
9352 {
9353 SRNone,
9354 SRScope,
9355 SRReturnScope,
9356 SRRef,
9357 SRReturnRef,
9358 SRRefScope,
9359 SRReturnRef_Scope,
9360 SRRef_ReturnScope,
9361 SRMAX,
9362 };
9363
9364 /* Shrinking the representation is necessary because StorageClass is so wide
9365 * Params:
9366 * returnByRef = true if the function returns by ref
9367 * stc = storage class of parameter
9368 */
9369 static unsigned buildSR(bool returnByRef, StorageClass stc)
9370 {
9371 unsigned result;
efc08a8f 9372 StorageClass stc2 = stc & (STCref | STCscope | STCreturn);
9373 if (stc2 == 0)
9374 result = SRNone;
9375 else if (stc2 == STCref)
9376 result = SRRef;
9377 else if (stc2 == STCscope)
9378 result = SRScope;
9379 else if (stc2 == (STCscope | STCreturn))
9380 result = SRReturnScope;
9381 else if (stc2 == (STCref | STCreturn))
9382 result = SRReturnRef;
9383 else if (stc2 == (STCscope | STCref))
9384 result = SRRefScope;
9385 else if (stc2 == (STCscope | STCref | STCreturn))
9386 result = returnByRef ? SRReturnRef_Scope : SRRef_ReturnScope;
9387 else
9388 assert(0);
03385ed3 9389 return result;
9390 }
9391
9392 static void covariantInit(bool covariant[SRMAX][SRMAX])
9393 {
9394 /* Initialize covariant[][] with this:
9395
9396 From\To n rs s
9397 None X
9398 ReturnScope X X
9399 Scope X X X
9400
9401 From\To r rr rs rr-s r-rs
9402 Ref X X
9403 ReturnRef X
9404 RefScope X X X X X
9405 ReturnRef-Scope X X
9406 Ref-ReturnScope X X X
9407 */
9408 for (int i = 0; i < SRMAX; i++)
9409 {
9410 covariant[i][i] = true;
9411 covariant[SRRefScope][i] = true;
9412 }
9413 covariant[SRReturnScope][SRNone] = true;
9414 covariant[SRScope ][SRNone] = true;
9415 covariant[SRScope ][SRReturnScope] = true;
9416
9417 covariant[SRRef ][SRReturnRef] = true;
9418 covariant[SRReturnRef_Scope][SRReturnRef] = true;
9419 covariant[SRRef_ReturnScope][SRRef ] = true;
9420 covariant[SRRef_ReturnScope][SRReturnRef] = true;
9421 }
9422 };
9423
9424 /* result is true if the 'from' can be used as a 'to'
9425 */
9426
9427 if ((from ^ to) & STCref) // differing in 'ref' means no covariance
9428 return false;
9429
9430 static bool covariant[SR::SRMAX][SR::SRMAX];
9431 static bool init = false;
9432 if (!init)
9433 {
9434 SR::covariantInit(covariant);
9435 init = true;
9436 }
9437
9438 return covariant[SR::buildSR(returnByRef, from)][SR::buildSR(returnByRef, to)];
9439}