comparison dmd2/mtype.c @ 758:f04dde6e882c

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