Don't allow "a~b" if either could be null
[delight/core.git] / dmd / mtype.c
blob16f3efb9f0716202dd89567257d260f3fb87685a
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 'Q'
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 Type *Type::maybe()
311 if (!mbe)
312 { Type *t;
314 t = new TypeMaybe(this);
315 mbe = t->merge();
317 return mbe;
320 Type *Type::pointerTo()
322 if (!pto)
323 { Type *t;
325 t = new TypePointer(this);
326 pto = t->merge();
328 return pto;
331 Type *Type::referenceTo()
333 if (!rto)
334 { Type *t;
336 t = new TypeReference(this);
337 rto = t->merge();
339 return rto;
342 Type *Type::arrayOf()
344 if (!arrayof)
345 { Type *t;
347 t = new TypeDArray(this);
348 arrayof = t->merge();
350 return arrayof;
353 Dsymbol *Type::toDsymbol(Scope *sc)
355 return NULL;
358 /*******************************
359 * If this is a shell around another type,
360 * get that other type.
363 Type *Type::toBasetype()
365 return this;
368 /********************************
369 * Name mangling.
372 void Type::toDecoBuffer(OutBuffer *buf)
374 buf->writeByte(mangleChar[ty]);
375 if (next)
377 assert(next != this);
378 //printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty);
379 next->toDecoBuffer(buf);
383 /********************************
384 * For pretty-printing a type.
387 char *Type::toChars()
388 { OutBuffer *buf;
389 HdrGenState hgs;
391 buf = new OutBuffer();
392 toCBuffer(buf, NULL, &hgs);
393 return buf->toChars();
396 void Type::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
398 toCBuffer2(buf, hgs, 0);
399 if (ident)
400 { buf->writeByte(' ');
401 buf->writestring(ident->toChars());
405 void Type::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
407 if (mod != this->mod)
408 { toCBuffer3(buf, hgs, mod);
409 return;
411 buf->writestring(toChars());
414 void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod)
416 if (mod != this->mod)
417 { char *p;
419 switch (this->mod)
421 case 0:
422 toCBuffer2(buf, hgs, this->mod);
423 break;
424 case MODconst:
425 p = "const(";
426 goto L1;
427 case MODinvariant:
428 p = "invariant(";
429 L1: buf->writestring(p);
430 toCBuffer2(buf, hgs, this->mod);
431 buf->writeByte(')');
432 break;
433 default:
434 assert(0);
440 /************************************
443 Type *Type::merge()
444 { Type *t;
446 //printf("merge(%s)\n", toChars());
447 t = this;
448 assert(t);
449 if (!deco)
451 OutBuffer buf;
452 StringValue *sv;
454 if (next)
455 next = next->merge();
456 toDecoBuffer(&buf);
457 sv = stringtable.update((char *)buf.data, buf.offset);
458 if (sv->ptrvalue)
459 { t = (Type *) sv->ptrvalue;
460 assert(t->deco);
461 //printf("old value, deco = '%s' %p\n", t->deco, t->deco);
463 else
465 sv->ptrvalue = this;
466 deco = sv->lstring.string;
467 //printf("new value, deco = '%s' %p\n", t->deco, t->deco);
470 return t;
473 int Type::isbit()
475 return FALSE;
478 int Type::isintegral()
480 return FALSE;
483 int Type::isfloating()
485 return FALSE;
488 int Type::isreal()
490 return FALSE;
493 int Type::isimaginary()
495 return FALSE;
498 int Type::iscomplex()
500 return FALSE;
503 int Type::isscalar()
505 return FALSE;
508 int Type::isunsigned()
510 return FALSE;
513 ClassDeclaration *Type::isClassHandle()
515 return NULL;
518 int Type::isauto()
520 return FALSE;
523 int Type::isString()
525 return FALSE;
528 int Type::checkBoolean()
530 return isscalar();
533 /*********************************
534 * Check type to see if it is based on a deprecated symbol.
537 void Type::checkDeprecated(Loc loc, Scope *sc)
539 Type *t;
540 Dsymbol *s;
542 for (t = this; t; t = t->next)
544 s = t->toDsymbol(sc);
545 if (s)
546 s->checkDeprecated(loc, sc);
551 Expression *Type::defaultInit(Loc loc)
553 #if LOGDEFAULTINIT
554 printf("Type::defaultInit() '%s'\n", toChars());
555 #endif
556 return NULL;
559 int Type::isZeroInit()
561 return 0; // assume not
564 int Type::isBaseOf(Type *t, target_ptrdiff_t *poffset)
566 return 0; // assume not
569 /********************************
570 * Determine if 'this' can be implicitly converted
571 * to type 'to'.
572 * Returns:
573 * 0 can't convert
574 * 1 can convert using implicit conversions
575 * 2 this and to are the same type
578 MATCH Type::implicitConvTo(Type *to)
580 //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to);
581 //printf("\tthis->next=%p, to->next=%p\n", this->next, to->next);
582 if (this == to)
583 return MATCHexact;
584 // if (to->ty == Tvoid)
585 // return 1;
586 return MATCHnomatch;
589 Expression *Type::getProperty(Loc loc, Identifier *ident)
590 { Expression *e;
592 #if LOGDOTEXP
593 printf("Type::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars());
594 #endif
595 if (ident == Id::__sizeof)
597 e = new IntegerExp(loc, size(loc), Type::tsize_t);
599 else if (ident == Id::size)
601 error(loc, ".size property should be replaced with .sizeof");
602 e = new IntegerExp(loc, size(loc), Type::tsize_t);
604 else if (ident == Id::alignof)
606 e = new IntegerExp(loc, alignsize(), Type::tsize_t);
608 else if (ident == Id::typeinfo)
610 if (!global.params.useDeprecated)
611 error(loc, ".typeinfo deprecated, use typeid(type)");
612 e = getTypeInfo(NULL);
614 else if (ident == Id::init)
616 if (ty == Tvoid)
617 error(loc, "void does not have an initializer");
618 e = defaultInit(loc);
620 else if (ident == Id::mangleof)
622 assert(deco);
623 e = new StringExp(loc, deco, strlen(deco), 'c');
624 Scope sc;
625 e = e->semantic(&sc);
627 else if (ident == Id::stringof)
628 { char *s = toChars();
629 e = new StringExp(loc, s, strlen(s), 'c');
630 Scope sc;
631 e = e->semantic(&sc);
633 else
635 error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars());
636 e = new IntegerExp(loc, 1, Type::tint32);
638 return e;
641 Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident)
642 { VarDeclaration *v = NULL;
644 #if LOGDOTEXP
645 printf("Type::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
646 #endif
647 if (e->op == TOKdotvar)
649 DotVarExp *dv = (DotVarExp *)e;
650 v = dv->var->isVarDeclaration();
652 else if (e->op == TOKvar)
654 VarExp *ve = (VarExp *)e;
655 v = ve->var->isVarDeclaration();
657 if (v)
659 if (ident == Id::offset)
661 if (!global.params.useDeprecated)
662 error(e->loc, ".offset deprecated, use .offsetof");
663 goto Loffset;
665 else if (ident == Id::offsetof)
667 Loffset:
668 if (v->storage_class & STCfield)
670 e = new IntegerExp(e->loc, v->offset, Type::tsize_t);
671 return e;
674 else if (ident == Id::init)
676 #if 0
677 if (v->init)
679 if (v->init->isVoidInitializer())
680 error(e->loc, "%s.init is void", v->toChars());
681 else
682 { Loc loc = e->loc;
683 e = v->init->toExpression();
684 if (e->op == TOKassign || e->op == TOKconstruct)
686 e = ((AssignExp *)e)->e2;
688 /* Take care of case where we used a 0
689 * to initialize the struct.
691 if (e->type == Type::tint32 &&
692 e->isBool(0) &&
693 v->type->toBasetype()->ty == Tstruct)
695 e = v->type->defaultInit(loc);
698 e = e->optimize(WANTvalue | WANTinterpret);
699 // if (!e->isConst())
700 // error(loc, ".init cannot be evaluated at compile time");
702 return e;
704 #endif
705 Expression *ex = defaultInit(e->loc);
706 return ex;
709 if (ident == Id::typeinfo)
711 if (!global.params.useDeprecated)
712 error(e->loc, ".typeinfo deprecated, use typeid(type)");
713 e = getTypeInfo(sc);
714 return e;
716 if (ident == Id::stringof)
717 { char *s = e->toChars();
718 e = new StringExp(e->loc, s, strlen(s), 'c');
719 Scope sc;
720 e = e->semantic(&sc);
721 return e;
723 return getProperty(e->loc, ident);
726 unsigned Type::memalign(unsigned salign)
728 return salign;
731 void Type::error(Loc loc, const char *format, ...)
733 va_list ap;
734 va_start(ap, format);
735 ::verror(loc, format, ap);
736 va_end( ap );
739 Identifier *Type::getTypeInfoIdent(int internal)
741 // _init_10TypeInfo_%s
742 OutBuffer buf;
743 Identifier *id;
744 char *name;
745 int len;
747 //toTypeInfoBuffer(&buf);
748 if (internal)
749 { buf.writeByte(mangleChar[ty]);
750 if (ty == Tarray)
751 buf.writeByte(mangleChar[next->ty]);
753 else
754 toDecoBuffer(&buf);
755 len = buf.offset;
756 name = (char *)alloca(19 + sizeof(len) * 3 + len + 1);
757 buf.writeByte(0);
758 sprintf(name, "_D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
759 if (global.params.isWindows)
760 name++; // C mangling will add it back in
761 //printf("name = %s\n", name);
762 id = Lexer::idPool(name);
763 return id;
766 TypeBasic *Type::isTypeBasic()
768 return NULL;
772 void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
774 Type *t;
776 t = semantic(loc, sc);
777 *pt = t;
778 *pe = NULL;
779 *ps = NULL;
782 /*******************************
783 * If one of the subtypes of this type is a TypeIdentifier,
784 * i.e. it's an unresolved type, return that type.
787 Type *Type::reliesOnTident()
789 if (!next)
790 return NULL;
791 else
792 return next->reliesOnTident();
795 /********************************
796 * We've mistakenly parsed this as a type.
797 * Redo it as an Expression.
798 * NULL if cannot.
801 Expression *Type::toExpression()
803 return NULL;
806 /***************************************
807 * Return !=0 if type has pointers that need to
808 * be scanned by the GC during a collection cycle.
811 int Type::hasPointers()
813 return FALSE;
816 /* ============================= TypeBasic =========================== */
818 TypeBasic::TypeBasic(TY ty)
819 : Type(ty, NULL)
820 { char *c;
821 char *d;
822 unsigned flags;
824 #define TFLAGSintegral 1
825 #define TFLAGSfloating 2
826 #define TFLAGSunsigned 4
827 #define TFLAGSreal 8
828 #define TFLAGSimaginary 0x10
829 #define TFLAGScomplex 0x20
831 flags = 0;
832 switch (ty)
834 case Tvoid: d = Token::toChars(TOKvoid);
835 c = "void";
836 break;
838 case Tint8: d = Token::toChars(TOKint8);
839 c = "byte";
840 flags |= TFLAGSintegral;
841 break;
843 case Tuns8: d = Token::toChars(TOKuns8);
844 c = "ubyte";
845 flags |= TFLAGSintegral | TFLAGSunsigned;
846 break;
848 case Tint16: d = Token::toChars(TOKint16);
849 c = "short";
850 flags |= TFLAGSintegral;
851 break;
853 case Tuns16: d = Token::toChars(TOKuns16);
854 c = "ushort";
855 flags |= TFLAGSintegral | TFLAGSunsigned;
856 break;
858 case Tint32: d = Token::toChars(TOKint32);
859 c = "int";
860 flags |= TFLAGSintegral;
861 break;
863 case Tuns32: d = Token::toChars(TOKuns32);
864 c = "uint";
865 flags |= TFLAGSintegral | TFLAGSunsigned;
866 break;
868 case Tfloat32: d = Token::toChars(TOKfloat32);
869 c = "float";
870 flags |= TFLAGSfloating | TFLAGSreal;
871 break;
873 case Tint64: d = Token::toChars(TOKint64);
874 c = "long";
875 flags |= TFLAGSintegral;
876 break;
878 case Tuns64: d = Token::toChars(TOKuns64);
879 c = "ulong";
880 flags |= TFLAGSintegral | TFLAGSunsigned;
881 break;
883 case Tfloat64: d = Token::toChars(TOKfloat64);
884 c = "double";
885 flags |= TFLAGSfloating | TFLAGSreal;
886 break;
888 case Tfloat80: d = Token::toChars(TOKfloat80);
889 c = "real";
890 flags |= TFLAGSfloating | TFLAGSreal;
891 break;
893 case Timaginary32: d = Token::toChars(TOKimaginary32);
894 c = "ifloat";
895 flags |= TFLAGSfloating | TFLAGSimaginary;
896 break;
898 case Timaginary64: d = Token::toChars(TOKimaginary64);
899 c = "idouble";
900 flags |= TFLAGSfloating | TFLAGSimaginary;
901 break;
903 case Timaginary80: d = Token::toChars(TOKimaginary80);
904 c = "ireal";
905 flags |= TFLAGSfloating | TFLAGSimaginary;
906 break;
908 case Tcomplex32: d = Token::toChars(TOKcomplex32);
909 c = "cfloat";
910 flags |= TFLAGSfloating | TFLAGScomplex;
911 break;
913 case Tcomplex64: d = Token::toChars(TOKcomplex64);
914 c = "cdouble";
915 flags |= TFLAGSfloating | TFLAGScomplex;
916 break;
918 case Tcomplex80: d = Token::toChars(TOKcomplex80);
919 c = "creal";
920 flags |= TFLAGSfloating | TFLAGScomplex;
921 break;
924 case Tbit: d = Token::toChars(TOKbit);
925 c = "bit";
926 flags |= TFLAGSintegral | TFLAGSunsigned;
927 break;
929 case Tbool: d = "bool";
930 c = d;
931 flags |= TFLAGSintegral | TFLAGSunsigned;
932 break;
934 case Tascii: d = Token::toChars(TOKchar);
935 c = "char";
936 flags |= TFLAGSintegral | TFLAGSunsigned;
937 break;
939 case Twchar: d = Token::toChars(TOKwchar);
940 c = "wchar";
941 flags |= TFLAGSintegral | TFLAGSunsigned;
942 break;
944 case Tdchar: d = Token::toChars(TOKdchar);
945 c = "dchar";
946 flags |= TFLAGSintegral | TFLAGSunsigned;
947 break;
949 default: assert(0);
951 this->dstring = d;
952 this->cstring = c;
953 this->flags = flags;
954 merge();
957 Type *TypeBasic::syntaxCopy()
959 // No semantic analysis done on basic types, no need to copy
960 return this;
964 char *TypeBasic::toChars()
966 return dstring;
969 void TypeBasic::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
971 //printf("TypeBasic::toCBuffer2(mod = %d, this->mod = %d)\n", mod, this->mod);
972 if (mod != this->mod)
973 { toCBuffer3(buf, hgs, mod);
974 return;
976 buf->writestring(dstring);
979 d_uns64 TypeBasic::size(Loc loc)
980 { unsigned size;
982 //printf("TypeBasic::size()\n");
983 switch (ty)
985 case Tint8:
986 case Tuns8: size = 1; break;
987 case Tint16:
988 case Tuns16: size = 2; break;
989 case Tint32:
990 case Tuns32:
991 case Tfloat32:
992 case Timaginary32:
993 size = 4; break;
994 case Tint64:
995 case Tuns64:
996 case Tfloat64:
997 case Timaginary64:
998 size = 8; break;
999 case Tfloat80:
1000 case Timaginary80:
1001 size = REALSIZE; break;
1002 case Tcomplex32:
1003 size = 8; break;
1004 case Tcomplex64:
1005 size = 16; break;
1006 case Tcomplex80:
1007 size = REALSIZE * 2; break;
1009 case Tvoid:
1010 //size = Type::size(); // error message
1011 size = 1;
1012 break;
1014 case Tbit: size = 1; break;
1015 case Tbool: size = 1; break;
1016 case Tascii: size = 1; break;
1017 case Twchar: size = 2; break;
1018 case Tdchar: size = 4; break;
1020 default:
1021 assert(0);
1022 break;
1024 //printf("TypeBasic::size() = %d\n", size);
1025 return size;
1028 unsigned TypeBasic::alignsize()
1029 { unsigned sz;
1031 switch (ty)
1033 case Tfloat80:
1034 case Timaginary80:
1035 case Tcomplex80:
1036 sz = 2;
1037 break;
1039 default:
1040 sz = size(0);
1041 break;
1043 return sz;
1047 Expression *TypeBasic::getProperty(Loc loc, Identifier *ident)
1049 Expression *e;
1050 d_int64 ivalue;
1051 #ifdef IN_GCC
1052 real_t fvalue;
1053 #else
1054 d_float80 fvalue;
1055 #endif
1057 //printf("TypeBasic::getProperty('%s')\n", ident->toChars());
1058 if (ident == Id::max)
1060 switch (ty)
1062 case Tint8: ivalue = 0x7F; goto Livalue;
1063 case Tuns8: ivalue = 0xFF; goto Livalue;
1064 case Tint16: ivalue = 0x7FFFUL; goto Livalue;
1065 case Tuns16: ivalue = 0xFFFFUL; goto Livalue;
1066 case Tint32: ivalue = 0x7FFFFFFFUL; goto Livalue;
1067 case Tuns32: ivalue = 0xFFFFFFFFUL; goto Livalue;
1068 case Tint64: ivalue = 0x7FFFFFFFFFFFFFFFLL; goto Livalue;
1069 case Tuns64: ivalue = 0xFFFFFFFFFFFFFFFFULL; goto Livalue;
1070 case Tbit: ivalue = 1; goto Livalue;
1071 case Tbool: ivalue = 1; goto Livalue;
1072 case Tchar: ivalue = 0xFF; goto Livalue;
1073 case Twchar: ivalue = 0xFFFFUL; goto Livalue;
1074 case Tdchar: ivalue = 0x10FFFFUL; goto Livalue;
1076 case Tcomplex32:
1077 case Timaginary32:
1078 #ifdef IN_GCC
1079 // %% lazy, fix
1080 #define FLT_MAX real_t_properties[real_t::Float].maxval;
1081 #define DBL_MAX real_t_properties[real_t::Double].maxval;
1082 #define LDBL_MAX real_t_properties[real_t::LongDouble].maxval;
1083 #define FLT_MIN real_t_properties[real_t::Float].minval;
1084 #define DBL_MIN real_t_properties[real_t::Double].minval;
1085 #define LDBL_MIN real_t_properties[real_t::LongDouble].minval;
1086 #define FLT_DIG real_t_properties[real_t::Float].dig;
1087 #define DBL_DIG real_t_properties[real_t::Double].dig;
1088 #define LDBL_DIG real_t_properties[real_t::LongDouble].dig;
1089 #define FLT_MANT_DIG real_t_properties[real_t::Float].mant_dig;
1090 #define DBL_MANT_DIG real_t_properties[real_t::Double].mant_dig;
1091 #define LDBL_MANT_DIG real_t_properties[real_t::LongDouble].mant_dig;
1092 #define FLT_MAX_10_EXP real_t_properties[real_t::Float].max_10_exp;
1093 #define DBL_MAX_10_EXP real_t_properties[real_t::Double].max_10_exp;
1094 #define LDBL_MAX_10_EXP real_t_properties[real_t::LongDouble].max_10_exp;
1095 #define FLT_MIN_10_EXP real_t_properties[real_t::Float].min_10_exp;
1096 #define DBL_MIN_10_EXP real_t_properties[real_t::Double].min_10_exp;
1097 #define LDBL_MIN_10_EXP real_t_properties[real_t::LongDouble].min_10_exp;
1098 #define FLT_MAX_EXP real_t_properties[real_t::Float].max_exp;
1099 #define DBL_MAX_EXP real_t_properties[real_t::Double].max_exp;
1100 #define LDBL_MAX_EXP real_t_properties[real_t::LongDouble].max_exp;
1101 #define FLT_MIN_EXP real_t_properties[real_t::Float].min_exp;
1102 #define DBL_MIN_EXP real_t_properties[real_t::Double].min_exp;
1103 #define LDBL_MIN_EXP real_t_properties[real_t::LongDouble].min_exp;
1104 #define FLT_EPSILON real_t_properties[real_t::Float].epsilonval;
1105 #define DBL_EPSILON real_t_properties[real_t::Double].epsilonval;
1106 #define LDBL_EPSILON real_t_properties[real_t::LongDouble].epsilonval;
1109 #endif
1110 case Tfloat32: fvalue = FLT_MAX; goto Lfvalue;
1111 case Tcomplex64:
1112 case Timaginary64:
1113 case Tfloat64: fvalue = DBL_MAX; goto Lfvalue;
1114 case Tcomplex80:
1115 case Timaginary80:
1116 case Tfloat80: fvalue = LDBL_MAX; goto Lfvalue;
1119 else if (ident == Id::min)
1121 switch (ty)
1123 case Tint8: ivalue = -128; goto Livalue;
1124 case Tuns8: ivalue = 0; goto Livalue;
1125 case Tint16: ivalue = -32768; goto Livalue;
1126 case Tuns16: ivalue = 0; goto Livalue;
1127 case Tint32: ivalue = -2147483647L - 1; goto Livalue;
1128 case Tuns32: ivalue = 0; goto Livalue;
1129 case Tint64: ivalue = (-9223372036854775807LL-1LL); goto Livalue;
1130 case Tuns64: ivalue = 0; goto Livalue;
1131 case Tbit: ivalue = 0; goto Livalue;
1132 case Tbool: ivalue = 0; goto Livalue;
1133 case Tchar: ivalue = 0; goto Livalue;
1134 case Twchar: ivalue = 0; goto Livalue;
1135 case Tdchar: ivalue = 0; goto Livalue;
1137 case Tcomplex32:
1138 case Timaginary32:
1139 case Tfloat32: fvalue = FLT_MIN; goto Lfvalue;
1140 case Tcomplex64:
1141 case Timaginary64:
1142 case Tfloat64: fvalue = DBL_MIN; goto Lfvalue;
1143 case Tcomplex80:
1144 case Timaginary80:
1145 case Tfloat80: fvalue = LDBL_MIN; goto Lfvalue;
1148 else if (ident == Id::nan)
1150 switch (ty)
1152 case Tcomplex32:
1153 case Tcomplex64:
1154 case Tcomplex80:
1155 case Timaginary32:
1156 case Timaginary64:
1157 case Timaginary80:
1158 case Tfloat32:
1159 case Tfloat64:
1160 case Tfloat80:
1162 #if IN_GCC
1163 // mode doesn't matter, will be converted in RealExp anyway
1164 fvalue = real_t::getnan(real_t::LongDouble);
1165 #elif __GNUC__
1166 // gcc nan's have the sign bit set by default, so turn it off
1167 // Need the volatile to prevent gcc from doing incorrect
1168 // constant folding.
1169 volatile d_float80 foo;
1170 foo = NAN;
1171 if (signbit(foo)) // signbit sometimes, not always, set
1172 foo = -foo; // turn off sign bit
1173 fvalue = foo;
1174 #elif _MSC_VER
1175 unsigned long nan[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
1176 fvalue = *(double*)nan;
1177 #else
1178 fvalue = NAN;
1179 #endif
1180 goto Lfvalue;
1184 else if (ident == Id::infinity)
1186 switch (ty)
1188 case Tcomplex32:
1189 case Tcomplex64:
1190 case Tcomplex80:
1191 case Timaginary32:
1192 case Timaginary64:
1193 case Timaginary80:
1194 case Tfloat32:
1195 case Tfloat64:
1196 case Tfloat80:
1197 #if IN_GCC
1198 fvalue = real_t::getinfinity();
1199 #elif __GNUC__
1200 fvalue = 1 / zero;
1201 #elif _MSC_VER
1202 fvalue = std::numeric_limits<long double>::infinity();
1203 #else
1204 fvalue = INFINITY;
1205 #endif
1206 goto Lfvalue;
1209 else if (ident == Id::dig)
1211 switch (ty)
1213 case Tcomplex32:
1214 case Timaginary32:
1215 case Tfloat32: ivalue = FLT_DIG; goto Lint;
1216 case Tcomplex64:
1217 case Timaginary64:
1218 case Tfloat64: ivalue = DBL_DIG; goto Lint;
1219 case Tcomplex80:
1220 case Timaginary80:
1221 case Tfloat80: ivalue = LDBL_DIG; goto Lint;
1224 else if (ident == Id::epsilon)
1226 switch (ty)
1228 case Tcomplex32:
1229 case Timaginary32:
1230 case Tfloat32: fvalue = FLT_EPSILON; goto Lfvalue;
1231 case Tcomplex64:
1232 case Timaginary64:
1233 case Tfloat64: fvalue = DBL_EPSILON; goto Lfvalue;
1234 case Tcomplex80:
1235 case Timaginary80:
1236 case Tfloat80: fvalue = LDBL_EPSILON; goto Lfvalue;
1239 else if (ident == Id::mant_dig)
1241 switch (ty)
1243 case Tcomplex32:
1244 case Timaginary32:
1245 case Tfloat32: ivalue = FLT_MANT_DIG; goto Lint;
1246 case Tcomplex64:
1247 case Timaginary64:
1248 case Tfloat64: ivalue = DBL_MANT_DIG; goto Lint;
1249 case Tcomplex80:
1250 case Timaginary80:
1251 case Tfloat80: ivalue = LDBL_MANT_DIG; goto Lint;
1254 else if (ident == Id::max_10_exp)
1256 switch (ty)
1258 case Tcomplex32:
1259 case Timaginary32:
1260 case Tfloat32: ivalue = FLT_MAX_10_EXP; goto Lint;
1261 case Tcomplex64:
1262 case Timaginary64:
1263 case Tfloat64: ivalue = DBL_MAX_10_EXP; goto Lint;
1264 case Tcomplex80:
1265 case Timaginary80:
1266 case Tfloat80: ivalue = LDBL_MAX_10_EXP; goto Lint;
1269 else if (ident == Id::max_exp)
1271 switch (ty)
1273 case Tcomplex32:
1274 case Timaginary32:
1275 case Tfloat32: ivalue = FLT_MAX_EXP; goto Lint;
1276 case Tcomplex64:
1277 case Timaginary64:
1278 case Tfloat64: ivalue = DBL_MAX_EXP; goto Lint;
1279 case Tcomplex80:
1280 case Timaginary80:
1281 case Tfloat80: ivalue = LDBL_MAX_EXP; goto Lint;
1284 else if (ident == Id::min_10_exp)
1286 switch (ty)
1288 case Tcomplex32:
1289 case Timaginary32:
1290 case Tfloat32: ivalue = FLT_MIN_10_EXP; goto Lint;
1291 case Tcomplex64:
1292 case Timaginary64:
1293 case Tfloat64: ivalue = DBL_MIN_10_EXP; goto Lint;
1294 case Tcomplex80:
1295 case Timaginary80:
1296 case Tfloat80: ivalue = LDBL_MIN_10_EXP; goto Lint;
1299 else if (ident == Id::min_exp)
1301 switch (ty)
1303 case Tcomplex32:
1304 case Timaginary32:
1305 case Tfloat32: ivalue = FLT_MIN_EXP; goto Lint;
1306 case Tcomplex64:
1307 case Timaginary64:
1308 case Tfloat64: ivalue = DBL_MIN_EXP; goto Lint;
1309 case Tcomplex80:
1310 case Timaginary80:
1311 case Tfloat80: ivalue = LDBL_MIN_EXP; goto Lint;
1315 Ldefault:
1316 return Type::getProperty(loc, ident);
1318 Livalue:
1319 e = new IntegerExp(loc, ivalue, this);
1320 return e;
1322 Lfvalue:
1323 if (isreal() || isimaginary())
1324 e = new RealExp(loc, fvalue, this);
1325 else
1327 complex_t cvalue;
1329 #if __DMC__
1330 //((real_t *)&cvalue)[0] = fvalue;
1331 //((real_t *)&cvalue)[1] = fvalue;
1332 cvalue = fvalue + fvalue * I;
1333 #else
1334 cvalue.re = fvalue;
1335 cvalue.im = fvalue;
1336 #endif
1337 //for (int i = 0; i < 20; i++)
1338 // printf("%02x ", ((unsigned char *)&cvalue)[i]);
1339 //printf("\n");
1340 e = new ComplexExp(loc, cvalue, this);
1342 return e;
1344 Lint:
1345 e = new IntegerExp(loc, ivalue, Type::tint32);
1346 return e;
1349 Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
1351 #if LOGDOTEXP
1352 printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1353 #endif
1354 Type *t;
1356 if (ident == Id::re)
1358 switch (ty)
1360 case Tcomplex32: t = tfloat32; goto L1;
1361 case Tcomplex64: t = tfloat64; goto L1;
1362 case Tcomplex80: t = tfloat80; goto L1;
1364 e = e->castTo(sc, t);
1365 break;
1367 case Tfloat32:
1368 case Tfloat64:
1369 case Tfloat80:
1370 break;
1372 case Timaginary32: t = tfloat32; goto L2;
1373 case Timaginary64: t = tfloat64; goto L2;
1374 case Timaginary80: t = tfloat80; goto L2;
1376 e = new RealExp(0, 0, t);
1377 break;
1379 default:
1380 return Type::getProperty(e->loc, ident);
1383 else if (ident == Id::im)
1384 { Type *t2;
1386 switch (ty)
1388 case Tcomplex32: t = timaginary32; t2 = tfloat32; goto L3;
1389 case Tcomplex64: t = timaginary64; t2 = tfloat64; goto L3;
1390 case Tcomplex80: t = timaginary80; t2 = tfloat80; goto L3;
1392 e = e->castTo(sc, t);
1393 e->type = t2;
1394 break;
1396 case Timaginary32: t = tfloat32; goto L4;
1397 case Timaginary64: t = tfloat64; goto L4;
1398 case Timaginary80: t = tfloat80; goto L4;
1400 e->type = t;
1401 break;
1403 case Tfloat32:
1404 case Tfloat64:
1405 case Tfloat80:
1406 e = new RealExp(0, 0, this);
1407 break;
1409 default:
1410 return Type::getProperty(e->loc, ident);
1413 else
1415 return Type::dotExp(sc, e, ident);
1417 return e;
1420 Expression *TypeBasic::defaultInit(Loc loc)
1421 { integer_t value = 0;
1423 #if LOGDEFAULTINIT
1424 printf("TypeBasic::defaultInit() '%s'\n", toChars());
1425 #endif
1426 switch (ty)
1428 case Tchar:
1429 value = 0xFF;
1430 break;
1432 case Twchar:
1433 case Tdchar:
1434 value = 0xFFFF;
1435 break;
1437 case Timaginary32:
1438 case Timaginary64:
1439 case Timaginary80:
1440 case Tfloat32:
1441 case Tfloat64:
1442 case Tfloat80:
1443 case Tcomplex32:
1444 case Tcomplex64:
1445 case Tcomplex80:
1446 return getProperty(loc, Id::nan);
1448 return new IntegerExp(loc, value, this);
1451 int TypeBasic::isZeroInit()
1453 switch (ty)
1455 case Tchar:
1456 case Twchar:
1457 case Tdchar:
1458 case Timaginary32:
1459 case Timaginary64:
1460 case Timaginary80:
1461 case Tfloat32:
1462 case Tfloat64:
1463 case Tfloat80:
1464 case Tcomplex32:
1465 case Tcomplex64:
1466 case Tcomplex80:
1467 return 0; // no
1469 return 1; // yes
1472 int TypeBasic::isbit()
1474 return (ty == Tbit);
1477 int TypeBasic::isintegral()
1479 //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags);
1480 return flags & TFLAGSintegral;
1483 int TypeBasic::isfloating()
1485 return flags & TFLAGSfloating;
1488 int TypeBasic::isreal()
1490 return flags & TFLAGSreal;
1493 int TypeBasic::isimaginary()
1495 return flags & TFLAGSimaginary;
1498 int TypeBasic::iscomplex()
1500 return flags & TFLAGScomplex;
1503 int TypeBasic::isunsigned()
1505 return flags & TFLAGSunsigned;
1508 int TypeBasic::isscalar()
1510 return flags & (TFLAGSintegral | TFLAGSfloating);
1513 MATCH TypeBasic::implicitConvTo(Type *to)
1515 //printf("TypeBasic::implicitConvTo(%s) from %s\n", to->toChars(), toChars());
1516 if (this == to)
1517 return MATCHexact;
1519 if (ty == Tvoid || to->ty == Tvoid)
1520 return MATCHnomatch;
1521 if (1 || global.params.Dversion == 1)
1523 if (to->ty == Tbool)
1524 return MATCHnomatch;
1526 else
1528 if (ty == Tbool || to->ty == Tbool)
1529 return MATCHnomatch;
1531 if (!to->isTypeBasic())
1532 return MATCHnomatch;
1534 TypeBasic *tob = (TypeBasic *)to;
1535 if (flags & TFLAGSintegral)
1537 // Disallow implicit conversion of integers to imaginary or complex
1538 if (tob->flags & (TFLAGSimaginary | TFLAGScomplex))
1539 return MATCHnomatch;
1541 // If converting to integral
1542 if (0 && global.params.Dversion > 1 && tob->flags & TFLAGSintegral)
1543 { d_uns64 sz = size(0);
1544 d_uns64 tosz = tob->size(0);
1546 /* Can't convert to smaller size or, if same size, change sign
1548 if (sz > tosz)
1549 return MATCHnomatch;
1551 /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned)
1552 return MATCHnomatch;*/
1555 else if (flags & TFLAGSfloating)
1557 // Disallow implicit conversion of floating point to integer
1558 if (tob->flags & TFLAGSintegral)
1559 return MATCHnomatch;
1561 assert(tob->flags & TFLAGSfloating);
1563 // Disallow implicit conversion from complex to non-complex
1564 if (flags & TFLAGScomplex && !(tob->flags & TFLAGScomplex))
1565 return MATCHnomatch;
1567 // Disallow implicit conversion of real or imaginary to complex
1568 if (flags & (TFLAGSreal | TFLAGSimaginary) &&
1569 tob->flags & TFLAGScomplex)
1570 return MATCHnomatch;
1572 // Disallow implicit conversion to-from real and imaginary
1573 if ((flags & (TFLAGSreal | TFLAGSimaginary)) !=
1574 (tob->flags & (TFLAGSreal | TFLAGSimaginary)))
1575 return MATCHnomatch;
1577 return MATCHconvert;
1580 TypeBasic *TypeBasic::isTypeBasic()
1582 return (TypeBasic *)this;
1585 /***************************** TypeArray *****************************/
1587 TypeArray::TypeArray(TY ty, Type *next)
1588 : Type(ty, next)
1592 Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
1594 Type *n = this->next->toBasetype(); // uncover any typedef's
1596 #if LOGDOTEXP
1597 printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1598 #endif
1599 if (ident == Id::reverse && (n->ty == Tchar || n->ty == Twchar))
1601 Expression *ec;
1602 FuncDeclaration *fd;
1603 Expressions *arguments;
1604 char *nm;
1605 static char *name[2] = { "_adReverseChar", "_adReverseWchar" };
1607 nm = name[n->ty == Twchar];
1608 fd = FuncDeclaration::genCfunc(next->arrayOf(), nm, Type::tvoid->arrayOf());
1609 ec = new VarExp(0, fd);
1610 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1611 arguments = new Expressions();
1612 arguments->push(e);
1613 e = new CallExp(e->loc, ec, arguments);
1614 e->type = next->arrayOf();
1616 else if (ident == Id::sort && (n->ty == Tchar || n->ty == Twchar))
1618 Expression *ec;
1619 FuncDeclaration *fd;
1620 Expressions *arguments;
1621 char *nm;
1622 static char *name[2] = { "_adSortChar", "_adSortWchar" };
1624 nm = name[n->ty == Twchar];
1625 fd = FuncDeclaration::genCfunc(next->arrayOf(), nm, Type::tvoid->arrayOf());
1626 ec = new VarExp(0, fd);
1627 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1628 arguments = new Expressions();
1629 arguments->push(e);
1630 e = new CallExp(e->loc, ec, arguments);
1631 e->type = next->arrayOf();
1633 else if (ident == Id::reverse || ident == Id::dup)
1635 Expression *ec;
1636 FuncDeclaration *fd;
1637 Expressions *arguments;
1638 target_size_t size = next->size(e->loc);
1639 int dup;
1641 assert(size);
1642 dup = (ident == Id::dup);
1643 if (dup)
1644 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::adDup,
1645 Type::typeinfo->type, Type::tvoid->arrayOf());
1646 else
1647 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::adReverse,
1648 Type::tvoid->arrayOf(), Type::tsize_t);
1649 ec = new VarExp(0, fd);
1650 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1651 arguments = new Expressions();
1652 if (dup)
1653 arguments->push(getTypeInfo(sc));
1654 arguments->push(e);
1655 if (!dup)
1656 arguments->push(new IntegerExp(0, size, Type::tsize_t));
1657 e = new CallExp(e->loc, ec, arguments);
1658 e->type = next->arrayOf();
1660 else if (ident == Id::sort)
1662 Expression *ec;
1663 FuncDeclaration *fd;
1664 Expressions *arguments;
1666 fd = FuncDeclaration::genCfunc(tint32->arrayOf(),
1667 (char*)(n->ty == Tbit ? "_adSortBit" : "_adSort"),
1668 Type::tvoid->arrayOf(),
1669 n->ty == Tbit ? NULL : Type::tvoid->pointerTo());
1670 ec = new VarExp(0, fd);
1671 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1672 arguments = new Expressions();
1673 arguments->push(e);
1674 if (next->ty != Tbit)
1675 arguments->push(n->ty == Tsarray
1676 ? n->getTypeInfo(sc) // don't convert to dynamic array
1677 : n->getInternalTypeInfo(sc));
1678 e = new CallExp(e->loc, ec, arguments);
1679 e->type = next->arrayOf();
1681 else
1683 e = Type::dotExp(sc, e, ident);
1685 return e;
1689 /***************************** TypeSArray *****************************/
1691 TypeSArray::TypeSArray(Type *t, Expression *dim)
1692 : TypeArray(Tsarray, t)
1694 //printf("TypeSArray(%s)\n", dim->toChars());
1695 this->dim = dim;
1698 Type *TypeSArray::syntaxCopy()
1700 Type *t = next->syntaxCopy();
1701 Expression *e = dim->syntaxCopy();
1702 t = new TypeSArray(t, e);
1703 return t;
1706 d_uns64 TypeSArray::size(Loc loc)
1707 { integer_t sz;
1709 if (!dim)
1710 return Type::size(loc);
1711 sz = dim->toInteger();
1712 if (next->toBasetype()->ty == Tbit) // if array of bits
1714 if (sz + 31 < sz)
1715 goto Loverflow;
1716 sz = ((sz + 31) & ~31) / 8; // size in bytes, rounded up to 32 bit dwords
1718 else
1719 { integer_t n, n2;
1721 n = next->size();
1722 n2 = n * sz;
1723 if (n && (n2 / n) != sz)
1724 goto Loverflow;
1725 sz = n2;
1727 return sz;
1729 Loverflow:
1730 error(loc, "index %"PRIdMAX" overflow for static array", sz);
1731 return 1;
1734 unsigned TypeSArray::alignsize()
1736 return next->alignsize();
1739 /**************************
1740 * This evaluates exp while setting length to be the number
1741 * of elements in the tuple t.
1743 Expression *semanticLength(Scope *sc, Type *t, Expression *exp)
1745 if (t->ty == Ttuple)
1746 { ScopeDsymbol *sym = new ArrayScopeSymbol((TypeTuple *)t);
1747 sym->parent = sc->scopesym;
1748 sc = sc->push(sym);
1750 exp = exp->semantic(sc);
1752 sc->pop();
1754 else
1755 exp = exp->semantic(sc);
1756 return exp;
1759 Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp)
1761 ScopeDsymbol *sym = new ArrayScopeSymbol(s);
1762 sym->parent = sc->scopesym;
1763 sc = sc->push(sym);
1765 exp = exp->semantic(sc);
1767 sc->pop();
1768 return exp;
1771 void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
1773 //printf("TypeSArray::resolve() %s\n", toChars());
1774 next->resolve(loc, sc, pe, pt, ps);
1775 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
1776 if (*pe)
1777 { // It's really an index expression
1778 Expression *e;
1779 e = new IndexExp(loc, *pe, dim);
1780 *pe = e;
1782 else if (*ps)
1783 { Dsymbol *s = *ps;
1784 TupleDeclaration *td = s->isTupleDeclaration();
1785 if (td)
1787 ScopeDsymbol *sym = new ArrayScopeSymbol(td);
1788 sym->parent = sc->scopesym;
1789 sc = sc->push(sym);
1791 dim = dim->semantic(sc);
1792 dim = dim->optimize(WANTvalue | WANTinterpret);
1793 uinteger_t d = dim->toUInteger();
1795 sc = sc->pop();
1797 if (d >= td->objects->dim)
1798 { error(loc, "tuple index %"PRIuMAX" exceeds %u", d, td->objects->dim);
1799 goto Ldefault;
1801 Object *o = (Object *)td->objects->data[(size_t)d];
1802 if (o->dyncast() == DYNCAST_DSYMBOL)
1804 *ps = (Dsymbol *)o;
1805 return;
1807 if (o->dyncast() == DYNCAST_EXPRESSION)
1809 *ps = NULL;
1810 *pe = (Expression *)o;
1811 return;
1814 /* Create a new TupleDeclaration which
1815 * is a slice [d..d+1] out of the old one.
1816 * Do it this way because TemplateInstance::semanticTiargs()
1817 * can handle unresolved Objects this way.
1819 Objects *objects = new Objects;
1820 objects->setDim(1);
1821 objects->data[0] = o;
1823 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
1824 *ps = tds;
1826 else
1827 goto Ldefault;
1829 else
1831 Ldefault:
1832 Type::resolve(loc, sc, pe, pt, ps);
1836 Type *TypeSArray::semantic(Loc loc, Scope *sc)
1838 //printf("TypeSArray::semantic() %s\n", toChars());
1840 Type *t;
1841 Expression *e;
1842 Dsymbol *s;
1843 next->resolve(loc, sc, &e, &t, &s);
1844 if (dim && s && s->isTupleDeclaration())
1845 { TupleDeclaration *sd = s->isTupleDeclaration();
1847 dim = semanticLength(sc, sd, dim);
1848 dim = dim->optimize(WANTvalue | WANTinterpret);
1849 uinteger_t d = dim->toUInteger();
1851 if (d >= sd->objects->dim)
1852 { error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim);
1853 return Type::terror;
1855 Object *o = (Object *)sd->objects->data[(size_t)d];
1856 if (o->dyncast() != DYNCAST_TYPE)
1857 { error(loc, "%s is not a type", toChars());
1858 return Type::terror;
1860 t = (Type *)o;
1861 return t;
1864 next = next->semantic(loc,sc);
1865 Type *tbn = next->toBasetype();
1867 if (dim)
1868 { integer_t n, n2;
1870 dim = semanticLength(sc, tbn, dim);
1872 dim = dim->optimize(WANTvalue | WANTinterpret);
1873 if (sc->parameterSpecialization && dim->op == TOKvar &&
1874 ((VarExp *)dim)->var->storage_class & STCtemplateparameter)
1876 /* It could be a template parameter N which has no value yet:
1877 * template Foo(T : T[N], size_t N);
1879 return this;
1881 integer_t d1 = dim->toInteger();
1882 dim = dim->castTo(sc, tsize_t);
1883 dim = dim->optimize(WANTvalue);
1884 integer_t d2 = dim->toInteger();
1886 if (d1 != d2)
1887 goto Loverflow;
1889 if (tbn->isintegral() ||
1890 tbn->isfloating() ||
1891 tbn->ty == Tpointer ||
1892 tbn->ty == Tarray ||
1893 tbn->ty == Tsarray ||
1894 tbn->ty == Taarray ||
1895 tbn->ty == Tclass)
1897 /* Only do this for types that don't need to have semantic()
1898 * run on them for the size, since they may be forward referenced.
1900 n = tbn->size(loc);
1901 n2 = n * d2;
1902 if ((int)n2 < 0)
1903 goto Loverflow;
1904 if (n2 >= 0x1000000) // put a 'reasonable' limit on it
1905 goto Loverflow;
1906 if (n && n2 / n != d2)
1908 Loverflow:
1909 error(loc, "index %"PRIdMAX" overflow for static array", d1);
1910 dim = new IntegerExp(0, 1, tsize_t);
1914 switch (tbn->ty)
1916 case Ttuple:
1917 { // Index the tuple to get the type
1918 assert(dim);
1919 TypeTuple *tt = (TypeTuple *)tbn;
1920 uinteger_t d = dim->toUInteger();
1922 if (d >= tt->arguments->dim)
1923 { error(loc, "tuple index %"PRIuMAX" exceeds %u", d, tt->arguments->dim);
1924 return Type::terror;
1926 Argument *arg = (Argument *)tt->arguments->data[(size_t)d];
1927 return arg->type;
1929 case Tfunction:
1930 case Tnone:
1931 error(loc, "can't have array of %s", tbn->toChars());
1932 tbn = next = tint32;
1933 break;
1935 if (tbn->isauto())
1936 error(loc, "cannot have array of auto %s", tbn->toChars());
1937 return merge();
1940 void TypeSArray::toDecoBuffer(OutBuffer *buf)
1942 buf->writeByte(mangleChar[ty]);
1943 if (dim)
1944 buf->printf("%"PRIuMAX, dim->toInteger());
1945 if (next)
1946 next->toDecoBuffer(buf);
1949 void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
1951 if (mod != this->mod)
1952 { toCBuffer3(buf, hgs, mod);
1953 return;
1955 next->toCBuffer2(buf, hgs, this->mod);
1956 buf->printf("[%s]", dim->toChars());
1959 Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
1961 #if LOGDOTEXP
1962 printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1963 #endif
1964 if (ident == Id::length)
1966 e = dim;
1968 else if (ident == Id::ptr)
1970 e = e->castTo(sc, next->pointerTo());
1972 else
1974 e = TypeArray::dotExp(sc, e, ident);
1976 return e;
1979 int TypeSArray::isString()
1981 TY nty = next->toBasetype()->ty;
1982 return nty == Tchar || nty == Twchar || nty == Tdchar;
1985 unsigned TypeSArray::memalign(unsigned salign)
1987 return next->memalign(salign);
1990 MATCH TypeSArray::implicitConvTo(Type *to)
1992 //printf("TypeSArray::implicitConvTo()\n");
1994 if (to->ty == Tmaybe && to->next)
1995 to = to->next;
1997 // Allow implicit conversion of static array to pointer or dynamic array
1998 if ((IMPLICIT_ARRAY_TO_PTR && to->ty == Tpointer) &&
1999 (to->next->ty == Tvoid || next->equals(to->next)
2000 /*|| to->next->isBaseOf(next)*/))
2002 return MATCHconvert;
2004 if (to->ty == Tarray)
2005 { target_ptrdiff_t offset = 0;
2007 if (next->equals(to->next) ||
2008 (to->next->isBaseOf(next, &offset) && offset == 0) ||
2009 to->next->ty == Tvoid)
2010 return MATCHconvert;
2012 #if 0
2013 if (to->ty == Tsarray)
2015 TypeSArray *tsa = (TypeSArray *)to;
2017 if (next->equals(tsa->next) && dim->equals(tsa->dim))
2019 return MATCHconvert;
2022 #endif
2023 return Type::implicitConvTo(to);
2026 Expression *TypeSArray::defaultInit(Loc loc)
2028 #if LOGDEFAULTINIT
2029 printf("TypeSArray::defaultInit() '%s'\n", toChars());
2030 #endif
2031 return next->defaultInit(loc);
2034 int TypeSArray::isZeroInit()
2036 return next->isZeroInit();
2040 Expression *TypeSArray::toExpression()
2042 Expression *e = next->toExpression();
2043 if (e)
2044 { Expressions *arguments = new Expressions();
2045 arguments->push(dim);
2046 e = new ArrayExp(dim->loc, e, arguments);
2048 return e;
2051 int TypeSArray::hasPointers()
2053 return next->hasPointers();
2056 /***************************** TypeDArray *****************************/
2058 TypeDArray::TypeDArray(Type *t)
2059 : TypeArray(Tarray, t)
2061 //printf("TypeDArray(t = %p)\n", t);
2064 Type *TypeDArray::syntaxCopy()
2066 Type *t = next->syntaxCopy();
2067 if (t == next)
2068 t = this;
2069 else
2070 t = new TypeDArray(t);
2071 return t;
2074 d_uns64 TypeDArray::size(Loc loc)
2076 //printf("TypeDArray::size()\n");
2077 return PTRSIZE * 2;
2080 unsigned TypeDArray::alignsize()
2082 // A DArray consists of two ptr-sized values, so align it on pointer size
2083 // boundary
2084 return PTRSIZE;
2087 Type *TypeDArray::semantic(Loc loc, Scope *sc)
2088 { Type *tn = next;
2090 tn = next->semantic(loc,sc);
2091 Type *tbn = tn->toBasetype();
2092 switch (tbn->ty)
2094 case Tfunction:
2095 case Tnone:
2096 case Ttuple:
2097 error(loc, "can't have array of %s", tbn->toChars());
2098 tn = next = tint32;
2099 break;
2101 if (tn->isauto())
2102 error(loc, "cannot have array of auto %s", tn->toChars());
2103 if (next != tn)
2104 //deco = NULL; // redo
2105 return tn->arrayOf();
2106 return merge();
2109 void TypeDArray::toDecoBuffer(OutBuffer *buf)
2111 buf->writeByte(NOT_NULL_MANGLE);
2112 buf->writeByte(mangleChar[ty]);
2113 if (next)
2114 next->toDecoBuffer(buf);
2117 void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2119 if (mod != this->mod)
2120 { toCBuffer3(buf, hgs, mod);
2121 return;
2123 next->toCBuffer2(buf, hgs, this->mod);
2124 buf->writestring("[]");
2127 Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
2129 #if LOGDOTEXP
2130 printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2131 #endif
2132 if (ident == Id::length)
2134 if (e->op == TOKstring)
2135 { StringExp *se = (StringExp *)e;
2137 return new IntegerExp(se->loc, se->len, Type::tindex);
2139 e = new ArrayLengthExp(e->loc, e);
2140 e->type = Type::tsize_t;
2141 return e;
2143 else if (ident == Id::ptr)
2145 e = e->castTo(sc, next->pointerTo());
2146 return e;
2148 else
2150 e = TypeArray::dotExp(sc, e, ident);
2152 return e;
2155 int TypeDArray::isString()
2157 TY nty = next->toBasetype()->ty;
2158 return nty == Tchar || nty == Twchar || nty == Tdchar;
2161 MATCH TypeDArray::implicitConvTo(Type *to)
2163 //printf("TypeDArray::implicitConvTo()\n");
2165 if (to->ty == Tmaybe && to->next)
2166 to = to->next;
2168 // Allow implicit conversion of array to pointer
2169 if (IMPLICIT_ARRAY_TO_PTR &&
2170 to->ty == Tpointer &&
2171 (to->next->ty == Tvoid || next->equals(to->next) /*|| to->next->isBaseOf(next)*/))
2173 return MATCHconvert;
2176 if (to->ty == Tarray)
2177 { target_ptrdiff_t offset = 0;
2179 if ((to->next->isBaseOf(next, &offset) && offset == 0) ||
2180 to->next->ty == Tvoid)
2181 return MATCHconvert;
2183 return Type::implicitConvTo(to);
2186 Expression *TypeDArray::defaultInit(Loc loc)
2188 #if LOGDEFAULTINIT
2189 printf("TypeDArray::defaultInit() '%s'\n", toChars());
2190 #endif
2191 Expression *e;
2192 e = new NullExp(loc);
2193 e->type = this;
2194 return e;
2197 int TypeDArray::isZeroInit()
2199 return 1;
2202 int TypeDArray::checkBoolean()
2204 return TRUE;
2207 int TypeDArray::hasPointers()
2209 return TRUE;
2212 /***************************** TypeAArray *****************************/
2214 TypeAArray::TypeAArray(Type *t, Type *index)
2215 : TypeArray(Taarray, t)
2217 this->index = index;
2218 this->key = NULL;
2221 Type *TypeAArray::syntaxCopy()
2223 Type *t = next->syntaxCopy();
2224 Type *ti = index->syntaxCopy();
2225 if (t == next && ti == index)
2226 t = this;
2227 else
2228 t = new TypeAArray(t, ti);
2229 return t;
2232 d_uns64 TypeAArray::size(Loc loc)
2234 return PTRSIZE /* * 2*/;
2238 Type *TypeAArray::semantic(Loc loc, Scope *sc)
2240 //printf("TypeAArray::semantic() %s index->ty = %d\n", toChars(), index->ty);
2242 // Deal with the case where we thought the index was a type, but
2243 // in reality it was an expression.
2244 if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray)
2246 Expression *e;
2247 Type *t;
2248 Dsymbol *s;
2250 index->resolve(loc, sc, &e, &t, &s);
2251 if (e)
2252 { // It was an expression -
2253 // Rewrite as a static array
2254 TypeSArray *tsa;
2256 tsa = new TypeSArray(next, e);
2257 return tsa->semantic(loc,sc);
2259 else if (t)
2260 index = t;
2261 else
2262 index->error(loc, "index is not a type or an expression");
2264 else
2265 index = index->semantic(loc,sc);
2267 // Compute key type; the purpose of the key type is to
2268 // minimize the permutations of runtime library
2269 // routines as much as possible.
2270 key = index->toBasetype();
2271 switch (key->ty)
2273 #if 0
2274 case Tint8:
2275 case Tuns8:
2276 case Tint16:
2277 case Tuns16:
2278 key = tint32;
2279 break;
2280 #endif
2282 case Tsarray:
2283 #if 0
2284 // Convert to Tarray
2285 key = key->next->arrayOf();
2286 #endif
2287 break;
2288 case Tbit:
2289 case Tbool:
2290 case Tfunction:
2291 case Tvoid:
2292 case Tnone:
2293 error(loc, "can't have associative array key of %s", key->toChars());
2294 break;
2296 next = next->semantic(loc,sc);
2297 switch (next->toBasetype()->ty)
2299 case Tfunction:
2300 case Tnone:
2301 error(loc, "can't have associative array of %s", next->toChars());
2302 break;
2304 if (next->isauto())
2305 error(loc, "cannot have array of auto %s", next->toChars());
2307 return merge();
2310 void TypeAArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
2312 //printf("TypeAArray::resolve() %s\n", toChars());
2314 // Deal with the case where we thought the index was a type, but
2315 // in reality it was an expression.
2316 if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray)
2318 Expression *e;
2319 Type *t;
2320 Dsymbol *s;
2322 index->resolve(loc, sc, &e, &t, &s);
2323 if (e)
2324 { // It was an expression -
2325 // Rewrite as a static array
2327 TypeSArray *tsa = new TypeSArray(next, e);
2328 return tsa->resolve(loc, sc, pe, pt, ps);
2330 else if (t)
2331 index = t;
2332 else
2333 index->error(loc, "index is not a type or an expression");
2335 Type::resolve(loc, sc, pe, pt, ps);
2339 Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
2341 #if LOGDOTEXP
2342 printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2343 #endif
2344 if (ident == Id::length)
2346 Expression *ec;
2347 FuncDeclaration *fd;
2348 Expressions *arguments;
2350 fd = FuncDeclaration::genCfunc(Type::tsize_t, Id::aaLen, Type::tvoid->arrayOf());
2351 ec = new VarExp(0, fd);
2352 arguments = new Expressions();
2353 arguments->push(e);
2354 e = new CallExp(e->loc, ec, arguments);
2355 e->type = fd->type->next;
2357 else if (ident == Id::keys)
2359 Expression *ec;
2360 FuncDeclaration *fd;
2361 Expressions *arguments;
2362 int size = key->size(e->loc);
2364 assert(size);
2365 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaKeys,
2366 Type::tvoid->arrayOf(), Type::tsize_t);
2367 ec = new VarExp(0, fd);
2368 arguments = new Expressions();
2369 arguments->push(e);
2370 arguments->push(new IntegerExp(0, size, Type::tsize_t));
2371 e = new CallExp(e->loc, ec, arguments);
2372 e->type = index->arrayOf();
2374 else if (ident == Id::values)
2376 Expression *ec;
2377 FuncDeclaration *fd;
2378 Expressions *arguments;
2380 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaValues,
2381 Type::tvoid->arrayOf(), Type::tsize_t, Type::tsize_t);
2382 ec = new VarExp(0, fd);
2383 arguments = new Expressions();
2384 arguments->push(e);
2385 size_t keysize = key->size(e->loc);
2386 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1);
2387 arguments->push(new IntegerExp(0, keysize, Type::tsize_t));
2388 arguments->push(new IntegerExp(0, next->size(e->loc), Type::tsize_t));
2389 e = new CallExp(e->loc, ec, arguments);
2390 e->type = next->arrayOf();
2392 else if (ident == Id::rehash)
2394 Expression *ec;
2395 FuncDeclaration *fd;
2396 Expressions *arguments;
2398 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaRehash);
2399 ec = new VarExp(0, fd);
2400 arguments = new Expressions();
2401 arguments->push(e->addressOf(sc));
2402 arguments->push(key->getInternalTypeInfo(sc));
2403 e = new CallExp(e->loc, ec, arguments);
2404 e->type = this;
2406 else
2408 e = Type::dotExp(sc, e, ident);
2410 return e;
2413 void TypeAArray::toDecoBuffer(OutBuffer *buf)
2415 buf->writeByte(mangleChar[ty]);
2416 index->toDecoBuffer(buf);
2417 next->toDecoBuffer(buf);
2420 void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2422 if (mod != this->mod)
2423 { toCBuffer3(buf, hgs, mod);
2424 return;
2426 next->toCBuffer2(buf, hgs, this->mod);
2427 buf->writeByte('[');
2428 index->toCBuffer2(buf, hgs, 0);
2429 buf->writeByte(']');
2432 Expression *TypeAArray::defaultInit(Loc loc)
2434 #if LOGDEFAULTINIT
2435 printf("TypeAArray::defaultInit() '%s'\n", toChars());
2436 #endif
2437 Expression *e;
2438 e = new NullExp(loc);
2439 e->type = this;
2440 return e;
2443 int TypeAArray::checkBoolean()
2445 return TRUE;
2448 int TypeAArray::hasPointers()
2450 return TRUE;
2453 /***************************** TypeMaybe *****************************/
2455 TypeMaybe::TypeMaybe(Type *t)
2456 : Type(Tmaybe, t)
2460 void TypeMaybe::toDecoBuffer(OutBuffer *buf)
2462 int offset = buf->offset;
2464 // Since all D types are TypeMaybe, adding a char here
2465 // would prevent linking to existing libraries.
2466 next->toDecoBuffer(buf);
2468 if (buf->data[offset] == 'Q')
2469 buf->remove(offset, 1); // After semantic: remove not-null qualifier
2470 else
2471 buf->insert(offset, "?", 1); // Before semantic: just make name unique
2474 Type *TypeMaybe::syntaxCopy()
2476 Type *t = next->syntaxCopy();
2477 if (t == next)
2478 t = this;
2479 else
2480 t = new TypeMaybe(t);
2481 return t;
2484 Type *TypeMaybe::toBasetype()
2486 return next->toBasetype();
2489 Expression *TypeMaybe::dotExp(Scope *sc, Expression *e, Identifier *ident)
2491 e->error("Attempt to access property '%s' for '%s' of type '%s', which may be null.",
2492 ident->string, e->toChars(), toChars());
2493 return next->dotExp(sc, e, ident);
2496 Type *TypeMaybe::semantic(Loc loc, Scope *sc)
2498 //printf("TypeMaybe::semantic()\n");
2499 Type *n = next->semantic(loc, sc);
2501 // For D source we don't know if it's a maybe type or not, so the parser
2502 // wraps everything in a TypeMaybe (including structs, etc, since it can't
2503 // tell). If the next type can't be null, we vanish here.
2504 switch (n->ty)
2506 case Tarray:
2507 break;
2508 case Tclass:
2509 break;
2510 default:
2511 //error(loc, "can't have maybe for %s of type %d", n->toChars(), n->toBasetype()->ty);
2512 return n;
2514 if (n != next)
2515 deco = NULL;
2516 next = n;
2517 return merge();
2520 d_uns64 TypeMaybe::size(Loc loc)
2522 return next->size();
2525 void TypeMaybe::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2527 //printf("TypeMaybe::toCBuffer2() next = %d\n", next->ty);
2528 if (mod != this->mod)
2529 { toCBuffer3(buf, hgs, mod);
2530 return;
2532 next->toCBuffer2(buf, hgs, this->mod);
2533 buf->writeByte('?');
2536 MATCH TypeMaybe::implicitConvTo(Type *to)
2538 //printf("TypeMaybe::implicitConvTo(%s)\n", to->toChars());
2540 if (this == to)
2541 return MATCHexact;
2543 if (to->ty == Tpointer && to->next)
2545 if (to->next->ty == Tvoid)
2546 return MATCHconvert;
2548 #if 0
2549 if (to->next->isBaseOf(next))
2550 return MATCHconvert;
2551 #endif
2553 if (next->ty == Tfunction && to->next->ty == Tfunction)
2554 { TypeFunction *tf;
2555 TypeFunction *tfto;
2557 tf = (TypeFunction *)(next);
2558 tfto = (TypeFunction *)(to->next);
2559 return tfto->equals(tf) ? MATCHexact : MATCHnomatch;
2562 // if (to->ty == Tvoid)
2563 // return MATCHconvert;
2565 return MATCHnomatch;
2568 int TypeMaybe::isscalar()
2570 return next->isscalar();
2573 Expression *TypeMaybe::defaultInit(Loc loc)
2575 #if LOGDEFAULTINIT
2576 printf("TypeMaybe::defaultInit() '%s'\n", toChars());
2577 #endif
2578 return next->defaultInit();
2581 int TypeMaybe::isZeroInit()
2583 return next->isZeroInit();
2586 int TypeMaybe::hasPointers()
2588 return next->hasPointers();
2591 /***************************** TypePointer *****************************/
2593 TypePointer::TypePointer(Type *t)
2594 : Type(Tpointer, t)
2598 Type *TypePointer::syntaxCopy()
2600 Type *t = next->syntaxCopy();
2601 if (t == next)
2602 t = this;
2603 else
2604 t = new TypePointer(t);
2605 return t;
2608 Type *TypePointer::semantic(Loc loc, Scope *sc)
2610 //printf("TypePointer::semantic()\n");
2611 Type *n = next->semantic(loc, sc);
2612 switch (n->toBasetype()->ty)
2614 case Ttuple:
2615 error(loc, "can't have pointer to %s", n->toChars());
2616 n = tint32;
2617 break;
2619 if (n != next)
2620 deco = NULL;
2621 next = n;
2622 return merge();
2626 d_uns64 TypePointer::size(Loc loc)
2628 return PTRSIZE;
2631 void TypePointer::toDecoBuffer(OutBuffer *buf)
2633 buf->writeByte(NOT_NULL_MANGLE);
2634 Type::toDecoBuffer(buf);
2637 void TypePointer::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2639 //printf("TypePointer::toCBuffer2() next = %d\n", next->ty);
2640 if (mod != this->mod)
2641 { toCBuffer3(buf, hgs, mod);
2642 return;
2644 next->toCBuffer2(buf, hgs, this->mod);
2645 if (next->ty != Tfunction)
2646 buf->writeByte('*');
2649 MATCH TypePointer::implicitConvTo(Type *to)
2651 //printf("TypePointer::implicitConvTo()\n");
2653 if (this == to)
2654 return MATCHexact;
2655 if (to->ty == Tpointer && to->next)
2657 if (to->next->ty == Tvoid)
2658 return MATCHconvert;
2660 #if 0
2661 if (to->next->isBaseOf(next))
2662 return MATCHconvert;
2663 #endif
2665 if (next->ty == Tfunction && to->next->ty == Tfunction)
2666 { TypeFunction *tf;
2667 TypeFunction *tfto;
2669 tf = (TypeFunction *)(next);
2670 tfto = (TypeFunction *)(to->next);
2671 return tfto->equals(tf) ? MATCHexact : MATCHnomatch;
2674 // if (to->ty == Tvoid)
2675 // return MATCHconvert;
2676 return MATCHnomatch;
2679 int TypePointer::isscalar()
2681 return TRUE;
2684 Expression *TypePointer::defaultInit(Loc loc)
2686 #if LOGDEFAULTINIT
2687 printf("TypePointer::defaultInit() '%s'\n", toChars());
2688 #endif
2689 Expression *e;
2690 e = new NullExp(loc);
2691 e->type = this;
2692 return e;
2695 int TypePointer::isZeroInit()
2697 return 1;
2700 int TypePointer::hasPointers()
2702 return TRUE;
2706 /***************************** TypeReference *****************************/
2708 TypeReference::TypeReference(Type *t)
2709 : Type(Treference, t)
2711 if (t->ty == Tbit)
2712 error(0,"cannot make reference to a bit");
2713 // BUG: what about references to static arrays?
2716 Type *TypeReference::syntaxCopy()
2718 Type *t = next->syntaxCopy();
2719 if (t == next)
2720 t = this;
2721 else
2722 t = new TypeReference(t);
2723 return t;
2726 d_uns64 TypeReference::size(Loc loc)
2728 return PTRSIZE;
2731 void TypeReference::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2733 if (mod != this->mod)
2734 { toCBuffer3(buf, hgs, mod);
2735 return;
2737 next->toCBuffer2(buf, hgs, this->mod);
2738 buf->writeByte('&');
2741 Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident)
2743 #if LOGDOTEXP
2744 printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2745 #endif
2747 // References just forward things along
2748 return next->dotExp(sc, e, ident);
2751 Expression *TypeReference::defaultInit(Loc loc)
2753 #if LOGDEFAULTINIT
2754 printf("TypeReference::defaultInit() '%s'\n", toChars());
2755 #endif
2756 Expression *e;
2757 e = new NullExp(loc);
2758 e->type = this;
2759 return e;
2762 int TypeReference::isZeroInit()
2764 return 1;
2768 /***************************** TypeFunction *****************************/
2770 TypeFunction::TypeFunction(Arguments *parameters, Type *treturn, int varargs, enum LINK linkage)
2771 : Type(Tfunction, treturn)
2773 //if (!treturn) *(char*)0=0;
2774 // assert(treturn);
2775 this->parameters = parameters;
2776 this->varargs = varargs;
2777 this->linkage = linkage;
2778 this->inuse = 0;
2781 Type *TypeFunction::syntaxCopy()
2783 Type *treturn = next ? next->syntaxCopy() : NULL;
2784 Arguments *params = Argument::arraySyntaxCopy(parameters);
2785 Type *t = new TypeFunction(params, treturn, varargs, linkage);
2786 return t;
2789 /*******************************
2790 * Returns:
2791 * 0 types are distinct
2792 * 1 this is covariant with t
2793 * 2 arguments match as far as overloading goes,
2794 * but types are not covariant
2795 * 3 cannot determine covariance because of forward references
2798 int Type::covariant(Type *t)
2800 #if 0
2801 printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars());
2802 printf("deco = %p, %p\n", deco, t->deco);
2803 printf("ty = %d\n", next->ty);
2804 #endif
2806 int inoutmismatch = 0;
2808 if (equals(t))
2809 goto Lcovariant;
2810 if (ty != Tfunction || t->ty != Tfunction)
2811 goto Ldistinct;
2814 TypeFunction *t1 = (TypeFunction *)this;
2815 TypeFunction *t2 = (TypeFunction *)t;
2817 if (t1->varargs != t2->varargs)
2818 goto Ldistinct;
2820 if (t1->parameters && t2->parameters)
2822 size_t dim = Argument::dim(t1->parameters);
2823 if (dim != Argument::dim(t2->parameters))
2824 goto Ldistinct;
2826 for (size_t i = 0; i < dim; i++)
2827 { Argument *arg1 = Argument::getNth(t1->parameters, i);
2828 Argument *arg2 = Argument::getNth(t2->parameters, i);
2830 if (!arg1->type->equals(arg2->type))
2831 goto Ldistinct;
2832 if (arg1->storageClass != arg2->storageClass)
2833 inoutmismatch = 1;
2836 else if (t1->parameters != t2->parameters)
2837 goto Ldistinct;
2839 // The argument lists match
2840 if (inoutmismatch)
2841 goto Lnotcovariant;
2842 if (t1->linkage != t2->linkage)
2843 goto Lnotcovariant;
2845 Type *t1n = t1->next;
2846 Type *t2n = t2->next;
2848 if (t1n->equals(t2n))
2849 goto Lcovariant;
2850 if (t1n->ty != Tclass || t2n->ty != Tclass)
2851 goto Lnotcovariant;
2853 // If t1n is forward referenced:
2854 ClassDeclaration *cd = ((TypeClass *)t1n)->sym;
2855 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
2857 return 3;
2860 if (t1n->implicitConvTo(t2n))
2861 goto Lcovariant;
2862 goto Lnotcovariant;
2865 Lcovariant:
2866 //printf("\tcovaraint: 1\n");
2867 return 1;
2869 Ldistinct:
2870 //printf("\tcovaraint: 0\n");
2871 return 0;
2873 Lnotcovariant:
2874 //printf("\tcovaraint: 2\n");
2875 return 2;
2878 void TypeFunction::toDecoBuffer(OutBuffer *buf)
2879 { unsigned char mc;
2881 //printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars());
2882 //static int nest; if (++nest == 50) *(char*)0=0;
2883 if (inuse)
2884 { inuse = 2; // flag error to caller
2885 return;
2887 inuse++;
2888 switch (linkage)
2890 case LINKd: mc = 'F'; break;
2891 case LINKc: mc = 'U'; break;
2892 case LINKwindows: mc = 'W'; break;
2893 case LINKpascal: mc = 'V'; break;
2894 case LINKcpp: mc = 'R'; break;
2895 default:
2896 assert(0);
2898 buf->writeByte(mc);
2899 // Write argument types
2900 Argument::argsToDecoBuffer(buf, parameters);
2901 //if (buf->data[buf->offset - 1] == '@') halt();
2902 buf->writeByte('Z' - varargs); // mark end of arg list
2903 next->toDecoBuffer(buf);
2904 inuse--;
2907 void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
2909 char *p = NULL;
2911 if (inuse)
2912 { inuse = 2; // flag error to caller
2913 return;
2915 inuse++;
2916 if (next && (!ident || ident->toHChars2() == ident->toChars()))
2917 next->toCBuffer2(buf, hgs, 0);
2918 if (hgs->ddoc != 1)
2920 switch (linkage)
2922 case LINKd: p = NULL; break;
2923 case LINKc: p = "C "; break;
2924 case LINKwindows: p = "Windows "; break;
2925 case LINKpascal: p = "Pascal "; break;
2926 case LINKcpp: p = "C++ "; break;
2927 default:
2928 assert(0);
2932 if (!hgs->hdrgen && p)
2933 buf->writestring(p);
2934 if (ident)
2935 { buf->writeByte(' ');
2936 buf->writestring(ident->toHChars2());
2938 Argument::argsToCBuffer(buf, hgs, parameters, varargs);
2939 inuse--;
2942 void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2944 char *p = NULL;
2946 if (inuse)
2947 { inuse = 2; // flag error to caller
2948 return;
2950 inuse++;
2951 if (next)
2952 next->toCBuffer2(buf, hgs, 0);
2953 if (hgs->ddoc != 1)
2955 switch (linkage)
2957 case LINKd: p = NULL; break;
2958 case LINKc: p = "C "; break;
2959 case LINKwindows: p = "Windows "; break;
2960 case LINKpascal: p = "Pascal "; break;
2961 case LINKcpp: p = "C++ "; break;
2962 default:
2963 assert(0);
2967 if (!hgs->hdrgen && p)
2968 buf->writestring(p);
2969 buf->writestring(" function");
2970 Argument::argsToCBuffer(buf, hgs, parameters, varargs);
2971 inuse--;
2974 Type *TypeFunction::semantic(Loc loc, Scope *sc)
2976 if (deco) // if semantic() already run
2978 //printf("already done\n");
2979 return this;
2981 //printf("TypeFunction::semantic() this = %p\n", this);
2983 TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
2984 memcpy(tf, this, sizeof(TypeFunction));
2985 if (parameters)
2986 { tf->parameters = (Arguments *)parameters->copy();
2987 for (size_t i = 0; i < parameters->dim; i++)
2988 { Argument *arg = (Argument *)parameters->data[i];
2989 Argument *cpy = (Argument *)mem.malloc(sizeof(Argument));
2990 memcpy(cpy, arg, sizeof(Argument));
2991 tf->parameters->data[i] = (void *)cpy;
2995 tf->linkage = sc->linkage;
2996 if (!tf->next)
2998 assert(global.errors);
2999 tf->next = tvoid;
3001 tf->next = tf->next->semantic(loc,sc);
3002 if (tf->next->toBasetype()->ty == Tsarray)
3003 { error(loc, "functions cannot return static array %s", tf->next->toChars());
3004 tf->next = Type::terror;
3006 if (tf->next->toBasetype()->ty == Tfunction)
3007 { error(loc, "functions cannot return a function");
3008 tf->next = Type::terror;
3010 if (tf->next->toBasetype()->ty == Ttuple)
3011 { error(loc, "functions cannot return a tuple");
3012 tf->next = Type::terror;
3014 if (tf->next->isauto() && !(sc->flags & SCOPEctor))
3015 error(loc, "functions cannot return auto %s", tf->next->toChars());
3017 if (tf->parameters)
3018 { size_t dim = Argument::dim(tf->parameters);
3020 for (size_t i = 0; i < dim; i++)
3021 { Argument *arg = Argument::getNth(tf->parameters, i);
3022 Type *t;
3024 tf->inuse++;
3025 arg->type = arg->type->semantic(loc,sc);
3026 if (tf->inuse == 1) tf->inuse--;
3027 t = arg->type->toBasetype();
3029 if (arg->storageClass & (STCout | STCref | STClazy))
3031 if (t->ty == Tsarray)
3032 error(loc, "cannot have out or ref parameter of type %s", t->toChars());
3034 if (!(arg->storageClass & STClazy) && t->ty == Tvoid)
3035 error(loc, "cannot have parameter of type %s", arg->type->toChars());
3037 if (arg->defaultArg)
3039 arg->defaultArg = arg->defaultArg->semantic(sc);
3040 arg->defaultArg = resolveProperties(sc, arg->defaultArg);
3041 arg->defaultArg = arg->defaultArg->implicitCastTo(sc, arg->type);
3044 /* If arg turns out to be a tuple, the number of parameters may
3045 * change.
3047 if (t->ty == Ttuple)
3048 { dim = Argument::dim(tf->parameters);
3049 i--;
3053 tf->deco = tf->merge()->deco;
3055 if (tf->inuse)
3056 { error(loc, "recursive type");
3057 tf->inuse = 0;
3058 return terror;
3061 if (tf->varargs == 1 && tf->linkage != LINKd && Argument::dim(tf->parameters) == 0)
3062 error(loc, "variadic functions with non-D linkage must have at least one parameter");
3064 /* Don't return merge(), because arg identifiers and default args
3065 * can be different
3066 * even though the types match
3068 return tf;
3071 /********************************
3072 * 'args' are being matched to function 'this'
3073 * Determine match level.
3074 * Returns:
3075 * MATCHxxxx
3078 int TypeFunction::callMatch(Expressions *args)
3080 //printf("TypeFunction::callMatch()\n");
3081 int match = MATCHexact; // assume exact match
3083 size_t nparams = Argument::dim(parameters);
3084 size_t nargs = args ? args->dim : 0;
3085 if (nparams == nargs)
3087 else if (nargs > nparams)
3089 if (varargs == 0)
3090 goto Nomatch; // too many args; no match
3091 match = MATCHconvert; // match ... with a "conversion" match level
3094 for (size_t u = 0; u < nparams; u++)
3095 { int m;
3096 Expression *arg;
3098 // BUG: what about out and ref?
3100 Argument *p = Argument::getNth(parameters, u);
3101 assert(p);
3102 if (u >= nargs)
3104 if (p->defaultArg)
3105 continue;
3106 if (varargs == 2 && u + 1 == nparams)
3107 goto L1;
3108 goto Nomatch; // not enough arguments
3110 arg = (Expression *)args->data[u];
3111 assert(arg);
3112 if (p->storageClass & STClazy && p->type->ty == Tvoid && arg->type->ty != Tvoid)
3113 m = MATCHconvert;
3114 else
3115 m = arg->implicitConvTo(p->type);
3116 //printf("\tm = %d\n", m);
3117 if (m == MATCHnomatch) // if no match
3120 if (varargs == 2 && u + 1 == nparams) // if last varargs param
3121 { Type *tb = p->type->toBasetype();
3122 TypeSArray *tsa;
3123 integer_t sz;
3125 switch (tb->ty)
3127 case Tsarray:
3128 tsa = (TypeSArray *)tb;
3129 sz = tsa->dim->toInteger();
3130 if (sz != nargs - u)
3131 goto Nomatch;
3132 case Tarray:
3133 for (; u < nargs; u++)
3135 arg = (Expression *)args->data[u];
3136 assert(arg);
3137 #if 1
3138 /* If lazy array of delegates,
3139 * convert arg(s) to delegate(s)
3141 Type *tret = p->isLazyArray();
3142 if (tret)
3144 if (tb->next->equals(arg->type))
3145 { m = MATCHexact;
3147 else
3149 m = arg->implicitConvTo(tret);
3150 if (m == MATCHnomatch)
3152 if (tret->toBasetype()->ty == Tvoid)
3153 m = MATCHconvert;
3157 else
3158 m = arg->implicitConvTo(tb->next);
3159 #else
3160 m = arg->implicitConvTo(tb->next);
3161 #endif
3162 if (m == 0)
3163 goto Nomatch;
3164 if (m < match)
3165 match = m;
3167 goto Ldone;
3169 case Tclass:
3170 // Should see if there's a constructor match?
3171 // Or just leave it ambiguous?
3172 goto Ldone;
3174 default:
3175 goto Nomatch;
3178 goto Nomatch;
3180 if (m < match)
3181 match = m; // pick worst match
3184 Ldone:
3185 //printf("match = %d\n", match);
3186 return match;
3188 Nomatch:
3189 //printf("no match\n");
3190 return MATCHnomatch;
3193 Type *TypeFunction::reliesOnTident()
3195 if (parameters)
3197 for (size_t i = 0; i < parameters->dim; i++)
3198 { Argument *arg = (Argument *)parameters->data[i];
3199 Type *t = arg->type->reliesOnTident();
3200 if (t)
3201 return t;
3204 return next->reliesOnTident();
3207 /***************************** TypeDelegate *****************************/
3209 TypeDelegate::TypeDelegate(Type *t)
3210 : Type(Tfunction, t)
3212 ty = Tdelegate;
3215 Type *TypeDelegate::syntaxCopy()
3217 Type *t = next->syntaxCopy();
3218 if (t == next)
3219 t = this;
3220 else
3221 t = new TypeDelegate(t);
3222 return t;
3225 Type *TypeDelegate::semantic(Loc loc, Scope *sc)
3227 if (deco) // if semantic() already run
3229 //printf("already done\n");
3230 return this;
3232 next = next->semantic(loc,sc);
3233 return merge();
3236 d_uns64 TypeDelegate::size(Loc loc)
3238 return PTRSIZE * 2;
3241 void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3243 if (mod != this->mod)
3244 { toCBuffer3(buf, hgs, mod);
3245 return;
3247 TypeFunction *tf = (TypeFunction *)next;
3249 tf->next->toCBuffer2(buf, hgs, 0);
3250 buf->writestring(" delegate");
3251 Argument::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs);
3254 Expression *TypeDelegate::defaultInit(Loc loc)
3256 #if LOGDEFAULTINIT
3257 printf("TypeDelegate::defaultInit() '%s'\n", toChars());
3258 #endif
3259 Expression *e;
3260 e = new NullExp(loc);
3261 e->type = this;
3262 return e;
3265 int TypeDelegate::isZeroInit()
3267 return 1;
3270 int TypeDelegate::checkBoolean()
3272 return TRUE;
3275 Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident)
3277 #if LOGDOTEXP
3278 printf("TypeDelegate::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
3279 #endif
3280 if (ident == Id::ptr)
3282 #ifndef IN_GCC
3283 e->type = tvoidptr;
3284 #else
3285 if (e->op == TOKdelegate || e->op == TOKcast)
3286 e = e->castTo(sc, tvoidptr); // Not an lvalue
3287 else
3289 e = e->addressOf(sc);
3290 e = e->castTo(sc, tvoidptr->pointerTo());
3291 e = new PtrExp(e->loc, e);
3292 e->type = tvoidptr;
3294 #endif
3295 return e;
3297 else if (ident == Id::funcptr)
3299 e = e->addressOf(sc);
3300 e->type = tvoidptr;
3301 e = new AddExp(e->loc, e, new IntegerExp(PTRSIZE));
3302 e->type = tvoidptr;
3303 e = new PtrExp(e->loc, e);
3304 e->type = next->pointerTo();
3305 return e;
3307 else
3309 e = Type::dotExp(sc, e, ident);
3311 return e;
3314 int TypeDelegate::hasPointers()
3316 return TRUE;
3321 /***************************** TypeQualified *****************************/
3323 TypeQualified::TypeQualified(TY ty, Loc loc)
3324 : Type(ty, NULL)
3326 this->loc = loc;
3329 void TypeQualified::syntaxCopyHelper(TypeQualified *t)
3331 //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t->toChars(), toChars());
3332 idents.setDim(t->idents.dim);
3333 for (int i = 0; i < idents.dim; i++)
3335 Identifier *id = (Identifier *)t->idents.data[i];
3336 if (id->dyncast() == DYNCAST_DSYMBOL)
3338 TemplateInstance *ti = (TemplateInstance *)id;
3340 ti = (TemplateInstance *)ti->syntaxCopy(NULL);
3341 id = (Identifier *)ti;
3343 idents.data[i] = id;
3348 void TypeQualified::addIdent(Identifier *ident)
3350 idents.push(ident);
3353 void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs)
3355 int i;
3357 for (i = 0; i < idents.dim; i++)
3358 { Identifier *id = (Identifier *)idents.data[i];
3360 buf->writeByte('.');
3362 if (id->dyncast() == DYNCAST_DSYMBOL)
3364 TemplateInstance *ti = (TemplateInstance *)id;
3365 ti->toCBuffer(buf, hgs);
3367 else
3368 buf->writestring(id->toChars());
3372 d_uns64 TypeQualified::size(Loc loc)
3374 error(this->loc, "size of type %s is not known", toChars());
3375 return 1;
3378 /*************************************
3379 * Takes an array of Identifiers and figures out if
3380 * it represents a Type or an Expression.
3381 * Output:
3382 * if expression, *pe is set
3383 * if type, *pt is set
3386 void TypeQualified::resolveHelper(Loc loc, Scope *sc,
3387 Dsymbol *s, Dsymbol *scopesym,
3388 Expression **pe, Type **pt, Dsymbol **ps)
3390 Identifier *id = NULL;
3391 int i;
3392 VarDeclaration *v;
3393 EnumMember *em;
3394 TupleDeclaration *td;
3395 Type *t;
3396 Expression *e;
3398 #if 0
3399 printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, toChars());
3400 if (scopesym)
3401 printf("\tscopesym = '%s'\n", scopesym->toChars());
3402 #endif
3403 *pe = NULL;
3404 *pt = NULL;
3405 *ps = NULL;
3406 if (s)
3408 //printf("\t1: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3409 s = s->toAlias();
3410 //printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3411 for (i = 0; i < idents.dim; i++)
3412 { Dsymbol *sm;
3414 id = (Identifier *)idents.data[i];
3415 sm = s->searchX(loc, sc, id);
3416 //printf("\t3: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3417 //printf("getType = '%s'\n", s->getType()->toChars());
3418 if (!sm)
3420 v = s->isVarDeclaration();
3421 if (v && id == Id::length)
3423 if (v->isConst() && v->getExpInitializer())
3424 { e = v->getExpInitializer()->exp;
3426 else
3427 e = new VarExp(loc, v);
3428 t = e->type;
3429 if (!t)
3430 goto Lerror;
3431 goto L3;
3433 t = s->getType();
3434 if (!t && s->isDeclaration())
3435 t = s->isDeclaration()->type;
3436 if (t)
3438 sm = t->toDsymbol(sc);
3439 if (sm)
3440 { sm = sm->search(loc, id, 0);
3441 if (sm)
3442 goto L2;
3444 //e = t->getProperty(loc, id);
3445 e = new TypeExp(loc, t);
3446 e = t->dotExp(sc, e, id);
3447 i++;
3449 for (; i < idents.dim; i++)
3451 id = (Identifier *)idents.data[i];
3452 //printf("e: '%s', id: '%s', type = %p\n", e->toChars(), id->toChars(), e->type);
3453 e = e->type->dotExp(sc, e, id);
3455 *pe = e;
3457 else
3458 Lerror:
3459 error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
3460 return;
3463 s = sm->toAlias();
3466 v = s->isVarDeclaration();
3467 if (v)
3469 // It's not a type, it's an expression
3470 if (v->isConst() && v->getExpInitializer())
3472 ExpInitializer *ei = v->getExpInitializer();
3473 assert(ei);
3474 *pe = ei->exp->copy(); // make copy so we can change loc
3475 (*pe)->loc = loc;
3477 else
3479 #if 0
3480 WithScopeSymbol *withsym;
3481 if (scopesym && (withsym = scopesym->isWithScopeSymbol()) != NULL)
3483 // Same as wthis.ident
3484 e = new VarExp(loc, withsym->withstate->wthis);
3485 e = new DotIdExp(loc, e, ident);
3486 //assert(0); // BUG: should handle this
3488 else
3489 #endif
3490 *pe = new VarExp(loc, v);
3492 return;
3494 em = s->isEnumMember();
3495 if (em)
3497 // It's not a type, it's an expression
3498 *pe = em->value->copy();
3499 return;
3503 t = s->getType();
3504 if (!t)
3506 // If the symbol is an import, try looking inside the import
3507 Import *si;
3509 si = s->isImport();
3510 if (si)
3512 s = si->search(loc, s->ident, 0);
3513 if (s && s != si)
3514 goto L1;
3515 s = si;
3517 *ps = s;
3518 return;
3520 if (t->ty == Tinstance && t != this && !t->deco)
3521 { error(loc, "forward reference to '%s'", t->toChars());
3522 return;
3525 if (t != this)
3527 if (t->reliesOnTident())
3529 Scope *scx;
3531 for (scx = sc; 1; scx = scx->enclosing)
3533 if (!scx)
3534 { error(loc, "forward reference to '%s'", t->toChars());
3535 return;
3537 if (scx->scopesym == scopesym)
3538 break;
3540 t = t->semantic(loc, scx);
3541 //((TypeIdentifier *)t)->resolve(loc, scx, pe, &t, ps);
3544 if (t->ty == Ttuple)
3545 *pt = t;
3546 else
3547 *pt = t->merge();
3549 if (!s)
3551 error(loc, "identifier '%s' is not defined", toChars());
3555 /***************************** TypeIdentifier *****************************/
3557 TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident)
3558 : TypeQualified(Tident, loc)
3560 this->ident = ident;
3564 Type *TypeIdentifier::syntaxCopy()
3566 TypeIdentifier *t;
3568 t = new TypeIdentifier(loc, ident);
3569 t->syntaxCopyHelper(this);
3570 return t;
3573 void TypeIdentifier::toDecoBuffer(OutBuffer *buf)
3574 { unsigned len;
3575 char *name;
3577 name = ident->toChars();
3578 len = strlen(name);
3579 buf->printf("%c%d%s", mangleChar[ty], len, name);
3580 //buf->printf("%c%s", mangleChar[ty], name);
3583 void TypeIdentifier::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3585 if (mod != this->mod)
3586 { toCBuffer3(buf, hgs, mod);
3587 return;
3589 buf->writestring(this->ident->toChars());
3590 toCBuffer2Helper(buf, hgs);
3593 /*************************************
3594 * Takes an array of Identifiers and figures out if
3595 * it represents a Type or an Expression.
3596 * Output:
3597 * if expression, *pe is set
3598 * if type, *pt is set
3601 void TypeIdentifier::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
3602 { Dsymbol *s;
3603 Dsymbol *scopesym;
3605 //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars());
3606 s = sc->search(loc, ident, &scopesym);
3607 resolveHelper(loc, sc, s, scopesym, pe, pt, ps);
3610 /*****************************************
3611 * See if type resolves to a symbol, if so,
3612 * return that symbol.
3615 Dsymbol *TypeIdentifier::toDsymbol(Scope *sc)
3617 //printf("TypeIdentifier::toDsymbol('%s')\n", toChars());
3618 if (!sc)
3619 return NULL;
3620 //printf("ident = '%s'\n", ident->toChars());
3622 Dsymbol *scopesym;
3623 Dsymbol *s = sc->search(loc, ident, &scopesym);
3624 if (s)
3626 for (int i = 0; i < idents.dim; i++)
3628 Identifier *id = (Identifier *)idents.data[i];
3629 s = s->searchX(loc, sc, id);
3630 if (!s) // failed to find a symbol
3631 { //printf("\tdidn't find a symbol\n");
3632 break;
3636 return s;
3639 Type *TypeIdentifier::semantic(Loc loc, Scope *sc)
3641 Type *t;
3642 Expression *e;
3643 Dsymbol *s;
3645 //printf("TypeIdentifier::semantic(%s)\n", toChars());
3646 resolve(loc, sc, &e, &t, &s);
3647 if (t)
3649 //printf("\tit's a type %d, %s, %s\n", t->ty, t->toChars(), t->deco);
3651 if (t->ty == Ttypedef)
3652 { TypeTypedef *tt = (TypeTypedef *)t;
3654 if (tt->sym->sem == 1)
3655 error(loc, "circular reference of typedef %s", tt->toChars());
3658 else
3660 #ifdef DEBUG
3661 if (!global.gag)
3662 printf("1: ");
3663 #endif
3664 if (s)
3666 s->error(loc, "is used as a type");
3668 else
3669 error(loc, "%s is used as a type", toChars());
3670 t = tvoid;
3672 //t->print();
3673 return t;
3676 Type *TypeIdentifier::reliesOnTident()
3678 return this;
3681 Expression *TypeIdentifier::toExpression()
3683 Expression *e = new IdentifierExp(loc, ident);
3684 for (int i = 0; i < idents.dim; i++)
3686 Identifier *id = (Identifier *)idents.data[i];
3687 e = new DotIdExp(loc, e, id);
3690 return e;
3693 /***************************** TypeInstance *****************************/
3695 TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst)
3696 : TypeQualified(Tinstance, loc)
3698 this->tempinst = tempinst;
3701 Type *TypeInstance::syntaxCopy()
3703 //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim);
3704 TypeInstance *t;
3706 t = new TypeInstance(loc, (TemplateInstance *)tempinst->syntaxCopy(NULL));
3707 t->syntaxCopyHelper(this);
3708 return t;
3712 void TypeInstance::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3714 if (mod != this->mod)
3715 { toCBuffer3(buf, hgs, mod);
3716 return;
3718 tempinst->toCBuffer(buf, hgs);
3719 toCBuffer2Helper(buf, hgs);
3722 void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
3724 // Note close similarity to TypeIdentifier::resolve()
3726 Dsymbol *s;
3728 *pe = NULL;
3729 *pt = NULL;
3730 *ps = NULL;
3732 #if 0
3733 if (!idents.dim)
3735 error(loc, "template instance '%s' has no identifier", toChars());
3736 return;
3738 #endif
3739 //id = (Identifier *)idents.data[0];
3740 //printf("TypeInstance::resolve(sc = %p, idents = '%s')\n", sc, id->toChars());
3741 s = tempinst;
3742 if (s)
3743 s->semantic(sc);
3744 resolveHelper(loc, sc, s, NULL, pe, pt, ps);
3745 //printf("pt = '%s'\n", (*pt)->toChars());
3748 Type *TypeInstance::semantic(Loc loc, Scope *sc)
3750 Type *t;
3751 Expression *e;
3752 Dsymbol *s;
3754 //printf("TypeInstance::semantic(%s)\n", toChars());
3756 if (sc->parameterSpecialization)
3758 unsigned errors = global.errors;
3759 global.gag++;
3761 resolve(loc, sc, &e, &t, &s);
3763 global.gag--;
3764 if (errors != global.errors)
3765 { if (global.gag == 0)
3766 global.errors = errors;
3767 return this;
3770 else
3771 resolve(loc, sc, &e, &t, &s);
3773 if (!t)
3775 #ifdef DEBUG
3776 printf("2: ");
3777 #endif
3778 error(loc, "%s is used as a type", toChars());
3779 t = tvoid;
3781 return t;
3785 /***************************** TypeTypeof *****************************/
3787 TypeTypeof::TypeTypeof(Loc loc, Expression *exp)
3788 : TypeQualified(Ttypeof, loc)
3790 this->exp = exp;
3793 Type *TypeTypeof::syntaxCopy()
3795 TypeTypeof *t;
3797 t = new TypeTypeof(loc, exp->syntaxCopy());
3798 t->syntaxCopyHelper(this);
3799 return t;
3802 Dsymbol *TypeTypeof::toDsymbol(Scope *sc)
3804 Type *t;
3806 t = semantic(0, sc);
3807 if (t == this)
3808 return NULL;
3809 return t->toDsymbol(sc);
3812 void TypeTypeof::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3814 if (mod != this->mod)
3815 { toCBuffer3(buf, hgs, mod);
3816 return;
3818 buf->writestring("typeof(");
3819 exp->toCBuffer(buf, hgs);
3820 buf->writeByte(')');
3821 toCBuffer2Helper(buf, hgs);
3824 Type *TypeTypeof::semantic(Loc loc, Scope *sc)
3825 { Expression *e;
3826 Type *t;
3828 //printf("TypeTypeof::semantic() %p\n", this);
3830 //static int nest; if (++nest == 50) *(char*)0=0;
3832 #if 0
3833 /* Special case for typeof(this) and typeof(super) since both
3834 * should work even if they are not inside a non-static member function
3836 if (exp->op == TOKthis || exp->op == TOKsuper)
3838 // Find enclosing struct or class
3839 for (Dsymbol *s = sc->parent; 1; s = s->parent)
3841 ClassDeclaration *cd;
3842 StructDeclaration *sd;
3844 if (!s)
3846 error(loc, "%s is not in a struct or class scope", exp->toChars());
3847 goto Lerr;
3849 cd = s->isClassDeclaration();
3850 if (cd)
3852 if (exp->op == TOKsuper)
3854 cd = cd->baseClass;
3855 if (!cd)
3856 { error(loc, "class %s has no 'super'", s->toChars());
3857 goto Lerr;
3860 t = cd->type;
3861 break;
3863 sd = s->isStructDeclaration();
3864 if (sd)
3866 if (exp->op == TOKsuper)
3868 error(loc, "struct %s has no 'super'", sd->toChars());
3869 goto Lerr;
3871 t = sd->type->pointerTo();
3872 break;
3876 else
3877 #endif
3879 sc->intypeof++;
3880 exp = exp->semantic(sc);
3881 sc->intypeof--;
3882 t = exp->type;
3883 if (!t)
3885 error(loc, "expression (%s) has no type", exp->toChars());
3886 goto Lerr;
3890 if (idents.dim)
3892 Dsymbol *s = t->toDsymbol(sc);
3893 for (size_t i = 0; i < idents.dim; i++)
3895 if (!s)
3896 break;
3897 Identifier *id = (Identifier *)idents.data[i];
3898 s = s->searchX(loc, sc, id);
3900 if (s)
3902 t = s->getType();
3903 if (!t)
3904 { error(loc, "%s is not a type", s->toChars());
3905 goto Lerr;
3908 else
3909 { error(loc, "cannot resolve .property for %s", toChars());
3910 goto Lerr;
3913 return t;
3915 Lerr:
3916 return tvoid;
3919 d_uns64 TypeTypeof::size(Loc loc)
3921 if (exp->type)
3922 return exp->type->size(loc);
3923 else
3924 return TypeQualified::size(loc);
3929 /***************************** TypeEnum *****************************/
3931 TypeEnum::TypeEnum(EnumDeclaration *sym)
3932 : Type(Tenum, NULL)
3934 this->sym = sym;
3937 char *TypeEnum::toChars()
3939 return sym->toChars();
3942 Type *TypeEnum::semantic(Loc loc, Scope *sc)
3944 sym->semantic(sc);
3945 return merge();
3948 d_uns64 TypeEnum::size(Loc loc)
3950 if (!sym->memtype)
3952 error(loc, "enum %s is forward referenced", sym->toChars());
3953 return 4;
3955 return sym->memtype->size(loc);
3958 unsigned TypeEnum::alignsize()
3960 if (!sym->memtype)
3962 #ifdef DEBUG
3963 printf("1: ");
3964 #endif
3965 error(0, "enum %s is forward referenced", sym->toChars());
3966 return 4;
3968 return sym->memtype->alignsize();
3971 Dsymbol *TypeEnum::toDsymbol(Scope *sc)
3973 return sym;
3976 Type *TypeEnum::toBasetype()
3978 if (!sym->memtype)
3980 #ifdef DEBUG
3981 printf("2: ");
3982 #endif
3983 error(sym->loc, "enum %s is forward referenced", sym->toChars());
3984 return tint32;
3986 return sym->memtype->toBasetype();
3989 void TypeEnum::toDecoBuffer(OutBuffer *buf)
3990 { char *name;
3992 name = sym->mangle();
3993 // if (name[0] == '_' && name[1] == 'D')
3994 // name += 2;
3995 buf->printf("%c%s", mangleChar[ty], name);
3998 void TypeEnum::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4000 if (mod != this->mod)
4001 { toCBuffer3(buf, hgs, mod);
4002 return;
4004 buf->writestring(sym->toChars());
4007 Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident)
4009 EnumMember *m;
4010 Dsymbol *s;
4011 Expression *em;
4013 #if LOGDOTEXP
4014 printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars());
4015 #endif
4016 if (!sym->symtab)
4017 goto Lfwd;
4018 s = sym->symtab->lookup(ident);
4019 if (!s)
4021 return getProperty(e->loc, ident);
4023 m = s->isEnumMember();
4024 em = m->value->copy();
4025 em->loc = e->loc;
4026 return em;
4028 Lfwd:
4029 error(e->loc, "forward reference of %s.%s", toChars(), ident->toChars());
4030 return new IntegerExp(0, 0, this);
4033 Expression *TypeEnum::getProperty(Loc loc, Identifier *ident)
4034 { Expression *e;
4036 if (ident == Id::max)
4038 if (!sym->symtab)
4039 goto Lfwd;
4040 e = new IntegerExp(0, sym->maxval, this);
4042 else if (ident == Id::min)
4044 if (!sym->symtab)
4045 goto Lfwd;
4046 e = new IntegerExp(0, sym->minval, this);
4048 else if (ident == Id::init)
4050 if (!sym->symtab)
4051 goto Lfwd;
4052 e = defaultInit(loc);
4054 else
4056 if (!sym->memtype)
4057 goto Lfwd;
4058 e = sym->memtype->getProperty(loc, ident);
4060 return e;
4062 Lfwd:
4063 error(loc, "forward reference of %s.%s", toChars(), ident->toChars());
4064 return new IntegerExp(0, 0, this);
4067 int TypeEnum::isintegral()
4069 return 1;
4072 int TypeEnum::isfloating()
4074 return 0;
4077 int TypeEnum::isunsigned()
4079 return sym->memtype->isunsigned();
4082 int TypeEnum::isscalar()
4084 return 1;
4085 //return sym->memtype->isscalar();
4088 MATCH TypeEnum::implicitConvTo(Type *to)
4089 { MATCH m;
4091 //printf("TypeEnum::implicitConvTo()\n");
4092 if (this->equals(to))
4093 m = MATCHexact; // exact match
4094 else if (sym->memtype->implicitConvTo(to))
4095 m = MATCHconvert; // match with conversions
4096 else
4097 m = MATCHnomatch; // no match
4098 return m;
4101 Expression *TypeEnum::defaultInit(Loc loc)
4103 #if LOGDEFAULTINIT
4104 printf("TypeEnum::defaultInit() '%s'\n", toChars());
4105 #endif
4106 // Initialize to first member of enum
4107 Expression *e;
4108 e = new IntegerExp(loc, sym->defaultval, this);
4109 return e;
4112 int TypeEnum::isZeroInit()
4114 return (sym->defaultval == 0);
4117 int TypeEnum::hasPointers()
4119 return toBasetype()->hasPointers();
4122 /***************************** TypeTypedef *****************************/
4124 TypeTypedef::TypeTypedef(TypedefDeclaration *sym)
4125 : Type(Ttypedef, NULL)
4127 this->sym = sym;
4130 Type *TypeTypedef::syntaxCopy()
4132 return this;
4135 char *TypeTypedef::toChars()
4137 return sym->toChars();
4140 Type *TypeTypedef::semantic(Loc loc, Scope *sc)
4142 //printf("TypeTypedef::semantic(%s), sem = %d\n", toChars(), sym->sem);
4143 sym->semantic(sc);
4144 return merge();
4147 d_uns64 TypeTypedef::size(Loc loc)
4149 return sym->basetype->size(loc);
4152 unsigned TypeTypedef::alignsize()
4154 return sym->basetype->alignsize();
4157 Dsymbol *TypeTypedef::toDsymbol(Scope *sc)
4159 return sym;
4162 void TypeTypedef::toDecoBuffer(OutBuffer *buf)
4163 { unsigned len;
4164 char *name;
4166 name = sym->mangle();
4167 // if (name[0] == '_' && name[1] == 'D')
4168 // name += 2;
4169 //len = strlen(name);
4170 //buf->printf("%c%d%s", mangleChar[ty], len, name);
4171 buf->printf("%c%s", mangleChar[ty], name);
4174 void TypeTypedef::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4176 //printf("TypeTypedef::toCBuffer2() '%s'\n", sym->toChars());
4177 if (mod != this->mod)
4178 { toCBuffer3(buf, hgs, mod);
4179 return;
4181 buf->writestring(sym->toChars());
4184 Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident)
4186 #if LOGDOTEXP
4187 printf("TypeTypedef::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars());
4188 #endif
4189 if (ident == Id::init)
4191 return Type::dotExp(sc, e, ident);
4193 return sym->basetype->dotExp(sc, e, ident);
4196 Expression *TypeTypedef::getProperty(Loc loc, Identifier *ident)
4198 if (ident == Id::init)
4200 return Type::getProperty(loc, ident);
4202 return sym->basetype->getProperty(loc, ident);
4205 int TypeTypedef::isbit()
4207 return sym->basetype->isbit();
4210 int TypeTypedef::isintegral()
4212 //printf("TypeTypedef::isintegral()\n");
4213 //printf("sym = '%s'\n", sym->toChars());
4214 //printf("basetype = '%s'\n", sym->basetype->toChars());
4215 return sym->basetype->isintegral();
4218 int TypeTypedef::isfloating()
4220 return sym->basetype->isfloating();
4223 int TypeTypedef::isreal()
4225 return sym->basetype->isreal();
4228 int TypeTypedef::isimaginary()
4230 return sym->basetype->isimaginary();
4233 int TypeTypedef::iscomplex()
4235 return sym->basetype->iscomplex();
4238 int TypeTypedef::isunsigned()
4240 return sym->basetype->isunsigned();
4243 int TypeTypedef::isscalar()
4245 return sym->basetype->isscalar();
4248 int TypeTypedef::checkBoolean()
4250 return sym->basetype->checkBoolean();
4253 Type *TypeTypedef::toBasetype()
4255 if (sym->inuse)
4257 sym->error("circular definition");
4258 sym->basetype = Type::terror;
4259 return Type::terror;
4261 sym->inuse = 1;
4262 Type *t = sym->basetype->toBasetype();
4263 sym->inuse = 0;
4264 return t;
4267 MATCH TypeTypedef::implicitConvTo(Type *to)
4268 { MATCH m;
4270 //printf("TypeTypedef::implicitConvTo()\n");
4271 if (this->equals(to))
4272 m = MATCHexact; // exact match
4273 else if (sym->basetype->implicitConvTo(to))
4274 m = MATCHconvert; // match with conversions
4275 else
4276 m = MATCHnomatch; // no match
4277 return m;
4280 Expression *TypeTypedef::defaultInit(Loc loc)
4281 { Expression *e;
4282 Type *bt;
4284 #if LOGDEFAULTINIT
4285 printf("TypeTypedef::defaultInit() '%s'\n", toChars());
4286 #endif
4287 if (sym->init)
4289 //sym->init->toExpression()->print();
4290 return sym->init->toExpression();
4292 bt = sym->basetype;
4293 e = bt->defaultInit(loc);
4294 e->type = this;
4295 while (bt->ty == Tsarray)
4297 e->type = bt->next;
4298 bt = bt->next->toBasetype();
4300 return e;
4303 int TypeTypedef::isZeroInit()
4305 if (sym->init)
4307 if (sym->init->isVoidInitializer())
4308 return 1; // initialize voids to 0
4309 Expression *e = sym->init->toExpression();
4310 if (e && e->isBool(FALSE))
4311 return 1;
4312 return 0; // assume not
4314 if (sym->inuse)
4316 sym->error("circular definition");
4317 sym->basetype = Type::terror;
4319 sym->inuse = 1;
4320 int result = sym->basetype->isZeroInit();
4321 sym->inuse = 0;
4322 return result;
4325 int TypeTypedef::hasPointers()
4327 return toBasetype()->hasPointers();
4330 /***************************** TypeStruct *****************************/
4332 TypeStruct::TypeStruct(StructDeclaration *sym)
4333 : Type(Tstruct, NULL)
4335 this->sym = sym;
4338 char *TypeStruct::toChars()
4340 //printf("sym.parent: %s, deco = %s\n", sym->parent->toChars(), deco);
4341 TemplateInstance *ti = sym->parent->isTemplateInstance();
4342 if (ti && ti->toAlias() == sym)
4343 return ti->toChars();
4344 return sym->toChars();
4347 Type *TypeStruct::syntaxCopy()
4349 return this;
4352 Type *TypeStruct::semantic(Loc loc, Scope *sc)
4354 //printf("TypeStruct::semantic('%s')\n", sym->toChars());
4356 /* Cannot do semantic for sym because scope chain may not
4357 * be right.
4359 //sym->semantic(sc);
4361 return merge();
4364 d_uns64 TypeStruct::size(Loc loc)
4366 return sym->size(loc);
4369 unsigned TypeStruct::alignsize()
4370 { target_size_t sz;
4372 sym->size(0); // give error for forward references
4373 sz = sym->alignsize;
4374 if (sz > sym->structalign)
4375 sz = sym->structalign;
4376 return sz;
4379 Dsymbol *TypeStruct::toDsymbol(Scope *sc)
4381 return sym;
4384 void TypeStruct::toDecoBuffer(OutBuffer *buf)
4385 { unsigned len;
4386 char *name;
4388 name = sym->mangle();
4389 //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", toChars(), name);
4390 // if (name[0] == '_' && name[1] == 'D')
4391 // name += 2;
4392 //len = strlen(name);
4393 //buf->printf("%c%d%s", mangleChar[ty], len, name);
4394 buf->printf("%c%s", mangleChar[ty], name);
4397 void TypeStruct::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4399 if (mod != this->mod)
4400 { toCBuffer3(buf, hgs, mod);
4401 return;
4403 TemplateInstance *ti = sym->parent->isTemplateInstance();
4404 if (ti && ti->toAlias() == sym)
4405 buf->writestring(ti->toChars());
4406 else
4407 buf->writestring(sym->toChars());
4410 Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
4411 { unsigned offset;
4413 Expression *b;
4414 VarDeclaration *v;
4415 Dsymbol *s;
4416 DotVarExp *de;
4417 Declaration *d;
4419 #if LOGDOTEXP
4420 printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
4421 #endif
4422 if (!sym->members)
4424 error(e->loc, "struct %s is forward referenced", sym->toChars());
4425 return new IntegerExp(e->loc, 0, Type::tint32);
4428 if (ident == Id::tupleof)
4430 /* Create a TupleExp
4432 Expressions *exps = new Expressions;
4433 exps->reserve(sym->fields.dim);
4434 for (size_t i = 0; i < sym->fields.dim; i++)
4435 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
4436 Expression *fe = new DotVarExp(e->loc, e, v);
4437 exps->push(fe);
4439 e = new TupleExp(e->loc, exps);
4440 e = e->semantic(sc);
4441 return e;
4444 if (e->op == TOKdotexp)
4445 { DotExp *de = (DotExp *)e;
4447 if (de->e1->op == TOKimport)
4449 ScopeExp *se = (ScopeExp *)de->e1;
4451 s = se->sds->search(e->loc, ident, 0);
4452 e = de->e1;
4453 goto L1;
4457 s = sym->search(e->loc, ident, 0);
4459 if (!s)
4461 //return getProperty(e->loc, ident);
4462 return Type::dotExp(sc, e, ident);
4464 s = s->toAlias();
4466 v = s->isVarDeclaration();
4467 if (v && v->isConst())
4468 { ExpInitializer *ei = v->getExpInitializer();
4470 if (ei)
4471 { e = ei->exp->copy(); // need to copy it if it's a StringExp
4472 e = e->semantic(sc);
4473 return e;
4477 if (s->getType())
4479 //return new DotTypeExp(e->loc, e, s);
4480 return new TypeExp(e->loc, s->getType());
4483 EnumMember *em = s->isEnumMember();
4484 if (em)
4486 assert(em->value);
4487 return em->value->copy();
4490 TemplateMixin *tm = s->isTemplateMixin();
4491 if (tm)
4492 { Expression *de;
4494 de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
4495 de->type = e->type;
4496 return de;
4499 TemplateDeclaration *td = s->isTemplateDeclaration();
4500 if (td)
4502 e = new DotTemplateExp(e->loc, e, td);
4503 e->semantic(sc);
4504 return e;
4507 TemplateInstance *ti = s->isTemplateInstance();
4508 if (ti)
4509 { if (!ti->semanticdone)
4510 ti->semantic(sc);
4511 s = ti->inst->toAlias();
4512 if (!s->isTemplateInstance())
4513 goto L1;
4514 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
4515 de->type = e->type;
4516 return de;
4519 d = s->isDeclaration();
4520 #ifdef DEBUG
4521 if (!d)
4522 printf("d = %s '%s'\n", s->kind(), s->toChars());
4523 #endif
4524 assert(d);
4526 if (e->op == TOKtype)
4527 { FuncDeclaration *fd = sc->func;
4529 if (d->needThis() && fd && fd->vthis)
4531 e = new DotVarExp(e->loc, new ThisExp(e->loc), d);
4532 e = e->semantic(sc);
4533 return e;
4535 if (d->isTupleDeclaration())
4537 e = new TupleExp(e->loc, d->isTupleDeclaration());
4538 e = e->semantic(sc);
4539 return e;
4541 return new VarExp(e->loc, d);
4544 if (d->isDataseg())
4546 // (e, d)
4547 VarExp *ve;
4549 accessCheck(e->loc, sc, e, d);
4550 ve = new VarExp(e->loc, d);
4551 e = new CommaExp(e->loc, e, ve);
4552 e->type = d->type;
4553 return e;
4556 if (v)
4558 if (v->toParent() != sym)
4559 sym->error(e->loc, "'%s' is not a member", v->toChars());
4561 // *(&e + offset)
4562 accessCheck(e->loc, sc, e, d);
4563 b = new AddrExp(e->loc, e);
4564 b->type = e->type->pointerTo();
4565 b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tsize_t));
4566 b->type = v->type->pointerTo();
4567 e = new PtrExp(e->loc, b);
4568 e->type = v->type;
4569 return e;
4572 de = new DotVarExp(e->loc, e, d);
4573 return de->semantic(sc);
4576 unsigned TypeStruct::memalign(unsigned salign)
4578 sym->size(0); // give error for forward references
4579 return sym->structalign;
4582 Expression *TypeStruct::defaultInit(Loc loc)
4583 { Symbol *s;
4584 Declaration *d;
4586 #if LOGDEFAULTINIT
4587 printf("TypeStruct::defaultInit() '%s'\n", toChars());
4588 #endif
4589 s = sym->toInitializer();
4590 d = new SymbolDeclaration(sym->loc, s, sym);
4591 assert(d);
4592 d->type = this;
4593 return new VarExp(sym->loc, d);
4596 int TypeStruct::isZeroInit()
4598 return sym->zeroInit;
4601 int TypeStruct::checkBoolean()
4603 return FALSE;
4606 int TypeStruct::hasPointers()
4608 StructDeclaration *s = sym;
4610 sym->size(0); // give error for forward references
4611 if (s->members)
4613 for (size_t i = 0; i < s->members->dim; i++)
4615 Dsymbol *sm = (Dsymbol *)s->members->data[i];
4616 if (sm->hasPointers())
4617 return TRUE;
4620 return FALSE;
4624 /***************************** TypeClass *****************************/
4626 TypeClass::TypeClass(ClassDeclaration *sym)
4627 : Type(Tclass, NULL)
4629 this->sym = sym;
4632 char *TypeClass::toChars()
4634 return sym->toPrettyChars();
4637 Type *TypeClass::syntaxCopy()
4639 return this;
4642 Type *TypeClass::semantic(Loc loc, Scope *sc)
4644 //printf("TypeClass::semantic(%s)\n", sym->toChars());
4645 if (sym->scope)
4646 sym->semantic(sym->scope);
4647 return merge();
4650 d_uns64 TypeClass::size(Loc loc)
4652 return PTRSIZE;
4655 Dsymbol *TypeClass::toDsymbol(Scope *sc)
4657 return sym;
4660 void TypeClass::toDecoBuffer(OutBuffer *buf)
4661 { unsigned len;
4662 char *name;
4664 name = sym->mangle();
4665 // if (name[0] == '_' && name[1] == 'D')
4666 // name += 2;
4667 //printf("TypeClass::toDecoBuffer('%s') = '%s'\n", toChars(), name);
4668 //len = strlen(name);
4669 //buf->printf("%c%d%s", mangleChar[ty], len, name);
4670 buf->printf("Q%c%s", mangleChar[ty], name);
4673 void TypeClass::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4675 if (mod != this->mod)
4676 { toCBuffer3(buf, hgs, mod);
4677 return;
4679 buf->writestring(sym->toChars());
4682 Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
4683 { unsigned offset;
4685 Expression *b;
4686 VarDeclaration *v;
4687 Dsymbol *s;
4688 DotVarExp *de;
4689 Declaration *d;
4691 #if LOGDOTEXP
4692 printf("TypeClass::dotExp(e='%s', ident='%s')\n", e->toChars(), ident->toChars());
4693 #endif
4695 if (e->op == TOKdotexp)
4696 { DotExp *de = (DotExp *)e;
4698 if (de->e1->op == TOKimport)
4700 ScopeExp *se = (ScopeExp *)de->e1;
4702 s = se->sds->search(e->loc, ident, 0);
4703 e = de->e1;
4704 goto L1;
4708 if (ident == Id::tupleof)
4710 /* Create a TupleExp
4712 Expressions *exps = new Expressions;
4713 exps->reserve(sym->fields.dim);
4714 for (size_t i = 0; i < sym->fields.dim; i++)
4715 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
4716 Expression *fe = new DotVarExp(e->loc, e, v);
4717 exps->push(fe);
4719 e = new TupleExp(e->loc, exps);
4720 e = e->semantic(sc);
4721 return e;
4724 s = sym->search(e->loc, ident, 0);
4726 if (!s)
4728 // See if it's a base class
4729 ClassDeclaration *cbase;
4730 for (cbase = sym->baseClass; cbase; cbase = cbase->baseClass)
4732 if (cbase->ident->equals(ident))
4734 e = new DotTypeExp(0, e, cbase);
4735 return e;
4739 if (ident == Id::classinfo)
4741 Type *t;
4743 assert(ClassDeclaration::classinfo);
4744 t = ClassDeclaration::classinfo->type;
4745 if (e->op == TOKtype || e->op == TOKdottype)
4747 /* For type.classinfo, we know the classinfo
4748 * at compile time.
4750 if (!sym->vclassinfo)
4751 sym->vclassinfo = new ClassInfoDeclaration(sym);
4752 e = new VarExp(e->loc, sym->vclassinfo);
4753 e = e->addressOf(sc);
4754 e->type = t; // do this so we don't get redundant dereference
4756 else
4757 { /* For class objects, the classinfo reference is the first
4758 * entry in the vtbl[]
4760 e = new PtrExp(e->loc, e);
4761 e->type = t->pointerTo();
4762 if (sym->isInterfaceDeclaration())
4764 if (sym->isCOMinterface())
4765 { /* COM interface vtbl[]s are different in that the
4766 * first entry is always pointer to QueryInterface().
4767 * We can't get a .classinfo for it.
4769 error(e->loc, "no .classinfo for COM interface objects");
4771 /* For an interface, the first entry in the vtbl[]
4772 * is actually a pointer to an instance of struct Interface.
4773 * The first member of Interface is the .classinfo,
4774 * so add an extra pointer indirection.
4776 e->type = e->type->pointerTo();
4777 e = new PtrExp(e->loc, e);
4778 e->type = t->pointerTo();
4780 e = new PtrExp(e->loc, e, t);
4782 return e;
4785 if (ident == Id::typeinfo)
4787 if (!global.params.useDeprecated)
4788 error(e->loc, ".typeinfo deprecated, use typeid(type)");
4789 return getTypeInfo(sc);
4791 if (ident == Id::outer && sym->vthis)
4793 s = sym->vthis;
4795 else
4797 //return getProperty(e->loc, ident);
4798 return Type::dotExp(sc, e, ident);
4801 s = s->toAlias();
4802 v = s->isVarDeclaration();
4803 if (v && v->isConst())
4804 { ExpInitializer *ei = v->getExpInitializer();
4806 if (ei)
4807 { e = ei->exp->copy(); // need to copy it if it's a StringExp
4808 e = e->semantic(sc);
4809 return e;
4813 if (s->getType())
4815 // if (e->op == TOKtype)
4816 return new TypeExp(e->loc, s->getType());
4817 // return new DotTypeExp(e->loc, e, s);
4820 EnumMember *em = s->isEnumMember();
4821 if (em)
4823 assert(em->value);
4824 return em->value->copy();
4827 TemplateMixin *tm = s->isTemplateMixin();
4828 if (tm)
4829 { Expression *de;
4831 de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
4832 de->type = e->type;
4833 return de;
4836 TemplateDeclaration *td = s->isTemplateDeclaration();
4837 if (td)
4839 e = new DotTemplateExp(e->loc, e, td);
4840 e->semantic(sc);
4841 return e;
4844 TemplateInstance *ti = s->isTemplateInstance();
4845 if (ti)
4846 { if (!ti->semanticdone)
4847 ti->semantic(sc);
4848 s = ti->inst->toAlias();
4849 if (!s->isTemplateInstance())
4850 goto L1;
4851 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
4852 de->type = e->type;
4853 return de;
4856 d = s->isDeclaration();
4857 if (!d)
4859 e->error("%s.%s is not a declaration", e->toChars(), ident->toChars());
4860 return new IntegerExp(e->loc, 1, Type::tint32);
4863 if (e->op == TOKtype)
4865 VarExp *ve;
4867 if (d->needThis() && (hasThis(sc) || !d->isFuncDeclaration()))
4869 if (sc->func)
4871 ClassDeclaration *thiscd;
4872 thiscd = sc->func->toParent()->isClassDeclaration();
4874 if (thiscd)
4876 ClassDeclaration *cd = e->type->isClassHandle();
4878 if (cd == thiscd)
4880 e = new ThisExp(e->loc);
4881 e = new DotTypeExp(e->loc, e, cd);
4882 de = new DotVarExp(e->loc, e, d);
4883 e = de->semantic(sc);
4884 return e;
4886 else if ((!cd || !cd->isBaseOf(thiscd, NULL)) &&
4887 !d->isFuncDeclaration())
4888 e->error("'this' is required, but %s is not a base class of %s", e->type->toChars(), thiscd->toChars());
4892 de = new DotVarExp(e->loc, new ThisExp(e->loc), d);
4893 e = de->semantic(sc);
4894 return e;
4896 else if (d->isTupleDeclaration())
4898 e = new TupleExp(e->loc, d->isTupleDeclaration());
4899 e = e->semantic(sc);
4900 return e;
4902 else
4903 ve = new VarExp(e->loc, d);
4904 return ve;
4907 if (d->isDataseg())
4909 // (e, d)
4910 VarExp *ve;
4912 accessCheck(e->loc, sc, e, d);
4913 ve = new VarExp(e->loc, d);
4914 e = new CommaExp(e->loc, e, ve);
4915 e->type = d->type;
4916 return e;
4919 if (d->parent && d->toParent()->isModule())
4921 // (e, d)
4922 VarExp *ve;
4924 ve = new VarExp(e->loc, d);
4925 e = new CommaExp(e->loc, e, ve);
4926 e->type = d->type;
4927 return e;
4930 de = new DotVarExp(e->loc, e, d);
4931 return de->semantic(sc);
4934 ClassDeclaration *TypeClass::isClassHandle()
4936 return sym;
4939 int TypeClass::isauto()
4941 return sym->isauto;
4944 int TypeClass::isBaseOf(Type *t, target_ptrdiff_t *poffset)
4946 if (t->ty == Tclass)
4947 { ClassDeclaration *cd;
4949 cd = ((TypeClass *)t)->sym;
4950 if (sym->isBaseOf(cd, poffset))
4951 return 1;
4953 return 0;
4956 MATCH TypeClass::implicitConvTo(Type *to)
4958 //printf("TypeClass::implicitConvTo('%s')\n", to->toChars());
4960 // Can always convert a "Foo" to a "Foo?"
4961 if (to->ty == Tmaybe && to->next)
4962 to = to->next;
4964 if (this == to)
4965 return MATCHexact;
4967 ClassDeclaration *cdto = to->isClassHandle();
4968 if (cdto && cdto->isBaseOf(sym, NULL))
4969 { //printf("is base\n");
4970 return MATCHconvert;
4973 if (global.params.Dversion == 1)
4975 // Allow conversion to (void *)
4976 if (to->ty == Tpointer && to->next->ty == Tvoid)
4977 return MATCHconvert;
4980 return MATCHnomatch;
4983 Expression *TypeClass::defaultInit(Loc loc)
4985 #if LOGDEFAULTINIT
4986 printf("TypeClass::defaultInit() '%s'\n", toChars());
4987 #endif
4988 Expression *e;
4989 e = new NullExp(loc);
4990 e->type = this;
4991 return e;
4994 int TypeClass::isZeroInit()
4996 return 1;
4999 int TypeClass::checkBoolean()
5001 return TRUE;
5004 int TypeClass::hasPointers()
5006 return TRUE;
5009 /***************************** TypeTuple *****************************/
5011 TypeTuple::TypeTuple(Arguments *arguments)
5012 : Type(Ttuple, NULL)
5014 //printf("TypeTuple(this = %p)\n", this);
5015 this->arguments = arguments;
5016 #ifdef DEBUG
5017 if (arguments)
5019 for (size_t i = 0; i < arguments->dim; i++)
5021 Argument *arg = (Argument *)arguments->data[i];
5022 assert(arg && arg->type);
5025 #endif
5028 /****************
5029 * Form TypeTuple from the types of the expressions.
5030 * Assume exps[] is already tuple expanded.
5033 TypeTuple::TypeTuple(Expressions *exps)
5034 : Type(Ttuple, NULL)
5036 Arguments *arguments = new Arguments;
5037 if (exps)
5039 arguments->setDim(exps->dim);
5040 for (size_t i = 0; i < exps->dim; i++)
5041 { Expression *e = (Expression *)exps->data[i];
5042 if (e->type->ty == Ttuple)
5043 e->error("cannot form tuple of tuples");
5044 Argument *arg = new Argument(STCin, e->type, NULL, NULL);
5045 arguments->data[i] = (void *)arg;
5048 this->arguments = arguments;
5051 Type *TypeTuple::syntaxCopy()
5053 Arguments *args = Argument::arraySyntaxCopy(arguments);
5054 Type *t = new TypeTuple(args);
5055 return t;
5058 Type *TypeTuple::semantic(Loc loc, Scope *sc)
5060 //printf("TypeTuple::semantic(this = %p)\n", this);
5061 if (!deco)
5062 deco = merge()->deco;
5064 /* Don't return merge(), because a tuple with one type has the
5065 * same deco as that type.
5067 return this;
5070 int TypeTuple::equals(Object *o)
5071 { Type *t;
5073 t = (Type *)o;
5074 //printf("TypeTuple::equals(%s, %s)\n", toChars(), t->toChars());
5075 if (this == t)
5077 return 1;
5079 if (t->ty == Ttuple)
5080 { TypeTuple *tt = (TypeTuple *)t;
5082 if (arguments->dim == tt->arguments->dim)
5084 for (size_t i = 0; i < tt->arguments->dim; i++)
5085 { Argument *arg1 = (Argument *)arguments->data[i];
5086 Argument *arg2 = (Argument *)tt->arguments->data[i];
5088 if (!arg1->type->equals(arg2->type))
5089 return 0;
5091 return 1;
5094 return 0;
5097 Type *TypeTuple::reliesOnTident()
5099 if (arguments)
5101 for (size_t i = 0; i < arguments->dim; i++)
5103 Argument *arg = (Argument *)arguments->data[i];
5104 Type *t = arg->type->reliesOnTident();
5105 if (t)
5106 return t;
5109 return NULL;
5112 void TypeTuple::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
5114 Argument::argsToCBuffer(buf, hgs, arguments, 0);
5117 void TypeTuple::toDecoBuffer(OutBuffer *buf)
5119 //printf("TypeTuple::toDecoBuffer() this = %p\n", this);
5120 OutBuffer buf2;
5121 Argument::argsToDecoBuffer(&buf2, arguments);
5122 unsigned len = buf2.offset;
5123 #if __NEWLIB_H__
5124 // newlib bug as of 1.14.0
5125 char * p = (char*) buf2.extractData();
5126 buf->printf("%c%d%.*s", mangleChar[ty], len, len, p ? p : "");
5127 #else
5128 buf->printf("%c%d%.*s", mangleChar[ty], len, len, (char *)buf2.extractData());
5129 #endif
5132 Expression *TypeTuple::getProperty(Loc loc, Identifier *ident)
5133 { Expression *e;
5135 #if LOGDOTEXP
5136 printf("TypeTuple::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars());
5137 #endif
5138 if (ident == Id::length)
5140 e = new IntegerExp(loc, arguments->dim, Type::tsize_t);
5142 else
5144 error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars());
5145 e = new IntegerExp(loc, 1, Type::tint32);
5147 return e;
5150 /***************************** TypeSlice *****************************/
5152 /* This is so we can slice a TypeTuple */
5154 TypeSlice::TypeSlice(Type *next, Expression *lwr, Expression *upr)
5155 : Type(Tslice, next)
5157 //printf("TypeSlice[%s .. %s]\n", lwr->toChars(), upr->toChars());
5158 this->lwr = lwr;
5159 this->upr = upr;
5162 Type *TypeSlice::syntaxCopy()
5164 Type *t = new TypeSlice(next->syntaxCopy(), lwr->syntaxCopy(), upr->syntaxCopy());
5165 return t;
5168 Type *TypeSlice::semantic(Loc loc, Scope *sc)
5170 //printf("TypeSlice::semantic() %s\n", toChars());
5171 next = next->semantic(loc, sc);
5172 //printf("next: %s\n", next->toChars());
5174 Type *tbn = next->toBasetype();
5175 if (tbn->ty != Ttuple)
5176 { error(loc, "can only slice tuple types, not %s", tbn->toChars());
5177 return Type::terror;
5179 TypeTuple *tt = (TypeTuple *)tbn;
5181 lwr = semanticLength(sc, tbn, lwr);
5182 lwr = lwr->optimize(WANTvalue);
5183 uinteger_t i1 = lwr->toUInteger();
5185 upr = semanticLength(sc, tbn, upr);
5186 upr = upr->optimize(WANTvalue);
5187 uinteger_t i2 = upr->toUInteger();
5189 if (!(i1 <= i2 && i2 <= tt->arguments->dim))
5190 { error(loc, "slice [%"PRIuMAX"..%"PRIuMAX"] is out of range of [0..%u]", i1, i2, tt->arguments->dim);
5191 return Type::terror;
5194 Arguments *args = new Arguments;
5195 args->reserve(i2 - i1);
5196 for (size_t i = i1; i < i2; i++)
5197 { Argument *arg = (Argument *)tt->arguments->data[i];
5198 args->push(arg);
5201 return new TypeTuple(args);
5204 void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
5206 next->resolve(loc, sc, pe, pt, ps);
5207 if (*pe)
5208 { // It's really a slice expression
5209 Expression *e;
5210 e = new SliceExp(loc, *pe, lwr, upr);
5211 *pe = e;
5213 else if (*ps)
5214 { Dsymbol *s = *ps;
5215 TupleDeclaration *td = s->isTupleDeclaration();
5216 if (td)
5218 /* It's a slice of a TupleDeclaration
5220 ScopeDsymbol *sym = new ArrayScopeSymbol(td);
5221 sym->parent = sc->scopesym;
5222 sc = sc->push(sym);
5224 lwr = lwr->semantic(sc);
5225 lwr = lwr->optimize(WANTvalue);
5226 uinteger_t i1 = lwr->toUInteger();
5228 upr = upr->semantic(sc);
5229 upr = upr->optimize(WANTvalue);
5230 uinteger_t i2 = upr->toUInteger();
5232 sc = sc->pop();
5234 if (!(i1 <= i2 && i2 <= td->objects->dim))
5235 { error(loc, "slice [%"PRIuMAX"u..%"PRIuMAX"u] is out of range of [0..%u]", i1, i2, td->objects->dim);
5236 goto Ldefault;
5239 if (i1 == 0 && i2 == td->objects->dim)
5241 *ps = td;
5242 return;
5245 /* Create a new TupleDeclaration which
5246 * is a slice [i1..i2] out of the old one.
5248 Objects *objects = new Objects;
5249 objects->setDim(i2 - i1);
5250 for (size_t i = 0; i < objects->dim; i++)
5252 objects->data[i] = td->objects->data[(size_t)i1 + i];
5255 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
5256 *ps = tds;
5258 else
5259 goto Ldefault;
5261 else
5263 Ldefault:
5264 Type::resolve(loc, sc, pe, pt, ps);
5268 void TypeSlice::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
5270 if (mod != this->mod)
5271 { toCBuffer3(buf, hgs, mod);
5272 return;
5274 next->toCBuffer2(buf, hgs, this->mod);
5276 buf->printf("[%s .. ", lwr->toChars());
5277 buf->printf("%s]", upr->toChars());
5280 /***************************** Argument *****************************/
5282 Argument::Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg)
5284 this->type = type;
5285 this->ident = ident;
5286 this->storageClass = storageClass;
5287 this->defaultArg = defaultArg;
5290 Argument *Argument::syntaxCopy()
5292 Argument *a = new Argument(storageClass,
5293 type ? type->syntaxCopy() : NULL,
5294 ident,
5295 defaultArg ? defaultArg->syntaxCopy() : NULL);
5296 return a;
5299 Arguments *Argument::arraySyntaxCopy(Arguments *args)
5300 { Arguments *a = NULL;
5302 if (args)
5304 a = new Arguments();
5305 a->setDim(args->dim);
5306 for (size_t i = 0; i < a->dim; i++)
5307 { Argument *arg = (Argument *)args->data[i];
5309 arg = arg->syntaxCopy();
5310 a->data[i] = (void *)arg;
5313 return a;
5316 char *Argument::argsTypesToChars(Arguments *args, int varargs)
5317 { OutBuffer *buf;
5319 buf = new OutBuffer();
5321 buf->writeByte('(');
5322 if (args)
5323 { int i;
5324 OutBuffer argbuf;
5325 HdrGenState hgs;
5327 for (i = 0; i < args->dim; i++)
5328 { Argument *arg;
5330 if (i)
5331 buf->writeByte(',');
5332 arg = (Argument *)args->data[i];
5333 argbuf.reset();
5334 arg->type->toCBuffer2(&argbuf, &hgs, 0);
5335 buf->write(&argbuf);
5337 if (varargs)
5339 if (i && varargs == 1)
5340 buf->writeByte(',');
5341 buf->writestring("...");
5344 buf->writeByte(')');
5346 return buf->toChars();
5349 void Argument::argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs)
5351 buf->writeByte('(');
5352 if (arguments)
5353 { int i;
5354 OutBuffer argbuf;
5356 for (i = 0; i < arguments->dim; i++)
5357 { Argument *arg;
5359 if (i)
5360 buf->writestring(", ");
5361 arg = (Argument *)arguments->data[i];
5362 if (arg->storageClass & STCout)
5363 buf->writestring("out ");
5364 else if (arg->storageClass & STCref)
5365 buf->writestring((global.params.Dversion == 1)
5366 ? (char *)"inout " : (char *)"ref ");
5367 else if (arg->storageClass & STClazy)
5368 buf->writestring("lazy ");
5369 argbuf.reset();
5370 arg->type->toCBuffer(&argbuf, arg->ident, hgs);
5371 if (arg->defaultArg)
5373 argbuf.writestring(" = ");
5374 arg->defaultArg->toCBuffer(&argbuf, hgs);
5376 buf->write(&argbuf);
5378 if (varargs)
5380 if (i && varargs == 1)
5381 buf->writeByte(',');
5382 buf->writestring("...");
5385 buf->writeByte(')');
5389 void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments)
5391 //printf("Argument::argsToDecoBuffer()\n");
5393 // Write argument types
5394 if (arguments)
5396 size_t dim = Argument::dim(arguments);
5397 for (size_t i = 0; i < dim; i++)
5399 Argument *arg = Argument::getNth(arguments, i);
5400 arg->toDecoBuffer(buf);
5405 /****************************************************
5406 * Determine if parameter is a lazy array of delegates.
5407 * If so, return the return type of those delegates.
5408 * If not, return NULL.
5411 Type *Argument::isLazyArray()
5413 // if (inout == Lazy)
5415 Type *tb = type->toBasetype();
5416 if (tb->ty == Tsarray || tb->ty == Tarray)
5418 Type *tel = tb->next->toBasetype();
5419 if (tel->ty == Tdelegate)
5421 TypeDelegate *td = (TypeDelegate *)tel;
5422 TypeFunction *tf = (TypeFunction *)td->next;
5424 if (!tf->varargs && Argument::dim(tf->parameters) == 0)
5426 return tf->next; // return type of delegate
5431 return NULL;
5434 void Argument::toDecoBuffer(OutBuffer *buf)
5436 switch (storageClass & (STCin | STCout | STCref | STClazy))
5437 { case 0:
5438 case STCin:
5439 break;
5440 case STCout:
5441 buf->writeByte('J');
5442 break;
5443 case STCref:
5444 buf->writeByte('K');
5445 break;
5446 case STClazy:
5447 buf->writeByte('L');
5448 break;
5449 default:
5450 #ifdef DEBUG
5451 halt();
5452 #endif
5453 assert(0);
5455 type->toDecoBuffer(buf);
5458 /***************************************
5459 * Determine number of arguments, folding in tuples.
5462 size_t Argument::dim(Arguments *args)
5464 size_t n = 0;
5465 if (args)
5467 for (size_t i = 0; i < args->dim; i++)
5468 { Argument *arg = (Argument *)args->data[i];
5469 Type *t = arg->type->toBasetype();
5471 if (t->ty == Ttuple)
5472 { TypeTuple *tu = (TypeTuple *)t;
5473 n += dim(tu->arguments);
5475 else
5476 n++;
5479 return n;
5482 /***************************************
5483 * Get nth Argument, folding in tuples.
5484 * Returns:
5485 * Argument* nth Argument
5486 * NULL not found, *pn gets incremented by the number
5487 * of Arguments
5490 Argument *Argument::getNth(Arguments *args, size_t nth, size_t *pn)
5492 if (!args)
5493 return NULL;
5495 size_t n = 0;
5496 for (size_t i = 0; i < args->dim; i++)
5497 { Argument *arg = (Argument *)args->data[i];
5498 Type *t = arg->type->toBasetype();
5500 if (t->ty == Ttuple)
5501 { TypeTuple *tu = (TypeTuple *)t;
5502 arg = getNth(tu->arguments, nth - n, &n);
5503 if (arg)
5504 return arg;
5506 else if (n == nth)
5507 return arg;
5508 else
5509 n++;
5512 if (pn)
5513 *pn += n;
5514 return NULL;