Added linkage to ClassDeclaration
[delight/core.git] / dmd2 / mtype.c
blob5b69fca51742ac3d45e28b6116a79d42e6d24c67
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
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.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, December 2006
17 // Issues with using -include total.h (defines integer_t) and then complex.h fails...
18 #undef integer_t
20 #define __USE_ISOC99 1 // so signbit() gets defined
21 #include <math.h>
23 #include <stdio.h>
24 #include <assert.h>
25 #include <float.h>
27 #include "gdc_alloca.h"
29 #ifdef __DMC__
30 #include <fp.h>
31 #endif
33 // TODO%% this undefines signbit and includes is the wrong complex.h anyway
34 // -- not sure why this is needed, anyway
35 // don't need to worry about all this if the 'nan negative by default' issue is resolved
36 #if _MSC_VER
37 #include <malloc.h>
38 #include <complex>
39 #include <limits>
40 #elif __DMC__
41 // includes the wrong complex.h in C++
42 #include <complex.h>
43 #else
44 //#define signbit 56
45 #endif
47 #if __APPLE__
48 #include <math.h>
49 static double zero = 0;
50 #elif __GNUC__
51 #include <math.h>
52 // %% shouldn't be necessary
53 //#include <bits/nan.h>
54 //#include <bits/mathdef.h>
55 static double zero = 0;
56 #endif
58 #ifndef NAN
59 #define NAN (nan("0"))
60 #endif
61 #ifndef INFINITY
62 #define INFINITY (infinity())
63 #endif
67 #ifdef __APPLE__
68 #define integer_t dmd_integer_t
69 #endif
72 #include "mem.h"
74 #include "dsymbol.h"
75 #include "mtype.h"
76 #include "scope.h"
77 #include "init.h"
78 #include "expression.h"
79 #include "attrib.h"
80 #include "declaration.h"
81 #include "template.h"
82 #include "id.h"
83 #include "enum.h"
84 #include "import.h"
85 #include "aggregate.h"
86 #include "hdrgen.h"
88 FuncDeclaration *hasThis(Scope *sc);
91 #define LOGDOTEXP 0 // log ::dotExp()
92 #define LOGDEFAULTINIT 0 // log ::defaultInit()
94 // Allow implicit conversion of T[] to T*
95 #define IMPLICIT_ARRAY_TO_PTR global.params.useDeprecated
97 /* These have default values for 32 bit code, they get
98 * adjusted for 64 bit code.
101 int PTRSIZE = 4;
102 #if TARGET_LINUX
103 int REALSIZE = 12;
104 int REALPAD = 2;
105 #else
106 int REALSIZE = 10;
107 int REALPAD = 0;
108 #endif
109 int Tsize_t = Tuns32;
110 int Tptrdiff_t = Tint32;
111 int Tindex = Tint32;
112 int CLASSINFO_SIZE = 0x3c+12;
114 /***************************** Type *****************************/
116 ClassDeclaration *Type::typeinfo;
117 ClassDeclaration *Type::typeinfoclass;
118 ClassDeclaration *Type::typeinfointerface;
119 ClassDeclaration *Type::typeinfostruct;
120 ClassDeclaration *Type::typeinfotypedef;
121 ClassDeclaration *Type::typeinfopointer;
122 ClassDeclaration *Type::typeinfoarray;
123 ClassDeclaration *Type::typeinfostaticarray;
124 ClassDeclaration *Type::typeinfoassociativearray;
125 ClassDeclaration *Type::typeinfoenum;
126 ClassDeclaration *Type::typeinfofunction;
127 ClassDeclaration *Type::typeinfodelegate;
128 ClassDeclaration *Type::typeinfotypelist;
129 ClassDeclaration *Type::typeinfoconst;
130 ClassDeclaration *Type::typeinfoinvariant;
132 Type *Type::tvoidptr;
133 Type *Type::basic[TMAX];
134 unsigned char Type::mangleChar[TMAX];
135 unsigned char Type::sizeTy[TMAX];
136 StringTable Type::stringtable;
139 Type::Type(TY ty)
141 this->ty = ty;
142 this->mod = 0;
143 this->deco = NULL;
144 #if V2
145 this->cto = NULL;
146 this->ito = NULL;
147 #endif
148 this->pto = NULL;
149 this->mbe = NULL;
150 this->rto = NULL;
151 this->arrayof = NULL;
152 this->vtinfo = NULL;
153 this->ctype = NULL;
156 Type *Type::syntaxCopy()
158 print();
159 fprintf(stdmsg, "ty = %d\n", ty);
160 assert(0);
161 return this;
164 int Type::equals(Object *o)
165 { Type *t;
167 t = (Type *)o;
168 //printf("Type::equals(%s, %s)\n", toChars(), t->toChars());
169 if (this == o ||
170 (t && deco == t->deco) && // deco strings are unique
171 deco != NULL) // and semantic() has been run
173 //printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
174 return 1;
176 //if (deco && t && t->deco) printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
177 return 0;
180 char Type::needThisPrefix()
182 return 'M'; // name mangling prefix for functions needing 'this'
185 void Type::init()
186 { int i;
187 int j;
189 Lexer::initKeywords();
191 for (i = 0; i < TMAX; i++)
192 sizeTy[i] = sizeof(TypeBasic);
193 sizeTy[Tsarray] = sizeof(TypeSArray);
194 sizeTy[Tarray] = sizeof(TypeDArray);
195 sizeTy[Taarray] = sizeof(TypeAArray);
196 sizeTy[Tpointer] = sizeof(TypePointer);
197 sizeTy[Treference] = sizeof(TypeReference);
198 sizeTy[Tfunction] = sizeof(TypeFunction);
199 sizeTy[Tdelegate] = sizeof(TypeDelegate);
200 sizeTy[Tident] = sizeof(TypeIdentifier);
201 sizeTy[Tinstance] = sizeof(TypeInstance);
202 sizeTy[Ttypeof] = sizeof(TypeTypeof);
203 sizeTy[Tenum] = sizeof(TypeEnum);
204 sizeTy[Ttypedef] = sizeof(TypeTypedef);
205 sizeTy[Tstruct] = sizeof(TypeStruct);
206 sizeTy[Tclass] = sizeof(TypeClass);
207 sizeTy[Ttuple] = sizeof(TypeTuple);
208 sizeTy[Tslice] = sizeof(TypeSlice);
209 sizeTy[Treturn] = sizeof(TypeReturn);
211 mangleChar[Tarray] = 'A';
212 mangleChar[Tsarray] = 'G';
213 mangleChar[Taarray] = 'H';
214 mangleChar[Tpointer] = 'P';
216 // For compat with D libraries, the maybe qualifier gets stripped from
217 // symbol names. In TypeInfo names, it is replaced by 'Q'.
218 mangleChar[Tmaybe] = '?';
220 mangleChar[Treference] = 'R';
221 mangleChar[Tfunction] = 'F';
222 mangleChar[Tident] = 'I';
223 mangleChar[Tclass] = 'C';
224 mangleChar[Tstruct] = 'S';
225 mangleChar[Tenum] = 'E';
226 mangleChar[Ttypedef] = 'T';
227 mangleChar[Tdelegate] = 'D';
229 mangleChar[Tnone] = 'n';
230 mangleChar[Tvoid] = 'v';
231 mangleChar[Tint8] = 'g';
232 mangleChar[Tuns8] = 'h';
233 mangleChar[Tint16] = 's';
234 mangleChar[Tuns16] = 't';
235 mangleChar[Tint32] = 'i';
236 mangleChar[Tuns32] = 'k';
237 mangleChar[Tint64] = 'l';
238 mangleChar[Tuns64] = 'm';
239 mangleChar[Tfloat32] = 'f';
240 mangleChar[Tfloat64] = 'd';
241 mangleChar[Tfloat80] = 'e';
243 mangleChar[Timaginary32] = 'o';
244 mangleChar[Timaginary64] = 'p';
245 mangleChar[Timaginary80] = 'j';
246 mangleChar[Tcomplex32] = 'q';
247 mangleChar[Tcomplex64] = 'r';
248 mangleChar[Tcomplex80] = 'c';
250 mangleChar[Tbool] = 'b';
251 mangleChar[Tascii] = 'a';
252 mangleChar[Twchar] = 'u';
253 mangleChar[Tdchar] = 'w';
255 mangleChar[Tbit] = '@';
256 mangleChar[Tinstance] = '@';
257 mangleChar[Terror] = '@';
258 mangleChar[Ttypeof] = '@';
259 mangleChar[Ttuple] = 'B';
260 mangleChar[Tslice] = '@';
261 mangleChar[Treturn] = '@';
263 for (i = 0; i < TMAX; i++)
264 { if (!mangleChar[i])
265 fprintf(stdmsg, "ty = %d\n", i);
266 assert(mangleChar[i]);
269 // Set basic types
270 static TY basetab[] =
271 { Tvoid, Tint8, Tuns8, Tint16, Tuns16, Tint32, Tuns32, Tint64, Tuns64,
272 Tfloat32, Tfloat64, Tfloat80,
273 Timaginary32, Timaginary64, Timaginary80,
274 Tcomplex32, Tcomplex64, Tcomplex80,
275 Tbool,
276 Tascii, Twchar, Tdchar };
278 for (i = 0; i < sizeof(basetab) / sizeof(basetab[0]); i++)
279 { Type *t = new TypeBasic(basetab[i]);
280 t = t->merge();
281 basic[basetab[i]] = t;
283 basic[Terror] = basic[Tint32];
285 tvoidptr = tvoid->pointerTo();
287 if (global.params.isX86_64)
289 PTRSIZE = 8;
290 if (global.params.isLinux)
291 REALSIZE = 10;
292 else
293 REALSIZE = 8;
294 Tsize_t = Tuns64;
295 Tptrdiff_t = Tint64;
296 Tindex = Tint64;
298 else
300 PTRSIZE = 4;
301 #if TARGET_LINUX
302 REALSIZE = 12;
303 REALPAD = 2;
304 #else
305 REALSIZE = 10;
306 REALPAD = 0;
307 #endif
308 Tsize_t = Tuns32;
309 Tptrdiff_t = Tint32;
311 CLASSINFO_SIZE = 18 * PTRSIZE;
314 d_uns64 Type::size()
316 return size(0);
319 d_uns64 Type::size(Loc loc)
321 error(loc, "no size for type %s", toChars());
322 return 1;
325 unsigned Type::alignsize()
327 return size(0);
330 Type *Type::semantic(Loc loc, Scope *sc)
332 return merge();
335 /*******************************
336 * Determine if converting 'this' to 'to' is an identity operation,
337 * a conversion to const operation, or the types aren't the same.
338 * Returns:
339 * MATCHequal 'this' == 'to'
340 * MATCHconst 'to' is const
341 * MATCHnomatch conversion to mutable or invariant
344 MATCH Type::constConv(Type *to)
346 if (equals(to))
347 return MATCHexact;
348 if (ty == to->ty && to->mod == MODconst)
349 return MATCHconst;
350 return MATCHnomatch;
353 Type *Type::constOf()
355 //printf("Type::constOf() %p %s\n", this, toChars());
356 if (isConst())
357 return this;
358 if (cto)
359 return cto;
360 Type *t = makeConst();
361 t = t->merge();
362 cto = t;
363 if (ito)
364 ito->cto = t;
365 //if (t->nextOf()) assert(t->nextOf()->isConst());
366 //printf("-Type::constOf() %p %s\n", t, toChars());
367 return t;
370 Type *Type::invariantOf()
372 //printf("Type::invariantOf() %p %s\n", this, toChars());
373 if (isInvariant())
375 return this;
377 if (ito)
379 //if (!ito->isInvariant()) printf("\tito is %p %s\n", ito, ito->toChars());
380 assert(ito->isInvariant());
381 return ito;
383 Type *t = makeInvariant();
384 t = t->merge();
385 ito = t;
386 if (cto)
387 cto->ito = t;
388 #if 0 // fails for function types
389 if (t->nextOf() && !t->nextOf()->isInvariant())
391 assert(0);
393 #endif
394 //printf("\t%p\n", t);
395 return t;
398 Type *Type::mutableOf()
400 //printf("Type::mutableOf() %p, %s\n", this, toChars());
401 Type *t = this;
402 if (isConst())
403 { t = cto;
404 assert(!t || t->isMutable());
406 else if (isInvariant())
407 { t = ito;
408 assert(!t || t->isMutable());
410 if (!t)
412 unsigned sz = sizeTy[ty];
413 t = (Type *)mem.malloc(sz);
414 memcpy(t, this, sz);
415 t->mod = 0;
416 t->deco = NULL;
417 t->arrayof = NULL;
418 t->pto = NULL;
419 t->rto = NULL;
420 t->cto = NULL;
421 t->ito = NULL;
422 t->vtinfo = NULL;
423 if (ty == Tsarray)
424 { TypeSArray *ta = (TypeSArray *)t;
425 //ta->next = ta->next->mutableOf();
427 t = t->merge();
428 if (isConst())
429 { cto = t;
430 t->cto = this;
431 if (ito)
432 ito->cto = this;
434 else if (isInvariant())
435 { ito = t;
436 t->ito = this;
437 if (cto)
438 cto->ito = this;
441 return t;
444 Type *Type::makeConst()
446 //printf("Type::makeConst() %p, %s\n", this, toChars());
447 if (cto)
448 return cto;
449 unsigned sz = sizeTy[ty];
450 Type *t = (Type *)mem.malloc(sz);
451 memcpy(t, this, sz);
452 t->mod = MODconst;
453 t->deco = NULL;
454 t->arrayof = NULL;
455 t->pto = NULL;
456 t->rto = NULL;
457 t->cto = NULL;
458 t->ito = NULL;
459 t->vtinfo = NULL;
460 //printf("-Type::makeConst() %p, %s\n", t, toChars());
461 return t;
464 Type *Type::makeInvariant()
466 if (ito)
467 return ito;
468 unsigned sz = sizeTy[ty];
469 Type *t = (Type *)mem.malloc(sz);
470 memcpy(t, this, sz);
471 t->mod = MODinvariant;
472 t->deco = NULL;
473 t->arrayof = NULL;
474 t->pto = NULL;
475 t->rto = NULL;
476 t->cto = NULL;
477 t->ito = NULL;
478 t->vtinfo = NULL;
479 return t;
482 /**************************
483 * Return type with the top level of it being mutable.
485 Type *Type::toHeadMutable()
487 if (!mod)
488 return this;
489 return mutableOf();
493 // If this type can be null, wrap it in TypeMaybe.
494 // Otherwise just, returns itself. This is so that
495 // we can try wrapping everything in D source easily.
496 // merge should be false if we haven't yet run semantic
497 // on the type.
498 Type *Type::maybe(bool merge)
500 if (ty == Tmaybe)
502 return this;
505 // For some reason, "void*?" causes problems.
506 // Since it's not type safe anyway, don't worry about it.
507 if (ty == Tpointer && nextOf()->ty == Tvoid)
508 return this;
510 if (ty != Tpointer && ty != Tclass && ty != Tident)
511 return this; // Can't be null
513 if (!mbe)
514 { Type *t;
516 t = new TypeMaybe(this);
517 if (!merge || t->reliesOnTident())
518 mbe = t;
519 else
520 mbe = t->merge();
522 return mbe;
525 Type *Type::pointerTo()
527 if (!pto)
528 { Type *t;
530 t = new TypePointer(this);
531 pto = t->merge();
533 return pto;
536 Type *Type::referenceTo()
538 if (!rto)
539 { Type *t;
541 t = new TypeReference(this);
542 rto = t->merge();
544 return rto;
547 Type *Type::arrayOf()
549 if (!arrayof)
550 { Type *t;
552 t = new TypeDArray(this);
553 arrayof = t->merge();
555 return arrayof;
558 Dsymbol *Type::toDsymbol(Scope *sc)
560 return NULL;
563 /*******************************
564 * If this is a shell around another type,
565 * get that other type.
568 Type *Type::toBasetype()
570 return this;
573 /********************************
574 * Name mangling.
575 * Input:
576 * flag 0x100 do not do const/invariant
579 void Type::toDecoBuffer(OutBuffer *buf, int flag)
581 if (flag != mod && flag != 0x100)
583 switch (mod)
585 case 0: break;
586 case MODconst: buf->writeByte('x'); break;
587 case MODinvariant: buf->writeByte('y'); break;
588 default: assert(0);
591 buf->writeByte(mangleChar[ty]);
594 /********************************
595 * For pretty-printing a type.
598 char *Type::toChars()
599 { OutBuffer *buf;
600 HdrGenState hgs;
602 buf = new OutBuffer();
603 toCBuffer(buf, NULL, &hgs);
604 return buf->toChars();
607 void Type::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
609 toCBuffer2(buf, hgs, 0);
610 if (ident)
611 { buf->writeByte(' ');
612 buf->writestring(ident->toChars());
616 void Type::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
618 if (mod != this->mod)
619 { toCBuffer3(buf, hgs, mod);
620 return;
622 buf->writestring(toChars());
625 void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod)
627 if (mod != this->mod)
628 { char *p;
630 switch (this->mod)
632 case 0:
633 toCBuffer2(buf, hgs, this->mod);
634 break;
635 case MODconst:
636 p = "const(";
637 goto L1;
638 case MODinvariant:
639 p = "invariant(";
640 L1: buf->writestring(p);
641 toCBuffer2(buf, hgs, this->mod);
642 buf->writeByte(')');
643 break;
644 default:
645 assert(0);
650 /************************************
653 Type *Type::merge()
654 { Type *t;
655 //printf("merge(%s)\n", toChars());
656 t = this;
657 assert(t);
658 if (!deco)
660 OutBuffer buf;
661 StringValue *sv;
663 //if (next)
664 //next = next->merge();
665 toDecoBuffer(&buf);
666 sv = stringtable.update((char *)buf.data, buf.offset);
667 if (sv->ptrvalue)
668 { t = (Type *) sv->ptrvalue;
669 if (! t->deco) {
670 fprintf(stderr, "nooooooooooooooooooooooo! %s %s\n", toChars(), t->toChars());
672 assert(t->deco);
673 //printf("old value, deco = '%s' %p\n", t->deco, t->deco);
675 else
677 sv->ptrvalue = this;
678 deco = sv->lstring.string;
679 if (! t->deco) {
680 fprintf(stderr, "yeeeeeeeeeeeeeeeeeeeeeeeesss!\n");
682 assert(deco);
683 //printf("new value, deco = '%s' %p\n", t->deco, t->deco);
686 return t;
689 int Type::isintegral()
691 return FALSE;
694 int Type::isfloating()
696 return FALSE;
699 int Type::isreal()
701 return FALSE;
704 int Type::isimaginary()
706 return FALSE;
709 int Type::iscomplex()
711 return FALSE;
714 int Type::isscalar()
716 return FALSE;
719 int Type::isunsigned()
721 return FALSE;
724 ClassDeclaration *Type::isClassHandle()
726 return NULL;
729 int Type::isauto()
731 return FALSE;
734 int Type::isString()
736 return FALSE;
739 /**************************
740 * Given:
741 * T a, b;
742 * Can we assign:
743 * a = b;
746 int Type::isAssignable()
748 return TRUE;
751 int Type::checkBoolean()
753 return isscalar();
756 /*********************************
757 * Check type to see if it is based on a deprecated symbol.
760 void Type::checkDeprecated(Loc loc, Scope *sc)
762 Dsymbol *s = toDsymbol(sc);
764 if (s)
765 s->checkDeprecated(loc, sc);
769 Expression *Type::defaultInit(Loc loc)
771 #if LOGDEFAULTINIT
772 printf("Type::defaultInit() '%s'\n", toChars());
773 #endif
774 return NULL;
777 int Type::isZeroInit()
779 return 0; // assume not
782 int Type::isBaseOf(Type *t, target_ptrdiff_t *poffset)
784 return 0; // assume not
787 /********************************
788 * Determine if 'this' can be implicitly converted
789 * to type 'to'.
790 * Returns:
791 * 0 can't convert
792 * 1 can convert using implicit conversions
793 * 2 this and to are the same type
796 MATCH Type::implicitConvTo(Type *to)
798 //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to);
799 if (this == to)
800 return MATCHexact;
801 return MATCHnomatch;
804 Expression *Type::getProperty(Loc loc, Identifier *ident)
805 { Expression *e;
807 #if LOGDOTEXP
808 printf("Type::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars());
809 #endif
810 if (ident == Id::__sizeof)
812 e = new IntegerExp(loc, size(loc), Type::tsize_t);
814 else if (ident == Id::size)
816 error(loc, ".size property should be replaced with .sizeof");
817 e = new IntegerExp(loc, size(loc), Type::tsize_t);
819 else if (ident == Id::alignof)
821 e = new IntegerExp(loc, alignsize(), Type::tsize_t);
823 else if (ident == Id::typeinfo)
825 if (!global.params.useDeprecated)
826 error(loc, ".typeinfo deprecated, use typeid(type)");
827 e = getTypeInfo(NULL);
829 else if (ident == Id::init)
831 if (ty == Tvoid)
832 error(loc, "void does not have an initializer");
833 e = defaultInit(loc);
835 else if (ident == Id::mangleof)
837 assert(deco);
838 e = new StringExp(loc, deco, strlen(deco), 'c');
839 Scope sc;
840 e = e->semantic(&sc);
842 else if (ident == Id::stringof)
843 { char *s = toChars();
844 e = new StringExp(loc, s, strlen(s), 'c');
845 Scope sc;
846 e = e->semantic(&sc);
848 else
850 error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars());
851 e = new IntegerExp(loc, 1, Type::tint32);
853 return e;
856 Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident)
857 { VarDeclaration *v = NULL;
859 #if LOGDOTEXP
860 printf("Type::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
861 #endif
862 if (e->op == TOKdotvar)
864 DotVarExp *dv = (DotVarExp *)e;
865 v = dv->var->isVarDeclaration();
867 else if (e->op == TOKvar)
869 VarExp *ve = (VarExp *)e;
870 v = ve->var->isVarDeclaration();
872 if (v)
874 if (ident == Id::offset)
876 if (!global.params.useDeprecated)
877 error(e->loc, ".offset deprecated, use .offsetof");
878 goto Loffset;
880 else if (ident == Id::offsetof)
882 Loffset:
883 if (v->storage_class & STCfield)
885 e = new IntegerExp(e->loc, v->offset, Type::tsize_t);
886 return e;
889 else if (ident == Id::init)
891 #if 0
892 if (v->init)
894 if (v->init->isVoidInitializer())
895 error(e->loc, "%s.init is void", v->toChars());
896 else
897 { Loc loc = e->loc;
898 e = v->init->toExpression();
899 if (e->op == TOKassign || e->op == TOKconstruct || e->op == TOKblit)
901 e = ((AssignExp *)e)->e2;
903 /* Take care of case where we used a 0
904 * to initialize the struct.
906 if (e->type == Type::tint32 &&
907 e->isBool(0) &&
908 v->type->toBasetype()->ty == Tstruct)
910 e = v->type->defaultInit(e->loc);
913 e = e->optimize(WANTvalue | WANTinterpret);
914 // if (!e->isConst())
915 // error(loc, ".init cannot be evaluated at compile time");
917 return e;
919 #endif
920 Expression *ex = defaultInit(e->loc);
921 return ex;
924 if (ident == Id::typeinfo)
926 if (!global.params.useDeprecated)
927 error(e->loc, ".typeinfo deprecated, use typeid(type)");
928 e = getTypeInfo(sc);
929 return e;
931 if (ident == Id::stringof)
932 { char *s = e->toChars();
933 e = new StringExp(e->loc, s, strlen(s), 'c');
934 Scope sc;
935 e = e->semantic(&sc);
936 return e;
938 return getProperty(e->loc, ident);
941 unsigned Type::memalign(unsigned salign)
943 return salign;
946 void Type::error(Loc loc, const char *format, ...)
948 va_list ap;
949 va_start(ap, format);
950 ::verror(loc, format, ap);
951 va_end( ap );
954 Identifier *Type::getTypeInfoIdent(int internal)
956 // _init_10TypeInfo_%s
957 OutBuffer buf;
958 Identifier *id;
959 char *name;
960 int len;
962 if (internal)
963 { buf.writeByte(mangleChar[ty]);
964 if (ty == Tarray)
965 buf.writeByte(mangleChar[((TypeArray *)this)->next->ty]);
967 else
968 toDecoBuffer(&buf);
970 len = buf.offset;
971 name = (char *)alloca(19 + sizeof(len) * 3 + len + 1);
973 /* Maybe types contain invalid char ?, because they don't appear in
974 * mangled names. Use unused char Q for TypeInfo instead.
976 for (int i = 0; i < buf.offset; i++)
978 if (buf.data[i] == '?')
979 buf.data[i] = 'Q';
982 buf.writeByte(0);
984 sprintf(name, "_D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
985 if (global.params.isWindows)
986 name++; // C mangling will add it back in
987 //printf("name = %s\n", name);
988 id = Lexer::idPool(name);
989 return id;
992 TypeBasic *Type::isTypeBasic()
994 return NULL;
998 void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
1000 //printf("Type::resolve() %s, %d\n", toChars(), ty);
1001 Type *t = semantic(loc, sc);
1002 *pt = t;
1003 *pe = NULL;
1004 *ps = NULL;
1007 /*******************************
1008 * If one of the subtypes of this type is a TypeIdentifier,
1009 * i.e. it's an unresolved type, return that type.
1012 Type *Type::reliesOnTident()
1014 return NULL;
1017 /********************************
1018 * We've mistakenly parsed this as a type.
1019 * Redo it as an Expression.
1020 * NULL if cannot.
1023 Expression *Type::toExpression()
1025 return NULL;
1028 /***************************************
1029 * Return !=0 if type has pointers that need to
1030 * be scanned by the GC during a collection cycle.
1033 int Type::hasPointers()
1035 return FALSE;
1038 /*************************************
1039 * If this is a type of something, return that something.
1042 Type *Type::nextOf()
1044 return NULL;
1047 /* ============================= TypeNext =========================== */
1049 TypeNext::TypeNext(TY ty, Type *next)
1050 : Type(ty)
1052 this->next = next;
1055 void TypeNext::toDecoBuffer(OutBuffer *buf, int flag)
1057 Type::toDecoBuffer(buf, flag);
1058 assert(next != this);
1059 //printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty);
1060 next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod);
1063 void TypeNext::checkDeprecated(Loc loc, Scope *sc)
1065 Type::checkDeprecated(loc, sc);
1066 next->checkDeprecated(loc, sc);
1070 Type *TypeNext::reliesOnTident()
1072 return next->reliesOnTident();
1075 Type *TypeNext::nextOf()
1077 return next;
1080 Type *TypeNext::makeConst()
1082 //printf("TypeNext::makeConst() %p, %s\n", this, toChars());
1083 if (cto)
1084 return cto;
1085 TypeNext *t = (TypeNext *)Type::makeConst();
1086 if (ty != Tfunction && ty != Tdelegate && next->deco &&
1087 !next->isInvariant())
1088 t->next = next->constOf();
1089 //printf("TypeNext::makeConst() returns %p, %s\n", t, t->toChars());
1090 return t;
1093 Type *TypeNext::makeInvariant()
1095 //printf("TypeNext::makeInvariant() %s\n", toChars());
1096 if (ito)
1097 { assert(ito->isInvariant());
1098 return ito;
1100 TypeNext *t = (TypeNext *)Type::makeInvariant();
1101 if (ty != Tfunction && ty != Tdelegate && next->deco)
1102 { t->next = next->invariantOf();
1104 return t;
1107 MATCH TypeNext::constConv(Type *to)
1108 { MATCH m = Type::constConv(to);
1110 if (m == MATCHconst &&
1111 next->constConv(((TypeNext *)to)->next) == MATCHnomatch)
1112 m = MATCHnomatch;
1113 return m;
1117 /* ============================= TypeBasic =========================== */
1119 TypeBasic::TypeBasic(TY ty)
1120 : Type(ty)
1121 { char *d;
1122 unsigned flags;
1124 #define TFLAGSintegral 1
1125 #define TFLAGSfloating 2
1126 #define TFLAGSunsigned 4
1127 #define TFLAGSreal 8
1128 #define TFLAGSimaginary 0x10
1129 #define TFLAGScomplex 0x20
1131 flags = 0;
1132 switch (ty)
1134 case Tvoid: d = Token::toChars(TOKvoid);
1135 break;
1137 case Tint8: d = Token::toChars(TOKint8);
1138 flags |= TFLAGSintegral;
1139 break;
1141 case Tuns8: d = Token::toChars(TOKuns8);
1142 flags |= TFLAGSintegral | TFLAGSunsigned;
1143 break;
1145 case Tint16: d = Token::toChars(TOKint16);
1146 flags |= TFLAGSintegral;
1147 break;
1149 case Tuns16: d = Token::toChars(TOKuns16);
1150 flags |= TFLAGSintegral | TFLAGSunsigned;
1151 break;
1153 case Tint32: d = Token::toChars(TOKint32);
1154 flags |= TFLAGSintegral;
1155 break;
1157 case Tuns32: d = Token::toChars(TOKuns32);
1158 flags |= TFLAGSintegral | TFLAGSunsigned;
1159 break;
1161 case Tfloat32: d = Token::toChars(TOKfloat32);
1162 flags |= TFLAGSfloating | TFLAGSreal;
1163 break;
1165 case Tint64: d = Token::toChars(TOKint64);
1166 flags |= TFLAGSintegral;
1167 break;
1169 case Tuns64: d = Token::toChars(TOKuns64);
1170 flags |= TFLAGSintegral | TFLAGSunsigned;
1171 break;
1173 case Tfloat64: d = Token::toChars(TOKfloat64);
1174 flags |= TFLAGSfloating | TFLAGSreal;
1175 break;
1177 case Tfloat80: d = Token::toChars(TOKfloat80);
1178 flags |= TFLAGSfloating | TFLAGSreal;
1179 break;
1181 case Timaginary32: d = Token::toChars(TOKimaginary32);
1182 flags |= TFLAGSfloating | TFLAGSimaginary;
1183 break;
1185 case Timaginary64: d = Token::toChars(TOKimaginary64);
1186 flags |= TFLAGSfloating | TFLAGSimaginary;
1187 break;
1189 case Timaginary80: d = Token::toChars(TOKimaginary80);
1190 flags |= TFLAGSfloating | TFLAGSimaginary;
1191 break;
1193 case Tcomplex32: d = Token::toChars(TOKcomplex32);
1194 flags |= TFLAGSfloating | TFLAGScomplex;
1195 break;
1197 case Tcomplex64: d = Token::toChars(TOKcomplex64);
1198 flags |= TFLAGSfloating | TFLAGScomplex;
1199 break;
1201 case Tcomplex80: d = Token::toChars(TOKcomplex80);
1202 flags |= TFLAGSfloating | TFLAGScomplex;
1203 break;
1205 case Tbool: d = "bool";
1206 flags |= TFLAGSintegral | TFLAGSunsigned;
1207 break;
1209 case Tascii: d = Token::toChars(TOKchar);
1210 flags |= TFLAGSintegral | TFLAGSunsigned;
1211 break;
1213 case Twchar: d = Token::toChars(TOKwchar);
1214 flags |= TFLAGSintegral | TFLAGSunsigned;
1215 break;
1217 case Tdchar: d = Token::toChars(TOKdchar);
1218 flags |= TFLAGSintegral | TFLAGSunsigned;
1219 break;
1221 default: assert(0);
1223 this->dstring = d;
1224 this->flags = flags;
1225 merge();
1228 Type *TypeBasic::syntaxCopy()
1230 // No semantic analysis done on basic types, no need to copy
1231 return this;
1235 char *TypeBasic::toChars()
1237 return Type::toChars();
1240 void TypeBasic::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
1242 //printf("TypeBasic::toCBuffer2(mod = %d, this->mod = %d)\n", mod, this->mod);
1243 if (mod != this->mod)
1244 { toCBuffer3(buf, hgs, mod);
1245 return;
1247 buf->writestring(dstring);
1250 d_uns64 TypeBasic::size(Loc loc)
1251 { unsigned size;
1253 //printf("TypeBasic::size()\n");
1254 switch (ty)
1256 case Tint8:
1257 case Tuns8: size = 1; break;
1258 case Tint16:
1259 case Tuns16: size = 2; break;
1260 case Tint32:
1261 case Tuns32:
1262 case Tfloat32:
1263 case Timaginary32:
1264 size = 4; break;
1265 case Tint64:
1266 case Tuns64:
1267 case Tfloat64:
1268 case Timaginary64:
1269 size = 8; break;
1270 case Tfloat80:
1271 case Timaginary80:
1272 size = REALSIZE; break;
1273 case Tcomplex32:
1274 size = 8; break;
1275 case Tcomplex64:
1276 size = 16; break;
1277 case Tcomplex80:
1278 size = REALSIZE * 2; break;
1280 case Tvoid:
1281 //size = Type::size(); // error message
1282 size = 1;
1283 break;
1285 case Tbool: size = 1; break;
1286 case Tascii: size = 1; break;
1287 case Twchar: size = 2; break;
1288 case Tdchar: size = 4; break;
1290 default:
1291 assert(0);
1292 break;
1294 //printf("TypeBasic::size() = %d\n", size);
1295 return size;
1298 unsigned TypeBasic::alignsize()
1299 { unsigned sz;
1301 switch (ty)
1303 case Tfloat80:
1304 case Timaginary80:
1305 case Tcomplex80:
1306 sz = 2;
1307 break;
1309 default:
1310 sz = size(0);
1311 break;
1313 return sz;
1317 Expression *TypeBasic::getProperty(Loc loc, Identifier *ident)
1319 Expression *e;
1320 d_int64 ivalue;
1321 #ifdef IN_GCC
1322 real_t fvalue;
1323 #else
1324 d_float80 fvalue;
1325 #endif
1327 //printf("TypeBasic::getProperty('%s')\n", ident->toChars());
1328 if (ident == Id::max)
1330 switch (ty)
1332 case Tint8: ivalue = 0x7F; goto Livalue;
1333 case Tuns8: ivalue = 0xFF; goto Livalue;
1334 case Tint16: ivalue = 0x7FFFUL; goto Livalue;
1335 case Tuns16: ivalue = 0xFFFFUL; goto Livalue;
1336 case Tint32: ivalue = 0x7FFFFFFFUL; goto Livalue;
1337 case Tuns32: ivalue = 0xFFFFFFFFUL; goto Livalue;
1338 case Tint64: ivalue = 0x7FFFFFFFFFFFFFFFLL; goto Livalue;
1339 case Tuns64: ivalue = 0xFFFFFFFFFFFFFFFFULL; goto Livalue;
1340 case Tbool: ivalue = 1; goto Livalue;
1341 case Tchar: ivalue = 0xFF; goto Livalue;
1342 case Twchar: ivalue = 0xFFFFUL; goto Livalue;
1343 case Tdchar: ivalue = 0x10FFFFUL; goto Livalue;
1345 case Tcomplex32:
1346 case Timaginary32:
1347 #ifdef IN_GCC
1348 // %% lazy, fix
1349 #define FLT_MAX real_t_properties[real_t::Float].maxval;
1350 #define DBL_MAX real_t_properties[real_t::Double].maxval;
1351 #define LDBL_MAX real_t_properties[real_t::LongDouble].maxval;
1352 #define FLT_MIN real_t_properties[real_t::Float].minval;
1353 #define DBL_MIN real_t_properties[real_t::Double].minval;
1354 #define LDBL_MIN real_t_properties[real_t::LongDouble].minval;
1355 #define FLT_DIG real_t_properties[real_t::Float].dig;
1356 #define DBL_DIG real_t_properties[real_t::Double].dig;
1357 #define LDBL_DIG real_t_properties[real_t::LongDouble].dig;
1358 #define FLT_MANT_DIG real_t_properties[real_t::Float].mant_dig;
1359 #define DBL_MANT_DIG real_t_properties[real_t::Double].mant_dig;
1360 #define LDBL_MANT_DIG real_t_properties[real_t::LongDouble].mant_dig;
1361 #define FLT_MAX_10_EXP real_t_properties[real_t::Float].max_10_exp;
1362 #define DBL_MAX_10_EXP real_t_properties[real_t::Double].max_10_exp;
1363 #define LDBL_MAX_10_EXP real_t_properties[real_t::LongDouble].max_10_exp;
1364 #define FLT_MIN_10_EXP real_t_properties[real_t::Float].min_10_exp;
1365 #define DBL_MIN_10_EXP real_t_properties[real_t::Double].min_10_exp;
1366 #define LDBL_MIN_10_EXP real_t_properties[real_t::LongDouble].min_10_exp;
1367 #define FLT_MAX_EXP real_t_properties[real_t::Float].max_exp;
1368 #define DBL_MAX_EXP real_t_properties[real_t::Double].max_exp;
1369 #define LDBL_MAX_EXP real_t_properties[real_t::LongDouble].max_exp;
1370 #define FLT_MIN_EXP real_t_properties[real_t::Float].min_exp;
1371 #define DBL_MIN_EXP real_t_properties[real_t::Double].min_exp;
1372 #define LDBL_MIN_EXP real_t_properties[real_t::LongDouble].min_exp;
1373 #define FLT_EPSILON real_t_properties[real_t::Float].epsilonval;
1374 #define DBL_EPSILON real_t_properties[real_t::Double].epsilonval;
1375 #define LDBL_EPSILON real_t_properties[real_t::LongDouble].epsilonval;
1378 #endif
1379 case Tfloat32: fvalue = FLT_MAX; goto Lfvalue;
1380 case Tcomplex64:
1381 case Timaginary64:
1382 case Tfloat64: fvalue = DBL_MAX; goto Lfvalue;
1383 case Tcomplex80:
1384 case Timaginary80:
1385 case Tfloat80: fvalue = LDBL_MAX; goto Lfvalue;
1388 else if (ident == Id::min)
1390 switch (ty)
1392 case Tint8: ivalue = -128; goto Livalue;
1393 case Tuns8: ivalue = 0; goto Livalue;
1394 case Tint16: ivalue = -32768; goto Livalue;
1395 case Tuns16: ivalue = 0; goto Livalue;
1396 case Tint32: ivalue = -2147483647L - 1; goto Livalue;
1397 case Tuns32: ivalue = 0; goto Livalue;
1398 case Tint64: ivalue = (-9223372036854775807LL-1LL); goto Livalue;
1399 case Tuns64: ivalue = 0; goto Livalue;
1400 case Tbool: ivalue = 0; goto Livalue;
1401 case Tchar: ivalue = 0; goto Livalue;
1402 case Twchar: ivalue = 0; goto Livalue;
1403 case Tdchar: ivalue = 0; goto Livalue;
1405 case Tcomplex32:
1406 case Timaginary32:
1407 case Tfloat32: fvalue = FLT_MIN; goto Lfvalue;
1408 case Tcomplex64:
1409 case Timaginary64:
1410 case Tfloat64: fvalue = DBL_MIN; goto Lfvalue;
1411 case Tcomplex80:
1412 case Timaginary80:
1413 case Tfloat80: fvalue = LDBL_MIN; goto Lfvalue;
1416 else if (ident == Id::nan)
1418 switch (ty)
1420 case Tcomplex32:
1421 case Tcomplex64:
1422 case Tcomplex80:
1423 case Timaginary32:
1424 case Timaginary64:
1425 case Timaginary80:
1426 case Tfloat32:
1427 case Tfloat64:
1428 case Tfloat80:
1430 #if IN_GCC
1431 // mode doesn't matter, will be converted in RealExp anyway
1432 fvalue = real_t::getnan(real_t::LongDouble);
1433 #elif __GNUC__
1434 // gcc nan's have the sign bit set by default, so turn it off
1435 // Need the volatile to prevent gcc from doing incorrect
1436 // constant folding.
1437 volatile d_float80 foo;
1438 foo = NAN;
1439 if (signbit(foo)) // signbit sometimes, not always, set
1440 foo = -foo; // turn off sign bit
1441 fvalue = foo;
1442 #elif _MSC_VER
1443 unsigned long nan[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
1444 fvalue = *(double*)nan;
1445 #else
1446 fvalue = NAN;
1447 #endif
1448 goto Lfvalue;
1452 else if (ident == Id::infinity)
1454 switch (ty)
1456 case Tcomplex32:
1457 case Tcomplex64:
1458 case Tcomplex80:
1459 case Timaginary32:
1460 case Timaginary64:
1461 case Timaginary80:
1462 case Tfloat32:
1463 case Tfloat64:
1464 case Tfloat80:
1465 #if IN_GCC
1466 fvalue = real_t::getinfinity();
1467 #elif __GNUC__
1468 fvalue = 1 / zero;
1469 #elif _MSC_VER
1470 fvalue = std::numeric_limits<long double>::infinity();
1471 #else
1472 fvalue = INFINITY;
1473 #endif
1474 goto Lfvalue;
1477 else if (ident == Id::dig)
1479 switch (ty)
1481 case Tcomplex32:
1482 case Timaginary32:
1483 case Tfloat32: ivalue = FLT_DIG; goto Lint;
1484 case Tcomplex64:
1485 case Timaginary64:
1486 case Tfloat64: ivalue = DBL_DIG; goto Lint;
1487 case Tcomplex80:
1488 case Timaginary80:
1489 case Tfloat80: ivalue = LDBL_DIG; goto Lint;
1492 else if (ident == Id::epsilon)
1494 switch (ty)
1496 case Tcomplex32:
1497 case Timaginary32:
1498 case Tfloat32: fvalue = FLT_EPSILON; goto Lfvalue;
1499 case Tcomplex64:
1500 case Timaginary64:
1501 case Tfloat64: fvalue = DBL_EPSILON; goto Lfvalue;
1502 case Tcomplex80:
1503 case Timaginary80:
1504 case Tfloat80: fvalue = LDBL_EPSILON; goto Lfvalue;
1507 else if (ident == Id::mant_dig)
1509 switch (ty)
1511 case Tcomplex32:
1512 case Timaginary32:
1513 case Tfloat32: ivalue = FLT_MANT_DIG; goto Lint;
1514 case Tcomplex64:
1515 case Timaginary64:
1516 case Tfloat64: ivalue = DBL_MANT_DIG; goto Lint;
1517 case Tcomplex80:
1518 case Timaginary80:
1519 case Tfloat80: ivalue = LDBL_MANT_DIG; goto Lint;
1522 else if (ident == Id::max_10_exp)
1524 switch (ty)
1526 case Tcomplex32:
1527 case Timaginary32:
1528 case Tfloat32: ivalue = FLT_MAX_10_EXP; goto Lint;
1529 case Tcomplex64:
1530 case Timaginary64:
1531 case Tfloat64: ivalue = DBL_MAX_10_EXP; goto Lint;
1532 case Tcomplex80:
1533 case Timaginary80:
1534 case Tfloat80: ivalue = LDBL_MAX_10_EXP; goto Lint;
1537 else if (ident == Id::max_exp)
1539 switch (ty)
1541 case Tcomplex32:
1542 case Timaginary32:
1543 case Tfloat32: ivalue = FLT_MAX_EXP; goto Lint;
1544 case Tcomplex64:
1545 case Timaginary64:
1546 case Tfloat64: ivalue = DBL_MAX_EXP; goto Lint;
1547 case Tcomplex80:
1548 case Timaginary80:
1549 case Tfloat80: ivalue = LDBL_MAX_EXP; goto Lint;
1552 else if (ident == Id::min_10_exp)
1554 switch (ty)
1556 case Tcomplex32:
1557 case Timaginary32:
1558 case Tfloat32: ivalue = FLT_MIN_10_EXP; goto Lint;
1559 case Tcomplex64:
1560 case Timaginary64:
1561 case Tfloat64: ivalue = DBL_MIN_10_EXP; goto Lint;
1562 case Tcomplex80:
1563 case Timaginary80:
1564 case Tfloat80: ivalue = LDBL_MIN_10_EXP; goto Lint;
1567 else if (ident == Id::min_exp)
1569 switch (ty)
1571 case Tcomplex32:
1572 case Timaginary32:
1573 case Tfloat32: ivalue = FLT_MIN_EXP; goto Lint;
1574 case Tcomplex64:
1575 case Timaginary64:
1576 case Tfloat64: ivalue = DBL_MIN_EXP; goto Lint;
1577 case Tcomplex80:
1578 case Timaginary80:
1579 case Tfloat80: ivalue = LDBL_MIN_EXP; goto Lint;
1583 Ldefault:
1584 return Type::getProperty(loc, ident);
1586 Livalue:
1587 e = new IntegerExp(loc, ivalue, this);
1588 return e;
1590 Lfvalue:
1591 if (isreal() || isimaginary())
1592 e = new RealExp(loc, fvalue, this);
1593 else
1595 complex_t cvalue;
1597 #if __DMC__
1598 //((real_t *)&cvalue)[0] = fvalue;
1599 //((real_t *)&cvalue)[1] = fvalue;
1600 cvalue = fvalue + fvalue * I;
1601 #else
1602 cvalue.re = fvalue;
1603 cvalue.im = fvalue;
1604 #endif
1605 //for (int i = 0; i < 20; i++)
1606 // printf("%02x ", ((unsigned char *)&cvalue)[i]);
1607 //printf("\n");
1608 e = new ComplexExp(loc, cvalue, this);
1610 return e;
1612 Lint:
1613 e = new IntegerExp(loc, ivalue, Type::tint32);
1614 return e;
1617 Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
1619 #if LOGDOTEXP
1620 printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1621 #endif
1622 Type *t;
1624 if (ident == Id::re)
1626 switch (ty)
1628 case Tcomplex32: t = tfloat32; goto L1;
1629 case Tcomplex64: t = tfloat64; goto L1;
1630 case Tcomplex80: t = tfloat80; goto L1;
1632 e = e->castTo(sc, t);
1633 break;
1635 case Tfloat32:
1636 case Tfloat64:
1637 case Tfloat80:
1638 break;
1640 case Timaginary32: t = tfloat32; goto L2;
1641 case Timaginary64: t = tfloat64; goto L2;
1642 case Timaginary80: t = tfloat80; goto L2;
1644 e = new RealExp(0, 0, t);
1645 break;
1647 default:
1648 return Type::getProperty(e->loc, ident);
1651 else if (ident == Id::im)
1652 { Type *t2;
1654 switch (ty)
1656 case Tcomplex32: t = timaginary32; t2 = tfloat32; goto L3;
1657 case Tcomplex64: t = timaginary64; t2 = tfloat64; goto L3;
1658 case Tcomplex80: t = timaginary80; t2 = tfloat80; goto L3;
1660 e = e->castTo(sc, t);
1661 e->type = t2;
1662 break;
1664 case Timaginary32: t = tfloat32; goto L4;
1665 case Timaginary64: t = tfloat64; goto L4;
1666 case Timaginary80: t = tfloat80; goto L4;
1668 e = e->copy();
1669 e->type = t;
1670 break;
1672 case Tfloat32:
1673 case Tfloat64:
1674 case Tfloat80:
1675 e = new RealExp(0, 0, this);
1676 break;
1678 default:
1679 return Type::getProperty(e->loc, ident);
1682 else
1684 return Type::dotExp(sc, e, ident);
1686 return e;
1689 Expression *TypeBasic::defaultInit(Loc loc)
1690 { integer_t value = 0;
1692 #if LOGDEFAULTINIT
1693 printf("TypeBasic::defaultInit() '%s'\n", toChars());
1694 #endif
1695 switch (ty)
1697 case Tchar:
1698 value = 0xFF;
1699 break;
1701 case Twchar:
1702 case Tdchar:
1703 value = 0xFFFF;
1704 break;
1706 case Timaginary32:
1707 case Timaginary64:
1708 case Timaginary80:
1709 case Tfloat32:
1710 case Tfloat64:
1711 case Tfloat80:
1712 case Tcomplex32:
1713 case Tcomplex64:
1714 case Tcomplex80:
1715 return getProperty(loc, Id::nan);
1717 case Tvoid:
1718 error(loc, "void does not have a default initializer");
1720 return new IntegerExp(loc, value, this);
1723 int TypeBasic::isZeroInit()
1725 switch (ty)
1727 case Tchar:
1728 case Twchar:
1729 case Tdchar:
1730 case Timaginary32:
1731 case Timaginary64:
1732 case Timaginary80:
1733 case Tfloat32:
1734 case Tfloat64:
1735 case Tfloat80:
1736 case Tcomplex32:
1737 case Tcomplex64:
1738 case Tcomplex80:
1739 return 0; // no
1741 return 1; // yes
1744 int TypeBasic::isintegral()
1746 //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags);
1747 return flags & TFLAGSintegral;
1750 int TypeBasic::isfloating()
1752 return flags & TFLAGSfloating;
1755 int TypeBasic::isreal()
1757 return flags & TFLAGSreal;
1760 int TypeBasic::isimaginary()
1762 return flags & TFLAGSimaginary;
1765 int TypeBasic::iscomplex()
1767 return flags & TFLAGScomplex;
1770 int TypeBasic::isunsigned()
1772 return flags & TFLAGSunsigned;
1775 int TypeBasic::isscalar()
1777 return flags & (TFLAGSintegral | TFLAGSfloating);
1780 MATCH TypeBasic::implicitConvTo(Type *to)
1782 //printf("TypeBasic::implicitConvTo(%s) from %s\n", to->toChars(), toChars());
1783 if (this == to)
1784 return MATCHexact;
1786 if (ty == to->ty)
1788 return (mod == to->mod) ? MATCHexact : MATCHconst;
1791 if (ty == Tvoid || to->ty == Tvoid)
1792 return MATCHnomatch;
1793 if (1 || global.params.Dversion == 1)
1795 if (to->ty == Tbool)
1796 return MATCHnomatch;
1798 else
1800 if (ty == Tbool || to->ty == Tbool)
1801 return MATCHnomatch;
1803 if (!to->isTypeBasic())
1804 return MATCHnomatch;
1806 TypeBasic *tob = (TypeBasic *)to;
1807 if (flags & TFLAGSintegral)
1809 // Disallow implicit conversion of integers to imaginary or complex
1810 if (tob->flags & (TFLAGSimaginary | TFLAGScomplex))
1811 return MATCHnomatch;
1813 // If converting to integral
1814 if (0 && global.params.Dversion > 1 && tob->flags & TFLAGSintegral)
1815 { d_uns64 sz = size(0);
1816 d_uns64 tosz = tob->size(0);
1818 /* Can't convert to smaller size or, if same size, change sign
1820 if (sz > tosz)
1821 return MATCHnomatch;
1823 /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned)
1824 return MATCHnomatch;*/
1827 else if (flags & TFLAGSfloating)
1829 // Disallow implicit conversion of floating point to integer
1830 if (tob->flags & TFLAGSintegral)
1831 return MATCHnomatch;
1833 assert(tob->flags & TFLAGSfloating);
1835 // Disallow implicit conversion from complex to non-complex
1836 if (flags & TFLAGScomplex && !(tob->flags & TFLAGScomplex))
1837 return MATCHnomatch;
1839 // Disallow implicit conversion of real or imaginary to complex
1840 if (flags & (TFLAGSreal | TFLAGSimaginary) &&
1841 tob->flags & TFLAGScomplex)
1842 return MATCHnomatch;
1844 // Disallow implicit conversion to-from real and imaginary
1845 if ((flags & (TFLAGSreal | TFLAGSimaginary)) !=
1846 (tob->flags & (TFLAGSreal | TFLAGSimaginary)))
1847 return MATCHnomatch;
1849 return MATCHconvert;
1852 TypeBasic *TypeBasic::isTypeBasic()
1854 return (TypeBasic *)this;
1857 /***************************** TypeArray *****************************/
1859 TypeArray::TypeArray(TY ty, Type *next)
1860 : TypeNext(ty, next)
1864 Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
1866 Type *n = this->next->toBasetype(); // uncover any typedef's
1868 #if LOGDOTEXP
1869 printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1870 #endif
1871 if (ident == Id::reverse && (n->ty == Tchar || n->ty == Twchar))
1873 Expression *ec;
1874 FuncDeclaration *fd;
1875 Expressions *arguments;
1876 char *nm;
1877 static char *name[2] = { "_adReverseChar", "_adReverseWchar" };
1879 nm = name[n->ty == Twchar];
1880 fd = FuncDeclaration::genCfunc(next->arrayOf(), nm, Type::tvoid->arrayOf());
1881 ec = new VarExp(0, fd);
1882 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1883 arguments = new Expressions();
1884 arguments->push(e);
1885 e = new CallExp(e->loc, ec, arguments);
1886 e->type = next->arrayOf();
1888 else if (ident == Id::sort && (n->ty == Tchar || n->ty == Twchar))
1890 Expression *ec;
1891 FuncDeclaration *fd;
1892 Expressions *arguments;
1893 char *nm;
1894 static char *name[2] = { "_adSortChar", "_adSortWchar" };
1896 nm = name[n->ty == Twchar];
1897 fd = FuncDeclaration::genCfunc(next->arrayOf(), nm, Type::tvoid->arrayOf());
1898 ec = new VarExp(0, fd);
1899 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1900 arguments = new Expressions();
1901 arguments->push(e);
1902 e = new CallExp(e->loc, ec, arguments);
1903 e->type = next->arrayOf();
1905 else if (ident == Id::reverse || ident == Id::dup || ident == Id::idup)
1907 Expression *ec;
1908 FuncDeclaration *fd;
1909 Expressions *arguments;
1910 target_size_t size = next->size(e->loc);
1911 int dup;
1913 assert(size);
1914 dup = (ident == Id::dup || ident == Id::idup);
1915 if (dup)
1916 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::adDup,
1917 Type::typeinfo->type, Type::tvoid->arrayOf());
1918 else
1919 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::adReverse,
1920 Type::tvoid->arrayOf(), Type::tsize_t);
1921 ec = new VarExp(0, fd);
1922 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1923 arguments = new Expressions();
1924 if (dup)
1925 arguments->push(getTypeInfo(sc));
1926 arguments->push(e);
1927 if (!dup)
1928 arguments->push(new IntegerExp(0, size, Type::tsize_t));
1929 e = new CallExp(e->loc, ec, arguments);
1930 if (ident == Id::idup)
1931 { Type *einv = next->invariantOf();
1932 if (next->implicitConvTo(einv) < MATCHconst)
1933 error(e->loc, "cannot implicitly convert element type %s to invariant", next->toChars());
1934 e->type = einv->arrayOf();
1936 else
1937 e->type = next->mutableOf()->arrayOf();
1939 else if (ident == Id::sort)
1941 Expression *ec;
1942 FuncDeclaration *fd;
1943 Expressions *arguments;
1945 fd = FuncDeclaration::genCfunc(tint32->arrayOf(), "_adSort",
1946 Type::tvoid->arrayOf(), Type::tvoid->pointerTo());
1947 ec = new VarExp(0, fd);
1948 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1949 arguments = new Expressions();
1950 arguments->push(e);
1951 arguments->push(n->ty == Tsarray
1952 ? n->getTypeInfo(sc) // don't convert to dynamic array
1953 : n->getInternalTypeInfo(sc));
1954 e = new CallExp(e->loc, ec, arguments);
1955 e->type = next->arrayOf();
1957 else
1959 e = Type::dotExp(sc, e, ident);
1961 return e;
1966 /***************************** TypeSArray *****************************/
1968 TypeSArray::TypeSArray(Type *t, Expression *dim)
1969 : TypeArray(Tsarray, t)
1971 //printf("TypeSArray(%s)\n", dim->toChars());
1972 this->dim = dim;
1975 Type *TypeSArray::syntaxCopy()
1977 Type *t = next->syntaxCopy();
1978 Expression *e = dim->syntaxCopy();
1979 t = new TypeSArray(t, e);
1980 t->mod = mod;
1981 return t;
1984 d_uns64 TypeSArray::size(Loc loc)
1985 { integer_t sz;
1987 if (!dim)
1988 return Type::size(loc);
1989 sz = dim->toInteger();
1991 { integer_t n, n2;
1993 n = next->size();
1994 n2 = n * sz;
1995 if (n && (n2 / n) != sz)
1996 goto Loverflow;
1997 sz = n2;
1999 return sz;
2001 Loverflow:
2002 error(loc, "index %"PRIdMAX" overflow for static array", sz);
2003 return 1;
2006 unsigned TypeSArray::alignsize()
2008 return next->alignsize();
2011 /**************************
2012 * This evaluates exp while setting length to be the number
2013 * of elements in the tuple t.
2015 Expression *semanticLength(Scope *sc, Type *t, Expression *exp)
2017 if (t->ty == Ttuple)
2018 { ScopeDsymbol *sym = new ArrayScopeSymbol(sc, (TypeTuple *)t);
2019 sym->parent = sc->scopesym;
2020 sc = sc->push(sym);
2022 exp = exp->semantic(sc);
2024 sc->pop();
2026 else
2027 exp = exp->semantic(sc);
2028 return exp;
2031 Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp)
2033 ScopeDsymbol *sym = new ArrayScopeSymbol(sc, s);
2034 sym->parent = sc->scopesym;
2035 sc = sc->push(sym);
2037 exp = exp->semantic(sc);
2039 sc->pop();
2040 return exp;
2043 void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
2045 //printf("TypeSArray::resolve() %s\n", toChars());
2046 next->resolve(loc, sc, pe, pt, ps);
2047 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
2048 if (*pe)
2049 { // It's really an index expression
2050 Expression *e = new IndexExp(loc, *pe, dim);
2051 *pe = e;
2053 else if (*ps)
2054 { Dsymbol *s = *ps;
2055 TupleDeclaration *td = s->isTupleDeclaration();
2056 if (td)
2058 ScopeDsymbol *sym = new ArrayScopeSymbol(sc, td);
2059 sym->parent = sc->scopesym;
2060 sc = sc->push(sym);
2062 dim = dim->semantic(sc);
2063 dim = dim->optimize(WANTvalue | WANTinterpret);
2064 uinteger_t d = dim->toUInteger();
2066 sc = sc->pop();
2068 if (d >= td->objects->dim)
2069 { error(loc, "tuple index %"PRIuMAX" exceeds %u", d, td->objects->dim);
2070 goto Ldefault;
2072 Object *o = (Object *)td->objects->data[(size_t)d];
2073 if (o->dyncast() == DYNCAST_DSYMBOL)
2075 *ps = (Dsymbol *)o;
2076 return;
2078 if (o->dyncast() == DYNCAST_EXPRESSION)
2080 *ps = NULL;
2081 *pe = (Expression *)o;
2082 return;
2085 /* Create a new TupleDeclaration which
2086 * is a slice [d..d+1] out of the old one.
2087 * Do it this way because TemplateInstance::semanticTiargs()
2088 * can handle unresolved Objects this way.
2090 Objects *objects = new Objects;
2091 objects->setDim(1);
2092 objects->data[0] = o;
2094 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
2095 *ps = tds;
2097 else
2098 goto Ldefault;
2100 else
2102 Ldefault:
2103 Type::resolve(loc, sc, pe, pt, ps);
2107 Type *TypeSArray::semantic(Loc loc, Scope *sc)
2109 //printf("TypeSArray::semantic() %s\n", toChars());
2111 Type *t;
2112 Expression *e;
2113 Dsymbol *s;
2114 next->resolve(loc, sc, &e, &t, &s);
2115 if (dim && s && s->isTupleDeclaration())
2116 { TupleDeclaration *sd = s->isTupleDeclaration();
2118 dim = semanticLength(sc, sd, dim);
2119 dim = dim->optimize(WANTvalue | WANTinterpret);
2120 uinteger_t d = dim->toUInteger();
2122 if (d >= sd->objects->dim)
2123 { error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim);
2124 return Type::terror;
2126 Object *o = (Object *)sd->objects->data[(size_t)d];
2127 if (o->dyncast() != DYNCAST_TYPE)
2128 { error(loc, "%s is not a type", toChars());
2129 return Type::terror;
2131 t = (Type *)o;
2132 return t;
2135 next = next->semantic(loc,sc);
2136 if (mod == MODconst && !next->isInvariant())
2137 next = next->constOf();
2138 else if (mod == MODinvariant)
2139 next = next->invariantOf();
2141 Type *tbn = next->toBasetype();
2143 if (dim)
2144 { integer_t n, n2;
2146 dim = semanticLength(sc, tbn, dim);
2148 dim = dim->optimize(WANTvalue | WANTinterpret);
2149 if (sc->parameterSpecialization && dim->op == TOKvar &&
2150 ((VarExp *)dim)->var->storage_class & STCtemplateparameter)
2152 /* It could be a template parameter N which has no value yet:
2153 * template Foo(T : T[N], size_t N);
2155 return this;
2157 integer_t d1 = dim->toInteger();
2158 dim = dim->castTo(sc, tsize_t);
2159 dim = dim->optimize(WANTvalue);
2160 integer_t d2 = dim->toInteger();
2162 if (d1 != d2)
2163 goto Loverflow;
2165 if (tbn->isintegral() ||
2166 tbn->isfloating() ||
2167 tbn->ty == Tpointer ||
2168 tbn->ty == Tarray ||
2169 tbn->ty == Tsarray ||
2170 tbn->ty == Taarray ||
2171 tbn->ty == Tclass)
2173 /* Only do this for types that don't need to have semantic()
2174 * run on them for the size, since they may be forward referenced.
2176 n = tbn->size(loc);
2177 n2 = n * d2;
2178 if ((int)n2 < 0)
2179 goto Loverflow;
2180 if (n2 >= 0x1000000) // put a 'reasonable' limit on it
2181 goto Loverflow;
2182 if (n && n2 / n != d2)
2184 Loverflow:
2185 error(loc, "index %"PRIdMAX" overflow for static array", d1);
2186 dim = new IntegerExp(0, 1, tsize_t);
2190 switch (tbn->ty)
2192 case Ttuple:
2193 { // Index the tuple to get the type
2194 assert(dim);
2195 TypeTuple *tt = (TypeTuple *)tbn;
2196 uinteger_t d = dim->toUInteger();
2198 if (d >= tt->arguments->dim)
2199 { error(loc, "tuple index %"PRIuMAX" exceeds %u", d, tt->arguments->dim);
2200 return Type::terror;
2202 Argument *arg = (Argument *)tt->arguments->data[(size_t)d];
2203 return arg->type;
2205 case Tfunction:
2206 case Tnone:
2207 error(loc, "can't have array of %s", tbn->toChars());
2208 tbn = next = tint32;
2209 break;
2211 if (tbn->isauto())
2212 error(loc, "cannot have array of auto %s", tbn->toChars());
2213 return merge();
2216 void TypeSArray::toDecoBuffer(OutBuffer *buf, int flag)
2218 Type::toDecoBuffer(buf, flag);
2219 if (dim)
2220 buf->printf("%"PRIuMAX, dim->toInteger());
2221 if (next)
2222 /* Note that static arrays are value types, so
2223 * for a parameter, propagate the 0x100 to the next
2224 * level, since for T[4][3], any const should apply to the T,
2225 * not the [4].
2227 next->toDecoBuffer(buf, (flag & 0x100) ? flag : mod);
2230 void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2232 if (mod != this->mod)
2233 { toCBuffer3(buf, hgs, mod);
2234 return;
2236 next->toCBuffer2(buf, hgs, this->mod);
2237 buf->printf("[%s]", dim->toChars());
2240 Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
2242 #if LOGDOTEXP
2243 printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2244 #endif
2245 if (ident == Id::length)
2247 e = dim;
2249 else if (ident == Id::ptr)
2251 e = e->castTo(sc, next->pointerTo());
2253 else
2255 e = TypeArray::dotExp(sc, e, ident);
2257 return e;
2260 int TypeSArray::isString()
2262 TY nty = next->toBasetype()->ty;
2263 return nty == Tchar || nty == Twchar || nty == Tdchar;
2266 unsigned TypeSArray::memalign(unsigned salign)
2268 return next->memalign(salign);
2271 MATCH TypeSArray::constConv(Type *to)
2273 if (to->ty == Tsarray)
2275 TypeSArray *tsa = (TypeSArray *)to;
2276 if (!dim->equals(tsa->dim))
2277 return MATCHnomatch;
2279 return TypeNext::constConv(to);
2282 MATCH TypeSArray::implicitConvTo(Type *to)
2284 //printf("TypeSArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars());
2286 if (to->ty == Tmaybe && to->nextOf())
2287 to = to->nextOf();
2289 // Allow implicit conversion of static array to pointer or dynamic array
2290 if (IMPLICIT_ARRAY_TO_PTR && to->ty == Tpointer)
2292 TypePointer *tp = (TypePointer *)to;
2294 if (next->mod != tp->next->mod && tp->next->mod != MODconst)
2295 return MATCHnomatch;
2297 if (tp->next->ty == Tvoid || next->constConv(tp->next) != MATCHnomatch)
2299 return MATCHconvert;
2301 return MATCHnomatch;
2303 if (to->ty == Tarray)
2304 { target_ptrdiff_t offset = 0;
2305 TypeDArray *ta = (TypeDArray *)to;
2307 if (next->mod != ta->next->mod && ta->next->mod != MODconst)
2308 return MATCHnomatch;
2310 if (next->equals(ta->next) ||
2311 next->implicitConvTo(ta->next) >= MATCHconst ||
2312 (ta->next->isBaseOf(next, &offset) && offset == 0) ||
2313 ta->next->ty == Tvoid)
2314 return MATCHconvert;
2315 return MATCHnomatch;
2317 if (to->ty == Tsarray)
2319 if (this == to)
2320 return MATCHexact;
2322 TypeSArray *tsa = (TypeSArray *)to;
2324 if (dim->equals(tsa->dim))
2326 /* Since static arrays are value types, allow
2327 * conversions from const elements to non-const
2328 * ones, just like we allow conversion from const int
2329 * to int.
2331 MATCH m = next->implicitConvTo(tsa->next);
2332 if (m >= MATCHconst)
2334 if (mod != to->mod)
2335 m = MATCHconst;
2336 return m;
2340 return MATCHnomatch;
2343 Expression *TypeSArray::defaultInit(Loc loc)
2345 #if LOGDEFAULTINIT
2346 printf("TypeSArray::defaultInit() '%s'\n", toChars());
2347 #endif
2348 return next->defaultInit(loc);
2351 int TypeSArray::isZeroInit()
2353 return next->isZeroInit();
2357 Expression *TypeSArray::toExpression()
2359 Expression *e = next->toExpression();
2360 if (e)
2361 { Expressions *arguments = new Expressions();
2362 arguments->push(dim);
2363 e = new ArrayExp(dim->loc, e, arguments);
2365 return e;
2368 int TypeSArray::hasPointers()
2370 return next->hasPointers();
2373 /***************************** TypeDArray *****************************/
2375 TypeDArray::TypeDArray(Type *t)
2376 : TypeArray(Tarray, t)
2378 //printf("TypeDArray(t = %p)\n", t);
2381 Type *TypeDArray::syntaxCopy()
2383 Type *t = next->syntaxCopy();
2384 if (t == next)
2385 t = this;
2386 else
2387 { t = new TypeDArray(t);
2388 t->mod = mod;
2390 return t;
2393 d_uns64 TypeDArray::size(Loc loc)
2395 //printf("TypeDArray::size()\n");
2396 return PTRSIZE * 2;
2399 unsigned TypeDArray::alignsize()
2401 // A DArray consists of two ptr-sized values, so align it on pointer size
2402 // boundary
2403 return PTRSIZE;
2406 Type *TypeDArray::semantic(Loc loc, Scope *sc)
2407 { Type *tn = next;
2409 tn = next->semantic(loc,sc);
2410 Type *tbn = tn->toBasetype();
2411 switch (tbn->ty)
2413 case Tfunction:
2414 case Tnone:
2415 case Ttuple:
2416 error(loc, "can't have array of %s", tbn->toChars());
2417 tn = next = tint32;
2418 break;
2420 if (tn->isauto())
2421 error(loc, "cannot have array of auto %s", tn->toChars());
2423 if (mod == MODconst && !tn->isInvariant())
2424 tn = tn->constOf();
2425 else if (mod == MODinvariant)
2426 tn = tn->invariantOf();
2428 next = tn;
2429 return merge();
2432 void TypeDArray::toDecoBuffer(OutBuffer *buf, int flag)
2434 Type::toDecoBuffer(buf, flag);
2435 if (next)
2436 next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod);
2439 void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2441 if (mod != this->mod)
2442 { toCBuffer3(buf, hgs, mod);
2443 return;
2445 next->toCBuffer2(buf, hgs, this->mod);
2446 buf->writestring("[]");
2449 Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
2451 #if LOGDOTEXP
2452 printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2453 #endif
2454 if (ident == Id::length)
2456 if (e->op == TOKstring)
2457 { StringExp *se = (StringExp *)e;
2459 return new IntegerExp(se->loc, se->len, Type::tindex);
2461 e = new ArrayLengthExp(e->loc, e);
2462 e->type = Type::tsize_t;
2463 return e;
2465 else if (ident == Id::ptr)
2467 if (sc->fromDcode)
2468 e = e->castTo(sc, next->pointerTo());
2469 else
2470 e = e->castTo(sc, next->pointerTo()->maybe(true));
2471 return e;
2473 else
2475 e = TypeArray::dotExp(sc, e, ident);
2477 return e;
2480 int TypeDArray::isString()
2482 TY nty = next->toBasetype()->ty;
2483 return nty == Tchar || nty == Twchar || nty == Tdchar;
2486 MATCH TypeDArray::implicitConvTo(Type *to)
2488 //printf("TypeDArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars());
2489 if (equals(to))
2490 return MATCHexact;
2492 if (to->ty == Tmaybe)
2493 to = to->nextOf();
2495 // Allow implicit conversion of array to pointer
2496 if (IMPLICIT_ARRAY_TO_PTR && to->ty == Tpointer)
2498 TypePointer *tp = (TypePointer *)to;
2500 /* Allow conversion to void*
2502 if (tp->next->ty == Tvoid &&
2503 (next->mod == tp->next->mod || tp->next->mod == MODconst))
2505 return MATCHconvert;
2508 return next->constConv(to);
2511 if (to->ty == Tarray)
2512 { target_ptrdiff_t offset = 0;
2513 TypeDArray *ta = (TypeDArray *)to;
2515 if (!(next->mod == ta->next->mod || ta->next->mod == MODconst))
2516 return MATCHnomatch; // not const-compatible
2518 /* Allow conversion to void[]
2520 if (next->ty != Tvoid && ta->next->ty == Tvoid)
2522 return MATCHconvert;
2525 MATCH m = next->constConv(ta->next);
2526 if (m != MATCHnomatch)
2528 if (m == MATCHexact && mod != to->mod)
2529 m = MATCHconst;
2530 return m;
2533 /* Allow conversions of T[][] to const(T)[][]
2535 if (mod == ta->mod && next->ty == Tarray && ta->next->ty == Tarray)
2537 m = next->implicitConvTo(ta->next);
2538 if (m == MATCHconst)
2539 return m;
2542 /* Conversion of array of derived to array of base
2544 if (ta->next->isBaseOf(next, &offset) && offset == 0)
2545 return MATCHconvert;
2547 return Type::implicitConvTo(to);
2550 Expression *TypeDArray::defaultInit(Loc loc)
2552 #if LOGDEFAULTINIT
2553 printf("TypeDArray::defaultInit() '%s'\n", toChars());
2554 #endif
2555 Expression *e;
2556 e = new NullExp(loc);
2557 e->type = this;
2558 return e;
2561 int TypeDArray::isZeroInit()
2563 return 1;
2566 int TypeDArray::checkBoolean()
2568 return TRUE;
2571 int TypeDArray::hasPointers()
2573 return TRUE;
2576 /***************************** TypeAArray *****************************/
2578 TypeAArray::TypeAArray(Type *t, Type *index)
2579 : TypeArray(Taarray, t)
2581 this->index = index;
2584 Type *TypeAArray::syntaxCopy()
2586 Type *t = next->syntaxCopy();
2587 Type *ti = index->syntaxCopy();
2588 if (t == next && ti == index)
2589 t = this;
2590 else
2591 { t = new TypeAArray(t, ti);
2592 t->mod = mod;
2594 return t;
2597 d_uns64 TypeAArray::size(Loc loc)
2599 return PTRSIZE /* * 2*/;
2603 Type *TypeAArray::semantic(Loc loc, Scope *sc)
2605 //printf("TypeAArray::semantic() %s index->ty = %d\n", toChars(), index->ty);
2607 // Deal with the case where we thought the index was a type, but
2608 // in reality it was an expression.
2609 if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray)
2611 Expression *e;
2612 Type *t;
2613 Dsymbol *s;
2615 index->resolve(loc, sc, &e, &t, &s);
2616 if (e)
2617 { // It was an expression -
2618 // Rewrite as a static array
2619 TypeSArray *tsa;
2621 tsa = new TypeSArray(next, e);
2622 return tsa->semantic(loc,sc);
2624 else if (t)
2625 index = t;
2626 else
2627 index->error(loc, "index is not a type or an expression");
2629 else
2630 index = index->semantic(loc,sc);
2632 if (index->nextOf() && !index->nextOf()->isInvariant())
2634 index = index->constOf()->mutableOf();
2637 switch (index->toBasetype()->ty)
2639 case Tbool:
2640 case Tfunction:
2641 case Tvoid:
2642 case Tnone:
2643 error(loc, "can't have associative array key of %s", index->toBasetype()->toChars());
2644 break;
2646 next = next->semantic(loc,sc);
2647 if (mod == MODconst && !next->isInvariant())
2648 next = next->constOf();
2649 else if (mod == MODinvariant)
2650 next = next->invariantOf();
2652 switch (next->toBasetype()->ty)
2654 case Tfunction:
2655 case Tnone:
2656 error(loc, "can't have associative array of %s", next->toChars());
2657 break;
2659 if (next->isauto())
2660 error(loc, "cannot have array of auto %s", next->toChars());
2662 return merge();
2665 void TypeAArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
2667 //printf("TypeAArray::resolve() %s\n", toChars());
2669 // Deal with the case where we thought the index was a type, but
2670 // in reality it was an expression.
2671 if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray)
2673 Expression *e;
2674 Type *t;
2675 Dsymbol *s;
2677 index->resolve(loc, sc, &e, &t, &s);
2678 if (e)
2679 { // It was an expression -
2680 // Rewrite as a static array
2682 TypeSArray *tsa = new TypeSArray(next, e);
2683 return tsa->resolve(loc, sc, pe, pt, ps);
2685 else if (t)
2686 index = t;
2687 else
2688 index->error(loc, "index is not a type or an expression");
2690 Type::resolve(loc, sc, pe, pt, ps);
2694 Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
2696 #if LOGDOTEXP
2697 printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2698 #endif
2699 if (ident == Id::length)
2701 Expression *ec;
2702 FuncDeclaration *fd;
2703 Expressions *arguments;
2705 fd = FuncDeclaration::genCfunc(Type::tsize_t, Id::aaLen, Type::tvoid->arrayOf());
2706 ec = new VarExp(0, fd);
2707 arguments = new Expressions();
2708 arguments->push(e);
2709 e = new CallExp(e->loc, ec, arguments);
2710 e->type = ((TypeFunction *)fd->type)->next;
2712 else if (ident == Id::keys)
2714 Expression *ec;
2715 FuncDeclaration *fd;
2716 Expressions *arguments;
2717 int size = index->size(e->loc);
2719 assert(size);
2720 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaKeys,
2721 Type::tvoid->arrayOf(), Type::tsize_t);
2722 ec = new VarExp(0, fd);
2723 arguments = new Expressions();
2724 arguments->push(e);
2725 arguments->push(new IntegerExp(0, size, Type::tsize_t));
2726 e = new CallExp(e->loc, ec, arguments);
2727 e->type = index->arrayOf();
2729 else if (ident == Id::values)
2731 Expression *ec;
2732 FuncDeclaration *fd;
2733 Expressions *arguments;
2735 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaValues,
2736 Type::tvoid->arrayOf(), Type::tsize_t, Type::tsize_t);
2737 ec = new VarExp(0, fd);
2738 arguments = new Expressions();
2739 arguments->push(e);
2740 size_t keysize = index->size(e->loc);
2741 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1);
2742 arguments->push(new IntegerExp(0, keysize, Type::tsize_t));
2743 arguments->push(new IntegerExp(0, next->size(e->loc), Type::tsize_t));
2744 e = new CallExp(e->loc, ec, arguments);
2745 e->type = next->arrayOf();
2747 else if (ident == Id::rehash)
2749 Expression *ec;
2750 FuncDeclaration *fd;
2751 Expressions *arguments;
2753 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaRehash);
2754 ec = new VarExp(0, fd);
2755 arguments = new Expressions();
2756 arguments->push(e->addressOf(sc));
2757 arguments->push(index->getInternalTypeInfo(sc));
2758 e = new CallExp(e->loc, ec, arguments);
2759 e->type = this;
2761 else
2763 e = Type::dotExp(sc, e, ident);
2765 return e;
2768 void TypeAArray::toDecoBuffer(OutBuffer *buf, int flag)
2770 Type::toDecoBuffer(buf, flag);
2771 index->toDecoBuffer(buf);
2772 next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod);
2775 void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2777 if (mod != this->mod)
2778 { toCBuffer3(buf, hgs, mod);
2779 return;
2781 next->toCBuffer2(buf, hgs, this->mod);
2782 buf->writeByte('[');
2783 index->toCBuffer2(buf, hgs, 0);
2784 buf->writeByte(']');
2787 Expression *TypeAArray::defaultInit(Loc loc)
2789 #if LOGDEFAULTINIT
2790 printf("TypeAArray::defaultInit() '%s'\n", toChars());
2791 #endif
2792 Expression *e;
2793 e = new NullExp(loc);
2794 e->type = this;
2795 return e;
2798 int TypeAArray::checkBoolean()
2800 return TRUE;
2803 int TypeAArray::hasPointers()
2805 return TRUE;
2808 MATCH TypeAArray::implicitConvTo(Type *to)
2810 //printf("TypeAArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars());
2811 if (equals(to))
2812 return MATCHexact;
2813 if (to->ty == Taarray)
2814 { TypeAArray *ta = (TypeAArray *)to;
2816 if (!(next->mod == ta->next->mod || ta->next->mod == MODconst))
2817 return MATCHnomatch; // not const-compatible
2819 if (!(index->mod == ta->index->mod || ta->index->mod == MODconst))
2820 return MATCHnomatch; // not const-compatible
2822 MATCH m = next->constConv(ta->next);
2823 MATCH mi = index->constConv(ta->index);
2824 if (m != MATCHnomatch && mi != MATCHnomatch)
2826 if (m == MATCHexact && mod != to->mod)
2827 m = MATCHconst;
2828 if (mi < m)
2829 m = mi;
2830 return m;
2833 return Type::implicitConvTo(to);
2836 MATCH TypeAArray::constConv(Type *to)
2838 if (to->ty == Taarray)
2840 TypeAArray *taa = (TypeAArray *)to;
2841 MATCH mindex = index->constConv(taa->index);
2842 MATCH mkey = next->constConv(taa->next);
2843 // Pick the worst match
2844 return mkey < mindex ? mkey : mindex;
2846 else
2847 return Type::constConv(to);
2850 /***************************** TypeMaybe *****************************/
2852 TypeMaybe::TypeMaybe(Type *t)
2853 : TypeNext(Tmaybe, t)
2857 Type *TypeMaybe::syntaxCopy()
2859 Type *t = next->syntaxCopy();
2860 if (t == next)
2861 t = this;
2862 else
2863 t = new TypeMaybe(t);
2864 return t;
2867 Type *TypeMaybe::toBasetype()
2869 return next->toBasetype();
2872 Expression *TypeMaybe::dotExp(Scope *sc, Expression *e, Identifier *ident)
2874 if (sc->module->isDltFile)
2875 e->error("attempt to access property '%s' for '%s' of type '%s', which may be null.",
2876 ident->string, e->toChars(), toChars());
2877 // else it came from D - ignore any problems since we can't check
2878 return next->dotExp(sc, e, ident);
2881 Type *TypeMaybe::semantic(Loc loc, Scope *sc)
2883 //printf("TypeMaybe::semantic()\n");
2884 Type *n = next->semantic(loc, sc);
2886 switch (n->ty)
2888 case Tpointer:
2889 if (n->nextOf()->ty == Tvoid)
2890 return n;
2891 break;
2892 case Tclass:
2893 break;
2894 default:
2895 error(loc, "can't have maybe for %s of type %d", n->toChars(), n->toBasetype()->ty);
2896 return n;
2898 if (n != next)
2899 deco = NULL;
2900 next = n;
2901 return merge();
2904 d_uns64 TypeMaybe::size(Loc loc)
2906 return next->size();
2909 void TypeMaybe::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2911 //printf("TypeMaybe::toCBuffer2() next = %d\n", next->ty);
2912 if (mod != this->mod)
2913 { toCBuffer3(buf, hgs, mod);
2914 return;
2916 next->toCBuffer2(buf, hgs, this->mod);
2917 buf->writeByte('?');
2920 MATCH TypeMaybe::implicitConvTo(Type *to)
2922 //printf("TypeMaybe::implicitConvTo(%s)\n", to->toChars());
2924 if (this == to)
2925 return MATCHexact;
2927 if (to->ty == Tmaybe)
2929 // Allow (Subclass?) -> (ParentClass?)
2930 return next->implicitConvTo(to->nextOf());
2933 // Deny (Subclass?) -> (ParentClass)
2934 // (Subclass) -> (ParentClass?) handled in TypeClass
2936 // Can always convert Foo*? to void*
2937 if (to->ty == Tpointer && to->nextOf())
2939 if (to->nextOf()->ty == Tvoid)
2940 return MATCHconvert;
2943 return MATCHnomatch;
2946 int TypeMaybe::isscalar()
2948 return next->isscalar();
2951 Expression *TypeMaybe::defaultInit(Loc loc)
2953 #if LOGDEFAULTINIT
2954 printf("TypeMaybe::defaultInit() '%s'\n", toChars());
2955 #endif
2956 return next->defaultInit();
2959 int TypeMaybe::isZeroInit()
2961 return next->isZeroInit();
2964 int TypeMaybe::hasPointers()
2966 return next->hasPointers();
2969 int TypeMaybe::checkBoolean()
2971 return TRUE;
2974 /***************************** TypePointer *****************************/
2976 TypePointer::TypePointer(Type *t)
2977 : TypeNext(Tpointer, t)
2981 Type *TypePointer::syntaxCopy()
2983 Type *t = next->syntaxCopy();
2984 if (t == next)
2985 t = this;
2986 else
2987 { t = new TypePointer(t);
2988 t->mod = mod;
2990 return t;
2993 Type *TypePointer::semantic(Loc loc, Scope *sc)
2995 //printf("TypePointer::semantic()\n");
2996 Type *n = next->semantic(loc, sc);
2997 switch (n->toBasetype()->ty)
2999 case Ttuple:
3000 error(loc, "can't have pointer to %s", n->toChars());
3001 n = tint32;
3002 break;
3004 if (n != next)
3005 deco = NULL;
3006 next = n;
3007 if (mod == MODconst && !next->isInvariant())
3008 next = next->constOf();
3009 else if (mod == MODinvariant)
3010 next = next->invariantOf();
3011 return merge();
3015 d_uns64 TypePointer::size(Loc loc)
3017 return PTRSIZE;
3020 void TypePointer::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3022 //printf("TypePointer::toCBuffer2() next = %d\n", next->ty);
3023 if (mod != this->mod)
3024 { toCBuffer3(buf, hgs, mod);
3025 return;
3027 next->toCBuffer2(buf, hgs, this->mod);
3028 if (next->ty != Tfunction)
3029 buf->writeByte('*');
3032 MATCH TypePointer::implicitConvTo(Type *to)
3034 //printf("TypePointer::implicitConvTo(to = %s) %s\n", to->toChars(), toChars());
3036 if (equals(to))
3037 return MATCHexact;
3039 // Can always convert a "Foo*" to a "Foo*?"
3040 if (to->ty == Tmaybe)
3041 to = to->nextOf();
3043 if (to->ty == Tpointer)
3044 { TypePointer *tp = (TypePointer *)to;
3045 assert(tp->next);
3047 if (!(next->mod == tp->next->mod || tp->next->mod == MODconst))
3048 return MATCHnomatch; // not const-compatible
3050 /* Alloc conversion to void[]
3052 if (next->ty != Tvoid && tp->next->ty == Tvoid)
3054 return MATCHconvert;
3057 MATCH m = next->constConv(tp->next);
3058 if (m != MATCHnomatch)
3060 if (m == MATCHexact && mod != to->mod)
3061 m = MATCHconst;
3062 return m;
3065 /* Conversion of ptr to derived to ptr to base
3067 target_ptrdiff_t offset = 0;
3068 if (tp->next->isBaseOf(next, &offset) && offset == 0)
3069 return MATCHconvert;
3071 return MATCHnomatch;
3074 int TypePointer::isscalar()
3076 return TRUE;
3079 Expression *TypePointer::defaultInit(Loc loc)
3081 #if LOGDEFAULTINIT
3082 printf("TypePointer::defaultInit() '%s'\n", toChars());
3083 #endif
3084 Expression *e;
3085 e = new NullExp(loc);
3086 e->type = this;
3087 return e;
3090 int TypePointer::isZeroInit()
3092 return 1;
3095 int TypePointer::hasPointers()
3097 return TRUE;
3101 /***************************** TypeReference *****************************/
3103 TypeReference::TypeReference(Type *t)
3104 : TypeNext(Treference, t)
3106 // BUG: what about references to static arrays?
3109 Type *TypeReference::syntaxCopy()
3111 Type *t = next->syntaxCopy();
3112 if (t == next)
3113 t = this;
3114 else
3115 { t = new TypeReference(t);
3116 t->mod = mod;
3118 return t;
3121 Type *TypeReference::semantic(Loc loc, Scope *sc)
3123 //printf("TypeReference::semantic()\n");
3124 Type *n = next->semantic(loc, sc);
3125 if (n != next)
3126 deco = NULL;
3127 next = n;
3128 if (mod == MODconst && !next->isInvariant())
3129 next = next->constOf();
3130 else if (mod == MODinvariant)
3131 next = next->invariantOf();
3132 return merge();
3136 d_uns64 TypeReference::size(Loc loc)
3138 return PTRSIZE;
3141 void TypeReference::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3143 if (mod != this->mod)
3144 { toCBuffer3(buf, hgs, mod);
3145 return;
3147 next->toCBuffer2(buf, hgs, this->mod);
3148 buf->writeByte('&');
3151 Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident)
3153 #if LOGDOTEXP
3154 printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
3155 #endif
3157 // References just forward things along
3158 return next->dotExp(sc, e, ident);
3161 Expression *TypeReference::defaultInit(Loc loc)
3163 #if LOGDEFAULTINIT
3164 printf("TypeReference::defaultInit() '%s'\n", toChars());
3165 #endif
3166 Expression *e;
3167 e = new NullExp(loc);
3168 e->type = this;
3169 return e;
3172 int TypeReference::isZeroInit()
3174 return 1;
3178 /***************************** TypeFunction *****************************/
3180 TypeFunction::TypeFunction(Arguments *parameters, Type *treturn, int varargs, enum LINK linkage)
3181 : TypeNext(Tfunction, treturn)
3183 //if (!treturn) *(char*)0=0;
3184 // assert(treturn);
3185 this->parameters = parameters;
3186 this->varargs = varargs;
3187 this->linkage = linkage;
3188 this->inuse = 0;
3189 this->isnothrow = false;
3190 this->ispure = false;
3193 Type *TypeFunction::syntaxCopy()
3195 Type *treturn = next ? next->syntaxCopy() : NULL;
3196 Arguments *params = Argument::arraySyntaxCopy(parameters);
3197 TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage);
3198 t->mod = mod;
3199 t->isnothrow = isnothrow;
3200 t->ispure = ispure;
3201 return t;
3204 /*******************************
3205 * Returns:
3206 * 0 types are distinct
3207 * 1 this is covariant with t
3208 * 2 arguments match as far as overloading goes,
3209 * but types are not covariant
3210 * 3 cannot determine covariance because of forward references
3213 int Type::covariant(Type *t)
3215 #if 0
3216 printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars());
3217 printf("deco = %p, %p\n", deco, t->deco);
3218 //printf("ty = %d\n", next->ty);
3219 #endif
3221 int inoutmismatch = 0;
3223 if (equals(t))
3224 goto Lcovariant;
3225 if (ty != Tfunction || t->ty != Tfunction)
3226 goto Ldistinct;
3229 TypeFunction *t1 = (TypeFunction *)this;
3230 TypeFunction *t2 = (TypeFunction *)t;
3232 if (t1->varargs != t2->varargs)
3233 goto Ldistinct;
3235 /* Can convert pure to impure, and nothrow to throw
3237 if (!t1->ispure && t2->ispure)
3238 goto Ldistinct;
3240 if (!t1->isnothrow && t2->isnothrow)
3241 goto Ldistinct;
3243 if (t1->parameters && t2->parameters)
3245 size_t dim = Argument::dim(t1->parameters);
3246 if (dim != Argument::dim(t2->parameters))
3247 goto Ldistinct;
3249 for (size_t i = 0; i < dim; i++)
3250 { Argument *arg1 = Argument::getNth(t1->parameters, i);
3251 Argument *arg2 = Argument::getNth(t2->parameters, i);
3253 if (!arg1->type->equals(arg2->type))
3254 goto Ldistinct;
3255 if (arg1->storageClass != arg2->storageClass)
3256 inoutmismatch = 1;
3259 else if (t1->parameters != t2->parameters)
3260 goto Ldistinct;
3262 // The argument lists match
3263 if (inoutmismatch)
3264 goto Lnotcovariant;
3265 if (t1->linkage != t2->linkage)
3266 goto Lnotcovariant;
3268 // Return types
3269 Type *t1n = t1->next;
3270 Type *t2n = t2->next;
3272 if (t1n->equals(t2n))
3273 goto Lcovariant;
3275 if (t2n->ty == Tmaybe)
3277 t2n = t2n->nextOf(); // Foo -> Foo? is OK
3278 if (t1n->ty == Tmaybe)
3279 t1n = t1n->nextOf(); // Foo? -> Foo? is OK
3282 if (t1n->ty == Tclass && t2n->ty == Tclass)
3284 /* If same class type, but t2n is const, then it's
3285 * covariant. Do this test first because it can work on
3286 * forward references.
3288 if (((TypeClass *)t1n)->sym == ((TypeClass *)t2n)->sym &&
3289 t2n->mod == MODconst)
3290 goto Lcovariant;
3292 // If t1n is forward referenced:
3293 ClassDeclaration *cd = ((TypeClass *)t1n)->sym;
3294 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
3296 return 3;
3299 if (t1n->implicitConvTo(t2n))
3300 goto Lcovariant;
3301 goto Lnotcovariant;
3304 Lcovariant:
3305 //printf("\tcovaraint: 1\n");
3306 return 1;
3308 Ldistinct:
3309 //printf("\tcovaraint: 0\n");
3310 return 0;
3312 Lnotcovariant:
3313 //printf("\tcovaraint: 2\n");
3314 return 2;
3317 void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag)
3318 { unsigned char mc;
3320 //printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars());
3321 //static int nest; if (++nest == 50) *(char*)0=0;
3322 if (inuse)
3323 { inuse = 2; // flag error to caller
3324 return;
3326 inuse++;
3327 #if 1
3328 if (mod == MODconst)
3329 buf->writeByte('x');
3330 else if (mod == MODinvariant)
3331 buf->writeByte('y');
3332 #endif
3333 switch (linkage)
3335 case LINKd: mc = 'F'; break;
3336 case LINKc: mc = 'U'; break;
3337 case LINKwindows: mc = 'W'; break;
3338 case LINKpascal: mc = 'V'; break;
3339 case LINKcpp: mc = 'R'; break;
3340 case LINKgobject: mc = 'O'; break;
3341 default:
3342 assert(0);
3344 buf->writeByte(mc);
3345 if (ispure || isnothrow)
3346 { buf->writeByte('N');
3347 buf->writeByte(ispure ? 'a' : 'b');
3349 // Write argument types
3350 Argument::argsToDecoBuffer(buf, parameters);
3351 //if (buf->data[buf->offset - 1] == '@') halt();
3352 buf->writeByte('Z' - varargs); // mark end of arg list
3353 next->toDecoBuffer(buf);
3354 inuse--;
3357 void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
3359 //printf("TypeFunction::toCBuffer() this = %p %s\n", this, toChars());
3360 char *p = NULL;
3362 if (inuse)
3363 { inuse = 2; // flag error to caller
3364 return;
3366 inuse++;
3368 /* Use 'storage class' style for attributes
3370 switch (mod)
3372 case 0:
3373 break;
3374 case MODconst:
3375 buf->writestring("const ");
3376 break;
3377 case MODinvariant:
3378 buf->writestring("invariant ");
3379 break;
3380 default:
3381 assert(0);
3382 break;
3384 if (ispure)
3385 buf->writestring("pure ");
3386 if (isnothrow)
3387 buf->writestring("pure ");
3389 if (next && (!ident || ident->toHChars2() == ident->toChars()))
3390 next->toCBuffer2(buf, hgs, 0);
3391 if (hgs->ddoc != 1)
3393 switch (linkage)
3395 case LINKd: p = NULL; break;
3396 case LINKc: p = "C "; break;
3397 case LINKwindows: p = "Windows "; break;
3398 case LINKpascal: p = "Pascal "; break;
3399 case LINKcpp: p = "C++ "; break;
3400 default:
3401 assert(0);
3405 if (!hgs->hdrgen && p)
3406 buf->writestring(p);
3407 if (ident)
3408 { buf->writeByte(' ');
3409 buf->writestring(ident->toHChars2());
3411 Argument::argsToCBuffer(buf, hgs, parameters, varargs);
3412 inuse--;
3415 void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3417 //printf("TypeFunction::toCBuffer2() this = %p %s\n", this, toChars());
3418 char *p = NULL;
3420 if (inuse)
3421 { inuse = 2; // flag error to caller
3422 return;
3424 inuse++;
3425 if (next)
3426 next->toCBuffer2(buf, hgs, 0);
3427 if (hgs->ddoc != 1)
3429 switch (linkage)
3431 case LINKd: p = NULL; break;
3432 case LINKc: p = "C "; break;
3433 case LINKwindows: p = "Windows "; break;
3434 case LINKpascal: p = "Pascal "; break;
3435 case LINKcpp: p = "C++ "; break;
3436 default:
3437 assert(0);
3441 if (!hgs->hdrgen && p)
3442 buf->writestring(p);
3443 buf->writestring(" function");
3444 Argument::argsToCBuffer(buf, hgs, parameters, varargs);
3446 /* Use postfix style for attributes
3448 if (mod != this->mod)
3450 switch (mod)
3452 case 0:
3453 break;
3454 case MODconst:
3455 buf->writestring(" const");
3456 break;
3457 case MODinvariant:
3458 buf->writestring(" invariant");
3459 break;
3460 default:
3461 assert(0);
3462 break;
3465 if (ispure)
3466 buf->writestring(" pure");
3467 if (isnothrow)
3468 buf->writestring(" pure");
3470 inuse--;
3473 Type *TypeFunction::semantic(Loc loc, Scope *sc)
3475 if (deco) // if semantic() already run
3477 //printf("already done\n");
3478 return this;
3480 //printf("TypeFunction::semantic() this = %p\n", this);
3482 TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
3483 memcpy(tf, this, sizeof(TypeFunction));
3484 if (parameters)
3485 { tf->parameters = (Arguments *)parameters->copy();
3486 for (size_t i = 0; i < parameters->dim; i++)
3487 { Argument *arg = (Argument *)parameters->data[i];
3488 Argument *cpy = (Argument *)mem.malloc(sizeof(Argument));
3489 memcpy(cpy, arg, sizeof(Argument));
3490 tf->parameters->data[i] = (void *)cpy;
3494 tf->linkage = sc->linkage;
3495 if (!tf->next)
3497 assert(global.errors);
3498 tf->next = tvoid;
3500 tf->next = tf->next->semantic(loc,sc);
3501 if (tf->next->toBasetype()->ty == Tsarray)
3502 { error(loc, "functions cannot return static array %s", tf->next->toChars());
3503 tf->next = Type::terror;
3505 if (tf->next->toBasetype()->ty == Tfunction)
3506 { error(loc, "functions cannot return a function");
3507 tf->next = Type::terror;
3509 if (tf->next->toBasetype()->ty == Ttuple)
3510 { error(loc, "functions cannot return a tuple");
3511 tf->next = Type::terror;
3513 if (tf->next->isauto() && !(sc->flags & SCOPEctor))
3514 error(loc, "functions cannot return auto %s", tf->next->toChars());
3516 if (tf->parameters)
3517 { size_t dim = Argument::dim(tf->parameters);
3519 for (size_t i = 0; i < dim; i++)
3520 { Argument *arg = Argument::getNth(tf->parameters, i);
3521 Type *t;
3523 tf->inuse++;
3524 arg->type = arg->type->semantic(loc,sc);
3525 if (tf->inuse == 1) tf->inuse--;
3527 if (arg->storageClass & (STCconst | STCin))
3529 if (!arg->type->isInvariant())
3530 arg->type = arg->type->constOf();
3532 else if (arg->storageClass & STCinvariant)
3533 arg->type = arg->type->invariantOf();
3535 t = arg->type->toBasetype();
3537 if (arg->storageClass & (STCout | STCref | STClazy))
3539 if (t->ty == Tsarray)
3540 error(loc, "cannot have out or ref parameter of type %s", t->toChars());
3541 if (arg->storageClass & STCout && arg->type->mod)
3542 error(loc, "cannot have const/invariant out parameter of type %s", t->toChars());
3544 if (!(arg->storageClass & STClazy) && t->ty == Tvoid)
3545 error(loc, "cannot have parameter of type %s", arg->type->toChars());
3547 if (arg->defaultArg)
3549 arg->defaultArg = arg->defaultArg->semantic(sc);
3550 arg->defaultArg = resolveProperties(sc, arg->defaultArg);
3551 arg->defaultArg = arg->defaultArg->implicitCastTo(sc, arg->type);
3554 /* If arg turns out to be a tuple, the number of parameters may
3555 * change.
3557 if (t->ty == Ttuple)
3558 { dim = Argument::dim(tf->parameters);
3559 i--;
3563 tf->deco = tf->merge()->deco;
3565 if (tf->inuse)
3566 { error(loc, "recursive type");
3567 tf->inuse = 0;
3568 return terror;
3571 if (tf->varargs == 1 && tf->linkage != LINKd && Argument::dim(tf->parameters) == 0)
3572 error(loc, "variadic functions with non-D linkage must have at least one parameter");
3574 /* Don't return merge(), because arg identifiers and default args
3575 * can be different
3576 * even though the types match
3578 return tf;
3581 /********************************
3582 * 'args' are being matched to function 'this'
3583 * Determine match level.
3584 * Returns:
3585 * MATCHxxxx
3588 int TypeFunction::callMatch(Expression *ethis, Expressions *args)
3590 //printf("TypeFunction::callMatch() %s\n", toChars());
3591 MATCH match = MATCHexact; // assume exact match
3593 if (ethis)
3594 { Type *t = ethis->type;
3595 if (t->toBasetype()->ty == Tpointer)
3596 t = t->toBasetype()->nextOf(); // change struct* to struct
3597 if (t->mod != mod)
3599 if (mod == MODconst)
3600 match = MATCHconst;
3601 else
3602 return MATCHnomatch;
3606 size_t nparams = Argument::dim(parameters);
3607 size_t nargs = args ? args->dim : 0;
3608 if (nparams == nargs)
3610 else if (nargs > nparams)
3612 if (varargs == 0)
3613 goto Nomatch; // too many args; no match
3614 match = MATCHconvert; // match ... with a "conversion" match level
3617 for (size_t u = 0; u < nparams; u++)
3618 { MATCH m;
3619 Expression *arg;
3621 // BUG: what about out and ref?
3623 Argument *p = Argument::getNth(parameters, u);
3624 assert(p);
3625 if (u >= nargs)
3627 if (p->defaultArg)
3628 continue;
3629 if (varargs == 2 && u + 1 == nparams)
3630 goto L1;
3631 goto Nomatch; // not enough arguments
3633 arg = (Expression *)args->data[u];
3634 assert(arg);
3635 if (p->storageClass & STClazy && p->type->ty == Tvoid &&
3636 arg->type->ty != Tvoid)
3637 m = MATCHconvert;
3638 else
3639 m = arg->implicitConvTo(p->type);
3640 //printf("\tm = %d\n", m);
3641 if (m == MATCHnomatch) // if no match
3644 if (varargs == 2 && u + 1 == nparams) // if last varargs param
3645 { Type *tb = p->type->toBasetype();
3646 TypeSArray *tsa;
3647 integer_t sz;
3649 switch (tb->ty)
3651 case Tsarray:
3652 tsa = (TypeSArray *)tb;
3653 sz = tsa->dim->toInteger();
3654 if (sz != nargs - u)
3655 goto Nomatch;
3656 case Tarray:
3657 { TypeArray *ta = (TypeArray *)tb;
3658 for (; u < nargs; u++)
3660 arg = (Expression *)args->data[u];
3661 assert(arg);
3662 #if 1
3663 /* If lazy array of delegates,
3664 * convert arg(s) to delegate(s)
3666 Type *tret = p->isLazyArray();
3667 if (tret)
3669 if (ta->next->equals(arg->type))
3670 { m = MATCHexact;
3672 else
3674 m = arg->implicitConvTo(tret);
3675 if (m == MATCHnomatch)
3677 if (tret->toBasetype()->ty == Tvoid)
3678 m = MATCHconvert;
3682 else
3683 m = arg->implicitConvTo(ta->next);
3684 #else
3685 m = arg->implicitConvTo(ta->next);
3686 #endif
3687 if (m == MATCHnomatch)
3688 goto Nomatch;
3689 if (m < match)
3690 match = m;
3692 goto Ldone;
3694 case Tclass:
3695 // Should see if there's a constructor match?
3696 // Or just leave it ambiguous?
3697 goto Ldone;
3699 default:
3700 goto Nomatch;
3703 goto Nomatch;
3705 if (m < match)
3706 match = m; // pick worst match
3709 Ldone:
3710 //printf("match = %d\n", match);
3711 return match;
3713 Nomatch:
3714 //printf("no match\n");
3715 return MATCHnomatch;
3718 Type *TypeFunction::reliesOnTident()
3720 if (parameters)
3722 for (size_t i = 0; i < parameters->dim; i++)
3723 { Argument *arg = (Argument *)parameters->data[i];
3724 Type *t = arg->type->reliesOnTident();
3725 if (t)
3726 return t;
3729 return next->reliesOnTident();
3732 /***************************** TypeDelegate *****************************/
3734 TypeDelegate::TypeDelegate(Type *t)
3735 : TypeNext(Tfunction, t)
3737 ty = Tdelegate;
3740 Type *TypeDelegate::syntaxCopy()
3742 Type *t = next->syntaxCopy();
3743 if (t == next)
3744 t = this;
3745 else
3746 { t = new TypeDelegate(t);
3747 t->mod = mod;
3749 return t;
3752 Type *TypeDelegate::semantic(Loc loc, Scope *sc)
3754 if (deco) // if semantic() already run
3756 //printf("already done\n");
3757 return this;
3759 next = next->semantic(loc,sc);
3760 return merge();
3763 d_uns64 TypeDelegate::size(Loc loc)
3765 return PTRSIZE * 2;
3768 void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3770 if (mod != this->mod)
3771 { toCBuffer3(buf, hgs, mod);
3772 return;
3774 TypeFunction *tf = (TypeFunction *)next;
3776 tf->next->toCBuffer2(buf, hgs, 0);
3777 buf->writestring(" delegate");
3778 Argument::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs);
3781 Expression *TypeDelegate::defaultInit(Loc loc)
3783 #if LOGDEFAULTINIT
3784 printf("TypeDelegate::defaultInit() '%s'\n", toChars());
3785 #endif
3786 Expression *e;
3787 e = new NullExp(loc);
3788 e->type = this;
3789 return e;
3792 int TypeDelegate::isZeroInit()
3794 return 1;
3797 int TypeDelegate::checkBoolean()
3799 return TRUE;
3802 Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident)
3804 #if LOGDOTEXP
3805 printf("TypeDelegate::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
3806 #endif
3807 if (ident == Id::ptr)
3809 #ifndef IN_GCC
3810 e->type = tvoidptr;
3811 #else
3812 if (e->op == TOKdelegate || e->op == TOKcast)
3813 e = e->castTo(sc, tvoidptr); // Not an lvalue
3814 else
3816 e = e->addressOf(sc);
3817 e = e->castTo(sc, tvoidptr->pointerTo());
3818 e = new PtrExp(e->loc, e);
3819 e->type = tvoidptr;
3821 #endif
3822 return e;
3824 else if (ident == Id::funcptr)
3826 e = e->addressOf(sc);
3827 e->type = tvoidptr;
3828 e = new AddExp(e->loc, e, new IntegerExp(PTRSIZE));
3829 e->type = tvoidptr;
3830 e = new PtrExp(e->loc, e);
3831 e->type = next->pointerTo();
3832 return e;
3834 else
3836 e = Type::dotExp(sc, e, ident);
3838 return e;
3841 int TypeDelegate::hasPointers()
3843 return TRUE;
3848 /***************************** TypeQualified *****************************/
3850 TypeQualified::TypeQualified(TY ty, Loc loc)
3851 : Type(ty)
3853 this->loc = loc;
3856 void TypeQualified::syntaxCopyHelper(TypeQualified *t)
3858 //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t->toChars(), toChars());
3859 idents.setDim(t->idents.dim);
3860 for (int i = 0; i < idents.dim; i++)
3862 Identifier *id = (Identifier *)t->idents.data[i];
3863 if (id->dyncast() == DYNCAST_DSYMBOL)
3865 TemplateInstance *ti = (TemplateInstance *)id;
3867 ti = (TemplateInstance *)ti->syntaxCopy(NULL);
3868 id = (Identifier *)ti;
3870 idents.data[i] = id;
3875 void TypeQualified::addIdent(Identifier *ident)
3877 idents.push(ident);
3880 void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs)
3882 int i;
3884 for (i = 0; i < idents.dim; i++)
3885 { Identifier *id = (Identifier *)idents.data[i];
3887 buf->writeByte('.');
3889 if (id->dyncast() == DYNCAST_DSYMBOL)
3891 TemplateInstance *ti = (TemplateInstance *)id;
3892 ti->toCBuffer(buf, hgs);
3894 else
3895 buf->writestring(id->toChars());
3899 d_uns64 TypeQualified::size(Loc loc)
3901 error(this->loc, "size of type %s is not known", toChars());
3902 return 1;
3905 /*************************************
3906 * Takes an array of Identifiers and figures out if
3907 * it represents a Type or an Expression.
3908 * Output:
3909 * if expression, *pe is set
3910 * if type, *pt is set
3913 void TypeQualified::resolveHelper(Loc loc, Scope *sc,
3914 Dsymbol *s, Dsymbol *scopesym,
3915 Expression **pe, Type **pt, Dsymbol **ps)
3917 VarDeclaration *v;
3918 EnumMember *em;
3919 TupleDeclaration *td;
3920 Expression *e;
3922 #if 0
3923 printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, toChars());
3924 if (scopesym)
3925 printf("\tscopesym = '%s'\n", scopesym->toChars());
3926 #endif
3927 *pe = NULL;
3928 *pt = NULL;
3929 *ps = NULL;
3930 if (s)
3932 //printf("\t1: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3933 s = s->toAlias();
3934 //printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3935 for (int i = 0; i < idents.dim; i++)
3937 Identifier *id = (Identifier *)idents.data[i];
3938 Dsymbol *sm = s->searchX(loc, sc, id);
3939 //printf("\t3: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3940 //printf("\tgetType = '%s'\n", s->getType()->toChars());
3941 if (!sm)
3942 { Type *t;
3944 v = s->isVarDeclaration();
3945 if (v && id == Id::length)
3947 e = v->getConstInitializer();
3948 if (!e)
3949 e = new VarExp(loc, v);
3950 t = e->type;
3951 if (!t)
3952 goto Lerror;
3953 goto L3;
3955 t = s->getType();
3956 if (!t && s->isDeclaration())
3957 t = s->isDeclaration()->type;
3958 if (t)
3960 sm = t->toDsymbol(sc);
3961 if (sm)
3962 { sm = sm->search(loc, id, 0);
3963 if (sm)
3964 goto L2;
3966 //e = t->getProperty(loc, id);
3967 e = new TypeExp(loc, t);
3968 e = t->dotExp(sc, e, id);
3969 i++;
3971 for (; i < idents.dim; i++)
3973 id = (Identifier *)idents.data[i];
3974 //printf("e: '%s', id: '%s', type = %p\n", e->toChars(), id->toChars(), e->type);
3975 if (id == Id::offsetof)
3976 { e = new DotIdExp(e->loc, e, id);
3977 e = e->semantic(sc);
3979 else
3980 e = e->type->dotExp(sc, e, id);
3982 *pe = e;
3984 else
3985 Lerror:
3986 error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
3987 return;
3990 s = sm->toAlias();
3993 v = s->isVarDeclaration();
3994 if (v)
3996 #if 0
3997 // It's not a type, it's an expression
3998 Expression *e = v->getConstInitializer();
3999 if (e)
4001 *pe = e->copy(); // make copy so we can change loc
4002 (*pe)->loc = loc;
4004 else
4005 #endif
4007 #if 0
4008 WithScopeSymbol *withsym;
4009 if (scopesym && (withsym = scopesym->isWithScopeSymbol()) != NULL)
4011 // Same as wthis.ident
4012 e = new VarExp(loc, withsym->withstate->wthis);
4013 e = new DotIdExp(loc, e, ident);
4014 //assert(0); // BUG: should handle this
4016 else
4017 #endif
4018 *pe = new VarExp(loc, v);
4020 return;
4022 em = s->isEnumMember();
4023 if (em)
4025 // It's not a type, it's an expression
4026 *pe = em->value->copy();
4027 return;
4031 Type *t = s->getType();
4032 if (!t)
4034 // If the symbol is an import, try looking inside the import
4035 Import *si;
4037 si = s->isImport();
4038 if (si)
4040 s = si->search(loc, s->ident, 0);
4041 if (s && s != si)
4042 goto L1;
4043 s = si;
4045 *ps = s;
4046 return;
4048 if (t->ty == Tinstance && t != this && !t->deco)
4049 { error(loc, "forward reference to '%s'", t->toChars());
4050 return;
4053 if (t != this)
4055 if (t->reliesOnTident())
4057 Scope *scx;
4059 for (scx = sc; 1; scx = scx->enclosing)
4061 if (!scx)
4062 { error(loc, "forward reference to '%s'", t->toChars());
4063 return;
4065 if (scx->scopesym == scopesym)
4066 break;
4068 t = t->semantic(loc, scx);
4069 //((TypeIdentifier *)t)->resolve(loc, scx, pe, &t, ps);
4072 if (t->ty == Ttuple)
4073 *pt = t;
4074 else
4075 *pt = t->merge();
4077 if (!s)
4079 error(loc, "identifier '%s' is not defined", toChars());
4083 /***************************** TypeIdentifier *****************************/
4085 TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident)
4086 : TypeQualified(Tident, loc)
4088 this->ident = ident;
4089 this->maybe = 0;
4093 Type *TypeIdentifier::syntaxCopy()
4095 TypeIdentifier *t;
4097 t = new TypeIdentifier(loc, ident);
4098 t->maybe = maybe;
4099 t->syntaxCopyHelper(this);
4100 t->mod = mod;
4101 return t;
4104 void TypeIdentifier::toDecoBuffer(OutBuffer *buf, int flag)
4105 { unsigned len;
4106 char *name;
4108 Type::toDecoBuffer(buf, flag);
4109 name = ident->toChars();
4110 len = strlen(name);
4111 buf->printf("%d%s", len, name);
4114 void TypeIdentifier::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4116 if (mod != this->mod)
4117 { toCBuffer3(buf, hgs, mod);
4118 return;
4120 buf->writestring(this->ident->toChars());
4121 toCBuffer2Helper(buf, hgs);
4124 /*************************************
4125 * Takes an array of Identifiers and figures out if
4126 * it represents a Type or an Expression.
4127 * Output:
4128 * if expression, *pe is set
4129 * if type, *pt is set
4132 void TypeIdentifier::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
4133 { Dsymbol *s;
4134 Dsymbol *scopesym;
4136 //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars());
4137 s = sc->search(loc, ident, &scopesym);
4138 resolveHelper(loc, sc, s, scopesym, pe, pt, ps);
4139 if (*pt && mod)
4141 if (mod & MODconst)
4142 *pt = (*pt)->constOf();
4143 else if (mod & MODinvariant)
4144 *pt = (*pt)->invariantOf();
4148 /*****************************************
4149 * See if type resolves to a symbol, if so,
4150 * return that symbol.
4153 Dsymbol *TypeIdentifier::toDsymbol(Scope *sc)
4155 //printf("TypeIdentifier::toDsymbol('%s')\n", toChars());
4156 if (!sc)
4157 return NULL;
4158 //printf("ident = '%s'\n", ident->toChars());
4160 Dsymbol *scopesym;
4161 Dsymbol *s = sc->search(loc, ident, &scopesym);
4162 if (s)
4164 for (int i = 0; i < idents.dim; i++)
4166 Identifier *id = (Identifier *)idents.data[i];
4167 s = s->searchX(loc, sc, id);
4168 if (!s) // failed to find a symbol
4169 { //printf("\tdidn't find a symbol\n");
4170 break;
4174 return s;
4177 Type *TypeIdentifier::semantic(Loc loc, Scope *sc)
4179 Type *t;
4180 Expression *e;
4181 Dsymbol *s;
4183 //printf("TypeIdentifier::semantic(%s)\n", toChars());
4184 resolve(loc, sc, &e, &t, &s);
4185 if (t)
4187 //printf("\tit's a type %d, %s, %s\n", t->ty, t->toChars(), t->deco);
4189 if (t->ty == Ttypedef)
4190 { TypeTypedef *tt = (TypeTypedef *)t;
4192 if (tt->sym->sem == 1)
4193 error(loc, "circular reference of typedef %s", tt->toChars());
4195 if (isConst())
4196 t = t->constOf();
4197 else if (isInvariant())
4198 t = t->invariantOf();
4200 // Do the delayed wrapping now we're sure it's a type
4201 if (maybe) {
4202 return t->maybe(false)->semantic(loc, sc);
4205 else
4207 #ifdef DEBUG
4208 if (!global.gag)
4209 printf("1: ");
4210 #endif
4211 if (s)
4213 s->error(loc, "is used as a type");
4214 //halt();
4216 else
4217 error(loc, "%s is used as a type", toChars());
4218 t = tvoid;
4220 //t->print();
4221 return t;
4224 Type *TypeIdentifier::reliesOnTident()
4226 return this;
4229 Expression *TypeIdentifier::toExpression()
4231 Expression *e = new IdentifierExp(loc, ident);
4232 for (int i = 0; i < idents.dim; i++)
4234 Identifier *id = (Identifier *)idents.data[i];
4235 e = new DotIdExp(loc, e, id);
4238 return e;
4241 /***************************** TypeInstance *****************************/
4243 TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst)
4244 : TypeQualified(Tinstance, loc)
4246 this->tempinst = tempinst;
4249 Type *TypeInstance::syntaxCopy()
4251 //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim);
4252 TypeInstance *t;
4254 t = new TypeInstance(loc, (TemplateInstance *)tempinst->syntaxCopy(NULL));
4255 t->syntaxCopyHelper(this);
4256 t->mod = mod;
4257 return t;
4261 void TypeInstance::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4263 if (mod != this->mod)
4264 { toCBuffer3(buf, hgs, mod);
4265 return;
4267 tempinst->toCBuffer(buf, hgs);
4268 toCBuffer2Helper(buf, hgs);
4271 void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
4273 // Note close similarity to TypeIdentifier::resolve()
4275 Dsymbol *s;
4277 *pe = NULL;
4278 *pt = NULL;
4279 *ps = NULL;
4281 #if 0
4282 if (!idents.dim)
4284 error(loc, "template instance '%s' has no identifier", toChars());
4285 return;
4287 #endif
4288 //id = (Identifier *)idents.data[0];
4289 //printf("TypeInstance::resolve(sc = %p, idents = '%s')\n", sc, id->toChars());
4290 s = tempinst;
4291 if (s)
4292 s->semantic(sc);
4293 resolveHelper(loc, sc, s, NULL, pe, pt, ps);
4294 if (*pt && mod)
4296 if (mod & MODconst)
4297 *pt = (*pt)->constOf();
4298 else if (mod & MODinvariant)
4299 *pt = (*pt)->invariantOf();
4301 //printf("pt = '%s'\n", (*pt)->toChars());
4304 Type *TypeInstance::semantic(Loc loc, Scope *sc)
4306 Type *t;
4307 Expression *e;
4308 Dsymbol *s;
4310 //printf("TypeInstance::semantic(%s)\n", toChars());
4312 if (sc->parameterSpecialization)
4314 unsigned errors = global.errors;
4315 global.gag++;
4317 resolve(loc, sc, &e, &t, &s);
4319 global.gag--;
4320 if (errors != global.errors)
4321 { if (global.gag == 0)
4322 global.errors = errors;
4323 return this;
4326 else
4327 resolve(loc, sc, &e, &t, &s);
4329 if (!t)
4331 #ifdef DEBUG
4332 printf("2: ");
4333 #endif
4334 error(loc, "%s is used as a type", toChars());
4335 t = tvoid;
4337 return t;
4341 /***************************** TypeTypeof *****************************/
4343 TypeTypeof::TypeTypeof(Loc loc, Expression *exp)
4344 : TypeQualified(Ttypeof, loc)
4346 this->exp = exp;
4349 Type *TypeTypeof::syntaxCopy()
4351 TypeTypeof *t;
4353 t = new TypeTypeof(loc, exp->syntaxCopy());
4354 t->syntaxCopyHelper(this);
4355 t->mod = mod;
4356 return t;
4359 Dsymbol *TypeTypeof::toDsymbol(Scope *sc)
4361 Type *t;
4363 t = semantic(0, sc);
4364 if (t == this)
4365 return NULL;
4366 return t->toDsymbol(sc);
4369 void TypeTypeof::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4371 if (mod != this->mod)
4372 { toCBuffer3(buf, hgs, mod);
4373 return;
4375 buf->writestring("typeof(");
4376 exp->toCBuffer(buf, hgs);
4377 buf->writeByte(')');
4378 toCBuffer2Helper(buf, hgs);
4381 Type *TypeTypeof::semantic(Loc loc, Scope *sc)
4382 { Expression *e;
4383 Type *t;
4385 //printf("TypeTypeof::semantic() %p\n", this);
4387 //static int nest; if (++nest == 50) *(char*)0=0;
4389 #if 0
4390 /* Special case for typeof(this) and typeof(super) since both
4391 * should work even if they are not inside a non-static member function
4393 if (exp->op == TOKthis || exp->op == TOKsuper)
4395 // Find enclosing struct or class
4396 for (Dsymbol *s = sc->parent; 1; s = s->parent)
4398 ClassDeclaration *cd;
4399 StructDeclaration *sd;
4401 if (!s)
4403 error(loc, "%s is not in a struct or class scope", exp->toChars());
4404 goto Lerr;
4406 cd = s->isClassDeclaration();
4407 if (cd)
4409 if (exp->op == TOKsuper)
4411 cd = cd->baseClass;
4412 if (!cd)
4413 { error(loc, "class %s has no 'super'", s->toChars());
4414 goto Lerr;
4417 t = cd->type;
4418 break;
4420 sd = s->isStructDeclaration();
4421 if (sd)
4423 if (exp->op == TOKsuper)
4425 error(loc, "struct %s has no 'super'", sd->toChars());
4426 goto Lerr;
4428 t = sd->type->pointerTo();
4429 break;
4433 else
4434 #endif
4436 sc->intypeof++;
4437 exp = exp->semantic(sc);
4438 sc->intypeof--;
4439 t = exp->type;
4440 if (!t)
4442 error(loc, "expression (%s) has no type", exp->toChars());
4443 goto Lerr;
4445 if (t->ty == Ttypeof)
4446 error(loc, "forward reference to %s", toChars());
4448 /* typeof should reflect the true type,
4449 * not what 'auto' would have gotten us.
4451 //t = t->toHeadMutable();
4454 if (idents.dim)
4456 Dsymbol *s = t->toDsymbol(sc);
4457 for (size_t i = 0; i < idents.dim; i++)
4459 if (!s)
4460 break;
4461 Identifier *id = (Identifier *)idents.data[i];
4462 s = s->searchX(loc, sc, id);
4464 if (s)
4466 t = s->getType();
4467 if (!t)
4468 { error(loc, "%s is not a type", s->toChars());
4469 goto Lerr;
4472 else
4473 { error(loc, "cannot resolve .property for %s", toChars());
4474 goto Lerr;
4477 return t;
4479 Lerr:
4480 return tvoid;
4483 d_uns64 TypeTypeof::size(Loc loc)
4485 if (exp->type)
4486 return exp->type->size(loc);
4487 else
4488 return TypeQualified::size(loc);
4493 /***************************** TypeReturn *****************************/
4495 TypeReturn::TypeReturn(Loc loc)
4496 : TypeQualified(Treturn, loc)
4500 Type *TypeReturn::syntaxCopy()
4502 TypeReturn *t = new TypeReturn(loc);
4503 t->syntaxCopyHelper(this);
4504 t->mod = mod;
4505 return t;
4508 Dsymbol *TypeReturn::toDsymbol(Scope *sc)
4510 Type *t = semantic(0, sc);
4511 if (t == this)
4512 return NULL;
4513 return t->toDsymbol(sc);
4516 Type *TypeReturn::semantic(Loc loc, Scope *sc)
4518 Type *t;
4519 if (!sc->func)
4520 { error(loc, "typeof(return) must be inside function");
4521 goto Lerr;
4523 t = sc->func->type->nextOf();
4525 if (mod & MODinvariant)
4526 t = t->invariantOf();
4527 else if (mod & MODconst)
4528 t = t->constOf();
4530 if (idents.dim)
4532 Dsymbol *s = t->toDsymbol(sc);
4533 for (size_t i = 0; i < idents.dim; i++)
4535 if (!s)
4536 break;
4537 Identifier *id = (Identifier *)idents.data[i];
4538 s = s->searchX(loc, sc, id);
4540 if (s)
4542 t = s->getType();
4543 if (!t)
4544 { error(loc, "%s is not a type", s->toChars());
4545 goto Lerr;
4548 else
4549 { error(loc, "cannot resolve .property for %s", toChars());
4550 goto Lerr;
4553 return t;
4555 Lerr:
4556 return terror;
4559 void TypeReturn::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4561 if (mod != this->mod)
4562 { toCBuffer3(buf, hgs, mod);
4563 return;
4565 buf->writestring("typeof(return)");
4566 toCBuffer2Helper(buf, hgs);
4570 /***************************** TypeEnum *****************************/
4572 TypeEnum::TypeEnum(EnumDeclaration *sym)
4573 : Type(Tenum)
4575 this->sym = sym;
4578 char *TypeEnum::toChars()
4580 if (mod)
4581 return Type::toChars();
4582 return sym->toChars();
4585 Type *TypeEnum::semantic(Loc loc, Scope *sc)
4587 //printf("TypeEnum::semantic() %s\n", toChars());
4588 sym->semantic(sc);
4589 return merge();
4592 d_uns64 TypeEnum::size(Loc loc)
4594 if (!sym->memtype)
4596 error(loc, "enum %s is forward referenced", sym->toChars());
4597 return 4;
4599 return sym->memtype->size(loc);
4602 unsigned TypeEnum::alignsize()
4604 if (!sym->memtype)
4606 #ifdef DEBUG
4607 printf("1: ");
4608 #endif
4609 error(0, "enum %s is forward referenced", sym->toChars());
4610 return 4;
4612 return sym->memtype->alignsize();
4615 Dsymbol *TypeEnum::toDsymbol(Scope *sc)
4617 return sym;
4620 Type *TypeEnum::toBasetype()
4622 if (!sym->memtype)
4624 #ifdef DEBUG
4625 printf("2: ");
4626 #endif
4627 error(sym->loc, "enum %s is forward referenced", sym->toChars());
4628 return tint32;
4630 return sym->memtype->toBasetype();
4633 void TypeEnum::toDecoBuffer(OutBuffer *buf, int flag)
4634 { char *name;
4636 name = sym->mangle();
4637 Type::toDecoBuffer(buf, flag);
4638 buf->printf("%s", name);
4641 void TypeEnum::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4643 if (mod != this->mod)
4644 { toCBuffer3(buf, hgs, mod);
4645 return;
4647 buf->writestring(sym->toChars());
4650 Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident)
4652 #if LOGDOTEXP
4653 printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars());
4654 #endif
4655 Dsymbol *s = sym->search(e->loc, ident, 0);
4656 if (!s)
4658 return getProperty(e->loc, ident);
4660 EnumMember *m = s->isEnumMember();
4661 Expression *em = m->value->copy();
4662 em->loc = e->loc;
4663 return em;
4666 Expression *TypeEnum::getProperty(Loc loc, Identifier *ident)
4667 { Expression *e;
4669 if (ident == Id::max)
4671 if (!sym->maxval)
4672 goto Lfwd;
4673 e = sym->maxval;
4675 else if (ident == Id::min)
4677 if (!sym->minval)
4678 goto Lfwd;
4679 e = sym->minval;
4681 else if (ident == Id::init)
4683 e = defaultInit(loc);
4685 else
4687 e = toBasetype()->getProperty(loc, ident);
4689 return e;
4691 Lfwd:
4692 error(loc, "forward reference of %s.%s", toChars(), ident->toChars());
4693 return new IntegerExp(0, 0, this);
4696 int TypeEnum::isintegral()
4698 return 1;
4701 int TypeEnum::isfloating()
4703 return 0;
4706 int TypeEnum::isunsigned()
4708 return sym->memtype->isunsigned();
4711 int TypeEnum::isscalar()
4713 return 1;
4714 //return sym->memtype->isscalar();
4717 MATCH TypeEnum::implicitConvTo(Type *to)
4718 { MATCH m;
4720 //printf("TypeEnum::implicitConvTo()\n");
4721 if (ty == to->ty && sym == ((TypeEnum *)to)->sym)
4722 m = (mod == to->mod) ? MATCHexact : MATCHconst;
4723 else if (sym->memtype->implicitConvTo(to))
4724 m = MATCHconvert; // match with conversions
4725 else
4726 m = MATCHnomatch; // no match
4727 return m;
4730 MATCH TypeEnum::constConv(Type *to)
4732 if (equals(to))
4733 return MATCHexact;
4734 if (ty == to->ty && sym == ((TypeEnum *)to)->sym &&
4735 to->mod == MODconst)
4736 return MATCHconst;
4737 return MATCHnomatch;
4741 Expression *TypeEnum::defaultInit(Loc loc)
4743 #if LOGDEFAULTINIT
4744 printf("TypeEnum::defaultInit() '%s'\n", toChars());
4745 #endif
4746 // Initialize to first member of enum
4747 //printf("%s\n", sym->defaultval->type->toChars());
4748 if (!sym->defaultval)
4750 error(loc, "forward reference of %s.init", toChars());
4751 return new IntegerExp(0, 0, this);
4753 return sym->defaultval;
4756 int TypeEnum::isZeroInit()
4758 return sym->defaultval->isBool(FALSE);
4761 int TypeEnum::hasPointers()
4763 return toBasetype()->hasPointers();
4766 /***************************** TypeTypedef *****************************/
4768 TypeTypedef::TypeTypedef(TypedefDeclaration *sym)
4769 : Type(Ttypedef)
4771 this->sym = sym;
4774 Type *TypeTypedef::syntaxCopy()
4776 return this;
4779 char *TypeTypedef::toChars()
4781 return Type::toChars();
4784 Type *TypeTypedef::semantic(Loc loc, Scope *sc)
4786 //printf("TypeTypedef::semantic(%s), sem = %d\n", toChars(), sym->sem);
4787 sym->semantic(sc);
4788 return merge();
4791 d_uns64 TypeTypedef::size(Loc loc)
4793 return sym->basetype->size(loc);
4796 unsigned TypeTypedef::alignsize()
4798 return sym->basetype->alignsize();
4801 Dsymbol *TypeTypedef::toDsymbol(Scope *sc)
4803 return sym;
4806 Type *TypeTypedef::toHeadMutable()
4808 if (!mod)
4809 return this;
4811 Type *tb = toBasetype();
4812 Type *t = tb->toHeadMutable();
4813 if (t->equals(tb))
4814 return this;
4815 else
4816 return mutableOf();
4819 void TypeTypedef::toDecoBuffer(OutBuffer *buf, int flag)
4821 char *name;
4823 Type::toDecoBuffer(buf, flag);
4824 name = sym->mangle();
4825 buf->printf("%s", name);
4828 void TypeTypedef::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4830 //printf("TypeTypedef::toCBuffer2() '%s'\n", sym->toChars());
4831 if (mod != this->mod)
4832 { toCBuffer3(buf, hgs, mod);
4833 return;
4835 buf->writestring(sym->toChars());
4838 Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident)
4840 #if LOGDOTEXP
4841 printf("TypeTypedef::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars());
4842 #endif
4843 if (ident == Id::init)
4845 return Type::dotExp(sc, e, ident);
4847 return sym->basetype->dotExp(sc, e, ident);
4850 Expression *TypeTypedef::getProperty(Loc loc, Identifier *ident)
4852 #if LOGDOTEXP
4853 printf("TypeTypedef::getProperty(ident = '%s') '%s'\n", ident->toChars(), toChars());
4854 #endif
4855 if (ident == Id::init)
4857 return Type::getProperty(loc, ident);
4859 return sym->basetype->getProperty(loc, ident);
4862 int TypeTypedef::isintegral()
4864 //printf("TypeTypedef::isintegral()\n");
4865 //printf("sym = '%s'\n", sym->toChars());
4866 //printf("basetype = '%s'\n", sym->basetype->toChars());
4867 return sym->basetype->isintegral();
4870 int TypeTypedef::isfloating()
4872 return sym->basetype->isfloating();
4875 int TypeTypedef::isreal()
4877 return sym->basetype->isreal();
4880 int TypeTypedef::isimaginary()
4882 return sym->basetype->isimaginary();
4885 int TypeTypedef::iscomplex()
4887 return sym->basetype->iscomplex();
4890 int TypeTypedef::isunsigned()
4892 return sym->basetype->isunsigned();
4895 int TypeTypedef::isscalar()
4897 return sym->basetype->isscalar();
4900 int TypeTypedef::isAssignable()
4902 return sym->basetype->isAssignable();
4905 int TypeTypedef::checkBoolean()
4907 return sym->basetype->checkBoolean();
4910 Type *TypeTypedef::toBasetype()
4912 if (sym->inuse)
4914 sym->error("circular definition");
4915 sym->basetype = Type::terror;
4916 return Type::terror;
4918 sym->inuse = 1;
4919 Type *t = sym->basetype->toBasetype();
4920 sym->inuse = 0;
4921 if (mod == MODconst && !t->isInvariant())
4922 t = t->constOf();
4923 else if (mod == MODinvariant)
4924 t = t->invariantOf();
4925 return t;
4928 MATCH TypeTypedef::implicitConvTo(Type *to)
4929 { MATCH m;
4931 //printf("TypeTypedef::implicitConvTo(to = %s) %s\n", to->toChars(), toChars());
4932 if (equals(to))
4933 m = MATCHexact; // exact match
4934 else if (sym->basetype->implicitConvTo(to))
4935 m = MATCHconvert; // match with conversions
4936 else if (ty == to->ty && sym == ((TypeTypedef *)to)->sym)
4938 m = constConv(to);
4940 else
4941 m = MATCHnomatch; // no match
4942 return m;
4945 MATCH TypeTypedef::constConv(Type *to)
4947 if (equals(to))
4948 return MATCHexact;
4949 if (ty == to->ty && sym == ((TypeTypedef *)to)->sym)
4950 return sym->basetype->implicitConvTo(((TypeTypedef *)to)->sym->basetype);
4951 return MATCHnomatch;
4955 Expression *TypeTypedef::defaultInit(Loc loc)
4956 { Expression *e;
4957 Type *bt;
4959 #if LOGDEFAULTINIT
4960 printf("TypeTypedef::defaultInit() '%s'\n", toChars());
4961 #endif
4962 if (sym->init)
4964 //sym->init->toExpression()->print();
4965 return sym->init->toExpression();
4967 bt = sym->basetype;
4968 e = bt->defaultInit(loc);
4969 e->type = this;
4970 while (bt->ty == Tsarray)
4971 { TypeSArray *tsa = (TypeSArray *)bt;
4972 e->type = tsa->next;
4973 bt = tsa->next->toBasetype();
4975 return e;
4978 int TypeTypedef::isZeroInit()
4980 if (sym->init)
4982 if (sym->init->isVoidInitializer())
4983 return 1; // initialize voids to 0
4984 Expression *e = sym->init->toExpression();
4985 if (e && e->isBool(FALSE))
4986 return 1;
4987 return 0; // assume not
4989 if (sym->inuse)
4991 sym->error("circular definition");
4992 sym->basetype = Type::terror;
4994 sym->inuse = 1;
4995 int result = sym->basetype->isZeroInit();
4996 sym->inuse = 0;
4997 return result;
5000 int TypeTypedef::hasPointers()
5002 return toBasetype()->hasPointers();
5005 /***************************** TypeStruct *****************************/
5007 TypeStruct::TypeStruct(StructDeclaration *sym)
5008 : Type(Tstruct)
5010 this->sym = sym;
5013 char *TypeStruct::toChars()
5015 //printf("sym.parent: %s, deco = %s\n", sym->parent->toChars(), deco);
5016 if (mod)
5017 return Type::toChars();
5018 TemplateInstance *ti = sym->parent->isTemplateInstance();
5019 if (ti && ti->toAlias() == sym)
5021 return ti->toChars();
5023 return sym->toChars();
5026 Type *TypeStruct::syntaxCopy()
5028 return this;
5031 Type *TypeStruct::semantic(Loc loc, Scope *sc)
5033 //printf("TypeStruct::semantic('%s')\n", sym->toChars());
5035 /* Cannot do semantic for sym because scope chain may not
5036 * be right.
5038 //sym->semantic(sc);
5040 return merge();
5043 d_uns64 TypeStruct::size(Loc loc)
5045 return sym->size(loc);
5048 unsigned TypeStruct::alignsize()
5049 { target_size_t sz;
5051 sym->size(0); // give error for forward references
5052 sz = sym->alignsize;
5053 if (sz > sym->structalign)
5054 sz = sym->structalign;
5055 return sz;
5058 Dsymbol *TypeStruct::toDsymbol(Scope *sc)
5060 return sym;
5063 void TypeStruct::toDecoBuffer(OutBuffer *buf, int flag)
5065 char *name;
5067 name = sym->mangle();
5068 //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", toChars(), name);
5069 Type::toDecoBuffer(buf, flag);
5070 buf->printf("%s", name);
5073 void TypeStruct::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
5075 if (mod != this->mod)
5076 { toCBuffer3(buf, hgs, mod);
5077 return;
5079 TemplateInstance *ti = sym->parent->isTemplateInstance();
5080 if (ti && ti->toAlias() == sym)
5081 buf->writestring(ti->toChars());
5082 else
5083 buf->writestring(sym->toChars());
5086 Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
5087 { unsigned offset;
5089 Expression *b;
5090 VarDeclaration *v;
5091 Dsymbol *s;
5092 DotVarExp *de;
5093 Declaration *d;
5095 #if LOGDOTEXP
5096 printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
5097 #endif
5098 if (!sym->members)
5100 error(e->loc, "struct %s is forward referenced", sym->toChars());
5101 return new IntegerExp(e->loc, 0, Type::tint32);
5104 /* If e.tupleof
5106 if (ident == Id::tupleof)
5108 /* Create a TupleExp out of the fields of the struct e:
5109 * (e.field0, e.field1, e.field2, ...)
5111 e = e->semantic(sc); // do this before turning on noaccesscheck
5112 Expressions *exps = new Expressions;
5113 exps->reserve(sym->fields.dim);
5114 for (size_t i = 0; i < sym->fields.dim; i++)
5115 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
5116 Expression *fe = new DotVarExp(e->loc, e, v);
5117 exps->push(fe);
5119 e = new TupleExp(e->loc, exps);
5120 sc = sc->push();
5121 sc->noaccesscheck = 1;
5122 e = e->semantic(sc);
5123 sc->pop();
5124 return e;
5127 if (e->op == TOKdotexp)
5128 { DotExp *de = (DotExp *)e;
5130 if (de->e1->op == TOKimport)
5132 assert(0); // cannot find a case where this happens; leave
5133 // assert in until we do
5134 ScopeExp *se = (ScopeExp *)de->e1;
5136 s = se->sds->search(e->loc, ident, 0);
5137 e = de->e1;
5138 goto L1;
5142 s = sym->search(e->loc, ident, 0);
5144 if (!s)
5146 if (ident != Id::__sizeof &&
5147 ident != Id::alignof &&
5148 ident != Id::init &&
5149 ident != Id::mangleof &&
5150 ident != Id::stringof &&
5151 ident != Id::offsetof)
5153 /* Look for overloaded opDot() to see if we should forward request
5154 * to it.
5156 Dsymbol *fd = search_function(sym, Id::opDot);
5157 if (fd)
5158 { /* Rewrite e.ident as:
5159 * e.opId().ident
5161 e = build_overload(e->loc, sc, e, NULL, fd->ident);
5162 e = new DotIdExp(e->loc, e, ident);
5163 return e->semantic(sc);
5166 return Type::dotExp(sc, e, ident);
5168 s = s->toAlias();
5170 v = s->isVarDeclaration();
5171 if (v && !v->isDataseg())
5173 Expression *ei = v->getConstInitializer();
5174 if (ei)
5175 { e = ei->copy(); // need to copy it if it's a StringExp
5176 e = e->semantic(sc);
5177 return e;
5181 if (s->getType())
5183 //return new DotTypeExp(e->loc, e, s);
5184 return new TypeExp(e->loc, s->getType());
5187 EnumMember *em = s->isEnumMember();
5188 if (em)
5190 assert(em->value);
5191 return em->value->copy();
5194 TemplateMixin *tm = s->isTemplateMixin();
5195 if (tm)
5197 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
5198 de->type = e->type;
5199 return de;
5202 TemplateDeclaration *td = s->isTemplateDeclaration();
5203 if (td)
5205 e = new DotTemplateExp(e->loc, e, td);
5206 e->semantic(sc);
5207 return e;
5210 TemplateInstance *ti = s->isTemplateInstance();
5211 if (ti)
5212 { if (!ti->semanticdone)
5213 ti->semantic(sc);
5214 s = ti->inst->toAlias();
5215 if (!s->isTemplateInstance())
5216 goto L1;
5217 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
5218 de->type = e->type;
5219 return de;
5222 d = s->isDeclaration();
5223 #ifdef DEBUG
5224 if (!d)
5225 printf("d = %s '%s'\n", s->kind(), s->toChars());
5226 #endif
5227 assert(d);
5229 if (e->op == TOKtype)
5230 { FuncDeclaration *fd = sc->func;
5232 if (d->needThis() && fd && fd->vthis)
5234 e = new DotVarExp(e->loc, new ThisExp(e->loc), d);
5235 e = e->semantic(sc);
5236 return e;
5238 if (d->isTupleDeclaration())
5240 e = new TupleExp(e->loc, d->isTupleDeclaration());
5241 e = e->semantic(sc);
5242 return e;
5244 return new VarExp(e->loc, d, 1);
5247 if (d->isDataseg())
5249 // (e, d)
5250 VarExp *ve;
5252 accessCheck(e->loc, sc, e, d);
5253 ve = new VarExp(e->loc, d);
5254 e = new CommaExp(e->loc, e, ve);
5255 e->type = d->type;
5256 return e;
5259 if (v)
5261 if (v->toParent() != sym)
5262 sym->error(e->loc, "'%s' is not a member", v->toChars());
5264 // *(&e + offset)
5265 accessCheck(e->loc, sc, e, d);
5266 b = new AddrExp(e->loc, e);
5267 b->type = e->type->pointerTo();
5268 b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tsize_t));
5269 b->type = v->type->pointerTo();
5270 b = new PtrExp(e->loc, b);
5271 b->type = v->type;
5272 if (e->type->isConst())
5273 b->type = b->type->constOf();
5274 else if (e->type->isInvariant())
5275 b->type = b->type->invariantOf();
5276 return b;
5279 de = new DotVarExp(e->loc, e, d);
5280 return de->semantic(sc);
5283 unsigned TypeStruct::memalign(unsigned salign)
5285 sym->size(0); // give error for forward references
5286 return sym->structalign;
5289 Expression *TypeStruct::defaultInit(Loc loc)
5290 { Symbol *s;
5291 Declaration *d;
5293 #if LOGDEFAULTINIT
5294 printf("TypeStruct::defaultInit() '%s'\n", toChars());
5295 #endif
5296 s = sym->toInitializer();
5297 d = new SymbolDeclaration(sym->loc, s, sym);
5298 assert(d);
5299 d->type = this;
5300 return new VarExp(sym->loc, d);
5303 int TypeStruct::isZeroInit()
5305 return sym->zeroInit;
5308 int TypeStruct::checkBoolean()
5310 return FALSE;
5313 int TypeStruct::isAssignable()
5315 /* If any of the fields are const or invariant,
5316 * then one cannot assign this struct.
5318 for (size_t i = 0; i < sym->fields.dim; i++)
5319 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
5320 if (v->isConst() || v->isInvariant())
5321 return FALSE;
5323 return TRUE;
5326 int TypeStruct::hasPointers()
5328 StructDeclaration *s = sym;
5330 sym->size(0); // give error for forward references
5331 for (size_t i = 0; i < s->fields.dim; i++)
5333 Dsymbol *sm = (Dsymbol *)s->fields.data[i];
5334 if (sm->hasPointers())
5335 return TRUE;
5337 return FALSE;
5340 MATCH TypeStruct::implicitConvTo(Type *to)
5341 { MATCH m;
5343 //printf("TypeStruct::implicitConvTo(%s => %s)\n", toChars(), to->toChars());
5344 if (ty == to->ty && sym == ((TypeStruct *)to)->sym)
5345 { m = MATCHexact; // exact match
5346 if (mod != to->mod)
5348 if (to->mod == MODconst)
5349 m = MATCHconst;
5350 else
5351 { /* Check all the fields. If they can all be converted,
5352 * allow the conversion.
5354 for (int i = 0; i < sym->fields.dim; i++)
5355 { Dsymbol *s = (Dsymbol *)sym->fields.data[i];
5356 VarDeclaration *v = s->isVarDeclaration();
5357 assert(v && v->storage_class & STCfield);
5359 // 'from' type
5360 Type *tvf = v->type;
5361 if (mod == MODconst)
5362 tvf = tvf->constOf();
5363 else if (mod == MODinvariant)
5364 tvf = tvf->invariantOf();
5366 // 'to' type
5367 Type *tv = v->type;
5368 if (to->mod == 0)
5369 tv = tv->mutableOf();
5370 else
5371 { assert(to->mod == MODinvariant);
5372 tv = tv->invariantOf();
5375 //printf("\t%s => %s, match = %d\n", v->type->toChars(), tv->toChars(), tvf->implicitConvTo(tv));
5376 if (tvf->implicitConvTo(tv) < MATCHconst)
5377 return MATCHnomatch;
5379 m = MATCHconst;
5383 else
5384 m = MATCHnomatch; // no match
5385 return m;
5388 Type *TypeStruct::toHeadMutable()
5390 return this;
5393 MATCH TypeStruct::constConv(Type *to)
5395 if (equals(to))
5396 return MATCHexact;
5397 if (ty == to->ty && sym == ((TypeStruct *)to)->sym &&
5398 to->mod == MODconst)
5399 return MATCHconst;
5400 return MATCHnomatch;
5404 /***************************** TypeClass *****************************/
5406 TypeClass::TypeClass(ClassDeclaration *sym)
5407 : Type(Tclass)
5409 this->sym = sym;
5412 char *TypeClass::toChars()
5414 if (mod)
5415 return Type::toChars();
5416 return sym->toPrettyChars();
5419 Type *TypeClass::syntaxCopy()
5421 return this;
5424 Type *TypeClass::semantic(Loc loc, Scope *sc)
5426 //printf("TypeClass::semantic(%s)\n", sym->toChars());
5427 if (sym->scope)
5428 sym->semantic(sym->scope);
5429 return merge();
5432 d_uns64 TypeClass::size(Loc loc)
5434 return PTRSIZE;
5437 Dsymbol *TypeClass::toDsymbol(Scope *sc)
5439 return sym;
5442 void TypeClass::toDecoBuffer(OutBuffer *buf, int flag)
5444 char *name;
5446 name = sym->mangle();
5447 //printf("TypeClass::toDecoBuffer('%s' flag=%d mod=%x) = '%s'\n", toChars(), flag, mod, name);
5448 Type::toDecoBuffer(buf, flag);
5449 buf->printf("%s", name);
5452 void TypeClass::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
5454 if (mod != this->mod)
5455 { toCBuffer3(buf, hgs, mod);
5456 return;
5458 buf->writestring(sym->toChars());
5461 Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
5462 { unsigned offset;
5464 Expression *b;
5465 VarDeclaration *v;
5466 Dsymbol *s;
5468 #if LOGDOTEXP
5469 printf("TypeClass::dotExp(e='%s', ident='%s')\n", e->toChars(), ident->toChars());
5470 #endif
5472 if (e->op == TOKdotexp)
5473 { DotExp *de = (DotExp *)e;
5475 if (de->e1->op == TOKimport)
5477 ScopeExp *se = (ScopeExp *)de->e1;
5479 s = se->sds->search(e->loc, ident, 0);
5480 e = de->e1;
5481 goto L1;
5485 if (ident == Id::tupleof)
5487 /* Create a TupleExp
5489 e = e->semantic(sc); // do this before turning on noaccesscheck
5490 Expressions *exps = new Expressions;
5491 exps->reserve(sym->fields.dim);
5492 for (size_t i = 0; i < sym->fields.dim; i++)
5493 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
5494 Expression *fe = new DotVarExp(e->loc, e, v);
5495 exps->push(fe);
5497 e = new TupleExp(e->loc, exps);
5498 sc = sc->push();
5499 sc->noaccesscheck = 1;
5500 e = e->semantic(sc);
5501 sc->pop();
5502 return e;
5505 s = sym->search(e->loc, ident, 0);
5507 if (!s)
5509 // See if it's a base class
5510 ClassDeclaration *cbase;
5511 for (cbase = sym->baseClass; cbase; cbase = cbase->baseClass)
5513 if (cbase->ident->equals(ident))
5515 e = new DotTypeExp(0, e, cbase);
5516 return e;
5520 if (ident == Id::classinfo)
5522 assert(ClassDeclaration::classinfo);
5523 Type *t = ClassDeclaration::classinfo->type;
5524 if (e->op == TOKtype || e->op == TOKdottype)
5526 /* For type.classinfo, we know the classinfo
5527 * at compile time.
5529 if (!sym->vclassinfo)
5530 sym->vclassinfo = new ClassInfoDeclaration(sym);
5531 e = new VarExp(e->loc, sym->vclassinfo);
5532 e = e->addressOf(sc);
5533 e->type = t; // do this so we don't get redundant dereference
5535 else
5536 { /* For class objects, the classinfo reference is the first
5537 * entry in the vtbl[]
5539 e = new PtrExp(e->loc, e);
5540 e->type = t->pointerTo();
5541 if (sym->isInterfaceDeclaration())
5543 if (sym->isCPPinterface())
5544 { /* C++ interface vtbl[]s are different in that the
5545 * first entry is always pointer to the first virtual
5546 * function, not classinfo.
5547 * We can't get a .classinfo for it.
5549 error(e->loc, "no .classinfo for C++ interface objects");
5551 /* For an interface, the first entry in the vtbl[]
5552 * is actually a pointer to an instance of struct Interface.
5553 * The first member of Interface is the .classinfo,
5554 * so add an extra pointer indirection.
5556 e->type = e->type->pointerTo();
5557 e = new PtrExp(e->loc, e);
5558 e->type = t->pointerTo();
5560 e = new PtrExp(e->loc, e, t);
5562 return e;
5565 if (ident == Id::typeinfo)
5567 if (!global.params.useDeprecated)
5568 error(e->loc, ".typeinfo deprecated, use typeid(type)");
5569 return getTypeInfo(sc);
5571 if (ident == Id::outer && sym->vthis)
5573 s = sym->vthis;
5575 else
5578 if (ident != Id::__sizeof &&
5579 ident != Id::alignof &&
5580 ident != Id::init &&
5581 ident != Id::mangleof &&
5582 ident != Id::stringof &&
5583 ident != Id::offsetof)
5585 /* Look for overloaded opDot() to see if we should forward request
5586 * to it.
5588 Dsymbol *fd = search_function(sym, Id::opDot);
5589 if (fd)
5590 { /* Rewrite e.ident as:
5591 * e.opId().ident
5593 e = build_overload(e->loc, sc, e, NULL, fd->ident);
5594 e = new DotIdExp(e->loc, e, ident);
5595 return e->semantic(sc);
5599 return Type::dotExp(sc, e, ident);
5602 s = s->toAlias();
5603 v = s->isVarDeclaration();
5604 if (v && !v->isDataseg())
5605 { Expression *ei = v->getConstInitializer();
5607 if (ei)
5608 { e = ei->copy(); // need to copy it if it's a StringExp
5609 e = e->semantic(sc);
5610 return e;
5614 if (s->getType())
5616 // if (e->op == TOKtype)
5617 return new TypeExp(e->loc, s->getType());
5618 // return new DotTypeExp(e->loc, e, s);
5621 EnumMember *em = s->isEnumMember();
5622 if (em)
5624 assert(em->value);
5625 return em->value->copy();
5628 TemplateMixin *tm = s->isTemplateMixin();
5629 if (tm)
5631 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
5632 de->type = e->type;
5633 return de;
5636 TemplateDeclaration *td = s->isTemplateDeclaration();
5637 if (td)
5639 e = new DotTemplateExp(e->loc, e, td);
5640 e->semantic(sc);
5641 return e;
5644 TemplateInstance *ti = s->isTemplateInstance();
5645 if (ti)
5646 { if (!ti->semanticdone)
5647 ti->semantic(sc);
5648 s = ti->inst->toAlias();
5649 if (!s->isTemplateInstance())
5650 goto L1;
5651 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
5652 de->type = e->type;
5653 return de;
5656 Declaration *d = s->isDeclaration();
5657 if (!d)
5659 e->error("%s.%s is not a declaration", e->toChars(), ident->toChars());
5660 return new IntegerExp(e->loc, 1, Type::tint32);
5663 if (e->op == TOKtype)
5665 /* It's:
5666 * Class.d
5668 if (d->needThis() && (hasThis(sc) || !d->isFuncDeclaration()))
5670 if (sc->func)
5672 ClassDeclaration *thiscd;
5673 thiscd = sc->func->toParent()->isClassDeclaration();
5675 if (thiscd)
5677 ClassDeclaration *cd = e->type->isClassHandle();
5679 if (cd == thiscd)
5681 e = new ThisExp(e->loc);
5682 e = new DotTypeExp(e->loc, e, cd);
5683 DotVarExp *de = new DotVarExp(e->loc, e, d);
5684 e = de->semantic(sc);
5685 return e;
5687 else if ((!cd || !cd->isBaseOf(thiscd, NULL)) &&
5688 !d->isFuncDeclaration())
5689 e->error("'this' is required, but %s is not a base class of %s", e->type->toChars(), thiscd->toChars());
5693 /* Rewrite as:
5694 * this.d
5696 DotVarExp *de = new DotVarExp(e->loc, new ThisExp(e->loc), d);
5697 e = de->semantic(sc);
5698 return e;
5700 else if (d->isTupleDeclaration())
5702 e = new TupleExp(e->loc, d->isTupleDeclaration());
5703 e = e->semantic(sc);
5704 return e;
5706 else
5708 VarExp *ve = new VarExp(e->loc, d, 1);
5709 return ve;
5713 if (d->isDataseg())
5715 // (e, d)
5716 VarExp *ve;
5718 accessCheck(e->loc, sc, e, d);
5719 ve = new VarExp(e->loc, d);
5720 e = new CommaExp(e->loc, e, ve);
5721 e->type = d->type;
5722 return e;
5725 if (d->parent && d->toParent()->isModule())
5727 // (e, d)
5729 VarExp *ve = new VarExp(e->loc, d, 1);
5730 e = new CommaExp(e->loc, e, ve);
5731 e->type = d->type;
5732 return e;
5735 DotVarExp *de = new DotVarExp(e->loc, e, d);
5736 return de->semantic(sc);
5739 ClassDeclaration *TypeClass::isClassHandle()
5741 return sym;
5744 int TypeClass::isauto()
5746 return sym->isauto;
5749 int TypeClass::isBaseOf(Type *t, target_ptrdiff_t *poffset)
5751 if (t->ty == Tclass)
5752 { ClassDeclaration *cd;
5754 cd = ((TypeClass *)t)->sym;
5755 if (sym->isBaseOf(cd, poffset))
5756 return 1;
5758 return 0;
5761 MATCH TypeClass::implicitConvTo(Type *to)
5763 //printf("TypeClass::implicitConvTo(to = '%s') %s\n", to->toChars(), toChars());
5765 // Can always convert a "Foo" to a "Foo?"
5766 if (to->ty == Tmaybe)
5767 to = to->nextOf();
5769 MATCH m = constConv(to);
5770 if (m != MATCHnomatch)
5771 return m;
5773 ClassDeclaration *cdto = to->isClassHandle();
5774 if (cdto && cdto->isBaseOf(sym, NULL))
5775 { //printf("'to' is base\n");
5776 return MATCHconvert;
5779 // Can convert any (D) instance to Object
5780 if (cdto == ClassDeclaration::object)
5782 if (sym->linkage != LINKd)
5783 return MATCHnomatch;
5784 return MATCHconvert;
5787 if (global.params.Dversion == 1)
5789 // Allow conversion to (void *)
5790 if (to->ty == Tpointer && ((TypePointer *)to)->next->ty == Tvoid)
5791 return MATCHconvert;
5794 return MATCHnomatch;
5797 MATCH TypeClass::constConv(Type *to)
5799 if (equals(to))
5800 return MATCHexact;
5801 if (ty == to->ty && sym == ((TypeClass *)to)->sym &&
5802 to->mod == MODconst)
5803 return MATCHconst;
5804 return MATCHnomatch;
5807 Type *TypeClass::toHeadMutable()
5809 return this;
5812 Expression *TypeClass::defaultInit(Loc loc)
5814 #if LOGDEFAULTINIT
5815 printf("TypeClass::defaultInit() '%s'\n", toChars());
5816 #endif
5817 Expression *e;
5818 e = new NullExp(loc);
5819 e->type = this;
5820 return e;
5823 int TypeClass::isZeroInit()
5825 return 1;
5828 int TypeClass::checkBoolean()
5830 return TRUE;
5833 int TypeClass::hasPointers()
5835 return TRUE;
5838 /***************************** TypeTuple *****************************/
5840 TypeTuple::TypeTuple(Arguments *arguments)
5841 : Type(Ttuple)
5843 //printf("TypeTuple(this = %p)\n", this);
5844 this->arguments = arguments;
5845 //printf("TypeTuple() %s\n", toChars());
5846 #ifdef DEBUG
5847 if (arguments)
5849 for (size_t i = 0; i < arguments->dim; i++)
5851 Argument *arg = (Argument *)arguments->data[i];
5852 assert(arg && arg->type);
5855 #endif
5858 /****************
5859 * Form TypeTuple from the types of the expressions.
5860 * Assume exps[] is already tuple expanded.
5863 TypeTuple::TypeTuple(Expressions *exps)
5864 : Type(Ttuple)
5866 Arguments *arguments = new Arguments;
5867 if (exps)
5869 arguments->setDim(exps->dim);
5870 for (size_t i = 0; i < exps->dim; i++)
5871 { Expression *e = (Expression *)exps->data[i];
5872 if (e->type->ty == Ttuple)
5873 e->error("cannot form tuple of tuples");
5874 Argument *arg = new Argument(STCundefined, e->type, NULL, NULL);
5875 arguments->data[i] = (void *)arg;
5878 this->arguments = arguments;
5881 Type *TypeTuple::syntaxCopy()
5883 Arguments *args = Argument::arraySyntaxCopy(arguments);
5884 Type *t = new TypeTuple(args);
5885 t->mod = mod;
5886 return t;
5889 Type *TypeTuple::semantic(Loc loc, Scope *sc)
5891 //printf("TypeTuple::semantic(this = %p)\n", this);
5892 //printf("TypeTuple::semantic() %s\n", toChars());
5893 if (!deco)
5894 deco = merge()->deco;
5896 /* Don't return merge(), because a tuple with one type has the
5897 * same deco as that type.
5899 return this;
5902 int TypeTuple::equals(Object *o)
5903 { Type *t;
5905 t = (Type *)o;
5906 //printf("TypeTuple::equals(%s, %s)\n", toChars(), t->toChars());
5907 if (this == t)
5909 return 1;
5911 if (t->ty == Ttuple)
5912 { TypeTuple *tt = (TypeTuple *)t;
5914 if (arguments->dim == tt->arguments->dim)
5916 for (size_t i = 0; i < tt->arguments->dim; i++)
5917 { Argument *arg1 = (Argument *)arguments->data[i];
5918 Argument *arg2 = (Argument *)tt->arguments->data[i];
5920 if (!arg1->type->equals(arg2->type))
5921 return 0;
5923 return 1;
5926 return 0;
5929 Type *TypeTuple::reliesOnTident()
5931 if (arguments)
5933 for (size_t i = 0; i < arguments->dim; i++)
5935 Argument *arg = (Argument *)arguments->data[i];
5936 Type *t = arg->type->reliesOnTident();
5937 if (t)
5938 return t;
5941 return NULL;
5944 #if 0
5945 Type *TypeTuple::makeConst()
5947 //printf("TypeTuple::makeConst() %s\n", toChars());
5948 if (cto)
5949 return cto;
5950 TypeTuple *t = (TypeTuple *)Type::makeConst();
5951 t->arguments = new Arguments();
5952 t->arguments->setDim(arguments->dim);
5953 for (size_t i = 0; i < arguments->dim; i++)
5954 { Argument *arg = (Argument *)arguments->data[i];
5955 Argument *narg = new Argument(arg->storageClass, arg->type->constOf(), arg->ident, arg->defaultArg);
5956 t->arguments->data[i] = (Argument *)narg;
5958 return t;
5960 #endif
5962 void TypeTuple::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
5964 Argument::argsToCBuffer(buf, hgs, arguments, 0);
5967 void TypeTuple::toDecoBuffer(OutBuffer *buf, int flag)
5969 //printf("TypeTuple::toDecoBuffer() this = %p, %s\n", this, toChars());
5970 Type::toDecoBuffer(buf, flag);
5971 OutBuffer buf2;
5972 Argument::argsToDecoBuffer(&buf2, arguments);
5973 unsigned len = buf2.offset;
5974 #if __NEWLIB_H__
5975 // newlib bug as of 1.14.0
5976 char * p = (char*) buf2.extractData();
5977 buf->printf("%d%.*s", len, len, p ? p : "");
5978 #else
5979 buf->printf("%d%.*s", len, len, (char *)buf2.extractData());
5980 #endif
5983 Expression *TypeTuple::getProperty(Loc loc, Identifier *ident)
5984 { Expression *e;
5986 #if LOGDOTEXP
5987 printf("TypeTuple::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars());
5988 #endif
5989 if (ident == Id::length)
5991 e = new IntegerExp(loc, arguments->dim, Type::tsize_t);
5993 else
5995 error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars());
5996 e = new IntegerExp(loc, 1, Type::tint32);
5998 return e;
6001 /***************************** TypeSlice *****************************/
6003 /* This is so we can slice a TypeTuple */
6005 TypeSlice::TypeSlice(Type *next, Expression *lwr, Expression *upr)
6006 : TypeNext(Tslice, next)
6008 //printf("TypeSlice[%s .. %s]\n", lwr->toChars(), upr->toChars());
6009 this->lwr = lwr;
6010 this->upr = upr;
6013 Type *TypeSlice::syntaxCopy()
6015 Type *t = new TypeSlice(next->syntaxCopy(), lwr->syntaxCopy(), upr->syntaxCopy());
6016 t->mod = mod;
6017 return t;
6020 Type *TypeSlice::semantic(Loc loc, Scope *sc)
6022 //printf("TypeSlice::semantic() %s\n", toChars());
6023 next = next->semantic(loc, sc);
6024 if (mod == MODconst && !next->isInvariant())
6025 next = next->constOf();
6026 else if (mod == MODinvariant)
6027 next = next->invariantOf();
6028 //printf("next: %s\n", next->toChars());
6030 Type *tbn = next->toBasetype();
6031 if (tbn->ty != Ttuple)
6032 { error(loc, "can only slice tuple types, not %s", tbn->toChars());
6033 return Type::terror;
6035 TypeTuple *tt = (TypeTuple *)tbn;
6037 lwr = semanticLength(sc, tbn, lwr);
6038 lwr = lwr->optimize(WANTvalue);
6039 uinteger_t i1 = lwr->toUInteger();
6041 upr = semanticLength(sc, tbn, upr);
6042 upr = upr->optimize(WANTvalue);
6043 uinteger_t i2 = upr->toUInteger();
6045 if (!(i1 <= i2 && i2 <= tt->arguments->dim))
6046 { error(loc, "slice [%"PRIuMAX"..%"PRIuMAX"] is out of range of [0..%u]", i1, i2, tt->arguments->dim);
6047 return Type::terror;
6050 Arguments *args = new Arguments;
6051 args->reserve(i2 - i1);
6052 for (size_t i = i1; i < i2; i++)
6053 { Argument *arg = (Argument *)tt->arguments->data[i];
6054 args->push(arg);
6057 return new TypeTuple(args);
6060 void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
6062 next->resolve(loc, sc, pe, pt, ps);
6063 if (*pe)
6064 { // It's really a slice expression
6065 Expression *e;
6066 e = new SliceExp(loc, *pe, lwr, upr);
6067 *pe = e;
6069 else if (*ps)
6070 { Dsymbol *s = *ps;
6071 TupleDeclaration *td = s->isTupleDeclaration();
6072 if (td)
6074 /* It's a slice of a TupleDeclaration
6076 ScopeDsymbol *sym = new ArrayScopeSymbol(sc, td);
6077 sym->parent = sc->scopesym;
6078 sc = sc->push(sym);
6080 lwr = lwr->semantic(sc);
6081 lwr = lwr->optimize(WANTvalue);
6082 uinteger_t i1 = lwr->toUInteger();
6084 upr = upr->semantic(sc);
6085 upr = upr->optimize(WANTvalue);
6086 uinteger_t i2 = upr->toUInteger();
6088 sc = sc->pop();
6090 if (!(i1 <= i2 && i2 <= td->objects->dim))
6091 { error(loc, "slice [%"PRIuMAX"u..%"PRIuMAX"u] is out of range of [0..%u]", i1, i2, td->objects->dim);
6092 goto Ldefault;
6095 if (i1 == 0 && i2 == td->objects->dim)
6097 *ps = td;
6098 return;
6101 /* Create a new TupleDeclaration which
6102 * is a slice [i1..i2] out of the old one.
6104 Objects *objects = new Objects;
6105 objects->setDim(i2 - i1);
6106 for (size_t i = 0; i < objects->dim; i++)
6108 objects->data[i] = td->objects->data[(size_t)i1 + i];
6111 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
6112 *ps = tds;
6114 else
6115 goto Ldefault;
6117 else
6119 Ldefault:
6120 Type::resolve(loc, sc, pe, pt, ps);
6124 void TypeSlice::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
6126 if (mod != this->mod)
6127 { toCBuffer3(buf, hgs, mod);
6128 return;
6130 next->toCBuffer2(buf, hgs, this->mod);
6132 buf->printf("[%s .. ", lwr->toChars());
6133 buf->printf("%s]", upr->toChars());
6136 /***************************** Argument *****************************/
6138 Argument::Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg)
6140 this->type = type;
6141 this->ident = ident;
6142 this->storageClass = storageClass;
6143 this->defaultArg = defaultArg;
6146 Argument *Argument::syntaxCopy()
6148 Argument *a = new Argument(storageClass,
6149 type ? type->syntaxCopy() : NULL,
6150 ident,
6151 defaultArg ? defaultArg->syntaxCopy() : NULL);
6152 return a;
6155 Arguments *Argument::arraySyntaxCopy(Arguments *args)
6156 { Arguments *a = NULL;
6158 if (args)
6160 a = new Arguments();
6161 a->setDim(args->dim);
6162 for (size_t i = 0; i < a->dim; i++)
6163 { Argument *arg = (Argument *)args->data[i];
6165 arg = arg->syntaxCopy();
6166 a->data[i] = (void *)arg;
6169 return a;
6172 char *Argument::argsTypesToChars(Arguments *args, int varargs)
6173 { OutBuffer *buf;
6175 buf = new OutBuffer();
6177 buf->writeByte('(');
6178 if (args)
6179 { int i;
6180 OutBuffer argbuf;
6181 HdrGenState hgs;
6183 for (i = 0; i < args->dim; i++)
6184 { Argument *arg;
6186 if (i)
6187 buf->writeByte(',');
6188 arg = (Argument *)args->data[i];
6189 argbuf.reset();
6190 arg->type->toCBuffer2(&argbuf, &hgs, 0);
6191 buf->write(&argbuf);
6193 if (varargs)
6195 if (i && varargs == 1)
6196 buf->writeByte(',');
6197 buf->writestring("...");
6200 buf->writeByte(')');
6202 return buf->toChars();
6205 void Argument::argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs)
6207 buf->writeByte('(');
6208 if (arguments)
6209 { int i;
6210 OutBuffer argbuf;
6212 for (i = 0; i < arguments->dim; i++)
6213 { Argument *arg;
6215 if (i)
6216 buf->writestring(", ");
6217 arg = (Argument *)arguments->data[i];
6218 if (arg->storageClass & STCout)
6219 buf->writestring("out ");
6220 else if (arg->storageClass & STCref)
6221 buf->writestring((global.params.Dversion == 1)
6222 ? (char *)"inout " : (char *)"ref ");
6223 else if (arg->storageClass & STCin)
6224 buf->writestring("in ");
6225 else if (arg->storageClass & STClazy)
6226 buf->writestring("lazy ");
6227 if (arg->storageClass & STCconst)
6228 buf->writestring("const ");
6229 if (arg->storageClass & STCinvariant)
6230 buf->writestring("invariant ");
6231 argbuf.reset();
6232 arg->type->toCBuffer(&argbuf, arg->ident, hgs);
6233 if (arg->defaultArg)
6235 argbuf.writestring(" = ");
6236 arg->defaultArg->toCBuffer(&argbuf, hgs);
6238 buf->write(&argbuf);
6240 if (varargs)
6242 if (i && varargs == 1)
6243 buf->writeByte(',');
6244 buf->writestring("...");
6247 buf->writeByte(')');
6251 void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments)
6253 //printf("Argument::argsToDecoBuffer()\n");
6255 // Write argument types
6256 if (arguments)
6258 size_t dim = Argument::dim(arguments);
6259 for (size_t i = 0; i < dim; i++)
6261 Argument *arg = Argument::getNth(arguments, i);
6262 arg->toDecoBuffer(buf);
6267 /****************************************************
6268 * Determine if parameter is a lazy array of delegates.
6269 * If so, return the return type of those delegates.
6270 * If not, return NULL.
6273 Type *Argument::isLazyArray()
6275 // if (inout == Lazy)
6277 Type *tb = type->toBasetype();
6278 if (tb->ty == Tsarray || tb->ty == Tarray)
6280 Type *tel = ((TypeArray *)tb)->next->toBasetype();
6281 if (tel->ty == Tdelegate)
6283 TypeDelegate *td = (TypeDelegate *)tel;
6284 TypeFunction *tf = (TypeFunction *)td->next;
6286 if (!tf->varargs && Argument::dim(tf->parameters) == 0)
6288 return tf->next; // return type of delegate
6293 return NULL;
6296 void Argument::toDecoBuffer(OutBuffer *buf)
6298 switch (storageClass & (STCin | STCout | STCref | STClazy))
6299 { case 0:
6300 case STCin:
6301 break;
6302 case STCout:
6303 buf->writeByte('J');
6304 break;
6305 case STCref:
6306 buf->writeByte('K');
6307 break;
6308 case STClazy:
6309 buf->writeByte('L');
6310 break;
6311 default:
6312 #ifdef DEBUG
6313 halt();
6314 #endif
6315 assert(0);
6317 #if 0
6318 int mod = 0x100;
6319 if (type->toBasetype()->ty == Tclass)
6320 mod = 0;
6321 type->toDecoBuffer(buf, mod);
6322 #else
6323 //type->toHeadMutable()->toDecoBuffer(buf, 0);
6324 type->toDecoBuffer(buf, 0);
6325 #endif
6328 /***************************************
6329 * Determine number of arguments, folding in tuples.
6332 size_t Argument::dim(Arguments *args)
6334 size_t n = 0;
6335 if (args)
6337 for (size_t i = 0; i < args->dim; i++)
6338 { Argument *arg = (Argument *)args->data[i];
6339 Type *t = arg->type->toBasetype();
6341 if (t->ty == Ttuple)
6342 { TypeTuple *tu = (TypeTuple *)t;
6343 n += dim(tu->arguments);
6345 else
6346 n++;
6349 return n;
6352 /***************************************
6353 * Get nth Argument, folding in tuples.
6354 * Returns:
6355 * Argument* nth Argument
6356 * NULL not found, *pn gets incremented by the number
6357 * of Arguments
6360 Argument *Argument::getNth(Arguments *args, size_t nth, size_t *pn)
6362 if (!args)
6363 return NULL;
6365 size_t n = 0;
6366 for (size_t i = 0; i < args->dim; i++)
6367 { Argument *arg = (Argument *)args->data[i];
6368 Type *t = arg->type->toBasetype();
6370 if (t->ty == Ttuple)
6371 { TypeTuple *tu = (TypeTuple *)t;
6372 arg = getNth(tu->arguments, nth - n, &n);
6373 if (arg)
6374 return arg;
6376 else if (n == nth)
6377 return arg;
6378 else
6379 n++;
6382 if (pn)
6383 *pn += n;
6384 return NULL;