root/trunk/src/mtype.c

Revision 879, 208.6 kB (checked in by walter, 1 year ago)

64 bit alignment fix

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