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