comparison dmd/mtype.c @ 1:c53b6e3fe49a trunk

[svn r5] Initial commit. Most things are very rough.
author lindquist
date Sat, 01 Sep 2007 21:43:27 +0200
parents
children dafae18f9c08
comparison
equal deleted inserted replaced
0:a9e71648e74d 1:c53b6e3fe49a
1
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2007 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.
10
11 #define __USE_ISOC99 1 // so signbit() gets defined
12 #include <math.h>
13
14 #include <stdio.h>
15 #include <assert.h>
16 #include <float.h>
17
18 #ifdef __DMC__
19 #include <fp.h>
20 #endif
21
22 #if _MSC_VER
23 #include <malloc.h>
24 #include <complex>
25 #include <limits>
26 #elif __DMC__
27 #include <complex.h>
28 #else
29 //#define signbit 56
30 #endif
31
32 #if __APPLE__
33 #include <math.h>
34 static double zero = 0;
35 #elif __GNUC__
36 #include <math.h>
37 #include <bits/nan.h>
38 #include <bits/mathdef.h>
39 static double zero = 0;
40 #endif
41
42 #include "mem.h"
43
44 #include "dsymbol.h"
45 #include "mtype.h"
46 #include "scope.h"
47 #include "init.h"
48 #include "expression.h"
49 #include "attrib.h"
50 #include "declaration.h"
51 #include "template.h"
52 #include "id.h"
53 #include "enum.h"
54 #include "import.h"
55 #include "aggregate.h"
56 #include "hdrgen.h"
57
58 FuncDeclaration *hasThis(Scope *sc);
59
60
61 #define LOGDOTEXP 0 // log ::dotExp()
62 #define LOGDEFAULTINIT 0 // log ::defaultInit()
63
64 // Allow implicit conversion of T[] to T*
65 #define IMPLICIT_ARRAY_TO_PTR global.params.useDeprecated
66
67 /* These have default values for 32 bit code, they get
68 * adjusted for 64 bit code.
69 */
70
71 int PTRSIZE = 4;
72 #if IN_LLVM
73 int REALSIZE = 8;
74 int REALPAD = 0;
75 #elif TARGET_LINUX
76 int REALSIZE = 12;
77 int REALPAD = 2;
78 #else
79 int REALSIZE = 10;
80 int REALPAD = 0;
81 #endif
82 int Tsize_t = Tuns32;
83 int Tptrdiff_t = Tint32;
84
85 /***************************** Type *****************************/
86
87 ClassDeclaration *Type::typeinfo;
88 ClassDeclaration *Type::typeinfoclass;
89 ClassDeclaration *Type::typeinfointerface;
90 ClassDeclaration *Type::typeinfostruct;
91 ClassDeclaration *Type::typeinfotypedef;
92 ClassDeclaration *Type::typeinfopointer;
93 ClassDeclaration *Type::typeinfoarray;
94 ClassDeclaration *Type::typeinfostaticarray;
95 ClassDeclaration *Type::typeinfoassociativearray;
96 ClassDeclaration *Type::typeinfoenum;
97 ClassDeclaration *Type::typeinfofunction;
98 ClassDeclaration *Type::typeinfodelegate;
99 ClassDeclaration *Type::typeinfotypelist;
100
101 Type *Type::tvoidptr;
102 Type *Type::basic[TMAX];
103 unsigned char Type::mangleChar[TMAX];
104 StringTable Type::stringtable;
105
106
107 Type::Type(TY ty, Type *next)
108 {
109 this->ty = ty;
110 this->next = next;
111 this->deco = NULL;
112 this->pto = NULL;
113 this->rto = NULL;
114 this->arrayof = NULL;
115 this->vtinfo = NULL;
116 this->ctype = NULL;
117 this->llvmType = 0;
118 }
119
120 Type *Type::syntaxCopy()
121 {
122 print();
123 fprintf(stdmsg, "ty = %d\n", ty);
124 assert(0);
125 return this;
126 }
127
128 int Type::equals(Object *o)
129 { Type *t;
130
131 t = (Type *)o;
132 //printf("Type::equals(%s, %s)\n", toChars(), t->toChars());
133 if (this == o ||
134 (t && deco == t->deco) && // deco strings are unique
135 deco != NULL) // and semantic() has been run
136 {
137 //printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
138 return 1;
139 }
140 //if (deco && t && t->deco) printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
141 return 0;
142 }
143
144 char Type::needThisPrefix()
145 {
146 return 'M'; // name mangling prefix for functions needing 'this'
147 }
148
149 void Type::init()
150 { int i;
151 int j;
152
153 Lexer::initKeywords();
154
155 mangleChar[Tarray] = 'A';
156 mangleChar[Tsarray] = 'G';
157 mangleChar[Taarray] = 'H';
158 mangleChar[Tpointer] = 'P';
159 mangleChar[Treference] = 'R';
160 mangleChar[Tfunction] = 'F';
161 mangleChar[Tident] = 'I';
162 mangleChar[Tclass] = 'C';
163 mangleChar[Tstruct] = 'S';
164 mangleChar[Tenum] = 'E';
165 mangleChar[Ttypedef] = 'T';
166 mangleChar[Tdelegate] = 'D';
167
168 mangleChar[Tnone] = 'n';
169 mangleChar[Tvoid] = 'v';
170 mangleChar[Tint8] = 'g';
171 mangleChar[Tuns8] = 'h';
172 mangleChar[Tint16] = 's';
173 mangleChar[Tuns16] = 't';
174 mangleChar[Tint32] = 'i';
175 mangleChar[Tuns32] = 'k';
176 mangleChar[Tint64] = 'l';
177 mangleChar[Tuns64] = 'm';
178 mangleChar[Tfloat32] = 'f';
179 mangleChar[Tfloat64] = 'd';
180 mangleChar[Tfloat80] = 'e';
181
182 mangleChar[Timaginary32] = 'o';
183 mangleChar[Timaginary64] = 'p';
184 mangleChar[Timaginary80] = 'j';
185 mangleChar[Tcomplex32] = 'q';
186 mangleChar[Tcomplex64] = 'r';
187 mangleChar[Tcomplex80] = 'c';
188
189 mangleChar[Tbool] = 'b';
190 mangleChar[Tascii] = 'a';
191 mangleChar[Twchar] = 'u';
192 mangleChar[Tdchar] = 'w';
193
194 mangleChar[Tbit] = '@';
195 mangleChar[Tinstance] = '@';
196 mangleChar[Terror] = '@';
197 mangleChar[Ttypeof] = '@';
198 mangleChar[Ttuple] = 'B';
199 mangleChar[Tslice] = '@';
200
201 for (i = 0; i < TMAX; i++)
202 { if (!mangleChar[i])
203 fprintf(stdmsg, "ty = %d\n", i);
204 assert(mangleChar[i]);
205 }
206
207 // Set basic types
208 static TY basetab[] =
209 { Tvoid, Tint8, Tuns8, Tint16, Tuns16, Tint32, Tuns32, Tint64, Tuns64,
210 Tfloat32, Tfloat64, Tfloat80,
211 Timaginary32, Timaginary64, Timaginary80,
212 Tcomplex32, Tcomplex64, Tcomplex80,
213 Tbit, Tbool,
214 Tascii, Twchar, Tdchar };
215
216 for (i = 0; i < sizeof(basetab) / sizeof(basetab[0]); i++)
217 basic[basetab[i]] = new TypeBasic(basetab[i]);
218 basic[Terror] = basic[Tint32];
219
220 tvoidptr = tvoid->pointerTo();
221
222 if (global.params.is64bit)
223 {
224 PTRSIZE = 8;
225 #if !IN_LLVM
226 if (global.params.isLinux)
227 REALSIZE = 10;
228 else
229 REALSIZE = 8;
230 #else
231 REALSIZE = 8;
232 REALPAD = 0;
233 #endif
234 Tsize_t = Tuns64;
235 Tptrdiff_t = Tint64;
236 }
237 else
238 {
239 PTRSIZE = 4;
240 #if IN_LLVM
241 REALSIZE = 8;
242 REALPAD = 0;
243 #elif TARGET_LINUX
244 REALSIZE = 12;
245 REALPAD = 2;
246 #else
247 REALSIZE = 10;
248 REALPAD = 0;
249 #endif
250 Tsize_t = Tuns32;
251 Tptrdiff_t = Tint32;
252 }
253 }
254
255 d_uns64 Type::size()
256 {
257 return size(0);
258 }
259
260 d_uns64 Type::size(Loc loc)
261 {
262 error(loc, "no size for type %s", toChars());
263 return 1;
264 }
265
266 unsigned Type::alignsize()
267 {
268 return size(0);
269 }
270
271 Type *Type::semantic(Loc loc, Scope *sc)
272 {
273 if (next)
274 next = next->semantic(loc,sc);
275 return merge();
276 }
277
278 Type *Type::pointerTo()
279 {
280 if (!pto)
281 { Type *t;
282
283 t = new TypePointer(this);
284 pto = t->merge();
285 }
286 return pto;
287 }
288
289 Type *Type::referenceTo()
290 {
291 if (!rto)
292 { Type *t;
293
294 t = new TypeReference(this);
295 rto = t->merge();
296 }
297 return rto;
298 }
299
300 Type *Type::arrayOf()
301 {
302 if (!arrayof)
303 { Type *t;
304
305 t = new TypeDArray(this);
306 arrayof = t->merge();
307 }
308 return arrayof;
309 }
310
311 Dsymbol *Type::toDsymbol(Scope *sc)
312 {
313 return NULL;
314 }
315
316 /*******************************
317 * If this is a shell around another type,
318 * get that other type.
319 */
320
321 Type *Type::toBasetype()
322 {
323 return this;
324 }
325
326 /********************************
327 * Name mangling.
328 */
329
330 void Type::toDecoBuffer(OutBuffer *buf)
331 {
332 buf->writeByte(mangleChar[ty]);
333 if (next)
334 {
335 assert(next != this);
336 //printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty);
337 next->toDecoBuffer(buf);
338 }
339 }
340
341 /********************************
342 * Name mangling.
343 */
344
345 void Type::toTypeInfoBuffer(OutBuffer *buf)
346 {
347 assert(0);
348 buf->writeByte(mangleChar[ty]);
349 }
350
351 /********************************
352 * For pretty-printing a type.
353 */
354
355 char *Type::toChars()
356 { OutBuffer *buf;
357 HdrGenState hgs;
358
359 buf = new OutBuffer();
360 toCBuffer2(buf, NULL, &hgs);
361 return buf->toChars();
362 }
363
364 void Type::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
365 {
366 OutBuffer tbuf;
367
368 toCBuffer2(&tbuf, ident, hgs);
369 buf->write(&tbuf);
370 }
371
372 void Type::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
373 {
374 buf->prependstring(toChars());
375 if (ident)
376 { buf->writeByte(' ');
377 buf->writestring(ident->toChars());
378 }
379 }
380
381 /************************************
382 */
383
384 Type *Type::merge()
385 { Type *t;
386
387 //printf("merge(%s)\n", toChars());
388 t = this;
389 assert(t);
390 if (!deco)
391 {
392 OutBuffer buf;
393 StringValue *sv;
394
395 if (next)
396 next = next->merge();
397 toDecoBuffer(&buf);
398 sv = stringtable.update((char *)buf.data, buf.offset);
399 if (sv->ptrvalue)
400 { t = (Type *) sv->ptrvalue;
401 assert(t->deco);
402 //printf("old value, deco = '%s' %p\n", t->deco, t->deco);
403 }
404 else
405 {
406 sv->ptrvalue = this;
407 deco = sv->lstring.string;
408 //printf("new value, deco = '%s' %p\n", t->deco, t->deco);
409 }
410 }
411 return t;
412 }
413
414 int Type::isbit()
415 {
416 return FALSE;
417 }
418
419 int Type::isintegral()
420 {
421 return FALSE;
422 }
423
424 int Type::isfloating()
425 {
426 return FALSE;
427 }
428
429 int Type::isreal()
430 {
431 return FALSE;
432 }
433
434 int Type::isimaginary()
435 {
436 return FALSE;
437 }
438
439 int Type::iscomplex()
440 {
441 return FALSE;
442 }
443
444 int Type::isscalar()
445 {
446 return FALSE;
447 }
448
449 int Type::isunsigned()
450 {
451 return FALSE;
452 }
453
454 ClassDeclaration *Type::isClassHandle()
455 {
456 return NULL;
457 }
458
459 int Type::isauto()
460 {
461 return FALSE;
462 }
463
464 int Type::isString()
465 {
466 return FALSE;
467 }
468
469 int Type::checkBoolean()
470 {
471 return isscalar();
472 }
473
474 /*********************************
475 * Check type to see if it is based on a deprecated symbol.
476 */
477
478 void Type::checkDeprecated(Loc loc, Scope *sc)
479 {
480 Type *t;
481 Dsymbol *s;
482
483 for (t = this; t; t = t->next)
484 {
485 s = t->toDsymbol(sc);
486 if (s)
487 s->checkDeprecated(loc, sc);
488 }
489 }
490
491
492 Expression *Type::defaultInit()
493 {
494 #if LOGDEFAULTINIT
495 printf("Type::defaultInit() '%s'\n", toChars());
496 #endif
497 return NULL;
498 }
499
500 int Type::isZeroInit()
501 {
502 return 0; // assume not
503 }
504
505 int Type::isBaseOf(Type *t, int *poffset)
506 {
507 return 0; // assume not
508 }
509
510 /********************************
511 * Determine if 'this' can be implicitly converted
512 * to type 'to'.
513 * Returns:
514 * 0 can't convert
515 * 1 can convert using implicit conversions
516 * 2 this and to are the same type
517 */
518
519 MATCH Type::implicitConvTo(Type *to)
520 {
521 //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to);
522 //printf("\tthis->next=%p, to->next=%p\n", this->next, to->next);
523 if (this == to)
524 return MATCHexact;
525 // if (to->ty == Tvoid)
526 // return 1;
527 return MATCHnomatch;
528 }
529
530 Expression *Type::getProperty(Loc loc, Identifier *ident)
531 { Expression *e;
532
533 #if LOGDOTEXP
534 printf("Type::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars());
535 #endif
536 if (ident == Id::__sizeof)
537 {
538 e = new IntegerExp(loc, size(loc), Type::tsize_t);
539 }
540 else if (ident == Id::size)
541 {
542 error(loc, ".size property should be replaced with .sizeof");
543 e = new IntegerExp(loc, size(loc), Type::tsize_t);
544 }
545 else if (ident == Id::alignof)
546 {
547 e = new IntegerExp(loc, alignsize(), Type::tsize_t);
548 }
549 else if (ident == Id::typeinfo)
550 {
551 if (!global.params.useDeprecated)
552 error(loc, ".typeinfo deprecated, use typeid(type)");
553 e = getTypeInfo(NULL);
554 }
555 else if (ident == Id::init)
556 {
557 e = defaultInit();
558 e->loc = loc;
559 }
560 else if (ident == Id::mangleof)
561 {
562 assert(deco);
563 e = new StringExp(loc, deco, strlen(deco), 'c');
564 Scope sc;
565 e = e->semantic(&sc);
566 }
567 else if (ident == Id::stringof)
568 { char *s = toChars();
569 e = new StringExp(loc, s, strlen(s), 'c');
570 Scope sc;
571 e = e->semantic(&sc);
572 }
573 else
574 {
575 error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars());
576 e = new IntegerExp(loc, 1, Type::tint32);
577 }
578 return e;
579 }
580
581 Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident)
582 { VarDeclaration *v = NULL;
583
584 #if LOGDOTEXP
585 printf("Type::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
586 #endif
587 if (e->op == TOKdotvar)
588 {
589 DotVarExp *dv = (DotVarExp *)e;
590 v = dv->var->isVarDeclaration();
591 }
592 else if (e->op == TOKvar)
593 {
594 VarExp *ve = (VarExp *)e;
595 v = ve->var->isVarDeclaration();
596 }
597 if (v)
598 {
599 if (ident == Id::offset)
600 {
601 if (!global.params.useDeprecated)
602 error(e->loc, ".offset deprecated, use .offsetof");
603 goto Loffset;
604 }
605 else if (ident == Id::offsetof)
606 {
607 Loffset:
608 if (v->storage_class & STCfield)
609 {
610 e = new IntegerExp(e->loc, v->offset, Type::tsize_t);
611 return e;
612 }
613 }
614 else if (ident == Id::init)
615 {
616 #if 0
617 if (v->init)
618 {
619 if (v->init->isVoidInitializer())
620 error(e->loc, "%s.init is void", v->toChars());
621 else
622 { Loc loc = e->loc;
623 e = v->init->toExpression();
624 if (e->op == TOKassign || e->op == TOKconstruct)
625 {
626 e = ((AssignExp *)e)->e2;
627
628 /* Take care of case where we used a 0
629 * to initialize the struct.
630 */
631 if (e->type == Type::tint32 &&
632 e->isBool(0) &&
633 v->type->toBasetype()->ty == Tstruct)
634 {
635 e = v->type->defaultInit();
636 }
637 }
638 e = e->optimize(WANTvalue | WANTinterpret);
639 // if (!e->isConst())
640 // error(loc, ".init cannot be evaluated at compile time");
641 }
642 return e;
643 }
644 #endif
645 return defaultInit();
646 }
647 }
648 if (ident == Id::typeinfo)
649 {
650 if (!global.params.useDeprecated)
651 error(e->loc, ".typeinfo deprecated, use typeid(type)");
652 e = getTypeInfo(sc);
653 return e;
654 }
655 if (ident == Id::stringof)
656 { char *s = e->toChars();
657 e = new StringExp(e->loc, s, strlen(s), 'c');
658 Scope sc;
659 e = e->semantic(&sc);
660 return e;
661 }
662 return getProperty(e->loc, ident);
663 }
664
665 unsigned Type::memalign(unsigned salign)
666 {
667 return salign;
668 }
669
670 void Type::error(Loc loc, const char *format, ...)
671 {
672 va_list ap;
673 va_start(ap, format);
674 ::verror(loc, format, ap);
675 va_end( ap );
676 }
677
678 Identifier *Type::getTypeInfoIdent(int internal)
679 {
680 // _init_10TypeInfo_%s
681 OutBuffer buf;
682 Identifier *id;
683 char *name;
684 int len;
685
686 //toTypeInfoBuffer(&buf);
687 if (internal)
688 { buf.writeByte(mangleChar[ty]);
689 if (ty == Tarray)
690 buf.writeByte(mangleChar[next->ty]);
691 }
692 else
693 toDecoBuffer(&buf);
694 len = buf.offset;
695 name = (char *)alloca(19 + sizeof(len) * 3 + len + 1);
696 buf.writeByte(0);
697 sprintf(name, "_D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
698 if (global.params.isWindows)
699 name++; // C mangling will add it back in
700 //printf("name = %s\n", name);
701 id = Lexer::idPool(name);
702 return id;
703 }
704
705 TypeBasic *Type::isTypeBasic()
706 {
707 return NULL;
708 }
709
710
711 void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
712 {
713 Type *t;
714
715 t = semantic(loc, sc);
716 *pt = t;
717 *pe = NULL;
718 *ps = NULL;
719 }
720
721 /*******************************
722 * If one of the subtypes of this type is a TypeIdentifier,
723 * i.e. it's an unresolved type, return that type.
724 */
725
726 Type *Type::reliesOnTident()
727 {
728 if (!next)
729 return NULL;
730 else
731 return next->reliesOnTident();
732 }
733
734 /********************************
735 * We've mistakenly parsed this as a type.
736 * Redo it as an Expression.
737 * NULL if cannot.
738 */
739
740 Expression *Type::toExpression()
741 {
742 return NULL;
743 }
744
745 /***************************************
746 * Return !=0 if type has pointers that need to
747 * be scanned by the GC during a collection cycle.
748 */
749
750 int Type::hasPointers()
751 {
752 return FALSE;
753 }
754
755 /* ============================= TypeBasic =========================== */
756
757 TypeBasic::TypeBasic(TY ty)
758 : Type(ty, NULL)
759 { char *c;
760 char *d;
761 unsigned flags;
762
763 #define TFLAGSintegral 1
764 #define TFLAGSfloating 2
765 #define TFLAGSunsigned 4
766 #define TFLAGSreal 8
767 #define TFLAGSimaginary 0x10
768 #define TFLAGScomplex 0x20
769
770 flags = 0;
771 switch (ty)
772 {
773 case Tvoid: d = Token::toChars(TOKvoid);
774 c = "void";
775 break;
776
777 case Tint8: d = Token::toChars(TOKint8);
778 c = "byte";
779 flags |= TFLAGSintegral;
780 break;
781
782 case Tuns8: d = Token::toChars(TOKuns8);
783 c = "ubyte";
784 flags |= TFLAGSintegral | TFLAGSunsigned;
785 break;
786
787 case Tint16: d = Token::toChars(TOKint16);
788 c = "short";
789 flags |= TFLAGSintegral;
790 break;
791
792 case Tuns16: d = Token::toChars(TOKuns16);
793 c = "ushort";
794 flags |= TFLAGSintegral | TFLAGSunsigned;
795 break;
796
797 case Tint32: d = Token::toChars(TOKint32);
798 c = "int";
799 flags |= TFLAGSintegral;
800 break;
801
802 case Tuns32: d = Token::toChars(TOKuns32);
803 c = "uint";
804 flags |= TFLAGSintegral | TFLAGSunsigned;
805 break;
806
807 case Tfloat32: d = Token::toChars(TOKfloat32);
808 c = "float";
809 flags |= TFLAGSfloating | TFLAGSreal;
810 break;
811
812 case Tint64: d = Token::toChars(TOKint64);
813 c = "long";
814 flags |= TFLAGSintegral;
815 break;
816
817 case Tuns64: d = Token::toChars(TOKuns64);
818 c = "ulong";
819 flags |= TFLAGSintegral | TFLAGSunsigned;
820 break;
821
822 case Tfloat64: d = Token::toChars(TOKfloat64);
823 c = "double";
824 flags |= TFLAGSfloating | TFLAGSreal;
825 break;
826
827 case Tfloat80: d = Token::toChars(TOKfloat80);
828 c = "real";
829 flags |= TFLAGSfloating | TFLAGSreal;
830 break;
831
832 case Timaginary32: d = Token::toChars(TOKimaginary32);
833 c = "ifloat";
834 flags |= TFLAGSfloating | TFLAGSimaginary;
835 break;
836
837 case Timaginary64: d = Token::toChars(TOKimaginary64);
838 c = "idouble";
839 flags |= TFLAGSfloating | TFLAGSimaginary;
840 break;
841
842 case Timaginary80: d = Token::toChars(TOKimaginary80);
843 c = "ireal";
844 flags |= TFLAGSfloating | TFLAGSimaginary;
845 break;
846
847 case Tcomplex32: d = Token::toChars(TOKcomplex32);
848 c = "cfloat";
849 flags |= TFLAGSfloating | TFLAGScomplex;
850 break;
851
852 case Tcomplex64: d = Token::toChars(TOKcomplex64);
853 c = "cdouble";
854 flags |= TFLAGSfloating | TFLAGScomplex;
855 break;
856
857 case Tcomplex80: d = Token::toChars(TOKcomplex80);
858 c = "creal";
859 flags |= TFLAGSfloating | TFLAGScomplex;
860 break;
861
862
863 case Tbit: d = Token::toChars(TOKbit);
864 c = "bit";
865 flags |= TFLAGSintegral | TFLAGSunsigned;
866 break;
867
868 case Tbool: d = "bool";
869 c = d;
870 flags |= TFLAGSintegral | TFLAGSunsigned;
871 break;
872
873 case Tascii: d = Token::toChars(TOKchar);
874 c = "char";
875 flags |= TFLAGSintegral | TFLAGSunsigned;
876 break;
877
878 case Twchar: d = Token::toChars(TOKwchar);
879 c = "wchar";
880 flags |= TFLAGSintegral | TFLAGSunsigned;
881 break;
882
883 case Tdchar: d = Token::toChars(TOKdchar);
884 c = "dchar";
885 flags |= TFLAGSintegral | TFLAGSunsigned;
886 break;
887
888 default: assert(0);
889 }
890 this->dstring = d;
891 this->cstring = c;
892 this->flags = flags;
893 merge();
894 }
895
896 Type *TypeBasic::syntaxCopy()
897 {
898 // No semantic analysis done on basic types, no need to copy
899 return this;
900 }
901
902
903 char *TypeBasic::toChars()
904 {
905 return dstring;
906 }
907
908 void TypeBasic::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
909 {
910 buf->prependstring(cstring);
911 if (ident)
912 { buf->writeByte(' ');
913 buf->writestring(ident->toChars());
914 }
915 }
916
917 d_uns64 TypeBasic::size(Loc loc)
918 { unsigned size;
919
920 //printf("TypeBasic::size()\n");
921 switch (ty)
922 {
923 case Tint8:
924 case Tuns8: size = 1; break;
925 case Tint16:
926 case Tuns16: size = 2; break;
927 case Tint32:
928 case Tuns32:
929 case Tfloat32:
930 case Timaginary32:
931 size = 4; break;
932 case Tint64:
933 case Tuns64:
934 case Tfloat64:
935 case Timaginary64:
936 size = 8; break;
937 case Tfloat80:
938 case Timaginary80:
939 size = REALSIZE; break;
940 case Tcomplex32:
941 size = 8; break;
942 case Tcomplex64:
943 size = 16; break;
944 case Tcomplex80:
945 size = REALSIZE * 2; break;
946
947 case Tvoid:
948 //size = Type::size(); // error message
949 size = 1;
950 break;
951
952 case Tbit: size = 1; break;
953 case Tbool: size = 1; break;
954 case Tascii: size = 1; break;
955 case Twchar: size = 2; break;
956 case Tdchar: size = 4; break;
957
958 default:
959 assert(0);
960 break;
961 }
962 //printf("TypeBasic::size() = %d\n", size);
963 return size;
964 }
965
966 unsigned TypeBasic::alignsize()
967 { unsigned sz;
968
969 switch (ty)
970 {
971 case Tfloat80:
972 case Timaginary80:
973 case Tcomplex80:
974 sz = REALSIZE;
975 break;
976
977 default:
978 sz = size(0);
979 break;
980 }
981 return sz;
982 }
983
984
985 Expression *TypeBasic::getProperty(Loc loc, Identifier *ident)
986 {
987 Expression *e;
988 d_int64 ivalue;
989 #ifdef IN_GCC
990 real_t fvalue;
991 #else
992 d_float80 fvalue;
993 #endif
994
995 //printf("TypeBasic::getProperty('%s')\n", ident->toChars());
996 if (ident == Id::max)
997 {
998 switch (ty)
999 {
1000 case Tint8: ivalue = 0x7F; goto Livalue;
1001 case Tuns8: ivalue = 0xFF; goto Livalue;
1002 case Tint16: ivalue = 0x7FFFUL; goto Livalue;
1003 case Tuns16: ivalue = 0xFFFFUL; goto Livalue;
1004 case Tint32: ivalue = 0x7FFFFFFFUL; goto Livalue;
1005 case Tuns32: ivalue = 0xFFFFFFFFUL; goto Livalue;
1006 case Tint64: ivalue = 0x7FFFFFFFFFFFFFFFLL; goto Livalue;
1007 case Tuns64: ivalue = 0xFFFFFFFFFFFFFFFFULL; goto Livalue;
1008 case Tbit: ivalue = 1; goto Livalue;
1009 case Tbool: ivalue = 1; goto Livalue;
1010 case Tchar: ivalue = 0xFF; goto Livalue;
1011 case Twchar: ivalue = 0xFFFFUL; goto Livalue;
1012 case Tdchar: ivalue = 0x10FFFFUL; goto Livalue;
1013
1014 case Tcomplex32:
1015 case Timaginary32:
1016 case Tfloat32: fvalue = FLT_MAX; goto Lfvalue;
1017 case Tcomplex64:
1018 case Timaginary64:
1019 case Tfloat64: fvalue = DBL_MAX; goto Lfvalue;
1020 case Tcomplex80:
1021 case Timaginary80:
1022 case Tfloat80: fvalue = LDBL_MAX; goto Lfvalue;
1023 }
1024 }
1025 else if (ident == Id::min)
1026 {
1027 switch (ty)
1028 {
1029 case Tint8: ivalue = -128; goto Livalue;
1030 case Tuns8: ivalue = 0; goto Livalue;
1031 case Tint16: ivalue = -32768; goto Livalue;
1032 case Tuns16: ivalue = 0; goto Livalue;
1033 case Tint32: ivalue = -2147483647L - 1; goto Livalue;
1034 case Tuns32: ivalue = 0; goto Livalue;
1035 case Tint64: ivalue = (-9223372036854775807LL-1LL); goto Livalue;
1036 case Tuns64: ivalue = 0; goto Livalue;
1037 case Tbit: ivalue = 0; goto Livalue;
1038 case Tbool: ivalue = 0; goto Livalue;
1039 case Tchar: ivalue = 0; goto Livalue;
1040 case Twchar: ivalue = 0; goto Livalue;
1041 case Tdchar: ivalue = 0; goto Livalue;
1042
1043 case Tcomplex32:
1044 case Timaginary32:
1045 case Tfloat32: fvalue = FLT_MIN; goto Lfvalue;
1046 case Tcomplex64:
1047 case Timaginary64:
1048 case Tfloat64: fvalue = DBL_MIN; goto Lfvalue;
1049 case Tcomplex80:
1050 case Timaginary80:
1051 case Tfloat80: fvalue = LDBL_MIN; goto Lfvalue;
1052 }
1053 }
1054 else if (ident == Id::nan)
1055 {
1056 switch (ty)
1057 {
1058 case Tcomplex32:
1059 case Tcomplex64:
1060 case Tcomplex80:
1061 case Timaginary32:
1062 case Timaginary64:
1063 case Timaginary80:
1064 case Tfloat32:
1065 case Tfloat64:
1066 case Tfloat80:
1067 {
1068 #if IN_GCC
1069 // mode doesn't matter, will be converted in RealExp anyway
1070 fvalue = real_t::getnan(real_t::LongDouble);
1071 #elif __GNUC__
1072 // gcc nan's have the sign bit set by default, so turn it off
1073 // Need the volatile to prevent gcc from doing incorrect
1074 // constant folding.
1075 volatile d_float80 foo;
1076 foo = NAN;
1077 if (signbit(foo)) // signbit sometimes, not always, set
1078 foo = -foo; // turn off sign bit
1079 fvalue = foo;
1080 #elif _MSC_VER
1081 unsigned long nan[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
1082 fvalue = *(double*)nan;
1083 #else
1084 fvalue = NAN;
1085 #endif
1086 goto Lfvalue;
1087 }
1088 }
1089 }
1090 else if (ident == Id::infinity)
1091 {
1092 switch (ty)
1093 {
1094 case Tcomplex32:
1095 case Tcomplex64:
1096 case Tcomplex80:
1097 case Timaginary32:
1098 case Timaginary64:
1099 case Timaginary80:
1100 case Tfloat32:
1101 case Tfloat64:
1102 case Tfloat80:
1103 #if IN_GCC
1104 fvalue = real_t::getinfinity();
1105 #elif __GNUC__
1106 fvalue = 1 / zero;
1107 #elif _MSC_VER
1108 fvalue = std::numeric_limits<long double>::infinity();
1109 #else
1110 fvalue = INFINITY;
1111 #endif
1112 goto Lfvalue;
1113 }
1114 }
1115 else if (ident == Id::dig)
1116 {
1117 switch (ty)
1118 {
1119 case Tcomplex32:
1120 case Timaginary32:
1121 case Tfloat32: ivalue = FLT_DIG; goto Lint;
1122 case Tcomplex64:
1123 case Timaginary64:
1124 case Tfloat64: ivalue = DBL_DIG; goto Lint;
1125 case Tcomplex80:
1126 case Timaginary80:
1127 case Tfloat80: ivalue = LDBL_DIG; goto Lint;
1128 }
1129 }
1130 else if (ident == Id::epsilon)
1131 {
1132 switch (ty)
1133 {
1134 case Tcomplex32:
1135 case Timaginary32:
1136 case Tfloat32: fvalue = FLT_EPSILON; goto Lfvalue;
1137 case Tcomplex64:
1138 case Timaginary64:
1139 case Tfloat64: fvalue = DBL_EPSILON; goto Lfvalue;
1140 case Tcomplex80:
1141 case Timaginary80:
1142 case Tfloat80: fvalue = LDBL_EPSILON; goto Lfvalue;
1143 }
1144 }
1145 else if (ident == Id::mant_dig)
1146 {
1147 switch (ty)
1148 {
1149 case Tcomplex32:
1150 case Timaginary32:
1151 case Tfloat32: ivalue = FLT_MANT_DIG; goto Lint;
1152 case Tcomplex64:
1153 case Timaginary64:
1154 case Tfloat64: ivalue = DBL_MANT_DIG; goto Lint;
1155 case Tcomplex80:
1156 case Timaginary80:
1157 case Tfloat80: ivalue = LDBL_MANT_DIG; goto Lint;
1158 }
1159 }
1160 else if (ident == Id::max_10_exp)
1161 {
1162 switch (ty)
1163 {
1164 case Tcomplex32:
1165 case Timaginary32:
1166 case Tfloat32: ivalue = FLT_MAX_10_EXP; goto Lint;
1167 case Tcomplex64:
1168 case Timaginary64:
1169 case Tfloat64: ivalue = DBL_MAX_10_EXP; goto Lint;
1170 case Tcomplex80:
1171 case Timaginary80:
1172 case Tfloat80: ivalue = LDBL_MAX_10_EXP; goto Lint;
1173 }
1174 }
1175 else if (ident == Id::max_exp)
1176 {
1177 switch (ty)
1178 {
1179 case Tcomplex32:
1180 case Timaginary32:
1181 case Tfloat32: ivalue = FLT_MAX_EXP; goto Lint;
1182 case Tcomplex64:
1183 case Timaginary64:
1184 case Tfloat64: ivalue = DBL_MAX_EXP; goto Lint;
1185 case Tcomplex80:
1186 case Timaginary80:
1187 case Tfloat80: ivalue = LDBL_MAX_EXP; goto Lint;
1188 }
1189 }
1190 else if (ident == Id::min_10_exp)
1191 {
1192 switch (ty)
1193 {
1194 case Tcomplex32:
1195 case Timaginary32:
1196 case Tfloat32: ivalue = FLT_MIN_10_EXP; goto Lint;
1197 case Tcomplex64:
1198 case Timaginary64:
1199 case Tfloat64: ivalue = DBL_MIN_10_EXP; goto Lint;
1200 case Tcomplex80:
1201 case Timaginary80:
1202 case Tfloat80: ivalue = LDBL_MIN_10_EXP; goto Lint;
1203 }
1204 }
1205 else if (ident == Id::min_exp)
1206 {
1207 switch (ty)
1208 {
1209 case Tcomplex32:
1210 case Timaginary32:
1211 case Tfloat32: ivalue = FLT_MIN_EXP; goto Lint;
1212 case Tcomplex64:
1213 case Timaginary64:
1214 case Tfloat64: ivalue = DBL_MIN_EXP; goto Lint;
1215 case Tcomplex80:
1216 case Timaginary80:
1217 case Tfloat80: ivalue = LDBL_MIN_EXP; goto Lint;
1218 }
1219 }
1220
1221 Ldefault:
1222 return Type::getProperty(loc, ident);
1223
1224 Livalue:
1225 e = new IntegerExp(loc, ivalue, this);
1226 return e;
1227
1228 Lfvalue:
1229 if (isreal() || isimaginary())
1230 e = new RealExp(loc, fvalue, this);
1231 else
1232 {
1233 complex_t cvalue;
1234
1235 #if __DMC__
1236 //((real_t *)&cvalue)[0] = fvalue;
1237 //((real_t *)&cvalue)[1] = fvalue;
1238 cvalue = fvalue + fvalue * I;
1239 #else
1240 cvalue.re = fvalue;
1241 cvalue.im = fvalue;
1242 #endif
1243 //for (int i = 0; i < 20; i++)
1244 // printf("%02x ", ((unsigned char *)&cvalue)[i]);
1245 //printf("\n");
1246 e = new ComplexExp(loc, cvalue, this);
1247 }
1248 return e;
1249
1250 Lint:
1251 e = new IntegerExp(loc, ivalue, Type::tint32);
1252 return e;
1253 }
1254
1255 Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
1256 {
1257 #if LOGDOTEXP
1258 printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1259 #endif
1260 Type *t;
1261
1262 if (ident == Id::re)
1263 {
1264 switch (ty)
1265 {
1266 case Tcomplex32: t = tfloat32; goto L1;
1267 case Tcomplex64: t = tfloat64; goto L1;
1268 case Tcomplex80: t = tfloat80; goto L1;
1269 L1:
1270 e = e->castTo(sc, t);
1271 break;
1272
1273 case Tfloat32:
1274 case Tfloat64:
1275 case Tfloat80:
1276 break;
1277
1278 case Timaginary32: t = tfloat32; goto L2;
1279 case Timaginary64: t = tfloat64; goto L2;
1280 case Timaginary80: t = tfloat80; goto L2;
1281 L2:
1282 e = new RealExp(0, 0.0, t);
1283 break;
1284
1285 default:
1286 return Type::getProperty(e->loc, ident);
1287 }
1288 }
1289 else if (ident == Id::im)
1290 { Type *t2;
1291
1292 switch (ty)
1293 {
1294 case Tcomplex32: t = timaginary32; t2 = tfloat32; goto L3;
1295 case Tcomplex64: t = timaginary64; t2 = tfloat64; goto L3;
1296 case Tcomplex80: t = timaginary80; t2 = tfloat80; goto L3;
1297 L3:
1298 e = e->castTo(sc, t);
1299 e->type = t2;
1300 break;
1301
1302 case Timaginary32: t = tfloat32; goto L4;
1303 case Timaginary64: t = tfloat64; goto L4;
1304 case Timaginary80: t = tfloat80; goto L4;
1305 L4:
1306 e->type = t;
1307 break;
1308
1309 case Tfloat32:
1310 case Tfloat64:
1311 case Tfloat80:
1312 e = new RealExp(0, 0.0, this);
1313 break;
1314
1315 default:
1316 return Type::getProperty(e->loc, ident);
1317 }
1318 }
1319 else
1320 {
1321 return Type::dotExp(sc, e, ident);
1322 }
1323 return e;
1324 }
1325
1326 Expression *TypeBasic::defaultInit()
1327 { integer_t value = 0;
1328
1329 #if LOGDEFAULTINIT
1330 printf("TypeBasic::defaultInit() '%s'\n", toChars());
1331 #endif
1332 switch (ty)
1333 {
1334 case Tchar:
1335 value = 0xFF;
1336 break;
1337
1338 case Twchar:
1339 case Tdchar:
1340 value = 0xFFFF;
1341 break;
1342
1343 case Timaginary32:
1344 case Timaginary64:
1345 case Timaginary80:
1346 case Tfloat32:
1347 case Tfloat64:
1348 case Tfloat80:
1349 case Tcomplex32:
1350 case Tcomplex64:
1351 case Tcomplex80:
1352 return getProperty(0, Id::nan);
1353 }
1354 return new IntegerExp(0, value, this);
1355 }
1356
1357 int TypeBasic::isZeroInit()
1358 {
1359 switch (ty)
1360 {
1361 case Tchar:
1362 case Twchar:
1363 case Tdchar:
1364 case Timaginary32:
1365 case Timaginary64:
1366 case Timaginary80:
1367 case Tfloat32:
1368 case Tfloat64:
1369 case Tfloat80:
1370 case Tcomplex32:
1371 case Tcomplex64:
1372 case Tcomplex80:
1373 return 0; // no
1374 }
1375 return 1; // yes
1376 }
1377
1378 int TypeBasic::isbit()
1379 {
1380 return (ty == Tbit);
1381 }
1382
1383 int TypeBasic::isintegral()
1384 {
1385 //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags);
1386 return flags & TFLAGSintegral;
1387 }
1388
1389 int TypeBasic::isfloating()
1390 {
1391 return flags & TFLAGSfloating;
1392 }
1393
1394 int TypeBasic::isreal()
1395 {
1396 return flags & TFLAGSreal;
1397 }
1398
1399 int TypeBasic::isimaginary()
1400 {
1401 return flags & TFLAGSimaginary;
1402 }
1403
1404 int TypeBasic::iscomplex()
1405 {
1406 return flags & TFLAGScomplex;
1407 }
1408
1409 int TypeBasic::isunsigned()
1410 {
1411 return flags & TFLAGSunsigned;
1412 }
1413
1414 int TypeBasic::isscalar()
1415 {
1416 return flags & (TFLAGSintegral | TFLAGSfloating);
1417 }
1418
1419 MATCH TypeBasic::implicitConvTo(Type *to)
1420 {
1421 //printf("TypeBasic::implicitConvTo(%s) from %s\n", to->toChars(), toChars());
1422 if (this == to)
1423 return MATCHexact;
1424
1425 if (ty == Tvoid || to->ty == Tvoid)
1426 return MATCHnomatch;
1427 if (1 || global.params.Dversion == 1)
1428 {
1429 if (to->ty == Tbool)
1430 return MATCHnomatch;
1431 }
1432 else
1433 {
1434 if (ty == Tbool || to->ty == Tbool)
1435 return MATCHnomatch;
1436 }
1437 if (!to->isTypeBasic())
1438 return MATCHnomatch;
1439
1440 TypeBasic *tob = (TypeBasic *)to;
1441 if (flags & TFLAGSintegral)
1442 {
1443 // Disallow implicit conversion of integers to imaginary or complex
1444 if (tob->flags & (TFLAGSimaginary | TFLAGScomplex))
1445 return MATCHnomatch;
1446
1447 // If converting to integral
1448 if (0 && global.params.Dversion > 1 && tob->flags & TFLAGSintegral)
1449 { d_uns64 sz = size(0);
1450 d_uns64 tosz = tob->size(0);
1451
1452 /* Can't convert to smaller size or, if same size, change sign
1453 */
1454 if (sz > tosz)
1455 return MATCHnomatch;
1456
1457 /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned)
1458 return MATCHnomatch;*/
1459 }
1460 }
1461 else if (flags & TFLAGSfloating)
1462 {
1463 // Disallow implicit conversion of floating point to integer
1464 if (tob->flags & TFLAGSintegral)
1465 return MATCHnomatch;
1466
1467 assert(tob->flags & TFLAGSfloating);
1468
1469 // Disallow implicit conversion from complex to non-complex
1470 if (flags & TFLAGScomplex && !(tob->flags & TFLAGScomplex))
1471 return MATCHnomatch;
1472
1473 // Disallow implicit conversion of real or imaginary to complex
1474 if (flags & (TFLAGSreal | TFLAGSimaginary) &&
1475 tob->flags & TFLAGScomplex)
1476 return MATCHnomatch;
1477
1478 // Disallow implicit conversion to-from real and imaginary
1479 if ((flags & (TFLAGSreal | TFLAGSimaginary)) !=
1480 (tob->flags & (TFLAGSreal | TFLAGSimaginary)))
1481 return MATCHnomatch;
1482 }
1483 return MATCHconvert;
1484 }
1485
1486 TypeBasic *TypeBasic::isTypeBasic()
1487 {
1488 return (TypeBasic *)this;
1489 }
1490
1491 /***************************** TypeArray *****************************/
1492
1493 TypeArray::TypeArray(TY ty, Type *next)
1494 : Type(ty, next)
1495 {
1496 }
1497
1498 Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
1499 {
1500 Type *n = this->next->toBasetype(); // uncover any typedef's
1501
1502 #if LOGDOTEXP
1503 printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1504 #endif
1505 if (ident == Id::reverse && (n->ty == Tchar || n->ty == Twchar))
1506 {
1507 Expression *ec;
1508 FuncDeclaration *fd;
1509 Expressions *arguments;
1510 char *nm;
1511 static char *name[2] = { "_adReverseChar", "_adReverseWchar" };
1512
1513 nm = name[n->ty == Twchar];
1514 fd = FuncDeclaration::genCfunc(Type::tindex, nm);
1515 ec = new VarExp(0, fd);
1516 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1517 arguments = new Expressions();
1518 arguments->push(e);
1519 e = new CallExp(e->loc, ec, arguments);
1520 e->type = next->arrayOf();
1521 }
1522 else if (ident == Id::sort && (n->ty == Tchar || n->ty == Twchar))
1523 {
1524 Expression *ec;
1525 FuncDeclaration *fd;
1526 Expressions *arguments;
1527 char *nm;
1528 static char *name[2] = { "_adSortChar", "_adSortWchar" };
1529
1530 nm = name[n->ty == Twchar];
1531 fd = FuncDeclaration::genCfunc(Type::tindex, nm);
1532 ec = new VarExp(0, fd);
1533 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1534 arguments = new Expressions();
1535 arguments->push(e);
1536 e = new CallExp(e->loc, ec, arguments);
1537 e->type = next->arrayOf();
1538 }
1539 else if (ident == Id::reverse || ident == Id::dup)
1540 {
1541 Expression *ec;
1542 FuncDeclaration *fd;
1543 Expressions *arguments;
1544 int size = next->size(e->loc);
1545 int dup;
1546
1547 assert(size);
1548 dup = (ident == Id::dup);
1549 fd = FuncDeclaration::genCfunc(Type::tindex, dup ? Id::adDup : Id::adReverse);
1550 ec = new VarExp(0, fd);
1551 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1552 arguments = new Expressions();
1553 if (dup)
1554 arguments->push(getTypeInfo(sc));
1555 arguments->push(e);
1556 if (!dup)
1557 arguments->push(new IntegerExp(0, size, Type::tint32));
1558 e = new CallExp(e->loc, ec, arguments);
1559 e->type = next->arrayOf();
1560 }
1561 else if (ident == Id::sort)
1562 {
1563 Expression *ec;
1564 FuncDeclaration *fd;
1565 Expressions *arguments;
1566
1567 fd = FuncDeclaration::genCfunc(tint32->arrayOf(),
1568 (char*)(n->ty == Tbit ? "_adSortBit" : "_adSort"));
1569 ec = new VarExp(0, fd);
1570 e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
1571 arguments = new Expressions();
1572 arguments->push(e);
1573 if (next->ty != Tbit)
1574 arguments->push(n->ty == Tsarray
1575 ? n->getTypeInfo(sc) // don't convert to dynamic array
1576 : n->getInternalTypeInfo(sc));
1577 e = new CallExp(e->loc, ec, arguments);
1578 e->type = next->arrayOf();
1579 }
1580 else
1581 {
1582 e = Type::dotExp(sc, e, ident);
1583 }
1584 return e;
1585 }
1586
1587 void TypeArray::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
1588 {
1589 #if 1
1590 OutBuffer buf2;
1591 toPrettyBracket(&buf2, hgs);
1592 buf->prependstring(buf2.toChars());
1593 if (ident)
1594 {
1595 buf->writeByte(' ');
1596 buf->writestring(ident->toChars());
1597 }
1598 next->toCBuffer2(buf, NULL, hgs);
1599 #elif 1
1600 // The D way
1601 Type *t;
1602 OutBuffer buf2;
1603 for (t = this; 1; t = t->next)
1604 { TypeArray *ta;
1605
1606 ta = dynamic_cast<TypeArray *>(t);
1607 if (!ta)
1608 break;
1609 ta->toPrettyBracket(&buf2, hgs);
1610 }
1611 buf->prependstring(buf2.toChars());
1612 if (ident)
1613 {
1614 buf2.writestring(ident->toChars());
1615 }
1616 t->toCBuffer2(buf, NULL, hgs);
1617 #else
1618 // The C way
1619 if (buf->offset)
1620 { buf->bracket('(', ')');
1621 assert(!ident);
1622 }
1623 else if (ident)
1624 buf->writestring(ident->toChars());
1625 Type *t = this;
1626 do
1627 { Expression *dim;
1628 buf->writeByte('[');
1629 dim = ((TypeSArray *)t)->dim;
1630 if (dim)
1631 buf->printf("%lld", dim->toInteger());
1632 buf->writeByte(']');
1633 t = t->next;
1634 } while (t->ty == Tsarray);
1635 t->toCBuffer2(buf, NULL, hgs);
1636 #endif
1637 }
1638
1639
1640 /***************************** TypeSArray *****************************/
1641
1642 TypeSArray::TypeSArray(Type *t, Expression *dim)
1643 : TypeArray(Tsarray, t)
1644 {
1645 //printf("TypeSArray(%s)\n", dim->toChars());
1646 this->dim = dim;
1647 }
1648
1649 Type *TypeSArray::syntaxCopy()
1650 {
1651 Type *t = next->syntaxCopy();
1652 Expression *e = dim->syntaxCopy();
1653 t = new TypeSArray(t, e);
1654 return t;
1655 }
1656
1657 d_uns64 TypeSArray::size(Loc loc)
1658 { integer_t sz;
1659
1660 if (!dim)
1661 return Type::size(loc);
1662 sz = dim->toInteger();
1663 if (next->toBasetype()->ty == Tbit) // if array of bits
1664 {
1665 if (sz + 31 < sz)
1666 goto Loverflow;
1667 sz = ((sz + 31) & ~31) / 8; // size in bytes, rounded up to 32 bit dwords
1668 }
1669 else
1670 { integer_t n, n2;
1671
1672 n = next->size();
1673 n2 = n * sz;
1674 if (n && (n2 / n) != sz)
1675 goto Loverflow;
1676 sz = n2;
1677 }
1678 return sz;
1679
1680 Loverflow:
1681 error(loc, "index %jd overflow for static array", sz);
1682 return 1;
1683 }
1684
1685 unsigned TypeSArray::alignsize()
1686 {
1687 return next->alignsize();
1688 }
1689
1690 /**************************
1691 * This evaluates exp while setting length to be the number
1692 * of elements in the tuple t.
1693 */
1694 Expression *semanticLength(Scope *sc, Type *t, Expression *exp)
1695 {
1696 if (t->ty == Ttuple)
1697 { ScopeDsymbol *sym = new ArrayScopeSymbol((TypeTuple *)t);
1698 sym->parent = sc->scopesym;
1699 sc = sc->push(sym);
1700
1701 exp = exp->semantic(sc);
1702
1703 sc->pop();
1704 }
1705 else
1706 exp = exp->semantic(sc);
1707 return exp;
1708 }
1709
1710 Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp)
1711 {
1712 ScopeDsymbol *sym = new ArrayScopeSymbol(s);
1713 sym->parent = sc->scopesym;
1714 sc = sc->push(sym);
1715
1716 exp = exp->semantic(sc);
1717
1718 sc->pop();
1719 return exp;
1720 }
1721
1722 void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
1723 {
1724 //printf("TypeSArray::resolve() %s\n", toChars());
1725 next->resolve(loc, sc, pe, pt, ps);
1726 //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
1727 if (*pe)
1728 { // It's really an index expression
1729 Expression *e;
1730 e = new IndexExp(loc, *pe, dim);
1731 *pe = e;
1732 }
1733 else if (*ps)
1734 { Dsymbol *s = *ps;
1735 TupleDeclaration *td = s->isTupleDeclaration();
1736 if (td)
1737 {
1738 ScopeDsymbol *sym = new ArrayScopeSymbol(td);
1739 sym->parent = sc->scopesym;
1740 sc = sc->push(sym);
1741
1742 dim = dim->semantic(sc);
1743 dim = dim->optimize(WANTvalue | WANTinterpret);
1744 uinteger_t d = dim->toUInteger();
1745
1746 sc = sc->pop();
1747
1748 if (d >= td->objects->dim)
1749 { error(loc, "tuple index %ju exceeds %u", d, td->objects->dim);
1750 goto Ldefault;
1751 }
1752 Object *o = (Object *)td->objects->data[(size_t)d];
1753 if (o->dyncast() == DYNCAST_DSYMBOL)
1754 {
1755 *ps = (Dsymbol *)o;
1756 return;
1757 }
1758 if (o->dyncast() == DYNCAST_EXPRESSION)
1759 {
1760 *ps = NULL;
1761 *pe = (Expression *)o;
1762 return;
1763 }
1764
1765 /* Create a new TupleDeclaration which
1766 * is a slice [d..d+1] out of the old one.
1767 * Do it this way because TemplateInstance::semanticTiargs()
1768 * can handle unresolved Objects this way.
1769 */
1770 Objects *objects = new Objects;
1771 objects->setDim(1);
1772 objects->data[0] = o;
1773
1774 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
1775 *ps = tds;
1776 }
1777 else
1778 goto Ldefault;
1779 }
1780 else
1781 {
1782 Ldefault:
1783 Type::resolve(loc, sc, pe, pt, ps);
1784 }
1785 }
1786
1787 Type *TypeSArray::semantic(Loc loc, Scope *sc)
1788 {
1789 //printf("TypeSArray::semantic() %s\n", toChars());
1790
1791 Type *t;
1792 Expression *e;
1793 Dsymbol *s;
1794 next->resolve(loc, sc, &e, &t, &s);
1795 if (dim && s && s->isTupleDeclaration())
1796 { TupleDeclaration *sd = s->isTupleDeclaration();
1797
1798 dim = semanticLength(sc, sd, dim);
1799 dim = dim->optimize(WANTvalue | WANTinterpret);
1800 uinteger_t d = dim->toUInteger();
1801
1802 if (d >= sd->objects->dim)
1803 { error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim);
1804 return Type::terror;
1805 }
1806 Object *o = (Object *)sd->objects->data[(size_t)d];
1807 if (o->dyncast() != DYNCAST_TYPE)
1808 { error(loc, "%s is not a type", toChars());
1809 return Type::terror;
1810 }
1811 t = (Type *)o;
1812 return t;
1813 }
1814
1815 next = next->semantic(loc,sc);
1816 Type *tbn = next->toBasetype();
1817
1818 if (dim)
1819 { integer_t n, n2;
1820
1821 dim = semanticLength(sc, tbn, dim);
1822
1823 dim = dim->optimize(WANTvalue | WANTinterpret);
1824 integer_t d1 = dim->toInteger();
1825 dim = dim->castTo(sc, tsize_t);
1826 dim = dim->optimize(WANTvalue);
1827 integer_t d2 = dim->toInteger();
1828
1829 if (d1 != d2)
1830 goto Loverflow;
1831
1832 if (tbn->isintegral() ||
1833 tbn->isfloating() ||
1834 tbn->ty == Tpointer ||
1835 tbn->ty == Tarray ||
1836 tbn->ty == Tsarray ||
1837 tbn->ty == Taarray ||
1838 tbn->ty == Tclass)
1839 {
1840 /* Only do this for types that don't need to have semantic()
1841 * run on them for the size, since they may be forward referenced.
1842 */
1843 n = tbn->size(loc);
1844 n2 = n * d2;
1845 if ((int)n2 < 0)
1846 goto Loverflow;
1847 if (n2 >= 0x1000000) // put a 'reasonable' limit on it
1848 goto Loverflow;
1849 if (n && n2 / n != d2)
1850 {
1851 Loverflow:
1852 error(loc, "index %jd overflow for static array", d1);
1853 dim = new IntegerExp(0, 1, tsize_t);
1854 }
1855 }
1856 }
1857 switch (tbn->ty)
1858 {
1859 case Ttuple:
1860 { // Index the tuple to get the type
1861 assert(dim);
1862 TypeTuple *tt = (TypeTuple *)tbn;
1863 uinteger_t d = dim->toUInteger();
1864
1865 if (d >= tt->arguments->dim)
1866 { error(loc, "tuple index %ju exceeds %u", d, tt->arguments->dim);
1867 return Type::terror;
1868 }
1869 Argument *arg = (Argument *)tt->arguments->data[(size_t)d];
1870 return arg->type;
1871 }
1872 case Tfunction:
1873 case Tnone:
1874 error(loc, "can't have array of %s", tbn->toChars());
1875 tbn = next = tint32;
1876 break;
1877 }
1878 if (tbn->isauto())
1879 error(loc, "cannot have array of auto %s", tbn->toChars());
1880 return merge();
1881 }
1882
1883 void TypeSArray::toDecoBuffer(OutBuffer *buf)
1884 {
1885 buf->writeByte(mangleChar[ty]);
1886 if (dim)
1887 buf->printf("%ju", dim->toInteger());
1888 if (next)
1889 next->toDecoBuffer(buf);
1890 }
1891
1892 void TypeSArray::toTypeInfoBuffer(OutBuffer *buf)
1893 {
1894 buf->writeByte(mangleChar[Tarray]);
1895 if (next)
1896 next->toTypeInfoBuffer(buf);
1897 }
1898
1899 void TypeSArray::toPrettyBracket(OutBuffer *buf, HdrGenState *hgs)
1900 {
1901 buf->printf("[%s]", dim->toChars());
1902 }
1903
1904 Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
1905 {
1906 #if LOGDOTEXP
1907 printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1908 #endif
1909 if (ident == Id::length)
1910 {
1911 e = dim;
1912 }
1913 else if (ident == Id::ptr)
1914 {
1915 e = e->castTo(sc, next->pointerTo());
1916 }
1917 else
1918 {
1919 e = TypeArray::dotExp(sc, e, ident);
1920 }
1921 return e;
1922 }
1923
1924 int TypeSArray::isString()
1925 {
1926 TY nty = next->toBasetype()->ty;
1927 return nty == Tchar || nty == Twchar || nty == Tdchar;
1928 }
1929
1930 unsigned TypeSArray::memalign(unsigned salign)
1931 {
1932 return next->memalign(salign);
1933 }
1934
1935 MATCH TypeSArray::implicitConvTo(Type *to)
1936 {
1937 //printf("TypeSArray::implicitConvTo()\n");
1938
1939 // Allow implicit conversion of static array to pointer or dynamic array
1940 if ((IMPLICIT_ARRAY_TO_PTR && to->ty == Tpointer) &&
1941 (to->next->ty == Tvoid || next->equals(to->next)
1942 /*|| to->next->isBaseOf(next)*/))
1943 {
1944 return MATCHconvert;
1945 }
1946 if (to->ty == Tarray)
1947 { int offset = 0;
1948
1949 if (next->equals(to->next) ||
1950 (to->next->isBaseOf(next, &offset) && offset == 0) ||
1951 to->next->ty == Tvoid)
1952 return MATCHconvert;
1953 }
1954 #if 0
1955 if (to->ty == Tsarray)
1956 {
1957 TypeSArray *tsa = (TypeSArray *)to;
1958
1959 if (next->equals(tsa->next) && dim->equals(tsa->dim))
1960 {
1961 return MATCHconvert;
1962 }
1963 }
1964 #endif
1965 return Type::implicitConvTo(to);
1966 }
1967
1968 Expression *TypeSArray::defaultInit()
1969 {
1970 #if LOGDEFAULTINIT
1971 printf("TypeSArray::defaultInit() '%s'\n", toChars());
1972 #endif
1973 return next->defaultInit();
1974 }
1975
1976 int TypeSArray::isZeroInit()
1977 {
1978 return next->isZeroInit();
1979 }
1980
1981
1982 Expression *TypeSArray::toExpression()
1983 {
1984 Expression *e = next->toExpression();
1985 if (e)
1986 { Expressions *arguments = new Expressions();
1987 arguments->push(dim);
1988 e = new ArrayExp(dim->loc, e, arguments);
1989 }
1990 return e;
1991 }
1992
1993 int TypeSArray::hasPointers()
1994 {
1995 return next->hasPointers();
1996 }
1997
1998 /***************************** TypeDArray *****************************/
1999
2000 TypeDArray::TypeDArray(Type *t)
2001 : TypeArray(Tarray, t)
2002 {
2003 //printf("TypeDArray(t = %p)\n", t);
2004 }
2005
2006 Type *TypeDArray::syntaxCopy()
2007 {
2008 Type *t = next->syntaxCopy();
2009 if (t == next)
2010 t = this;
2011 else
2012 t = new TypeDArray(t);
2013 return t;
2014 }
2015
2016 d_uns64 TypeDArray::size(Loc loc)
2017 {
2018 //printf("TypeDArray::size()\n");
2019 return PTRSIZE * 2;
2020 }
2021
2022 unsigned TypeDArray::alignsize()
2023 {
2024 // A DArray consists of two ptr-sized values, so align it on pointer size
2025 // boundary
2026 return PTRSIZE;
2027 }
2028
2029 Type *TypeDArray::semantic(Loc loc, Scope *sc)
2030 { Type *tn = next;
2031
2032 tn = next->semantic(loc,sc);
2033 Type *tbn = tn->toBasetype();
2034 switch (tbn->ty)
2035 {
2036 case Tfunction:
2037 case Tnone:
2038 case Ttuple:
2039 error(loc, "can't have array of %s", tbn->toChars());
2040 tn = next = tint32;
2041 break;
2042 }
2043 if (tn->isauto())
2044 error(loc, "cannot have array of auto %s", tn->toChars());
2045 if (next != tn)
2046 //deco = NULL; // redo
2047 return tn->arrayOf();
2048 return merge();
2049 }
2050
2051 void TypeDArray::toDecoBuffer(OutBuffer *buf)
2052 {
2053 buf->writeByte(mangleChar[ty]);
2054 if (next)
2055 next->toDecoBuffer(buf);
2056 }
2057
2058 void TypeDArray::toTypeInfoBuffer(OutBuffer *buf)
2059 {
2060 buf->writeByte(mangleChar[ty]);
2061 if (next)
2062 next->toTypeInfoBuffer(buf);
2063 }
2064
2065 void TypeDArray::toPrettyBracket(OutBuffer *buf, HdrGenState *hgs)
2066 {
2067 buf->writestring("[]");
2068 }
2069
2070 Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
2071 {
2072 #if LOGDOTEXP
2073 printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2074 #endif
2075 if (ident == Id::length)
2076 {
2077 if (e->op == TOKstring)
2078 { StringExp *se = (StringExp *)e;
2079
2080 return new IntegerExp(se->loc, se->len, Type::tindex);
2081 }
2082 e = new ArrayLengthExp(e->loc, e);
2083 e->type = Type::tsize_t;
2084 return e;
2085 }
2086 else if (ident == Id::ptr)
2087 {
2088 e = e->castTo(sc, next->pointerTo());
2089 return e;
2090 }
2091 else
2092 {
2093 e = TypeArray::dotExp(sc, e, ident);
2094 }
2095 return e;
2096 }
2097
2098 int TypeDArray::isString()
2099 {
2100 TY nty = next->toBasetype()->ty;
2101 return nty == Tchar || nty == Twchar || nty == Tdchar;
2102 }
2103
2104 MATCH TypeDArray::implicitConvTo(Type *to)
2105 {
2106 //printf("TypeDArray::implicitConvTo()\n");
2107
2108 // Allow implicit conversion of array to pointer
2109 if (IMPLICIT_ARRAY_TO_PTR &&
2110 to->ty == Tpointer &&
2111 (to->next->ty == Tvoid || next->equals(to->next) /*|| to->next->isBaseOf(next)*/))
2112 {
2113 return MATCHconvert;
2114 }
2115
2116 if (to->ty == Tarray)
2117 { int offset = 0;
2118
2119 if ((to->next->isBaseOf(next, &offset) && offset == 0) ||
2120 to->next->ty == Tvoid)
2121 return MATCHconvert;
2122 }
2123 return Type::implicitConvTo(to);
2124 }
2125
2126 Expression *TypeDArray::defaultInit()
2127 {
2128 #if LOGDEFAULTINIT
2129 printf("TypeDArray::defaultInit() '%s'\n", toChars());
2130 #endif
2131 Expression *e;
2132 e = new NullExp(0);
2133 e->type = this;
2134 return e;
2135 }
2136
2137 int TypeDArray::isZeroInit()
2138 {
2139 return 1;
2140 }
2141
2142 int TypeDArray::checkBoolean()
2143 {
2144 return TRUE;
2145 }
2146
2147 int TypeDArray::hasPointers()
2148 {
2149 return TRUE;
2150 }
2151
2152 /***************************** TypeAArray *****************************/
2153
2154 TypeAArray::TypeAArray(Type *t, Type *index)
2155 : TypeArray(Taarray, t)
2156 {
2157 this->index = index;
2158 this->key = NULL;
2159 }
2160
2161 Type *TypeAArray::syntaxCopy()
2162 {
2163 Type *t = next->syntaxCopy();
2164 Type *ti = index->syntaxCopy();
2165 if (t == next && ti == index)
2166 t = this;
2167 else
2168 t = new TypeAArray(t, ti);
2169 return t;
2170 }
2171
2172 d_uns64 TypeAArray::size(Loc loc)
2173 {
2174 return PTRSIZE /* * 2*/;
2175 }
2176
2177
2178 Type *TypeAArray::semantic(Loc loc, Scope *sc)
2179 {
2180 //printf("TypeAArray::semantic() %s index->ty = %d\n", toChars(), index->ty);
2181
2182 // Deal with the case where we thought the index was a type, but
2183 // in reality it was an expression.
2184 if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray)
2185 {
2186 Expression *e;
2187 Type *t;
2188 Dsymbol *s;
2189
2190 index->resolve(loc, sc, &e, &t, &s);
2191 if (e)
2192 { // It was an expression -
2193 // Rewrite as a static array
2194 TypeSArray *tsa;
2195
2196 tsa = new TypeSArray(next, e);
2197 return tsa->semantic(loc,sc);
2198 }
2199 else if (t)
2200 index = t;
2201 else
2202 index->error(loc, "index is not a type or an expression");
2203 }
2204 else
2205 index = index->semantic(loc,sc);
2206
2207 // Compute key type; the purpose of the key type is to
2208 // minimize the permutations of runtime library
2209 // routines as much as possible.
2210 key = index->toBasetype();
2211 switch (key->ty)
2212 {
2213 #if 0
2214 case Tint8:
2215 case Tuns8:
2216 case Tint16:
2217 case Tuns16:
2218 key = tint32;
2219 break;
2220 #endif
2221
2222 case Tsarray:
2223 #if 0
2224 // Convert to Tarray
2225 key = key->next->arrayOf();
2226 #endif
2227 break;
2228 case Tbit:
2229 case Tbool:
2230 case Tfunction:
2231 case Tvoid:
2232 case Tnone:
2233 error(loc, "can't have associative array key of %s", key->toChars());
2234 break;
2235 }
2236 next = next->semantic(loc,sc);
2237 switch (next->toBasetype()->ty)
2238 {
2239 case Tfunction:
2240 case Tnone:
2241 error(loc, "can't have associative array of %s", next->toChars());
2242 break;
2243 }
2244 if (next->isauto())
2245 error(loc, "cannot have array of auto %s", next->toChars());
2246
2247 return merge();
2248 }
2249
2250 Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
2251 {
2252 #if LOGDOTEXP
2253 printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2254 #endif
2255 if (ident == Id::length)
2256 {
2257 Expression *ec;
2258 FuncDeclaration *fd;
2259 Expressions *arguments;
2260
2261 fd = FuncDeclaration::genCfunc(Type::tsize_t, Id::aaLen);
2262 ec = new VarExp(0, fd);
2263 arguments = new Expressions();
2264 arguments->push(e);
2265 e = new CallExp(e->loc, ec, arguments);
2266 e->type = fd->type->next;
2267 }
2268 else if (ident == Id::keys)
2269 {
2270 Expression *ec;
2271 FuncDeclaration *fd;
2272 Expressions *arguments;
2273 int size = key->size(e->loc);
2274
2275 assert(size);
2276 fd = FuncDeclaration::genCfunc(Type::tindex, Id::aaKeys);
2277 ec = new VarExp(0, fd);
2278 arguments = new Expressions();
2279 arguments->push(e);
2280 arguments->push(new IntegerExp(0, size, Type::tsize_t));
2281 e = new CallExp(e->loc, ec, arguments);
2282 e->type = index->arrayOf();
2283 }
2284 else if (ident == Id::values)
2285 {
2286 Expression *ec;
2287 FuncDeclaration *fd;
2288 Expressions *arguments;
2289
2290 fd = FuncDeclaration::genCfunc(Type::tindex, Id::aaValues);
2291 ec = new VarExp(0, fd);
2292 arguments = new Expressions();
2293 arguments->push(e);
2294 size_t keysize = key->size(e->loc);
2295 keysize = (keysize + 3) & ~3; // BUG: 64 bit pointers?
2296 arguments->push(new IntegerExp(0, keysize, Type::tsize_t));
2297 arguments->push(new IntegerExp(0, next->size(e->loc), Type::tsize_t));
2298 e = new CallExp(e->loc, ec, arguments);
2299 e->type = next->arrayOf();
2300 }
2301 else if (ident == Id::rehash)
2302 {
2303 Expression *ec;
2304 FuncDeclaration *fd;
2305 Expressions *arguments;
2306
2307 fd = FuncDeclaration::genCfunc(Type::tint64, Id::aaRehash);
2308 ec = new VarExp(0, fd);
2309 arguments = new Expressions();
2310 arguments->push(e->addressOf(sc));
2311 arguments->push(key->getInternalTypeInfo(sc));
2312 e = new CallExp(e->loc, ec, arguments);
2313 e->type = this;
2314 }
2315 else
2316 {
2317 e = Type::dotExp(sc, e, ident);
2318 }
2319 return e;
2320 }
2321
2322 void TypeAArray::toDecoBuffer(OutBuffer *buf)
2323 {
2324 buf->writeByte(mangleChar[ty]);
2325 index->toDecoBuffer(buf);
2326 next->toDecoBuffer(buf);
2327 }
2328
2329 void TypeAArray::toPrettyBracket(OutBuffer *buf, HdrGenState *hgs)
2330 {
2331 buf->writeByte('[');
2332 { OutBuffer ibuf;
2333
2334 index->toCBuffer2(&ibuf, NULL, hgs);
2335 buf->write(&ibuf);
2336 }
2337 buf->writeByte(']');
2338 }
2339
2340 Expression *TypeAArray::defaultInit()
2341 {
2342 #if LOGDEFAULTINIT
2343 printf("TypeAArray::defaultInit() '%s'\n", toChars());
2344 #endif
2345 Expression *e;
2346 e = new NullExp(0);
2347 e->type = this;
2348 return e;
2349 }
2350
2351 int TypeAArray::checkBoolean()
2352 {
2353 return TRUE;
2354 }
2355
2356 int TypeAArray::hasPointers()
2357 {
2358 return TRUE;
2359 }
2360
2361 /***************************** TypePointer *****************************/
2362
2363 TypePointer::TypePointer(Type *t)
2364 : Type(Tpointer, t)
2365 {
2366 }
2367
2368 Type *TypePointer::syntaxCopy()
2369 {
2370 Type *t = next->syntaxCopy();
2371 if (t == next)
2372 t = this;
2373 else
2374 t = new TypePointer(t);
2375 return t;
2376 }
2377
2378 Type *TypePointer::semantic(Loc loc, Scope *sc)
2379 {
2380 //printf("TypePointer::semantic()\n");
2381 Type *n = next->semantic(loc, sc);
2382 switch (n->toBasetype()->ty)
2383 {
2384 case Ttuple:
2385 error(loc, "can't have pointer to %s", n->toChars());
2386 n = tint32;
2387 break;
2388 }
2389 if (n != next)
2390 deco = NULL;
2391 next = n;
2392 return merge();
2393 }
2394
2395
2396 d_uns64 TypePointer::size(Loc loc)
2397 {
2398 return PTRSIZE;
2399 }
2400
2401 void TypePointer::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
2402 {
2403 //printf("TypePointer::toCBuffer2() next = %d\n", next->ty);
2404 buf->prependstring("*");
2405 if (ident)
2406 {
2407 buf->writeByte(' ');
2408 buf->writestring(ident->toChars());
2409 }
2410 next->toCBuffer2(buf, NULL, hgs);
2411 }
2412
2413 MATCH TypePointer::implicitConvTo(Type *to)
2414 {
2415 //printf("TypePointer::implicitConvTo()\n");
2416
2417 if (this == to)
2418 return MATCHexact;
2419 if (to->ty == Tpointer && to->next)
2420 {
2421 if (to->next->ty == Tvoid)
2422 return MATCHconvert;
2423
2424 #if 0
2425 if (to->next->isBaseOf(next))
2426 return MATCHconvert;
2427 #endif
2428
2429 if (next->ty == Tfunction && to->next->ty == Tfunction)
2430 { TypeFunction *tf;
2431 TypeFunction *tfto;
2432
2433 tf = (TypeFunction *)(next);
2434 tfto = (TypeFunction *)(to->next);
2435 return tfto->equals(tf) ? MATCHexact : MATCHnomatch;
2436 }
2437 }
2438 // if (to->ty == Tvoid)
2439 // return MATCHconvert;
2440 return MATCHnomatch;
2441 }
2442
2443 int TypePointer::isscalar()
2444 {
2445 return TRUE;
2446 }
2447
2448 Expression *TypePointer::defaultInit()
2449 {
2450 #if LOGDEFAULTINIT
2451 printf("TypePointer::defaultInit() '%s'\n", toChars());
2452 #endif
2453 Expression *e;
2454 e = new NullExp(0);
2455 e->type = this;
2456 return e;
2457 }
2458
2459 int TypePointer::isZeroInit()
2460 {
2461 return 1;
2462 }
2463
2464 int TypePointer::hasPointers()
2465 {
2466 return TRUE;
2467 }
2468
2469
2470 /***************************** TypeReference *****************************/
2471
2472 TypeReference::TypeReference(Type *t)
2473 : Type(Treference, t)
2474 {
2475 if (t->ty == Tbit)
2476 error(0,"cannot make reference to a bit");
2477 // BUG: what about references to static arrays?
2478 }
2479
2480 Type *TypeReference::syntaxCopy()
2481 {
2482 Type *t = next->syntaxCopy();
2483 if (t == next)
2484 t = this;
2485 else
2486 t = new TypeReference(t);
2487 return t;
2488 }
2489
2490 d_uns64 TypeReference::size(Loc loc)
2491 {
2492 return PTRSIZE;
2493 }
2494
2495 void TypeReference::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
2496 {
2497 buf->prependstring("&");
2498 if (ident)
2499 {
2500 buf->writestring(ident->toChars());
2501 }
2502 next->toCBuffer2(buf, NULL, hgs);
2503 }
2504
2505 Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident)
2506 {
2507 #if LOGDOTEXP
2508 printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2509 #endif
2510
2511 // References just forward things along
2512 return next->dotExp(sc, e, ident);
2513 }
2514
2515 Expression *TypeReference::defaultInit()
2516 {
2517 #if LOGDEFAULTINIT
2518 printf("TypeReference::defaultInit() '%s'\n", toChars());
2519 #endif
2520 Expression *e;
2521 e = new NullExp(0);
2522 e->type = this;
2523 return e;
2524 }
2525
2526 int TypeReference::isZeroInit()
2527 {
2528 return 1;
2529 }
2530
2531
2532 /***************************** TypeFunction *****************************/
2533
2534 TypeFunction::TypeFunction(Arguments *parameters, Type *treturn, int varargs, enum LINK linkage)
2535 : Type(Tfunction, treturn)
2536 {
2537 //if (!treturn) *(char*)0=0;
2538 // assert(treturn);
2539 this->parameters = parameters;
2540 this->varargs = varargs;
2541 this->linkage = linkage;
2542 this->inuse = 0;
2543 this->llvmRetInPtr = false;
2544 this->llvmRetArg = 0;
2545 this->llvmAllocaPoint = 0;
2546 }
2547
2548 Type *TypeFunction::syntaxCopy()
2549 {
2550 Type *treturn = next ? next->syntaxCopy() : NULL;
2551 Arguments *params = Argument::arraySyntaxCopy(parameters);
2552 Type *t = new TypeFunction(params, treturn, varargs, linkage);
2553 return t;
2554 }
2555
2556 /*******************************
2557 * Returns:
2558 * 0 types are distinct
2559 * 1 this is covariant with t
2560 * 2 arguments match as far as overloading goes,
2561 * but types are not covariant
2562 * 3 cannot determine covariance because of forward references
2563 */
2564
2565 int Type::covariant(Type *t)
2566 {
2567 #if 0
2568 printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars());
2569 printf("deco = %p, %p\n", deco, t->deco);
2570 printf("ty = %d\n", next->ty);
2571 #endif
2572
2573 int inoutmismatch = 0;
2574
2575 if (equals(t))
2576 goto Lcovariant;
2577 if (ty != Tfunction || t->ty != Tfunction)
2578 goto Ldistinct;
2579
2580 {
2581 TypeFunction *t1 = (TypeFunction *)this;
2582 TypeFunction *t2 = (TypeFunction *)t;
2583
2584 if (t1->varargs != t2->varargs)
2585 goto Ldistinct;
2586
2587 if (t1->parameters && t2->parameters)
2588 {
2589 size_t dim = Argument::dim(t1->parameters);
2590 if (dim != Argument::dim(t2->parameters))
2591 goto Ldistinct;
2592
2593 for (size_t i = 0; i < dim; i++)
2594 { Argument *arg1 = Argument::getNth(t1->parameters, i);
2595 Argument *arg2 = Argument::getNth(t2->parameters, i);
2596
2597 if (!arg1->type->equals(arg2->type))
2598 goto Ldistinct;
2599 if (arg1->storageClass != arg2->storageClass)
2600 inoutmismatch = 1;
2601 }
2602 }
2603 else if (t1->parameters != t2->parameters)
2604 goto Ldistinct;
2605
2606 // The argument lists match
2607 if (inoutmismatch)
2608 goto Lnotcovariant;
2609 if (t1->linkage != t2->linkage)
2610 goto Lnotcovariant;
2611
2612 Type *t1n = t1->next;
2613 Type *t2n = t2->next;
2614
2615 if (t1n->equals(t2n))
2616 goto Lcovariant;
2617 if (t1n->ty != Tclass || t2n->ty != Tclass)
2618 goto Lnotcovariant;
2619
2620 // If t1n is forward referenced:
2621 ClassDeclaration *cd = ((TypeClass *)t1n)->sym;
2622 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
2623 {
2624 return 3;
2625 }
2626
2627 if (t1n->implicitConvTo(t2n))
2628 goto Lcovariant;
2629 goto Lnotcovariant;
2630 }
2631
2632 Lcovariant:
2633 //printf("\tcovaraint: 1\n");
2634 return 1;
2635
2636 Ldistinct:
2637 //printf("\tcovaraint: 0\n");
2638 return 0;
2639
2640 Lnotcovariant:
2641 //printf("\tcovaraint: 2\n");
2642 return 2;
2643 }
2644
2645 void TypeFunction::toDecoBuffer(OutBuffer *buf)
2646 { unsigned char mc;
2647
2648 //printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars());
2649 //static int nest; if (++nest == 50) *(char*)0=0;
2650 if (inuse)
2651 { inuse = 2; // flag error to caller
2652 return;
2653 }
2654 inuse++;
2655 switch (linkage)
2656 {
2657 case LINKd: mc = 'F'; break;
2658 case LINKc: mc = 'U'; break;
2659 case LINKwindows: mc = 'W'; break;
2660 case LINKpascal: mc = 'V'; break;
2661 case LINKcpp: mc = 'R'; break;
2662 default:
2663 assert(0);
2664 }
2665 buf->writeByte(mc);
2666 // Write argument types
2667 Argument::argsToDecoBuffer(buf, parameters);
2668 //if (buf->data[buf->offset - 1] == '@') halt();
2669 buf->writeByte('Z' - varargs); // mark end of arg list
2670 next->toDecoBuffer(buf);
2671 inuse--;
2672 }
2673
2674 void TypeFunction::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
2675 {
2676 char *p = NULL;
2677
2678 if (inuse)
2679 { inuse = 2; // flag error to caller
2680 return;
2681 }
2682 inuse++;
2683 if (hgs->ddoc != 1)
2684 {
2685 switch (linkage)
2686 {
2687 case LINKd: p = NULL; break;
2688 case LINKc: p = "C "; break;
2689 case LINKwindows: p = "Windows "; break;
2690 case LINKpascal: p = "Pascal "; break;
2691 case LINKcpp: p = "C++ "; break;
2692 default:
2693 assert(0);
2694 }
2695 }
2696
2697 if (buf->offset)
2698 {
2699 if (!hgs->hdrgen && p)
2700 buf->prependstring(p);
2701 buf->bracket('(', ')');
2702 assert(!ident);
2703 }
2704 else
2705 {
2706 if (!hgs->hdrgen && p)
2707 buf->writestring(p);
2708 if (ident)
2709 { buf->writeByte(' ');
2710 buf->writestring(ident->toHChars2());
2711 }
2712 }
2713 Argument::argsToCBuffer(buf, hgs, parameters, varargs);
2714 if (next && (!ident || ident->toHChars2() == ident->toChars()))
2715 next->toCBuffer2(buf, NULL, hgs);
2716 inuse--;
2717 }
2718
2719 Type *TypeFunction::semantic(Loc loc, Scope *sc)
2720 {
2721 if (deco) // if semantic() already run
2722 {
2723 //printf("already done\n");
2724 return this;
2725 }
2726 //printf("TypeFunction::semantic() this = %p\n", this);
2727
2728 linkage = sc->linkage;
2729 if (!next)
2730 {
2731 assert(global.errors);
2732 next = tvoid;
2733 }
2734 next = next->semantic(loc,sc);
2735 if (next->toBasetype()->ty == Tsarray)
2736 { error(loc, "functions cannot return static array %s", next->toChars());
2737 next = Type::terror;
2738 }
2739 if (next->toBasetype()->ty == Tfunction)
2740 { error(loc, "functions cannot return a function");
2741 next = Type::terror;
2742 }
2743 if (next->toBasetype()->ty == Ttuple)
2744 { error(loc, "functions cannot return a tuple");
2745 next = Type::terror;
2746 }
2747 if (next->isauto() && !(sc->flags & SCOPEctor))
2748 error(loc, "functions cannot return auto %s", next->toChars());
2749
2750 if (parameters)
2751 { size_t dim = Argument::dim(parameters);
2752
2753 for (size_t i = 0; i < dim; i++)
2754 { Argument *arg = Argument::getNth(parameters, i);
2755 Type *t;
2756
2757 inuse++;
2758 arg->type = arg->type->semantic(loc,sc);
2759 if (inuse == 1) inuse--;
2760 t = arg->type->toBasetype();
2761
2762 if (arg->storageClass & (STCout | STCref | STClazy))
2763 {
2764 if (t->ty == Tsarray)
2765 error(loc, "cannot have out or ref parameter of type %s", t->toChars());
2766 }
2767 if (!(arg->storageClass & STClazy) && t->ty == Tvoid)
2768 error(loc, "cannot have parameter of type %s", arg->type->toChars());
2769
2770 if (arg->defaultArg)
2771 {
2772 arg->defaultArg = arg->defaultArg->semantic(sc);
2773 arg->defaultArg = resolveProperties(sc, arg->defaultArg);
2774 arg->defaultArg = arg->defaultArg->implicitCastTo(sc, arg->type);
2775 }
2776
2777 /* If arg turns out to be a tuple, the number of parameters may
2778 * change.
2779 */
2780 if (t->ty == Ttuple)
2781 { dim = Argument::dim(parameters);
2782 i--;
2783 }
2784 }
2785 }
2786 deco = merge()->deco;
2787
2788 if (inuse)
2789 { error(loc, "recursive type");
2790 inuse = 0;
2791 return terror;
2792 }
2793
2794 if (varargs == 1 && linkage != LINKd && Argument::dim(parameters) == 0)
2795 error(loc, "variadic functions with non-D linkage must have at least one parameter");
2796
2797 /* Don't return merge(), because arg identifiers and default args
2798 * can be different
2799 * even though the types match
2800 */
2801 return this;
2802 }
2803
2804 /********************************
2805 * 'args' are being matched to function 'this'
2806 * Determine match level.
2807 * Returns:
2808 * MATCHxxxx
2809 */
2810
2811 int TypeFunction::callMatch(Expressions *args)
2812 {
2813 //printf("TypeFunction::callMatch()\n");
2814 int match = MATCHexact; // assume exact match
2815
2816 size_t nparams = Argument::dim(parameters);
2817 size_t nargs = args ? args->dim : 0;
2818 if (nparams == nargs)
2819 ;
2820 else if (nargs > nparams)
2821 {
2822 if (varargs == 0)
2823 goto Nomatch; // too many args; no match
2824 match = MATCHconvert; // match ... with a "conversion" match level
2825 }
2826
2827 for (size_t u = 0; u < nparams; u++)
2828 { int m;
2829 Expression *arg;
2830
2831 // BUG: what about out and ref?
2832
2833 Argument *p = Argument::getNth(parameters, u);
2834 assert(p);
2835 if (u >= nargs)
2836 {
2837 if (p->defaultArg)
2838 continue;
2839 if (varargs == 2 && u + 1 == nparams)
2840 goto L1;
2841 goto Nomatch; // not enough arguments
2842 }
2843 arg = (Expression *)args->data[u];
2844 assert(arg);
2845 if (p->storageClass & STClazy && p->type->ty == Tvoid && arg->type->ty != Tvoid)
2846 m = MATCHconvert;
2847 else
2848 m = arg->implicitConvTo(p->type);
2849 //printf("\tm = %d\n", m);
2850 if (m == MATCHnomatch) // if no match
2851 {
2852 L1:
2853 if (varargs == 2 && u + 1 == nparams) // if last varargs param
2854 { Type *tb = p->type->toBasetype();
2855 TypeSArray *tsa;
2856 integer_t sz;
2857
2858 switch (tb->ty)
2859 {
2860 case Tsarray:
2861 tsa = (TypeSArray *)tb;
2862 sz = tsa->dim->toInteger();
2863 if (sz != nargs - u)
2864 goto Nomatch;
2865 case Tarray:
2866 for (; u < nargs; u++)
2867 {
2868 arg = (Expression *)args->data[u];
2869 assert(arg);
2870 #if 1
2871 /* If lazy array of delegates,
2872 * convert arg(s) to delegate(s)
2873 */
2874 Type *tret = p->isLazyArray();
2875 if (tret)
2876 {
2877 if (tb->next->equals(arg->type))
2878 { m = MATCHexact;
2879 }
2880 else
2881 {
2882 m = arg->implicitConvTo(tret);
2883 if (m == MATCHnomatch)
2884 {
2885 if (tret->toBasetype()->ty == Tvoid)
2886 m = MATCHconvert;
2887 }
2888 }
2889 }
2890 else
2891 m = arg->implicitConvTo(tb->next);
2892 #else
2893 m = arg->implicitConvTo(tb->next);
2894 #endif
2895 if (m == 0)
2896 goto Nomatch;
2897 if (m < match)
2898 match = m;
2899 }
2900 goto Ldone;
2901
2902 case Tclass:
2903 // Should see if there's a constructor match?
2904 // Or just leave it ambiguous?
2905 goto Ldone;
2906
2907 default:
2908 goto Nomatch;
2909 }
2910 }
2911 goto Nomatch;
2912 }
2913 if (m < match)
2914 match = m; // pick worst match
2915 }
2916
2917 Ldone:
2918 //printf("match = %d\n", match);
2919 return match;
2920
2921 Nomatch:
2922 //printf("no match\n");
2923 return MATCHnomatch;
2924 }
2925
2926 Type *TypeFunction::reliesOnTident()
2927 {
2928 if (parameters)
2929 {
2930 for (size_t i = 0; i < parameters->dim; i++)
2931 { Argument *arg = (Argument *)parameters->data[i];
2932 Type *t = arg->type->reliesOnTident();
2933 if (t)
2934 return t;
2935 }
2936 }
2937 return next->reliesOnTident();
2938 }
2939
2940 /***************************** TypeDelegate *****************************/
2941
2942 TypeDelegate::TypeDelegate(Type *t)
2943 : Type(Tfunction, t)
2944 {
2945 ty = Tdelegate;
2946 }
2947
2948 Type *TypeDelegate::syntaxCopy()
2949 {
2950 Type *t = next->syntaxCopy();
2951 if (t == next)
2952 t = this;
2953 else
2954 t = new TypeDelegate(t);
2955 return t;
2956 }
2957
2958 Type *TypeDelegate::semantic(Loc loc, Scope *sc)
2959 {
2960 if (deco) // if semantic() already run
2961 {
2962 //printf("already done\n");
2963 return this;
2964 }
2965 next = next->semantic(loc,sc);
2966 return merge();
2967 }
2968
2969 d_uns64 TypeDelegate::size(Loc loc)
2970 {
2971 return PTRSIZE * 2;
2972 }
2973
2974 void TypeDelegate::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
2975 {
2976 #if 1
2977 OutBuffer args;
2978 TypeFunction *tf = (TypeFunction *)next;
2979
2980 Argument::argsToCBuffer(&args, hgs, tf->parameters, tf->varargs);
2981 buf->prependstring(args.toChars());
2982 buf->prependstring(" delegate");
2983 if (ident)
2984 {
2985 buf->writeByte(' ');
2986 buf->writestring(ident->toChars());
2987 }
2988 next->next->toCBuffer2(buf, NULL, hgs);
2989 #else
2990 next->toCBuffer2(buf, Id::delegate, hgs);
2991 if (ident)
2992 {
2993 buf->writestring(ident->toChars());
2994 }
2995 #endif
2996 }
2997
2998 Expression *TypeDelegate::defaultInit()
2999 {
3000 #if LOGDEFAULTINIT
3001 printf("TypeDelegate::defaultInit() '%s'\n", toChars());
3002 #endif
3003 Expression *e;
3004 e = new NullExp(0);
3005 e->type = this;
3006 return e;
3007 }
3008
3009 int TypeDelegate::isZeroInit()
3010 {
3011 return 1;
3012 }
3013
3014 int TypeDelegate::checkBoolean()
3015 {
3016 return TRUE;
3017 }
3018
3019 Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident)
3020 {
3021 #if LOGDOTEXP
3022 printf("TypeDelegate::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
3023 #endif
3024 if (ident == Id::ptr)
3025 {
3026 e->type = tvoidptr;
3027 return e;
3028 }
3029 else if (ident == Id::funcptr)
3030 {
3031 e = e->addressOf(sc);
3032 e->type = tvoidptr;
3033 e = new AddExp(e->loc, e, new IntegerExp(PTRSIZE));
3034 e->type = tvoidptr;
3035 e = new PtrExp(e->loc, e);
3036 e->type = next->pointerTo();
3037 return e;
3038 }
3039 else
3040 {
3041 e = Type::dotExp(sc, e, ident);
3042 }
3043 return e;
3044 }
3045
3046 int TypeDelegate::hasPointers()
3047 {
3048 return TRUE;
3049 }
3050
3051
3052
3053 /***************************** TypeQualified *****************************/
3054
3055 TypeQualified::TypeQualified(TY ty, Loc loc)
3056 : Type(ty, NULL)
3057 {
3058 this->loc = loc;
3059 }
3060
3061 void TypeQualified::syntaxCopyHelper(TypeQualified *t)
3062 {
3063 //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t->toChars(), toChars());
3064 idents.setDim(t->idents.dim);
3065 for (int i = 0; i < idents.dim; i++)
3066 {
3067 Identifier *id = (Identifier *)t->idents.data[i];
3068 if (id->dyncast() == DYNCAST_DSYMBOL)
3069 {
3070 TemplateInstance *ti = (TemplateInstance *)id;
3071
3072 ti = (TemplateInstance *)ti->syntaxCopy(NULL);
3073 id = (Identifier *)ti;
3074 }
3075 idents.data[i] = id;
3076 }
3077 }
3078
3079
3080 void TypeQualified::addIdent(Identifier *ident)
3081 {
3082 idents.push(ident);
3083 }
3084
3085 void TypeQualified::toCBuffer2Helper(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
3086 {
3087 int i;
3088
3089 for (i = 0; i < idents.dim; i++)
3090 { Identifier *id = (Identifier *)idents.data[i];
3091
3092 buf->writeByte('.');
3093
3094 if (id->dyncast() == DYNCAST_DSYMBOL)
3095 {
3096 TemplateInstance *ti = (TemplateInstance *)id;
3097 ti->toCBuffer(buf, hgs);
3098 }
3099 else
3100 buf->writestring(id->toChars());
3101 }
3102 }
3103
3104 d_uns64 TypeQualified::size(Loc loc)
3105 {
3106 error(this->loc, "size of type %s is not known", toChars());
3107 return 1;
3108 }
3109
3110 /*************************************
3111 * Takes an array of Identifiers and figures out if
3112 * it represents a Type or an Expression.
3113 * Output:
3114 * if expression, *pe is set
3115 * if type, *pt is set
3116 */
3117
3118 void TypeQualified::resolveHelper(Loc loc, Scope *sc,
3119 Dsymbol *s, Dsymbol *scopesym,
3120 Expression **pe, Type **pt, Dsymbol **ps)
3121 {
3122 Identifier *id = NULL;
3123 int i;
3124 VarDeclaration *v;
3125 EnumMember *em;
3126 TupleDeclaration *td;
3127 Type *t;
3128 Expression *e;
3129
3130 #if 0
3131 printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, toChars());
3132 if (scopesym)
3133 printf("\tscopesym = '%s'\n", scopesym->toChars());
3134 #endif
3135 *pe = NULL;
3136 *pt = NULL;
3137 *ps = NULL;
3138 if (s)
3139 {
3140 //printf("\t1: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3141 s = s->toAlias();
3142 //printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3143 for (i = 0; i < idents.dim; i++)
3144 { Dsymbol *sm;
3145
3146 id = (Identifier *)idents.data[i];
3147 sm = s->searchX(loc, sc, id);
3148 //printf("\t3: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
3149 //printf("getType = '%s'\n", s->getType()->toChars());
3150 if (!sm)
3151 {
3152 v = s->isVarDeclaration();
3153 if (v && id == Id::length)
3154 {
3155 if (v->isConst() && v->getExpInitializer())
3156 { e = v->getExpInitializer()->exp;
3157 }
3158 else
3159 e = new VarExp(loc, v);
3160 t = e->type;
3161 if (!t)
3162 goto Lerror;
3163 goto L3;
3164 }
3165 t = s->getType();
3166 if (!t && s->isDeclaration())
3167 t = s->isDeclaration()->type;
3168 if (t)
3169 {
3170 sm = t->toDsymbol(sc);
3171 if (sm)
3172 { sm = sm->search(loc, id, 0);
3173 if (sm)
3174 goto L2;
3175 }
3176 //e = t->getProperty(loc, id);
3177 e = new TypeExp(loc, t);
3178 e = t->dotExp(sc, e, id);
3179 i++;
3180 L3:
3181 for (; i < idents.dim; i++)
3182 {
3183 id = (Identifier *)idents.data[i];
3184 //printf("e: '%s', id: '%s', type = %p\n", e->toChars(), id->toChars(), e->type);
3185 e = e->type->dotExp(sc, e, id);
3186 }
3187 *pe = e;
3188 }
3189 else
3190 Lerror:
3191 error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
3192 return;
3193 }
3194 L2:
3195 s = sm->toAlias();
3196 }
3197
3198 v = s->isVarDeclaration();
3199 if (v)
3200 {
3201 // It's not a type, it's an expression
3202 if (v->isConst() && v->getExpInitializer())
3203 {
3204 ExpInitializer *ei = v->getExpInitializer();
3205 assert(ei);
3206 *pe = ei->exp->copy(); // make copy so we can change loc
3207 (*pe)->loc = loc;
3208 }
3209 else
3210 {
3211 #if 0
3212 WithScopeSymbol *withsym;
3213 if (scopesym && (withsym = scopesym->isWithScopeSymbol()) != NULL)
3214 {
3215 // Same as wthis.ident
3216 e = new VarExp(loc, withsym->withstate->wthis);
3217 e = new DotIdExp(loc, e, ident);
3218 //assert(0); // BUG: should handle this
3219 }
3220 else
3221 #endif
3222 *pe = new VarExp(loc, v);
3223 }
3224 return;
3225 }
3226 em = s->isEnumMember();
3227 if (em)
3228 {
3229 // It's not a type, it's an expression
3230 *pe = em->value->copy();
3231 return;
3232 }
3233
3234 L1:
3235 t = s->getType();
3236 if (!t)
3237 {
3238 // If the symbol is an import, try looking inside the import
3239 Import *si;
3240
3241 si = s->isImport();
3242 if (si)
3243 {
3244 s = si->search(loc, s->ident, 0);
3245 if (s && s != si)
3246 goto L1;
3247 s = si;
3248 }
3249 *ps = s;
3250 return;
3251 }
3252 if (t->ty == Tinstance && t != this && !t->deco)
3253 { error(loc, "forward reference to '%s'", t->toChars());
3254 return;
3255 }
3256
3257 if (t != this)
3258 {
3259 if (t->reliesOnTident())
3260 {
3261 Scope *scx;
3262
3263 for (scx = sc; 1; scx = scx->enclosing)
3264 {
3265 if (!scx)
3266 { error(loc, "forward reference to '%s'", t->toChars());
3267 return;
3268 }
3269 if (scx->scopesym == scopesym)
3270 break;
3271 }
3272 t = t->semantic(loc, scx);
3273 //((TypeIdentifier *)t)->resolve(loc, scx, pe, &t, ps);
3274 }
3275 }
3276 if (t->ty == Ttuple)
3277 *pt = t;
3278 else
3279 *pt = t->merge();
3280 }
3281 if (!s)
3282 {
3283 error(loc, "identifier '%s' is not defined", toChars());
3284 }
3285 }
3286
3287 /***************************** TypeIdentifier *****************************/
3288
3289 TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident)
3290 : TypeQualified(Tident, loc)
3291 {
3292 this->ident = ident;
3293 }
3294
3295
3296 Type *TypeIdentifier::syntaxCopy()
3297 {
3298 TypeIdentifier *t;
3299
3300 t = new TypeIdentifier(loc, ident);
3301 t->syntaxCopyHelper(this);
3302 return t;
3303 }
3304
3305 void TypeIdentifier::toDecoBuffer(OutBuffer *buf)
3306 { unsigned len;
3307 char *name;
3308
3309 name = ident->toChars();
3310 len = strlen(name);
3311 buf->printf("%c%d%s", mangleChar[ty], len, name);
3312 //buf->printf("%c%s", mangleChar[ty], name);
3313 }
3314
3315 void TypeIdentifier::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
3316 {
3317 OutBuffer tmp;
3318
3319 tmp.writestring(this->ident->toChars());
3320 toCBuffer2Helper(&tmp, NULL, hgs);
3321 buf->prependstring(tmp.toChars());
3322 if (ident)
3323 { buf->writeByte(' ');
3324 buf->writestring(ident->toChars());
3325 }
3326 }
3327
3328 /*************************************
3329 * Takes an array of Identifiers and figures out if
3330 * it represents a Type or an Expression.
3331 * Output:
3332 * if expression, *pe is set
3333 * if type, *pt is set
3334 */
3335
3336 void TypeIdentifier::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
3337 { Dsymbol *s;
3338 Dsymbol *scopesym;
3339
3340 //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars());
3341 s = sc->search(loc, ident, &scopesym);
3342 resolveHelper(loc, sc, s, scopesym, pe, pt, ps);
3343 }
3344
3345 /*****************************************
3346 * See if type resolves to a symbol, if so,
3347 * return that symbol.
3348 */
3349
3350 Dsymbol *TypeIdentifier::toDsymbol(Scope *sc)
3351 {
3352 //printf("TypeIdentifier::toDsymbol('%s')\n", toChars());
3353 if (!sc)
3354 return NULL;
3355 //printf("ident = '%s'\n", ident->toChars());
3356
3357 Dsymbol *scopesym;
3358 Dsymbol *s = sc->search(loc, ident, &scopesym);
3359 if (s)
3360 {
3361 for (int i = 0; i < idents.dim; i++)
3362 {
3363 Identifier *id = (Identifier *)idents.data[i];
3364 s = s->searchX(loc, sc, id);
3365 if (!s) // failed to find a symbol
3366 { //printf("\tdidn't find a symbol\n");
3367 break;
3368 }
3369 }
3370 }
3371 return s;
3372 }
3373
3374 Type *TypeIdentifier::semantic(Loc loc, Scope *sc)
3375 {
3376 Type *t;
3377 Expression *e;
3378 Dsymbol *s;
3379
3380 //printf("TypeIdentifier::semantic(%s)\n", toChars());
3381 resolve(loc, sc, &e, &t, &s);
3382 if (t)
3383 {
3384 //printf("\tit's a type %d, %s, %s\n", t->ty, t->toChars(), t->deco);
3385
3386 if (t->ty == Ttypedef)
3387 { TypeTypedef *tt = (TypeTypedef *)t;
3388
3389 if (tt->sym->sem == 1)
3390 error(loc, "circular reference of typedef %s", tt->toChars());
3391 }
3392 }
3393 else
3394 {
3395 #ifdef DEBUG
3396 if (!global.gag)
3397 printf("1: ");
3398 #endif
3399 if (s)
3400 {
3401 s->error(loc, "is used as a type");
3402 }
3403 else
3404 error(loc, "%s is used as a type", toChars());
3405 t = tvoid;
3406 }
3407 //t->print();
3408 return t;
3409 }
3410
3411 Type *TypeIdentifier::reliesOnTident()
3412 {
3413 return this;
3414 }
3415
3416 Expression *TypeIdentifier::toExpression()
3417 {
3418 Expression *e = new IdentifierExp(loc, ident);
3419 for (int i = 0; i < idents.dim; i++)
3420 {
3421 Identifier *id = (Identifier *)idents.data[i];
3422 e = new DotIdExp(loc, e, id);
3423 }
3424
3425 return e;
3426 }
3427
3428 /***************************** TypeInstance *****************************/
3429
3430 TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst)
3431 : TypeQualified(Tinstance, loc)
3432 {
3433 this->tempinst = tempinst;
3434 }
3435
3436 Type *TypeInstance::syntaxCopy()
3437 {
3438 //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim);
3439 TypeInstance *t;
3440
3441 t = new TypeInstance(loc, (TemplateInstance *)tempinst->syntaxCopy(NULL));
3442 t->syntaxCopyHelper(this);
3443 return t;
3444 }
3445
3446
3447 void TypeInstance::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
3448 {
3449 OutBuffer tmp;
3450
3451 tempinst->toCBuffer(&tmp, hgs);
3452 toCBuffer2Helper(&tmp, NULL, hgs);
3453 buf->prependstring(tmp.toChars());
3454 if (ident)
3455 { buf->writeByte(' ');
3456 buf->writestring(ident->toChars());
3457 }
3458 }
3459
3460 void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
3461 {
3462 // Note close similarity to TypeIdentifier::resolve()
3463
3464 Dsymbol *s;
3465
3466 *pe = NULL;
3467 *pt = NULL;
3468 *ps = NULL;
3469
3470 #if 0
3471 if (!idents.dim)
3472 {
3473 error(loc, "template instance '%s' has no identifier", toChars());
3474 return;
3475 }
3476 #endif
3477 //id = (Identifier *)idents.data[0];
3478 //printf("TypeInstance::resolve(sc = %p, idents = '%s')\n", sc, id->toChars());
3479 s = tempinst;
3480 if (s)
3481 s->semantic(sc);
3482 resolveHelper(loc, sc, s, NULL, pe, pt, ps);
3483 //printf("pt = '%s'\n", (*pt)->toChars());
3484 }
3485
3486 Type *TypeInstance::semantic(Loc loc, Scope *sc)
3487 {
3488 Type *t;
3489 Expression *e;
3490 Dsymbol *s;
3491
3492 //printf("TypeInstance::semantic(%s)\n", toChars());
3493
3494 if (sc->parameterSpecialization)
3495 {
3496 unsigned errors = global.errors;
3497 global.gag++;
3498
3499 resolve(loc, sc, &e, &t, &s);
3500
3501 global.gag--;
3502 if (errors != global.errors)
3503 { if (global.gag == 0)
3504 global.errors = errors;
3505 return this;
3506 }
3507 }
3508 else
3509 resolve(loc, sc, &e, &t, &s);
3510
3511 if (!t)
3512 {
3513 #ifdef DEBUG
3514 printf("2: ");
3515 #endif
3516 error(loc, "%s is used as a type", toChars());
3517 t = tvoid;
3518 }
3519 return t;
3520 }
3521
3522
3523 /***************************** TypeTypeof *****************************/
3524
3525 TypeTypeof::TypeTypeof(Loc loc, Expression *exp)
3526 : TypeQualified(Ttypeof, loc)
3527 {
3528 this->exp = exp;
3529 }
3530
3531 Type *TypeTypeof::syntaxCopy()
3532 {
3533 TypeTypeof *t;
3534
3535 t = new TypeTypeof(loc, exp->syntaxCopy());
3536 t->syntaxCopyHelper(this);
3537 return t;
3538 }
3539
3540 Dsymbol *TypeTypeof::toDsymbol(Scope *sc)
3541 {
3542 Type *t;
3543
3544 t = semantic(0, sc);
3545 if (t == this)
3546 return NULL;
3547 return t->toDsymbol(sc);
3548 }
3549
3550 void TypeTypeof::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
3551 {
3552 OutBuffer tmp;
3553
3554 tmp.writestring("typeof(");
3555 exp->toCBuffer(&tmp, hgs);
3556 tmp.writeByte(')');
3557 toCBuffer2Helper(&tmp, NULL, hgs);
3558 buf->prependstring(tmp.toChars());
3559 if (ident)
3560 { buf->writeByte(' ');
3561 buf->writestring(ident->toChars());
3562 }
3563 }
3564
3565 Type *TypeTypeof::semantic(Loc loc, Scope *sc)
3566 { Expression *e;
3567 Type *t;
3568
3569 //printf("TypeTypeof::semantic() %p\n", this);
3570
3571 //static int nest; if (++nest == 50) *(char*)0=0;
3572
3573 #if 0
3574 /* Special case for typeof(this) and typeof(super) since both
3575 * should work even if they are not inside a non-static member function
3576 */
3577 if (exp->op == TOKthis || exp->op == TOKsuper)
3578 {
3579 // Find enclosing struct or class
3580 for (Dsymbol *s = sc->parent; 1; s = s->parent)
3581 {
3582 ClassDeclaration *cd;
3583 StructDeclaration *sd;
3584
3585 if (!s)
3586 {
3587 error(loc, "%s is not in a struct or class scope", exp->toChars());
3588 goto Lerr;
3589 }
3590 cd = s->isClassDeclaration();
3591 if (cd)
3592 {
3593 if (exp->op == TOKsuper)
3594 {
3595 cd = cd->baseClass;
3596 if (!cd)
3597 { error(loc, "class %s has no 'super'", s->toChars());
3598 goto Lerr;
3599 }
3600 }
3601 t = cd->type;
3602 break;
3603 }
3604 sd = s->isStructDeclaration();
3605 if (sd)
3606 {
3607 if (exp->op == TOKsuper)
3608 {
3609 error(loc, "struct %s has no 'super'", sd->toChars());
3610 goto Lerr;
3611 }
3612 t = sd->type->pointerTo();
3613 break;
3614 }
3615 }
3616 }
3617 else
3618 #endif
3619 {
3620 sc->intypeof++;
3621 exp = exp->semantic(sc);
3622 sc->intypeof--;
3623 t = exp->type;
3624 if (!t)
3625 {
3626 error(loc, "expression (%s) has no type", exp->toChars());
3627 goto Lerr;
3628 }
3629 }
3630
3631 if (idents.dim)
3632 {
3633 Dsymbol *s = t->toDsymbol(sc);
3634 for (size_t i = 0; i < idents.dim; i++)
3635 {
3636 if (!s)
3637 break;
3638 Identifier *id = (Identifier *)idents.data[i];
3639 s = s->searchX(loc, sc, id);
3640 }
3641 if (s)
3642 {
3643 t = s->getType();
3644 if (!t)
3645 { error(loc, "%s is not a type", s->toChars());
3646 goto Lerr;
3647 }
3648 }
3649 else
3650 { error(loc, "cannot resolve .property for %s", toChars());
3651 goto Lerr;
3652 }
3653 }
3654 return t;
3655
3656 Lerr:
3657 return tvoid;
3658 }
3659
3660 d_uns64 TypeTypeof::size(Loc loc)
3661 {
3662 if (exp->type)
3663 return exp->type->size(loc);
3664 else
3665 return TypeQualified::size(loc);
3666 }
3667
3668
3669
3670 /***************************** TypeEnum *****************************/
3671
3672 TypeEnum::TypeEnum(EnumDeclaration *sym)
3673 : Type(Tenum, NULL)
3674 {
3675 this->sym = sym;
3676 }
3677
3678 char *TypeEnum::toChars()
3679 {
3680 return sym->toChars();
3681 }
3682
3683 Type *TypeEnum::semantic(Loc loc, Scope *sc)
3684 {
3685 sym->semantic(sc);
3686 return merge();
3687 }
3688
3689 d_uns64 TypeEnum::size(Loc loc)
3690 {
3691 if (!sym->memtype)
3692 {
3693 error(loc, "enum %s is forward referenced", sym->toChars());
3694 return 4;
3695 }
3696 return sym->memtype->size(loc);
3697 }
3698
3699 unsigned TypeEnum::alignsize()
3700 {
3701 if (!sym->memtype)
3702 {
3703 #ifdef DEBUG
3704 printf("1: ");
3705 #endif
3706 error(0, "enum %s is forward referenced", sym->toChars());
3707 return 4;
3708 }
3709 return sym->memtype->alignsize();
3710 }
3711
3712 Dsymbol *TypeEnum::toDsymbol(Scope *sc)
3713 {
3714 return sym;
3715 }
3716
3717 Type *TypeEnum::toBasetype()
3718 {
3719 if (!sym->memtype)
3720 {
3721 #ifdef DEBUG
3722 printf("2: ");
3723 #endif
3724 error(sym->loc, "enum %s is forward referenced", sym->toChars());
3725 return tint32;
3726 }
3727 return sym->memtype->toBasetype();
3728 }
3729
3730 void TypeEnum::toDecoBuffer(OutBuffer *buf)
3731 { char *name;
3732
3733 name = sym->mangle();
3734 // if (name[0] == '_' && name[1] == 'D')
3735 // name += 2;
3736 buf->printf("%c%s", mangleChar[ty], name);
3737 }
3738
3739 void TypeEnum::toTypeInfoBuffer(OutBuffer *buf)
3740 {
3741 toBasetype()->toTypeInfoBuffer(buf);
3742 }
3743
3744 void TypeEnum::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
3745 {
3746 buf->prependstring(sym->toChars());
3747 if (ident)
3748 { buf->writeByte(' ');
3749 buf->writestring(ident->toChars());
3750 }
3751 }
3752
3753 Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident)
3754 {
3755 EnumMember *m;
3756 Dsymbol *s;
3757 Expression *em;
3758
3759 #if LOGDOTEXP
3760 printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars());
3761 #endif
3762 s = sym->symtab->lookup(ident);
3763 if (!s)
3764 {
3765 return getProperty(e->loc, ident);
3766 }
3767 m = s->isEnumMember();
3768 em = m->value->copy();
3769 em->loc = e->loc;
3770 return em;
3771 }
3772
3773 Expression *TypeEnum::getProperty(Loc loc, Identifier *ident)
3774 { Expression *e;
3775
3776 if (ident == Id::max)
3777 {
3778 if (!sym->symtab)
3779 goto Lfwd;
3780 e = new IntegerExp(0, sym->maxval, this);
3781 }
3782 else if (ident == Id::min)
3783 {
3784 if (!sym->symtab)
3785 goto Lfwd;
3786 e = new IntegerExp(0, sym->minval, this);
3787 }
3788 else if (ident == Id::init)
3789 {
3790 if (!sym->symtab)
3791 goto Lfwd;
3792 e = defaultInit();
3793 }
3794 else
3795 {
3796 if (!sym->memtype)
3797 goto Lfwd;
3798 e = sym->memtype->getProperty(loc, ident);
3799 }
3800 return e;
3801
3802 Lfwd:
3803 error(loc, "forward reference of %s.%s", toChars(), ident->toChars());
3804 return new IntegerExp(0, 0, this);
3805 }
3806
3807 int TypeEnum::isintegral()
3808 {
3809 return 1;
3810 }
3811
3812 int TypeEnum::isfloating()
3813 {
3814 return 0;
3815 }
3816
3817 int TypeEnum::isunsigned()
3818 {
3819 return sym->memtype->isunsigned();
3820 }
3821
3822 int TypeEnum::isscalar()
3823 {
3824 return 1;
3825 //return sym->memtype->isscalar();
3826 }
3827
3828 MATCH TypeEnum::implicitConvTo(Type *to)
3829 { MATCH m;
3830
3831 //printf("TypeEnum::implicitConvTo()\n");
3832 if (this->equals(to))
3833 m = MATCHexact; // exact match
3834 else if (sym->memtype->implicitConvTo(to))
3835 m = MATCHconvert; // match with conversions
3836 else
3837 m = MATCHnomatch; // no match
3838 return m;
3839 }
3840
3841 Expression *TypeEnum::defaultInit()
3842 {
3843 #if LOGDEFAULTINIT
3844 printf("TypeEnum::defaultInit() '%s'\n", toChars());
3845 #endif
3846 // Initialize to first member of enum
3847 Expression *e;
3848 e = new IntegerExp(0, sym->defaultval, this);
3849 return e;
3850 }
3851
3852 int TypeEnum::isZeroInit()
3853 {
3854 return (sym->defaultval == 0);
3855 }
3856
3857 int TypeEnum::hasPointers()
3858 {
3859 return toBasetype()->hasPointers();
3860 }
3861
3862 /***************************** TypeTypedef *****************************/
3863
3864 TypeTypedef::TypeTypedef(TypedefDeclaration *sym)
3865 : Type(Ttypedef, NULL)
3866 {
3867 this->sym = sym;
3868 }
3869
3870 Type *TypeTypedef::syntaxCopy()
3871 {
3872 return this;
3873 }
3874
3875 char *TypeTypedef::toChars()
3876 {
3877 return sym->toChars();
3878 }
3879
3880 Type *TypeTypedef::semantic(Loc loc, Scope *sc)
3881 {
3882 //printf("TypeTypedef::semantic(%s), sem = %d\n", toChars(), sym->sem);
3883 sym->semantic(sc);
3884 return merge();
3885 }
3886
3887 d_uns64 TypeTypedef::size(Loc loc)
3888 {
3889 return sym->basetype->size(loc);
3890 }
3891
3892 unsigned TypeTypedef::alignsize()
3893 {
3894 return sym->basetype->alignsize();
3895 }
3896
3897 Dsymbol *TypeTypedef::toDsymbol(Scope *sc)
3898 {
3899 return sym;
3900 }
3901
3902 void TypeTypedef::toDecoBuffer(OutBuffer *buf)
3903 { unsigned len;
3904 char *name;
3905
3906 name = sym->mangle();
3907 // if (name[0] == '_' && name[1] == 'D')
3908 // name += 2;
3909 //len = strlen(name);
3910 //buf->printf("%c%d%s", mangleChar[ty], len, name);
3911 buf->printf("%c%s", mangleChar[ty], name);
3912 }
3913
3914 void TypeTypedef::toTypeInfoBuffer(OutBuffer *buf)
3915 {
3916 sym->basetype->toTypeInfoBuffer(buf);
3917 }
3918
3919 void TypeTypedef::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
3920 {
3921 //printf("TypeTypedef::toCBuffer2() '%s'\n", sym->toChars());
3922 buf->prependstring(sym->toChars());
3923 if (ident)
3924 { buf->writeByte(' ');
3925 buf->writestring(ident->toChars());
3926 }
3927 }
3928
3929 Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident)
3930 {
3931 #if LOGDOTEXP
3932 printf("TypeTypedef::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars());
3933 #endif
3934 if (ident == Id::init)
3935 {
3936 return Type::dotExp(sc, e, ident);
3937 }
3938 return sym->basetype->dotExp(sc, e, ident);
3939 }
3940
3941 int TypeTypedef::isbit()
3942 {
3943 return sym->basetype->isbit();
3944 }
3945
3946 int TypeTypedef::isintegral()
3947 {
3948 //printf("TypeTypedef::isintegral()\n");
3949 //printf("sym = '%s'\n", sym->toChars());
3950 //printf("basetype = '%s'\n", sym->basetype->toChars());
3951 return sym->basetype->isintegral();
3952 }
3953
3954 int TypeTypedef::isfloating()
3955 {
3956 return sym->basetype->isfloating();
3957 }
3958
3959 int TypeTypedef::isreal()
3960 {
3961 return sym->basetype->isreal();
3962 }
3963
3964 int TypeTypedef::isimaginary()
3965 {
3966 return sym->basetype->isimaginary();
3967 }
3968
3969 int TypeTypedef::iscomplex()
3970 {
3971 return sym->basetype->iscomplex();
3972 }
3973
3974 int TypeTypedef::isunsigned()
3975 {
3976 return sym->basetype->isunsigned();
3977 }
3978
3979 int TypeTypedef::isscalar()
3980 {
3981 return sym->basetype->isscalar();
3982 }
3983
3984 int TypeTypedef::checkBoolean()
3985 {
3986 return sym->basetype->checkBoolean();
3987 }
3988
3989 Type *TypeTypedef::toBasetype()
3990 {
3991 if (sym->inuse)
3992 {
3993 sym->error("circular definition");
3994 sym->basetype = Type::terror;
3995 return Type::terror;
3996 }
3997 sym->inuse = 1;
3998 Type *t = sym->basetype->toBasetype();
3999 sym->inuse = 0;
4000 return t;
4001 }
4002
4003 MATCH TypeTypedef::implicitConvTo(Type *to)
4004 { MATCH m;
4005
4006 //printf("TypeTypedef::implicitConvTo()\n");
4007 if (this->equals(to))
4008 m = MATCHexact; // exact match
4009 else if (sym->basetype->implicitConvTo(to))
4010 m = MATCHconvert; // match with conversions
4011 else
4012 m = MATCHnomatch; // no match
4013 return m;
4014 }
4015
4016 Expression *TypeTypedef::defaultInit()
4017 { Expression *e;
4018 Type *bt;
4019
4020 #if LOGDEFAULTINIT
4021 printf("TypeTypedef::defaultInit() '%s'\n", toChars());
4022 #endif
4023 if (sym->init)
4024 {
4025 //sym->init->toExpression()->print();
4026 return sym->init->toExpression();
4027 }
4028 bt = sym->basetype;
4029 e = bt->defaultInit();
4030 e->type = this;
4031 while (bt->ty == Tsarray)
4032 {
4033 e->type = bt->next;
4034 bt = bt->next->toBasetype();
4035 }
4036 return e;
4037 }
4038
4039 int TypeTypedef::isZeroInit()
4040 {
4041 if (sym->init)
4042 {
4043 if (sym->init->isVoidInitializer())
4044 return 1; // initialize voids to 0
4045 Expression *e = sym->init->toExpression();
4046 if (e && e->isBool(FALSE))
4047 return 1;
4048 return 0; // assume not
4049 }
4050 if (sym->inuse)
4051 {
4052 sym->error("circular definition");
4053 sym->basetype = Type::terror;
4054 }
4055 sym->inuse = 1;
4056 int result = sym->basetype->isZeroInit();
4057 sym->inuse = 0;
4058 return result;
4059 }
4060
4061 int TypeTypedef::hasPointers()
4062 {
4063 return toBasetype()->hasPointers();
4064 }
4065
4066 /***************************** TypeStruct *****************************/
4067
4068 TypeStruct::TypeStruct(StructDeclaration *sym)
4069 : Type(Tstruct, NULL)
4070 {
4071 this->sym = sym;
4072 llvmInit = 0;
4073 }
4074
4075 char *TypeStruct::toChars()
4076 {
4077 //printf("sym.parent: %s, deco = %s\n", sym->parent->toChars(), deco);
4078 TemplateInstance *ti = sym->parent->isTemplateInstance();
4079 if (ti && ti->toAlias() == sym)
4080 return ti->toChars();
4081 return sym->toChars();
4082 }
4083
4084 Type *TypeStruct::syntaxCopy()
4085 {
4086 return this;
4087 }
4088
4089 Type *TypeStruct::semantic(Loc loc, Scope *sc)
4090 {
4091 //printf("TypeStruct::semantic('%s')\n", sym->toChars());
4092
4093 /* Cannot do semantic for sym because scope chain may not
4094 * be right.
4095 */
4096 //sym->semantic(sc);
4097
4098 return merge();
4099 }
4100
4101 d_uns64 TypeStruct::size(Loc loc)
4102 {
4103 return sym->size(loc);
4104 }
4105
4106 unsigned TypeStruct::alignsize()
4107 { unsigned sz;
4108
4109 sym->size(0); // give error for forward references
4110 sz = sym->alignsize;
4111 if (sz > sym->structalign)
4112 sz = sym->structalign;
4113 return sz;
4114 }
4115
4116 Dsymbol *TypeStruct::toDsymbol(Scope *sc)
4117 {
4118 return sym;
4119 }
4120
4121 void TypeStruct::toDecoBuffer(OutBuffer *buf)
4122 { unsigned len;
4123 char *name;
4124
4125 name = sym->mangle();
4126 //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", toChars(), name);
4127 // if (name[0] == '_' && name[1] == 'D')
4128 // name += 2;
4129 //len = strlen(name);
4130 //buf->printf("%c%d%s", mangleChar[ty], len, name);
4131 buf->printf("%c%s", mangleChar[ty], name);
4132 }
4133
4134 void TypeStruct::toTypeInfoBuffer(OutBuffer *buf)
4135 {
4136 toDecoBuffer(buf);
4137 }
4138
4139
4140 void TypeStruct::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
4141 {
4142 buf->prependbyte(' ');
4143 buf->prependstring(toChars());
4144 if (ident)
4145 buf->writestring(ident->toChars());
4146 }
4147
4148 Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
4149 { unsigned offset;
4150
4151 Expression *b;
4152 VarDeclaration *v;
4153 Dsymbol *s;
4154 DotVarExp *de;
4155 Declaration *d;
4156
4157 #if LOGDOTEXP
4158 printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
4159 #endif
4160 if (!sym->members)
4161 {
4162 error(e->loc, "struct %s is forward referenced", sym->toChars());
4163 return new IntegerExp(e->loc, 0, Type::tint32);
4164 }
4165
4166 if (ident == Id::tupleof)
4167 {
4168 /* Create a TupleExp
4169 */
4170 Expressions *exps = new Expressions;
4171 exps->reserve(sym->fields.dim);
4172 for (size_t i = 0; i < sym->fields.dim; i++)
4173 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
4174 Expression *fe = new DotVarExp(e->loc, e, v);
4175 exps->push(fe);
4176 }
4177 e = new TupleExp(e->loc, exps);
4178 e = e->semantic(sc);
4179 return e;
4180 }
4181
4182 if (e->op == TOKdotexp)
4183 { DotExp *de = (DotExp *)e;
4184
4185 if (de->e1->op == TOKimport)
4186 {
4187 ScopeExp *se = (ScopeExp *)de->e1;
4188
4189 s = se->sds->search(e->loc, ident, 0);
4190 e = de->e1;
4191 goto L1;
4192 }
4193 }
4194
4195 s = sym->search(e->loc, ident, 0);
4196 L1:
4197 if (!s)
4198 {
4199 //return getProperty(e->loc, ident);
4200 return Type::dotExp(sc, e, ident);
4201 }
4202 s = s->toAlias();
4203
4204 v = s->isVarDeclaration();
4205 if (v && v->isConst())
4206 { ExpInitializer *ei = v->getExpInitializer();
4207
4208 if (ei)
4209 { e = ei->exp->copy(); // need to copy it if it's a StringExp
4210 e = e->semantic(sc);
4211 return e;
4212 }
4213 }
4214
4215 if (s->getType())
4216 {
4217 //return new DotTypeExp(e->loc, e, s);
4218 return new TypeExp(e->loc, s->getType());
4219 }
4220
4221 EnumMember *em = s->isEnumMember();
4222 if (em)
4223 {
4224 assert(em->value);
4225 return em->value->copy();
4226 }
4227
4228 TemplateMixin *tm = s->isTemplateMixin();
4229 if (tm)
4230 { Expression *de;
4231
4232 de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
4233 de->type = e->type;
4234 return de;
4235 }
4236
4237 TemplateDeclaration *td = s->isTemplateDeclaration();
4238 if (td)
4239 {
4240 e = new DotTemplateExp(e->loc, e, td);
4241 e->semantic(sc);
4242 return e;
4243 }
4244
4245 d = s->isDeclaration();
4246 #ifdef DEBUG
4247 if (!d)
4248 printf("d = %s '%s'\n", s->kind(), s->toChars());
4249 #endif
4250 assert(d);
4251
4252 if (e->op == TOKtype)
4253 { FuncDeclaration *fd = sc->func;
4254
4255 if (d->needThis() && fd && fd->vthis)
4256 {
4257 e = new DotVarExp(e->loc, new ThisExp(e->loc), d);
4258 e = e->semantic(sc);
4259 return e;
4260 }
4261 if (d->isTupleDeclaration())
4262 {
4263 e = new TupleExp(e->loc, d->isTupleDeclaration());
4264 e = e->semantic(sc);
4265 return e;
4266 }
4267 return new VarExp(e->loc, d);
4268 }
4269
4270 if (d->isDataseg())
4271 {
4272 // (e, d)
4273 VarExp *ve;
4274
4275 accessCheck(e->loc, sc, e, d);
4276 ve = new VarExp(e->loc, d);
4277 e = new CommaExp(e->loc, e, ve);
4278 e->type = d->type;
4279 return e;
4280 }
4281
4282 if (v)
4283 {
4284 if (v->toParent() != sym)
4285 sym->error(e->loc, "'%s' is not a member", v->toChars());
4286
4287 // *(&e + offset)
4288 accessCheck(e->loc, sc, e, d);
4289 b = new AddrExp(e->loc, e);
4290 b->type = e->type->pointerTo();
4291 b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tint32));
4292 b->type = v->type->pointerTo();
4293 e = new PtrExp(e->loc, b);
4294 e->type = v->type;
4295 return e;
4296 }
4297
4298 de = new DotVarExp(e->loc, e, d);
4299 return de->semantic(sc);
4300 }
4301
4302 unsigned TypeStruct::memalign(unsigned salign)
4303 {
4304 sym->size(0); // give error for forward references
4305 return sym->structalign;
4306 }
4307
4308 Expression *TypeStruct::defaultInit()
4309 { Symbol *s;
4310 Declaration *d;
4311
4312 #if LOGDEFAULTINIT
4313 printf("TypeStruct::defaultInit() '%s'\n", toChars());
4314 #endif
4315 s = sym->toInitializer();
4316 d = new SymbolDeclaration(sym->loc, s, sym);
4317 assert(d);
4318 d->type = this;
4319 return new VarExp(sym->loc, d);
4320 }
4321
4322 int TypeStruct::isZeroInit()
4323 {
4324 return sym->zeroInit;
4325 }
4326
4327 int TypeStruct::checkBoolean()
4328 {
4329 return FALSE;
4330 }
4331
4332 int TypeStruct::hasPointers()
4333 {
4334 StructDeclaration *s = sym;
4335
4336 sym->size(0); // give error for forward references
4337 if (s->members)
4338 {
4339 for (size_t i = 0; i < s->members->dim; i++)
4340 {
4341 Dsymbol *sm = (Dsymbol *)s->members->data[i];
4342 if (sm->hasPointers())
4343 return TRUE;
4344 }
4345 }
4346 return FALSE;
4347 }
4348
4349
4350 /***************************** TypeClass *****************************/
4351
4352 TypeClass::TypeClass(ClassDeclaration *sym)
4353 : Type(Tclass, NULL)
4354 {
4355 this->sym = sym;
4356 llvmInit = 0;
4357 }
4358
4359 char *TypeClass::toChars()
4360 {
4361 return sym->toPrettyChars();
4362 }
4363
4364 Type *TypeClass::syntaxCopy()
4365 {
4366 return this;
4367 }
4368
4369 Type *TypeClass::semantic(Loc loc, Scope *sc)
4370 {
4371 //printf("TypeClass::semantic(%s)\n", sym->toChars());
4372 if (sym->scope)
4373 sym->semantic(sym->scope);
4374 return merge();
4375 }
4376
4377 d_uns64 TypeClass::size(Loc loc)
4378 {
4379 return PTRSIZE;
4380 }
4381
4382 Dsymbol *TypeClass::toDsymbol(Scope *sc)
4383 {
4384 return sym;
4385 }
4386
4387 void TypeClass::toDecoBuffer(OutBuffer *buf)
4388 { unsigned len;
4389 char *name;
4390
4391 name = sym->mangle();
4392 // if (name[0] == '_' && name[1] == 'D')
4393 // name += 2;
4394 //printf("TypeClass::toDecoBuffer('%s') = '%s'\n", toChars(), name);
4395 //len = strlen(name);
4396 //buf->printf("%c%d%s", mangleChar[ty], len, name);
4397 buf->printf("%c%s", mangleChar[ty], name);
4398 }
4399
4400 void TypeClass::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
4401 {
4402 buf->prependstring(sym->toChars());
4403 if (ident)
4404 { buf->writeByte(' ');
4405 buf->writestring(ident->toChars());
4406 }
4407 }
4408
4409 Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
4410 { unsigned offset;
4411
4412 Expression *b;
4413 VarDeclaration *v;
4414 Dsymbol *s;
4415 DotVarExp *de;
4416 Declaration *d;
4417
4418 #if LOGDOTEXP
4419 printf("TypeClass::dotExp(e='%s', ident='%s')\n", e->toChars(), ident->toChars());
4420 #endif
4421
4422 if (e->op == TOKdotexp)
4423 { DotExp *de = (DotExp *)e;
4424
4425 if (de->e1->op == TOKimport)
4426 {
4427 ScopeExp *se = (ScopeExp *)de->e1;
4428
4429 s = se->sds->search(e->loc, ident, 0);
4430 e = de->e1;
4431 goto L1;
4432 }
4433 }
4434
4435 if (ident == Id::tupleof)
4436 {
4437 /* Create a TupleExp
4438 */
4439 Expressions *exps = new Expressions;
4440 exps->reserve(sym->fields.dim);
4441 for (size_t i = 0; i < sym->fields.dim; i++)
4442 { VarDeclaration *v = (VarDeclaration *)sym->fields.data[i];
4443 Expression *fe = new DotVarExp(e->loc, e, v);
4444 exps->push(fe);
4445 }
4446 e = new TupleExp(e->loc, exps);
4447 e = e->semantic(sc);
4448 return e;
4449 }
4450
4451 s = sym->search(e->loc, ident, 0);
4452 L1:
4453 if (!s)
4454 {
4455 // See if it's a base class
4456 ClassDeclaration *cbase;
4457 for (cbase = sym->baseClass; cbase; cbase = cbase->baseClass)
4458 {
4459 if (cbase->ident->equals(ident))
4460 {
4461 e = new DotTypeExp(0, e, cbase);
4462 return e;
4463 }
4464 }
4465
4466 if (ident == Id::classinfo)
4467 {
4468 Type *t;
4469
4470 assert(ClassDeclaration::classinfo);
4471 t = ClassDeclaration::classinfo->type;
4472 if (e->op == TOKtype || e->op == TOKdottype)
4473 {
4474 if (!sym->vclassinfo)
4475 sym->vclassinfo = new ClassInfoDeclaration(sym);
4476 e = new VarExp(e->loc, sym->vclassinfo);
4477 e = e->addressOf(sc);
4478 e->type = t; // do this so we don't get redundant dereference
4479 }
4480 else
4481 {
4482 e = new PtrExp(e->loc, e);
4483 e->type = t->pointerTo();
4484 if (sym->isInterfaceDeclaration())
4485 {
4486 if (sym->isCOMclass())
4487 error(e->loc, "no .classinfo for COM interface objects");
4488 e->type = e->type->pointerTo();
4489 e = new PtrExp(e->loc, e);
4490 e->type = t->pointerTo();
4491 }
4492 e = new PtrExp(e->loc, e, t);
4493 }
4494 return e;
4495 }
4496
4497 if (ident == Id::typeinfo)
4498 {
4499 if (!global.params.useDeprecated)
4500 error(e->loc, ".typeinfo deprecated, use typeid(type)");
4501 return getTypeInfo(sc);
4502 }
4503 if (ident == Id::outer && sym->vthis)
4504 {
4505 s = sym->vthis;
4506 }
4507 else
4508 {
4509 //return getProperty(e->loc, ident);
4510 return Type::dotExp(sc, e, ident);
4511 }
4512 }
4513 s = s->toAlias();
4514 v = s->isVarDeclaration();
4515 if (v && v->isConst())
4516 { ExpInitializer *ei = v->getExpInitializer();
4517
4518 if (ei)
4519 { e = ei->exp->copy(); // need to copy it if it's a StringExp
4520 e = e->semantic(sc);
4521 return e;
4522 }
4523 }
4524
4525 if (s->getType())
4526 {
4527 // if (e->op == TOKtype)
4528 return new TypeExp(e->loc, s->getType());
4529 // return new DotTypeExp(e->loc, e, s);
4530 }
4531
4532 EnumMember *em = s->isEnumMember();
4533 if (em)
4534 {
4535 assert(em->value);
4536 return em->value->copy();
4537 }
4538
4539 TemplateMixin *tm = s->isTemplateMixin();
4540 if (tm)
4541 { Expression *de;
4542
4543 de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
4544 de->type = e->type;
4545 return de;
4546 }
4547
4548 TemplateDeclaration *td = s->isTemplateDeclaration();
4549 if (td)
4550 {
4551 e = new DotTemplateExp(e->loc, e, td);
4552 e->semantic(sc);
4553 return e;
4554 }
4555
4556 d = s->isDeclaration();
4557 if (!d)
4558 {
4559 e->error("%s.%s is not a declaration", e->toChars(), ident->toChars());
4560 return new IntegerExp(e->loc, 1, Type::tint32);
4561 }
4562
4563 if (e->op == TOKtype)
4564 {
4565 VarExp *ve;
4566
4567 if (d->needThis() && (hasThis(sc) || !d->isFuncDeclaration()))
4568 {
4569 if (sc->func)
4570 {
4571 ClassDeclaration *thiscd;
4572 thiscd = sc->func->toParent()->isClassDeclaration();
4573
4574 if (thiscd)
4575 {
4576 ClassDeclaration *cd = e->type->isClassHandle();
4577
4578 if (cd == thiscd)
4579 {
4580 e = new ThisExp(e->loc);
4581 e = new DotTypeExp(e->loc, e, cd);
4582 de = new DotVarExp(e->loc, e, d);
4583 e = de->semantic(sc);
4584 return e;
4585 }
4586 else if ((!cd || !cd->isBaseOf(thiscd, NULL)) &&
4587 !d->isFuncDeclaration())
4588 e->error("'this' is required, but %s is not a base class of %s", e->type->toChars(), thiscd->toChars());
4589 }
4590 }
4591
4592 de = new DotVarExp(e->loc, new ThisExp(e->loc), d);
4593 e = de->semantic(sc);
4594 return e;
4595 }
4596 else if (d->isTupleDeclaration())
4597 {
4598 e = new TupleExp(e->loc, d->isTupleDeclaration());
4599 e = e->semantic(sc);
4600 return e;
4601 }
4602 else
4603 ve = new VarExp(e->loc, d);
4604 return ve;
4605 }
4606
4607 if (d->isDataseg())
4608 {
4609 // (e, d)
4610 VarExp *ve;
4611
4612 accessCheck(e->loc, sc, e, d);
4613 ve = new VarExp(e->loc, d);
4614 e = new CommaExp(e->loc, e, ve);
4615 e->type = d->type;
4616 return e;
4617 }
4618
4619 if (d->parent && d->toParent()->isModule())
4620 {
4621 // (e, d)
4622 VarExp *ve;
4623
4624 ve = new VarExp(e->loc, d);
4625 e = new CommaExp(e->loc, e, ve);
4626 e->type = d->type;
4627 return e;
4628 }
4629
4630 de = new DotVarExp(e->loc, e, d);
4631 return de->semantic(sc);
4632 }
4633
4634 ClassDeclaration *TypeClass::isClassHandle()
4635 {
4636 return sym;
4637 }
4638
4639 int TypeClass::isauto()
4640 {
4641 return sym->isauto;
4642 }
4643
4644 int TypeClass::isBaseOf(Type *t, int *poffset)
4645 {
4646 if (t->ty == Tclass)
4647 { ClassDeclaration *cd;
4648
4649 cd = ((TypeClass *)t)->sym;
4650 if (sym->isBaseOf(cd, poffset))
4651 return 1;
4652 }
4653 return 0;
4654 }
4655
4656 MATCH TypeClass::implicitConvTo(Type *to)
4657 {
4658 //printf("TypeClass::implicitConvTo('%s')\n", to->toChars());
4659 if (this == to)
4660 return MATCHexact;
4661
4662 ClassDeclaration *cdto = to->isClassHandle();
4663 if (cdto && cdto->isBaseOf(sym, NULL))
4664 { //printf("is base\n");
4665 return MATCHconvert;
4666 }
4667
4668 if (global.params.Dversion == 1)
4669 {
4670 // Allow conversion to (void *)
4671 if (to->ty == Tpointer && to->next->ty == Tvoid)
4672 return MATCHconvert;
4673 }
4674
4675 return MATCHnomatch;
4676 }
4677
4678 Expression *TypeClass::defaultInit()
4679 {
4680 #if LOGDEFAULTINIT
4681 printf("TypeClass::defaultInit() '%s'\n", toChars());
4682 #endif
4683 Expression *e;
4684 e = new NullExp(0);
4685 e->type = this;
4686 return e;
4687 }
4688
4689 int TypeClass::isZeroInit()
4690 {
4691 return 1;
4692 }
4693
4694 int TypeClass::checkBoolean()
4695 {
4696 return TRUE;
4697 }
4698
4699 int TypeClass::hasPointers()
4700 {
4701 return TRUE;
4702 }
4703
4704 /***************************** TypeTuple *****************************/
4705
4706 TypeTuple::TypeTuple(Arguments *arguments)
4707 : Type(Ttuple, NULL)
4708 {
4709 //printf("TypeTuple(this = %p)\n", this);
4710 this->arguments = arguments;
4711 #ifdef DEBUG
4712 if (arguments)
4713 {
4714 for (size_t i = 0; i < arguments->dim; i++)
4715 {
4716 Argument *arg = (Argument *)arguments->data[i];
4717 assert(arg && arg->type);
4718 }
4719 }
4720 #endif
4721 }
4722
4723 /****************
4724 * Form TypeTuple from the types of the expressions.
4725 * Assume exps[] is already tuple expanded.
4726 */
4727
4728 TypeTuple::TypeTuple(Expressions *exps)
4729 : Type(Ttuple, NULL)
4730 {
4731 Arguments *arguments = new Arguments;
4732 if (exps)
4733 {
4734 arguments->setDim(exps->dim);
4735 for (size_t i = 0; i < exps->dim; i++)
4736 { Expression *e = (Expression *)exps->data[i];
4737 if (e->type->ty == Ttuple)
4738 e->error("cannot form tuple of tuples");
4739 Argument *arg = new Argument(STCin, e->type, NULL, NULL);
4740 arguments->data[i] = (void *)arg;
4741 }
4742 }
4743 this->arguments = arguments;
4744 }
4745
4746 Type *TypeTuple::syntaxCopy()
4747 {
4748 Arguments *args = Argument::arraySyntaxCopy(arguments);
4749 Type *t = new TypeTuple(args);
4750 return t;
4751 }
4752
4753 Type *TypeTuple::semantic(Loc loc, Scope *sc)
4754 {
4755 //printf("TypeTuple::semantic(this = %p)\n", this);
4756 if (!deco)
4757 deco = merge()->deco;
4758
4759 /* Don't return merge(), because a tuple with one type has the
4760 * same deco as that type.
4761 */
4762 return this;
4763 }
4764
4765 int TypeTuple::equals(Object *o)
4766 { Type *t;
4767
4768 t = (Type *)o;
4769 //printf("TypeTuple::equals(%s, %s)\n", toChars(), t->toChars());
4770 if (this == t)
4771 {
4772 return 1;
4773 }
4774 if (t->ty == Ttuple)
4775 { TypeTuple *tt = (TypeTuple *)t;
4776
4777 if (arguments->dim == tt->arguments->dim)
4778 {
4779 for (size_t i = 0; i < tt->arguments->dim; i++)
4780 { Argument *arg1 = (Argument *)arguments->data[i];
4781 Argument *arg2 = (Argument *)tt->arguments->data[i];
4782
4783 if (!arg1->type->equals(arg2->type))
4784 return 0;
4785 }
4786 return 1;
4787 }
4788 }
4789 return 0;
4790 }
4791
4792 Type *TypeTuple::reliesOnTident()
4793 {
4794 if (arguments)
4795 {
4796 for (size_t i = 0; i < arguments->dim; i++)
4797 {
4798 Argument *arg = (Argument *)arguments->data[i];
4799 Type *t = arg->type->reliesOnTident();
4800 if (t)
4801 return t;
4802 }
4803 }
4804 return NULL;
4805 }
4806
4807 void TypeTuple::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
4808 {
4809 OutBuffer buf2;
4810 Argument::argsToCBuffer(&buf2, hgs, arguments, 0);
4811 buf->prependstring(buf2.toChars());
4812 if (ident)
4813 { buf->writeByte(' ');
4814 buf->writestring(ident->toChars());
4815 }
4816 }
4817
4818 void TypeTuple::toDecoBuffer(OutBuffer *buf)
4819 {
4820 //printf("TypeTuple::toDecoBuffer() this = %p\n", this);
4821 OutBuffer buf2;
4822 Argument::argsToDecoBuffer(&buf2, arguments);
4823 unsigned len = buf2.offset;
4824 buf->printf("%c%d%.*s", mangleChar[ty], len, len, (char *)buf2.extractData());
4825 }
4826
4827 Expression *TypeTuple::getProperty(Loc loc, Identifier *ident)
4828 { Expression *e;
4829
4830 #if LOGDOTEXP
4831 printf("TypeTuple::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars());
4832 #endif
4833 if (ident == Id::length)
4834 {
4835 e = new IntegerExp(loc, arguments->dim, Type::tsize_t);
4836 }
4837 else
4838 {
4839 error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars());
4840 e = new IntegerExp(loc, 1, Type::tint32);
4841 }
4842 return e;
4843 }
4844
4845 /***************************** TypeSlice *****************************/
4846
4847 /* This is so we can slice a TypeTuple */
4848
4849 TypeSlice::TypeSlice(Type *next, Expression *lwr, Expression *upr)
4850 : Type(Tslice, next)
4851 {
4852 //printf("TypeSlice[%s .. %s]\n", lwr->toChars(), upr->toChars());
4853 this->lwr = lwr;
4854 this->upr = upr;
4855 }
4856
4857 Type *TypeSlice::syntaxCopy()
4858 {
4859 Type *t = new TypeSlice(next->syntaxCopy(), lwr->syntaxCopy(), upr->syntaxCopy());
4860 return t;
4861 }
4862
4863 Type *TypeSlice::semantic(Loc loc, Scope *sc)
4864 {
4865 //printf("TypeSlice::semantic() %s\n", toChars());
4866 next = next->semantic(loc, sc);
4867 //printf("next: %s\n", next->toChars());
4868
4869 Type *tbn = next->toBasetype();
4870 if (tbn->ty != Ttuple)
4871 { error(loc, "can only slice tuple types, not %s", tbn->toChars());
4872 return Type::terror;
4873 }
4874 TypeTuple *tt = (TypeTuple *)tbn;
4875
4876 lwr = semanticLength(sc, tbn, lwr);
4877 lwr = lwr->optimize(WANTvalue);
4878 uinteger_t i1 = lwr->toUInteger();
4879
4880 upr = semanticLength(sc, tbn, upr);
4881 upr = upr->optimize(WANTvalue);
4882 uinteger_t i2 = upr->toUInteger();
4883
4884 if (!(i1 <= i2 && i2 <= tt->arguments->dim))
4885 { error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, tt->arguments->dim);
4886 return Type::terror;
4887 }
4888
4889 Arguments *args = new Arguments;
4890 args->reserve(i2 - i1);
4891 for (size_t i = i1; i < i2; i++)
4892 { Argument *arg = (Argument *)tt->arguments->data[i];
4893 args->push(arg);
4894 }
4895
4896 return new TypeTuple(args);
4897 }
4898
4899 void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
4900 {
4901 next->resolve(loc, sc, pe, pt, ps);
4902 if (*pe)
4903 { // It's really a slice expression
4904 Expression *e;
4905 e = new SliceExp(loc, *pe, lwr, upr);
4906 *pe = e;
4907 }
4908 else if (*ps)
4909 { Dsymbol *s = *ps;
4910 TupleDeclaration *td = s->isTupleDeclaration();
4911 if (td)
4912 {
4913 /* It's a slice of a TupleDeclaration
4914 */
4915 ScopeDsymbol *sym = new ArrayScopeSymbol(td);
4916 sym->parent = sc->scopesym;
4917 sc = sc->push(sym);
4918
4919 lwr = lwr->semantic(sc);
4920 lwr = lwr->optimize(WANTvalue);
4921 uinteger_t i1 = lwr->toUInteger();
4922
4923 upr = upr->semantic(sc);
4924 upr = upr->optimize(WANTvalue);
4925 uinteger_t i2 = upr->toUInteger();
4926
4927 sc = sc->pop();
4928
4929 if (!(i1 <= i2 && i2 <= td->objects->dim))
4930 { error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, td->objects->dim);
4931 goto Ldefault;
4932 }
4933
4934 if (i1 == 0 && i2 == td->objects->dim)
4935 {
4936 *ps = td;
4937 return;
4938 }
4939
4940 /* Create a new TupleDeclaration which
4941 * is a slice [i1..i2] out of the old one.
4942 */
4943 Objects *objects = new Objects;
4944 objects->setDim(i2 - i1);
4945 for (size_t i = 0; i < objects->dim; i++)
4946 {
4947 objects->data[i] = td->objects->data[(size_t)i1 + i];
4948 }
4949
4950 TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
4951 *ps = tds;
4952 }
4953 else
4954 goto Ldefault;
4955 }
4956 else
4957 {
4958 Ldefault:
4959 Type::resolve(loc, sc, pe, pt, ps);
4960 }
4961 }
4962
4963 void TypeSlice::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
4964 {
4965 OutBuffer buf2;
4966
4967 buf2.printf("[%s .. ", lwr->toChars());
4968 buf2.printf("%s]", upr->toChars());
4969
4970 buf->prependstring(buf2.toChars());
4971 if (ident)
4972 {
4973 buf->writeByte(' ');
4974 buf->writestring(ident->toChars());
4975 }
4976 next->toCBuffer2(buf, NULL, hgs);
4977 }
4978
4979 /***************************** Argument *****************************/
4980
4981 Argument::Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg)
4982 {
4983 this->type = type;
4984 this->ident = ident;
4985 this->storageClass = storageClass;
4986 this->defaultArg = defaultArg;
4987 this->llvmCopy = false;
4988 this->vardecl = 0;
4989 }
4990
4991 Argument *Argument::syntaxCopy()
4992 {
4993 Argument *a = new Argument(storageClass,
4994 type ? type->syntaxCopy() : NULL,
4995 ident,
4996 defaultArg ? defaultArg->syntaxCopy() : NULL);
4997 return a;
4998 }
4999
5000 Arguments *Argument::arraySyntaxCopy(Arguments *args)
5001 { Arguments *a = NULL;
5002
5003 if (args)
5004 {
5005 a = new Arguments();
5006 a->setDim(args->dim);
5007 for (size_t i = 0; i < a->dim; i++)
5008 { Argument *arg = (Argument *)args->data[i];
5009
5010 arg = arg->syntaxCopy();
5011 a->data[i] = (void *)arg;
5012 }
5013 }
5014 return a;
5015 }
5016
5017 char *Argument::argsTypesToChars(Arguments *args, int varargs)
5018 { OutBuffer *buf;
5019
5020 buf = new OutBuffer();
5021
5022 buf->writeByte('(');
5023 if (args)
5024 { int i;
5025 OutBuffer argbuf;
5026 HdrGenState hgs;
5027
5028 for (i = 0; i < args->dim; i++)
5029 { Argument *arg;
5030
5031 if (i)
5032 buf->writeByte(',');
5033 arg = (Argument *)args->data[i];
5034 argbuf.reset();
5035 arg->type->toCBuffer2(&argbuf, NULL, &hgs);
5036 buf->write(&argbuf);
5037 }
5038 if (varargs)
5039 {
5040 if (i && varargs == 1)
5041 buf->writeByte(',');
5042 buf->writestring("...");
5043 }
5044 }
5045 buf->writeByte(')');
5046
5047 return buf->toChars();
5048 }
5049
5050 void Argument::argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs)
5051 {
5052 buf->writeByte('(');
5053 if (arguments)
5054 { int i;
5055 OutBuffer argbuf;
5056
5057 for (i = 0; i < arguments->dim; i++)
5058 { Argument *arg;
5059
5060 if (i)
5061 buf->writestring(", ");
5062 arg = (Argument *)arguments->data[i];
5063 if (arg->storageClass & STCout)
5064 buf->writestring("out ");
5065 else if (arg->storageClass & STCref)
5066 buf->writestring((global.params.Dversion == 1)
5067 ? (char *)"inout " : (char *)"ref ");
5068 else if (arg->storageClass & STClazy)
5069 buf->writestring("lazy ");
5070 argbuf.reset();
5071 arg->type->toCBuffer2(&argbuf, arg->ident, hgs);
5072 if (arg->defaultArg)
5073 {
5074 argbuf.writestring(" = ");
5075 arg->defaultArg->toCBuffer(&argbuf, hgs);
5076 }
5077 buf->write(&argbuf);
5078 }
5079 if (varargs)
5080 {
5081 if (i && varargs == 1)
5082 buf->writeByte(',');
5083 buf->writestring("...");
5084 }
5085 }
5086 buf->writeByte(')');
5087 }
5088
5089
5090 void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments)
5091 {
5092 //printf("Argument::argsToDecoBuffer()\n");
5093
5094 // Write argument types
5095 if (arguments)
5096 {
5097 size_t dim = Argument::dim(arguments);
5098 for (size_t i = 0; i < dim; i++)
5099 {
5100 Argument *arg = Argument::getNth(arguments, i);
5101 arg->toDecoBuffer(buf);
5102 }
5103 }
5104 }
5105
5106 /****************************************************
5107 * Determine if parameter is a lazy array of delegates.
5108 * If so, return the return type of those delegates.
5109 * If not, return NULL.
5110 */
5111
5112 Type *Argument::isLazyArray()
5113 {
5114 // if (inout == Lazy)
5115 {
5116 Type *tb = type->toBasetype();
5117 if (tb->ty == Tsarray || tb->ty == Tarray)
5118 {
5119 Type *tel = tb->next->toBasetype();
5120 if (tel->ty == Tdelegate)
5121 {
5122 TypeDelegate *td = (TypeDelegate *)tel;
5123 TypeFunction *tf = (TypeFunction *)td->next;
5124
5125 if (!tf->varargs && Argument::dim(tf->parameters) == 0)
5126 {
5127 return tf->next; // return type of delegate
5128 }
5129 }
5130 }
5131 }
5132 return NULL;
5133 }
5134
5135 void Argument::toDecoBuffer(OutBuffer *buf)
5136 {
5137 switch (storageClass & (STCin | STCout | STCref | STClazy))
5138 { case 0:
5139 case STCin:
5140 break;
5141 case STCout:
5142 buf->writeByte('J');
5143 break;
5144 case STCref:
5145 buf->writeByte('K');
5146 break;
5147 case STClazy:
5148 buf->writeByte('L');
5149 break;
5150 default:
5151 #ifdef DEBUG
5152 halt();
5153 #endif
5154 assert(0);
5155 }
5156 type->toDecoBuffer(buf);
5157 }
5158
5159 /***************************************
5160 * Determine number of arguments, folding in tuples.
5161 */
5162
5163 size_t Argument::dim(Arguments *args)
5164 {
5165 size_t n = 0;
5166 if (args)
5167 {
5168 for (size_t i = 0; i < args->dim; i++)
5169 { Argument *arg = (Argument *)args->data[i];
5170 Type *t = arg->type->toBasetype();
5171
5172 if (t->ty == Ttuple)
5173 { TypeTuple *tu = (TypeTuple *)t;
5174 n += dim(tu->arguments);
5175 }
5176 else
5177 n++;
5178 }
5179 }
5180 return n;
5181 }
5182
5183 /***************************************
5184 * Get nth Argument, folding in tuples.
5185 * Returns:
5186 * Argument* nth Argument
5187 * NULL not found, *pn gets incremented by the number
5188 * of Arguments
5189 */
5190
5191 Argument *Argument::getNth(Arguments *args, size_t nth, size_t *pn)
5192 {
5193 if (!args)
5194 return NULL;
5195
5196 size_t n = 0;
5197 for (size_t i = 0; i < args->dim; i++)
5198 { Argument *arg = (Argument *)args->data[i];
5199 Type *t = arg->type->toBasetype();
5200
5201 if (t->ty == Ttuple)
5202 { TypeTuple *tu = (TypeTuple *)t;
5203 arg = getNth(tu->arguments, nth - n, &n);
5204 if (arg)
5205 return arg;
5206 }
5207 else if (n == nth)
5208 return arg;
5209 else
5210 n++;
5211 }
5212
5213 if (pn)
5214 *pn += n;
5215 return NULL;
5216 }