Added Maybe type
[delight/core.git] / dmd / mtype.c
blob38b35877766b40dc797894c645b82c6fec039f07
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 mangleChar[Tmaybe] = 'Q';
195 mangleChar[Treference] = 'R';
196 mangleChar[Tfunction] = 'F';
197 mangleChar[Tident] = 'I';
198 mangleChar[Tclass] = 'C';
199 mangleChar[Tstruct] = 'S';
200 mangleChar[Tenum] = 'E';
201 mangleChar[Ttypedef] = 'T';
202 mangleChar[Tdelegate] = 'D';
204 mangleChar[Tnone] = 'n';
205 mangleChar[Tvoid] = 'v';
206 mangleChar[Tint8] = 'g';
207 mangleChar[Tuns8] = 'h';
208 mangleChar[Tint16] = 's';
209 mangleChar[Tuns16] = 't';
210 mangleChar[Tint32] = 'i';
211 mangleChar[Tuns32] = 'k';
212 mangleChar[Tint64] = 'l';
213 mangleChar[Tuns64] = 'm';
214 mangleChar[Tfloat32] = 'f';
215 mangleChar[Tfloat64] = 'd';
216 mangleChar[Tfloat80] = 'e';
218 mangleChar[Timaginary32] = 'o';
219 mangleChar[Timaginary64] = 'p';
220 mangleChar[Timaginary80] = 'j';
221 mangleChar[Tcomplex32] = 'q';
222 mangleChar[Tcomplex64] = 'r';
223 mangleChar[Tcomplex80] = 'c';
225 mangleChar[Tbool] = 'b';
226 mangleChar[Tascii] = 'a';
227 mangleChar[Twchar] = 'u';
228 mangleChar[Tdchar] = 'w';
230 mangleChar[Tbit] = '@';
231 mangleChar[Tinstance] = '@';
232 mangleChar[Terror] = '@';
233 mangleChar[Ttypeof] = '@';
234 mangleChar[Ttuple] = 'B';
235 mangleChar[Tslice] = '@';
237 for (i = 0; i < TMAX; i++)
238 { if (!mangleChar[i])
239 fprintf(stdmsg, "ty = %d\n", i);
240 assert(mangleChar[i]);
243 // Set basic types
244 static TY basetab[] =
245 { Tvoid, Tint8, Tuns8, Tint16, Tuns16, Tint32, Tuns32, Tint64, Tuns64,
246 Tfloat32, Tfloat64, Tfloat80,
247 Timaginary32, Timaginary64, Timaginary80,
248 Tcomplex32, Tcomplex64, Tcomplex80,
249 Tbit, Tbool,
250 Tascii, Twchar, Tdchar };
252 for (i = 0; i < sizeof(basetab) / sizeof(basetab[0]); i++)
253 basic[basetab[i]] = new TypeBasic(basetab[i]);
254 basic[Terror] = basic[Tint32];
256 tvoidptr = tvoid->pointerTo();
258 if (global.params.isX86_64)
260 PTRSIZE = 8;
261 if (global.params.isLinux)
262 REALSIZE = 10;
263 else
264 REALSIZE = 8;
265 Tsize_t = Tuns64;
266 Tptrdiff_t = Tint64;
267 Tindex = Tint64;
269 else
271 PTRSIZE = 4;
272 #if TARGET_LINUX
273 REALSIZE = 12;
274 REALPAD = 2;
275 #else
276 REALSIZE = 10;
277 REALPAD = 0;
278 #endif
279 Tsize_t = Tuns32;
280 Tptrdiff_t = Tint32;
282 CLASSINFO_SIZE = 18 * PTRSIZE;
285 d_uns64 Type::size()
287 return size(0);
290 d_uns64 Type::size(Loc loc)
292 error(loc, "no size for type %s", toChars());
293 return 1;
296 unsigned Type::alignsize()
298 return size(0);
301 Type *Type::semantic(Loc loc, Scope *sc)
303 if (next)
304 next = next->semantic(loc,sc);
305 return merge();
308 Type *Type::maybe()
310 if (!mbe)
311 { Type *t;
313 t = new TypeMaybe(this);
314 mbe = t->merge();
316 return mbe;
319 Type *Type::pointerTo()
321 if (!pto)
322 { Type *t;
324 t = new TypePointer(this);
325 pto = t->merge();
327 return pto;
330 Type *Type::referenceTo()
332 if (!rto)
333 { Type *t;
335 t = new TypeReference(this);
336 rto = t->merge();
338 return rto;
341 Type *Type::arrayOf()
343 if (!arrayof)
344 { Type *t;
346 t = new TypeDArray(this);
347 arrayof = t->merge();
349 return arrayof;
352 Dsymbol *Type::toDsymbol(Scope *sc)
354 return NULL;
357 /*******************************
358 * If this is a shell around another type,
359 * get that other type.
362 Type *Type::toBasetype()
364 return this;
367 /********************************
368 * Name mangling.
371 void Type::toDecoBuffer(OutBuffer *buf)
373 buf->writeByte(mangleChar[ty]);
374 if (next)
376 assert(next != this);
377 //printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty);
378 next->toDecoBuffer(buf);
382 /********************************
383 * For pretty-printing a type.
386 char *Type::toChars()
387 { OutBuffer *buf;
388 HdrGenState hgs;
390 buf = new OutBuffer();
391 toCBuffer(buf, NULL, &hgs);
392 return buf->toChars();
395 void Type::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
397 toCBuffer2(buf, hgs, 0);
398 if (ident)
399 { buf->writeByte(' ');
400 buf->writestring(ident->toChars());
404 void Type::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
406 if (mod != this->mod)
407 { toCBuffer3(buf, hgs, mod);
408 return;
410 buf->writestring(toChars());
413 void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod)
415 if (mod != this->mod)
416 { char *p;
418 switch (this->mod)
420 case 0:
421 toCBuffer2(buf, hgs, this->mod);
422 break;
423 case MODconst:
424 p = "const(";
425 goto L1;
426 case MODinvariant:
427 p = "invariant(";
428 L1: buf->writestring(p);
429 toCBuffer2(buf, hgs, this->mod);
430 buf->writeByte(')');
431 break;
432 default:
433 assert(0);
439 /************************************
442 Type *Type::merge()
443 { Type *t;
445 //printf("merge(%s)\n", toChars());
446 t = this;
447 assert(t);
448 if (!deco)
450 OutBuffer buf;
451 StringValue *sv;
453 if (next)
454 next = next->merge();
455 toDecoBuffer(&buf);
456 sv = stringtable.update((char *)buf.data, buf.offset);
457 if (sv->ptrvalue)
458 { t = (Type *) sv->ptrvalue;
459 assert(t->deco);
460 //printf("old value, deco = '%s' %p\n", t->deco, t->deco);
462 else
464 sv->ptrvalue = this;
465 deco = sv->lstring.string;
466 //printf("new value, deco = '%s' %p\n", t->deco, t->deco);
469 return t;
472 int Type::isbit()
474 return FALSE;
477 int Type::isintegral()
479 return FALSE;
482 int Type::isfloating()
484 return FALSE;
487 int Type::isreal()
489 return FALSE;
492 int Type::isimaginary()
494 return FALSE;
497 int Type::iscomplex()
499 return FALSE;
502 int Type::isscalar()
504 return FALSE;
507 int Type::isunsigned()
509 return FALSE;
512 ClassDeclaration *Type::isClassHandle()
514 return NULL;
517 int Type::isauto()
519 return FALSE;
522 int Type::isString()
524 return FALSE;
527 int Type::checkBoolean()
529 return isscalar();
532 /*********************************
533 * Check type to see if it is based on a deprecated symbol.
536 void Type::checkDeprecated(Loc loc, Scope *sc)
538 Type *t;
539 Dsymbol *s;
541 for (t = this; t; t = t->next)
543 s = t->toDsymbol(sc);
544 if (s)
545 s->checkDeprecated(loc, sc);
550 Expression *Type::defaultInit(Loc loc)
552 #if LOGDEFAULTINIT
553 printf("Type::defaultInit() '%s'\n", toChars());
554 #endif
555 return NULL;
558 int Type::isZeroInit()
560 return 0; // assume not
563 int Type::isBaseOf(Type *t, target_ptrdiff_t *poffset)
565 return 0; // assume not
568 /********************************
569 * Determine if 'this' can be implicitly converted
570 * to type 'to'.
571 * Returns:
572 * 0 can't convert
573 * 1 can convert using implicit conversions
574 * 2 this and to are the same type
577 MATCH Type::implicitConvTo(Type *to)
579 //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to);
580 //printf("\tthis->next=%p, to->next=%p\n", this->next, to->next);
581 if (this == to)
582 return MATCHexact;
583 // if (to->ty == Tvoid)
584 // return 1;
585 return MATCHnomatch;
588 Expression *Type::getProperty(Loc loc, Identifier *ident)
589 { Expression *e;
591 #if LOGDOTEXP
592 printf("Type::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars());
593 #endif
594 if (ident == Id::__sizeof)
596 e = new IntegerExp(loc, size(loc), Type::tsize_t);
598 else if (ident == Id::size)
600 error(loc, ".size property should be replaced with .sizeof");
601 e = new IntegerExp(loc, size(loc), Type::tsize_t);
603 else if (ident == Id::alignof)
605 e = new IntegerExp(loc, alignsize(), Type::tsize_t);
607 else if (ident == Id::typeinfo)
609 if (!global.params.useDeprecated)
610 error(loc, ".typeinfo deprecated, use typeid(type)");
611 e = getTypeInfo(NULL);
613 else if (ident == Id::init)
615 if (ty == Tvoid)
616 error(loc, "void does not have an initializer");
617 e = defaultInit(loc);
619 else if (ident == Id::mangleof)
621 assert(deco);
622 e = new StringExp(loc, deco, strlen(deco), 'c');
623 Scope sc;
624 e = e->semantic(&sc);
626 else if (ident == Id::stringof)
627 { char *s = toChars();
628 e = new StringExp(loc, s, strlen(s), 'c');
629 Scope sc;
630 e = e->semantic(&sc);
632 else
634 error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars());
635 e = new IntegerExp(loc, 1, Type::tint32);
637 return e;
640 Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident)
641 { VarDeclaration *v = NULL;
643 #if LOGDOTEXP
644 printf("Type::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
645 #endif
646 if (e->op == TOKdotvar)
648 DotVarExp *dv = (DotVarExp *)e;
649 v = dv->var->isVarDeclaration();
651 else if (e->op == TOKvar)
653 VarExp *ve = (VarExp *)e;
654 v = ve->var->isVarDeclaration();
656 if (v)
658 if (ident == Id::offset)
660 if (!global.params.useDeprecated)
661 error(e->loc, ".offset deprecated, use .offsetof");
662 goto Loffset;
664 else if (ident == Id::offsetof)
666 Loffset:
667 if (v->storage_class & STCfield)
669 e = new IntegerExp(e->loc, v->offset, Type::tsize_t);
670 return e;
673 else if (ident == Id::init)
675 #if 0
676 if (v->init)
678 if (v->init->isVoidInitializer())
679 error(e->loc, "%s.init is void", v->toChars());
680 else
681 { Loc loc = e->loc;
682 e = v->init->toExpression();
683 if (e->op == TOKassign || e->op == TOKconstruct)
685 e = ((AssignExp *)e)->e2;
687 /* Take care of case where we used a 0
688 * to initialize the struct.
690 if (e->type == Type::tint32 &&
691 e->isBool(0) &&
692 v->type->toBasetype()->ty == Tstruct)
694 e = v->type->defaultInit(loc);
697 e = e->optimize(WANTvalue | WANTinterpret);
698 // if (!e->isConst())
699 // error(loc, ".init cannot be evaluated at compile time");
701 return e;
703 #endif
704 Expression *ex = defaultInit(e->loc);
705 return ex;
708 if (ident == Id::typeinfo)
710 if (!global.params.useDeprecated)
711 error(e->loc, ".typeinfo deprecated, use typeid(type)");
712 e = getTypeInfo(sc);
713 return e;
715 if (ident == Id::stringof)
716 { char *s = e->toChars();
717 e = new StringExp(e->loc, s, strlen(s), 'c');
718 Scope sc;
719 e = e->semantic(&sc);
720 return e;
722 return getProperty(e->loc, ident);
725 unsigned Type::memalign(unsigned salign)
727 return salign;
730 void Type::error(Loc loc, const char *format, ...)
732 va_list ap;
733 va_start(ap, format);
734 ::verror(loc, format, ap);
735 va_end( ap );
738 Identifier *Type::getTypeInfoIdent(int internal)
740 // _init_10TypeInfo_%s
741 OutBuffer buf;
742 Identifier *id;
743 char *name;
744 int len;
746 //toTypeInfoBuffer(&buf);
747 if (internal)
748 { buf.writeByte(mangleChar[ty]);
749 if (ty == Tarray)
750 buf.writeByte(mangleChar[next->ty]);
752 else
753 toDecoBuffer(&buf);
754 len = buf.offset;
755 name = (char *)alloca(19 + sizeof(len) * 3 + len + 1);
756 buf.writeByte(0);
757 sprintf(name, "_D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
758 if (global.params.isWindows)
759 name++; // C mangling will add it back in
760 //printf("name = %s\n", name);
761 id = Lexer::idPool(name);
762 return id;
765 TypeBasic *Type::isTypeBasic()
767 return NULL;
771 void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
773 Type *t;
775 t = semantic(loc, sc);
776 *pt = t;
777 *pe = NULL;
778 *ps = NULL;
781 /*******************************
782 * If one of the subtypes of this type is a TypeIdentifier,
783 * i.e. it's an unresolved type, return that type.
786 Type *Type::reliesOnTident()
788 if (!next)
789 return NULL;
790 else
791 return next->reliesOnTident();
794 /********************************
795 * We've mistakenly parsed this as a type.
796 * Redo it as an Expression.
797 * NULL if cannot.
800 Expression *Type::toExpression()
802 return NULL;
805 /***************************************
806 * Return !=0 if type has pointers that need to
807 * be scanned by the GC during a collection cycle.
810 int Type::hasPointers()
812 return FALSE;
815 /* ============================= TypeBasic =========================== */
817 TypeBasic::TypeBasic(TY ty)
818 : Type(ty, NULL)
819 { char *c;
820 char *d;
821 unsigned flags;
823 #define TFLAGSintegral 1
824 #define TFLAGSfloating 2
825 #define TFLAGSunsigned 4
826 #define TFLAGSreal 8
827 #define TFLAGSimaginary 0x10
828 #define TFLAGScomplex 0x20
830 flags = 0;
831 switch (ty)
833 case Tvoid: d = Token::toChars(TOKvoid);
834 c = "void";
835 break;
837 case Tint8: d = Token::toChars(TOKint8);
838 c = "byte";
839 flags |= TFLAGSintegral;
840 break;
842 case Tuns8: d = Token::toChars(TOKuns8);
843 c = "ubyte";
844 flags |= TFLAGSintegral | TFLAGSunsigned;
845 break;
847 case Tint16: d = Token::toChars(TOKint16);
848 c = "short";
849 flags |= TFLAGSintegral;
850 break;
852 case Tuns16: d = Token::toChars(TOKuns16);
853 c = "ushort";
854 flags |= TFLAGSintegral | TFLAGSunsigned;
855 break;
857 case Tint32: d = Token::toChars(TOKint32);
858 c = "int";
859 flags |= TFLAGSintegral;
860 break;
862 case Tuns32: d = Token::toChars(TOKuns32);
863 c = "uint";
864 flags |= TFLAGSintegral | TFLAGSunsigned;
865 break;
867 case Tfloat32: d = Token::toChars(TOKfloat32);
868 c = "float";
869 flags |= TFLAGSfloating | TFLAGSreal;
870 break;
872 case Tint64: d = Token::toChars(TOKint64);
873 c = "long";
874 flags |= TFLAGSintegral;
875 break;
877 case Tuns64: d = Token::toChars(TOKuns64);
878 c = "ulong";
879 flags |= TFLAGSintegral | TFLAGSunsigned;
880 break;
882 case Tfloat64: d = Token::toChars(TOKfloat64);
883 c = "double";
884 flags |= TFLAGSfloating | TFLAGSreal;
885 break;
887 case Tfloat80: d = Token::toChars(TOKfloat80);
888 c = "real";
889 flags |= TFLAGSfloating | TFLAGSreal;
890 break;
892 case Timaginary32: d = Token::toChars(TOKimaginary32);
893 c = "ifloat";
894 flags |= TFLAGSfloating | TFLAGSimaginary;
895 break;
897 case Timaginary64: d = Token::toChars(TOKimaginary64);
898 c = "idouble";
899 flags |= TFLAGSfloating | TFLAGSimaginary;
900 break;
902 case Timaginary80: d = Token::toChars(TOKimaginary80);
903 c = "ireal";
904 flags |= TFLAGSfloating | TFLAGSimaginary;
905 break;
907 case Tcomplex32: d = Token::toChars(TOKcomplex32);
908 c = "cfloat";
909 flags |= TFLAGSfloating | TFLAGScomplex;
910 break;
912 case Tcomplex64: d = Token::toChars(TOKcomplex64);
913 c = "cdouble";
914 flags |= TFLAGSfloating | TFLAGScomplex;
915 break;
917 case Tcomplex80: d = Token::toChars(TOKcomplex80);
918 c = "creal";
919 flags |= TFLAGSfloating | TFLAGScomplex;
920 break;
923 case Tbit: d = Token::toChars(TOKbit);
924 c = "bit";
925 flags |= TFLAGSintegral | TFLAGSunsigned;
926 break;
928 case Tbool: d = "bool";
929 c = d;
930 flags |= TFLAGSintegral | TFLAGSunsigned;
931 break;
933 case Tascii: d = Token::toChars(TOKchar);
934 c = "char";
935 flags |= TFLAGSintegral | TFLAGSunsigned;
936 break;
938 case Twchar: d = Token::toChars(TOKwchar);
939 c = "wchar";
940 flags |= TFLAGSintegral | TFLAGSunsigned;
941 break;
943 case Tdchar: d = Token::toChars(TOKdchar);
944 c = "dchar";
945 flags |= TFLAGSintegral | TFLAGSunsigned;
946 break;
948 default: assert(0);
950 this->dstring = d;
951 this->cstring = c;
952 this->flags = flags;
953 merge();
956 Type *TypeBasic::syntaxCopy()
958 // No semantic analysis done on basic types, no need to copy
959 return this;
963 char *TypeBasic::toChars()
965 return dstring;
968 void TypeBasic::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
970 //printf("TypeBasic::toCBuffer2(mod = %d, this->mod = %d)\n", mod, this->mod);
971 if (mod != this->mod)
972 { toCBuffer3(buf, hgs, mod);
973 return;
975 buf->writestring(dstring);
978 d_uns64 TypeBasic::size(Loc loc)
979 { unsigned size;
981 //printf("TypeBasic::size()\n");
982 switch (ty)
984 case Tint8:
985 case Tuns8: size = 1; break;
986 case Tint16:
987 case Tuns16: size = 2; break;
988 case Tint32:
989 case Tuns32:
990 case Tfloat32:
991 case Timaginary32:
992 size = 4; break;
993 case Tint64:
994 case Tuns64:
995 case Tfloat64:
996 case Timaginary64:
997 size = 8; break;
998 case Tfloat80:
999 case Timaginary80:
1000 size = REALSIZE; break;
1001 case Tcomplex32:
1002 size = 8; break;
1003 case Tcomplex64:
1004 size = 16; break;
1005 case Tcomplex80:
1006 size = REALSIZE * 2; break;
1008 case Tvoid:
1009 //size = Type::size(); // error message
1010 size = 1;
1011 break;
1013 case Tbit: size = 1; break;
1014 case Tbool: size = 1; break;
1015 case Tascii: size = 1; break;
1016 case Twchar: size = 2; break;
1017 case Tdchar: size = 4; break;
1019 default:
1020 assert(0);
1021 break;
1023 //printf("TypeBasic::size() = %d\n", size);
1024 return size;
1027 unsigned TypeBasic::alignsize()
1028 { unsigned sz;
1030 switch (ty)
1032 case Tfloat80:
1033 case Timaginary80:
1034 case Tcomplex80:
1035 sz = 2;
1036 break;
1038 default:
1039 sz = size(0);
1040 break;
1042 return sz;
1046 Expression *TypeBasic::getProperty(Loc loc, Identifier *ident)
1048 Expression *e;
1049 d_int64 ivalue;
1050 #ifdef IN_GCC
1051 real_t fvalue;
1052 #else
1053 d_float80 fvalue;
1054 #endif
1056 //printf("TypeBasic::getProperty('%s')\n", ident->toChars());
1057 if (ident == Id::max)
1059 switch (ty)
1061 case Tint8: ivalue = 0x7F; goto Livalue;
1062 case Tuns8: ivalue = 0xFF; goto Livalue;
1063 case Tint16: ivalue = 0x7FFFUL; goto Livalue;
1064 case Tuns16: ivalue = 0xFFFFUL; goto Livalue;
1065 case Tint32: ivalue = 0x7FFFFFFFUL; goto Livalue;
1066 case Tuns32: ivalue = 0xFFFFFFFFUL; goto Livalue;
1067 case Tint64: ivalue = 0x7FFFFFFFFFFFFFFFLL; goto Livalue;
1068 case Tuns64: ivalue = 0xFFFFFFFFFFFFFFFFULL; goto Livalue;
1069 case Tbit: ivalue = 1; goto Livalue;
1070 case Tbool: ivalue = 1; goto Livalue;
1071 case Tchar: ivalue = 0xFF; goto Livalue;
1072 case Twchar: ivalue = 0xFFFFUL; goto Livalue;
1073 case Tdchar: ivalue = 0x10FFFFUL; goto Livalue;
1075 case Tcomplex32:
1076 case Timaginary32:
1077 #ifdef IN_GCC
1078 // %% lazy, fix
1079 #define FLT_MAX real_t_properties[real_t::Float].maxval;
1080 #define DBL_MAX real_t_properties[real_t::Double].maxval;
1081 #define LDBL_MAX real_t_properties[real_t::LongDouble].maxval;
1082 #define FLT_MIN real_t_properties[real_t::Float].minval;
1083 #define DBL_MIN real_t_properties[real_t::Double].minval;
1084 #define LDBL_MIN real_t_properties[real_t::LongDouble].minval;
1085 #define FLT_DIG real_t_properties[real_t::Float].dig;
1086 #define DBL_DIG real_t_properties[real_t::Double].dig;
1087 #define LDBL_DIG real_t_properties[real_t::LongDouble].dig;
1088 #define FLT_MANT_DIG real_t_properties[real_t::Float].mant_dig;
1089 #define DBL_MANT_DIG real_t_properties[real_t::Double].mant_dig;
1090 #define LDBL_MANT_DIG real_t_properties[real_t::LongDouble].mant_dig;
1091 #define FLT_MAX_10_EXP real_t_properties[real_t::Float].max_10_exp;
1092 #define DBL_MAX_10_EXP real_t_properties[real_t::Double].max_10_exp;
1093 #define LDBL_MAX_10_EXP real_t_properties[real_t::LongDouble].max_10_exp;
1094 #define FLT_MIN_10_EXP real_t_properties[real_t::Float].min_10_exp;
1095 #define DBL_MIN_10_EXP real_t_properties[real_t::Double].min_10_exp;
1096 #define LDBL_MIN_10_EXP real_t_properties[real_t::LongDouble].min_10_exp;
1097 #define FLT_MAX_EXP real_t_properties[real_t::Float].max_exp;
1098 #define DBL_MAX_EXP real_t_properties[real_t::Double].max_exp;
1099 #define LDBL_MAX_EXP real_t_properties[real_t::LongDouble].max_exp;
1100 #define FLT_MIN_EXP real_t_properties[real_t::Float].min_exp;
1101 #define DBL_MIN_EXP real_t_properties[real_t::Double].min_exp;
1102 #define LDBL_MIN_EXP real_t_properties[real_t::LongDouble].min_exp;
1103 #define FLT_EPSILON real_t_properties[real_t::Float].epsilonval;
1104 #define DBL_EPSILON real_t_properties[real_t::Double].epsilonval;
1105 #define LDBL_EPSILON real_t_properties[real_t::LongDouble].epsilonval;
1108 #endif
1109 case Tfloat32: fvalue = FLT_MAX; goto Lfvalue;
1110 case Tcomplex64:
1111 case Timaginary64:
1112 case Tfloat64: fvalue = DBL_MAX; goto Lfvalue;
1113 case Tcomplex80:
1114 case Timaginary80:
1115 case Tfloat80: fvalue = LDBL_MAX; goto Lfvalue;
1118 else if (ident == Id::min)
1120 switch (ty)
1122 case Tint8: ivalue = -128; goto Livalue;
1123 case Tuns8: ivalue = 0; goto Livalue;
1124 case Tint16: ivalue = -32768; goto Livalue;
1125 case Tuns16: ivalue = 0; goto Livalue;
1126 case Tint32: ivalue = -2147483647L - 1; goto Livalue;
1127 case Tuns32: ivalue = 0; goto Livalue;
1128 case Tint64: ivalue = (-9223372036854775807LL-1LL); goto Livalue;
1129 case Tuns64: ivalue = 0; goto Livalue;
1130 case Tbit: ivalue = 0; goto Livalue;
1131 case Tbool: ivalue = 0; goto Livalue;
1132 case Tchar: ivalue = 0; goto Livalue;
1133 case Twchar: ivalue = 0; goto Livalue;
1134 case Tdchar: ivalue = 0; goto Livalue;
1136 case Tcomplex32:
1137 case Timaginary32:
1138 case Tfloat32: fvalue = FLT_MIN; goto Lfvalue;
1139 case Tcomplex64:
1140 case Timaginary64:
1141 case Tfloat64: fvalue = DBL_MIN; goto Lfvalue;
1142 case Tcomplex80:
1143 case Timaginary80:
1144 case Tfloat80: fvalue = LDBL_MIN; goto Lfvalue;
1147 else if (ident == Id::nan)
1149 switch (ty)
1151 case Tcomplex32:
1152 case Tcomplex64:
1153 case Tcomplex80:
1154 case Timaginary32:
1155 case Timaginary64:
1156 case Timaginary80:
1157 case Tfloat32:
1158 case Tfloat64:
1159 case Tfloat80:
1161 #if IN_GCC
1162 // mode doesn't matter, will be converted in RealExp anyway
1163 fvalue = real_t::getnan(real_t::LongDouble);
1164 #elif __GNUC__
1165 // gcc nan's have the sign bit set by default, so turn it off
1166 // Need the volatile to prevent gcc from doing incorrect
1167 // constant folding.
1168 volatile d_float80 foo;
1169 foo = NAN;
1170 if (signbit(foo)) // signbit sometimes, not always, set
1171 foo = -foo; // turn off sign bit
1172 fvalue = foo;
1173 #elif _MSC_VER
1174 unsigned long nan[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
1175 fvalue = *(double*)nan;
1176 #else
1177 fvalue = NAN;
1178 #endif
1179 goto Lfvalue;
1183 else if (ident == Id::infinity)
1185 switch (ty)
1187 case Tcomplex32:
1188 case Tcomplex64:
1189 case Tcomplex80:
1190 case Timaginary32:
1191 case Timaginary64:
1192 case Timaginary80:
1193 case Tfloat32:
1194 case Tfloat64:
1195 case Tfloat80:
1196 #if IN_GCC
1197 fvalue = real_t::getinfinity();
1198 #elif __GNUC__
1199 fvalue = 1 / zero;
1200 #elif _MSC_VER
1201 fvalue = std::numeric_limits<long double>::infinity();
1202 #else
1203 fvalue = INFINITY;
1204 #endif
1205 goto Lfvalue;
1208 else if (ident == Id::dig)
1210 switch (ty)
1212 case Tcomplex32:
1213 case Timaginary32:
1214 case Tfloat32: ivalue = FLT_DIG; goto Lint;
1215 case Tcomplex64:
1216 case Timaginary64:
1217 case Tfloat64: ivalue = DBL_DIG; goto Lint;
1218 case Tcomplex80:
1219 case Timaginary80:
1220 case Tfloat80: ivalue = LDBL_DIG; goto Lint;
1223 else if (ident == Id::epsilon)
1225 switch (ty)
1227 case Tcomplex32:
1228 case Timaginary32:
1229 case Tfloat32: fvalue = FLT_EPSILON; goto Lfvalue;
1230 case Tcomplex64:
1231 case Timaginary64:
1232 case Tfloat64: fvalue = DBL_EPSILON; goto Lfvalue;
1233 case Tcomplex80:
1234 case Timaginary80:
1235 case Tfloat80: fvalue = LDBL_EPSILON; goto Lfvalue;
1238 else if (ident == Id::mant_dig)
1240 switch (ty)
1242 case Tcomplex32:
1243 case Timaginary32:
1244 case Tfloat32: ivalue = FLT_MANT_DIG; goto Lint;
1245 case Tcomplex64:
1246 case Timaginary64:
1247 case Tfloat64: ivalue = DBL_MANT_DIG; goto Lint;
1248 case Tcomplex80:
1249 case Timaginary80:
1250 case Tfloat80: ivalue = LDBL_MANT_DIG; goto Lint;
1253 else if (ident == Id::max_10_exp)
1255 switch (ty)
1257 case Tcomplex32:
1258 case Timaginary32:
1259 case Tfloat32: ivalue = FLT_MAX_10_EXP; goto Lint;
1260 case Tcomplex64:
1261 case Timaginary64:
1262 case Tfloat64: ivalue = DBL_MAX_10_EXP; goto Lint;
1263 case Tcomplex80:
1264 case Timaginary80:
1265 case Tfloat80: ivalue = LDBL_MAX_10_EXP; goto Lint;
1268 else if (ident == Id::max_exp)
1270 switch (ty)
1272 case Tcomplex32:
1273 case Timaginary32:
1274 case Tfloat32: ivalue = FLT_MAX_EXP; goto Lint;
1275 case Tcomplex64:
1276 case Timaginary64:
1277 case Tfloat64: ivalue = DBL_MAX_EXP; goto Lint;
1278 case Tcomplex80:
1279 case Timaginary80:
1280 case Tfloat80: ivalue = LDBL_MAX_EXP; goto Lint;
1283 else if (ident == Id::min_10_exp)
1285 switch (ty)
1287 case Tcomplex32:
1288 case Timaginary32:
1289 case Tfloat32: ivalue = FLT_MIN_10_EXP; goto Lint;
1290 case Tcomplex64:
1291 case Timaginary64:
1292 case Tfloat64: ivalue = DBL_MIN_10_EXP; goto Lint;
1293 case Tcomplex80:
1294 case Timaginary80:
1295 case Tfloat80: ivalue = LDBL_MIN_10_EXP; goto Lint;
1298 else if (ident == Id::min_exp)
1300 switch (ty)
1302 case Tcomplex32:
1303 case Timaginary32:
1304 case Tfloat32: ivalue = FLT_MIN_EXP; goto Lint;
1305 case Tcomplex64:
1306 case Timaginary64:
1307 case Tfloat64: ivalue = DBL_MIN_EXP; goto Lint;
1308 case Tcomplex80:
1309 case Timaginary80:
1310 case Tfloat80: ivalue = LDBL_MIN_EXP; goto Lint;
1314 Ldefault:
1315 return Type::getProperty(loc, ident);
1317 Livalue:
1318 e = new IntegerExp(loc, ivalue, this);
1319 return e;
1321 Lfvalue:
1322 if (isreal() || isimaginary())
1323 e = new RealExp(loc, fvalue, this);
1324 else
1326 complex_t cvalue;
1328 #if __DMC__
1329 //((real_t *)&cvalue)[0] = fvalue;
1330 //((real_t *)&cvalue)[1] = fvalue;
1331 cvalue = fvalue + fvalue * I;
1332 #else
1333 cvalue.re = fvalue;
1334 cvalue.im = fvalue;
1335 #endif
1336 //for (int i = 0; i < 20; i++)
1337 // printf("%02x ", ((unsigned char *)&cvalue)[i]);
1338 //printf("\n");
1339 e = new ComplexExp(loc, cvalue, this);
1341 return e;
1343 Lint:
1344 e = new IntegerExp(loc, ivalue, Type::tint32);
1345 return e;
1348 Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
1350 #if LOGDOTEXP
1351 printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1352 #endif
1353 Type *t;
1355 if (ident == Id::re)
1357 switch (ty)
1359 case Tcomplex32: t = tfloat32; goto L1;
1360 case Tcomplex64: t = tfloat64; goto L1;
1361 case Tcomplex80: t = tfloat80; goto L1;
1363 e = e->castTo(sc, t);
1364 break;
1366 case Tfloat32:
1367 case Tfloat64:
1368 case Tfloat80:
1369 break;
1371 case Timaginary32: t = tfloat32; goto L2;
1372 case Timaginary64: t = tfloat64; goto L2;
1373 case Timaginary80: t = tfloat80; goto L2;
1375 e = new RealExp(0, 0, t);
1376 break;
1378 default:
1379 return Type::getProperty(e->loc, ident);
1382 else if (ident == Id::im)
1383 { Type *t2;
1385 switch (ty)
1387 case Tcomplex32: t = timaginary32; t2 = tfloat32; goto L3;
1388 case Tcomplex64: t = timaginary64; t2 = tfloat64; goto L3;
1389 case Tcomplex80: t = timaginary80; t2 = tfloat80; goto L3;
1391 e = e->castTo(sc, t);
1392 e->type = t2;
1393 break;
1395 case Timaginary32: t = tfloat32; goto L4;
1396 case Timaginary64: t = tfloat64; goto L4;
1397 case Timaginary80: t = tfloat80; goto L4;
1399 e->type = t;
1400 break;
1402 case Tfloat32:
1403 case Tfloat64:
1404 case Tfloat80:
1405 e = new RealExp(0, 0, this);
1406 break;
1408 default:
1409 return Type::getProperty(e->loc, ident);
1412 else
1414 return Type::dotExp(sc, e, ident);
1416 return e;
1419 Expression *TypeBasic::defaultInit(Loc loc)
1420 { integer_t value = 0;
1422 #if LOGDEFAULTINIT
1423 printf("TypeBasic::defaultInit() '%s'\n", toChars());
1424 #endif
1425 switch (ty)
1427 case Tchar:
1428 value = 0xFF;
1429 break;
1431 case Twchar:
1432 case Tdchar:
1433 value = 0xFFFF;
1434 break;
1436 case Timaginary32:
1437 case Timaginary64:
1438 case Timaginary80:
1439 case Tfloat32:
1440 case Tfloat64:
1441 case Tfloat80:
1442 case Tcomplex32:
1443 case Tcomplex64:
1444 case Tcomplex80:
1445 return getProperty(loc, Id::nan);
1447 return new IntegerExp(loc, value, this);
1450 int TypeBasic::isZeroInit()
1452 switch (ty)
1454 case Tchar:
1455 case Twchar:
1456 case Tdchar:
1457 case Timaginary32:
1458 case Timaginary64:
1459 case Timaginary80:
1460 case Tfloat32:
1461 case Tfloat64:
1462 case Tfloat80:
1463 case Tcomplex32:
1464 case Tcomplex64:
1465 case Tcomplex80:
1466 return 0; // no
1468 return 1; // yes
1471 int TypeBasic::isbit()
1473 return (ty == Tbit);
1476 int TypeBasic::isintegral()
1478 //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags);
1479 return flags & TFLAGSintegral;
1482 int TypeBasic::isfloating()
1484 return flags & TFLAGSfloating;
1487 int TypeBasic::isreal()
1489 return flags & TFLAGSreal;
1492 int TypeBasic::isimaginary()
1494 return flags & TFLAGSimaginary;
1497 int TypeBasic::iscomplex()
1499 return flags & TFLAGScomplex;
1502 int TypeBasic::isunsigned()
1504 return flags & TFLAGSunsigned;
1507 int TypeBasic::isscalar()
1509 return flags & (TFLAGSintegral | TFLAGSfloating);
1512 MATCH TypeBasic::implicitConvTo(Type *to)
1514 //printf("TypeBasic::implicitConvTo(%s) from %s\n", to->toChars(), toChars());
1515 if (this == to)
1516 return MATCHexact;
1518 if (ty == Tvoid || to->ty == Tvoid)
1519 return MATCHnomatch;
1520 if (1 || global.params.Dversion == 1)
1522 if (to->ty == Tbool)
1523 return MATCHnomatch;
1525 else
1527 if (ty == Tbool || to->ty == Tbool)
1528 return MATCHnomatch;
1530 if (!to->isTypeBasic())
1531 return MATCHnomatch;
1533 TypeBasic *tob = (TypeBasic *)to;
1534 if (flags & TFLAGSintegral)
1536 // Disallow implicit conversion of integers to imaginary or complex
1537 if (tob->flags & (TFLAGSimaginary | TFLAGScomplex))
1538 return MATCHnomatch;
1540 // If converting to integral
1541 if (0 && global.params.Dversion > 1 && tob->flags & TFLAGSintegral)
1542 { d_uns64 sz = size(0);
1543 d_uns64 tosz = tob->size(0);
1545 /* Can't convert to smaller size or, if same size, change sign
1547 if (sz > tosz)
1548 return MATCHnomatch;
1550 /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned)
1551 return MATCHnomatch;*/
1554 else if (flags & TFLAGSfloating)
1556 // Disallow implicit conversion of floating point to integer
1557 if (tob->flags & TFLAGSintegral)
1558 return MATCHnomatch;
1560 assert(tob->flags & TFLAGSfloating);
1562 // Disallow implicit conversion from complex to non-complex
1563 if (flags & TFLAGScomplex && !(tob->flags & TFLAGScomplex))
1564 return MATCHnomatch;
1566 // Disallow implicit conversion of real or imaginary to complex
1567 if (flags & (TFLAGSreal | TFLAGSimaginary) &&
1568 tob->flags & TFLAGScomplex)
1569 return MATCHnomatch;
1571 // Disallow implicit conversion to-from real and imaginary
1572 if ((flags & (TFLAGSreal | TFLAGSimaginary)) !=
1573 (tob->flags & (TFLAGSreal | TFLAGSimaginary)))
1574 return MATCHnomatch;
1576 return MATCHconvert;
1579 TypeBasic *TypeBasic::isTypeBasic()
1581 return (TypeBasic *)this;
1584 /***************************** TypeArray *****************************/
1586 TypeArray::TypeArray(TY ty, Type *next)
1587 : Type(ty, next)
1591 Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
1593 Type *n = this->next->toBasetype(); // uncover any typedef's
1595 #if LOGDOTEXP
1596 printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1597 #endif
1598 if (ident == Id::reverse && (n->ty == Tchar || n->ty == Twchar))
1600 Expression *ec;
1601 FuncDeclaration *fd;
1602 Expressions *arguments;
1603 char *nm;
1604 static char *name[2] = { "_adReverseChar", "_adReverseWchar" };
1606 nm = name[n->ty == Twchar];
1607 fd = FuncDeclaration::genCfunc(next->arrayOf(), nm, Type::tvoid->arrayOf());
1608 ec = new VarExp(0, fd);
1609 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1610 arguments = new Expressions();
1611 arguments->push(e);
1612 e = new CallExp(e->loc, ec, arguments);
1613 e->type = next->arrayOf();
1615 else if (ident == Id::sort && (n->ty == Tchar || n->ty == Twchar))
1617 Expression *ec;
1618 FuncDeclaration *fd;
1619 Expressions *arguments;
1620 char *nm;
1621 static char *name[2] = { "_adSortChar", "_adSortWchar" };
1623 nm = name[n->ty == Twchar];
1624 fd = FuncDeclaration::genCfunc(next->arrayOf(), nm, Type::tvoid->arrayOf());
1625 ec = new VarExp(0, fd);
1626 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1627 arguments = new Expressions();
1628 arguments->push(e);
1629 e = new CallExp(e->loc, ec, arguments);
1630 e->type = next->arrayOf();
1632 else if (ident == Id::reverse || ident == Id::dup)
1634 Expression *ec;
1635 FuncDeclaration *fd;
1636 Expressions *arguments;
1637 target_size_t size = next->size(e->loc);
1638 int dup;
1640 assert(size);
1641 dup = (ident == Id::dup);
1642 if (dup)
1643 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::adDup,
1644 Type::typeinfo->type, Type::tvoid->arrayOf());
1645 else
1646 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::adReverse,
1647 Type::tvoid->arrayOf(), Type::tsize_t);
1648 ec = new VarExp(0, fd);
1649 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1650 arguments = new Expressions();
1651 if (dup)
1652 arguments->push(getTypeInfo(sc));
1653 arguments->push(e);
1654 if (!dup)
1655 arguments->push(new IntegerExp(0, size, Type::tsize_t));
1656 e = new CallExp(e->loc, ec, arguments);
1657 e->type = next->arrayOf();
1659 else if (ident == Id::sort)
1661 Expression *ec;
1662 FuncDeclaration *fd;
1663 Expressions *arguments;
1665 fd = FuncDeclaration::genCfunc(tint32->arrayOf(),
1666 (char*)(n->ty == Tbit ? "_adSortBit" : "_adSort"),
1667 Type::tvoid->arrayOf(),
1668 n->ty == Tbit ? NULL : Type::tvoid->pointerTo());
1669 ec = new VarExp(0, fd);
1670 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1671 arguments = new Expressions();
1672 arguments->push(e);
1673 if (next->ty != Tbit)
1674 arguments->push(n->ty == Tsarray
1675 ? n->getTypeInfo(sc) // don't convert to dynamic array
1676 : n->getInternalTypeInfo(sc));
1677 e = new CallExp(e->loc, ec, arguments);
1678 e->type = next->arrayOf();
1680 else
1682 e = Type::dotExp(sc, e, ident);
1684 return e;
1688 /***************************** TypeSArray *****************************/
1690 TypeSArray::TypeSArray(Type *t, Expression *dim)
1691 : TypeArray(Tsarray, t)
1693 //printf("TypeSArray(%s)\n", dim->toChars());
1694 this->dim = dim;
1697 Type *TypeSArray::syntaxCopy()
1699 Type *t = next->syntaxCopy();
1700 Expression *e = dim->syntaxCopy();
1701 t = new TypeSArray(t, e);
1702 return t;
1705 d_uns64 TypeSArray::size(Loc loc)
1706 { integer_t sz;
1708 if (!dim)
1709 return Type::size(loc);
1710 sz = dim->toInteger();
1711 if (next->toBasetype()->ty == Tbit) // if array of bits
1713 if (sz + 31 < sz)
1714 goto Loverflow;
1715 sz = ((sz + 31) & ~31) / 8; // size in bytes, rounded up to 32 bit dwords
1717 else
1718 { integer_t n, n2;
1720 n = next->size();
1721 n2 = n * sz;
1722 if (n && (n2 / n) != sz)
1723 goto Loverflow;
1724 sz = n2;
1726 return sz;
1728 Loverflow:
1729 error(loc, "index %"PRIdMAX" overflow for static array", sz);
1730 return 1;
1733 unsigned TypeSArray::alignsize()
1735 return next->alignsize();
1738 /**************************
1739 * This evaluates exp while setting length to be the number
1740 * of elements in the tuple t.
1742 Expression *semanticLength(Scope *sc, Type *t, Expression *exp)
1744 if (t->ty == Ttuple)
1745 { ScopeDsymbol *sym = new ArrayScopeSymbol((TypeTuple *)t);
1746 sym->parent = sc->scopesym;
1747 sc = sc->push(sym);
1749 exp = exp->semantic(sc);
1751 sc->pop();
1753 else
1754 exp = exp->semantic(sc);
1755 return exp;
1758 Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp)
1760 ScopeDsymbol *sym = new ArrayScopeSymbol(s);
1761 sym->parent = sc->scopesym;
1762 sc = sc->push(sym);
1764 exp = exp->semantic(sc);
1766 sc->pop();
1767 return exp;
1770 void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
1772 //printf("TypeSArray::resolve() %s\n", toChars());
1773 next->resolve(loc, sc, pe, pt, ps);
1774 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
1775 if (*pe)
1776 { // It's really an index expression
1777 Expression *e;
1778 e = new IndexExp(loc, *pe, dim);
1779 *pe = e;
1781 else if (*ps)
1782 { Dsymbol *s = *ps;
1783 TupleDeclaration *td = s->isTupleDeclaration();
1784 if (td)
1786 ScopeDsymbol *sym = new ArrayScopeSymbol(td);
1787 sym->parent = sc->scopesym;
1788 sc = sc->push(sym);
1790 dim = dim->semantic(sc);
1791 dim = dim->optimize(WANTvalue | WANTinterpret);
1792 uinteger_t d = dim->toUInteger();
1794 sc = sc->pop();
1796 if (d >= td->objects->dim)
1797 { error(loc, "tuple index %"PRIuMAX" exceeds %u", d, td->objects->dim);
1798 goto Ldefault;
1800 Object *o = (Object *)td->objects->data[(size_t)d];
1801 if (o->dyncast() == DYNCAST_DSYMBOL)
1803 *ps = (Dsymbol *)o;
1804 return;
1806 if (o->dyncast() == DYNCAST_EXPRESSION)
1808 *ps = NULL;
1809 *pe = (Expression *)o;
1810 return;
1813 /* Create a new TupleDeclaration which
1814 * is a slice [d..d+1] out of the old one.
1815 * Do it this way because TemplateInstance::semanticTiargs()
1816 * can handle unresolved Objects this way.
1818 Objects *objects = new Objects;
1819 objects->setDim(1);
1820 objects->data[0] = o;
1822 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
1823 *ps = tds;
1825 else
1826 goto Ldefault;
1828 else
1830 Ldefault:
1831 Type::resolve(loc, sc, pe, pt, ps);
1835 Type *TypeSArray::semantic(Loc loc, Scope *sc)
1837 //printf("TypeSArray::semantic() %s\n", toChars());
1839 Type *t;
1840 Expression *e;
1841 Dsymbol *s;
1842 next->resolve(loc, sc, &e, &t, &s);
1843 if (dim && s && s->isTupleDeclaration())
1844 { TupleDeclaration *sd = s->isTupleDeclaration();
1846 dim = semanticLength(sc, sd, dim);
1847 dim = dim->optimize(WANTvalue | WANTinterpret);
1848 uinteger_t d = dim->toUInteger();
1850 if (d >= sd->objects->dim)
1851 { error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim);
1852 return Type::terror;
1854 Object *o = (Object *)sd->objects->data[(size_t)d];
1855 if (o->dyncast() != DYNCAST_TYPE)
1856 { error(loc, "%s is not a type", toChars());
1857 return Type::terror;
1859 t = (Type *)o;
1860 return t;
1863 next = next->semantic(loc,sc);
1864 Type *tbn = next->toBasetype();
1866 if (dim)
1867 { integer_t n, n2;
1869 dim = semanticLength(sc, tbn, dim);
1871 dim = dim->optimize(WANTvalue | WANTinterpret);
1872 if (sc->parameterSpecialization && dim->op == TOKvar &&
1873 ((VarExp *)dim)->var->storage_class & STCtemplateparameter)
1875 /* It could be a template parameter N which has no value yet:
1876 * template Foo(T : T[N], size_t N);
1878 return this;
1880 integer_t d1 = dim->toInteger();
1881 dim = dim->castTo(sc, tsize_t);
1882 dim = dim->optimize(WANTvalue);
1883 integer_t d2 = dim->toInteger();
1885 if (d1 != d2)
1886 goto Loverflow;
1888 if (tbn->isintegral() ||
1889 tbn->isfloating() ||
1890 tbn->ty == Tpointer ||
1891 tbn->ty == Tarray ||
1892 tbn->ty == Tsarray ||
1893 tbn->ty == Taarray ||
1894 tbn->ty == Tclass)
1896 /* Only do this for types that don't need to have semantic()
1897 * run on them for the size, since they may be forward referenced.
1899 n = tbn->size(loc);
1900 n2 = n * d2;
1901 if ((int)n2 < 0)
1902 goto Loverflow;
1903 if (n2 >= 0x1000000) // put a 'reasonable' limit on it
1904 goto Loverflow;
1905 if (n && n2 / n != d2)
1907 Loverflow:
1908 error(loc, "index %"PRIdMAX" overflow for static array", d1);
1909 dim = new IntegerExp(0, 1, tsize_t);
1913 switch (tbn->ty)
1915 case Ttuple:
1916 { // Index the tuple to get the type
1917 assert(dim);
1918 TypeTuple *tt = (TypeTuple *)tbn;
1919 uinteger_t d = dim->toUInteger();
1921 if (d >= tt->arguments->dim)
1922 { error(loc, "tuple index %"PRIuMAX" exceeds %u", d, tt->arguments->dim);
1923 return Type::terror;
1925 Argument *arg = (Argument *)tt->arguments->data[(size_t)d];
1926 return arg->type;
1928 case Tfunction:
1929 case Tnone:
1930 error(loc, "can't have array of %s", tbn->toChars());
1931 tbn = next = tint32;
1932 break;
1934 if (tbn->isauto())
1935 error(loc, "cannot have array of auto %s", tbn->toChars());
1936 return merge();
1939 void TypeSArray::toDecoBuffer(OutBuffer *buf)
1941 buf->writeByte(mangleChar[ty]);
1942 if (dim)
1943 buf->printf("%"PRIuMAX, dim->toInteger());
1944 if (next)
1945 next->toDecoBuffer(buf);
1948 void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
1950 if (mod != this->mod)
1951 { toCBuffer3(buf, hgs, mod);
1952 return;
1954 next->toCBuffer2(buf, hgs, this->mod);
1955 buf->printf("[%s]", dim->toChars());
1958 Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
1960 #if LOGDOTEXP
1961 printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1962 #endif
1963 if (ident == Id::length)
1965 e = dim;
1967 else if (ident == Id::ptr)
1969 e = e->castTo(sc, next->pointerTo());
1971 else
1973 e = TypeArray::dotExp(sc, e, ident);
1975 return e;
1978 int TypeSArray::isString()
1980 TY nty = next->toBasetype()->ty;
1981 return nty == Tchar || nty == Twchar || nty == Tdchar;
1984 unsigned TypeSArray::memalign(unsigned salign)
1986 return next->memalign(salign);
1989 MATCH TypeSArray::implicitConvTo(Type *to)
1991 //printf("TypeSArray::implicitConvTo()\n");
1993 // Allow implicit conversion of static array to pointer or dynamic array
1994 if ((IMPLICIT_ARRAY_TO_PTR && to->ty == Tpointer) &&
1995 (to->next->ty == Tvoid || next->equals(to->next)
1996 /*|| to->next->isBaseOf(next)*/))
1998 return MATCHconvert;
2000 if (to->ty == Tarray)
2001 { target_ptrdiff_t offset = 0;
2003 if (next->equals(to->next) ||
2004 (to->next->isBaseOf(next, &offset) && offset == 0) ||
2005 to->next->ty == Tvoid)
2006 return MATCHconvert;
2008 #if 0
2009 if (to->ty == Tsarray)
2011 TypeSArray *tsa = (TypeSArray *)to;
2013 if (next->equals(tsa->next) && dim->equals(tsa->dim))
2015 return MATCHconvert;
2018 #endif
2019 return Type::implicitConvTo(to);
2022 Expression *TypeSArray::defaultInit(Loc loc)
2024 #if LOGDEFAULTINIT
2025 printf("TypeSArray::defaultInit() '%s'\n", toChars());
2026 #endif
2027 return next->defaultInit(loc);
2030 int TypeSArray::isZeroInit()
2032 return next->isZeroInit();
2036 Expression *TypeSArray::toExpression()
2038 Expression *e = next->toExpression();
2039 if (e)
2040 { Expressions *arguments = new Expressions();
2041 arguments->push(dim);
2042 e = new ArrayExp(dim->loc, e, arguments);
2044 return e;
2047 int TypeSArray::hasPointers()
2049 return next->hasPointers();
2052 /***************************** TypeDArray *****************************/
2054 TypeDArray::TypeDArray(Type *t)
2055 : TypeArray(Tarray, t)
2057 //printf("TypeDArray(t = %p)\n", t);
2060 Type *TypeDArray::syntaxCopy()
2062 Type *t = next->syntaxCopy();
2063 if (t == next)
2064 t = this;
2065 else
2066 t = new TypeDArray(t);
2067 return t;
2070 d_uns64 TypeDArray::size(Loc loc)
2072 //printf("TypeDArray::size()\n");
2073 return PTRSIZE * 2;
2076 unsigned TypeDArray::alignsize()
2078 // A DArray consists of two ptr-sized values, so align it on pointer size
2079 // boundary
2080 return PTRSIZE;
2083 Type *TypeDArray::semantic(Loc loc, Scope *sc)
2084 { Type *tn = next;
2086 tn = next->semantic(loc,sc);
2087 Type *tbn = tn->toBasetype();
2088 switch (tbn->ty)
2090 case Tfunction:
2091 case Tnone:
2092 case Ttuple:
2093 error(loc, "can't have array of %s", tbn->toChars());
2094 tn = next = tint32;
2095 break;
2097 if (tn->isauto())
2098 error(loc, "cannot have array of auto %s", tn->toChars());
2099 if (next != tn)
2100 //deco = NULL; // redo
2101 return tn->arrayOf();
2102 return merge();
2105 void TypeDArray::toDecoBuffer(OutBuffer *buf)
2107 buf->writeByte(mangleChar[ty]);
2108 if (next)
2109 next->toDecoBuffer(buf);
2112 void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2114 if (mod != this->mod)
2115 { toCBuffer3(buf, hgs, mod);
2116 return;
2118 next->toCBuffer2(buf, hgs, this->mod);
2119 buf->writestring("[]");
2122 Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
2124 #if LOGDOTEXP
2125 printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2126 #endif
2127 if (ident == Id::length)
2129 if (e->op == TOKstring)
2130 { StringExp *se = (StringExp *)e;
2132 return new IntegerExp(se->loc, se->len, Type::tindex);
2134 e = new ArrayLengthExp(e->loc, e);
2135 e->type = Type::tsize_t;
2136 return e;
2138 else if (ident == Id::ptr)
2140 e = e->castTo(sc, next->pointerTo());
2141 return e;
2143 else
2145 e = TypeArray::dotExp(sc, e, ident);
2147 return e;
2150 int TypeDArray::isString()
2152 TY nty = next->toBasetype()->ty;
2153 return nty == Tchar || nty == Twchar || nty == Tdchar;
2156 MATCH TypeDArray::implicitConvTo(Type *to)
2158 //printf("TypeDArray::implicitConvTo()\n");
2160 // Allow implicit conversion of array to pointer
2161 if (IMPLICIT_ARRAY_TO_PTR &&
2162 to->ty == Tpointer &&
2163 (to->next->ty == Tvoid || next->equals(to->next) /*|| to->next->isBaseOf(next)*/))
2165 return MATCHconvert;
2168 if (to->ty == Tarray)
2169 { target_ptrdiff_t offset = 0;
2171 if ((to->next->isBaseOf(next, &offset) && offset == 0) ||
2172 to->next->ty == Tvoid)
2173 return MATCHconvert;
2175 return Type::implicitConvTo(to);
2178 Expression *TypeDArray::defaultInit(Loc loc)
2180 #if LOGDEFAULTINIT
2181 printf("TypeDArray::defaultInit() '%s'\n", toChars());
2182 #endif
2183 Expression *e;
2184 e = new NullExp(loc);
2185 e->type = this;
2186 return e;
2189 int TypeDArray::isZeroInit()
2191 return 1;
2194 int TypeDArray::checkBoolean()
2196 return TRUE;
2199 int TypeDArray::hasPointers()
2201 return TRUE;
2204 /***************************** TypeAArray *****************************/
2206 TypeAArray::TypeAArray(Type *t, Type *index)
2207 : TypeArray(Taarray, t)
2209 this->index = index;
2210 this->key = NULL;
2213 Type *TypeAArray::syntaxCopy()
2215 Type *t = next->syntaxCopy();
2216 Type *ti = index->syntaxCopy();
2217 if (t == next && ti == index)
2218 t = this;
2219 else
2220 t = new TypeAArray(t, ti);
2221 return t;
2224 d_uns64 TypeAArray::size(Loc loc)
2226 return PTRSIZE /* * 2*/;
2230 Type *TypeAArray::semantic(Loc loc, Scope *sc)
2232 //printf("TypeAArray::semantic() %s index->ty = %d\n", toChars(), index->ty);
2234 // Deal with the case where we thought the index was a type, but
2235 // in reality it was an expression.
2236 if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray)
2238 Expression *e;
2239 Type *t;
2240 Dsymbol *s;
2242 index->resolve(loc, sc, &e, &t, &s);
2243 if (e)
2244 { // It was an expression -
2245 // Rewrite as a static array
2246 TypeSArray *tsa;
2248 tsa = new TypeSArray(next, e);
2249 return tsa->semantic(loc,sc);
2251 else if (t)
2252 index = t;
2253 else
2254 index->error(loc, "index is not a type or an expression");
2256 else
2257 index = index->semantic(loc,sc);
2259 // Compute key type; the purpose of the key type is to
2260 // minimize the permutations of runtime library
2261 // routines as much as possible.
2262 key = index->toBasetype();
2263 switch (key->ty)
2265 #if 0
2266 case Tint8:
2267 case Tuns8:
2268 case Tint16:
2269 case Tuns16:
2270 key = tint32;
2271 break;
2272 #endif
2274 case Tsarray:
2275 #if 0
2276 // Convert to Tarray
2277 key = key->next->arrayOf();
2278 #endif
2279 break;
2280 case Tbit:
2281 case Tbool:
2282 case Tfunction:
2283 case Tvoid:
2284 case Tnone:
2285 error(loc, "can't have associative array key of %s", key->toChars());
2286 break;
2288 next = next->semantic(loc,sc);
2289 switch (next->toBasetype()->ty)
2291 case Tfunction:
2292 case Tnone:
2293 error(loc, "can't have associative array of %s", next->toChars());
2294 break;
2296 if (next->isauto())
2297 error(loc, "cannot have array of auto %s", next->toChars());
2299 return merge();
2302 void TypeAArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
2304 //printf("TypeAArray::resolve() %s\n", toChars());
2306 // Deal with the case where we thought the index was a type, but
2307 // in reality it was an expression.
2308 if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray)
2310 Expression *e;
2311 Type *t;
2312 Dsymbol *s;
2314 index->resolve(loc, sc, &e, &t, &s);
2315 if (e)
2316 { // It was an expression -
2317 // Rewrite as a static array
2319 TypeSArray *tsa = new TypeSArray(next, e);
2320 return tsa->resolve(loc, sc, pe, pt, ps);
2322 else if (t)
2323 index = t;
2324 else
2325 index->error(loc, "index is not a type or an expression");
2327 Type::resolve(loc, sc, pe, pt, ps);
2331 Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
2333 #if LOGDOTEXP
2334 printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2335 #endif
2336 if (ident == Id::length)
2338 Expression *ec;
2339 FuncDeclaration *fd;
2340 Expressions *arguments;
2342 fd = FuncDeclaration::genCfunc(Type::tsize_t, Id::aaLen, Type::tvoid->arrayOf());
2343 ec = new VarExp(0, fd);
2344 arguments = new Expressions();
2345 arguments->push(e);
2346 e = new CallExp(e->loc, ec, arguments);
2347 e->type = fd->type->next;
2349 else if (ident == Id::keys)
2351 Expression *ec;
2352 FuncDeclaration *fd;
2353 Expressions *arguments;
2354 int size = key->size(e->loc);
2356 assert(size);
2357 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaKeys,
2358 Type::tvoid->arrayOf(), Type::tsize_t);
2359 ec = new VarExp(0, fd);
2360 arguments = new Expressions();
2361 arguments->push(e);
2362 arguments->push(new IntegerExp(0, size, Type::tsize_t));
2363 e = new CallExp(e->loc, ec, arguments);
2364 e->type = index->arrayOf();
2366 else if (ident == Id::values)
2368 Expression *ec;
2369 FuncDeclaration *fd;
2370 Expressions *arguments;
2372 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaValues,
2373 Type::tvoid->arrayOf(), Type::tsize_t, Type::tsize_t);
2374 ec = new VarExp(0, fd);
2375 arguments = new Expressions();
2376 arguments->push(e);
2377 size_t keysize = key->size(e->loc);
2378 keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1);
2379 arguments->push(new IntegerExp(0, keysize, Type::tsize_t));
2380 arguments->push(new IntegerExp(0, next->size(e->loc), Type::tsize_t));
2381 e = new CallExp(e->loc, ec, arguments);
2382 e->type = next->arrayOf();
2384 else if (ident == Id::rehash)
2386 Expression *ec;
2387 FuncDeclaration *fd;
2388 Expressions *arguments;
2390 fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), Id::aaRehash);
2391 ec = new VarExp(0, fd);
2392 arguments = new Expressions();
2393 arguments->push(e->addressOf(sc));
2394 arguments->push(key->getInternalTypeInfo(sc));
2395 e = new CallExp(e->loc, ec, arguments);
2396 e->type = this;
2398 else
2400 e = Type::dotExp(sc, e, ident);
2402 return e;
2405 void TypeAArray::toDecoBuffer(OutBuffer *buf)
2407 buf->writeByte(mangleChar[ty]);
2408 index->toDecoBuffer(buf);
2409 next->toDecoBuffer(buf);
2412 void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2414 if (mod != this->mod)
2415 { toCBuffer3(buf, hgs, mod);
2416 return;
2418 next->toCBuffer2(buf, hgs, this->mod);
2419 buf->writeByte('[');
2420 index->toCBuffer2(buf, hgs, 0);
2421 buf->writeByte(']');
2424 Expression *TypeAArray::defaultInit(Loc loc)
2426 #if LOGDEFAULTINIT
2427 printf("TypeAArray::defaultInit() '%s'\n", toChars());
2428 #endif
2429 Expression *e;
2430 e = new NullExp(loc);
2431 e->type = this;
2432 return e;
2435 int TypeAArray::checkBoolean()
2437 return TRUE;
2440 int TypeAArray::hasPointers()
2442 return TRUE;
2445 /***************************** TypeMaybe *****************************/
2447 TypeMaybe::TypeMaybe(Type *t)
2448 : Type(Tmaybe, t)
2452 Type *TypeMaybe::syntaxCopy()
2454 Type *t = next->syntaxCopy();
2455 if (t == next)
2456 t = this;
2457 else
2458 t = new TypeMaybe(t);
2459 return t;
2462 Type *TypeMaybe::semantic(Loc loc, Scope *sc)
2464 //printf("TypeMaybe::semantic()\n");
2465 Type *n = next->semantic(loc, sc);
2466 switch (n->ty)
2468 case Tclass:
2469 break;
2470 default:
2471 error(loc, "can't have maybe for %s of type %d", n->toChars(), n->toBasetype()->ty);
2472 n = tint32;
2474 if (n != next)
2475 deco = NULL;
2476 next = n;
2477 return merge();
2480 d_uns64 TypeMaybe::size(Loc loc)
2482 return PTRSIZE;
2485 void TypeMaybe::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2487 //printf("TypePointer::toCBuffer2() next = %d\n", next->ty);
2488 if (mod != this->mod)
2489 { toCBuffer3(buf, hgs, mod);
2490 return;
2492 next->toCBuffer2(buf, hgs, this->mod);
2493 if (next->ty != Tfunction)
2494 buf->writeByte('?');
2497 MATCH TypeMaybe::implicitConvTo(Type *to)
2499 printf("TypeMaybe::implicitConvTo(%s)\n", to->toChars());
2501 if (this == to)
2502 return MATCHexact;
2504 if (to->ty == Tpointer && to->next)
2506 if (to->next->ty == Tvoid)
2507 return MATCHconvert;
2509 #if 0
2510 if (to->next->isBaseOf(next))
2511 return MATCHconvert;
2512 #endif
2514 if (next->ty == Tfunction && to->next->ty == Tfunction)
2515 { TypeFunction *tf;
2516 TypeFunction *tfto;
2518 tf = (TypeFunction *)(next);
2519 tfto = (TypeFunction *)(to->next);
2520 return tfto->equals(tf) ? MATCHexact : MATCHnomatch;
2523 // if (to->ty == Tvoid)
2524 // return MATCHconvert;
2526 return MATCHnomatch;
2529 int TypeMaybe::isscalar()
2531 return TRUE;
2534 Expression *TypeMaybe::defaultInit(Loc loc)
2536 #if LOGDEFAULTINIT
2537 printf("TypeMaybe::defaultInit() '%s'\n", toChars());
2538 #endif
2539 Expression *e;
2540 e = new NullExp(loc);
2541 e->type = this;
2542 return e;
2545 int TypeMaybe::isZeroInit()
2547 return 1;
2550 int TypeMaybe::hasPointers()
2552 return TRUE;
2555 /***************************** TypePointer *****************************/
2557 TypePointer::TypePointer(Type *t)
2558 : Type(Tpointer, t)
2562 Type *TypePointer::syntaxCopy()
2564 Type *t = next->syntaxCopy();
2565 if (t == next)
2566 t = this;
2567 else
2568 t = new TypePointer(t);
2569 return t;
2572 Type *TypePointer::semantic(Loc loc, Scope *sc)
2574 //printf("TypePointer::semantic()\n");
2575 Type *n = next->semantic(loc, sc);
2576 switch (n->toBasetype()->ty)
2578 case Ttuple:
2579 error(loc, "can't have pointer to %s", n->toChars());
2580 n = tint32;
2581 break;
2583 if (n != next)
2584 deco = NULL;
2585 next = n;
2586 return merge();
2590 d_uns64 TypePointer::size(Loc loc)
2592 return PTRSIZE;
2595 void TypePointer::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2597 //printf("TypePointer::toCBuffer2() next = %d\n", next->ty);
2598 if (mod != this->mod)
2599 { toCBuffer3(buf, hgs, mod);
2600 return;
2602 next->toCBuffer2(buf, hgs, this->mod);
2603 if (next->ty != Tfunction)
2604 buf->writeByte('*');
2607 MATCH TypePointer::implicitConvTo(Type *to)
2609 //printf("TypePointer::implicitConvTo()\n");
2611 if (this == to)
2612 return MATCHexact;
2613 if (to->ty == Tpointer && to->next)
2615 if (to->next->ty == Tvoid)
2616 return MATCHconvert;
2618 #if 0
2619 if (to->next->isBaseOf(next))
2620 return MATCHconvert;
2621 #endif
2623 if (next->ty == Tfunction && to->next->ty == Tfunction)
2624 { TypeFunction *tf;
2625 TypeFunction *tfto;
2627 tf = (TypeFunction *)(next);
2628 tfto = (TypeFunction *)(to->next);
2629 return tfto->equals(tf) ? MATCHexact : MATCHnomatch;
2632 // if (to->ty == Tvoid)
2633 // return MATCHconvert;
2634 return MATCHnomatch;
2637 int TypePointer::isscalar()
2639 return TRUE;
2642 Expression *TypePointer::defaultInit(Loc loc)
2644 #if LOGDEFAULTINIT
2645 printf("TypePointer::defaultInit() '%s'\n", toChars());
2646 #endif
2647 Expression *e;
2648 e = new NullExp(loc);
2649 e->type = this;
2650 return e;
2653 int TypePointer::isZeroInit()
2655 return 1;
2658 int TypePointer::hasPointers()
2660 return TRUE;
2664 /***************************** TypeReference *****************************/
2666 TypeReference::TypeReference(Type *t)
2667 : Type(Treference, t)
2669 if (t->ty == Tbit)
2670 error(0,"cannot make reference to a bit");
2671 // BUG: what about references to static arrays?
2674 Type *TypeReference::syntaxCopy()
2676 Type *t = next->syntaxCopy();
2677 if (t == next)
2678 t = this;
2679 else
2680 t = new TypeReference(t);
2681 return t;
2684 d_uns64 TypeReference::size(Loc loc)
2686 return PTRSIZE;
2689 void TypeReference::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2691 if (mod != this->mod)
2692 { toCBuffer3(buf, hgs, mod);
2693 return;
2695 next->toCBuffer2(buf, hgs, this->mod);
2696 buf->writeByte('&');
2699 Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident)
2701 #if LOGDOTEXP
2702 printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2703 #endif
2705 // References just forward things along
2706 return next->dotExp(sc, e, ident);
2709 Expression *TypeReference::defaultInit(Loc loc)
2711 #if LOGDEFAULTINIT
2712 printf("TypeReference::defaultInit() '%s'\n", toChars());
2713 #endif
2714 Expression *e;
2715 e = new NullExp(loc);
2716 e->type = this;
2717 return e;
2720 int TypeReference::isZeroInit()
2722 return 1;
2726 /***************************** TypeFunction *****************************/
2728 TypeFunction::TypeFunction(Arguments *parameters, Type *treturn, int varargs, enum LINK linkage)
2729 : Type(Tfunction, treturn)
2731 //if (!treturn) *(char*)0=0;
2732 // assert(treturn);
2733 this->parameters = parameters;
2734 this->varargs = varargs;
2735 this->linkage = linkage;
2736 this->inuse = 0;
2739 Type *TypeFunction::syntaxCopy()
2741 Type *treturn = next ? next->syntaxCopy() : NULL;
2742 Arguments *params = Argument::arraySyntaxCopy(parameters);
2743 Type *t = new TypeFunction(params, treturn, varargs, linkage);
2744 return t;
2747 /*******************************
2748 * Returns:
2749 * 0 types are distinct
2750 * 1 this is covariant with t
2751 * 2 arguments match as far as overloading goes,
2752 * but types are not covariant
2753 * 3 cannot determine covariance because of forward references
2756 int Type::covariant(Type *t)
2758 #if 0
2759 printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars());
2760 printf("deco = %p, %p\n", deco, t->deco);
2761 printf("ty = %d\n", next->ty);
2762 #endif
2764 int inoutmismatch = 0;
2766 if (equals(t))
2767 goto Lcovariant;
2768 if (ty != Tfunction || t->ty != Tfunction)
2769 goto Ldistinct;
2772 TypeFunction *t1 = (TypeFunction *)this;
2773 TypeFunction *t2 = (TypeFunction *)t;
2775 if (t1->varargs != t2->varargs)
2776 goto Ldistinct;
2778 if (t1->parameters && t2->parameters)
2780 size_t dim = Argument::dim(t1->parameters);
2781 if (dim != Argument::dim(t2->parameters))
2782 goto Ldistinct;
2784 for (size_t i = 0; i < dim; i++)
2785 { Argument *arg1 = Argument::getNth(t1->parameters, i);
2786 Argument *arg2 = Argument::getNth(t2->parameters, i);
2788 if (!arg1->type->equals(arg2->type))
2789 goto Ldistinct;
2790 if (arg1->storageClass != arg2->storageClass)
2791 inoutmismatch = 1;
2794 else if (t1->parameters != t2->parameters)
2795 goto Ldistinct;
2797 // The argument lists match
2798 if (inoutmismatch)
2799 goto Lnotcovariant;
2800 if (t1->linkage != t2->linkage)
2801 goto Lnotcovariant;
2803 Type *t1n = t1->next;
2804 Type *t2n = t2->next;
2806 if (t1n->equals(t2n))
2807 goto Lcovariant;
2808 if (t1n->ty != Tclass || t2n->ty != Tclass)
2809 goto Lnotcovariant;
2811 // If t1n is forward referenced:
2812 ClassDeclaration *cd = ((TypeClass *)t1n)->sym;
2813 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
2815 return 3;
2818 if (t1n->implicitConvTo(t2n))
2819 goto Lcovariant;
2820 goto Lnotcovariant;
2823 Lcovariant:
2824 //printf("\tcovaraint: 1\n");
2825 return 1;
2827 Ldistinct:
2828 //printf("\tcovaraint: 0\n");
2829 return 0;
2831 Lnotcovariant:
2832 //printf("\tcovaraint: 2\n");
2833 return 2;
2836 void TypeFunction::toDecoBuffer(OutBuffer *buf)
2837 { unsigned char mc;
2839 //printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars());
2840 //static int nest; if (++nest == 50) *(char*)0=0;
2841 if (inuse)
2842 { inuse = 2; // flag error to caller
2843 return;
2845 inuse++;
2846 switch (linkage)
2848 case LINKd: mc = 'F'; break;
2849 case LINKc: mc = 'U'; break;
2850 case LINKwindows: mc = 'W'; break;
2851 case LINKpascal: mc = 'V'; break;
2852 case LINKcpp: mc = 'R'; break;
2853 default:
2854 assert(0);
2856 buf->writeByte(mc);
2857 // Write argument types
2858 Argument::argsToDecoBuffer(buf, parameters);
2859 //if (buf->data[buf->offset - 1] == '@') halt();
2860 buf->writeByte('Z' - varargs); // mark end of arg list
2861 next->toDecoBuffer(buf);
2862 inuse--;
2865 void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
2867 char *p = NULL;
2869 if (inuse)
2870 { inuse = 2; // flag error to caller
2871 return;
2873 inuse++;
2874 if (next && (!ident || ident->toHChars2() == ident->toChars()))
2875 next->toCBuffer2(buf, hgs, 0);
2876 if (hgs->ddoc != 1)
2878 switch (linkage)
2880 case LINKd: p = NULL; break;
2881 case LINKc: p = "C "; break;
2882 case LINKwindows: p = "Windows "; break;
2883 case LINKpascal: p = "Pascal "; break;
2884 case LINKcpp: p = "C++ "; break;
2885 default:
2886 assert(0);
2890 if (!hgs->hdrgen && p)
2891 buf->writestring(p);
2892 if (ident)
2893 { buf->writeByte(' ');
2894 buf->writestring(ident->toHChars2());
2896 Argument::argsToCBuffer(buf, hgs, parameters, varargs);
2897 inuse--;
2900 void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2902 char *p = NULL;
2904 if (inuse)
2905 { inuse = 2; // flag error to caller
2906 return;
2908 inuse++;
2909 if (next)
2910 next->toCBuffer2(buf, hgs, 0);
2911 if (hgs->ddoc != 1)
2913 switch (linkage)
2915 case LINKd: p = NULL; break;
2916 case LINKc: p = "C "; break;
2917 case LINKwindows: p = "Windows "; break;
2918 case LINKpascal: p = "Pascal "; break;
2919 case LINKcpp: p = "C++ "; break;
2920 default:
2921 assert(0);
2925 if (!hgs->hdrgen && p)
2926 buf->writestring(p);
2927 buf->writestring(" function");
2928 Argument::argsToCBuffer(buf, hgs, parameters, varargs);
2929 inuse--;
2932 Type *TypeFunction::semantic(Loc loc, Scope *sc)
2934 if (deco) // if semantic() already run
2936 //printf("already done\n");
2937 return this;
2939 //printf("TypeFunction::semantic() this = %p\n", this);
2941 TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
2942 memcpy(tf, this, sizeof(TypeFunction));
2943 if (parameters)
2944 { tf->parameters = (Arguments *)parameters->copy();
2945 for (size_t i = 0; i < parameters->dim; i++)
2946 { Argument *arg = (Argument *)parameters->data[i];
2947 Argument *cpy = (Argument *)mem.malloc(sizeof(Argument));
2948 memcpy(cpy, arg, sizeof(Argument));
2949 tf->parameters->data[i] = (void *)cpy;
2953 tf->linkage = sc->linkage;
2954 if (!tf->next)
2956 assert(global.errors);
2957 tf->next = tvoid;
2959 tf->next = tf->next->semantic(loc,sc);
2960 if (tf->next->toBasetype()->ty == Tsarray)
2961 { error(loc, "functions cannot return static array %s", tf->next->toChars());
2962 tf->next = Type::terror;
2964 if (tf->next->toBasetype()->ty == Tfunction)
2965 { error(loc, "functions cannot return a function");
2966 tf->next = Type::terror;
2968 if (tf->next->toBasetype()->ty == Ttuple)
2969 { error(loc, "functions cannot return a tuple");
2970 tf->next = Type::terror;
2972 if (tf->next->isauto() && !(sc->flags & SCOPEctor))
2973 error(loc, "functions cannot return auto %s", tf->next->toChars());
2975 if (tf->parameters)
2976 { size_t dim = Argument::dim(tf->parameters);
2978 for (size_t i = 0; i < dim; i++)
2979 { Argument *arg = Argument::getNth(tf->parameters, i);
2980 Type *t;
2982 tf->inuse++;
2983 arg->type = arg->type->semantic(loc,sc);
2984 if (tf->inuse == 1) tf->inuse--;
2985 t = arg->type->toBasetype();
2987 if (arg->storageClass & (STCout | STCref | STClazy))
2989 if (t->ty == Tsarray)
2990 error(loc, "cannot have out or ref parameter of type %s", t->toChars());
2992 if (!(arg->storageClass & STClazy) && t->ty == Tvoid)
2993 error(loc, "cannot have parameter of type %s", arg->type->toChars());
2995 if (arg->defaultArg)
2997 arg->defaultArg = arg->defaultArg->semantic(sc);
2998 arg->defaultArg = resolveProperties(sc, arg->defaultArg);
2999 arg->defaultArg = arg->defaultArg->implicitCastTo(sc, arg->type);
3002 /* If arg turns out to be a tuple, the number of parameters may
3003 * change.
3005 if (t->ty == Ttuple)
3006 { dim = Argument::dim(tf->parameters);
3007 i--;
3011 tf->deco = tf->merge()->deco;
3013 if (tf->inuse)
3014 { error(loc, "recursive type");
3015 tf->inuse = 0;
3016 return terror;
3019 if (tf->varargs == 1 && tf->linkage != LINKd && Argument::dim(tf->parameters) == 0)
3020 error(loc, "variadic functions with non-D linkage must have at least one parameter");
3022 /* Don't return merge(), because arg identifiers and default args
3023 * can be different
3024 * even though the types match
3026 return tf;
3029 /********************************
3030 * 'args' are being matched to function 'this'
3031 * Determine match level.
3032 * Returns:
3033 * MATCHxxxx
3036 int TypeFunction::callMatch(Expressions *args)
3038 //printf("TypeFunction::callMatch()\n");
3039 int match = MATCHexact; // assume exact match
3041 size_t nparams = Argument::dim(parameters);
3042 size_t nargs = args ? args->dim : 0;
3043 if (nparams == nargs)
3045 else if (nargs > nparams)
3047 if (varargs == 0)
3048 goto Nomatch; // too many args; no match
3049 match = MATCHconvert; // match ... with a "conversion" match level
3052 for (size_t u = 0; u < nparams; u++)
3053 { int m;
3054 Expression *arg;
3056 // BUG: what about out and ref?
3058 Argument *p = Argument::getNth(parameters, u);
3059 assert(p);
3060 if (u >= nargs)
3062 if (p->defaultArg)
3063 continue;
3064 if (varargs == 2 && u + 1 == nparams)
3065 goto L1;
3066 goto Nomatch; // not enough arguments
3068 arg = (Expression *)args->data[u];
3069 assert(arg);
3070 if (p->storageClass & STClazy && p->type->ty == Tvoid && arg->type->ty != Tvoid)
3071 m = MATCHconvert;
3072 else
3073 m = arg->implicitConvTo(p->type);
3074 //printf("\tm = %d\n", m);
3075 if (m == MATCHnomatch) // if no match
3078 if (varargs == 2 && u + 1 == nparams) // if last varargs param
3079 { Type *tb = p->type->toBasetype();
3080 TypeSArray *tsa;
3081 integer_t sz;
3083 switch (tb->ty)
3085 case Tsarray:
3086 tsa = (TypeSArray *)tb;
3087 sz = tsa->dim->toInteger();
3088 if (sz != nargs - u)
3089 goto Nomatch;
3090 case Tarray:
3091 for (; u < nargs; u++)
3093 arg = (Expression *)args->data[u];
3094 assert(arg);
3095 #if 1
3096 /* If lazy array of delegates,
3097 * convert arg(s) to delegate(s)
3099 Type *tret = p->isLazyArray();
3100 if (tret)
3102 if (tb->next->equals(arg->type))
3103 { m = MATCHexact;
3105 else
3107 m = arg->implicitConvTo(tret);
3108 if (m == MATCHnomatch)
3110 if (tret->toBasetype()->ty == Tvoid)
3111 m = MATCHconvert;
3115 else
3116 m = arg->implicitConvTo(tb->next);
3117 #else
3118 m = arg->implicitConvTo(tb->next);
3119 #endif
3120 if (m == 0)
3121 goto Nomatch;
3122 if (m < match)
3123 match = m;
3125 goto Ldone;
3127 case Tclass:
3128 // Should see if there's a constructor match?
3129 // Or just leave it ambiguous?
3130 goto Ldone;
3132 default:
3133 goto Nomatch;
3136 goto Nomatch;
3138 if (m < match)
3139 match = m; // pick worst match
3142 Ldone:
3143 //printf("match = %d\n", match);
3144 return match;
3146 Nomatch:
3147 //printf("no match\n");
3148 return MATCHnomatch;
3151 Type *TypeFunction::reliesOnTident()
3153 if (parameters)
3155 for (size_t i = 0; i < parameters->dim; i++)
3156 { Argument *arg = (Argument *)parameters->data[i];
3157 Type *t = arg->type->reliesOnTident();
3158 if (t)
3159 return t;
3162 return next->reliesOnTident();
3165 /***************************** TypeDelegate *****************************/
3167 TypeDelegate::TypeDelegate(Type *t)
3168 : Type(Tfunction, t)
3170 ty = Tdelegate;
3173 Type *TypeDelegate::syntaxCopy()
3175 Type *t = next->syntaxCopy();
3176 if (t == next)
3177 t = this;
3178 else
3179 t = new TypeDelegate(t);
3180 return t;
3183 Type *TypeDelegate::semantic(Loc loc, Scope *sc)
3185 if (deco) // if semantic() already run
3187 //printf("already done\n");
3188 return this;
3190 next = next->semantic(loc,sc);
3191 return merge();
3194 d_uns64 TypeDelegate::size(Loc loc)
3196 return PTRSIZE * 2;
3199 void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3201 if (mod != this->mod)
3202 { toCBuffer3(buf, hgs, mod);
3203 return;
3205 TypeFunction *tf = (TypeFunction *)next;
3207 tf->next->toCBuffer2(buf, hgs, 0);
3208 buf->writestring(" delegate");
3209 Argument::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs);
3212 Expression *TypeDelegate::defaultInit(Loc loc)
3214 #if LOGDEFAULTINIT
3215 printf("TypeDelegate::defaultInit() '%s'\n", toChars());
3216 #endif
3217 Expression *e;
3218 e = new NullExp(loc);
3219 e->type = this;
3220 return e;
3223 int TypeDelegate::isZeroInit()
3225 return 1;
3228 int TypeDelegate::checkBoolean()
3230 return TRUE;
3233 Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident)
3235 #if LOGDOTEXP
3236 printf("TypeDelegate::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
3237 #endif
3238 if (ident == Id::ptr)
3240 #ifndef IN_GCC
3241 e->type = tvoidptr;
3242 #else
3243 if (e->op == TOKdelegate || e->op == TOKcast)
3244 e = e->castTo(sc, tvoidptr); // Not an lvalue
3245 else
3247 e = e->addressOf(sc);
3248 e = e->castTo(sc, tvoidptr->pointerTo());
3249 e = new PtrExp(e->loc, e);
3250 e->type = tvoidptr;
3252 #endif
3253 return e;
3255 else if (ident == Id::funcptr)
3257 e = e->addressOf(sc);
3258 e->type = tvoidptr;
3259 e = new AddExp(e->loc, e, new IntegerExp(PTRSIZE));
3260 e->type = tvoidptr;
3261 e = new PtrExp(e->loc, e);
3262 e->type = next->pointerTo();
3263 return e;
3265 else
3267 e = Type::dotExp(sc, e, ident);
3269 return e;
3272 int TypeDelegate::hasPointers()
3274 return TRUE;
3279 /***************************** TypeQualified *****************************/
3281 TypeQualified::TypeQualified(TY ty, Loc loc)
3282 : Type(ty, NULL)
3284 this->loc = loc;
3287 void TypeQualified::syntaxCopyHelper(TypeQualified *t)
3289 //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t->toChars(), toChars());
3290 idents.setDim(t->idents.dim);
3291 for (int i = 0; i < idents.dim; i++)
3293 Identifier *id = (Identifier *)t->idents.data[i];
3294 if (id->dyncast() == DYNCAST_DSYMBOL)
3296 TemplateInstance *ti = (TemplateInstance *)id;
3298 ti = (TemplateInstance *)ti->syntaxCopy(NULL);
3299 id = (Identifier *)ti;
3301 idents.data[i] = id;
3306 void TypeQualified::addIdent(Identifier *ident)
3308 idents.push(ident);
3311 void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs)
3313 int i;
3315 for (i = 0; i < idents.dim; i++)
3316 { Identifier *id = (Identifier *)idents.data[i];
3318 buf->writeByte('.');
3320 if (id->dyncast() == DYNCAST_DSYMBOL)
3322 TemplateInstance *ti = (TemplateInstance *)id;
3323 ti->toCBuffer(buf, hgs);
3325 else
3326 buf->writestring(id->toChars());
3330 d_uns64 TypeQualified::size(Loc loc)
3332 error(this->loc, "size of type %s is not known", toChars());
3333 return 1;
3336 /*************************************
3337 * Takes an array of Identifiers and figures out if
3338 * it represents a Type or an Expression.
3339 * Output:
3340 * if expression, *pe is set
3341 * if type, *pt is set
3344 void TypeQualified::resolveHelper(Loc loc, Scope *sc,
3345 Dsymbol *s, Dsymbol *scopesym,
3346 Expression **pe, Type **pt, Dsymbol **ps)
3348 Identifier *id = NULL;
3349 int i;
3350 VarDeclaration *v;
3351 EnumMember *em;
3352 TupleDeclaration *td;
3353 Type *t;
3354 Expression *e;
3356 #if 0
3357 printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, toChars());
3358 if (scopesym)
3359 printf("\tscopesym = '%s'\n", scopesym->toChars());
3360 #endif
3361 *pe = NULL;
3362 *pt = NULL;
3363 *ps = NULL;
3364 if (s)
3366 //printf("\t1: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3367 s = s->toAlias();
3368 //printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3369 for (i = 0; i < idents.dim; i++)
3370 { Dsymbol *sm;
3372 id = (Identifier *)idents.data[i];
3373 sm = s->searchX(loc, sc, id);
3374 //printf("\t3: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3375 //printf("getType = '%s'\n", s->getType()->toChars());
3376 if (!sm)
3378 v = s->isVarDeclaration();
3379 if (v && id == Id::length)
3381 if (v->isConst() && v->getExpInitializer())
3382 { e = v->getExpInitializer()->exp;
3384 else
3385 e = new VarExp(loc, v);
3386 t = e->type;
3387 if (!t)
3388 goto Lerror;
3389 goto L3;
3391 t = s->getType();
3392 if (!t && s->isDeclaration())
3393 t = s->isDeclaration()->type;
3394 if (t)
3396 sm = t->toDsymbol(sc);
3397 if (sm)
3398 { sm = sm->search(loc, id, 0);
3399 if (sm)
3400 goto L2;
3402 //e = t->getProperty(loc, id);
3403 e = new TypeExp(loc, t);
3404 e = t->dotExp(sc, e, id);
3405 i++;
3407 for (; i < idents.dim; i++)
3409 id = (Identifier *)idents.data[i];
3410 //printf("e: '%s', id: '%s', type = %p\n", e->toChars(), id->toChars(), e->type);
3411 e = e->type->dotExp(sc, e, id);
3413 *pe = e;
3415 else
3416 Lerror:
3417 error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
3418 return;
3421 s = sm->toAlias();
3424 v = s->isVarDeclaration();
3425 if (v)
3427 // It's not a type, it's an expression
3428 if (v->isConst() && v->getExpInitializer())
3430 ExpInitializer *ei = v->getExpInitializer();
3431 assert(ei);
3432 *pe = ei->exp->copy(); // make copy so we can change loc
3433 (*pe)->loc = loc;
3435 else
3437 #if 0
3438 WithScopeSymbol *withsym;
3439 if (scopesym && (withsym = scopesym->isWithScopeSymbol()) != NULL)
3441 // Same as wthis.ident
3442 e = new VarExp(loc, withsym->withstate->wthis);
3443 e = new DotIdExp(loc, e, ident);
3444 //assert(0); // BUG: should handle this
3446 else
3447 #endif
3448 *pe = new VarExp(loc, v);
3450 return;
3452 em = s->isEnumMember();
3453 if (em)
3455 // It's not a type, it's an expression
3456 *pe = em->value->copy();
3457 return;
3461 t = s->getType();
3462 if (!t)
3464 // If the symbol is an import, try looking inside the import
3465 Import *si;
3467 si = s->isImport();
3468 if (si)
3470 s = si->search(loc, s->ident, 0);
3471 if (s && s != si)
3472 goto L1;
3473 s = si;
3475 *ps = s;
3476 return;
3478 if (t->ty == Tinstance && t != this && !t->deco)
3479 { error(loc, "forward reference to '%s'", t->toChars());
3480 return;
3483 if (t != this)
3485 if (t->reliesOnTident())
3487 Scope *scx;
3489 for (scx = sc; 1; scx = scx->enclosing)
3491 if (!scx)
3492 { error(loc, "forward reference to '%s'", t->toChars());
3493 return;
3495 if (scx->scopesym == scopesym)
3496 break;
3498 t = t->semantic(loc, scx);
3499 //((TypeIdentifier *)t)->resolve(loc, scx, pe, &t, ps);
3502 if (t->ty == Ttuple)
3503 *pt = t;
3504 else
3505 *pt = t->merge();
3507 if (!s)
3509 error(loc, "identifier '%s' is not defined", toChars());
3513 /***************************** TypeIdentifier *****************************/
3515 TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident)
3516 : TypeQualified(Tident, loc)
3518 this->ident = ident;
3522 Type *TypeIdentifier::syntaxCopy()
3524 TypeIdentifier *t;
3526 t = new TypeIdentifier(loc, ident);
3527 t->syntaxCopyHelper(this);
3528 return t;
3531 void TypeIdentifier::toDecoBuffer(OutBuffer *buf)
3532 { unsigned len;
3533 char *name;
3535 name = ident->toChars();
3536 len = strlen(name);
3537 buf->printf("%c%d%s", mangleChar[ty], len, name);
3538 //buf->printf("%c%s", mangleChar[ty], name);
3541 void TypeIdentifier::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3543 if (mod != this->mod)
3544 { toCBuffer3(buf, hgs, mod);
3545 return;
3547 buf->writestring(this->ident->toChars());
3548 toCBuffer2Helper(buf, hgs);
3551 /*************************************
3552 * Takes an array of Identifiers and figures out if
3553 * it represents a Type or an Expression.
3554 * Output:
3555 * if expression, *pe is set
3556 * if type, *pt is set
3559 void TypeIdentifier::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
3560 { Dsymbol *s;
3561 Dsymbol *scopesym;
3563 //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars());
3564 s = sc->search(loc, ident, &scopesym);
3565 resolveHelper(loc, sc, s, scopesym, pe, pt, ps);
3568 /*****************************************
3569 * See if type resolves to a symbol, if so,
3570 * return that symbol.
3573 Dsymbol *TypeIdentifier::toDsymbol(Scope *sc)
3575 //printf("TypeIdentifier::toDsymbol('%s')\n", toChars());
3576 if (!sc)
3577 return NULL;
3578 //printf("ident = '%s'\n", ident->toChars());
3580 Dsymbol *scopesym;
3581 Dsymbol *s = sc->search(loc, ident, &scopesym);
3582 if (s)
3584 for (int i = 0; i < idents.dim; i++)
3586 Identifier *id = (Identifier *)idents.data[i];
3587 s = s->searchX(loc, sc, id);
3588 if (!s) // failed to find a symbol
3589 { //printf("\tdidn't find a symbol\n");
3590 break;
3594 return s;
3597 Type *TypeIdentifier::semantic(Loc loc, Scope *sc)
3599 Type *t;
3600 Expression *e;
3601 Dsymbol *s;
3603 //printf("TypeIdentifier::semantic(%s)\n", toChars());
3604 resolve(loc, sc, &e, &t, &s);
3605 if (t)
3607 //printf("\tit's a type %d, %s, %s\n", t->ty, t->toChars(), t->deco);
3609 if (t->ty == Ttypedef)
3610 { TypeTypedef *tt = (TypeTypedef *)t;
3612 if (tt->sym->sem == 1)
3613 error(loc, "circular reference of typedef %s", tt->toChars());
3616 else
3618 #ifdef DEBUG
3619 if (!global.gag)
3620 printf("1: ");
3621 #endif
3622 if (s)
3624 s->error(loc, "is used as a type");
3626 else
3627 error(loc, "%s is used as a type", toChars());
3628 t = tvoid;
3630 //t->print();
3631 return t;
3634 Type *TypeIdentifier::reliesOnTident()
3636 return this;
3639 Expression *TypeIdentifier::toExpression()
3641 Expression *e = new IdentifierExp(loc, ident);
3642 for (int i = 0; i < idents.dim; i++)
3644 Identifier *id = (Identifier *)idents.data[i];
3645 e = new DotIdExp(loc, e, id);
3648 return e;
3651 /***************************** TypeInstance *****************************/
3653 TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst)
3654 : TypeQualified(Tinstance, loc)
3656 this->tempinst = tempinst;
3659 Type *TypeInstance::syntaxCopy()
3661 //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim);
3662 TypeInstance *t;
3664 t = new TypeInstance(loc, (TemplateInstance *)tempinst->syntaxCopy(NULL));
3665 t->syntaxCopyHelper(this);
3666 return t;
3670 void TypeInstance::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3672 if (mod != this->mod)
3673 { toCBuffer3(buf, hgs, mod);
3674 return;
3676 tempinst->toCBuffer(buf, hgs);
3677 toCBuffer2Helper(buf, hgs);
3680 void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
3682 // Note close similarity to TypeIdentifier::resolve()
3684 Dsymbol *s;
3686 *pe = NULL;
3687 *pt = NULL;
3688 *ps = NULL;
3690 #if 0
3691 if (!idents.dim)
3693 error(loc, "template instance '%s' has no identifier", toChars());
3694 return;
3696 #endif
3697 //id = (Identifier *)idents.data[0];
3698 //printf("TypeInstance::resolve(sc = %p, idents = '%s')\n", sc, id->toChars());
3699 s = tempinst;
3700 if (s)
3701 s->semantic(sc);
3702 resolveHelper(loc, sc, s, NULL, pe, pt, ps);
3703 //printf("pt = '%s'\n", (*pt)->toChars());
3706 Type *TypeInstance::semantic(Loc loc, Scope *sc)
3708 Type *t;
3709 Expression *e;
3710 Dsymbol *s;
3712 //printf("TypeInstance::semantic(%s)\n", toChars());
3714 if (sc->parameterSpecialization)
3716 unsigned errors = global.errors;
3717 global.gag++;
3719 resolve(loc, sc, &e, &t, &s);
3721 global.gag--;
3722 if (errors != global.errors)
3723 { if (global.gag == 0)
3724 global.errors = errors;
3725 return this;
3728 else
3729 resolve(loc, sc, &e, &t, &s);
3731 if (!t)
3733 #ifdef DEBUG
3734 printf("2: ");
3735 #endif
3736 error(loc, "%s is used as a type", toChars());
3737 t = tvoid;
3739 return t;
3743 /***************************** TypeTypeof *****************************/
3745 TypeTypeof::TypeTypeof(Loc loc, Expression *exp)
3746 : TypeQualified(Ttypeof, loc)
3748 this->exp = exp;
3751 Type *TypeTypeof::syntaxCopy()
3753 TypeTypeof *t;
3755 t = new TypeTypeof(loc, exp->syntaxCopy());
3756 t->syntaxCopyHelper(this);
3757 return t;
3760 Dsymbol *TypeTypeof::toDsymbol(Scope *sc)
3762 Type *t;
3764 t = semantic(0, sc);
3765 if (t == this)
3766 return NULL;
3767 return t->toDsymbol(sc);
3770 void TypeTypeof::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3772 if (mod != this->mod)
3773 { toCBuffer3(buf, hgs, mod);
3774 return;
3776 buf->writestring("typeof(");
3777 exp->toCBuffer(buf, hgs);
3778 buf->writeByte(')');
3779 toCBuffer2Helper(buf, hgs);
3782 Type *TypeTypeof::semantic(Loc loc, Scope *sc)
3783 { Expression *e;
3784 Type *t;
3786 //printf("TypeTypeof::semantic() %p\n", this);
3788 //static int nest; if (++nest == 50) *(char*)0=0;
3790 #if 0
3791 /* Special case for typeof(this) and typeof(super) since both
3792 * should work even if they are not inside a non-static member function
3794 if (exp->op == TOKthis || exp->op == TOKsuper)
3796 // Find enclosing struct or class
3797 for (Dsymbol *s = sc->parent; 1; s = s->parent)
3799 ClassDeclaration *cd;
3800 StructDeclaration *sd;
3802 if (!s)
3804 error(loc, "%s is not in a struct or class scope", exp->toChars());
3805 goto Lerr;
3807 cd = s->isClassDeclaration();
3808 if (cd)
3810 if (exp->op == TOKsuper)
3812 cd = cd->baseClass;
3813 if (!cd)
3814 { error(loc, "class %s has no 'super'", s->toChars());
3815 goto Lerr;
3818 t = cd->type;
3819 break;
3821 sd = s->isStructDeclaration();
3822 if (sd)
3824 if (exp->op == TOKsuper)
3826 error(loc, "struct %s has no 'super'", sd->toChars());
3827 goto Lerr;
3829 t = sd->type->pointerTo();
3830 break;
3834 else
3835 #endif
3837 sc->intypeof++;
3838 exp = exp->semantic(sc);
3839 sc->intypeof--;
3840 t = exp->type;
3841 if (!t)
3843 error(loc, "expression (%s) has no type", exp->toChars());
3844 goto Lerr;
3848 if (idents.dim)
3850 Dsymbol *s = t->toDsymbol(sc);
3851 for (size_t i = 0; i < idents.dim; i++)
3853 if (!s)
3854 break;
3855 Identifier *id = (Identifier *)idents.data[i];
3856 s = s->searchX(loc, sc, id);
3858 if (s)
3860 t = s->getType();
3861 if (!t)
3862 { error(loc, "%s is not a type", s->toChars());
3863 goto Lerr;
3866 else
3867 { error(loc, "cannot resolve .property for %s", toChars());
3868 goto Lerr;
3871 return t;
3873 Lerr:
3874 return tvoid;
3877 d_uns64 TypeTypeof::size(Loc loc)
3879 if (exp->type)
3880 return exp->type->size(loc);
3881 else
3882 return TypeQualified::size(loc);
3887 /***************************** TypeEnum *****************************/
3889 TypeEnum::TypeEnum(EnumDeclaration *sym)
3890 : Type(Tenum, NULL)
3892 this->sym = sym;
3895 char *TypeEnum::toChars()
3897 return sym->toChars();
3900 Type *TypeEnum::semantic(Loc loc, Scope *sc)
3902 sym->semantic(sc);
3903 return merge();
3906 d_uns64 TypeEnum::size(Loc loc)
3908 if (!sym->memtype)
3910 error(loc, "enum %s is forward referenced", sym->toChars());
3911 return 4;
3913 return sym->memtype->size(loc);
3916 unsigned TypeEnum::alignsize()
3918 if (!sym->memtype)
3920 #ifdef DEBUG
3921 printf("1: ");
3922 #endif
3923 error(0, "enum %s is forward referenced", sym->toChars());
3924 return 4;
3926 return sym->memtype->alignsize();
3929 Dsymbol *TypeEnum::toDsymbol(Scope *sc)
3931 return sym;
3934 Type *TypeEnum::toBasetype()
3936 if (!sym->memtype)
3938 #ifdef DEBUG
3939 printf("2: ");
3940 #endif
3941 error(sym->loc, "enum %s is forward referenced", sym->toChars());
3942 return tint32;
3944 return sym->memtype->toBasetype();
3947 void TypeEnum::toDecoBuffer(OutBuffer *buf)
3948 { char *name;
3950 name = sym->mangle();
3951 // if (name[0] == '_' && name[1] == 'D')
3952 // name += 2;
3953 buf->printf("%c%s", mangleChar[ty], name);
3956 void TypeEnum::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3958 if (mod != this->mod)
3959 { toCBuffer3(buf, hgs, mod);
3960 return;
3962 buf->writestring(sym->toChars());
3965 Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident)
3967 EnumMember *m;
3968 Dsymbol *s;
3969 Expression *em;
3971 #if LOGDOTEXP
3972 printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars());
3973 #endif
3974 if (!sym->symtab)
3975 goto Lfwd;
3976 s = sym->symtab->lookup(ident);
3977 if (!s)
3979 return getProperty(e->loc, ident);
3981 m = s->isEnumMember();
3982 em = m->value->copy();
3983 em->loc = e->loc;
3984 return em;
3986 Lfwd:
3987 error(e->loc, "forward reference of %s.%s", toChars(), ident->toChars());
3988 return new IntegerExp(0, 0, this);
3991 Expression *TypeEnum::getProperty(Loc loc, Identifier *ident)
3992 { Expression *e;
3994 if (ident == Id::max)
3996 if (!sym->symtab)
3997 goto Lfwd;
3998 e = new IntegerExp(0, sym->maxval, this);
4000 else if (ident == Id::min)
4002 if (!sym->symtab)
4003 goto Lfwd;
4004 e = new IntegerExp(0, sym->minval, this);
4006 else if (ident == Id::init)
4008 if (!sym->symtab)
4009 goto Lfwd;
4010 e = defaultInit(loc);
4012 else
4014 if (!sym->memtype)
4015 goto Lfwd;
4016 e = sym->memtype->getProperty(loc, ident);
4018 return e;
4020 Lfwd:
4021 error(loc, "forward reference of %s.%s", toChars(), ident->toChars());
4022 return new IntegerExp(0, 0, this);
4025 int TypeEnum::isintegral()
4027 return 1;
4030 int TypeEnum::isfloating()
4032 return 0;
4035 int TypeEnum::isunsigned()
4037 return sym->memtype->isunsigned();
4040 int TypeEnum::isscalar()
4042 return 1;
4043 //return sym->memtype->isscalar();
4046 MATCH TypeEnum::implicitConvTo(Type *to)
4047 { MATCH m;
4049 //printf("TypeEnum::implicitConvTo()\n");
4050 if (this->equals(to))
4051 m = MATCHexact; // exact match
4052 else if (sym->memtype->implicitConvTo(to))
4053 m = MATCHconvert; // match with conversions
4054 else
4055 m = MATCHnomatch; // no match
4056 return m;
4059 Expression *TypeEnum::defaultInit(Loc loc)
4061 #if LOGDEFAULTINIT
4062 printf("TypeEnum::defaultInit() '%s'\n", toChars());
4063 #endif
4064 // Initialize to first member of enum
4065 Expression *e;
4066 e = new IntegerExp(loc, sym->defaultval, this);
4067 return e;
4070 int TypeEnum::isZeroInit()
4072 return (sym->defaultval == 0);
4075 int TypeEnum::hasPointers()
4077 return toBasetype()->hasPointers();
4080 /***************************** TypeTypedef *****************************/
4082 TypeTypedef::TypeTypedef(TypedefDeclaration *sym)
4083 : Type(Ttypedef, NULL)
4085 this->sym = sym;
4088 Type *TypeTypedef::syntaxCopy()
4090 return this;
4093 char *TypeTypedef::toChars()
4095 return sym->toChars();
4098 Type *TypeTypedef::semantic(Loc loc, Scope *sc)
4100 //printf("TypeTypedef::semantic(%s), sem = %d\n", toChars(), sym->sem);
4101 sym->semantic(sc);
4102 return merge();
4105 d_uns64 TypeTypedef::size(Loc loc)
4107 return sym->basetype->size(loc);
4110 unsigned TypeTypedef::alignsize()
4112 return sym->basetype->alignsize();
4115 Dsymbol *TypeTypedef::toDsymbol(Scope *sc)
4117 return sym;
4120 void TypeTypedef::toDecoBuffer(OutBuffer *buf)
4121 { unsigned len;
4122 char *name;
4124 name = sym->mangle();
4125 // if (name[0] == '_' && name[1] == 'D')
4126 // name += 2;
4127 //len = strlen(name);
4128 //buf->printf("%c%d%s", mangleChar[ty], len, name);
4129 buf->printf("%c%s", mangleChar[ty], name);
4132 void TypeTypedef::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4134 //printf("TypeTypedef::toCBuffer2() '%s'\n", sym->toChars());
4135 if (mod != this->mod)
4136 { toCBuffer3(buf, hgs, mod);
4137 return;
4139 buf->writestring(sym->toChars());
4142 Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident)
4144 #if LOGDOTEXP
4145 printf("TypeTypedef::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars());
4146 #endif
4147 if (ident == Id::init)
4149 return Type::dotExp(sc, e, ident);
4151 return sym->basetype->dotExp(sc, e, ident);
4154 Expression *TypeTypedef::getProperty(Loc loc, Identifier *ident)
4156 if (ident == Id::init)
4158 return Type::getProperty(loc, ident);
4160 return sym->basetype->getProperty(loc, ident);
4163 int TypeTypedef::isbit()
4165 return sym->basetype->isbit();
4168 int TypeTypedef::isintegral()
4170 //printf("TypeTypedef::isintegral()\n");
4171 //printf("sym = '%s'\n", sym->toChars());
4172 //printf("basetype = '%s'\n", sym->basetype->toChars());
4173 return sym->basetype->isintegral();
4176 int TypeTypedef::isfloating()
4178 return sym->basetype->isfloating();
4181 int TypeTypedef::isreal()
4183 return sym->basetype->isreal();
4186 int TypeTypedef::isimaginary()
4188 return sym->basetype->isimaginary();
4191 int TypeTypedef::iscomplex()
4193 return sym->basetype->iscomplex();
4196 int TypeTypedef::isunsigned()
4198 return sym->basetype->isunsigned();
4201 int TypeTypedef::isscalar()
4203 return sym->basetype->isscalar();
4206 int TypeTypedef::checkBoolean()
4208 return sym->basetype->checkBoolean();
4211 Type *TypeTypedef::toBasetype()
4213 if (sym->inuse)
4215 sym->error("circular definition");
4216 sym->basetype = Type::terror;
4217 return Type::terror;
4219 sym->inuse = 1;
4220 Type *t = sym->basetype->toBasetype();
4221 sym->inuse = 0;
4222 return t;
4225 MATCH TypeTypedef::implicitConvTo(Type *to)
4226 { MATCH m;
4228 //printf("TypeTypedef::implicitConvTo()\n");
4229 if (this->equals(to))
4230 m = MATCHexact; // exact match
4231 else if (sym->basetype->implicitConvTo(to))
4232 m = MATCHconvert; // match with conversions
4233 else
4234 m = MATCHnomatch; // no match
4235 return m;
4238 Expression *TypeTypedef::defaultInit(Loc loc)
4239 { Expression *e;
4240 Type *bt;
4242 #if LOGDEFAULTINIT
4243 printf("TypeTypedef::defaultInit() '%s'\n", toChars());
4244 #endif
4245 if (sym->init)
4247 //sym->init->toExpression()->print();
4248 return sym->init->toExpression();
4250 bt = sym->basetype;
4251 e = bt->defaultInit(loc);
4252 e->type = this;
4253 while (bt->ty == Tsarray)
4255 e->type = bt->next;
4256 bt = bt->next->toBasetype();
4258 return e;
4261 int TypeTypedef::isZeroInit()
4263 if (sym->init)
4265 if (sym->init->isVoidInitializer())
4266 return 1; // initialize voids to 0
4267 Expression *e = sym->init->toExpression();
4268 if (e && e->isBool(FALSE))
4269 return 1;
4270 return 0; // assume not
4272 if (sym->inuse)
4274 sym->error("circular definition");
4275 sym->basetype = Type::terror;
4277 sym->inuse = 1;
4278 int result = sym->basetype->isZeroInit();
4279 sym->inuse = 0;
4280 return result;
4283 int TypeTypedef::hasPointers()
4285 return toBasetype()->hasPointers();
4288 /***************************** TypeStruct *****************************/
4290 TypeStruct::TypeStruct(StructDeclaration *sym)
4291 : Type(Tstruct, NULL)
4293 this->sym = sym;
4296 char *TypeStruct::toChars()
4298 //printf("sym.parent: %s, deco = %s\n", sym->parent->toChars(), deco);
4299 TemplateInstance *ti = sym->parent->isTemplateInstance();
4300 if (ti && ti->toAlias() == sym)
4301 return ti->toChars();
4302 return sym->toChars();
4305 Type *TypeStruct::syntaxCopy()
4307 return this;
4310 Type *TypeStruct::semantic(Loc loc, Scope *sc)
4312 //printf("TypeStruct::semantic('%s')\n", sym->toChars());
4314 /* Cannot do semantic for sym because scope chain may not
4315 * be right.
4317 //sym->semantic(sc);
4319 return merge();
4322 d_uns64 TypeStruct::size(Loc loc)
4324 return sym->size(loc);
4327 unsigned TypeStruct::alignsize()
4328 { target_size_t sz;
4330 sym->size(0); // give error for forward references
4331 sz = sym->alignsize;
4332 if (sz > sym->structalign)
4333 sz = sym->structalign;
4334 return sz;
4337 Dsymbol *TypeStruct::toDsymbol(Scope *sc)
4339 return sym;
4342 void TypeStruct::toDecoBuffer(OutBuffer *buf)
4343 { unsigned len;
4344 char *name;
4346 name = sym->mangle();
4347 //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", toChars(), name);
4348 // if (name[0] == '_' && name[1] == 'D')
4349 // name += 2;
4350 //len = strlen(name);
4351 //buf->printf("%c%d%s", mangleChar[ty], len, name);
4352 buf->printf("%c%s", mangleChar[ty], name);
4355 void TypeStruct::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4357 if (mod != this->mod)
4358 { toCBuffer3(buf, hgs, mod);
4359 return;
4361 TemplateInstance *ti = sym->parent->isTemplateInstance();
4362 if (ti && ti->toAlias() == sym)
4363 buf->writestring(ti->toChars());
4364 else
4365 buf->writestring(sym->toChars());
4368 Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
4369 { unsigned offset;
4371 Expression *b;
4372 VarDeclaration *v;
4373 Dsymbol *s;
4374 DotVarExp *de;
4375 Declaration *d;
4377 #if LOGDOTEXP
4378 printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
4379 #endif
4380 if (!sym->members)
4382 error(e->loc, "struct %s is forward referenced", sym->toChars());
4383 return new IntegerExp(e->loc, 0, Type::tint32);
4386 if (ident == Id::tupleof)
4388 /* Create a TupleExp
4390 Expressions *exps = new Expressions;
4391 exps->reserve(sym->fields.dim);
4392 for (size_t i = 0; i < sym->fields.dim; i++)
4393 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
4394 Expression *fe = new DotVarExp(e->loc, e, v);
4395 exps->push(fe);
4397 e = new TupleExp(e->loc, exps);
4398 e = e->semantic(sc);
4399 return e;
4402 if (e->op == TOKdotexp)
4403 { DotExp *de = (DotExp *)e;
4405 if (de->e1->op == TOKimport)
4407 ScopeExp *se = (ScopeExp *)de->e1;
4409 s = se->sds->search(e->loc, ident, 0);
4410 e = de->e1;
4411 goto L1;
4415 s = sym->search(e->loc, ident, 0);
4417 if (!s)
4419 //return getProperty(e->loc, ident);
4420 return Type::dotExp(sc, e, ident);
4422 s = s->toAlias();
4424 v = s->isVarDeclaration();
4425 if (v && v->isConst())
4426 { ExpInitializer *ei = v->getExpInitializer();
4428 if (ei)
4429 { e = ei->exp->copy(); // need to copy it if it's a StringExp
4430 e = e->semantic(sc);
4431 return e;
4435 if (s->getType())
4437 //return new DotTypeExp(e->loc, e, s);
4438 return new TypeExp(e->loc, s->getType());
4441 EnumMember *em = s->isEnumMember();
4442 if (em)
4444 assert(em->value);
4445 return em->value->copy();
4448 TemplateMixin *tm = s->isTemplateMixin();
4449 if (tm)
4450 { Expression *de;
4452 de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
4453 de->type = e->type;
4454 return de;
4457 TemplateDeclaration *td = s->isTemplateDeclaration();
4458 if (td)
4460 e = new DotTemplateExp(e->loc, e, td);
4461 e->semantic(sc);
4462 return e;
4465 TemplateInstance *ti = s->isTemplateInstance();
4466 if (ti)
4467 { if (!ti->semanticdone)
4468 ti->semantic(sc);
4469 s = ti->inst->toAlias();
4470 if (!s->isTemplateInstance())
4471 goto L1;
4472 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
4473 de->type = e->type;
4474 return de;
4477 d = s->isDeclaration();
4478 #ifdef DEBUG
4479 if (!d)
4480 printf("d = %s '%s'\n", s->kind(), s->toChars());
4481 #endif
4482 assert(d);
4484 if (e->op == TOKtype)
4485 { FuncDeclaration *fd = sc->func;
4487 if (d->needThis() && fd && fd->vthis)
4489 e = new DotVarExp(e->loc, new ThisExp(e->loc), d);
4490 e = e->semantic(sc);
4491 return e;
4493 if (d->isTupleDeclaration())
4495 e = new TupleExp(e->loc, d->isTupleDeclaration());
4496 e = e->semantic(sc);
4497 return e;
4499 return new VarExp(e->loc, d);
4502 if (d->isDataseg())
4504 // (e, d)
4505 VarExp *ve;
4507 accessCheck(e->loc, sc, e, d);
4508 ve = new VarExp(e->loc, d);
4509 e = new CommaExp(e->loc, e, ve);
4510 e->type = d->type;
4511 return e;
4514 if (v)
4516 if (v->toParent() != sym)
4517 sym->error(e->loc, "'%s' is not a member", v->toChars());
4519 // *(&e + offset)
4520 accessCheck(e->loc, sc, e, d);
4521 b = new AddrExp(e->loc, e);
4522 b->type = e->type->pointerTo();
4523 b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tsize_t));
4524 b->type = v->type->pointerTo();
4525 e = new PtrExp(e->loc, b);
4526 e->type = v->type;
4527 return e;
4530 de = new DotVarExp(e->loc, e, d);
4531 return de->semantic(sc);
4534 unsigned TypeStruct::memalign(unsigned salign)
4536 sym->size(0); // give error for forward references
4537 return sym->structalign;
4540 Expression *TypeStruct::defaultInit(Loc loc)
4541 { Symbol *s;
4542 Declaration *d;
4544 #if LOGDEFAULTINIT
4545 printf("TypeStruct::defaultInit() '%s'\n", toChars());
4546 #endif
4547 s = sym->toInitializer();
4548 d = new SymbolDeclaration(sym->loc, s, sym);
4549 assert(d);
4550 d->type = this;
4551 return new VarExp(sym->loc, d);
4554 int TypeStruct::isZeroInit()
4556 return sym->zeroInit;
4559 int TypeStruct::checkBoolean()
4561 return FALSE;
4564 int TypeStruct::hasPointers()
4566 StructDeclaration *s = sym;
4568 sym->size(0); // give error for forward references
4569 if (s->members)
4571 for (size_t i = 0; i < s->members->dim; i++)
4573 Dsymbol *sm = (Dsymbol *)s->members->data[i];
4574 if (sm->hasPointers())
4575 return TRUE;
4578 return FALSE;
4582 /***************************** TypeClass *****************************/
4584 TypeClass::TypeClass(ClassDeclaration *sym)
4585 : Type(Tclass, NULL)
4587 this->sym = sym;
4590 char *TypeClass::toChars()
4592 return sym->toPrettyChars();
4595 Type *TypeClass::syntaxCopy()
4597 return this;
4600 Type *TypeClass::semantic(Loc loc, Scope *sc)
4602 //printf("TypeClass::semantic(%s)\n", sym->toChars());
4603 if (sym->scope)
4604 sym->semantic(sym->scope);
4605 return merge();
4608 d_uns64 TypeClass::size(Loc loc)
4610 return PTRSIZE;
4613 Dsymbol *TypeClass::toDsymbol(Scope *sc)
4615 return sym;
4618 void TypeClass::toDecoBuffer(OutBuffer *buf)
4619 { unsigned len;
4620 char *name;
4622 name = sym->mangle();
4623 // if (name[0] == '_' && name[1] == 'D')
4624 // name += 2;
4625 //printf("TypeClass::toDecoBuffer('%s') = '%s'\n", toChars(), name);
4626 //len = strlen(name);
4627 //buf->printf("%c%d%s", mangleChar[ty], len, name);
4628 buf->printf("%c%s", mangleChar[ty], name);
4631 void TypeClass::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4633 if (mod != this->mod)
4634 { toCBuffer3(buf, hgs, mod);
4635 return;
4637 buf->writestring(sym->toChars());
4640 Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
4641 { unsigned offset;
4643 Expression *b;
4644 VarDeclaration *v;
4645 Dsymbol *s;
4646 DotVarExp *de;
4647 Declaration *d;
4649 #if LOGDOTEXP
4650 printf("TypeClass::dotExp(e='%s', ident='%s')\n", e->toChars(), ident->toChars());
4651 #endif
4653 if (e->op == TOKdotexp)
4654 { DotExp *de = (DotExp *)e;
4656 if (de->e1->op == TOKimport)
4658 ScopeExp *se = (ScopeExp *)de->e1;
4660 s = se->sds->search(e->loc, ident, 0);
4661 e = de->e1;
4662 goto L1;
4666 if (ident == Id::tupleof)
4668 /* Create a TupleExp
4670 Expressions *exps = new Expressions;
4671 exps->reserve(sym->fields.dim);
4672 for (size_t i = 0; i < sym->fields.dim; i++)
4673 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
4674 Expression *fe = new DotVarExp(e->loc, e, v);
4675 exps->push(fe);
4677 e = new TupleExp(e->loc, exps);
4678 e = e->semantic(sc);
4679 return e;
4682 s = sym->search(e->loc, ident, 0);
4684 if (!s)
4686 // See if it's a base class
4687 ClassDeclaration *cbase;
4688 for (cbase = sym->baseClass; cbase; cbase = cbase->baseClass)
4690 if (cbase->ident->equals(ident))
4692 e = new DotTypeExp(0, e, cbase);
4693 return e;
4697 if (ident == Id::classinfo)
4699 Type *t;
4701 assert(ClassDeclaration::classinfo);
4702 t = ClassDeclaration::classinfo->type;
4703 if (e->op == TOKtype || e->op == TOKdottype)
4705 /* For type.classinfo, we know the classinfo
4706 * at compile time.
4708 if (!sym->vclassinfo)
4709 sym->vclassinfo = new ClassInfoDeclaration(sym);
4710 e = new VarExp(e->loc, sym->vclassinfo);
4711 e = e->addressOf(sc);
4712 e->type = t; // do this so we don't get redundant dereference
4714 else
4715 { /* For class objects, the classinfo reference is the first
4716 * entry in the vtbl[]
4718 e = new PtrExp(e->loc, e);
4719 e->type = t->pointerTo();
4720 if (sym->isInterfaceDeclaration())
4722 if (sym->isCOMinterface())
4723 { /* COM interface vtbl[]s are different in that the
4724 * first entry is always pointer to QueryInterface().
4725 * We can't get a .classinfo for it.
4727 error(e->loc, "no .classinfo for COM interface objects");
4729 /* For an interface, the first entry in the vtbl[]
4730 * is actually a pointer to an instance of struct Interface.
4731 * The first member of Interface is the .classinfo,
4732 * so add an extra pointer indirection.
4734 e->type = e->type->pointerTo();
4735 e = new PtrExp(e->loc, e);
4736 e->type = t->pointerTo();
4738 e = new PtrExp(e->loc, e, t);
4740 return e;
4743 if (ident == Id::typeinfo)
4745 if (!global.params.useDeprecated)
4746 error(e->loc, ".typeinfo deprecated, use typeid(type)");
4747 return getTypeInfo(sc);
4749 if (ident == Id::outer && sym->vthis)
4751 s = sym->vthis;
4753 else
4755 //return getProperty(e->loc, ident);
4756 return Type::dotExp(sc, e, ident);
4759 s = s->toAlias();
4760 v = s->isVarDeclaration();
4761 if (v && v->isConst())
4762 { ExpInitializer *ei = v->getExpInitializer();
4764 if (ei)
4765 { e = ei->exp->copy(); // need to copy it if it's a StringExp
4766 e = e->semantic(sc);
4767 return e;
4771 if (s->getType())
4773 // if (e->op == TOKtype)
4774 return new TypeExp(e->loc, s->getType());
4775 // return new DotTypeExp(e->loc, e, s);
4778 EnumMember *em = s->isEnumMember();
4779 if (em)
4781 assert(em->value);
4782 return em->value->copy();
4785 TemplateMixin *tm = s->isTemplateMixin();
4786 if (tm)
4787 { Expression *de;
4789 de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
4790 de->type = e->type;
4791 return de;
4794 TemplateDeclaration *td = s->isTemplateDeclaration();
4795 if (td)
4797 e = new DotTemplateExp(e->loc, e, td);
4798 e->semantic(sc);
4799 return e;
4802 TemplateInstance *ti = s->isTemplateInstance();
4803 if (ti)
4804 { if (!ti->semanticdone)
4805 ti->semantic(sc);
4806 s = ti->inst->toAlias();
4807 if (!s->isTemplateInstance())
4808 goto L1;
4809 Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
4810 de->type = e->type;
4811 return de;
4814 d = s->isDeclaration();
4815 if (!d)
4817 e->error("%s.%s is not a declaration", e->toChars(), ident->toChars());
4818 return new IntegerExp(e->loc, 1, Type::tint32);
4821 if (e->op == TOKtype)
4823 VarExp *ve;
4825 if (d->needThis() && (hasThis(sc) || !d->isFuncDeclaration()))
4827 if (sc->func)
4829 ClassDeclaration *thiscd;
4830 thiscd = sc->func->toParent()->isClassDeclaration();
4832 if (thiscd)
4834 ClassDeclaration *cd = e->type->isClassHandle();
4836 if (cd == thiscd)
4838 e = new ThisExp(e->loc);
4839 e = new DotTypeExp(e->loc, e, cd);
4840 de = new DotVarExp(e->loc, e, d);
4841 e = de->semantic(sc);
4842 return e;
4844 else if ((!cd || !cd->isBaseOf(thiscd, NULL)) &&
4845 !d->isFuncDeclaration())
4846 e->error("'this' is required, but %s is not a base class of %s", e->type->toChars(), thiscd->toChars());
4850 de = new DotVarExp(e->loc, new ThisExp(e->loc), d);
4851 e = de->semantic(sc);
4852 return e;
4854 else if (d->isTupleDeclaration())
4856 e = new TupleExp(e->loc, d->isTupleDeclaration());
4857 e = e->semantic(sc);
4858 return e;
4860 else
4861 ve = new VarExp(e->loc, d);
4862 return ve;
4865 if (d->isDataseg())
4867 // (e, d)
4868 VarExp *ve;
4870 accessCheck(e->loc, sc, e, d);
4871 ve = new VarExp(e->loc, d);
4872 e = new CommaExp(e->loc, e, ve);
4873 e->type = d->type;
4874 return e;
4877 if (d->parent && d->toParent()->isModule())
4879 // (e, d)
4880 VarExp *ve;
4882 ve = new VarExp(e->loc, d);
4883 e = new CommaExp(e->loc, e, ve);
4884 e->type = d->type;
4885 return e;
4888 de = new DotVarExp(e->loc, e, d);
4889 return de->semantic(sc);
4892 ClassDeclaration *TypeClass::isClassHandle()
4894 return sym;
4897 int TypeClass::isauto()
4899 return sym->isauto;
4902 int TypeClass::isBaseOf(Type *t, target_ptrdiff_t *poffset)
4904 if (t->ty == Tclass)
4905 { ClassDeclaration *cd;
4907 cd = ((TypeClass *)t)->sym;
4908 if (sym->isBaseOf(cd, poffset))
4909 return 1;
4911 return 0;
4914 MATCH TypeClass::implicitConvTo(Type *to)
4916 //printf("TypeClass::implicitConvTo('%s')\n", to->toChars());
4918 // Can always convert a "Foo" to a "Foo?"
4919 if (to->ty == Tmaybe && to->next)
4920 to = to->next;
4922 if (this == to)
4923 return MATCHexact;
4925 ClassDeclaration *cdto = to->isClassHandle();
4926 if (cdto && cdto->isBaseOf(sym, NULL))
4927 { //printf("is base\n");
4928 return MATCHconvert;
4931 if (global.params.Dversion == 1)
4933 // Allow conversion to (void *)
4934 if (to->ty == Tpointer && to->next->ty == Tvoid)
4935 return MATCHconvert;
4938 return MATCHnomatch;
4941 Expression *TypeClass::defaultInit(Loc loc)
4943 #if LOGDEFAULTINIT
4944 printf("TypeClass::defaultInit() '%s'\n", toChars());
4945 #endif
4946 Expression *e;
4947 e = new NullExp(loc);
4948 e->type = this;
4949 return e;
4952 int TypeClass::isZeroInit()
4954 return 1;
4957 int TypeClass::checkBoolean()
4959 return TRUE;
4962 int TypeClass::hasPointers()
4964 return TRUE;
4967 /***************************** TypeTuple *****************************/
4969 TypeTuple::TypeTuple(Arguments *arguments)
4970 : Type(Ttuple, NULL)
4972 //printf("TypeTuple(this = %p)\n", this);
4973 this->arguments = arguments;
4974 #ifdef DEBUG
4975 if (arguments)
4977 for (size_t i = 0; i < arguments->dim; i++)
4979 Argument *arg = (Argument *)arguments->data[i];
4980 assert(arg && arg->type);
4983 #endif
4986 /****************
4987 * Form TypeTuple from the types of the expressions.
4988 * Assume exps[] is already tuple expanded.
4991 TypeTuple::TypeTuple(Expressions *exps)
4992 : Type(Ttuple, NULL)
4994 Arguments *arguments = new Arguments;
4995 if (exps)
4997 arguments->setDim(exps->dim);
4998 for (size_t i = 0; i < exps->dim; i++)
4999 { Expression *e = (Expression *)exps->data[i];
5000 if (e->type->ty == Ttuple)
5001 e->error("cannot form tuple of tuples");
5002 Argument *arg = new Argument(STCin, e->type, NULL, NULL);
5003 arguments->data[i] = (void *)arg;
5006 this->arguments = arguments;
5009 Type *TypeTuple::syntaxCopy()
5011 Arguments *args = Argument::arraySyntaxCopy(arguments);
5012 Type *t = new TypeTuple(args);
5013 return t;
5016 Type *TypeTuple::semantic(Loc loc, Scope *sc)
5018 //printf("TypeTuple::semantic(this = %p)\n", this);
5019 if (!deco)
5020 deco = merge()->deco;
5022 /* Don't return merge(), because a tuple with one type has the
5023 * same deco as that type.
5025 return this;
5028 int TypeTuple::equals(Object *o)
5029 { Type *t;
5031 t = (Type *)o;
5032 //printf("TypeTuple::equals(%s, %s)\n", toChars(), t->toChars());
5033 if (this == t)
5035 return 1;
5037 if (t->ty == Ttuple)
5038 { TypeTuple *tt = (TypeTuple *)t;
5040 if (arguments->dim == tt->arguments->dim)
5042 for (size_t i = 0; i < tt->arguments->dim; i++)
5043 { Argument *arg1 = (Argument *)arguments->data[i];
5044 Argument *arg2 = (Argument *)tt->arguments->data[i];
5046 if (!arg1->type->equals(arg2->type))
5047 return 0;
5049 return 1;
5052 return 0;
5055 Type *TypeTuple::reliesOnTident()
5057 if (arguments)
5059 for (size_t i = 0; i < arguments->dim; i++)
5061 Argument *arg = (Argument *)arguments->data[i];
5062 Type *t = arg->type->reliesOnTident();
5063 if (t)
5064 return t;
5067 return NULL;
5070 void TypeTuple::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
5072 Argument::argsToCBuffer(buf, hgs, arguments, 0);
5075 void TypeTuple::toDecoBuffer(OutBuffer *buf)
5077 //printf("TypeTuple::toDecoBuffer() this = %p\n", this);
5078 OutBuffer buf2;
5079 Argument::argsToDecoBuffer(&buf2, arguments);
5080 unsigned len = buf2.offset;
5081 #if __NEWLIB_H__
5082 // newlib bug as of 1.14.0
5083 char * p = (char*) buf2.extractData();
5084 buf->printf("%c%d%.*s", mangleChar[ty], len, len, p ? p : "");
5085 #else
5086 buf->printf("%c%d%.*s", mangleChar[ty], len, len, (char *)buf2.extractData());
5087 #endif
5090 Expression *TypeTuple::getProperty(Loc loc, Identifier *ident)
5091 { Expression *e;
5093 #if LOGDOTEXP
5094 printf("TypeTuple::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars());
5095 #endif
5096 if (ident == Id::length)
5098 e = new IntegerExp(loc, arguments->dim, Type::tsize_t);
5100 else
5102 error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars());
5103 e = new IntegerExp(loc, 1, Type::tint32);
5105 return e;
5108 /***************************** TypeSlice *****************************/
5110 /* This is so we can slice a TypeTuple */
5112 TypeSlice::TypeSlice(Type *next, Expression *lwr, Expression *upr)
5113 : Type(Tslice, next)
5115 //printf("TypeSlice[%s .. %s]\n", lwr->toChars(), upr->toChars());
5116 this->lwr = lwr;
5117 this->upr = upr;
5120 Type *TypeSlice::syntaxCopy()
5122 Type *t = new TypeSlice(next->syntaxCopy(), lwr->syntaxCopy(), upr->syntaxCopy());
5123 return t;
5126 Type *TypeSlice::semantic(Loc loc, Scope *sc)
5128 //printf("TypeSlice::semantic() %s\n", toChars());
5129 next = next->semantic(loc, sc);
5130 //printf("next: %s\n", next->toChars());
5132 Type *tbn = next->toBasetype();
5133 if (tbn->ty != Ttuple)
5134 { error(loc, "can only slice tuple types, not %s", tbn->toChars());
5135 return Type::terror;
5137 TypeTuple *tt = (TypeTuple *)tbn;
5139 lwr = semanticLength(sc, tbn, lwr);
5140 lwr = lwr->optimize(WANTvalue);
5141 uinteger_t i1 = lwr->toUInteger();
5143 upr = semanticLength(sc, tbn, upr);
5144 upr = upr->optimize(WANTvalue);
5145 uinteger_t i2 = upr->toUInteger();
5147 if (!(i1 <= i2 && i2 <= tt->arguments->dim))
5148 { error(loc, "slice [%"PRIuMAX"..%"PRIuMAX"] is out of range of [0..%u]", i1, i2, tt->arguments->dim);
5149 return Type::terror;
5152 Arguments *args = new Arguments;
5153 args->reserve(i2 - i1);
5154 for (size_t i = i1; i < i2; i++)
5155 { Argument *arg = (Argument *)tt->arguments->data[i];
5156 args->push(arg);
5159 return new TypeTuple(args);
5162 void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
5164 next->resolve(loc, sc, pe, pt, ps);
5165 if (*pe)
5166 { // It's really a slice expression
5167 Expression *e;
5168 e = new SliceExp(loc, *pe, lwr, upr);
5169 *pe = e;
5171 else if (*ps)
5172 { Dsymbol *s = *ps;
5173 TupleDeclaration *td = s->isTupleDeclaration();
5174 if (td)
5176 /* It's a slice of a TupleDeclaration
5178 ScopeDsymbol *sym = new ArrayScopeSymbol(td);
5179 sym->parent = sc->scopesym;
5180 sc = sc->push(sym);
5182 lwr = lwr->semantic(sc);
5183 lwr = lwr->optimize(WANTvalue);
5184 uinteger_t i1 = lwr->toUInteger();
5186 upr = upr->semantic(sc);
5187 upr = upr->optimize(WANTvalue);
5188 uinteger_t i2 = upr->toUInteger();
5190 sc = sc->pop();
5192 if (!(i1 <= i2 && i2 <= td->objects->dim))
5193 { error(loc, "slice [%"PRIuMAX"u..%"PRIuMAX"u] is out of range of [0..%u]", i1, i2, td->objects->dim);
5194 goto Ldefault;
5197 if (i1 == 0 && i2 == td->objects->dim)
5199 *ps = td;
5200 return;
5203 /* Create a new TupleDeclaration which
5204 * is a slice [i1..i2] out of the old one.
5206 Objects *objects = new Objects;
5207 objects->setDim(i2 - i1);
5208 for (size_t i = 0; i < objects->dim; i++)
5210 objects->data[i] = td->objects->data[(size_t)i1 + i];
5213 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
5214 *ps = tds;
5216 else
5217 goto Ldefault;
5219 else
5221 Ldefault:
5222 Type::resolve(loc, sc, pe, pt, ps);
5226 void TypeSlice::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
5228 if (mod != this->mod)
5229 { toCBuffer3(buf, hgs, mod);
5230 return;
5232 next->toCBuffer2(buf, hgs, this->mod);
5234 buf->printf("[%s .. ", lwr->toChars());
5235 buf->printf("%s]", upr->toChars());
5238 /***************************** Argument *****************************/
5240 Argument::Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg)
5242 this->type = type;
5243 this->ident = ident;
5244 this->storageClass = storageClass;
5245 this->defaultArg = defaultArg;
5248 Argument *Argument::syntaxCopy()
5250 Argument *a = new Argument(storageClass,
5251 type ? type->syntaxCopy() : NULL,
5252 ident,
5253 defaultArg ? defaultArg->syntaxCopy() : NULL);
5254 return a;
5257 Arguments *Argument::arraySyntaxCopy(Arguments *args)
5258 { Arguments *a = NULL;
5260 if (args)
5262 a = new Arguments();
5263 a->setDim(args->dim);
5264 for (size_t i = 0; i < a->dim; i++)
5265 { Argument *arg = (Argument *)args->data[i];
5267 arg = arg->syntaxCopy();
5268 a->data[i] = (void *)arg;
5271 return a;
5274 char *Argument::argsTypesToChars(Arguments *args, int varargs)
5275 { OutBuffer *buf;
5277 buf = new OutBuffer();
5279 buf->writeByte('(');
5280 if (args)
5281 { int i;
5282 OutBuffer argbuf;
5283 HdrGenState hgs;
5285 for (i = 0; i < args->dim; i++)
5286 { Argument *arg;
5288 if (i)
5289 buf->writeByte(',');
5290 arg = (Argument *)args->data[i];
5291 argbuf.reset();
5292 arg->type->toCBuffer2(&argbuf, &hgs, 0);
5293 buf->write(&argbuf);
5295 if (varargs)
5297 if (i && varargs == 1)
5298 buf->writeByte(',');
5299 buf->writestring("...");
5302 buf->writeByte(')');
5304 return buf->toChars();
5307 void Argument::argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs)
5309 buf->writeByte('(');
5310 if (arguments)
5311 { int i;
5312 OutBuffer argbuf;
5314 for (i = 0; i < arguments->dim; i++)
5315 { Argument *arg;
5317 if (i)
5318 buf->writestring(", ");
5319 arg = (Argument *)arguments->data[i];
5320 if (arg->storageClass & STCout)
5321 buf->writestring("out ");
5322 else if (arg->storageClass & STCref)
5323 buf->writestring((global.params.Dversion == 1)
5324 ? (char *)"inout " : (char *)"ref ");
5325 else if (arg->storageClass & STClazy)
5326 buf->writestring("lazy ");
5327 argbuf.reset();
5328 arg->type->toCBuffer(&argbuf, arg->ident, hgs);
5329 if (arg->defaultArg)
5331 argbuf.writestring(" = ");
5332 arg->defaultArg->toCBuffer(&argbuf, hgs);
5334 buf->write(&argbuf);
5336 if (varargs)
5338 if (i && varargs == 1)
5339 buf->writeByte(',');
5340 buf->writestring("...");
5343 buf->writeByte(')');
5347 void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments)
5349 //printf("Argument::argsToDecoBuffer()\n");
5351 // Write argument types
5352 if (arguments)
5354 size_t dim = Argument::dim(arguments);
5355 for (size_t i = 0; i < dim; i++)
5357 Argument *arg = Argument::getNth(arguments, i);
5358 arg->toDecoBuffer(buf);
5363 /****************************************************
5364 * Determine if parameter is a lazy array of delegates.
5365 * If so, return the return type of those delegates.
5366 * If not, return NULL.
5369 Type *Argument::isLazyArray()
5371 // if (inout == Lazy)
5373 Type *tb = type->toBasetype();
5374 if (tb->ty == Tsarray || tb->ty == Tarray)
5376 Type *tel = tb->next->toBasetype();
5377 if (tel->ty == Tdelegate)
5379 TypeDelegate *td = (TypeDelegate *)tel;
5380 TypeFunction *tf = (TypeFunction *)td->next;
5382 if (!tf->varargs && Argument::dim(tf->parameters) == 0)
5384 return tf->next; // return type of delegate
5389 return NULL;
5392 void Argument::toDecoBuffer(OutBuffer *buf)
5394 switch (storageClass & (STCin | STCout | STCref | STClazy))
5395 { case 0:
5396 case STCin:
5397 break;
5398 case STCout:
5399 buf->writeByte('J');
5400 break;
5401 case STCref:
5402 buf->writeByte('K');
5403 break;
5404 case STClazy:
5405 buf->writeByte('L');
5406 break;
5407 default:
5408 #ifdef DEBUG
5409 halt();
5410 #endif
5411 assert(0);
5413 type->toDecoBuffer(buf);
5416 /***************************************
5417 * Determine number of arguments, folding in tuples.
5420 size_t Argument::dim(Arguments *args)
5422 size_t n = 0;
5423 if (args)
5425 for (size_t i = 0; i < args->dim; i++)
5426 { Argument *arg = (Argument *)args->data[i];
5427 Type *t = arg->type->toBasetype();
5429 if (t->ty == Ttuple)
5430 { TypeTuple *tu = (TypeTuple *)t;
5431 n += dim(tu->arguments);
5433 else
5434 n++;
5437 return n;
5440 /***************************************
5441 * Get nth Argument, folding in tuples.
5442 * Returns:
5443 * Argument* nth Argument
5444 * NULL not found, *pn gets incremented by the number
5445 * of Arguments
5448 Argument *Argument::getNth(Arguments *args, size_t nth, size_t *pn)
5450 if (!args)
5451 return NULL;
5453 size_t n = 0;
5454 for (size_t i = 0; i < args->dim; i++)
5455 { Argument *arg = (Argument *)args->data[i];
5456 Type *t = arg->type->toBasetype();
5458 if (t->ty == Ttuple)
5459 { TypeTuple *tu = (TypeTuple *)t;
5460 arg = getNth(tu->arguments, nth - n, &n);
5461 if (arg)
5462 return arg;
5464 else if (n == nth)
5465 return arg;
5466 else
5467 n++;
5470 if (pn)
5471 *pn += n;
5472 return NULL;