Error on pointless maybe annotations
[delight/core.git] / dmd / mtype.c
blob7180917680ac6298525b5ddb530abe8a84986d21
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::typeinfomaybe;
123 ClassDeclaration *Type::typeinfoarray;
124 ClassDeclaration *Type::typeinfostaticarray;
125 ClassDeclaration *Type::typeinfoassociativearray;
126 ClassDeclaration *Type::typeinfoenum;
127 ClassDeclaration *Type::typeinfofunction;
128 ClassDeclaration *Type::typeinfodelegate;
129 ClassDeclaration *Type::typeinfotypelist;
131 Type *Type::tvoidptr;
132 Type *Type::basic[TMAX];
133 unsigned char Type::mangleChar[TMAX];
134 StringTable Type::stringtable;
137 Type::Type(TY ty, Type *next)
139 this->ty = ty;
140 this->mod = 0;
141 this->next = next;
142 this->deco = NULL;
143 #if V2
144 this->cto = NULL;
145 this->ito = NULL;
146 #endif
147 this->pto = NULL;
148 this->mbe = NULL;
149 this->rto = NULL;
150 this->arrayof = NULL;
151 this->vtinfo = NULL;
152 this->ctype = NULL;
155 Type *Type::syntaxCopy()
157 print();
158 fprintf(stdmsg, "ty = %d\n", ty);
159 assert(0);
160 return this;
163 int Type::equals(Object *o)
164 { Type *t;
166 t = (Type *)o;
167 //printf("Type::equals(%s, %s)\n", toChars(), t->toChars());
168 if (this == o ||
169 (t && deco == t->deco) && // deco strings are unique
170 deco != NULL) // and semantic() has been run
172 //printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
173 return 1;
175 //if (deco && t && t->deco) printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
176 return 0;
179 char Type::needThisPrefix()
181 return 'M'; // name mangling prefix for functions needing 'this'
184 void Type::init()
185 { int i;
186 int j;
188 Lexer::initKeywords();
190 mangleChar[Tarray] = 'A';
191 mangleChar[Tsarray] = 'G';
192 mangleChar[Taarray] = 'H';
193 mangleChar[Tpointer] = 'P';
194 #define NOT_NULL_MANGLE '?'
195 mangleChar[Tmaybe] = '?';
196 mangleChar[Treference] = 'R';
197 mangleChar[Tfunction] = 'F';
198 mangleChar[Tident] = 'I';
199 mangleChar[Tclass] = 'C';
200 mangleChar[Tstruct] = 'S';
201 mangleChar[Tenum] = 'E';
202 mangleChar[Ttypedef] = 'T';
203 mangleChar[Tdelegate] = 'D';
205 mangleChar[Tnone] = 'n';
206 mangleChar[Tvoid] = 'v';
207 mangleChar[Tint8] = 'g';
208 mangleChar[Tuns8] = 'h';
209 mangleChar[Tint16] = 's';
210 mangleChar[Tuns16] = 't';
211 mangleChar[Tint32] = 'i';
212 mangleChar[Tuns32] = 'k';
213 mangleChar[Tint64] = 'l';
214 mangleChar[Tuns64] = 'm';
215 mangleChar[Tfloat32] = 'f';
216 mangleChar[Tfloat64] = 'd';
217 mangleChar[Tfloat80] = 'e';
219 mangleChar[Timaginary32] = 'o';
220 mangleChar[Timaginary64] = 'p';
221 mangleChar[Timaginary80] = 'j';
222 mangleChar[Tcomplex32] = 'q';
223 mangleChar[Tcomplex64] = 'r';
224 mangleChar[Tcomplex80] = 'c';
226 mangleChar[Tbool] = 'b';
227 mangleChar[Tascii] = 'a';
228 mangleChar[Twchar] = 'u';
229 mangleChar[Tdchar] = 'w';
231 mangleChar[Tbit] = '@';
232 mangleChar[Tinstance] = '@';
233 mangleChar[Terror] = '@';
234 mangleChar[Ttypeof] = '@';
235 mangleChar[Ttuple] = 'B';
236 mangleChar[Tslice] = '@';
238 for (i = 0; i < TMAX; i++)
239 { if (!mangleChar[i])
240 fprintf(stdmsg, "ty = %d\n", i);
241 assert(mangleChar[i]);
244 // Set basic types
245 static TY basetab[] =
246 { Tvoid, Tint8, Tuns8, Tint16, Tuns16, Tint32, Tuns32, Tint64, Tuns64,
247 Tfloat32, Tfloat64, Tfloat80,
248 Timaginary32, Timaginary64, Timaginary80,
249 Tcomplex32, Tcomplex64, Tcomplex80,
250 Tbit, Tbool,
251 Tascii, Twchar, Tdchar };
253 for (i = 0; i < sizeof(basetab) / sizeof(basetab[0]); i++)
254 basic[basetab[i]] = new TypeBasic(basetab[i]);
255 basic[Terror] = basic[Tint32];
257 tvoidptr = tvoid->pointerTo();
259 if (global.params.isX86_64)
261 PTRSIZE = 8;
262 if (global.params.isLinux)
263 REALSIZE = 10;
264 else
265 REALSIZE = 8;
266 Tsize_t = Tuns64;
267 Tptrdiff_t = Tint64;
268 Tindex = Tint64;
270 else
272 PTRSIZE = 4;
273 #if TARGET_LINUX
274 REALSIZE = 12;
275 REALPAD = 2;
276 #else
277 REALSIZE = 10;
278 REALPAD = 0;
279 #endif
280 Tsize_t = Tuns32;
281 Tptrdiff_t = Tint32;
283 CLASSINFO_SIZE = 18 * PTRSIZE;
286 d_uns64 Type::size()
288 return size(0);
291 d_uns64 Type::size(Loc loc)
293 error(loc, "no size for type %s", toChars());
294 return 1;
297 unsigned Type::alignsize()
299 return size(0);
302 Type *Type::semantic(Loc loc, Scope *sc)
304 if (next)
305 next = next->semantic(loc,sc);
306 return merge();
309 // If this type can be null, wrap it in TypeMaybe.
310 // Otherwise just, returns itself. This is so that
311 // we can try wrapping everything in D source easily.
312 Type *Type::maybe()
314 if (ty == Tmaybe)
316 printf("maybe maybe\n");
317 return this;
320 // For some reason, "void*?" causes problems.
321 // Since it's not type safe anyway, don't worry about it.
322 if (ty == Tpointer && next->ty == Tvoid)
323 return this;
325 if (ty != Tpointer && ty != Tclass && ty != Tident)
326 return this; // Can't be null
328 if (!mbe)
329 { Type *t;
331 t = new TypeMaybe(this);
332 if (t->reliesOnTident())
333 mbe = t;
334 else
335 mbe = t->merge();
337 return mbe;
340 Type *Type::pointerTo()
342 if (!pto)
343 { Type *t;
345 t = new TypePointer(this);
346 pto = t->merge();
348 return pto;
351 Type *Type::referenceTo()
353 if (!rto)
354 { Type *t;
356 t = new TypeReference(this);
357 rto = t->merge();
359 return rto;
362 Type *Type::arrayOf()
364 if (!arrayof)
365 { Type *t;
367 t = new TypeDArray(this);
368 arrayof = t->merge();
370 return arrayof;
373 Dsymbol *Type::toDsymbol(Scope *sc)
375 return NULL;
378 /*******************************
379 * If this is a shell around another type,
380 * get that other type.
383 Type *Type::toBasetype()
385 return this;
388 /********************************
389 * Name mangling.
392 void Type::toDecoBuffer(OutBuffer *buf)
394 buf->writeByte(mangleChar[ty]);
395 if (next)
397 assert(next != this);
398 //printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty);
399 next->toDecoBuffer(buf);
403 /********************************
404 * For pretty-printing a type.
407 char *Type::toChars()
408 { OutBuffer *buf;
409 HdrGenState hgs;
411 buf = new OutBuffer();
412 toCBuffer(buf, NULL, &hgs);
413 return buf->toChars();
416 void Type::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
418 toCBuffer2(buf, hgs, 0);
419 if (ident)
420 { buf->writeByte(' ');
421 buf->writestring(ident->toChars());
425 void Type::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
427 if (mod != this->mod)
428 { toCBuffer3(buf, hgs, mod);
429 return;
431 buf->writestring(toChars());
434 void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod)
436 if (mod != this->mod)
437 { char *p;
439 switch (this->mod)
441 case 0:
442 toCBuffer2(buf, hgs, this->mod);
443 break;
444 case MODconst:
445 p = "const(";
446 goto L1;
447 case MODinvariant:
448 p = "invariant(";
449 L1: buf->writestring(p);
450 toCBuffer2(buf, hgs, this->mod);
451 buf->writeByte(')');
452 break;
453 default:
454 assert(0);
460 /************************************
463 Type *Type::merge()
464 { Type *t;
466 //printf("merge(%s)\n", toChars());
467 t = this;
468 assert(t);
469 if (!deco)
471 OutBuffer buf;
472 StringValue *sv;
474 if (next)
475 next = next->merge();
476 toDecoBuffer(&buf);
477 sv = stringtable.update((char *)buf.data, buf.offset);
478 if (sv->ptrvalue)
479 { t = (Type *) sv->ptrvalue;
480 assert(t->deco);
481 //printf("old value, deco = '%s' %p\n", t->deco, t->deco);
483 else
485 sv->ptrvalue = this;
486 deco = sv->lstring.string;
487 //printf("new value, deco = '%s' %p\n", t->deco, t->deco);
490 return t;
493 int Type::isbit()
495 return FALSE;
498 int Type::isintegral()
500 return FALSE;
503 int Type::isfloating()
505 return FALSE;
508 int Type::isreal()
510 return FALSE;
513 int Type::isimaginary()
515 return FALSE;
518 int Type::iscomplex()
520 return FALSE;
523 int Type::isscalar()
525 return FALSE;
528 int Type::isunsigned()
530 return FALSE;
533 ClassDeclaration *Type::isClassHandle()
535 return NULL;
538 int Type::isauto()
540 return FALSE;
543 int Type::isString()
545 return FALSE;
548 int Type::checkBoolean()
550 return isscalar();
553 /*********************************
554 * Check type to see if it is based on a deprecated symbol.
557 void Type::checkDeprecated(Loc loc, Scope *sc)
559 Type *t;
560 Dsymbol *s;
562 for (t = this; t; t = t->next)
564 s = t->toDsymbol(sc);
565 if (s)
566 s->checkDeprecated(loc, sc);
571 Expression *Type::defaultInit(Loc loc)
573 #if LOGDEFAULTINIT
574 printf("Type::defaultInit() '%s'\n", toChars());
575 #endif
576 return NULL;
579 int Type::isZeroInit()
581 return 0; // assume not
584 int Type::isBaseOf(Type *t, target_ptrdiff_t *poffset)
586 return 0; // assume not
589 /********************************
590 * Determine if 'this' can be implicitly converted
591 * to type 'to'.
592 * Returns:
593 * 0 can't convert
594 * 1 can convert using implicit conversions
595 * 2 this and to are the same type
598 MATCH Type::implicitConvTo(Type *to)
600 //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to);
601 //printf("\tthis->next=%p, to->next=%p\n", this->next, to->next);
602 if (this == to)
603 return MATCHexact;
604 // if (to->ty == Tvoid)
605 // return 1;
606 return MATCHnomatch;
609 Expression *Type::getProperty(Loc loc, Identifier *ident)
610 { Expression *e;
612 #if LOGDOTEXP
613 printf("Type::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars());
614 #endif
615 if (ident == Id::__sizeof)
617 e = new IntegerExp(loc, size(loc), Type::tsize_t);
619 else if (ident == Id::size)
621 error(loc, ".size property should be replaced with .sizeof");
622 e = new IntegerExp(loc, size(loc), Type::tsize_t);
624 else if (ident == Id::alignof)
626 e = new IntegerExp(loc, alignsize(), Type::tsize_t);
628 else if (ident == Id::typeinfo)
630 if (!global.params.useDeprecated)
631 error(loc, ".typeinfo deprecated, use typeid(type)");
632 e = getTypeInfo(NULL);
634 else if (ident == Id::init)
636 if (ty == Tvoid)
637 error(loc, "void does not have an initializer");
638 e = defaultInit(loc);
640 else if (ident == Id::mangleof)
642 assert(deco);
643 e = new StringExp(loc, deco, strlen(deco), 'c');
644 Scope sc;
645 e = e->semantic(&sc);
647 else if (ident == Id::stringof)
648 { char *s = toChars();
649 e = new StringExp(loc, s, strlen(s), 'c');
650 Scope sc;
651 e = e->semantic(&sc);
653 else
655 error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars());
656 e = new IntegerExp(loc, 1, Type::tint32);
658 return e;
661 Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident)
662 { VarDeclaration *v = NULL;
664 #if LOGDOTEXP
665 printf("Type::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
666 #endif
667 if (e->op == TOKdotvar)
669 DotVarExp *dv = (DotVarExp *)e;
670 v = dv->var->isVarDeclaration();
672 else if (e->op == TOKvar)
674 VarExp *ve = (VarExp *)e;
675 v = ve->var->isVarDeclaration();
677 if (v)
679 if (ident == Id::offset)
681 if (!global.params.useDeprecated)
682 error(e->loc, ".offset deprecated, use .offsetof");
683 goto Loffset;
685 else if (ident == Id::offsetof)
687 Loffset:
688 if (v->storage_class & STCfield)
690 e = new IntegerExp(e->loc, v->offset, Type::tsize_t);
691 return e;
694 else if (ident == Id::init)
696 #if 0
697 if (v->init)
699 if (v->init->isVoidInitializer())
700 error(e->loc, "%s.init is void", v->toChars());
701 else
702 { Loc loc = e->loc;
703 e = v->init->toExpression();
704 if (e->op == TOKassign || e->op == TOKconstruct)
706 e = ((AssignExp *)e)->e2;
708 /* Take care of case where we used a 0
709 * to initialize the struct.
711 if (e->type == Type::tint32 &&
712 e->isBool(0) &&
713 v->type->toBasetype()->ty == Tstruct)
715 e = v->type->defaultInit(loc);
718 e = e->optimize(WANTvalue | WANTinterpret);
719 // if (!e->isConst())
720 // error(loc, ".init cannot be evaluated at compile time");
722 return e;
724 #endif
725 Expression *ex = defaultInit(e->loc);
726 return ex;
729 if (ident == Id::typeinfo)
731 if (!global.params.useDeprecated)
732 error(e->loc, ".typeinfo deprecated, use typeid(type)");
733 e = getTypeInfo(sc);
734 return e;
736 if (ident == Id::stringof)
737 { char *s = e->toChars();
738 e = new StringExp(e->loc, s, strlen(s), 'c');
739 Scope sc;
740 e = e->semantic(&sc);
741 return e;
743 return getProperty(e->loc, ident);
746 unsigned Type::memalign(unsigned salign)
748 return salign;
751 void Type::error(Loc loc, const char *format, ...)
753 va_list ap;
754 va_start(ap, format);
755 ::verror(loc, format, ap);
756 va_end( ap );
759 Identifier *Type::getTypeInfoIdent(int internal)
761 // _init_10TypeInfo_%s
762 OutBuffer buf;
763 Identifier *id;
764 char *name;
765 int len;
767 //toTypeInfoBuffer(&buf);
768 if (internal)
769 { buf.writeByte(mangleChar[ty]);
770 if (ty == Tarray)
771 buf.writeByte(mangleChar[next->ty]);
773 else
774 toDecoBuffer(&buf);
776 // Because these are in the D library, they are maybe types
777 if (buf.data[0] == NOT_NULL_MANGLE)
778 buf.remove(0, 1);
780 len = buf.offset;
781 name = (char *)alloca(19 + sizeof(len) * 3 + len + 1);
782 buf.writeByte(0);
783 sprintf(name, "_D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
784 if (global.params.isWindows)
785 name++; // C mangling will add it back in
786 //printf("name = %s\n", name);
787 id = Lexer::idPool(name);
788 return id;
791 TypeBasic *Type::isTypeBasic()
793 return NULL;
797 void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
799 Type *t;
801 t = semantic(loc, sc);
802 *pt = t;
803 *pe = NULL;
804 *ps = NULL;
807 /*******************************
808 * If one of the subtypes of this type is a TypeIdentifier,
809 * i.e. it's an unresolved type, return that type.
812 Type *Type::reliesOnTident()
814 if (!next)
815 return NULL;
816 else
817 return next->reliesOnTident();
820 /********************************
821 * We've mistakenly parsed this as a type.
822 * Redo it as an Expression.
823 * NULL if cannot.
826 Expression *Type::toExpression()
828 return NULL;
831 /***************************************
832 * Return !=0 if type has pointers that need to
833 * be scanned by the GC during a collection cycle.
836 int Type::hasPointers()
838 return FALSE;
841 /* ============================= TypeBasic =========================== */
843 TypeBasic::TypeBasic(TY ty)
844 : Type(ty, NULL)
845 { char *c;
846 char *d;
847 unsigned flags;
849 #define TFLAGSintegral 1
850 #define TFLAGSfloating 2
851 #define TFLAGSunsigned 4
852 #define TFLAGSreal 8
853 #define TFLAGSimaginary 0x10
854 #define TFLAGScomplex 0x20
856 flags = 0;
857 switch (ty)
859 case Tvoid: d = Token::toChars(TOKvoid);
860 c = "void";
861 break;
863 case Tint8: d = Token::toChars(TOKint8);
864 c = "byte";
865 flags |= TFLAGSintegral;
866 break;
868 case Tuns8: d = Token::toChars(TOKuns8);
869 c = "ubyte";
870 flags |= TFLAGSintegral | TFLAGSunsigned;
871 break;
873 case Tint16: d = Token::toChars(TOKint16);
874 c = "short";
875 flags |= TFLAGSintegral;
876 break;
878 case Tuns16: d = Token::toChars(TOKuns16);
879 c = "ushort";
880 flags |= TFLAGSintegral | TFLAGSunsigned;
881 break;
883 case Tint32: d = Token::toChars(TOKint32);
884 c = "int";
885 flags |= TFLAGSintegral;
886 break;
888 case Tuns32: d = Token::toChars(TOKuns32);
889 c = "uint";
890 flags |= TFLAGSintegral | TFLAGSunsigned;
891 break;
893 case Tfloat32: d = Token::toChars(TOKfloat32);
894 c = "float";
895 flags |= TFLAGSfloating | TFLAGSreal;
896 break;
898 case Tint64: d = Token::toChars(TOKint64);
899 c = "long";
900 flags |= TFLAGSintegral;
901 break;
903 case Tuns64: d = Token::toChars(TOKuns64);
904 c = "ulong";
905 flags |= TFLAGSintegral | TFLAGSunsigned;
906 break;
908 case Tfloat64: d = Token::toChars(TOKfloat64);
909 c = "double";
910 flags |= TFLAGSfloating | TFLAGSreal;
911 break;
913 case Tfloat80: d = Token::toChars(TOKfloat80);
914 c = "real";
915 flags |= TFLAGSfloating | TFLAGSreal;
916 break;
918 case Timaginary32: d = Token::toChars(TOKimaginary32);
919 c = "ifloat";
920 flags |= TFLAGSfloating | TFLAGSimaginary;
921 break;
923 case Timaginary64: d = Token::toChars(TOKimaginary64);
924 c = "idouble";
925 flags |= TFLAGSfloating | TFLAGSimaginary;
926 break;
928 case Timaginary80: d = Token::toChars(TOKimaginary80);
929 c = "ireal";
930 flags |= TFLAGSfloating | TFLAGSimaginary;
931 break;
933 case Tcomplex32: d = Token::toChars(TOKcomplex32);
934 c = "cfloat";
935 flags |= TFLAGSfloating | TFLAGScomplex;
936 break;
938 case Tcomplex64: d = Token::toChars(TOKcomplex64);
939 c = "cdouble";
940 flags |= TFLAGSfloating | TFLAGScomplex;
941 break;
943 case Tcomplex80: d = Token::toChars(TOKcomplex80);
944 c = "creal";
945 flags |= TFLAGSfloating | TFLAGScomplex;
946 break;
949 case Tbit: d = Token::toChars(TOKbit);
950 c = "bit";
951 flags |= TFLAGSintegral | TFLAGSunsigned;
952 break;
954 case Tbool: d = "bool";
955 c = d;
956 flags |= TFLAGSintegral | TFLAGSunsigned;
957 break;
959 case Tascii: d = Token::toChars(TOKchar);
960 c = "char";
961 flags |= TFLAGSintegral | TFLAGSunsigned;
962 break;
964 case Twchar: d = Token::toChars(TOKwchar);
965 c = "wchar";
966 flags |= TFLAGSintegral | TFLAGSunsigned;
967 break;
969 case Tdchar: d = Token::toChars(TOKdchar);
970 c = "dchar";
971 flags |= TFLAGSintegral | TFLAGSunsigned;
972 break;
974 default: assert(0);
976 this->dstring = d;
977 this->cstring = c;
978 this->flags = flags;
979 merge();
982 Type *TypeBasic::syntaxCopy()
984 // No semantic analysis done on basic types, no need to copy
985 return this;
989 char *TypeBasic::toChars()
991 return dstring;
994 void TypeBasic::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
996 //printf("TypeBasic::toCBuffer2(mod = %d, this->mod = %d)\n", mod, this->mod);
997 if (mod != this->mod)
998 { toCBuffer3(buf, hgs, mod);
999 return;
1001 buf->writestring(dstring);
1004 d_uns64 TypeBasic::size(Loc loc)
1005 { unsigned size;
1007 //printf("TypeBasic::size()\n");
1008 switch (ty)
1010 case Tint8:
1011 case Tuns8: size = 1; break;
1012 case Tint16:
1013 case Tuns16: size = 2; break;
1014 case Tint32:
1015 case Tuns32:
1016 case Tfloat32:
1017 case Timaginary32:
1018 size = 4; break;
1019 case Tint64:
1020 case Tuns64:
1021 case Tfloat64:
1022 case Timaginary64:
1023 size = 8; break;
1024 case Tfloat80:
1025 case Timaginary80:
1026 size = REALSIZE; break;
1027 case Tcomplex32:
1028 size = 8; break;
1029 case Tcomplex64:
1030 size = 16; break;
1031 case Tcomplex80:
1032 size = REALSIZE * 2; break;
1034 case Tvoid:
1035 //size = Type::size(); // error message
1036 size = 1;
1037 break;
1039 case Tbit: size = 1; break;
1040 case Tbool: size = 1; break;
1041 case Tascii: size = 1; break;
1042 case Twchar: size = 2; break;
1043 case Tdchar: size = 4; break;
1045 default:
1046 assert(0);
1047 break;
1049 //printf("TypeBasic::size() = %d\n", size);
1050 return size;
1053 unsigned TypeBasic::alignsize()
1054 { unsigned sz;
1056 switch (ty)
1058 case Tfloat80:
1059 case Timaginary80:
1060 case Tcomplex80:
1061 sz = 2;
1062 break;
1064 default:
1065 sz = size(0);
1066 break;
1068 return sz;
1072 Expression *TypeBasic::getProperty(Loc loc, Identifier *ident)
1074 Expression *e;
1075 d_int64 ivalue;
1076 #ifdef IN_GCC
1077 real_t fvalue;
1078 #else
1079 d_float80 fvalue;
1080 #endif
1082 //printf("TypeBasic::getProperty('%s')\n", ident->toChars());
1083 if (ident == Id::max)
1085 switch (ty)
1087 case Tint8: ivalue = 0x7F; goto Livalue;
1088 case Tuns8: ivalue = 0xFF; goto Livalue;
1089 case Tint16: ivalue = 0x7FFFUL; goto Livalue;
1090 case Tuns16: ivalue = 0xFFFFUL; goto Livalue;
1091 case Tint32: ivalue = 0x7FFFFFFFUL; goto Livalue;
1092 case Tuns32: ivalue = 0xFFFFFFFFUL; goto Livalue;
1093 case Tint64: ivalue = 0x7FFFFFFFFFFFFFFFLL; goto Livalue;
1094 case Tuns64: ivalue = 0xFFFFFFFFFFFFFFFFULL; goto Livalue;
1095 case Tbit: ivalue = 1; goto Livalue;
1096 case Tbool: ivalue = 1; goto Livalue;
1097 case Tchar: ivalue = 0xFF; goto Livalue;
1098 case Twchar: ivalue = 0xFFFFUL; goto Livalue;
1099 case Tdchar: ivalue = 0x10FFFFUL; goto Livalue;
1101 case Tcomplex32:
1102 case Timaginary32:
1103 #ifdef IN_GCC
1104 // %% lazy, fix
1105 #define FLT_MAX real_t_properties[real_t::Float].maxval;
1106 #define DBL_MAX real_t_properties[real_t::Double].maxval;
1107 #define LDBL_MAX real_t_properties[real_t::LongDouble].maxval;
1108 #define FLT_MIN real_t_properties[real_t::Float].minval;
1109 #define DBL_MIN real_t_properties[real_t::Double].minval;
1110 #define LDBL_MIN real_t_properties[real_t::LongDouble].minval;
1111 #define FLT_DIG real_t_properties[real_t::Float].dig;
1112 #define DBL_DIG real_t_properties[real_t::Double].dig;
1113 #define LDBL_DIG real_t_properties[real_t::LongDouble].dig;
1114 #define FLT_MANT_DIG real_t_properties[real_t::Float].mant_dig;
1115 #define DBL_MANT_DIG real_t_properties[real_t::Double].mant_dig;
1116 #define LDBL_MANT_DIG real_t_properties[real_t::LongDouble].mant_dig;
1117 #define FLT_MAX_10_EXP real_t_properties[real_t::Float].max_10_exp;
1118 #define DBL_MAX_10_EXP real_t_properties[real_t::Double].max_10_exp;
1119 #define LDBL_MAX_10_EXP real_t_properties[real_t::LongDouble].max_10_exp;
1120 #define FLT_MIN_10_EXP real_t_properties[real_t::Float].min_10_exp;
1121 #define DBL_MIN_10_EXP real_t_properties[real_t::Double].min_10_exp;
1122 #define LDBL_MIN_10_EXP real_t_properties[real_t::LongDouble].min_10_exp;
1123 #define FLT_MAX_EXP real_t_properties[real_t::Float].max_exp;
1124 #define DBL_MAX_EXP real_t_properties[real_t::Double].max_exp;
1125 #define LDBL_MAX_EXP real_t_properties[real_t::LongDouble].max_exp;
1126 #define FLT_MIN_EXP real_t_properties[real_t::Float].min_exp;
1127 #define DBL_MIN_EXP real_t_properties[real_t::Double].min_exp;
1128 #define LDBL_MIN_EXP real_t_properties[real_t::LongDouble].min_exp;
1129 #define FLT_EPSILON real_t_properties[real_t::Float].epsilonval;
1130 #define DBL_EPSILON real_t_properties[real_t::Double].epsilonval;
1131 #define LDBL_EPSILON real_t_properties[real_t::LongDouble].epsilonval;
1134 #endif
1135 case Tfloat32: fvalue = FLT_MAX; goto Lfvalue;
1136 case Tcomplex64:
1137 case Timaginary64:
1138 case Tfloat64: fvalue = DBL_MAX; goto Lfvalue;
1139 case Tcomplex80:
1140 case Timaginary80:
1141 case Tfloat80: fvalue = LDBL_MAX; goto Lfvalue;
1144 else if (ident == Id::min)
1146 switch (ty)
1148 case Tint8: ivalue = -128; goto Livalue;
1149 case Tuns8: ivalue = 0; goto Livalue;
1150 case Tint16: ivalue = -32768; goto Livalue;
1151 case Tuns16: ivalue = 0; goto Livalue;
1152 case Tint32: ivalue = -2147483647L - 1; goto Livalue;
1153 case Tuns32: ivalue = 0; goto Livalue;
1154 case Tint64: ivalue = (-9223372036854775807LL-1LL); goto Livalue;
1155 case Tuns64: ivalue = 0; goto Livalue;
1156 case Tbit: ivalue = 0; goto Livalue;
1157 case Tbool: ivalue = 0; goto Livalue;
1158 case Tchar: ivalue = 0; goto Livalue;
1159 case Twchar: ivalue = 0; goto Livalue;
1160 case Tdchar: ivalue = 0; goto Livalue;
1162 case Tcomplex32:
1163 case Timaginary32:
1164 case Tfloat32: fvalue = FLT_MIN; goto Lfvalue;
1165 case Tcomplex64:
1166 case Timaginary64:
1167 case Tfloat64: fvalue = DBL_MIN; goto Lfvalue;
1168 case Tcomplex80:
1169 case Timaginary80:
1170 case Tfloat80: fvalue = LDBL_MIN; goto Lfvalue;
1173 else if (ident == Id::nan)
1175 switch (ty)
1177 case Tcomplex32:
1178 case Tcomplex64:
1179 case Tcomplex80:
1180 case Timaginary32:
1181 case Timaginary64:
1182 case Timaginary80:
1183 case Tfloat32:
1184 case Tfloat64:
1185 case Tfloat80:
1187 #if IN_GCC
1188 // mode doesn't matter, will be converted in RealExp anyway
1189 fvalue = real_t::getnan(real_t::LongDouble);
1190 #elif __GNUC__
1191 // gcc nan's have the sign bit set by default, so turn it off
1192 // Need the volatile to prevent gcc from doing incorrect
1193 // constant folding.
1194 volatile d_float80 foo;
1195 foo = NAN;
1196 if (signbit(foo)) // signbit sometimes, not always, set
1197 foo = -foo; // turn off sign bit
1198 fvalue = foo;
1199 #elif _MSC_VER
1200 unsigned long nan[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
1201 fvalue = *(double*)nan;
1202 #else
1203 fvalue = NAN;
1204 #endif
1205 goto Lfvalue;
1209 else if (ident == Id::infinity)
1211 switch (ty)
1213 case Tcomplex32:
1214 case Tcomplex64:
1215 case Tcomplex80:
1216 case Timaginary32:
1217 case Timaginary64:
1218 case Timaginary80:
1219 case Tfloat32:
1220 case Tfloat64:
1221 case Tfloat80:
1222 #if IN_GCC
1223 fvalue = real_t::getinfinity();
1224 #elif __GNUC__
1225 fvalue = 1 / zero;
1226 #elif _MSC_VER
1227 fvalue = std::numeric_limits<long double>::infinity();
1228 #else
1229 fvalue = INFINITY;
1230 #endif
1231 goto Lfvalue;
1234 else if (ident == Id::dig)
1236 switch (ty)
1238 case Tcomplex32:
1239 case Timaginary32:
1240 case Tfloat32: ivalue = FLT_DIG; goto Lint;
1241 case Tcomplex64:
1242 case Timaginary64:
1243 case Tfloat64: ivalue = DBL_DIG; goto Lint;
1244 case Tcomplex80:
1245 case Timaginary80:
1246 case Tfloat80: ivalue = LDBL_DIG; goto Lint;
1249 else if (ident == Id::epsilon)
1251 switch (ty)
1253 case Tcomplex32:
1254 case Timaginary32:
1255 case Tfloat32: fvalue = FLT_EPSILON; goto Lfvalue;
1256 case Tcomplex64:
1257 case Timaginary64:
1258 case Tfloat64: fvalue = DBL_EPSILON; goto Lfvalue;
1259 case Tcomplex80:
1260 case Timaginary80:
1261 case Tfloat80: fvalue = LDBL_EPSILON; goto Lfvalue;
1264 else if (ident == Id::mant_dig)
1266 switch (ty)
1268 case Tcomplex32:
1269 case Timaginary32:
1270 case Tfloat32: ivalue = FLT_MANT_DIG; goto Lint;
1271 case Tcomplex64:
1272 case Timaginary64:
1273 case Tfloat64: ivalue = DBL_MANT_DIG; goto Lint;
1274 case Tcomplex80:
1275 case Timaginary80:
1276 case Tfloat80: ivalue = LDBL_MANT_DIG; goto Lint;
1279 else if (ident == Id::max_10_exp)
1281 switch (ty)
1283 case Tcomplex32:
1284 case Timaginary32:
1285 case Tfloat32: ivalue = FLT_MAX_10_EXP; goto Lint;
1286 case Tcomplex64:
1287 case Timaginary64:
1288 case Tfloat64: ivalue = DBL_MAX_10_EXP; goto Lint;
1289 case Tcomplex80:
1290 case Timaginary80:
1291 case Tfloat80: ivalue = LDBL_MAX_10_EXP; goto Lint;
1294 else if (ident == Id::max_exp)
1296 switch (ty)
1298 case Tcomplex32:
1299 case Timaginary32:
1300 case Tfloat32: ivalue = FLT_MAX_EXP; goto Lint;
1301 case Tcomplex64:
1302 case Timaginary64:
1303 case Tfloat64: ivalue = DBL_MAX_EXP; goto Lint;
1304 case Tcomplex80:
1305 case Timaginary80:
1306 case Tfloat80: ivalue = LDBL_MAX_EXP; goto Lint;
1309 else if (ident == Id::min_10_exp)
1311 switch (ty)
1313 case Tcomplex32:
1314 case Timaginary32:
1315 case Tfloat32: ivalue = FLT_MIN_10_EXP; goto Lint;
1316 case Tcomplex64:
1317 case Timaginary64:
1318 case Tfloat64: ivalue = DBL_MIN_10_EXP; goto Lint;
1319 case Tcomplex80:
1320 case Timaginary80:
1321 case Tfloat80: ivalue = LDBL_MIN_10_EXP; goto Lint;
1324 else if (ident == Id::min_exp)
1326 switch (ty)
1328 case Tcomplex32:
1329 case Timaginary32:
1330 case Tfloat32: ivalue = FLT_MIN_EXP; goto Lint;
1331 case Tcomplex64:
1332 case Timaginary64:
1333 case Tfloat64: ivalue = DBL_MIN_EXP; goto Lint;
1334 case Tcomplex80:
1335 case Timaginary80:
1336 case Tfloat80: ivalue = LDBL_MIN_EXP; goto Lint;
1340 Ldefault:
1341 return Type::getProperty(loc, ident);
1343 Livalue:
1344 e = new IntegerExp(loc, ivalue, this);
1345 return e;
1347 Lfvalue:
1348 if (isreal() || isimaginary())
1349 e = new RealExp(loc, fvalue, this);
1350 else
1352 complex_t cvalue;
1354 #if __DMC__
1355 //((real_t *)&cvalue)[0] = fvalue;
1356 //((real_t *)&cvalue)[1] = fvalue;
1357 cvalue = fvalue + fvalue * I;
1358 #else
1359 cvalue.re = fvalue;
1360 cvalue.im = fvalue;
1361 #endif
1362 //for (int i = 0; i < 20; i++)
1363 // printf("%02x ", ((unsigned char *)&cvalue)[i]);
1364 //printf("\n");
1365 e = new ComplexExp(loc, cvalue, this);
1367 return e;
1369 Lint:
1370 e = new IntegerExp(loc, ivalue, Type::tint32);
1371 return e;
1374 Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
1376 #if LOGDOTEXP
1377 printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1378 #endif
1379 Type *t;
1381 if (ident == Id::re)
1383 switch (ty)
1385 case Tcomplex32: t = tfloat32; goto L1;
1386 case Tcomplex64: t = tfloat64; goto L1;
1387 case Tcomplex80: t = tfloat80; goto L1;
1389 e = e->castTo(sc, t);
1390 break;
1392 case Tfloat32:
1393 case Tfloat64:
1394 case Tfloat80:
1395 break;
1397 case Timaginary32: t = tfloat32; goto L2;
1398 case Timaginary64: t = tfloat64; goto L2;
1399 case Timaginary80: t = tfloat80; goto L2;
1401 e = new RealExp(0, 0, t);
1402 break;
1404 default:
1405 return Type::getProperty(e->loc, ident);
1408 else if (ident == Id::im)
1409 { Type *t2;
1411 switch (ty)
1413 case Tcomplex32: t = timaginary32; t2 = tfloat32; goto L3;
1414 case Tcomplex64: t = timaginary64; t2 = tfloat64; goto L3;
1415 case Tcomplex80: t = timaginary80; t2 = tfloat80; goto L3;
1417 e = e->castTo(sc, t);
1418 e->type = t2;
1419 break;
1421 case Timaginary32: t = tfloat32; goto L4;
1422 case Timaginary64: t = tfloat64; goto L4;
1423 case Timaginary80: t = tfloat80; goto L4;
1425 e->type = t;
1426 break;
1428 case Tfloat32:
1429 case Tfloat64:
1430 case Tfloat80:
1431 e = new RealExp(0, 0, this);
1432 break;
1434 default:
1435 return Type::getProperty(e->loc, ident);
1438 else
1440 return Type::dotExp(sc, e, ident);
1442 return e;
1445 Expression *TypeBasic::defaultInit(Loc loc)
1446 { integer_t value = 0;
1448 #if LOGDEFAULTINIT
1449 printf("TypeBasic::defaultInit() '%s'\n", toChars());
1450 #endif
1451 switch (ty)
1453 case Tchar:
1454 value = 0xFF;
1455 break;
1457 case Twchar:
1458 case Tdchar:
1459 value = 0xFFFF;
1460 break;
1462 case Timaginary32:
1463 case Timaginary64:
1464 case Timaginary80:
1465 case Tfloat32:
1466 case Tfloat64:
1467 case Tfloat80:
1468 case Tcomplex32:
1469 case Tcomplex64:
1470 case Tcomplex80:
1471 return getProperty(loc, Id::nan);
1473 return new IntegerExp(loc, value, this);
1476 int TypeBasic::isZeroInit()
1478 switch (ty)
1480 case Tchar:
1481 case Twchar:
1482 case Tdchar:
1483 case Timaginary32:
1484 case Timaginary64:
1485 case Timaginary80:
1486 case Tfloat32:
1487 case Tfloat64:
1488 case Tfloat80:
1489 case Tcomplex32:
1490 case Tcomplex64:
1491 case Tcomplex80:
1492 return 0; // no
1494 return 1; // yes
1497 int TypeBasic::isbit()
1499 return (ty == Tbit);
1502 int TypeBasic::isintegral()
1504 //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags);
1505 return flags & TFLAGSintegral;
1508 int TypeBasic::isfloating()
1510 return flags & TFLAGSfloating;
1513 int TypeBasic::isreal()
1515 return flags & TFLAGSreal;
1518 int TypeBasic::isimaginary()
1520 return flags & TFLAGSimaginary;
1523 int TypeBasic::iscomplex()
1525 return flags & TFLAGScomplex;
1528 int TypeBasic::isunsigned()
1530 return flags & TFLAGSunsigned;
1533 int TypeBasic::isscalar()
1535 return flags & (TFLAGSintegral | TFLAGSfloating);
1538 MATCH TypeBasic::implicitConvTo(Type *to)
1540 //printf("TypeBasic::implicitConvTo(%s) from %s\n", to->toChars(), toChars());
1541 if (this == to)
1542 return MATCHexact;
1544 if (ty == Tvoid || to->ty == Tvoid)
1545 return MATCHnomatch;
1546 if (1 || global.params.Dversion == 1)
1548 if (to->ty == Tbool)
1549 return MATCHnomatch;
1551 else
1553 if (ty == Tbool || to->ty == Tbool)
1554 return MATCHnomatch;
1556 if (!to->isTypeBasic())
1557 return MATCHnomatch;
1559 TypeBasic *tob = (TypeBasic *)to;
1560 if (flags & TFLAGSintegral)
1562 // Disallow implicit conversion of integers to imaginary or complex
1563 if (tob->flags & (TFLAGSimaginary | TFLAGScomplex))
1564 return MATCHnomatch;
1566 // If converting to integral
1567 if (0 && global.params.Dversion > 1 && tob->flags & TFLAGSintegral)
1568 { d_uns64 sz = size(0);
1569 d_uns64 tosz = tob->size(0);
1571 /* Can't convert to smaller size or, if same size, change sign
1573 if (sz > tosz)
1574 return MATCHnomatch;
1576 /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned)
1577 return MATCHnomatch;*/
1580 else if (flags & TFLAGSfloating)
1582 // Disallow implicit conversion of floating point to integer
1583 if (tob->flags & TFLAGSintegral)
1584 return MATCHnomatch;
1586 assert(tob->flags & TFLAGSfloating);
1588 // Disallow implicit conversion from complex to non-complex
1589 if (flags & TFLAGScomplex && !(tob->flags & TFLAGScomplex))
1590 return MATCHnomatch;
1592 // Disallow implicit conversion of real or imaginary to complex
1593 if (flags & (TFLAGSreal | TFLAGSimaginary) &&
1594 tob->flags & TFLAGScomplex)
1595 return MATCHnomatch;
1597 // Disallow implicit conversion to-from real and imaginary
1598 if ((flags & (TFLAGSreal | TFLAGSimaginary)) !=
1599 (tob->flags & (TFLAGSreal | TFLAGSimaginary)))
1600 return MATCHnomatch;
1602 return MATCHconvert;
1605 TypeBasic *TypeBasic::isTypeBasic()
1607 return (TypeBasic *)this;
1610 /***************************** TypeArray *****************************/
1612 TypeArray::TypeArray(TY ty, Type *next)
1613 : Type(ty, next)
1617 Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
1619 Type *n = this->next->toBasetype(); // uncover any typedef's
1621 #if LOGDOTEXP
1622 printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1623 #endif
1624 if (ident == Id::reverse && (n->ty == Tchar || n->ty == Twchar))
1626 Expression *ec;
1627 FuncDeclaration *fd;
1628 Expressions *arguments;
1629 char *nm;
1630 static char *name[2] = { "_adReverseChar", "_adReverseWchar" };
1632 nm = name[n->ty == Twchar];
1633 fd = FuncDeclaration::genCfunc(next->arrayOf(), nm, Type::tvoid->arrayOf());
1634 ec = new VarExp(0, fd);
1635 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1636 arguments = new Expressions();
1637 arguments->push(e);
1638 e = new CallExp(e->loc, ec, arguments);
1639 e->type = next->arrayOf();
1641 else if (ident == Id::sort && (n->ty == Tchar || n->ty == Twchar))
1643 Expression *ec;
1644 FuncDeclaration *fd;
1645 Expressions *arguments;
1646 char *nm;
1647 static char *name[2] = { "_adSortChar", "_adSortWchar" };
1649 nm = name[n->ty == Twchar];
1650 fd = FuncDeclaration::genCfunc(next->arrayOf(), nm, Type::tvoid->arrayOf());
1651 ec = new VarExp(0, fd);
1652 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1653 arguments = new Expressions();
1654 arguments->push(e);
1655 e = new CallExp(e->loc, ec, arguments);
1656 e->type = next->arrayOf();
1658 else if (ident == Id::reverse || ident == Id::dup)
1660 Expression *ec;
1661 FuncDeclaration *fd;
1662 Expressions *arguments;
1663 target_size_t size = next->size(e->loc);
1664 int dup;
1666 assert(size);
1667 dup = (ident == Id::dup);
1668 if (dup)
1669 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::adDup,
1670 Type::typeinfo->type, Type::tvoid->arrayOf());
1671 else
1672 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::adReverse,
1673 Type::tvoid->arrayOf(), Type::tsize_t);
1674 ec = new VarExp(0, fd);
1675 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1676 arguments = new Expressions();
1677 if (dup)
1678 arguments->push(getTypeInfo(sc));
1679 arguments->push(e);
1680 if (!dup)
1681 arguments->push(new IntegerExp(0, size, Type::tsize_t));
1682 e = new CallExp(e->loc, ec, arguments);
1683 e->type = next->arrayOf();
1685 else if (ident == Id::sort)
1687 Expression *ec;
1688 FuncDeclaration *fd;
1689 Expressions *arguments;
1691 fd = FuncDeclaration::genCfunc(tint32->arrayOf(),
1692 (char*)(n->ty == Tbit ? "_adSortBit" : "_adSort"),
1693 Type::tvoid->arrayOf(),
1694 n->ty == Tbit ? NULL : Type::tvoid->pointerTo());
1695 ec = new VarExp(0, fd);
1696 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1697 arguments = new Expressions();
1698 arguments->push(e);
1699 if (next->ty != Tbit)
1700 arguments->push(n->ty == Tsarray
1701 ? n->getTypeInfo(sc) // don't convert to dynamic array
1702 : n->getInternalTypeInfo(sc));
1703 e = new CallExp(e->loc, ec, arguments);
1704 e->type = next->arrayOf();
1706 else
1708 e = Type::dotExp(sc, e, ident);
1710 return e;
1714 /***************************** TypeSArray *****************************/
1716 TypeSArray::TypeSArray(Type *t, Expression *dim)
1717 : TypeArray(Tsarray, t)
1719 //printf("TypeSArray(%s)\n", dim->toChars());
1720 this->dim = dim;
1723 Type *TypeSArray::syntaxCopy()
1725 Type *t = next->syntaxCopy();
1726 Expression *e = dim->syntaxCopy();
1727 t = new TypeSArray(t, e);
1728 return t;
1731 d_uns64 TypeSArray::size(Loc loc)
1732 { integer_t sz;
1734 if (!dim)
1735 return Type::size(loc);
1736 sz = dim->toInteger();
1737 if (next->toBasetype()->ty == Tbit) // if array of bits
1739 if (sz + 31 < sz)
1740 goto Loverflow;
1741 sz = ((sz + 31) & ~31) / 8; // size in bytes, rounded up to 32 bit dwords
1743 else
1744 { integer_t n, n2;
1746 n = next->size();
1747 n2 = n * sz;
1748 if (n && (n2 / n) != sz)
1749 goto Loverflow;
1750 sz = n2;
1752 return sz;
1754 Loverflow:
1755 error(loc, "index %"PRIdMAX" overflow for static array", sz);
1756 return 1;
1759 unsigned TypeSArray::alignsize()
1761 return next->alignsize();
1764 /**************************
1765 * This evaluates exp while setting length to be the number
1766 * of elements in the tuple t.
1768 Expression *semanticLength(Scope *sc, Type *t, Expression *exp)
1770 if (t->ty == Ttuple)
1771 { ScopeDsymbol *sym = new ArrayScopeSymbol((TypeTuple *)t);
1772 sym->parent = sc->scopesym;
1773 sc = sc->push(sym);
1775 exp = exp->semantic(sc);
1777 sc->pop();
1779 else
1780 exp = exp->semantic(sc);
1781 return exp;
1784 Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp)
1786 ScopeDsymbol *sym = new ArrayScopeSymbol(s);
1787 sym->parent = sc->scopesym;
1788 sc = sc->push(sym);
1790 exp = exp->semantic(sc);
1792 sc->pop();
1793 return exp;
1796 void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
1798 //printf("TypeSArray::resolve() %s\n", toChars());
1799 next->resolve(loc, sc, pe, pt, ps);
1800 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
1801 if (*pe)
1802 { // It's really an index expression
1803 Expression *e;
1804 e = new IndexExp(loc, *pe, dim);
1805 *pe = e;
1807 else if (*ps)
1808 { Dsymbol *s = *ps;
1809 TupleDeclaration *td = s->isTupleDeclaration();
1810 if (td)
1812 ScopeDsymbol *sym = new ArrayScopeSymbol(td);
1813 sym->parent = sc->scopesym;
1814 sc = sc->push(sym);
1816 dim = dim->semantic(sc);
1817 dim = dim->optimize(WANTvalue | WANTinterpret);
1818 uinteger_t d = dim->toUInteger();
1820 sc = sc->pop();
1822 if (d >= td->objects->dim)
1823 { error(loc, "tuple index %"PRIuMAX" exceeds %u", d, td->objects->dim);
1824 goto Ldefault;
1826 Object *o = (Object *)td->objects->data[(size_t)d];
1827 if (o->dyncast() == DYNCAST_DSYMBOL)
1829 *ps = (Dsymbol *)o;
1830 return;
1832 if (o->dyncast() == DYNCAST_EXPRESSION)
1834 *ps = NULL;
1835 *pe = (Expression *)o;
1836 return;
1839 /* Create a new TupleDeclaration which
1840 * is a slice [d..d+1] out of the old one.
1841 * Do it this way because TemplateInstance::semanticTiargs()
1842 * can handle unresolved Objects this way.
1844 Objects *objects = new Objects;
1845 objects->setDim(1);
1846 objects->data[0] = o;
1848 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
1849 *ps = tds;
1851 else
1852 goto Ldefault;
1854 else
1856 Ldefault:
1857 Type::resolve(loc, sc, pe, pt, ps);
1861 Type *TypeSArray::semantic(Loc loc, Scope *sc)
1863 //printf("TypeSArray::semantic() %s\n", toChars());
1865 Type *t;
1866 Expression *e;
1867 Dsymbol *s;
1868 next->resolve(loc, sc, &e, &t, &s);
1869 if (dim && s && s->isTupleDeclaration())
1870 { TupleDeclaration *sd = s->isTupleDeclaration();
1872 dim = semanticLength(sc, sd, dim);
1873 dim = dim->optimize(WANTvalue | WANTinterpret);
1874 uinteger_t d = dim->toUInteger();
1876 if (d >= sd->objects->dim)
1877 { error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim);
1878 return Type::terror;
1880 Object *o = (Object *)sd->objects->data[(size_t)d];
1881 if (o->dyncast() != DYNCAST_TYPE)
1882 { error(loc, "%s is not a type", toChars());
1883 return Type::terror;
1885 t = (Type *)o;
1886 return t;
1889 next = next->semantic(loc,sc);
1890 Type *tbn = next->toBasetype();
1892 if (dim)
1893 { integer_t n, n2;
1895 dim = semanticLength(sc, tbn, dim);
1897 dim = dim->optimize(WANTvalue | WANTinterpret);
1898 if (sc->parameterSpecialization && dim->op == TOKvar &&
1899 ((VarExp *)dim)->var->storage_class & STCtemplateparameter)
1901 /* It could be a template parameter N which has no value yet:
1902 * template Foo(T : T[N], size_t N);
1904 return this;
1906 integer_t d1 = dim->toInteger();
1907 dim = dim->castTo(sc, tsize_t);
1908 dim = dim->optimize(WANTvalue);
1909 integer_t d2 = dim->toInteger();
1911 if (d1 != d2)
1912 goto Loverflow;
1914 if (tbn->isintegral() ||
1915 tbn->isfloating() ||
1916 tbn->ty == Tpointer ||
1917 tbn->ty == Tarray ||
1918 tbn->ty == Tsarray ||
1919 tbn->ty == Taarray ||
1920 tbn->ty == Tclass)
1922 /* Only do this for types that don't need to have semantic()
1923 * run on them for the size, since they may be forward referenced.
1925 n = tbn->size(loc);
1926 n2 = n * d2;
1927 if ((int)n2 < 0)
1928 goto Loverflow;
1929 if (n2 >= 0x1000000) // put a 'reasonable' limit on it
1930 goto Loverflow;
1931 if (n && n2 / n != d2)
1933 Loverflow:
1934 error(loc, "index %"PRIdMAX" overflow for static array", d1);
1935 dim = new IntegerExp(0, 1, tsize_t);
1939 switch (tbn->ty)
1941 case Ttuple:
1942 { // Index the tuple to get the type
1943 assert(dim);
1944 TypeTuple *tt = (TypeTuple *)tbn;
1945 uinteger_t d = dim->toUInteger();
1947 if (d >= tt->arguments->dim)
1948 { error(loc, "tuple index %"PRIuMAX" exceeds %u", d, tt->arguments->dim);
1949 return Type::terror;
1951 Argument *arg = (Argument *)tt->arguments->data[(size_t)d];
1952 return arg->type;
1954 case Tfunction:
1955 case Tnone:
1956 error(loc, "can't have array of %s", tbn->toChars());
1957 tbn = next = tint32;
1958 break;
1960 if (tbn->isauto())
1961 error(loc, "cannot have array of auto %s", tbn->toChars());
1962 return merge();
1965 void TypeSArray::toDecoBuffer(OutBuffer *buf)
1967 buf->writeByte(mangleChar[ty]);
1968 if (dim)
1969 buf->printf("%"PRIuMAX, dim->toInteger());
1970 if (next)
1971 next->toDecoBuffer(buf);
1974 void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
1976 if (mod != this->mod)
1977 { toCBuffer3(buf, hgs, mod);
1978 return;
1980 next->toCBuffer2(buf, hgs, this->mod);
1981 buf->printf("[%s]", dim->toChars());
1984 Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
1986 #if LOGDOTEXP
1987 printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1988 #endif
1989 if (ident == Id::length)
1991 e = dim;
1993 else if (ident == Id::ptr)
1995 e = e->castTo(sc, next->pointerTo());
1997 else
1999 e = TypeArray::dotExp(sc, e, ident);
2001 return e;
2004 int TypeSArray::isString()
2006 TY nty = next->toBasetype()->ty;
2007 return nty == Tchar || nty == Twchar || nty == Tdchar;
2010 unsigned TypeSArray::memalign(unsigned salign)
2012 return next->memalign(salign);
2015 MATCH TypeSArray::implicitConvTo(Type *to)
2017 //printf("TypeSArray::implicitConvTo()\n");
2019 if (to->ty == Tmaybe && to->next)
2020 to = to->next;
2022 // Allow implicit conversion of static array to pointer or dynamic array
2023 if ((IMPLICIT_ARRAY_TO_PTR && to->ty == Tpointer) &&
2024 (to->next->ty == Tvoid || next->equals(to->next)
2025 /*|| to->next->isBaseOf(next)*/))
2027 return MATCHconvert;
2029 if (to->ty == Tarray)
2030 { target_ptrdiff_t offset = 0;
2032 if (next->equals(to->next) ||
2033 (to->next->isBaseOf(next, &offset) && offset == 0) ||
2034 to->next->ty == Tvoid)
2035 return MATCHconvert;
2037 #if 0
2038 if (to->ty == Tsarray)
2040 TypeSArray *tsa = (TypeSArray *)to;
2042 if (next->equals(tsa->next) && dim->equals(tsa->dim))
2044 return MATCHconvert;
2047 #endif
2048 return Type::implicitConvTo(to);
2051 Expression *TypeSArray::defaultInit(Loc loc)
2053 #if LOGDEFAULTINIT
2054 printf("TypeSArray::defaultInit() '%s'\n", toChars());
2055 #endif
2056 return next->defaultInit(loc);
2059 int TypeSArray::isZeroInit()
2061 return next->isZeroInit();
2065 Expression *TypeSArray::toExpression()
2067 Expression *e = next->toExpression();
2068 if (e)
2069 { Expressions *arguments = new Expressions();
2070 arguments->push(dim);
2071 e = new ArrayExp(dim->loc, e, arguments);
2073 return e;
2076 int TypeSArray::hasPointers()
2078 return next->hasPointers();
2081 /***************************** TypeDArray *****************************/
2083 TypeDArray::TypeDArray(Type *t)
2084 : TypeArray(Tarray, t)
2086 //printf("TypeDArray(t = %p)\n", t);
2089 Type *TypeDArray::syntaxCopy()
2091 Type *t = next->syntaxCopy();
2092 if (t == next)
2093 t = this;
2094 else
2095 t = new TypeDArray(t);
2096 return t;
2099 d_uns64 TypeDArray::size(Loc loc)
2101 //printf("TypeDArray::size()\n");
2102 return PTRSIZE * 2;
2105 unsigned TypeDArray::alignsize()
2107 // A DArray consists of two ptr-sized values, so align it on pointer size
2108 // boundary
2109 return PTRSIZE;
2112 Type *TypeDArray::semantic(Loc loc, Scope *sc)
2113 { Type *tn = next;
2115 tn = next->semantic(loc,sc);
2116 Type *tbn = tn->toBasetype();
2117 switch (tbn->ty)
2119 case Tfunction:
2120 case Tnone:
2121 case Ttuple:
2122 error(loc, "can't have array of %s", tbn->toChars());
2123 tn = next = tint32;
2124 break;
2126 if (tn->isauto())
2127 error(loc, "cannot have array of auto %s", tn->toChars());
2128 if (next != tn)
2129 //deco = NULL; // redo
2130 return tn->arrayOf();
2131 return merge();
2134 void TypeDArray::toDecoBuffer(OutBuffer *buf)
2136 buf->writeByte(mangleChar[ty]);
2137 if (next)
2138 next->toDecoBuffer(buf);
2141 void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2143 if (mod != this->mod)
2144 { toCBuffer3(buf, hgs, mod);
2145 return;
2147 next->toCBuffer2(buf, hgs, this->mod);
2148 buf->writestring("[]");
2151 Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
2153 #if LOGDOTEXP
2154 printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2155 #endif
2156 if (ident == Id::length)
2158 if (e->op == TOKstring)
2159 { StringExp *se = (StringExp *)e;
2161 return new IntegerExp(se->loc, se->len, Type::tindex);
2163 e = new ArrayLengthExp(e->loc, e);
2164 e->type = Type::tsize_t;
2165 return e;
2167 else if (ident == Id::ptr)
2169 e = e->castTo(sc, next->pointerTo()->maybe());
2170 return e;
2172 else
2174 e = TypeArray::dotExp(sc, e, ident);
2176 return e;
2179 int TypeDArray::isString()
2181 TY nty = next->toBasetype()->ty;
2182 return nty == Tchar || nty == Twchar || nty == Tdchar;
2185 MATCH TypeDArray::implicitConvTo(Type *to)
2187 //printf("TypeDArray::implicitConvTo()\n");
2189 if (to->ty == Tmaybe && to->next)
2190 to = to->next;
2192 // Allow implicit conversion of array to pointer
2193 if (IMPLICIT_ARRAY_TO_PTR &&
2194 to->ty == Tpointer &&
2195 (to->next->ty == Tvoid || next->equals(to->next) /*|| to->next->isBaseOf(next)*/))
2197 return MATCHconvert;
2200 if (to->ty == Tarray)
2201 { target_ptrdiff_t offset = 0;
2203 if ((to->next->isBaseOf(next, &offset) && offset == 0) ||
2204 to->next->ty == Tvoid)
2205 return MATCHconvert;
2207 return Type::implicitConvTo(to);
2210 Expression *TypeDArray::defaultInit(Loc loc)
2212 #if LOGDEFAULTINIT
2213 printf("TypeDArray::defaultInit() '%s'\n", toChars());
2214 #endif
2215 Expression *e;
2216 e = new NullExp(loc);
2217 e->type = this;
2218 return e;
2221 int TypeDArray::isZeroInit()
2223 return 1;
2226 int TypeDArray::checkBoolean()
2228 return TRUE;
2231 int TypeDArray::hasPointers()
2233 return TRUE;
2236 /***************************** TypeAArray *****************************/
2238 TypeAArray::TypeAArray(Type *t, Type *index)
2239 : TypeArray(Taarray, t)
2241 this->index = index;
2242 this->key = NULL;
2245 Type *TypeAArray::syntaxCopy()
2247 Type *t = next->syntaxCopy();
2248 Type *ti = index->syntaxCopy();
2249 if (t == next && ti == index)
2250 t = this;
2251 else
2252 t = new TypeAArray(t, ti);
2253 return t;
2256 d_uns64 TypeAArray::size(Loc loc)
2258 return PTRSIZE /* * 2*/;
2262 Type *TypeAArray::semantic(Loc loc, Scope *sc)
2264 //printf("TypeAArray::semantic() %s index->ty = %d\n", toChars(), index->ty);
2266 // Deal with the case where we thought the index was a type, but
2267 // in reality it was an expression.
2268 if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray)
2270 Expression *e;
2271 Type *t;
2272 Dsymbol *s;
2274 index->resolve(loc, sc, &e, &t, &s);
2275 if (e)
2276 { // It was an expression -
2277 // Rewrite as a static array
2278 TypeSArray *tsa;
2280 tsa = new TypeSArray(next, e);
2281 return tsa->semantic(loc,sc);
2283 else if (t)
2284 index = t;
2285 else
2286 index->error(loc, "index is not a type or an expression");
2288 else
2289 index = index->semantic(loc,sc);
2291 // Compute key type; the purpose of the key type is to
2292 // minimize the permutations of runtime library
2293 // routines as much as possible.
2294 key = index->toBasetype();
2295 switch (key->ty)
2297 #if 0
2298 case Tint8:
2299 case Tuns8:
2300 case Tint16:
2301 case Tuns16:
2302 key = tint32;
2303 break;
2304 #endif
2306 case Tsarray:
2307 #if 0
2308 // Convert to Tarray
2309 key = key->next->arrayOf();
2310 #endif
2311 break;
2312 case Tbit:
2313 case Tbool:
2314 case Tfunction:
2315 case Tvoid:
2316 case Tnone:
2317 error(loc, "can't have associative array key of %s", key->toChars());
2318 break;
2320 next = next->semantic(loc,sc);
2321 switch (next->toBasetype()->ty)
2323 case Tfunction:
2324 case Tnone:
2325 error(loc, "can't have associative array of %s", next->toChars());
2326 break;
2328 if (next->isauto())
2329 error(loc, "cannot have array of auto %s", next->toChars());
2331 return merge();
2334 void TypeAArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
2336 //printf("TypeAArray::resolve() %s\n", toChars());
2338 // Deal with the case where we thought the index was a type, but
2339 // in reality it was an expression.
2340 if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray)
2342 Expression *e;
2343 Type *t;
2344 Dsymbol *s;
2346 index->resolve(loc, sc, &e, &t, &s);
2347 if (e)
2348 { // It was an expression -
2349 // Rewrite as a static array
2351 TypeSArray *tsa = new TypeSArray(next, e);
2352 return tsa->resolve(loc, sc, pe, pt, ps);
2354 else if (t)
2355 index = t;
2356 else
2357 index->error(loc, "index is not a type or an expression");
2359 Type::resolve(loc, sc, pe, pt, ps);
2363 Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
2365 #if LOGDOTEXP
2366 printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2367 #endif
2368 if (ident == Id::length)
2370 Expression *ec;
2371 FuncDeclaration *fd;
2372 Expressions *arguments;
2374 fd = FuncDeclaration::genCfunc(Type::tsize_t, Id::aaLen, Type::tvoid->arrayOf());
2375 ec = new VarExp(0, fd);
2376 arguments = new Expressions();
2377 arguments->push(e);
2378 e = new CallExp(e->loc, ec, arguments);
2379 e->type = fd->type->next;
2381 else if (ident == Id::keys)
2383 Expression *ec;
2384 FuncDeclaration *fd;
2385 Expressions *arguments;
2386 int size = key->size(e->loc);
2388 assert(size);
2389 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaKeys,
2390 Type::tvoid->arrayOf(), Type::tsize_t);
2391 ec = new VarExp(0, fd);
2392 arguments = new Expressions();
2393 arguments->push(e);
2394 arguments->push(new IntegerExp(0, size, Type::tsize_t));
2395 e = new CallExp(e->loc, ec, arguments);
2396 e->type = index->arrayOf();
2398 else if (ident == Id::values)
2400 Expression *ec;
2401 FuncDeclaration *fd;
2402 Expressions *arguments;
2404 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaValues,
2405 Type::tvoid->arrayOf(), Type::tsize_t, Type::tsize_t);
2406 ec = new VarExp(0, fd);
2407 arguments = new Expressions();
2408 arguments->push(e);
2409 size_t keysize = key->size(e->loc);
2410 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1);
2411 arguments->push(new IntegerExp(0, keysize, Type::tsize_t));
2412 arguments->push(new IntegerExp(0, next->size(e->loc), Type::tsize_t));
2413 e = new CallExp(e->loc, ec, arguments);
2414 e->type = next->arrayOf();
2416 else if (ident == Id::rehash)
2418 Expression *ec;
2419 FuncDeclaration *fd;
2420 Expressions *arguments;
2422 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaRehash);
2423 ec = new VarExp(0, fd);
2424 arguments = new Expressions();
2425 arguments->push(e->addressOf(sc));
2426 arguments->push(key->getInternalTypeInfo(sc));
2427 e = new CallExp(e->loc, ec, arguments);
2428 e->type = this;
2430 else
2432 e = Type::dotExp(sc, e, ident);
2434 return e;
2437 void TypeAArray::toDecoBuffer(OutBuffer *buf)
2439 buf->writeByte(mangleChar[ty]);
2440 index->toDecoBuffer(buf);
2441 next->toDecoBuffer(buf);
2444 void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2446 if (mod != this->mod)
2447 { toCBuffer3(buf, hgs, mod);
2448 return;
2450 next->toCBuffer2(buf, hgs, this->mod);
2451 buf->writeByte('[');
2452 index->toCBuffer2(buf, hgs, 0);
2453 buf->writeByte(']');
2456 Expression *TypeAArray::defaultInit(Loc loc)
2458 #if LOGDEFAULTINIT
2459 printf("TypeAArray::defaultInit() '%s'\n", toChars());
2460 #endif
2461 Expression *e;
2462 e = new NullExp(loc);
2463 e->type = this;
2464 return e;
2467 int TypeAArray::checkBoolean()
2469 return TRUE;
2472 int TypeAArray::hasPointers()
2474 return TRUE;
2477 /***************************** TypeMaybe *****************************/
2479 TypeMaybe::TypeMaybe(Type *t)
2480 : Type(Tmaybe, t)
2484 void TypeMaybe::toDecoBuffer(OutBuffer *buf)
2486 int offset = buf->offset;
2488 // Since all D types are TypeMaybe, adding a char here
2489 // would prevent linking to existing libraries.
2490 next->toDecoBuffer(buf);
2492 if (buf->data[offset] == NOT_NULL_MANGLE)
2493 buf->remove(offset, 1); // After semantic: remove not-null qualifier
2494 else
2495 buf->insert(offset, "?", 1); // Before semantic: just make name unique
2498 Type *TypeMaybe::syntaxCopy()
2500 Type *t = next->syntaxCopy();
2501 if (t == next)
2502 t = this;
2503 else
2504 t = new TypeMaybe(t);
2505 return t;
2508 Type *TypeMaybe::toBasetype()
2510 return next->toBasetype();
2513 Expression *TypeMaybe::dotExp(Scope *sc, Expression *e, Identifier *ident)
2515 if (sc->module->isDltFile)
2516 e->error("Attempt to access property '%s' for '%s' of type '%s', which may be null.",
2517 ident->string, e->toChars(), toChars());
2518 // else it came from D - ignore any problems since we can't check
2519 return next->dotExp(sc, e, ident);
2522 Type *TypeMaybe::semantic(Loc loc, Scope *sc)
2524 //printf("TypeMaybe::semantic()\n");
2525 Type *n = next->semantic(loc, sc);
2527 // For D source we don't know if it's a maybe type or not, so the parser
2528 // wraps everything in a TypeMaybe (including structs, etc, since it can't
2529 // tell). If the next type can't be null, we vanish here.
2530 switch (n->ty)
2532 case Tpointer:
2533 if (n->next->ty == Tvoid)
2534 return n;
2535 // fall-through
2536 case Tclass:
2537 break;
2538 default:
2539 error(loc, "can't have maybe for %s of type %d", n->toChars(), n->toBasetype()->ty);
2540 return n;
2542 if (n != next)
2543 deco = NULL;
2544 next = n;
2545 return merge();
2548 d_uns64 TypeMaybe::size(Loc loc)
2550 return next->size();
2553 void TypeMaybe::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2555 //printf("TypeMaybe::toCBuffer2() next = %d\n", next->ty);
2556 if (mod != this->mod)
2557 { toCBuffer3(buf, hgs, mod);
2558 return;
2560 next->toCBuffer2(buf, hgs, this->mod);
2561 buf->writeByte('?');
2564 MATCH TypeMaybe::implicitConvTo(Type *to)
2566 //printf("TypeMaybe::implicitConvTo(%s)\n", to->toChars());
2568 if (this == to)
2569 return MATCHexact;
2571 return MATCHnomatch;
2574 int TypeMaybe::isscalar()
2576 return next->isscalar();
2579 Expression *TypeMaybe::defaultInit(Loc loc)
2581 #if LOGDEFAULTINIT
2582 printf("TypeMaybe::defaultInit() '%s'\n", toChars());
2583 #endif
2584 return next->defaultInit();
2587 int TypeMaybe::isZeroInit()
2589 return next->isZeroInit();
2592 int TypeMaybe::hasPointers()
2594 return next->hasPointers();
2597 /***************************** TypePointer *****************************/
2599 TypePointer::TypePointer(Type *t)
2600 : Type(Tpointer, t)
2604 Type *TypePointer::syntaxCopy()
2606 Type *t = next->syntaxCopy();
2607 if (t == next)
2608 t = this;
2609 else
2610 t = new TypePointer(t);
2611 return t;
2614 Type *TypePointer::semantic(Loc loc, Scope *sc)
2616 //printf("TypePointer::semantic()\n");
2617 Type *n = next->semantic(loc, sc);
2618 switch (n->toBasetype()->ty)
2620 case Ttuple:
2621 error(loc, "can't have pointer to %s", n->toChars());
2622 n = tint32;
2623 break;
2625 if (n != next)
2626 deco = NULL;
2627 next = n;
2628 return merge();
2632 d_uns64 TypePointer::size(Loc loc)
2634 return PTRSIZE;
2637 void TypePointer::toDecoBuffer(OutBuffer *buf)
2639 buf->writeByte(NOT_NULL_MANGLE);
2640 Type::toDecoBuffer(buf);
2643 void TypePointer::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2645 //printf("TypePointer::toCBuffer2() next = %d\n", next->ty);
2646 if (mod != this->mod)
2647 { toCBuffer3(buf, hgs, mod);
2648 return;
2650 next->toCBuffer2(buf, hgs, this->mod);
2651 if (next->ty != Tfunction)
2652 buf->writeByte('*');
2655 MATCH TypePointer::implicitConvTo(Type *to)
2657 //printf("TypePointer::implicitConvTo()\n");
2659 // Can always convert a "Foo*" to a "Foo*?"
2660 if (to->ty == Tmaybe && to->next)
2661 to = to->next;
2663 if (this == to)
2664 return MATCHexact;
2665 if (to->ty == Tpointer && to->next)
2667 if (to->next->ty == Tvoid)
2668 return MATCHconvert;
2670 #if 0
2671 if (to->next->isBaseOf(next))
2672 return MATCHconvert;
2673 #endif
2675 if (next->ty == Tfunction && to->next->ty == Tfunction)
2676 { TypeFunction *tf;
2677 TypeFunction *tfto;
2679 tf = (TypeFunction *)(next);
2680 tfto = (TypeFunction *)(to->next);
2681 return tfto->equals(tf) ? MATCHexact : MATCHnomatch;
2684 // if (to->ty == Tvoid)
2685 // return MATCHconvert;
2686 return MATCHnomatch;
2689 int TypePointer::isscalar()
2691 return TRUE;
2694 Expression *TypePointer::defaultInit(Loc loc)
2696 #if LOGDEFAULTINIT
2697 printf("TypePointer::defaultInit() '%s'\n", toChars());
2698 #endif
2699 Expression *e;
2700 e = new NullExp(loc);
2701 e->type = this;
2702 return e;
2705 int TypePointer::isZeroInit()
2707 return 1;
2710 int TypePointer::hasPointers()
2712 return TRUE;
2716 /***************************** TypeReference *****************************/
2718 TypeReference::TypeReference(Type *t)
2719 : Type(Treference, t)
2721 if (t->ty == Tbit)
2722 error(0,"cannot make reference to a bit");
2723 // BUG: what about references to static arrays?
2726 Type *TypeReference::syntaxCopy()
2728 Type *t = next->syntaxCopy();
2729 if (t == next)
2730 t = this;
2731 else
2732 t = new TypeReference(t);
2733 return t;
2736 d_uns64 TypeReference::size(Loc loc)
2738 return PTRSIZE;
2741 void TypeReference::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2743 if (mod != this->mod)
2744 { toCBuffer3(buf, hgs, mod);
2745 return;
2747 next->toCBuffer2(buf, hgs, this->mod);
2748 buf->writeByte('&');
2751 Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident)
2753 #if LOGDOTEXP
2754 printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2755 #endif
2757 // References just forward things along
2758 return next->dotExp(sc, e, ident);
2761 Expression *TypeReference::defaultInit(Loc loc)
2763 #if LOGDEFAULTINIT
2764 printf("TypeReference::defaultInit() '%s'\n", toChars());
2765 #endif
2766 Expression *e;
2767 e = new NullExp(loc);
2768 e->type = this;
2769 return e;
2772 int TypeReference::isZeroInit()
2774 return 1;
2778 /***************************** TypeFunction *****************************/
2780 TypeFunction::TypeFunction(Arguments *parameters, Type *treturn, int varargs, enum LINK linkage)
2781 : Type(Tfunction, treturn)
2783 //if (!treturn) *(char*)0=0;
2784 // assert(treturn);
2785 this->parameters = parameters;
2786 this->varargs = varargs;
2787 this->linkage = linkage;
2788 this->inuse = 0;
2791 Type *TypeFunction::syntaxCopy()
2793 Type *treturn = next ? next->syntaxCopy() : NULL;
2794 Arguments *params = Argument::arraySyntaxCopy(parameters);
2795 Type *t = new TypeFunction(params, treturn, varargs, linkage);
2796 return t;
2799 /*******************************
2800 * Returns:
2801 * 0 types are distinct
2802 * 1 this is covariant with t
2803 * 2 arguments match as far as overloading goes,
2804 * but types are not covariant
2805 * 3 cannot determine covariance because of forward references
2808 int Type::covariant(Type *t)
2810 #if 0
2811 printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars());
2812 printf("deco = %p, %p\n", deco, t->deco);
2813 printf("ty = %d\n", next->ty);
2814 #endif
2816 int inoutmismatch = 0;
2818 if (equals(t))
2819 goto Lcovariant;
2820 if (ty != Tfunction || t->ty != Tfunction)
2821 goto Ldistinct;
2824 TypeFunction *t1 = (TypeFunction *)this;
2825 TypeFunction *t2 = (TypeFunction *)t;
2827 if (t1->varargs != t2->varargs)
2828 goto Ldistinct;
2830 if (t1->parameters && t2->parameters)
2832 size_t dim = Argument::dim(t1->parameters);
2833 if (dim != Argument::dim(t2->parameters))
2834 goto Ldistinct;
2836 for (size_t i = 0; i < dim; i++)
2837 { Argument *arg1 = Argument::getNth(t1->parameters, i);
2838 Argument *arg2 = Argument::getNth(t2->parameters, i);
2840 if (!arg1->type->equals(arg2->type))
2841 goto Ldistinct;
2842 if (arg1->storageClass != arg2->storageClass)
2843 inoutmismatch = 1;
2846 else if (t1->parameters != t2->parameters)
2847 goto Ldistinct;
2849 // The argument lists match
2850 if (inoutmismatch)
2851 goto Lnotcovariant;
2852 if (t1->linkage != t2->linkage)
2853 goto Lnotcovariant;
2855 Type *t1n = t1->next;
2856 Type *t2n = t2->next;
2858 if (t1n->equals(t2n))
2859 goto Lcovariant;
2860 if (t1n->ty != Tclass || t2n->ty != Tclass)
2861 goto Lnotcovariant;
2863 // If t1n is forward referenced:
2864 ClassDeclaration *cd = ((TypeClass *)t1n)->sym;
2865 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
2867 return 3;
2870 if (t1n->implicitConvTo(t2n))
2871 goto Lcovariant;
2872 goto Lnotcovariant;
2875 Lcovariant:
2876 //printf("\tcovaraint: 1\n");
2877 return 1;
2879 Ldistinct:
2880 //printf("\tcovaraint: 0\n");
2881 return 0;
2883 Lnotcovariant:
2884 //printf("\tcovaraint: 2\n");
2885 return 2;
2888 void TypeFunction::toDecoBuffer(OutBuffer *buf)
2889 { unsigned char mc;
2891 //printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars());
2892 //static int nest; if (++nest == 50) *(char*)0=0;
2893 if (inuse)
2894 { inuse = 2; // flag error to caller
2895 return;
2897 inuse++;
2898 switch (linkage)
2900 case LINKd: mc = 'F'; break;
2901 case LINKc: mc = 'U'; break;
2902 case LINKwindows: mc = 'W'; break;
2903 case LINKpascal: mc = 'V'; break;
2904 case LINKcpp: mc = 'R'; break;
2905 default:
2906 assert(0);
2908 buf->writeByte(mc);
2909 // Write argument types
2910 Argument::argsToDecoBuffer(buf, parameters);
2911 //if (buf->data[buf->offset - 1] == '@') halt();
2912 buf->writeByte('Z' - varargs); // mark end of arg list
2913 next->toDecoBuffer(buf);
2914 inuse--;
2917 void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
2919 char *p = NULL;
2921 if (inuse)
2922 { inuse = 2; // flag error to caller
2923 return;
2925 inuse++;
2926 if (next && (!ident || ident->toHChars2() == ident->toChars()))
2927 next->toCBuffer2(buf, hgs, 0);
2928 if (hgs->ddoc != 1)
2930 switch (linkage)
2932 case LINKd: p = NULL; break;
2933 case LINKc: p = "C "; break;
2934 case LINKwindows: p = "Windows "; break;
2935 case LINKpascal: p = "Pascal "; break;
2936 case LINKcpp: p = "C++ "; break;
2937 default:
2938 assert(0);
2942 if (!hgs->hdrgen && p)
2943 buf->writestring(p);
2944 if (ident)
2945 { buf->writeByte(' ');
2946 buf->writestring(ident->toHChars2());
2948 Argument::argsToCBuffer(buf, hgs, parameters, varargs);
2949 inuse--;
2952 void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2954 char *p = NULL;
2956 if (inuse)
2957 { inuse = 2; // flag error to caller
2958 return;
2960 inuse++;
2961 if (next)
2962 next->toCBuffer2(buf, hgs, 0);
2963 if (hgs->ddoc != 1)
2965 switch (linkage)
2967 case LINKd: p = NULL; break;
2968 case LINKc: p = "C "; break;
2969 case LINKwindows: p = "Windows "; break;
2970 case LINKpascal: p = "Pascal "; break;
2971 case LINKcpp: p = "C++ "; break;
2972 default:
2973 assert(0);
2977 if (!hgs->hdrgen && p)
2978 buf->writestring(p);
2979 buf->writestring(" function");
2980 Argument::argsToCBuffer(buf, hgs, parameters, varargs);
2981 inuse--;
2984 Type *TypeFunction::semantic(Loc loc, Scope *sc)
2986 if (deco) // if semantic() already run
2988 //printf("already done\n");
2989 return this;
2991 //printf("TypeFunction::semantic() this = %p\n", this);
2993 TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
2994 memcpy(tf, this, sizeof(TypeFunction));
2995 if (parameters)
2996 { tf->parameters = (Arguments *)parameters->copy();
2997 for (size_t i = 0; i < parameters->dim; i++)
2998 { Argument *arg = (Argument *)parameters->data[i];
2999 Argument *cpy = (Argument *)mem.malloc(sizeof(Argument));
3000 memcpy(cpy, arg, sizeof(Argument));
3001 tf->parameters->data[i] = (void *)cpy;
3005 tf->linkage = sc->linkage;
3006 if (!tf->next)
3008 assert(global.errors);
3009 tf->next = tvoid;
3011 tf->next = tf->next->semantic(loc,sc);
3012 if (tf->next->toBasetype()->ty == Tsarray)
3013 { error(loc, "functions cannot return static array %s", tf->next->toChars());
3014 tf->next = Type::terror;
3016 if (tf->next->toBasetype()->ty == Tfunction)
3017 { error(loc, "functions cannot return a function");
3018 tf->next = Type::terror;
3020 if (tf->next->toBasetype()->ty == Ttuple)
3021 { error(loc, "functions cannot return a tuple");
3022 tf->next = Type::terror;
3024 if (tf->next->isauto() && !(sc->flags & SCOPEctor))
3025 error(loc, "functions cannot return auto %s", tf->next->toChars());
3027 if (tf->parameters)
3028 { size_t dim = Argument::dim(tf->parameters);
3030 for (size_t i = 0; i < dim; i++)
3031 { Argument *arg = Argument::getNth(tf->parameters, i);
3032 Type *t;
3034 tf->inuse++;
3035 arg->type = arg->type->semantic(loc,sc);
3036 if (tf->inuse == 1) tf->inuse--;
3037 t = arg->type->toBasetype();
3039 if (arg->storageClass & (STCout | STCref | STClazy))
3041 if (t->ty == Tsarray)
3042 error(loc, "cannot have out or ref parameter of type %s", t->toChars());
3044 if (!(arg->storageClass & STClazy) && t->ty == Tvoid)
3045 error(loc, "cannot have parameter of type %s", arg->type->toChars());
3047 if (arg->defaultArg)
3049 arg->defaultArg = arg->defaultArg->semantic(sc);
3050 arg->defaultArg = resolveProperties(sc, arg->defaultArg);
3051 arg->defaultArg = arg->defaultArg->implicitCastTo(sc, arg->type);
3054 /* If arg turns out to be a tuple, the number of parameters may
3055 * change.
3057 if (t->ty == Ttuple)
3058 { dim = Argument::dim(tf->parameters);
3059 i--;
3063 tf->deco = tf->merge()->deco;
3065 if (tf->inuse)
3066 { error(loc, "recursive type");
3067 tf->inuse = 0;
3068 return terror;
3071 if (tf->varargs == 1 && tf->linkage != LINKd && Argument::dim(tf->parameters) == 0)
3072 error(loc, "variadic functions with non-D linkage must have at least one parameter");
3074 /* Don't return merge(), because arg identifiers and default args
3075 * can be different
3076 * even though the types match
3078 return tf;
3081 /********************************
3082 * 'args' are being matched to function 'this'
3083 * Determine match level.
3084 * Returns:
3085 * MATCHxxxx
3088 int TypeFunction::callMatch(Expressions *args)
3090 //printf("TypeFunction::callMatch()\n");
3091 int match = MATCHexact; // assume exact match
3093 size_t nparams = Argument::dim(parameters);
3094 size_t nargs = args ? args->dim : 0;
3095 if (nparams == nargs)
3097 else if (nargs > nparams)
3099 if (varargs == 0)
3100 goto Nomatch; // too many args; no match
3101 match = MATCHconvert; // match ... with a "conversion" match level
3104 for (size_t u = 0; u < nparams; u++)
3105 { int m;
3106 Expression *arg;
3108 // BUG: what about out and ref?
3110 Argument *p = Argument::getNth(parameters, u);
3111 assert(p);
3112 if (u >= nargs)
3114 if (p->defaultArg)
3115 continue;
3116 if (varargs == 2 && u + 1 == nparams)
3117 goto L1;
3118 goto Nomatch; // not enough arguments
3120 arg = (Expression *)args->data[u];
3121 assert(arg);
3122 if (p->storageClass & STClazy && p->type->ty == Tvoid && arg->type->ty != Tvoid)
3123 m = MATCHconvert;
3124 else
3125 m = arg->implicitConvTo(p->type);
3126 //printf("\tm = %d\n", m);
3127 if (m == MATCHnomatch) // if no match
3130 if (varargs == 2 && u + 1 == nparams) // if last varargs param
3131 { Type *tb = p->type->toBasetype();
3132 TypeSArray *tsa;
3133 integer_t sz;
3135 switch (tb->ty)
3137 case Tsarray:
3138 tsa = (TypeSArray *)tb;
3139 sz = tsa->dim->toInteger();
3140 if (sz != nargs - u)
3141 goto Nomatch;
3142 case Tarray:
3143 for (; u < nargs; u++)
3145 arg = (Expression *)args->data[u];
3146 assert(arg);
3147 #if 1
3148 /* If lazy array of delegates,
3149 * convert arg(s) to delegate(s)
3151 Type *tret = p->isLazyArray();
3152 if (tret)
3154 if (tb->next->equals(arg->type))
3155 { m = MATCHexact;
3157 else
3159 m = arg->implicitConvTo(tret);
3160 if (m == MATCHnomatch)
3162 if (tret->toBasetype()->ty == Tvoid)
3163 m = MATCHconvert;
3167 else
3168 m = arg->implicitConvTo(tb->next);
3169 #else
3170 m = arg->implicitConvTo(tb->next);
3171 #endif
3172 if (m == 0)
3173 goto Nomatch;
3174 if (m < match)
3175 match = m;
3177 goto Ldone;
3179 case Tclass:
3180 // Should see if there's a constructor match?
3181 // Or just leave it ambiguous?
3182 goto Ldone;
3184 default:
3185 goto Nomatch;
3188 goto Nomatch;
3190 if (m < match)
3191 match = m; // pick worst match
3194 Ldone:
3195 //printf("match = %d\n", match);
3196 return match;
3198 Nomatch:
3199 //printf("no match\n");
3200 return MATCHnomatch;
3203 Type *TypeFunction::reliesOnTident()
3205 if (parameters)
3207 for (size_t i = 0; i < parameters->dim; i++)
3208 { Argument *arg = (Argument *)parameters->data[i];
3209 Type *t = arg->type->reliesOnTident();
3210 if (t)
3211 return t;
3214 return next->reliesOnTident();
3217 /***************************** TypeDelegate *****************************/
3219 TypeDelegate::TypeDelegate(Type *t)
3220 : Type(Tfunction, t)
3222 ty = Tdelegate;
3225 Type *TypeDelegate::syntaxCopy()
3227 Type *t = next->syntaxCopy();
3228 if (t == next)
3229 t = this;
3230 else
3231 t = new TypeDelegate(t);
3232 return t;
3235 Type *TypeDelegate::semantic(Loc loc, Scope *sc)
3237 if (deco) // if semantic() already run
3239 //printf("already done\n");
3240 return this;
3242 next = next->semantic(loc,sc);
3243 return merge();
3246 d_uns64 TypeDelegate::size(Loc loc)
3248 return PTRSIZE * 2;
3251 void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3253 if (mod != this->mod)
3254 { toCBuffer3(buf, hgs, mod);
3255 return;
3257 TypeFunction *tf = (TypeFunction *)next;
3259 tf->next->toCBuffer2(buf, hgs, 0);
3260 buf->writestring(" delegate");
3261 Argument::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs);
3264 Expression *TypeDelegate::defaultInit(Loc loc)
3266 #if LOGDEFAULTINIT
3267 printf("TypeDelegate::defaultInit() '%s'\n", toChars());
3268 #endif
3269 Expression *e;
3270 e = new NullExp(loc);
3271 e->type = this;
3272 return e;
3275 int TypeDelegate::isZeroInit()
3277 return 1;
3280 int TypeDelegate::checkBoolean()
3282 return TRUE;
3285 Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident)
3287 #if LOGDOTEXP
3288 printf("TypeDelegate::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
3289 #endif
3290 if (ident == Id::ptr)
3292 #ifndef IN_GCC
3293 e->type = tvoidptr;
3294 #else
3295 if (e->op == TOKdelegate || e->op == TOKcast)
3296 e = e->castTo(sc, tvoidptr); // Not an lvalue
3297 else
3299 e = e->addressOf(sc);
3300 e = e->castTo(sc, tvoidptr->pointerTo());
3301 e = new PtrExp(e->loc, e);
3302 e->type = tvoidptr;
3304 #endif
3305 return e;
3307 else if (ident == Id::funcptr)
3309 e = e->addressOf(sc);
3310 e->type = tvoidptr;
3311 e = new AddExp(e->loc, e, new IntegerExp(PTRSIZE));
3312 e->type = tvoidptr;
3313 e = new PtrExp(e->loc, e);
3314 e->type = next->pointerTo();
3315 return e;
3317 else
3319 e = Type::dotExp(sc, e, ident);
3321 return e;
3324 int TypeDelegate::hasPointers()
3326 return TRUE;
3331 /***************************** TypeQualified *****************************/
3333 TypeQualified::TypeQualified(TY ty, Loc loc)
3334 : Type(ty, NULL)
3336 this->loc = loc;
3339 void TypeQualified::syntaxCopyHelper(TypeQualified *t)
3341 //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t->toChars(), toChars());
3342 idents.setDim(t->idents.dim);
3343 for (int i = 0; i < idents.dim; i++)
3345 Identifier *id = (Identifier *)t->idents.data[i];
3346 if (id->dyncast() == DYNCAST_DSYMBOL)
3348 TemplateInstance *ti = (TemplateInstance *)id;
3350 ti = (TemplateInstance *)ti->syntaxCopy(NULL);
3351 id = (Identifier *)ti;
3353 idents.data[i] = id;
3358 void TypeQualified::addIdent(Identifier *ident)
3360 idents.push(ident);
3363 void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs)
3365 int i;
3367 for (i = 0; i < idents.dim; i++)
3368 { Identifier *id = (Identifier *)idents.data[i];
3370 buf->writeByte('.');
3372 if (id->dyncast() == DYNCAST_DSYMBOL)
3374 TemplateInstance *ti = (TemplateInstance *)id;
3375 ti->toCBuffer(buf, hgs);
3377 else
3378 buf->writestring(id->toChars());
3382 d_uns64 TypeQualified::size(Loc loc)
3384 error(this->loc, "size of type %s is not known", toChars());
3385 return 1;
3388 /*************************************
3389 * Takes an array of Identifiers and figures out if
3390 * it represents a Type or an Expression.
3391 * Output:
3392 * if expression, *pe is set
3393 * if type, *pt is set
3396 void TypeQualified::resolveHelper(Loc loc, Scope *sc,
3397 Dsymbol *s, Dsymbol *scopesym,
3398 Expression **pe, Type **pt, Dsymbol **ps)
3400 Identifier *id = NULL;
3401 int i;
3402 VarDeclaration *v;
3403 EnumMember *em;
3404 TupleDeclaration *td;
3405 Type *t;
3406 Expression *e;
3408 #if 0
3409 printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, toChars());
3410 if (scopesym)
3411 printf("\tscopesym = '%s'\n", scopesym->toChars());
3412 #endif
3413 *pe = NULL;
3414 *pt = NULL;
3415 *ps = NULL;
3416 if (s)
3418 //printf("\t1: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3419 s = s->toAlias();
3420 //printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3421 for (i = 0; i < idents.dim; i++)
3422 { Dsymbol *sm;
3424 id = (Identifier *)idents.data[i];
3425 sm = s->searchX(loc, sc, id);
3426 //printf("\t3: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3427 //printf("getType = '%s'\n", s->getType()->toChars());
3428 if (!sm)
3430 v = s->isVarDeclaration();
3431 if (v && id == Id::length)
3433 if (v->isConst() && v->getExpInitializer())
3434 { e = v->getExpInitializer()->exp;
3436 else
3437 e = new VarExp(loc, v);
3438 t = e->type;
3439 if (!t)
3440 goto Lerror;
3441 goto L3;
3443 t = s->getType();
3444 if (!t && s->isDeclaration())
3445 t = s->isDeclaration()->type;
3446 if (t)
3448 sm = t->toDsymbol(sc);
3449 if (sm)
3450 { sm = sm->search(loc, id, 0);
3451 if (sm)
3452 goto L2;
3454 //e = t->getProperty(loc, id);
3455 e = new TypeExp(loc, t);
3456 e = t->dotExp(sc, e, id);
3457 i++;
3459 for (; i < idents.dim; i++)
3461 id = (Identifier *)idents.data[i];
3462 //printf("e: '%s', id: '%s', type = %p\n", e->toChars(), id->toChars(), e->type);
3463 e = e->type->dotExp(sc, e, id);
3465 *pe = e;
3467 else
3468 Lerror:
3469 error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
3470 return;
3473 s = sm->toAlias();
3476 v = s->isVarDeclaration();
3477 if (v)
3479 // It's not a type, it's an expression
3480 if (v->isConst() && v->getExpInitializer())
3482 ExpInitializer *ei = v->getExpInitializer();
3483 assert(ei);
3484 *pe = ei->exp->copy(); // make copy so we can change loc
3485 (*pe)->loc = loc;
3487 else
3489 #if 0
3490 WithScopeSymbol *withsym;
3491 if (scopesym && (withsym = scopesym->isWithScopeSymbol()) != NULL)
3493 // Same as wthis.ident
3494 e = new VarExp(loc, withsym->withstate->wthis);
3495 e = new DotIdExp(loc, e, ident);
3496 //assert(0); // BUG: should handle this
3498 else
3499 #endif
3500 *pe = new VarExp(loc, v);
3502 return;
3504 em = s->isEnumMember();
3505 if (em)
3507 // It's not a type, it's an expression
3508 *pe = em->value->copy();
3509 return;
3513 t = s->getType();
3514 if (!t)
3516 // If the symbol is an import, try looking inside the import
3517 Import *si;
3519 si = s->isImport();
3520 if (si)
3522 s = si->search(loc, s->ident, 0);
3523 if (s && s != si)
3524 goto L1;
3525 s = si;
3527 *ps = s;
3528 return;
3530 if (t->ty == Tinstance && t != this && !t->deco)
3531 { error(loc, "forward reference to '%s'", t->toChars());
3532 return;
3535 if (t != this)
3537 if (t->reliesOnTident())
3539 Scope *scx;
3541 for (scx = sc; 1; scx = scx->enclosing)
3543 if (!scx)
3544 { error(loc, "forward reference to '%s'", t->toChars());
3545 return;
3547 if (scx->scopesym == scopesym)
3548 break;
3550 t = t->semantic(loc, scx);
3551 //((TypeIdentifier *)t)->resolve(loc, scx, pe, &t, ps);
3554 if (t->ty == Ttuple)
3555 *pt = t;
3556 else
3557 *pt = t->merge();
3559 if (!s)
3561 error(loc, "identifier '%s' is not defined", toChars());
3565 /***************************** TypeIdentifier *****************************/
3567 TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident)
3568 : TypeQualified(Tident, loc)
3570 this->ident = ident;
3571 this->maybe = 0;
3575 Type *TypeIdentifier::syntaxCopy()
3577 TypeIdentifier *t;
3579 t = new TypeIdentifier(loc, ident);
3580 t->syntaxCopyHelper(this);
3581 return t;
3584 void TypeIdentifier::toDecoBuffer(OutBuffer *buf)
3585 { unsigned len;
3586 char *name;
3588 name = ident->toChars();
3589 len = strlen(name);
3590 buf->printf("%c%d%s", mangleChar[ty], len, name);
3591 //buf->printf("%c%s", mangleChar[ty], name);
3594 void TypeIdentifier::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3596 if (mod != this->mod)
3597 { toCBuffer3(buf, hgs, mod);
3598 return;
3600 buf->writestring(this->ident->toChars());
3601 toCBuffer2Helper(buf, hgs);
3604 /*************************************
3605 * Takes an array of Identifiers and figures out if
3606 * it represents a Type or an Expression.
3607 * Output:
3608 * if expression, *pe is set
3609 * if type, *pt is set
3612 void TypeIdentifier::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
3613 { Dsymbol *s;
3614 Dsymbol *scopesym;
3616 //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars());
3617 s = sc->search(loc, ident, &scopesym);
3618 resolveHelper(loc, sc, s, scopesym, pe, pt, ps);
3621 /*****************************************
3622 * See if type resolves to a symbol, if so,
3623 * return that symbol.
3626 Dsymbol *TypeIdentifier::toDsymbol(Scope *sc)
3628 //printf("TypeIdentifier::toDsymbol('%s')\n", toChars());
3629 if (!sc)
3630 return NULL;
3631 //printf("ident = '%s'\n", ident->toChars());
3633 Dsymbol *scopesym;
3634 Dsymbol *s = sc->search(loc, ident, &scopesym);
3635 if (s)
3637 for (int i = 0; i < idents.dim; i++)
3639 Identifier *id = (Identifier *)idents.data[i];
3640 s = s->searchX(loc, sc, id);
3641 if (!s) // failed to find a symbol
3642 { //printf("\tdidn't find a symbol\n");
3643 break;
3647 return s;
3650 Type *TypeIdentifier::semantic(Loc loc, Scope *sc)
3652 Type *t;
3653 Expression *e;
3654 Dsymbol *s;
3656 //printf("TypeIdentifier::semantic(%s)\n", toChars());
3657 resolve(loc, sc, &e, &t, &s);
3658 if (t)
3660 //printf("\tit's a type %d, %s, %s\n", t->ty, t->toChars(), t->deco);
3662 if (t->ty == Ttypedef)
3663 { TypeTypedef *tt = (TypeTypedef *)t;
3665 if (tt->sym->sem == 1)
3666 error(loc, "circular reference of typedef %s", tt->toChars());
3668 // Do the delayed wrapping now we're sure it's a type
3669 if (maybe) {
3670 return t->maybe()->semantic(loc, sc);
3673 else
3675 #ifdef DEBUG
3676 if (!global.gag)
3677 printf("1: ");
3678 #endif
3679 if (s)
3681 s->error(loc, "is used as a type");
3683 else
3684 error(loc, "%s is used as a type", toChars());
3685 t = tvoid;
3687 //t->print();
3688 return t;
3691 Type *TypeIdentifier::reliesOnTident()
3693 return this;
3696 Expression *TypeIdentifier::toExpression()
3698 Expression *e = new IdentifierExp(loc, ident);
3699 for (int i = 0; i < idents.dim; i++)
3701 Identifier *id = (Identifier *)idents.data[i];
3702 e = new DotIdExp(loc, e, id);
3705 return e;
3708 /***************************** TypeInstance *****************************/
3710 TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst)
3711 : TypeQualified(Tinstance, loc)
3713 this->tempinst = tempinst;
3716 Type *TypeInstance::syntaxCopy()
3718 //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim);
3719 TypeInstance *t;
3721 t = new TypeInstance(loc, (TemplateInstance *)tempinst->syntaxCopy(NULL));
3722 t->syntaxCopyHelper(this);
3723 return t;
3727 void TypeInstance::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3729 if (mod != this->mod)
3730 { toCBuffer3(buf, hgs, mod);
3731 return;
3733 tempinst->toCBuffer(buf, hgs);
3734 toCBuffer2Helper(buf, hgs);
3737 void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
3739 // Note close similarity to TypeIdentifier::resolve()
3741 Dsymbol *s;
3743 *pe = NULL;
3744 *pt = NULL;
3745 *ps = NULL;
3747 #if 0
3748 if (!idents.dim)
3750 error(loc, "template instance '%s' has no identifier", toChars());
3751 return;
3753 #endif
3754 //id = (Identifier *)idents.data[0];
3755 //printf("TypeInstance::resolve(sc = %p, idents = '%s')\n", sc, id->toChars());
3756 s = tempinst;
3757 if (s)
3758 s->semantic(sc);
3759 resolveHelper(loc, sc, s, NULL, pe, pt, ps);
3760 //printf("pt = '%s'\n", (*pt)->toChars());
3763 Type *TypeInstance::semantic(Loc loc, Scope *sc)
3765 Type *t;
3766 Expression *e;
3767 Dsymbol *s;
3769 //printf("TypeInstance::semantic(%s)\n", toChars());
3771 if (sc->parameterSpecialization)
3773 unsigned errors = global.errors;
3774 global.gag++;
3776 resolve(loc, sc, &e, &t, &s);
3778 global.gag--;
3779 if (errors != global.errors)
3780 { if (global.gag == 0)
3781 global.errors = errors;
3782 return this;
3785 else
3786 resolve(loc, sc, &e, &t, &s);
3788 if (!t)
3790 #ifdef DEBUG
3791 printf("2: ");
3792 #endif
3793 error(loc, "%s is used as a type", toChars());
3794 t = tvoid;
3796 return t;
3800 /***************************** TypeTypeof *****************************/
3802 TypeTypeof::TypeTypeof(Loc loc, Expression *exp)
3803 : TypeQualified(Ttypeof, loc)
3805 this->exp = exp;
3808 Type *TypeTypeof::syntaxCopy()
3810 TypeTypeof *t;
3812 t = new TypeTypeof(loc, exp->syntaxCopy());
3813 t->syntaxCopyHelper(this);
3814 return t;
3817 Dsymbol *TypeTypeof::toDsymbol(Scope *sc)
3819 Type *t;
3821 t = semantic(0, sc);
3822 if (t == this)
3823 return NULL;
3824 return t->toDsymbol(sc);
3827 void TypeTypeof::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3829 if (mod != this->mod)
3830 { toCBuffer3(buf, hgs, mod);
3831 return;
3833 buf->writestring("typeof(");
3834 exp->toCBuffer(buf, hgs);
3835 buf->writeByte(')');
3836 toCBuffer2Helper(buf, hgs);
3839 Type *TypeTypeof::semantic(Loc loc, Scope *sc)
3840 { Expression *e;
3841 Type *t;
3843 //printf("TypeTypeof::semantic() %p\n", this);
3845 //static int nest; if (++nest == 50) *(char*)0=0;
3847 #if 0
3848 /* Special case for typeof(this) and typeof(super) since both
3849 * should work even if they are not inside a non-static member function
3851 if (exp->op == TOKthis || exp->op == TOKsuper)
3853 // Find enclosing struct or class
3854 for (Dsymbol *s = sc->parent; 1; s = s->parent)
3856 ClassDeclaration *cd;
3857 StructDeclaration *sd;
3859 if (!s)
3861 error(loc, "%s is not in a struct or class scope", exp->toChars());
3862 goto Lerr;
3864 cd = s->isClassDeclaration();
3865 if (cd)
3867 if (exp->op == TOKsuper)
3869 cd = cd->baseClass;
3870 if (!cd)
3871 { error(loc, "class %s has no 'super'", s->toChars());
3872 goto Lerr;
3875 t = cd->type;
3876 break;
3878 sd = s->isStructDeclaration();
3879 if (sd)
3881 if (exp->op == TOKsuper)
3883 error(loc, "struct %s has no 'super'", sd->toChars());
3884 goto Lerr;
3886 t = sd->type->pointerTo();
3887 break;
3891 else
3892 #endif
3894 sc->intypeof++;
3895 exp = exp->semantic(sc);
3896 sc->intypeof--;
3897 t = exp->type;
3898 if (!t)
3900 error(loc, "expression (%s) has no type", exp->toChars());
3901 goto Lerr;
3905 if (idents.dim)
3907 Dsymbol *s = t->toDsymbol(sc);
3908 for (size_t i = 0; i < idents.dim; i++)
3910 if (!s)
3911 break;
3912 Identifier *id = (Identifier *)idents.data[i];
3913 s = s->searchX(loc, sc, id);
3915 if (s)
3917 t = s->getType();
3918 if (!t)
3919 { error(loc, "%s is not a type", s->toChars());
3920 goto Lerr;
3923 else
3924 { error(loc, "cannot resolve .property for %s", toChars());
3925 goto Lerr;
3928 return t;
3930 Lerr:
3931 return tvoid;
3934 d_uns64 TypeTypeof::size(Loc loc)
3936 if (exp->type)
3937 return exp->type->size(loc);
3938 else
3939 return TypeQualified::size(loc);
3944 /***************************** TypeEnum *****************************/
3946 TypeEnum::TypeEnum(EnumDeclaration *sym)
3947 : Type(Tenum, NULL)
3949 this->sym = sym;
3952 char *TypeEnum::toChars()
3954 return sym->toChars();
3957 Type *TypeEnum::semantic(Loc loc, Scope *sc)
3959 sym->semantic(sc);
3960 return merge();
3963 d_uns64 TypeEnum::size(Loc loc)
3965 if (!sym->memtype)
3967 error(loc, "enum %s is forward referenced", sym->toChars());
3968 return 4;
3970 return sym->memtype->size(loc);
3973 unsigned TypeEnum::alignsize()
3975 if (!sym->memtype)
3977 #ifdef DEBUG
3978 printf("1: ");
3979 #endif
3980 error(0, "enum %s is forward referenced", sym->toChars());
3981 return 4;
3983 return sym->memtype->alignsize();
3986 Dsymbol *TypeEnum::toDsymbol(Scope *sc)
3988 return sym;
3991 Type *TypeEnum::toBasetype()
3993 if (!sym->memtype)
3995 #ifdef DEBUG
3996 printf("2: ");
3997 #endif
3998 error(sym->loc, "enum %s is forward referenced", sym->toChars());
3999 return tint32;
4001 return sym->memtype->toBasetype();
4004 void TypeEnum::toDecoBuffer(OutBuffer *buf)
4005 { char *name;
4007 name = sym->mangle();
4008 // if (name[0] == '_' && name[1] == 'D')
4009 // name += 2;
4010 buf->printf("%c%s", mangleChar[ty], name);
4013 void TypeEnum::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4015 if (mod != this->mod)
4016 { toCBuffer3(buf, hgs, mod);
4017 return;
4019 buf->writestring(sym->toChars());
4022 Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident)
4024 EnumMember *m;
4025 Dsymbol *s;
4026 Expression *em;
4028 #if LOGDOTEXP
4029 printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars());
4030 #endif
4031 if (!sym->symtab)
4032 goto Lfwd;
4033 s = sym->symtab->lookup(ident);
4034 if (!s)
4036 return getProperty(e->loc, ident);
4038 m = s->isEnumMember();
4039 em = m->value->copy();
4040 em->loc = e->loc;
4041 return em;
4043 Lfwd:
4044 error(e->loc, "forward reference of %s.%s", toChars(), ident->toChars());
4045 return new IntegerExp(0, 0, this);
4048 Expression *TypeEnum::getProperty(Loc loc, Identifier *ident)
4049 { Expression *e;
4051 if (ident == Id::max)
4053 if (!sym->symtab)
4054 goto Lfwd;
4055 e = new IntegerExp(0, sym->maxval, this);
4057 else if (ident == Id::min)
4059 if (!sym->symtab)
4060 goto Lfwd;
4061 e = new IntegerExp(0, sym->minval, this);
4063 else if (ident == Id::init)
4065 if (!sym->symtab)
4066 goto Lfwd;
4067 e = defaultInit(loc);
4069 else
4071 if (!sym->memtype)
4072 goto Lfwd;
4073 e = sym->memtype->getProperty(loc, ident);
4075 return e;
4077 Lfwd:
4078 error(loc, "forward reference of %s.%s", toChars(), ident->toChars());
4079 return new IntegerExp(0, 0, this);
4082 int TypeEnum::isintegral()
4084 return 1;
4087 int TypeEnum::isfloating()
4089 return 0;
4092 int TypeEnum::isunsigned()
4094 return sym->memtype->isunsigned();
4097 int TypeEnum::isscalar()
4099 return 1;
4100 //return sym->memtype->isscalar();
4103 MATCH TypeEnum::implicitConvTo(Type *to)
4104 { MATCH m;
4106 //printf("TypeEnum::implicitConvTo()\n");
4107 if (this->equals(to))
4108 m = MATCHexact; // exact match
4109 else if (sym->memtype->implicitConvTo(to))
4110 m = MATCHconvert; // match with conversions
4111 else
4112 m = MATCHnomatch; // no match
4113 return m;
4116 Expression *TypeEnum::defaultInit(Loc loc)
4118 #if LOGDEFAULTINIT
4119 printf("TypeEnum::defaultInit() '%s'\n", toChars());
4120 #endif
4121 // Initialize to first member of enum
4122 Expression *e;
4123 e = new IntegerExp(loc, sym->defaultval, this);
4124 return e;
4127 int TypeEnum::isZeroInit()
4129 return (sym->defaultval == 0);
4132 int TypeEnum::hasPointers()
4134 return toBasetype()->hasPointers();
4137 /***************************** TypeTypedef *****************************/
4139 TypeTypedef::TypeTypedef(TypedefDeclaration *sym)
4140 : Type(Ttypedef, NULL)
4142 this->sym = sym;
4145 Type *TypeTypedef::syntaxCopy()
4147 return this;
4150 char *TypeTypedef::toChars()
4152 return sym->toChars();
4155 Type *TypeTypedef::semantic(Loc loc, Scope *sc)
4157 //printf("TypeTypedef::semantic(%s), sem = %d\n", toChars(), sym->sem);
4158 sym->semantic(sc);
4159 return merge();
4162 d_uns64 TypeTypedef::size(Loc loc)
4164 return sym->basetype->size(loc);
4167 unsigned TypeTypedef::alignsize()
4169 return sym->basetype->alignsize();
4172 Dsymbol *TypeTypedef::toDsymbol(Scope *sc)
4174 return sym;
4177 void TypeTypedef::toDecoBuffer(OutBuffer *buf)
4178 { unsigned len;
4179 char *name;
4181 name = sym->mangle();
4182 // if (name[0] == '_' && name[1] == 'D')
4183 // name += 2;
4184 //len = strlen(name);
4185 //buf->printf("%c%d%s", mangleChar[ty], len, name);
4186 buf->printf("%c%s", mangleChar[ty], name);
4189 void TypeTypedef::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4191 //printf("TypeTypedef::toCBuffer2() '%s'\n", sym->toChars());
4192 if (mod != this->mod)
4193 { toCBuffer3(buf, hgs, mod);
4194 return;
4196 buf->writestring(sym->toChars());
4199 Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident)
4201 #if LOGDOTEXP
4202 printf("TypeTypedef::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars());
4203 #endif
4204 if (ident == Id::init)
4206 return Type::dotExp(sc, e, ident);
4208 return sym->basetype->dotExp(sc, e, ident);
4211 Expression *TypeTypedef::getProperty(Loc loc, Identifier *ident)
4213 if (ident == Id::init)
4215 return Type::getProperty(loc, ident);
4217 return sym->basetype->getProperty(loc, ident);
4220 int TypeTypedef::isbit()
4222 return sym->basetype->isbit();
4225 int TypeTypedef::isintegral()
4227 //printf("TypeTypedef::isintegral()\n");
4228 //printf("sym = '%s'\n", sym->toChars());
4229 //printf("basetype = '%s'\n", sym->basetype->toChars());
4230 return sym->basetype->isintegral();
4233 int TypeTypedef::isfloating()
4235 return sym->basetype->isfloating();
4238 int TypeTypedef::isreal()
4240 return sym->basetype->isreal();
4243 int TypeTypedef::isimaginary()
4245 return sym->basetype->isimaginary();
4248 int TypeTypedef::iscomplex()
4250 return sym->basetype->iscomplex();
4253 int TypeTypedef::isunsigned()
4255 return sym->basetype->isunsigned();
4258 int TypeTypedef::isscalar()
4260 return sym->basetype->isscalar();
4263 int TypeTypedef::checkBoolean()
4265 return sym->basetype->checkBoolean();
4268 Type *TypeTypedef::toBasetype()
4270 if (sym->inuse)
4272 sym->error("circular definition");
4273 sym->basetype = Type::terror;
4274 return Type::terror;
4276 sym->inuse = 1;
4277 Type *t = sym->basetype->toBasetype();
4278 sym->inuse = 0;
4279 return t;
4282 MATCH TypeTypedef::implicitConvTo(Type *to)
4283 { MATCH m;
4285 //printf("TypeTypedef::implicitConvTo()\n");
4286 if (this->equals(to))
4287 m = MATCHexact; // exact match
4288 else if (sym->basetype->implicitConvTo(to))
4289 m = MATCHconvert; // match with conversions
4290 else
4291 m = MATCHnomatch; // no match
4292 return m;
4295 Expression *TypeTypedef::defaultInit(Loc loc)
4296 { Expression *e;
4297 Type *bt;
4299 #if LOGDEFAULTINIT
4300 printf("TypeTypedef::defaultInit() '%s'\n", toChars());
4301 #endif
4302 if (sym->init)
4304 //sym->init->toExpression()->print();
4305 return sym->init->toExpression();
4307 bt = sym->basetype;
4308 e = bt->defaultInit(loc);
4309 e->type = this;
4310 while (bt->ty == Tsarray)
4312 e->type = bt->next;
4313 bt = bt->next->toBasetype();
4315 return e;
4318 int TypeTypedef::isZeroInit()
4320 if (sym->init)
4322 if (sym->init->isVoidInitializer())
4323 return 1; // initialize voids to 0
4324 Expression *e = sym->init->toExpression();
4325 if (e && e->isBool(FALSE))
4326 return 1;
4327 return 0; // assume not
4329 if (sym->inuse)
4331 sym->error("circular definition");
4332 sym->basetype = Type::terror;
4334 sym->inuse = 1;
4335 int result = sym->basetype->isZeroInit();
4336 sym->inuse = 0;
4337 return result;
4340 int TypeTypedef::hasPointers()
4342 return toBasetype()->hasPointers();
4345 /***************************** TypeStruct *****************************/
4347 TypeStruct::TypeStruct(StructDeclaration *sym)
4348 : Type(Tstruct, NULL)
4350 this->sym = sym;
4353 char *TypeStruct::toChars()
4355 //printf("sym.parent: %s, deco = %s\n", sym->parent->toChars(), deco);
4356 TemplateInstance *ti = sym->parent->isTemplateInstance();
4357 if (ti && ti->toAlias() == sym)
4358 return ti->toChars();
4359 return sym->toChars();
4362 Type *TypeStruct::syntaxCopy()
4364 return this;
4367 Type *TypeStruct::semantic(Loc loc, Scope *sc)
4369 //printf("TypeStruct::semantic('%s')\n", sym->toChars());
4371 /* Cannot do semantic for sym because scope chain may not
4372 * be right.
4374 //sym->semantic(sc);
4376 return merge();
4379 d_uns64 TypeStruct::size(Loc loc)
4381 return sym->size(loc);
4384 unsigned TypeStruct::alignsize()
4385 { target_size_t sz;
4387 sym->size(0); // give error for forward references
4388 sz = sym->alignsize;
4389 if (sz > sym->structalign)
4390 sz = sym->structalign;
4391 return sz;
4394 Dsymbol *TypeStruct::toDsymbol(Scope *sc)
4396 return sym;
4399 void TypeStruct::toDecoBuffer(OutBuffer *buf)
4400 { unsigned len;
4401 char *name;
4403 name = sym->mangle();
4404 //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", toChars(), name);
4405 // if (name[0] == '_' && name[1] == 'D')
4406 // name += 2;
4407 //len = strlen(name);
4408 //buf->printf("%c%d%s", mangleChar[ty], len, name);
4409 buf->printf("%c%s", mangleChar[ty], name);
4412 void TypeStruct::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4414 if (mod != this->mod)
4415 { toCBuffer3(buf, hgs, mod);
4416 return;
4418 TemplateInstance *ti = sym->parent->isTemplateInstance();
4419 if (ti && ti->toAlias() == sym)
4420 buf->writestring(ti->toChars());
4421 else
4422 buf->writestring(sym->toChars());
4425 Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
4426 { unsigned offset;
4428 Expression *b;
4429 VarDeclaration *v;
4430 Dsymbol *s;
4431 DotVarExp *de;
4432 Declaration *d;
4434 #if LOGDOTEXP
4435 printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
4436 #endif
4437 if (!sym->members)
4439 error(e->loc, "struct %s is forward referenced", sym->toChars());
4440 return new IntegerExp(e->loc, 0, Type::tint32);
4443 if (ident == Id::tupleof)
4445 /* Create a TupleExp
4447 Expressions *exps = new Expressions;
4448 exps->reserve(sym->fields.dim);
4449 for (size_t i = 0; i < sym->fields.dim; i++)
4450 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
4451 Expression *fe = new DotVarExp(e->loc, e, v);
4452 exps->push(fe);
4454 e = new TupleExp(e->loc, exps);
4455 e = e->semantic(sc);
4456 return e;
4459 if (e->op == TOKdotexp)
4460 { DotExp *de = (DotExp *)e;
4462 if (de->e1->op == TOKimport)
4464 ScopeExp *se = (ScopeExp *)de->e1;
4466 s = se->sds->search(e->loc, ident, 0);
4467 e = de->e1;
4468 goto L1;
4472 s = sym->search(e->loc, ident, 0);
4474 if (!s)
4476 //return getProperty(e->loc, ident);
4477 return Type::dotExp(sc, e, ident);
4479 s = s->toAlias();
4481 v = s->isVarDeclaration();
4482 if (v && v->isConst())
4483 { ExpInitializer *ei = v->getExpInitializer();
4485 if (ei)
4486 { e = ei->exp->copy(); // need to copy it if it's a StringExp
4487 e = e->semantic(sc);
4488 return e;
4492 if (s->getType())
4494 //return new DotTypeExp(e->loc, e, s);
4495 return new TypeExp(e->loc, s->getType());
4498 EnumMember *em = s->isEnumMember();
4499 if (em)
4501 assert(em->value);
4502 return em->value->copy();
4505 TemplateMixin *tm = s->isTemplateMixin();
4506 if (tm)
4507 { Expression *de;
4509 de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
4510 de->type = e->type;
4511 return de;
4514 TemplateDeclaration *td = s->isTemplateDeclaration();
4515 if (td)
4517 e = new DotTemplateExp(e->loc, e, td);
4518 e->semantic(sc);
4519 return e;
4522 TemplateInstance *ti = s->isTemplateInstance();
4523 if (ti)
4524 { if (!ti->semanticdone)
4525 ti->semantic(sc);
4526 s = ti->inst->toAlias();
4527 if (!s->isTemplateInstance())
4528 goto L1;
4529 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
4530 de->type = e->type;
4531 return de;
4534 d = s->isDeclaration();
4535 #ifdef DEBUG
4536 if (!d)
4537 printf("d = %s '%s'\n", s->kind(), s->toChars());
4538 #endif
4539 assert(d);
4541 if (e->op == TOKtype)
4542 { FuncDeclaration *fd = sc->func;
4544 if (d->needThis() && fd && fd->vthis)
4546 e = new DotVarExp(e->loc, new ThisExp(e->loc), d);
4547 e = e->semantic(sc);
4548 return e;
4550 if (d->isTupleDeclaration())
4552 e = new TupleExp(e->loc, d->isTupleDeclaration());
4553 e = e->semantic(sc);
4554 return e;
4556 return new VarExp(e->loc, d);
4559 if (d->isDataseg())
4561 // (e, d)
4562 VarExp *ve;
4564 accessCheck(e->loc, sc, e, d);
4565 ve = new VarExp(e->loc, d);
4566 e = new CommaExp(e->loc, e, ve);
4567 e->type = d->type;
4568 return e;
4571 if (v)
4573 if (v->toParent() != sym)
4574 sym->error(e->loc, "'%s' is not a member", v->toChars());
4576 // *(&e + offset)
4577 accessCheck(e->loc, sc, e, d);
4578 b = new AddrExp(e->loc, e);
4579 b->type = e->type->pointerTo();
4580 b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tsize_t));
4581 b->type = v->type->pointerTo();
4582 e = new PtrExp(e->loc, b);
4583 e->type = v->type;
4584 return e;
4587 de = new DotVarExp(e->loc, e, d);
4588 return de->semantic(sc);
4591 unsigned TypeStruct::memalign(unsigned salign)
4593 sym->size(0); // give error for forward references
4594 return sym->structalign;
4597 Expression *TypeStruct::defaultInit(Loc loc)
4598 { Symbol *s;
4599 Declaration *d;
4601 #if LOGDEFAULTINIT
4602 printf("TypeStruct::defaultInit() '%s'\n", toChars());
4603 #endif
4604 s = sym->toInitializer();
4605 d = new SymbolDeclaration(sym->loc, s, sym);
4606 assert(d);
4607 d->type = this;
4608 return new VarExp(sym->loc, d);
4611 int TypeStruct::isZeroInit()
4613 return sym->zeroInit;
4616 int TypeStruct::checkBoolean()
4618 return FALSE;
4621 int TypeStruct::hasPointers()
4623 StructDeclaration *s = sym;
4625 sym->size(0); // give error for forward references
4626 if (s->members)
4628 for (size_t i = 0; i < s->members->dim; i++)
4630 Dsymbol *sm = (Dsymbol *)s->members->data[i];
4631 if (sm->hasPointers())
4632 return TRUE;
4635 return FALSE;
4639 /***************************** TypeClass *****************************/
4641 TypeClass::TypeClass(ClassDeclaration *sym)
4642 : Type(Tclass, NULL)
4644 this->sym = sym;
4647 char *TypeClass::toChars()
4649 return sym->toPrettyChars();
4652 Type *TypeClass::syntaxCopy()
4654 return this;
4657 Type *TypeClass::semantic(Loc loc, Scope *sc)
4659 //printf("TypeClass::semantic(%s)\n", sym->toChars());
4660 if (sym->scope)
4661 sym->semantic(sym->scope);
4662 return merge();
4665 d_uns64 TypeClass::size(Loc loc)
4667 return PTRSIZE;
4670 Dsymbol *TypeClass::toDsymbol(Scope *sc)
4672 return sym;
4675 void TypeClass::toDecoBuffer(OutBuffer *buf)
4676 { unsigned len;
4677 char *name;
4679 name = sym->mangle();
4680 // if (name[0] == '_' && name[1] == 'D')
4681 // name += 2;
4682 //printf("TypeClass::toDecoBuffer('%s') = '%s'\n", toChars(), name);
4683 //len = strlen(name);
4684 //buf->printf("%c%d%s", mangleChar[ty], len, name);
4685 buf->writebyte(NOT_NULL_MANGLE);
4686 buf->printf("%c%s", mangleChar[ty], name);
4689 void TypeClass::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4691 if (mod != this->mod)
4692 { toCBuffer3(buf, hgs, mod);
4693 return;
4695 buf->writestring(sym->toChars());
4698 Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
4699 { unsigned offset;
4701 Expression *b;
4702 VarDeclaration *v;
4703 Dsymbol *s;
4704 DotVarExp *de;
4705 Declaration *d;
4707 #if LOGDOTEXP
4708 printf("TypeClass::dotExp(e='%s', ident='%s')\n", e->toChars(), ident->toChars());
4709 #endif
4711 if (e->op == TOKdotexp)
4712 { DotExp *de = (DotExp *)e;
4714 if (de->e1->op == TOKimport)
4716 ScopeExp *se = (ScopeExp *)de->e1;
4718 s = se->sds->search(e->loc, ident, 0);
4719 e = de->e1;
4720 goto L1;
4724 if (ident == Id::tupleof)
4726 /* Create a TupleExp
4728 Expressions *exps = new Expressions;
4729 exps->reserve(sym->fields.dim);
4730 for (size_t i = 0; i < sym->fields.dim; i++)
4731 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
4732 Expression *fe = new DotVarExp(e->loc, e, v);
4733 exps->push(fe);
4735 e = new TupleExp(e->loc, exps);
4736 e = e->semantic(sc);
4737 return e;
4740 s = sym->search(e->loc, ident, 0);
4742 if (!s)
4744 // See if it's a base class
4745 ClassDeclaration *cbase;
4746 for (cbase = sym->baseClass; cbase; cbase = cbase->baseClass)
4748 if (cbase->ident->equals(ident))
4750 e = new DotTypeExp(0, e, cbase);
4751 return e;
4755 if (ident == Id::classinfo)
4757 Type *t;
4759 assert(ClassDeclaration::classinfo);
4760 t = ClassDeclaration::classinfo->type;
4761 if (e->op == TOKtype || e->op == TOKdottype)
4763 /* For type.classinfo, we know the classinfo
4764 * at compile time.
4766 if (!sym->vclassinfo)
4767 sym->vclassinfo = new ClassInfoDeclaration(sym);
4768 e = new VarExp(e->loc, sym->vclassinfo);
4769 e = e->addressOf(sc);
4770 e->type = t; // do this so we don't get redundant dereference
4772 else
4773 { /* For class objects, the classinfo reference is the first
4774 * entry in the vtbl[]
4776 e = new PtrExp(e->loc, e);
4777 e->type = t->pointerTo();
4778 if (sym->isInterfaceDeclaration())
4780 if (sym->isCOMinterface())
4781 { /* COM interface vtbl[]s are different in that the
4782 * first entry is always pointer to QueryInterface().
4783 * We can't get a .classinfo for it.
4785 error(e->loc, "no .classinfo for COM interface objects");
4787 /* For an interface, the first entry in the vtbl[]
4788 * is actually a pointer to an instance of struct Interface.
4789 * The first member of Interface is the .classinfo,
4790 * so add an extra pointer indirection.
4792 e->type = e->type->pointerTo();
4793 e = new PtrExp(e->loc, e);
4794 e->type = t->pointerTo();
4796 e = new PtrExp(e->loc, e, t);
4798 return e;
4801 if (ident == Id::typeinfo)
4803 if (!global.params.useDeprecated)
4804 error(e->loc, ".typeinfo deprecated, use typeid(type)");
4805 return getTypeInfo(sc);
4807 if (ident == Id::outer && sym->vthis)
4809 s = sym->vthis;
4811 else
4813 //return getProperty(e->loc, ident);
4814 return Type::dotExp(sc, e, ident);
4817 s = s->toAlias();
4818 v = s->isVarDeclaration();
4819 if (v && v->isConst())
4820 { ExpInitializer *ei = v->getExpInitializer();
4822 if (ei)
4823 { e = ei->exp->copy(); // need to copy it if it's a StringExp
4824 e = e->semantic(sc);
4825 return e;
4829 if (s->getType())
4831 // if (e->op == TOKtype)
4832 return new TypeExp(e->loc, s->getType());
4833 // return new DotTypeExp(e->loc, e, s);
4836 EnumMember *em = s->isEnumMember();
4837 if (em)
4839 assert(em->value);
4840 return em->value->copy();
4843 TemplateMixin *tm = s->isTemplateMixin();
4844 if (tm)
4845 { Expression *de;
4847 de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
4848 de->type = e->type;
4849 return de;
4852 TemplateDeclaration *td = s->isTemplateDeclaration();
4853 if (td)
4855 e = new DotTemplateExp(e->loc, e, td);
4856 e->semantic(sc);
4857 return e;
4860 TemplateInstance *ti = s->isTemplateInstance();
4861 if (ti)
4862 { if (!ti->semanticdone)
4863 ti->semantic(sc);
4864 s = ti->inst->toAlias();
4865 if (!s->isTemplateInstance())
4866 goto L1;
4867 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
4868 de->type = e->type;
4869 return de;
4872 d = s->isDeclaration();
4873 if (!d)
4875 e->error("%s.%s is not a declaration", e->toChars(), ident->toChars());
4876 return new IntegerExp(e->loc, 1, Type::tint32);
4879 if (e->op == TOKtype)
4881 VarExp *ve;
4883 if (d->needThis() && (hasThis(sc) || !d->isFuncDeclaration()))
4885 if (sc->func)
4887 ClassDeclaration *thiscd;
4888 thiscd = sc->func->toParent()->isClassDeclaration();
4890 if (thiscd)
4892 ClassDeclaration *cd = e->type->isClassHandle();
4894 if (cd == thiscd)
4896 e = new ThisExp(e->loc);
4897 e = new DotTypeExp(e->loc, e, cd);
4898 de = new DotVarExp(e->loc, e, d);
4899 e = de->semantic(sc);
4900 return e;
4902 else if ((!cd || !cd->isBaseOf(thiscd, NULL)) &&
4903 !d->isFuncDeclaration())
4904 e->error("'this' is required, but %s is not a base class of %s", e->type->toChars(), thiscd->toChars());
4908 de = new DotVarExp(e->loc, new ThisExp(e->loc), d);
4909 e = de->semantic(sc);
4910 return e;
4912 else if (d->isTupleDeclaration())
4914 e = new TupleExp(e->loc, d->isTupleDeclaration());
4915 e = e->semantic(sc);
4916 return e;
4918 else
4919 ve = new VarExp(e->loc, d);
4920 return ve;
4923 if (d->isDataseg())
4925 // (e, d)
4926 VarExp *ve;
4928 accessCheck(e->loc, sc, e, d);
4929 ve = new VarExp(e->loc, d);
4930 e = new CommaExp(e->loc, e, ve);
4931 e->type = d->type;
4932 return e;
4935 if (d->parent && d->toParent()->isModule())
4937 // (e, d)
4938 VarExp *ve;
4940 ve = new VarExp(e->loc, d);
4941 e = new CommaExp(e->loc, e, ve);
4942 e->type = d->type;
4943 return e;
4946 de = new DotVarExp(e->loc, e, d);
4947 return de->semantic(sc);
4950 ClassDeclaration *TypeClass::isClassHandle()
4952 return sym;
4955 int TypeClass::isauto()
4957 return sym->isauto;
4960 int TypeClass::isBaseOf(Type *t, target_ptrdiff_t *poffset)
4962 if (t->ty == Tclass)
4963 { ClassDeclaration *cd;
4965 cd = ((TypeClass *)t)->sym;
4966 if (sym->isBaseOf(cd, poffset))
4967 return 1;
4969 return 0;
4972 MATCH TypeClass::implicitConvTo(Type *to)
4974 //printf("TypeClass::implicitConvTo('%s')\n", to->toChars());
4976 // Can always convert a "Foo" to a "Foo?"
4977 if (to->ty == Tmaybe && to->next)
4978 to = to->next;
4980 if (this == to)
4981 return MATCHexact;
4983 ClassDeclaration *cdto = to->isClassHandle();
4984 if (cdto && cdto->isBaseOf(sym, NULL))
4985 { //printf("is base\n");
4986 return MATCHconvert;
4989 if (global.params.Dversion == 1)
4991 // Allow conversion to (void *)
4992 if (to->ty == Tpointer && to->next->ty == Tvoid)
4993 return MATCHconvert;
4996 return MATCHnomatch;
4999 Expression *TypeClass::defaultInit(Loc loc)
5001 #if LOGDEFAULTINIT
5002 printf("TypeClass::defaultInit() '%s'\n", toChars());
5003 #endif
5004 Expression *e;
5005 e = new NullExp(loc);
5006 e->type = this;
5007 return e;
5010 int TypeClass::isZeroInit()
5012 return 1;
5015 int TypeClass::checkBoolean()
5017 return TRUE;
5020 int TypeClass::hasPointers()
5022 return TRUE;
5025 /***************************** TypeTuple *****************************/
5027 TypeTuple::TypeTuple(Arguments *arguments)
5028 : Type(Ttuple, NULL)
5030 //printf("TypeTuple(this = %p)\n", this);
5031 this->arguments = arguments;
5032 #ifdef DEBUG
5033 if (arguments)
5035 for (size_t i = 0; i < arguments->dim; i++)
5037 Argument *arg = (Argument *)arguments->data[i];
5038 assert(arg && arg->type);
5041 #endif
5044 /****************
5045 * Form TypeTuple from the types of the expressions.
5046 * Assume exps[] is already tuple expanded.
5049 TypeTuple::TypeTuple(Expressions *exps)
5050 : Type(Ttuple, NULL)
5052 Arguments *arguments = new Arguments;
5053 if (exps)
5055 arguments->setDim(exps->dim);
5056 for (size_t i = 0; i < exps->dim; i++)
5057 { Expression *e = (Expression *)exps->data[i];
5058 if (e->type->ty == Ttuple)
5059 e->error("cannot form tuple of tuples");
5060 Argument *arg = new Argument(STCin, e->type, NULL, NULL);
5061 arguments->data[i] = (void *)arg;
5064 this->arguments = arguments;
5067 Type *TypeTuple::syntaxCopy()
5069 Arguments *args = Argument::arraySyntaxCopy(arguments);
5070 Type *t = new TypeTuple(args);
5071 return t;
5074 Type *TypeTuple::semantic(Loc loc, Scope *sc)
5076 //printf("TypeTuple::semantic(this = %p)\n", this);
5077 if (!deco)
5078 deco = merge()->deco;
5080 /* Don't return merge(), because a tuple with one type has the
5081 * same deco as that type.
5083 return this;
5086 int TypeTuple::equals(Object *o)
5087 { Type *t;
5089 t = (Type *)o;
5090 //printf("TypeTuple::equals(%s, %s)\n", toChars(), t->toChars());
5091 if (this == t)
5093 return 1;
5095 if (t->ty == Ttuple)
5096 { TypeTuple *tt = (TypeTuple *)t;
5098 if (arguments->dim == tt->arguments->dim)
5100 for (size_t i = 0; i < tt->arguments->dim; i++)
5101 { Argument *arg1 = (Argument *)arguments->data[i];
5102 Argument *arg2 = (Argument *)tt->arguments->data[i];
5104 if (!arg1->type->equals(arg2->type))
5105 return 0;
5107 return 1;
5110 return 0;
5113 Type *TypeTuple::reliesOnTident()
5115 if (arguments)
5117 for (size_t i = 0; i < arguments->dim; i++)
5119 Argument *arg = (Argument *)arguments->data[i];
5120 Type *t = arg->type->reliesOnTident();
5121 if (t)
5122 return t;
5125 return NULL;
5128 void TypeTuple::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
5130 Argument::argsToCBuffer(buf, hgs, arguments, 0);
5133 void TypeTuple::toDecoBuffer(OutBuffer *buf)
5135 //printf("TypeTuple::toDecoBuffer() this = %p\n", this);
5136 OutBuffer buf2;
5137 Argument::argsToDecoBuffer(&buf2, arguments);
5138 unsigned len = buf2.offset;
5139 #if __NEWLIB_H__
5140 // newlib bug as of 1.14.0
5141 char * p = (char*) buf2.extractData();
5142 buf->printf("%c%d%.*s", mangleChar[ty], len, len, p ? p : "");
5143 #else
5144 buf->printf("%c%d%.*s", mangleChar[ty], len, len, (char *)buf2.extractData());
5145 #endif
5148 Expression *TypeTuple::getProperty(Loc loc, Identifier *ident)
5149 { Expression *e;
5151 #if LOGDOTEXP
5152 printf("TypeTuple::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars());
5153 #endif
5154 if (ident == Id::length)
5156 e = new IntegerExp(loc, arguments->dim, Type::tsize_t);
5158 else
5160 error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars());
5161 e = new IntegerExp(loc, 1, Type::tint32);
5163 return e;
5166 /***************************** TypeSlice *****************************/
5168 /* This is so we can slice a TypeTuple */
5170 TypeSlice::TypeSlice(Type *next, Expression *lwr, Expression *upr)
5171 : Type(Tslice, next)
5173 //printf("TypeSlice[%s .. %s]\n", lwr->toChars(), upr->toChars());
5174 this->lwr = lwr;
5175 this->upr = upr;
5178 Type *TypeSlice::syntaxCopy()
5180 Type *t = new TypeSlice(next->syntaxCopy(), lwr->syntaxCopy(), upr->syntaxCopy());
5181 return t;
5184 Type *TypeSlice::semantic(Loc loc, Scope *sc)
5186 //printf("TypeSlice::semantic() %s\n", toChars());
5187 next = next->semantic(loc, sc);
5188 //printf("next: %s\n", next->toChars());
5190 Type *tbn = next->toBasetype();
5191 if (tbn->ty != Ttuple)
5192 { error(loc, "can only slice tuple types, not %s", tbn->toChars());
5193 return Type::terror;
5195 TypeTuple *tt = (TypeTuple *)tbn;
5197 lwr = semanticLength(sc, tbn, lwr);
5198 lwr = lwr->optimize(WANTvalue);
5199 uinteger_t i1 = lwr->toUInteger();
5201 upr = semanticLength(sc, tbn, upr);
5202 upr = upr->optimize(WANTvalue);
5203 uinteger_t i2 = upr->toUInteger();
5205 if (!(i1 <= i2 && i2 <= tt->arguments->dim))
5206 { error(loc, "slice [%"PRIuMAX"..%"PRIuMAX"] is out of range of [0..%u]", i1, i2, tt->arguments->dim);
5207 return Type::terror;
5210 Arguments *args = new Arguments;
5211 args->reserve(i2 - i1);
5212 for (size_t i = i1; i < i2; i++)
5213 { Argument *arg = (Argument *)tt->arguments->data[i];
5214 args->push(arg);
5217 return new TypeTuple(args);
5220 void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
5222 next->resolve(loc, sc, pe, pt, ps);
5223 if (*pe)
5224 { // It's really a slice expression
5225 Expression *e;
5226 e = new SliceExp(loc, *pe, lwr, upr);
5227 *pe = e;
5229 else if (*ps)
5230 { Dsymbol *s = *ps;
5231 TupleDeclaration *td = s->isTupleDeclaration();
5232 if (td)
5234 /* It's a slice of a TupleDeclaration
5236 ScopeDsymbol *sym = new ArrayScopeSymbol(td);
5237 sym->parent = sc->scopesym;
5238 sc = sc->push(sym);
5240 lwr = lwr->semantic(sc);
5241 lwr = lwr->optimize(WANTvalue);
5242 uinteger_t i1 = lwr->toUInteger();
5244 upr = upr->semantic(sc);
5245 upr = upr->optimize(WANTvalue);
5246 uinteger_t i2 = upr->toUInteger();
5248 sc = sc->pop();
5250 if (!(i1 <= i2 && i2 <= td->objects->dim))
5251 { error(loc, "slice [%"PRIuMAX"u..%"PRIuMAX"u] is out of range of [0..%u]", i1, i2, td->objects->dim);
5252 goto Ldefault;
5255 if (i1 == 0 && i2 == td->objects->dim)
5257 *ps = td;
5258 return;
5261 /* Create a new TupleDeclaration which
5262 * is a slice [i1..i2] out of the old one.
5264 Objects *objects = new Objects;
5265 objects->setDim(i2 - i1);
5266 for (size_t i = 0; i < objects->dim; i++)
5268 objects->data[i] = td->objects->data[(size_t)i1 + i];
5271 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
5272 *ps = tds;
5274 else
5275 goto Ldefault;
5277 else
5279 Ldefault:
5280 Type::resolve(loc, sc, pe, pt, ps);
5284 void TypeSlice::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
5286 if (mod != this->mod)
5287 { toCBuffer3(buf, hgs, mod);
5288 return;
5290 next->toCBuffer2(buf, hgs, this->mod);
5292 buf->printf("[%s .. ", lwr->toChars());
5293 buf->printf("%s]", upr->toChars());
5296 /***************************** Argument *****************************/
5298 Argument::Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg)
5300 this->type = type;
5301 this->ident = ident;
5302 this->storageClass = storageClass;
5303 this->defaultArg = defaultArg;
5306 Argument *Argument::syntaxCopy()
5308 Argument *a = new Argument(storageClass,
5309 type ? type->syntaxCopy() : NULL,
5310 ident,
5311 defaultArg ? defaultArg->syntaxCopy() : NULL);
5312 return a;
5315 Arguments *Argument::arraySyntaxCopy(Arguments *args)
5316 { Arguments *a = NULL;
5318 if (args)
5320 a = new Arguments();
5321 a->setDim(args->dim);
5322 for (size_t i = 0; i < a->dim; i++)
5323 { Argument *arg = (Argument *)args->data[i];
5325 arg = arg->syntaxCopy();
5326 a->data[i] = (void *)arg;
5329 return a;
5332 char *Argument::argsTypesToChars(Arguments *args, int varargs)
5333 { OutBuffer *buf;
5335 buf = new OutBuffer();
5337 buf->writeByte('(');
5338 if (args)
5339 { int i;
5340 OutBuffer argbuf;
5341 HdrGenState hgs;
5343 for (i = 0; i < args->dim; i++)
5344 { Argument *arg;
5346 if (i)
5347 buf->writeByte(',');
5348 arg = (Argument *)args->data[i];
5349 argbuf.reset();
5350 arg->type->toCBuffer2(&argbuf, &hgs, 0);
5351 buf->write(&argbuf);
5353 if (varargs)
5355 if (i && varargs == 1)
5356 buf->writeByte(',');
5357 buf->writestring("...");
5360 buf->writeByte(')');
5362 return buf->toChars();
5365 void Argument::argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs)
5367 buf->writeByte('(');
5368 if (arguments)
5369 { int i;
5370 OutBuffer argbuf;
5372 for (i = 0; i < arguments->dim; i++)
5373 { Argument *arg;
5375 if (i)
5376 buf->writestring(", ");
5377 arg = (Argument *)arguments->data[i];
5378 if (arg->storageClass & STCout)
5379 buf->writestring("out ");
5380 else if (arg->storageClass & STCref)
5381 buf->writestring((global.params.Dversion == 1)
5382 ? (char *)"inout " : (char *)"ref ");
5383 else if (arg->storageClass & STClazy)
5384 buf->writestring("lazy ");
5385 argbuf.reset();
5386 arg->type->toCBuffer(&argbuf, arg->ident, hgs);
5387 if (arg->defaultArg)
5389 argbuf.writestring(" = ");
5390 arg->defaultArg->toCBuffer(&argbuf, hgs);
5392 buf->write(&argbuf);
5394 if (varargs)
5396 if (i && varargs == 1)
5397 buf->writeByte(',');
5398 buf->writestring("...");
5401 buf->writeByte(')');
5405 void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments)
5407 //printf("Argument::argsToDecoBuffer()\n");
5409 // Write argument types
5410 if (arguments)
5412 size_t dim = Argument::dim(arguments);
5413 for (size_t i = 0; i < dim; i++)
5415 Argument *arg = Argument::getNth(arguments, i);
5416 arg->toDecoBuffer(buf);
5421 /****************************************************
5422 * Determine if parameter is a lazy array of delegates.
5423 * If so, return the return type of those delegates.
5424 * If not, return NULL.
5427 Type *Argument::isLazyArray()
5429 // if (inout == Lazy)
5431 Type *tb = type->toBasetype();
5432 if (tb->ty == Tsarray || tb->ty == Tarray)
5434 Type *tel = tb->next->toBasetype();
5435 if (tel->ty == Tdelegate)
5437 TypeDelegate *td = (TypeDelegate *)tel;
5438 TypeFunction *tf = (TypeFunction *)td->next;
5440 if (!tf->varargs && Argument::dim(tf->parameters) == 0)
5442 return tf->next; // return type of delegate
5447 return NULL;
5450 void Argument::toDecoBuffer(OutBuffer *buf)
5452 switch (storageClass & (STCin | STCout | STCref | STClazy))
5453 { case 0:
5454 case STCin:
5455 break;
5456 case STCout:
5457 buf->writeByte('J');
5458 break;
5459 case STCref:
5460 buf->writeByte('K');
5461 break;
5462 case STClazy:
5463 buf->writeByte('L');
5464 break;
5465 default:
5466 #ifdef DEBUG
5467 halt();
5468 #endif
5469 assert(0);
5471 type->toDecoBuffer(buf);
5474 /***************************************
5475 * Determine number of arguments, folding in tuples.
5478 size_t Argument::dim(Arguments *args)
5480 size_t n = 0;
5481 if (args)
5483 for (size_t i = 0; i < args->dim; i++)
5484 { Argument *arg = (Argument *)args->data[i];
5485 Type *t = arg->type->toBasetype();
5487 if (t->ty == Ttuple)
5488 { TypeTuple *tu = (TypeTuple *)t;
5489 n += dim(tu->arguments);
5491 else
5492 n++;
5495 return n;
5498 /***************************************
5499 * Get nth Argument, folding in tuples.
5500 * Returns:
5501 * Argument* nth Argument
5502 * NULL not found, *pn gets incremented by the number
5503 * of Arguments
5506 Argument *Argument::getNth(Arguments *args, size_t nth, size_t *pn)
5508 if (!args)
5509 return NULL;
5511 size_t n = 0;
5512 for (size_t i = 0; i < args->dim; i++)
5513 { Argument *arg = (Argument *)args->data[i];
5514 Type *t = arg->type->toBasetype();
5516 if (t->ty == Ttuple)
5517 { TypeTuple *tu = (TypeTuple *)t;
5518 arg = getNth(tu->arguments, nth - n, &n);
5519 if (arg)
5520 return arg;
5522 else if (n == nth)
5523 return arg;
5524 else
5525 n++;
5528 if (pn)
5529 *pn += n;
5530 return NULL;