1:
2: // Compiler implementation of the D programming language
3: // Copyright (c) 1999-2011 by Digital Mars
4: // All Rights Reserved
5: // written by Walter Bright
6: // http://www.digitalmars.com
7: // http://www.dsource.org/projects/dmd/browser/trunk/src/mtype.c
8: // License for redistribution is by either the Artistic License
9: // in artistic.txt, or the GNU General Public License in gnu.txt.
10: // See the included readme.txt for details.
11:
12: #define __C99FEATURES__ 1 // Needed on Solaris for NaN and more
13: #define __USE_ISOC99 1 // so signbit() gets defined
14:
15: #if (defined (__SVR4) && defined (__sun))
16: #include <alloca.h>
17: #endif
18:
19: #include <math.h>
20:
21: #include <stdio.h>
22: static char __file__[] = __FILE__; /* for tassert.h */
23: #include "tassert.h"
24: #include <float.h>
25:
26: #if _MSC_VER
27: #include <malloc.h>
28: #include <complex>
29: #include <limits>
30: #elif __DMC__
31: #include <complex.h>
32: #elif __MINGW32__
33: #include <malloc.h>
34: #endif
35:
36: #include "rmem.h"
37: #include "port.h"
38:
39: #include "dsymbol.h"
40: #include "mtype.h"
41: #include "scope.h"
42: #include "init.h"
43: #include "expression.h"
44: #include "attrib.h"
45: #include "declaration.h"
46: #include "template.h"
47: #include "id.h"
48: #include "enum.h"
49: #include "import.h"
50: #include "aggregate.h"
51: #include "hdrgen.h"
52:
53: FuncDeclaration *hasThis(Scope *sc);
54:
55:
56: #define LOGDOTEXP 0 // log ::dotExp()
57: #define LOGDEFAULTINIT 0 // log ::defaultInit()
58:
59: // Allow implicit conversion of T[] to T*
60: #define IMPLICIT_ARRAY_TO_PTR global.params.useDeprecated
61:
62: /* These have default values for 32 bit code, they get
63: * adjusted for 64 bit code.
64: */
65:
66: int PTRSIZE = 4;
67:
68: /* REALSIZE = size a real consumes in memory
69: * REALPAD = 'padding' added to the CPU real size to bring it up to REALSIZE
70: * REALALIGNSIZE = alignment for reals
71: */
72: #if TARGET_OSX
73: int REALSIZE = 16;
74: int REALPAD = 6;
75: int REALALIGNSIZE = 16;
76: #elif TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
77: int REALSIZE = 12;
78: int REALPAD = 2;
79: int REALALIGNSIZE = 4;
80: #elif TARGET_WINDOS
81: int REALSIZE = 10;
82: int REALPAD = 0;
83: int REALALIGNSIZE = 2;
84: #else
85: #error "fix this"
86: #endif
87:
88: int Tsize_t = Tuns32;
89: int Tptrdiff_t = Tint32;
90:
91: /***************************** Type *****************************/
92:
93: ClassDeclaration *Type::typeinfo;
94: ClassDeclaration *Type::typeinfoclass;
95: ClassDeclaration *Type::typeinfointerface;
96: ClassDeclaration *Type::typeinfostruct;
97: ClassDeclaration *Type::typeinfotypedef;
98: ClassDeclaration *Type::typeinfopointer;
99: ClassDeclaration *Type::typeinfoarray;
100: ClassDeclaration *Type::typeinfostaticarray;
101: ClassDeclaration *Type::typeinfoassociativearray;
102: ClassDeclaration *Type::typeinfoenum;
103: ClassDeclaration *Type::typeinfofunction;
104: ClassDeclaration *Type::typeinfodelegate;
105: ClassDeclaration *Type::typeinfotypelist;
106: ClassDeclaration *Type::typeinfoconst;
107: ClassDeclaration *Type::typeinfoinvariant;
108: ClassDeclaration *Type::typeinfoshared;
109: ClassDeclaration *Type::typeinfowild;
110:
111: TemplateDeclaration *Type::associativearray;
112:
113: Type *Type::tvoidptr;
114: Type *Type::tstring;
115: Type *Type::basic[TMAX];
116: unsigned char Type::mangleChar[TMAX];
117: unsigned char Type::sizeTy[TMAX];
118: StringTable Type::stringtable;
119:
120:
121: Type::Type(TY ty)
122: {
123: this->ty = ty;
124: this->mod = 0;
125: this->deco = NULL;
126: #if DMDV2
127: this->cto = NULL;
128: this->ito = NULL;
129: this->sto = NULL;
130: this->scto = NULL;
131: this->wto = NULL;
132: this->swto = NULL;
133: #endif
134: this->pto = NULL;
135: this->rto = NULL;
136: this->arrayof = NULL;
137: this->vtinfo = NULL;
138: this->ctype = NULL;
139: }
140:
141: Type *Type::syntaxCopy()
142: {
143: print();
144: fprintf(stdmsg, "ty = %d\n", ty);
145: assert(0);
146: return this;
147: }
148:
149: int Type::equals(Object *o)
150: { Type *t;
151:
152: t = (Type *)o;
153: //printf("Type::equals(%s, %s)\n", toChars(), t->toChars());
154: if (this == o ||
155: (t && deco == t->deco) && // deco strings are unique
156: deco != NULL) // and semantic() has been run
157: {
158: //printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
159: return 1;
160: }
161: //if (deco && t && t->deco) printf("deco = '%s', t->deco = '%s'\n", deco, t->deco);
162: return 0;
163: }
164:
165: char Type::needThisPrefix()
166: {
167: return 'M'; // name mangling prefix for functions needing 'this'
168: }
169:
170: void Type::init()
171: { int i;
172: int j;
warning C4101: 'j' : unreferenced local variable
173:
174: Lexer::initKeywords();
175:
176: for (i = 0; i < TMAX; i++)
177: sizeTy[i] = sizeof(TypeBasic);
178: sizeTy[Tsarray] = sizeof(TypeSArray);
179: sizeTy[Tarray] = sizeof(TypeDArray);
180: sizeTy[Taarray] = sizeof(TypeAArray);
181: sizeTy[Tpointer] = sizeof(TypePointer);
182: sizeTy[Treference] = sizeof(TypeReference);
183: sizeTy[Tfunction] = sizeof(TypeFunction);
184: sizeTy[Tdelegate] = sizeof(TypeDelegate);
185: sizeTy[Tident] = sizeof(TypeIdentifier);
186: sizeTy[Tinstance] = sizeof(TypeInstance);
187: sizeTy[Ttypeof] = sizeof(TypeTypeof);
188: sizeTy[Tenum] = sizeof(TypeEnum);
189: sizeTy[Ttypedef] = sizeof(TypeTypedef);
190: sizeTy[Tstruct] = sizeof(TypeStruct);
191: sizeTy[Tclass] = sizeof(TypeClass);
192: sizeTy[Ttuple] = sizeof(TypeTuple);
193: sizeTy[Tslice] = sizeof(TypeSlice);
194: sizeTy[Treturn] = sizeof(TypeReturn);
195:
196: mangleChar[Tarray] = 'A';
197: mangleChar[Tsarray] = 'G';
198: mangleChar[Taarray] = 'H';
199: mangleChar[Tpointer] = 'P';
200: mangleChar[Treference] = 'R';
201: mangleChar[Tfunction] = 'F';
202: mangleChar[Tident] = 'I';
203: mangleChar[Tclass] = 'C';
204: mangleChar[Tstruct] = 'S';
205: mangleChar[Tenum] = 'E';
206: mangleChar[Ttypedef] = 'T';
207: mangleChar[Tdelegate] = 'D';
208:
209: mangleChar[Tnone] = 'n';
210: mangleChar[Tvoid] = 'v';
211: mangleChar[Tint8] = 'g';
212: mangleChar[Tuns8] = 'h';
213: mangleChar[Tint16] = 's';
214: mangleChar[Tuns16] = 't';
215: mangleChar[Tint32] = 'i';
216: mangleChar[Tuns32] = 'k';
217: mangleChar[Tint64] = 'l';
218: mangleChar[Tuns64] = 'm';
219: mangleChar[Tfloat32] = 'f';
220: mangleChar[Tfloat64] = 'd';
221: mangleChar[Tfloat80] = 'e';
222:
223: mangleChar[Timaginary32] = 'o';
224: mangleChar[Timaginary64] = 'p';
225: mangleChar[Timaginary80] = 'j';
226: mangleChar[Tcomplex32] = 'q';
227: mangleChar[Tcomplex64] = 'r';
228: mangleChar[Tcomplex80] = 'c';
229:
230: mangleChar[Tbool] = 'b';
231: mangleChar[Tascii] = 'a';
232: mangleChar[Twchar] = 'u';
233: mangleChar[Tdchar] = 'w';
234:
235: // '@' shouldn't appear anywhere in the deco'd names
236: mangleChar[Tinstance] = '@';
237: mangleChar[Terror] = '@';
238: mangleChar[Ttypeof] = '@';
239: mangleChar[Ttuple] = 'B';
240: mangleChar[Tslice] = '@';
241: mangleChar[Treturn] = '@';
242:
243: for (i = 0; i < TMAX; i++)
244: { if (!mangleChar[i])
245: fprintf(stdmsg, "ty = %d\n", i);
246: assert(mangleChar[i]);
247: }
248:
249: // Set basic types
250: static TY basetab[] =
251: { Tvoid, Tint8, Tuns8, Tint16, Tuns16, Tint32, Tuns32, Tint64, Tuns64,
252: Tfloat32, Tfloat64, Tfloat80,
253: Timaginary32, Timaginary64, Timaginary80,
254: Tcomplex32, Tcomplex64, Tcomplex80,
255: Tbool,
256: Tascii, Twchar, Tdchar };
257:
258: for (i = 0; i < sizeof(basetab) / sizeof(basetab[0]); i++)
259: { Type *t = new TypeBasic(basetab[i]);
warning C6211: Leaking memory 't' due to an exception. Consider using a local catch block to clean up memory: Lines: 171, 172, 174, 176, 177, 176, 177, 176, 177, 176, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 223, 224, 225, 226, 227, 228, 230, 231, 232, 233, 236, 237, 238, 239, 240, 241, 243, 244, 246, 243, 244, 246, 243, 244, 246, 243, 250, 258, 259, 260, 261, 258, 259, 260, 261, 258, 259, 260, 261, 258, 263
260: t = t->merge();
261: basic[basetab[i]] = t;
262: }
263: basic[Terror] = new TypeError();
264:
265: tvoidptr = tvoid->pointerTo();
266: tstring = tchar->invariantOf()->arrayOf();
267:
268: if (global.params.is64bit)
269: {
270: PTRSIZE = 8;
271: if (global.params.isLinux || global.params.isFreeBSD || global.params.isSolaris)
272: {
273: REALSIZE = 16;
274: REALPAD = 6;
275: REALALIGNSIZE = 16;
276: }
277: Tsize_t = Tuns64;
278: Tptrdiff_t = Tint64;
279: }
280: else
281: {
282: PTRSIZE = 4;
283: #if TARGET_OSX
284: REALSIZE = 16;
285: REALPAD = 6;
286: #elif TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
287: REALSIZE = 12;
288: REALPAD = 2;
289: #else
290: REALSIZE = 10;
291: REALPAD = 0;
292: #endif
293: Tsize_t = Tuns32;
294: Tptrdiff_t = Tint32;
295: }
296: }
297:
298: d_uns64 Type::size()
299: {
300: return size(0);
301: }
302:
303: d_uns64 Type::size(Loc loc)
304: {
305: error(loc, "no size for type %s", toChars());
306: return 1;
307: }
308:
309: unsigned Type::alignsize()
310: {
311: return size(0);
warning C4244: 'return' : conversion from 'd_uns64' to 'unsigned int', possible loss of data
312: }
313:
314: Type *Type::semantic(Loc loc, Scope *sc)
315: {
316: return merge();
317: }
318:
319: Type *Type::trySemantic(Loc loc, Scope *sc)
320: {
321: //printf("+trySemantic(%s) %d\n", toChars(), global.errors);
322: unsigned errors = global.errors;
323: global.gag++; // suppress printing of error messages
324: Type *t = semantic(loc, sc);
325: global.gag--;
326: if (errors != global.errors) // if any errors happened
327: {
328: global.errors = errors;
329: t = NULL;
330: }
331: //printf("-trySemantic(%s) %d\n", toChars(), global.errors);
332: return t;
333: }
334:
335: /*******************************
336: * Determine if converting 'this' to 'to' is an identity operation,
337: * a conversion to const operation, or the types aren't the same.
338: * Returns:
339: * MATCHequal 'this' == 'to'
340: * MATCHconst 'to' is const
341: * MATCHnomatch conversion to mutable or invariant
342: */
343:
344: MATCH Type::constConv(Type *to)
345: {
346: if (equals(to))
347: return MATCHexact;
348: if (ty == to->ty && MODimplicitConv(mod, to->mod))
349: return MATCHconst;
350: return MATCHnomatch;
351: }
352:
353: /********************************
354: * Convert to 'const'.
355: */
356:
357: Type *Type::constOf()
358: {
359: //printf("Type::constOf() %p %s\n", this, toChars());
360: if (mod == MODconst)
361: return this;
362: if (cto)
363: { assert(cto->mod == MODconst);
364: return cto;
365: }
366: Type *t = makeConst();
367: t = t->merge();
368: t->fixTo(this);
369: //printf("-Type::constOf() %p %s\n", t, toChars());
370: return t;
371: }
372:
373: /********************************
374: * Convert to 'immutable'.
375: */
376:
377: Type *Type::invariantOf()
378: {
379: //printf("Type::invariantOf() %p %s\n", this, toChars());
380: if (isImmutable())
381: {
382: return this;
383: }
384: if (ito)
385: {
386: assert(ito->isImmutable());
387: return ito;
388: }
389: Type *t = makeInvariant();
390: t = t->merge();
391: t->fixTo(this);
392: //printf("\t%p\n", t);
393: return t;
394: }
395:
396: /********************************
397: * Make type mutable.
398: */
399:
400: Type *Type::mutableOf()
401: {
402: //printf("Type::mutableOf() %p, %s\n", this, toChars());
403: Type *t = this;
404: if (isConst())
405: { if (isShared())
406: t = sto; // shared const => shared
407: else
408: t = cto; // const => naked
409: assert(!t || t->isMutable());
410: }
411: else if (isImmutable())
412: { t = ito; // immutable => naked
413: assert(!t || (t->isMutable() && !t->isShared()));
414: }
415: else if (isWild())
416: {
417: if (isShared())
418: t = sto; // shared wild => shared
419: else
420: t = wto; // wild => naked
421: assert(!t || t->isMutable());
422: }
423: if (!t)
424: {
425: t = makeMutable();
426: t = t->merge();
427: t->fixTo(this);
428: }
429: assert(t->isMutable());
430: return t;
431: }
432:
433: Type *Type::sharedOf()
434: {
435: //printf("Type::sharedOf() %p, %s\n", this, toChars());
436: if (mod == MODshared)
437: {
438: return this;
439: }
440: if (sto)
441: {
442: assert(sto->isShared());
443: return sto;
444: }
445: Type *t = makeShared();
446: t = t->merge();
447: t->fixTo(this);
448: //printf("\t%p\n", t);
449: return t;
450: }
451:
452: Type *Type::sharedConstOf()
453: {
454: //printf("Type::sharedConstOf() %p, %s\n", this, toChars());
455: if (mod == (MODshared | MODconst))
456: {
457: return this;
458: }
459: if (scto)
460: {
461: assert(scto->mod == (MODshared | MODconst));
462: return scto;
463: }
464: Type *t = makeSharedConst();
465: t = t->merge();
466: t->fixTo(this);
467: //printf("\t%p\n", t);
468: return t;
469: }
470:
471:
472: /********************************
473: * Make type unshared.
474: * 0 => 0
475: * const => const
476: * immutable => immutable
477: * shared => 0
478: * shared const => const
479: * wild => wild
480: * shared wild => wild
481: */
482:
483: Type *Type::unSharedOf()
484: {
485: //printf("Type::unSharedOf() %p, %s\n", this, toChars());
486: Type *t = this;
487:
488: if (isShared())
489: {
490: if (isConst())
491: t = cto; // shared const => const
492: else if (isWild())
493: t = wto; // shared wild => wild
494: else
495: t = sto;
496: assert(!t || !t->isShared());
497: }
498:
499: if (!t)
500: {
501: unsigned sz = sizeTy[ty];
502: t = (Type *)mem.malloc(sz);
503: memcpy(t, this, sz);
504: t->mod = mod & ~MODshared;
505: t->deco = NULL;
506: t->arrayof = NULL;
507: t->pto = NULL;
508: t->rto = NULL;
509: t->cto = NULL;
510: t->ito = NULL;
511: t->sto = NULL;
512: t->scto = NULL;
513: t->wto = NULL;
514: t->swto = NULL;
515: t->vtinfo = NULL;
516: t = t->merge();
517:
518: t->fixTo(this);
519: }
520: assert(!t->isShared());
521: return t;
522: }
523:
524: /********************************
525: * Convert to 'wild'.
526: */
527:
528: Type *Type::wildOf()
529: {
530: //printf("Type::wildOf() %p %s\n", this, toChars());
531: if (mod == MODwild)
532: {
533: return this;
534: }
535: if (wto)
536: {
537: assert(wto->isWild());
538: return wto;
539: }
540: Type *t = makeWild();
541: t = t->merge();
542: t->fixTo(this);
543: //printf("\t%p %s\n", t, t->toChars());
544: return t;
545: }
546:
547: Type *Type::sharedWildOf()
548: {
549: //printf("Type::sharedWildOf() %p, %s\n", this, toChars());
550: if (mod == (MODshared | MODwild))
551: {
552: return this;
553: }
554: if (swto)
555: {
556: assert(swto->mod == (MODshared | MODwild));
557: return swto;
558: }
559: Type *t = makeSharedWild();
560: t = t->merge();
561: t->fixTo(this);
562: //printf("\t%p\n", t);
563: return t;
564: }
565:
566: /**********************************
567: * For our new type 'this', which is type-constructed from t,
568: * fill in the cto, ito, sto, scto, wto shortcuts.
569: */
570:
571: void Type::fixTo(Type *t)
572: {
573: ito = t->ito;
574: #if 0
575: /* Cannot do these because these are not fully transitive:
576: * there can be a shared ptr to immutable, for example.
577: * Immutable subtypes are always immutable, though.
578: */
579: cto = t->cto;
580: sto = t->sto;
581: scto = t->scto;
582: #endif
583:
584: assert(mod != t->mod);
585: #define X(m, n) (((m) << 4) | (n))
586: switch (X(mod, t->mod))
587: {
588: case X(0, MODconst):
589: cto = t;
590: break;
591:
592: case X(0, MODimmutable):
593: ito = t;
594: break;
595:
596: case X(0, MODshared):
597: sto = t;
598: break;
599:
600: case X(0, MODshared | MODconst):
601: scto = t;
602: break;
603:
604: case X(0, MODwild):
605: wto = t;
606: break;
607:
608: case X(0, MODshared | MODwild):
609: swto = t;
610: break;
611:
612:
613: case X(MODconst, 0):
614: cto = NULL;
615: goto L2;
616:
617: case X(MODconst, MODimmutable):
618: ito = t;
619: goto L2;
620:
621: case X(MODconst, MODshared):
622: sto = t;
623: goto L2;
624:
625: case X(MODconst, MODshared | MODconst):
626: scto = t;
627: goto L2;
628:
629: case X(MODconst, MODwild):
630: wto = t;
631: goto L2;
632:
633: case X(MODconst, MODshared | MODwild):
634: swto = t;
635: L2:
636: t->cto = this;
637: break;
638:
639:
640: case X(MODimmutable, 0):
641: ito = NULL;
642: goto L3;
643:
644: case X(MODimmutable, MODconst):
645: cto = t;
646: goto L3;
647:
648: case X(MODimmutable, MODshared):
649: sto = t;
650: goto L3;
651:
652: case X(MODimmutable, MODshared | MODconst):
653: scto = t;
654: goto L3;
655:
656: case X(MODimmutable, MODwild):
657: wto = t;
658: goto L3;
659:
660: case X(MODimmutable, MODshared | MODwild):
661: swto = t;
662: L3:
663: t->ito = this;
664: if (t->cto) t->cto->ito = this;
665: if (t->sto) t->sto->ito = this;
666: if (t->scto) t->scto->ito = this;
667: if (t->wto) t->wto->ito = this;
668: if (t->swto) t->swto->ito = this;
669: break;
670:
671:
672: case X(MODshared, 0):
673: sto = NULL;
674: goto L4;
675:
676: case X(MODshared, MODconst):
677: cto = t;
678: goto L4;
679:
680: case X(MODshared, MODimmutable):
681: ito = t;
682: goto L4;
683:
684: case X(MODshared, MODshared | MODconst):
685: scto = t;
686: goto L4;
687:
688: case X(MODshared, MODwild):
689: wto = t;
690: goto L4;
691:
692: case X(MODshared, MODshared | MODwild):
693: swto = t;
694: L4:
695: t->sto = this;
696: break;
697:
698:
699: case X(MODshared | MODconst, 0):
700: scto = NULL;
701: goto L5;
702:
703: case X(MODshared | MODconst, MODconst):
704: cto = t;
705: goto L5;
706:
707: case X(MODshared | MODconst, MODimmutable):
708: ito = t;
709: goto L5;
710:
711: case X(MODshared | MODconst, MODwild):
712: wto = t;
713: goto L5;
714:
715: case X(MODshared | MODconst, MODshared):
716: sto = t;
717: goto L5;
718:
719: case X(MODshared | MODconst, MODshared | MODwild):
720: swto = t;
721: L5:
722: t->scto = this;
723: break;
724:
725:
726: case X(MODwild, 0):
727: wto = NULL;
728: goto L6;
729:
730: case X(MODwild, MODconst):
731: cto = t;
732: goto L6;
733:
734: case X(MODwild, MODimmutable):
735: ito = t;
736: goto L6;
737:
738: case X(MODwild, MODshared):
739: sto = t;
740: goto L6;
741:
742: case X(MODwild, MODshared | MODconst):
743: scto = t;
744: goto L6;
745:
746: case X(MODwild, MODshared | MODwild):
747: swto = t;
748: L6:
749: t->wto = this;
750: break;
751:
752:
753: case X(MODshared | MODwild, 0):
754: swto = NULL;
755: goto L7;
756:
757: case X(MODshared | MODwild, MODconst):
758: cto = t;
759: goto L7;
760:
761: case X(MODshared | MODwild, MODimmutable):
762: ito = t;
763: goto L7;
764:
765: case X(MODshared | MODwild, MODshared):
766: sto = t;
767: goto L7;
768:
769: case X(MODshared | MODwild, MODshared | MODconst):
770: scto = t;
771: goto L7;
772:
773: case X(MODshared | MODwild, MODwild):
774: wto = t;
775: L7:
776: t->swto = this;
777: break;
778:
779:
780: default:
781: assert(0);
782: }
783: #undef X
784:
785: check();
786: t->check();
787: //printf("fixTo: %s, %s\n", toChars(), t->toChars());
788: }
789:
790: /***************************
791: * Look for bugs in constructing types.
792: */
793:
794: void Type::check()
795: {
796: switch (mod)
797: {
798: case 0:
799: if (cto) assert(cto->mod == MODconst);
800: if (ito) assert(ito->mod == MODimmutable);
801: if (sto) assert(sto->mod == MODshared);
802: if (scto) assert(scto->mod == (MODshared | MODconst));
803: if (wto) assert(wto->mod == MODwild);
804: if (swto) assert(swto->mod == (MODshared | MODwild));
805: break;
806:
807: case MODconst:
808: if (cto) assert(cto->mod == 0);
809: if (ito) assert(ito->mod == MODimmutable);
810: if (sto) assert(sto->mod == MODshared);
811: if (scto) assert(scto->mod == (MODshared | MODconst));
812: if (wto) assert(wto->mod == MODwild);
813: if (swto) assert(swto->mod == (MODshared | MODwild));
814: break;
815:
816: case MODimmutable:
817: if (cto) assert(cto->mod == MODconst);
818: if (ito) assert(ito->mod == 0);
819: if (sto) assert(sto->mod == MODshared);
820: if (scto) assert(scto->mod == (MODshared | MODconst));
821: if (wto) assert(wto->mod == MODwild);
822: if (swto) assert(swto->mod == (MODshared | MODwild));
823: break;
824:
825: case MODshared:
826: if (cto) assert(cto->mod == MODconst);
827: if (ito) assert(ito->mod == MODimmutable);
828: if (sto) assert(sto->mod == 0);
829: if (scto) assert(scto->mod == (MODshared | MODconst));
830: if (wto) assert(wto->mod == MODwild);
831: if (swto) assert(swto->mod == (MODshared | MODwild));
832: break;
833:
834: case MODshared | MODconst:
835: if (cto) assert(cto->mod == MODconst);
836: if (ito) assert(ito->mod == MODimmutable);
837: if (sto) assert(sto->mod == MODshared);
838: if (scto) assert(scto->mod == 0);
839: if (wto) assert(wto->mod == MODwild);
840: if (swto) assert(swto->mod == (MODshared | MODwild));
841: break;
842:
843: case MODwild:
844: if (cto) assert(cto->mod == MODconst);
845: if (ito) assert(ito->mod == MODimmutable);
846: if (sto) assert(sto->mod == MODshared);
847: if (scto) assert(scto->mod == (MODshared | MODconst));
848: if (wto) assert(wto->mod == 0);
849: if (swto) assert(swto->mod == (MODshared | MODwild));
850: break;
851:
852: case MODshared | MODwild:
853: if (cto) assert(cto->mod == MODconst);
854: if (ito) assert(ito->mod == MODimmutable);
855: if (sto) assert(sto->mod == MODshared);
856: if (scto) assert(scto->mod == (MODshared | MODconst));
857: if (wto) assert(wto->mod == MODwild);
858: if (swto) assert(swto->mod == 0);
859: break;
860:
861: default:
862: assert(0);
863: }
864:
865: Type *tn = nextOf();
866: if (tn && ty != Tfunction && ty != Tdelegate)
867: { // Verify transitivity
868: switch (mod)
869: {
870: case 0:
871: break;
872:
873: case MODconst:
874: assert(tn->mod & MODimmutable || tn->mod & MODconst);
875: break;
876:
877: case MODimmutable:
878: assert(tn->mod == MODimmutable);
879: break;
880:
881: case MODshared:
882: assert(tn->mod & MODimmutable || tn->mod & MODshared);
883: break;
884:
885: case MODshared | MODconst:
886: assert(tn->mod & MODimmutable || tn->mod & (MODshared | MODconst));
887: break;
888:
889: case MODwild:
890: assert(tn->mod);
891: break;
892:
893: case MODshared | MODwild:
894: assert(tn->mod == MODimmutable || tn->mod == (MODshared | MODconst) || tn->mod == (MODshared | MODwild));
895: break;
896:
897: default:
898: assert(0);
899: }
900: tn->check();
901: }
902: }
903:
904: Type *Type::makeConst()
905: {
906: //printf("Type::makeConst() %p, %s\n", this, toChars());
907: if (cto)
908: return cto;
909: unsigned sz = sizeTy[ty];
910: Type *t = (Type *)mem.malloc(sz);
911: memcpy(t, this, sz);
912: t->mod = MODconst;
913: t->deco = NULL;
914: t->arrayof = NULL;
915: t->pto = NULL;
916: t->rto = NULL;
917: t->cto = NULL;
918: t->ito = NULL;
919: t->sto = NULL;
920: t->scto = NULL;
921: t->wto = NULL;
922: t->swto = NULL;
923: t->vtinfo = NULL;
924: //printf("-Type::makeConst() %p, %s\n", t, toChars());
925: return t;
926: }
927:
928: Type *Type::makeInvariant()
929: {
930: if (ito)
931: return ito;
932: unsigned sz = sizeTy[ty];
933: Type *t = (Type *)mem.malloc(sz);
934: memcpy(t, this, sz);
935: t->mod = MODimmutable;
936: t->deco = NULL;
937: t->arrayof = NULL;
938: t->pto = NULL;
939: t->rto = NULL;
940: t->cto = NULL;
941: t->ito = NULL;
942: t->sto = NULL;
943: t->scto = NULL;
944: t->wto = NULL;
945: t->swto = NULL;
946: t->vtinfo = NULL;
947: return t;
948: }
949:
950: Type *Type::makeShared()
951: {
952: if (sto)
953: return sto;
954: unsigned sz = sizeTy[ty];
955: Type *t = (Type *)mem.malloc(sz);
956: memcpy(t, this, sz);
957: t->mod = MODshared;
958: t->deco = NULL;
959: t->arrayof = NULL;
960: t->pto = NULL;
961: t->rto = NULL;
962: t->cto = NULL;
963: t->ito = NULL;
964: t->sto = NULL;
965: t->scto = NULL;
966: t->wto = NULL;
967: t->swto = NULL;
968: t->vtinfo = NULL;
969: return t;
970: }
971:
972: Type *Type::makeSharedConst()
973: {
974: if (scto)
975: return scto;
976: unsigned sz = sizeTy[ty];
977: Type *t = (Type *)mem.malloc(sz);
978: memcpy(t, this, sz);
979: t->mod = MODshared | MODconst;
980: t->deco = NULL;
981: t->arrayof = NULL;
982: t->pto = NULL;
983: t->rto = NULL;
984: t->cto = NULL;
985: t->ito = NULL;
986: t->sto = NULL;
987: t->scto = NULL;
988: t->wto = NULL;
989: t->swto = NULL;
990: t->vtinfo = NULL;
991: return t;
992: }
993:
994: Type *Type::makeWild()
995: {
996: if (wto)
997: return wto;
998: unsigned sz = sizeTy[ty];
999: Type *t = (Type *)mem.malloc(sz);
1000: memcpy(t, this, sz);
1001: t->mod = MODwild;
1002: t->deco = NULL;
1003: t->arrayof = NULL;
1004: t->pto = NULL;
1005: t->rto = NULL;
1006: t->cto = NULL;
1007: t->ito = NULL;
1008: t->sto = NULL;
1009: t->scto = NULL;
1010: t->wto = NULL;
1011: t->swto = NULL;
1012: t->vtinfo = NULL;
1013: return t;
1014: }
1015:
1016: Type *Type::makeSharedWild()
1017: {
1018: if (swto)
1019: return swto;
1020: unsigned sz = sizeTy[ty];
1021: Type *t = (Type *)mem.malloc(sz);
1022: memcpy(t, this, sz);
1023: t->mod = MODshared | MODwild;
1024: t->deco = NULL;
1025: t->arrayof = NULL;
1026: t->pto = NULL;
1027: t->rto = NULL;
1028: t->cto = NULL;
1029: t->ito = NULL;
1030: t->sto = NULL;
1031: t->scto = NULL;
1032: t->wto = NULL;
1033: t->swto = NULL;
1034: t->vtinfo = NULL;
1035: return t;
1036: }
1037:
1038: Type *Type::makeMutable()
1039: {
1040: unsigned sz = sizeTy[ty];
1041: Type *t = (Type *)mem.malloc(sz);
1042: memcpy(t, this, sz);
1043: t->mod = mod & MODshared;
1044: t->deco = NULL;
1045: t->arrayof = NULL;
1046: t->pto = NULL;
1047: t->rto = NULL;
1048: t->cto = NULL;
1049: t->ito = NULL;
1050: t->sto = NULL;
1051: t->scto = NULL;
1052: t->wto = NULL;
1053: t->swto = NULL;
1054: t->vtinfo = NULL;
1055: return t;
1056: }
1057:
1058: /************************************
1059: * Apply MODxxxx bits to existing type.
1060: */
1061:
1062: Type *Type::castMod(unsigned mod)
1063: { Type *t;
1064:
1065: switch (mod)
1066: {
1067: case 0:
1068: t = unSharedOf()->mutableOf();
1069: break;
1070:
1071: case MODconst:
1072: t = unSharedOf()->constOf();
1073: break;
1074:
1075: case MODimmutable:
1076: t = invariantOf();
1077: break;
1078:
1079: case MODshared:
1080: t = mutableOf()->sharedOf();
1081: break;
1082:
1083: case MODshared | MODconst:
1084: t = sharedConstOf();
1085: break;
1086:
1087: case MODwild:
1088: t = unSharedOf()->wildOf();
1089: break;
1090:
1091: case MODshared | MODwild:
1092: t = sharedWildOf();
1093: break;
1094:
1095: default:
1096: assert(0);
1097: }
1098: return t;
1099: }
1100:
1101: /************************************
1102: * Add MODxxxx bits to existing type.
1103: * We're adding, not replacing, so adding const to
1104: * a shared type => "shared const"
1105: */
1106:
1107: Type *Type::addMod(unsigned mod)
1108: { Type *t = this;
1109:
1110: /* Add anything to immutable, and it remains immutable
1111: */
1112: if (!t->isImmutable())
1113: {
1114: //printf("addMod(%x) %s\n", mod, toChars());
1115: switch (mod)
1116: {
1117: case 0:
1118: break;
1119:
1120: case MODconst:
1121: if (isShared())
1122: t = sharedConstOf();
1123: else
1124: t = constOf();
1125: break;
1126:
1127: case MODimmutable:
1128: t = invariantOf();
1129: break;
1130:
1131: case MODshared:
1132: if (isConst())
1133: t = sharedConstOf();
1134: else if (isWild())
1135: t = sharedWildOf();
1136: else
1137: t = sharedOf();
1138: break;
1139:
1140: case MODshared | MODconst:
1141: t = sharedConstOf();
1142: break;
1143:
1144: case MODwild:
1145: if (isConst())
1146: ;
1147: else if (isShared())
1148: t = sharedWildOf();
1149: else
1150: t = wildOf();
1151: break;
1152:
1153: case MODshared | MODwild:
1154: t = sharedWildOf();
1155: break;
1156:
1157: default:
1158: assert(0);
1159: }
1160: }
1161: return t;
1162: }
1163:
1164: /************************************
1165: * Add storage class modifiers to type.
1166: */
1167:
1168: Type *Type::addStorageClass(StorageClass stc)
1169: {
1170: /* Just translate to MOD bits and let addMod() do the work
1171: */
1172: unsigned mod = 0;
1173:
1174: if (stc & STCimmutable)
1175: mod = MODimmutable;
1176: else
1177: { if (stc & (STCconst | STCin))
1178: mod = MODconst;
1179: else if (stc & STCwild) // const takes precedence over wild
1180: mod |= MODwild;
1181: if (stc & STCshared)
1182: mod |= MODshared;
1183: }
1184: return addMod(mod);
1185: }
1186:
1187: /**************************
1188: * Return type with the top level of it being mutable.
1189: */
1190: Type *Type::toHeadMutable()
1191: {
1192: if (!mod)
1193: return this;
1194: return mutableOf();
1195: }
1196:
1197: Type *Type::pointerTo()
1198: {
1199: if (ty == Terror)
1200: return this;
1201: if (!pto)
1202: { Type *t;
1203:
1204: t = new TypePointer(this);
1205: pto = t->merge();
1206: }
1207: return pto;
1208: }
1209:
1210: Type *Type::referenceTo()
1211: {
1212: if (ty == Terror)
1213: return this;
1214: if (!rto)
1215: { Type *t;
1216:
1217: t = new TypeReference(this);
1218: rto = t->merge();
1219: }
1220: return rto;
1221: }
1222:
1223: Type *Type::arrayOf()
1224: {
1225: if (ty == Terror)
1226: return this;
1227: if (!arrayof)
1228: { Type *t;
1229:
1230: t = new TypeDArray(this);
1231: arrayof = t->merge();
1232: }
1233: return arrayof;
1234: }
1235:
1236: Dsymbol *Type::toDsymbol(Scope *sc)
1237: {
1238: return NULL;
1239: }
1240:
1241: /*******************************
1242: * If this is a shell around another type,
1243: * get that other type.
1244: */
1245:
1246: Type *Type::toBasetype()
1247: {
1248: return this;
1249: }
1250:
1251: /***************************
1252: * Return !=0 if modfrom can be implicitly converted to modto
1253: */
1254: int MODimplicitConv(unsigned char modfrom, unsigned char modto)
1255: {
1256: if (modfrom == modto)
1257: return 1;
1258:
1259: //printf("MODimplicitConv(from = %x, to = %x)\n", modfrom, modto);
1260: #define X(m, n) (((m) << 4) | (n))
1261: switch (X(modfrom, modto))
1262: {
1263: case X(0, MODconst):
1264: case X(MODimmutable, MODconst):
1265: case X(MODwild, MODconst):
1266: case X(MODimmutable, MODconst | MODshared):
1267: case X(MODshared, MODconst | MODshared):
1268: case X(MODwild | MODshared, MODconst | MODshared):
1269: return 1;
1270:
1271: default:
1272: return 0;
1273: }
1274: #undef X
1275: }
1276:
1277: /***************************
1278: * Merge mod bits to form common mod.
1279: */
1280: int MODmerge(unsigned char mod1, unsigned char mod2)
1281: {
1282: if (mod1 == mod2)
1283: return mod1;
1284:
1285: //printf("MODmerge(1 = %x, 2 = %x)\n", modfrom, modto);
1286: #define X(m, n) (((m) << 4) | (n))
1287: // cases are commutative
1288: #define Y(m, n) X(m, n): case X(n, m)
1289: switch (X(mod1, mod2))
1290: {
1291: #if 0
1292: case X(0, 0):
1293: case X(MODconst, MODconst):
1294: case X(MODimmutable, MODimmutable):
1295: case X(MODshared, MODshared):
1296: case X(MODshared | MODconst, MODshared | MODconst):
1297: case X(MODwild, MODwild):
1298: case X(MODshared | MODwild, MODshared | MODwild):
1299: #endif
1300:
1301: case Y(0, MODconst):
1302: case Y(0, MODimmutable):
1303: case Y(MODconst, MODimmutable):
1304: case Y(MODconst, MODwild):
1305: case Y(0, MODwild):
1306: case Y(MODimmutable, MODwild):
1307: return MODconst;
1308:
1309: case Y(0, MODshared):
1310: return MODshared;
1311:
1312: case Y(0, MODshared | MODconst):
1313: case Y(MODconst, MODshared):
1314: case Y(MODconst, MODshared | MODconst):
1315: case Y(MODimmutable, MODshared):
1316: case Y(MODimmutable, MODshared | MODconst):
1317: case Y(MODshared, MODshared | MODconst):
1318: case Y(0, MODshared | MODwild):
1319: case Y(MODconst, MODshared | MODwild):
1320: case Y(MODimmutable, MODshared | MODwild):
1321: case Y(MODshared, MODwild):
1322: case Y(MODshared, MODshared | MODwild):
1323: case Y(MODshared | MODconst, MODwild):
1324: case Y(MODshared | MODconst, MODshared | MODwild):
1325: return MODshared | MODconst;
1326:
1327: case Y(MODwild, MODshared | MODwild):
1328: return MODshared | MODwild;
1329:
1330: default:
1331: assert(0);
1332: }
1333: #undef Y
1334: #undef X
1335: assert(0);
1336: return 0;
1337: }
1338:
1339: /*********************************
1340: * Mangling for mod.
1341: */
1342: void MODtoDecoBuffer(OutBuffer *buf, unsigned char mod)
1343: {
1344: switch (mod)
1345: { case 0:
1346: break;
1347: case MODconst:
1348: buf->writeByte('x');
1349: break;
1350: case MODimmutable:
1351: buf->writeByte('y');
1352: break;
1353: case MODshared:
1354: buf->writeByte('O');
1355: break;
1356: case MODshared | MODconst:
1357: buf->writestring("Ox");
1358: break;
1359: case MODwild:
1360: buf->writestring("Ng");
1361: break;
1362: case MODshared | MODwild:
1363: buf->writestring("ONg");
1364: break;
1365: default:
1366: assert(0);
1367: }
1368: }
1369:
1370: /*********************************
1371: * Name for mod.
1372: */
1373: void MODtoBuffer(OutBuffer *buf, unsigned char mod)
1374: {
1375: switch (mod)
1376: { case 0:
1377: break;
1378:
1379: case MODimmutable:
1380: buf->writestring(Token::tochars[TOKimmutable]);
1381: break;
1382:
1383: case MODshared:
1384: buf->writestring(Token::tochars[TOKshared]);
1385: break;
1386:
1387: case MODshared | MODconst:
1388: buf->writestring(Token::tochars[TOKshared]);
1389: buf->writeByte(' ');
1390: case MODconst:
1391: buf->writestring(Token::tochars[TOKconst]);
1392: break;
1393:
1394: case MODshared | MODwild:
1395: buf->writestring(Token::tochars[TOKshared]);
1396: buf->writeByte(' ');
1397: case MODwild:
1398: buf->writestring(Token::tochars[TOKwild]);
1399: break;
1400: default:
1401: assert(0);
1402: }
1403: }
1404:
1405: /********************************
1406: * Name mangling.
1407: * Input:
1408: * flag 0x100 do not do const/invariant
1409: */
1410:
1411: void Type::toDecoBuffer(OutBuffer *buf, int flag)
1412: {
1413: if (flag != mod && flag != 0x100)
1414: {
1415: MODtoDecoBuffer(buf, mod);
1416: }
1417: buf->writeByte(mangleChar[ty]);
1418: }
1419:
1420: /********************************
1421: * For pretty-printing a type.
1422: */
1423:
1424: char *Type::toChars()
1425: { OutBuffer *buf;
1426: HdrGenState hgs;
1427:
1428: buf = new OutBuffer();
1429: toCBuffer(buf, NULL, &hgs);
1430: return buf->toChars();
1431: }
1432:
1433: void Type::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
1434: {
1435: toCBuffer2(buf, hgs, 0);
1436: if (ident)
1437: { buf->writeByte(' ');
1438: buf->writestring(ident->toChars());
1439: }
1440: }
1441:
1442: void Type::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
1443: {
1444: if (mod != this->mod)
1445: { toCBuffer3(buf, hgs, mod);
1446: return;
1447: }
1448: buf->writestring(toChars());
1449: }
1450:
1451: void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod)
1452: {
1453: if (mod != this->mod)
1454: {
1455: if (this->mod & MODshared)
1456: {
1457: MODtoBuffer(buf, this->mod & MODshared);
1458: buf->writeByte('(');
1459: }
1460: if (this->mod & ~MODshared)
1461: {
1462: MODtoBuffer(buf, this->mod & ~MODshared);
1463: buf->writeByte('(');
1464: toCBuffer2(buf, hgs, this->mod);
1465: buf->writeByte(')');
1466: }
1467: else
1468: toCBuffer2(buf, hgs, this->mod);
1469: if (this->mod & MODshared)
1470: {
1471: buf->writeByte(')');
1472: }
1473: }
1474: }
1475:
1476: void Type::modToBuffer(OutBuffer *buf)
1477: {
1478: if (mod)
1479: {
1480: buf->writeByte(' ');
1481: MODtoBuffer(buf, mod);
1482: }
1483: }
1484:
1485: /************************************
1486: */
1487:
1488: Type *Type::merge()
1489: { Type *t;
1490:
1491: //printf("merge(%s)\n", toChars());
1492: t = this;
1493: assert(t);
1494: if (!deco)
1495: {
1496: OutBuffer buf;
1497: StringValue *sv;
1498:
1499: //if (next)
1500: //next = next->merge();
1501: toDecoBuffer(&buf);
1502: sv = stringtable.update((char *)buf.data, buf.offset);
1503: if (sv->ptrvalue)
1504: { t = (Type *) sv->ptrvalue;
1505: #ifdef DEBUG
1506: if (!t->deco)
1507: printf("t = %s\n", t->toChars());
1508: #endif
1509: assert(t->deco);
1510: //printf("old value, deco = '%s' %p\n", t->deco, t->deco);
1511: }
1512: else
1513: {
1514: sv->ptrvalue = this;
1515: deco = sv->lstring.string;
1516: //printf("new value, deco = '%s' %p\n", t->deco, t->deco);
1517: }
1518: }
1519: return t;
1520: }
1521:
1522: /*************************************
1523: * This version does a merge even if the deco is already computed.
1524: * Necessary for types that have a deco, but are not merged.
1525: */
1526: Type *Type::merge2()
1527: {
1528: //printf("merge2(%s)\n", toChars());
1529: Type *t = this;
1530: assert(t);
1531: if (!t->deco)
1532: return t->merge();
1533:
1534: StringValue *sv = stringtable.lookup((char *)t->deco, strlen(t->deco));
1535: if (sv && sv->ptrvalue)
1536: { t = (Type *) sv->ptrvalue;
1537: assert(t->deco);
1538: }
1539: else
1540: assert(0);
1541: return t;
1542: }
1543:
1544: int Type::isintegral()
1545: {
1546: return FALSE;
1547: }
1548:
1549: int Type::isfloating()
1550: {
1551: return FALSE;
1552: }
1553:
1554: int Type::isreal()
1555: {
1556: return FALSE;
1557: }
1558:
1559: int Type::isimaginary()
1560: {
1561: return FALSE;
1562: }
1563:
1564: int Type::iscomplex()
1565: {
1566: return FALSE;
1567: }
1568:
1569: int Type::isscalar()
1570: {
1571: return FALSE;
1572: }
1573:
1574: int Type::isunsigned()
1575: {
1576: return FALSE;
1577: }
1578:
1579: ClassDeclaration *Type::isClassHandle()
1580: {
1581: return NULL;
1582: }
1583:
1584: int Type::isscope()
1585: {
1586: return FALSE;
1587: }
1588:
1589: int Type::isString()
1590: {
1591: return FALSE;
1592: }
1593:
1594: /**************************
1595: * Given:
1596: * T a, b;
1597: * Can we assign:
1598: * a = b;
1599: * ?
1600: */
1601: int Type::isAssignable()
1602: {
1603: return TRUE;
1604: }
1605:
1606: int Type::checkBoolean()
1607: {
1608: return isscalar();
1609: }
1610:
1611: /********************************
1612: * TRUE if when type goes out of scope, it needs a destructor applied.
1613: * Only applies to value types, not ref types.
1614: */
1615: int Type::needsDestruction()
1616: {
1617: return FALSE;
1618: }
1619:
1620: /*********************************
1621: * Check type to see if it is based on a deprecated symbol.
1622: */
1623:
1624: void Type::checkDeprecated(Loc loc, Scope *sc)
1625: {
1626: Dsymbol *s = toDsymbol(sc);
1627:
1628: if (s)
1629: s->checkDeprecated(loc, sc);
1630: }
1631:
1632:
1633: Expression *Type::defaultInit(Loc loc)
1634: {
1635: #if LOGDEFAULTINIT
1636: printf("Type::defaultInit() '%s'\n", toChars());
1637: #endif
1638: return NULL;
1639: }
1640:
1641: /***************************************
1642: * Use when we prefer the default initializer to be a literal,
1643: * rather than a global immutable variable.
1644: */
1645: Expression *Type::defaultInitLiteral(Loc loc)
1646: {
1647: #if LOGDEFAULTINIT
1648: printf("Type::defaultInitLiteral() '%s'\n", toChars());
1649: #endif
1650: return defaultInit(loc);
1651: }
1652:
1653: int Type::isZeroInit(Loc loc)
1654: {
1655: return 0; // assume not
1656: }
1657:
1658: int Type::isBaseOf(Type *t, int *poffset)
1659: {
1660: return 0; // assume not
1661: }
1662:
1663: /********************************
1664: * Determine if 'this' can be implicitly converted
1665: * to type 'to'.
1666: * Returns:
1667: * MATCHnomatch, MATCHconvert, MATCHconst, MATCHexact
1668: */
1669:
1670: MATCH Type::implicitConvTo(Type *to)
1671: {
1672: //printf("Type::implicitConvTo(this=%p, to=%p)\n", this, to);
1673: //printf("from: %s\n", toChars());
1674: //printf("to : %s\n", to->toChars());
1675: if (this == to)
1676: return MATCHexact;
1677: return MATCHnomatch;
1678: }
1679:
1680: Expression *Type::getProperty(Loc loc, Identifier *ident)
1681: { Expression *e;
1682:
1683: #if LOGDOTEXP
1684: printf("Type::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars());
1685: #endif
1686: if (ident == Id::__sizeof)
1687: {
1688: e = new IntegerExp(loc, size(loc), Type::tsize_t);
1689: }
1690: else if (ident == Id::size)
1691: {
1692: error(loc, ".size property should be replaced with .sizeof");
1693: e = new ErrorExp();
1694: }
1695: else if (ident == Id::__xalignof)
1696: {
1697: e = new IntegerExp(loc, alignsize(), Type::tsize_t);
1698: }
1699: else if (ident == Id::typeinfo)
1700: {
1701: if (!global.params.useDeprecated)
1702: error(loc, ".typeinfo deprecated, use typeid(type)");
1703: e = getTypeInfo(NULL);
1704: }
1705: else if (ident == Id::init)
1706: {
1707: if (ty == Tvoid)
1708: error(loc, "void does not have an initializer");
1709: if (ty == Tfunction)
1710: error(loc, "function does not have an initializer");
1711: e = defaultInitLiteral(loc);
1712: }
1713: else if (ident == Id::mangleof)
1714: { const char *s;
1715: if (!deco)
1716: { s = toChars();
1717: error(loc, "forward reference of type %s.mangleof", s);
1718: }
1719: else
1720: s = deco;
1721: e = new StringExp(loc, (char *)s, strlen(s), 'c');
1722: Scope sc;
1723: e = e->semantic(&sc);
1724: }
1725: else if (ident == Id::stringof)
1726: { char *s = toChars();
1727: e = new StringExp(loc, s, strlen(s), 'c');
1728: Scope sc;
1729: e = e->semantic(&sc);
1730: }
1731: else
1732: {
1733: Dsymbol *s = NULL;
1734: if (ty == Tstruct || ty == Tclass || ty == Tenum || ty == Ttypedef)
1735: s = toDsymbol(NULL);
1736: if (s)
1737: s = s->search_correct(ident);
1738: if (this != Type::terror)
1739: {
1740: if (s)
1741: error(loc, "no property '%s' for type '%s', did you mean '%s'?", ident->toChars(), toChars(), s->toChars());
1742: else
1743: error(loc, "no property '%s' for type '%s'", ident->toChars(), toChars());
1744: }
1745: e = new ErrorExp();
1746: }
1747: return e;
1748: }
1749:
1750: Expression *Type::dotExp(Scope *sc, Expression *e, Identifier *ident)
1751: { VarDeclaration *v = NULL;
1752:
1753: #if LOGDOTEXP
1754: printf("Type::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
1755: #endif
1756: if (e->op == TOKdotvar)
1757: {
1758: DotVarExp *dv = (DotVarExp *)e;
1759: v = dv->var->isVarDeclaration();
1760: }
1761: else if (e->op == TOKvar)
1762: {
1763: VarExp *ve = (VarExp *)e;
1764: v = ve->var->isVarDeclaration();
1765: }
1766: if (v)
1767: {
1768: if (ident == Id::offset)
1769: {
1770: if (!global.params.useDeprecated)
1771: error(e->loc, ".offset deprecated, use .offsetof");
1772: goto Loffset;
1773: }
1774: else if (ident == Id::offsetof)
1775: {
1776: Loffset:
1777: if (v->storage_class & STCfield)
1778: {
1779: e = new IntegerExp(e->loc, v->offset, Type::tsize_t);
1780: return e;
1781: }
1782: }
1783: else if (ident == Id::init)
1784: {
1785: #if 0
1786: if (v->init)
1787: {
1788: if (v->init->isVoidInitializer())
1789: error(e->loc, "%s.init is void", v->toChars());
1790: else
1791: { Loc loc = e->loc;
1792: e = v->init->toExpression();
1793: if (e->op == TOKassign || e->op == TOKconstruct || e->op == TOKblit)
1794: {
1795: e = ((AssignExp *)e)->e2;
1796:
1797: /* Take care of case where we used a 0
1798: * to initialize the struct.
1799: */
1800: if (e->type == Type::tint32 &&
1801: e->isBool(0) &&
1802: v->type->toBasetype()->ty == Tstruct)
1803: {
1804: e = v->type->defaultInit(e->loc);
1805: }
1806: }
1807: e = e->optimize(WANTvalue | WANTinterpret);
1808: // if (!e->isConst())
1809: // error(loc, ".init cannot be evaluated at compile time");
1810: }
1811: goto Lreturn;
1812: }
1813: #endif
1814: e = defaultInitLiteral(e->loc);
1815: goto Lreturn;
1816: }
1817: }
1818: if (ident == Id::typeinfo)
1819: {
1820: if (!global.params.useDeprecated)
1821: error(e->loc, ".typeinfo deprecated, use typeid(type)");
1822: e = getTypeInfo(sc);
1823: }
1824: else if (ident == Id::stringof)
1825: { /* Bugzilla 3796: this should demangle e->type->deco rather than
1826: * pretty-printing the type.
1827: */
1828: char *s = e->toChars();
1829: e = new StringExp(e->loc, s, strlen(s), 'c');
1830: }
1831: else
1832: e = getProperty(e->loc, ident);
1833:
1834: Lreturn:
1835: e = e->semantic(sc);
1836: return e;
1837: }
1838:
1839: /***************************************
1840: * Figures out what to do with an undefined member reference
1841: * for classes and structs.
1842: */
1843: Expression *Type::noMember(Scope *sc, Expression *e, Identifier *ident)
1844: {
1845: assert(ty == Tstruct || ty == Tclass);
1846: AggregateDeclaration *sym = toDsymbol(sc)->isAggregateDeclaration();
1847: assert(sym);
1848:
1849: if (ident != Id::__sizeof &&
1850: ident != Id::__xalignof &&
1851: ident != Id::init &&
1852: ident != Id::mangleof &&
1853: ident != Id::stringof &&
1854: ident != Id::offsetof)
1855: {
1856: /* See if we should forward to the alias this.
1857: */
1858: if (sym->aliasthis)
1859: { /* Rewrite e.ident as:
1860: * e.aliasthis.ident
1861: */
1862: e = new DotIdExp(e->loc, e, sym->aliasthis->ident);
1863: e = new DotIdExp(e->loc, e, ident);
1864: return e->semantic(sc);
1865: }
1866:
1867: /* Look for overloaded opDot() to see if we should forward request
1868: * to it.
1869: */
1870: Dsymbol *fd = search_function(sym, Id::opDot);
1871: if (fd)
1872: { /* Rewrite e.ident as:
1873: * e.opDot().ident
1874: */
1875: e = build_overload(e->loc, sc, e, NULL, fd);
1876: e = new DotIdExp(e->loc, e, ident);
1877: return e->semantic(sc);
1878: }
1879:
1880: /* Look for overloaded opDispatch to see if we should forward request
1881: * to it.
1882: */
1883: fd = search_function(sym, Id::opDispatch);
1884: if (fd)
1885: {
1886: /* Rewrite e.ident as:
1887: * e.opDispatch!("ident")
1888: */
1889: TemplateDeclaration *td = fd->isTemplateDeclaration();
1890: if (!td)
1891: {
1892: fd->error("must be a template opDispatch(string s), not a %s", fd->kind());
1893: return new ErrorExp();
1894: }
1895: StringExp *se = new StringExp(e->loc, ident->toChars());
1896: Objects *tiargs = new Objects();
1897: tiargs->push(se);
1898: e = new DotTemplateInstanceExp(e->loc, e, Id::opDispatch, tiargs);
1899: ((DotTemplateInstanceExp *)e)->ti->tempdecl = td;
1900: return e;
1901: //return e->semantic(sc);
1902: }
1903: }
1904:
1905: return Type::dotExp(sc, e, ident);
1906: }
1907:
1908: unsigned Type::memalign(unsigned salign)
1909: {
1910: return salign;
1911: }
1912:
1913: void Type::error(Loc loc, const char *format, ...)
1914: {
1915: va_list ap;
1916: va_start(ap, format);
1917: ::verror(loc, format, ap);
1918: va_end( ap );
1919: }
1920:
1921: void Type::warning(Loc loc, const char *format, ...)
1922: {
1923: va_list ap;
1924: va_start(ap, format);
1925: ::vwarning(loc, format, ap);
1926: va_end( ap );
1927: }
1928:
1929: Identifier *Type::getTypeInfoIdent(int internal)
1930: {
1931: // _init_10TypeInfo_%s
1932: OutBuffer buf;
1933: Identifier *id;
1934: char *name;
1935: int len;
1936:
1937: if (internal)
1938: { buf.writeByte(mangleChar[ty]);
1939: if (ty == Tarray)
1940: buf.writeByte(mangleChar[((TypeArray *)this)->next->ty]);
1941: }
1942: else
1943: toDecoBuffer(&buf);
1944: len = buf.offset;
1945: name = (char *)alloca(19 + sizeof(len) * 3 + len + 1);
warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
1946: buf.writeByte(0);
1947: #if TARGET_OSX
1948: // The LINKc will prepend the _
1949: sprintf(name, "D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
1950: #else
1951: sprintf(name, "_D%dTypeInfo_%s6__initZ", 9 + len, buf.data);
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
1952: #endif
1953: if (global.params.isWindows)
1954: name++; // C mangling will add it back in
1955: //printf("name = %s\n", name);
1956: id = Lexer::idPool(name);
1957: return id;
1958: }
1959:
1960: TypeBasic *Type::isTypeBasic()
1961: {
1962: return NULL;
1963: }
1964:
1965:
1966: void Type::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
1967: {
1968: //printf("Type::resolve() %s, %d\n", toChars(), ty);
1969: Type *t = semantic(loc, sc);
1970: *pt = t;
1971: *pe = NULL;
1972: *ps = NULL;
1973: }
1974:
1975: /*******************************
1976: * If one of the subtypes of this type is a TypeIdentifier,
1977: * i.e. it's an unresolved type, return that type.
1978: */
1979:
1980: Type *Type::reliesOnTident()
1981: {
1982: return NULL;
1983: }
1984:
1985: /***************************************
1986: * Return !=0 if the type or any of its subtypes is wild.
1987: */
1988:
1989: int Type::hasWild()
1990: {
1991: return mod & MODwild;
1992: }
1993:
1994: /***************************************
1995: * Return MOD bits matching argument type (targ) to wild parameter type (this).
1996: */
1997:
1998: unsigned Type::wildMatch(Type *targ)
1999: {
2000: return 0;
2001: }
2002:
2003: /********************************
2004: * We've mistakenly parsed this as a type.
2005: * Redo it as an Expression.
2006: * NULL if cannot.
2007: */
2008:
2009: Expression *Type::toExpression()
2010: {
2011: return NULL;
2012: }
2013:
2014: /***************************************
2015: * Return !=0 if type has pointers that need to
2016: * be scanned by the GC during a collection cycle.
2017: */
2018:
2019: int Type::hasPointers()
2020: {
2021: //printf("Type::hasPointers() %s, %d\n", toChars(), ty);
2022: return FALSE;
2023: }
2024:
2025: /*************************************
2026: * If this is a type of something, return that something.
2027: */
2028:
2029: Type *Type::nextOf()
2030: {
2031: return NULL;
2032: }
2033:
2034: /****************************************
2035: * Return the mask that an integral type will
2036: * fit into.
2037: */
2038: uinteger_t Type::sizemask()
2039: { uinteger_t m;
2040:
2041: switch (toBasetype()->ty)
2042: {
2043: case Tbool: m = 1; break;
2044: case Tchar:
2045: case Tint8:
2046: case Tuns8: m = 0xFF; break;
2047: case Twchar:
2048: case Tint16:
2049: case Tuns16: m = 0xFFFFUL; break;
2050: case Tdchar:
2051: case Tint32:
2052: case Tuns32: m = 0xFFFFFFFFUL; break;
2053: case Tint64:
2054: case Tuns64: m = 0xFFFFFFFFFFFFFFFFULL; break;
2055: default:
2056: assert(0);
2057: }
2058: return m;
2059: }
2060:
2061: /* ============================= TypeError =========================== */
2062:
2063: TypeError::TypeError()
2064: : Type(Terror)
2065: {
2066: }
2067:
2068: void TypeError::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
2069: {
2070: buf->writestring("_error_");
2071: }
2072:
2073: d_uns64 TypeError::size(Loc loc) { return 1; }
2074: Expression *TypeError::getProperty(Loc loc, Identifier *ident) { return new ErrorExp(); }
2075: Expression *TypeError::dotExp(Scope *sc, Expression *e, Identifier *ident) { return new ErrorExp(); }
2076: Expression *TypeError::defaultInit(Loc loc) { return new ErrorExp(); }
2077: Expression *TypeError::defaultInitLiteral(Loc loc) { return new ErrorExp(); }
2078:
2079: /* ============================= TypeNext =========================== */
2080:
2081: TypeNext::TypeNext(TY ty, Type *next)
2082: : Type(ty)
2083: {
2084: this->next = next;
2085: }
2086:
2087: void TypeNext::toDecoBuffer(OutBuffer *buf, int flag)
2088: {
2089: Type::toDecoBuffer(buf, flag);
2090: assert(next != this);
2091: //printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty);
2092: next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod);
2093: }
2094:
2095: void TypeNext::checkDeprecated(Loc loc, Scope *sc)
2096: {
2097: Type::checkDeprecated(loc, sc);
2098: if (next) // next can be NULL if TypeFunction and auto return type
2099: next->checkDeprecated(loc, sc);
2100: }
2101:
2102:
2103: Type *TypeNext::reliesOnTident()
2104: {
2105: return next->reliesOnTident();
2106: }
2107:
2108: int TypeNext::hasWild()
2109: {
2110: return mod == MODwild || next->hasWild();
2111: }
2112:
2113: /***************************************
2114: * Return MOD bits matching argument type (targ) to wild parameter type (this).
2115: */
2116:
2117: unsigned TypeNext::wildMatch(Type *targ)
2118: { unsigned mod;
2119:
2120: Type *tb = targ->nextOf();
2121: if (!tb)
2122: return 0;
2123: tb = tb->toBasetype();
2124: if (tb->isMutable())
2125: mod = MODmutable;
2126: else if (tb->isConst() || tb->isWild())
2127: return MODconst;
2128: else if (tb->isImmutable())
2129: mod = MODimmutable;
2130: else
2131: assert(0);
2132: mod |= next->wildMatch(tb);
2133: return mod;
2134: }
2135:
2136:
2137: /*******************************
2138: * For TypeFunction, nextOf() can return NULL if the function return
2139: * type is meant to be inferred, and semantic() hasn't yet ben run
2140: * on the function. After semantic(), it must no longer be NULL.
2141: */
2142:
2143: Type *TypeNext::nextOf()
2144: {
2145: return next;
2146: }
2147:
2148: Type *TypeNext::makeConst()
2149: {
2150: //printf("TypeNext::makeConst() %p, %s\n", this, toChars());
2151: if (cto)
2152: { assert(cto->mod == MODconst);
2153: return cto;
2154: }
2155: TypeNext *t = (TypeNext *)Type::makeConst();
2156: if (ty != Tfunction && ty != Tdelegate &&
2157: //(next->deco || next->ty == Tfunction) &&
2158: !next->isImmutable() && !next->isConst())
2159: { if (next->isShared())
2160: t->next = next->sharedConstOf();
2161: else
2162: t->next = next->constOf();
2163: }
2164: if (ty == Taarray)
2165: {
2166: ((TypeAArray *)t)->impl = NULL; // lazily recompute it
2167: }
2168: //printf("TypeNext::makeConst() returns %p, %s\n", t, t->toChars());
2169: return t;
2170: }
2171:
2172: Type *TypeNext::makeInvariant()
2173: {
2174: //printf("TypeNext::makeInvariant() %s\n", toChars());
2175: if (ito)
2176: { assert(ito->isImmutable());
2177: return ito;
2178: }
2179: TypeNext *t = (TypeNext *)Type::makeInvariant();
2180: if (ty != Tfunction && ty != Tdelegate &&
2181: //(next->deco || next->ty == Tfunction) &&
2182: !next->isImmutable())
2183: { t->next = next->invariantOf();
2184: }
2185: if (ty == Taarray)
2186: {
2187: ((TypeAArray *)t)->impl = NULL; // lazily recompute it
2188: }
2189: return t;
2190: }
2191:
2192: Type *TypeNext::makeShared()
2193: {
2194: //printf("TypeNext::makeShared() %s\n", toChars());
2195: if (sto)
2196: { assert(sto->mod == MODshared);
2197: return sto;
2198: }
2199: TypeNext *t = (TypeNext *)Type::makeShared();
2200: if (ty != Tfunction && ty != Tdelegate &&
2201: //(next->deco || next->ty == Tfunction) &&
2202: !next->isImmutable() && !next->isShared())
2203: {
2204: if (next->isConst() || next->isWild())
2205: t->next = next->sharedConstOf();
2206: else
2207: t->next = next->sharedOf();
2208: }
2209: if (ty == Taarray)
2210: {
2211: ((TypeAArray *)t)->impl = NULL; // lazily recompute it
2212: }
2213: //printf("TypeNext::makeShared() returns %p, %s\n", t, t->toChars());
2214: return t;
2215: }
2216:
2217: Type *TypeNext::makeSharedConst()
2218: {
2219: //printf("TypeNext::makeSharedConst() %s\n", toChars());
2220: if (scto)
2221: { assert(scto->mod == (MODshared | MODconst));
2222: return scto;
2223: }
2224: TypeNext *t = (TypeNext *)Type::makeSharedConst();
2225: if (ty != Tfunction && ty != Tdelegate &&
2226: //(next->deco || next->ty == Tfunction) &&
2227: !next->isImmutable() && !next->isSharedConst())
2228: {
2229: t->next = next->sharedConstOf();
2230: }
2231: if (ty == Taarray)
2232: {
2233: ((TypeAArray *)t)->impl = NULL; // lazily recompute it
2234: }
2235: //printf("TypeNext::makeSharedConst() returns %p, %s\n", t, t->toChars());
2236: return t;
2237: }
2238:
2239: Type *TypeNext::makeWild()
2240: {
2241: //printf("TypeNext::makeWild() %s\n", toChars());
2242: if (wto)
2243: { assert(wto->mod == MODwild);
2244: return wto;
2245: }
2246: TypeNext *t = (TypeNext *)Type::makeWild();
2247: if (ty != Tfunction && ty != Tdelegate &&
2248: //(next->deco || next->ty == Tfunction) &&
2249: !next->isImmutable() && !next->isConst() && !next->isWild())
2250: {
2251: if (next->isShared())
2252: t->next = next->sharedWildOf();
2253: else
2254: t->next = next->wildOf();
2255: }
2256: if (ty == Taarray)
2257: {
2258: ((TypeAArray *)t)->impl = NULL; // lazily recompute it
2259: }
2260: //printf("TypeNext::makeWild() returns %p, %s\n", t, t->toChars());
2261: return t;
2262: }
2263:
2264: Type *TypeNext::makeSharedWild()
2265: {
2266: //printf("TypeNext::makeSharedWild() %s\n", toChars());
2267: if (swto)
2268: { assert(swto->isSharedWild());
2269: return swto;
2270: }
2271: TypeNext *t = (TypeNext *)Type::makeSharedWild();
2272: if (ty != Tfunction && ty != Tdelegate &&
2273: //(next->deco || next->ty == Tfunction) &&
2274: !next->isImmutable() && !next->isSharedConst())
2275: {
2276: t->next = next->sharedWildOf();
2277: }
2278: if (ty == Taarray)
2279: {
2280: ((TypeAArray *)t)->impl = NULL; // lazily recompute it
2281: }
2282: //printf("TypeNext::makeSharedWild() returns %p, %s\n", t, t->toChars());
2283: return t;
2284: }
2285:
2286: Type *TypeNext::makeMutable()
2287: {
2288: //printf("TypeNext::makeMutable() %p, %s\n", this, toChars());
2289: TypeNext *t = (TypeNext *)Type::makeMutable();
2290: if ((ty != Tfunction && ty != Tdelegate &&
2291: //(next->deco || next->ty == Tfunction) &&
2292: next->isWild()) || ty == Tsarray)
2293: {
2294: t->next = next->mutableOf();
2295: }
2296: if (ty == Taarray)
2297: {
2298: ((TypeAArray *)t)->impl = NULL; // lazily recompute it
2299: }
2300: //printf("TypeNext::makeMutable() returns %p, %s\n", t, t->toChars());
2301: return t;
2302: }
2303:
2304: MATCH TypeNext::constConv(Type *to)
2305: { MATCH m = Type::constConv(to);
2306:
2307: if (m == MATCHconst &&
2308: next->constConv(((TypeNext *)to)->next) == MATCHnomatch)
2309: m = MATCHnomatch;
2310: return m;
2311: }
2312:
2313:
2314: void TypeNext::transitive()
2315: {
2316: /* Invoke transitivity of type attributes
2317: */
2318: next = next->addMod(mod);
2319: }
2320:
2321: /* ============================= TypeBasic =========================== */
2322:
2323: TypeBasic::TypeBasic(TY ty)
2324: : Type(ty)
2325: { const char *d;
2326: unsigned flags;
2327:
2328: #define TFLAGSintegral 1
2329: #define TFLAGSfloating 2
2330: #define TFLAGSunsigned 4
2331: #define TFLAGSreal 8
2332: #define TFLAGSimaginary 0x10
2333: #define TFLAGScomplex 0x20
2334:
2335: flags = 0;
2336: switch (ty)
2337: {
2338: case Tvoid: d = Token::toChars(TOKvoid);
2339: break;
2340:
2341: case Tint8: d = Token::toChars(TOKint8);
2342: flags |= TFLAGSintegral;
2343: break;
2344:
2345: case Tuns8: d = Token::toChars(TOKuns8);
2346: flags |= TFLAGSintegral | TFLAGSunsigned;
2347: break;
2348:
2349: case Tint16: d = Token::toChars(TOKint16);
2350: flags |= TFLAGSintegral;
2351: break;
2352:
2353: case Tuns16: d = Token::toChars(TOKuns16);
2354: flags |= TFLAGSintegral | TFLAGSunsigned;
2355: break;
2356:
2357: case Tint32: d = Token::toChars(TOKint32);
2358: flags |= TFLAGSintegral;
2359: break;
2360:
2361: case Tuns32: d = Token::toChars(TOKuns32);
2362: flags |= TFLAGSintegral | TFLAGSunsigned;
2363: break;
2364:
2365: case Tfloat32: d = Token::toChars(TOKfloat32);
2366: flags |= TFLAGSfloating | TFLAGSreal;
2367: break;
2368:
2369: case Tint64: d = Token::toChars(TOKint64);
2370: flags |= TFLAGSintegral;
2371: break;
2372:
2373: case Tuns64: d = Token::toChars(TOKuns64);
2374: flags |= TFLAGSintegral | TFLAGSunsigned;
2375: break;
2376:
2377: case Tfloat64: d = Token::toChars(TOKfloat64);
2378: flags |= TFLAGSfloating | TFLAGSreal;
2379: break;
2380:
2381: case Tfloat80: d = Token::toChars(TOKfloat80);
2382: flags |= TFLAGSfloating | TFLAGSreal;
2383: break;
2384:
2385: case Timaginary32: d = Token::toChars(TOKimaginary32);
2386: flags |= TFLAGSfloating | TFLAGSimaginary;
2387: break;
2388:
2389: case Timaginary64: d = Token::toChars(TOKimaginary64);
2390: flags |= TFLAGSfloating | TFLAGSimaginary;
2391: break;
2392:
2393: case Timaginary80: d = Token::toChars(TOKimaginary80);
2394: flags |= TFLAGSfloating | TFLAGSimaginary;
2395: break;
2396:
2397: case Tcomplex32: d = Token::toChars(TOKcomplex32);
2398: flags |= TFLAGSfloating | TFLAGScomplex;
2399: break;
2400:
2401: case Tcomplex64: d = Token::toChars(TOKcomplex64);
2402: flags |= TFLAGSfloating | TFLAGScomplex;
2403: break;
2404:
2405: case Tcomplex80: d = Token::toChars(TOKcomplex80);
2406: flags |= TFLAGSfloating | TFLAGScomplex;
2407: break;
2408:
2409: case Tbool: d = "bool";
2410: flags |= TFLAGSintegral | TFLAGSunsigned;
2411: break;
2412:
2413: case Tascii: d = Token::toChars(TOKchar);
2414: flags |= TFLAGSintegral | TFLAGSunsigned;
2415: break;
2416:
2417: case Twchar: d = Token::toChars(TOKwchar);
2418: flags |= TFLAGSintegral | TFLAGSunsigned;
2419: break;
2420:
2421: case Tdchar: d = Token::toChars(TOKdchar);
2422: flags |= TFLAGSintegral | TFLAGSunsigned;
2423: break;
2424:
2425: default: assert(0);
2426: }
2427: this->dstring = d;
2428: this->flags = flags;
2429: merge();
2430: }
2431:
2432: Type *TypeBasic::syntaxCopy()
2433: {
2434: // No semantic analysis done on basic types, no need to copy
2435: return this;
2436: }
2437:
2438:
2439: char *TypeBasic::toChars()
2440: {
2441: return Type::toChars();
2442: }
2443:
2444: void TypeBasic::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
2445: {
2446: //printf("TypeBasic::toCBuffer2(mod = %d, this->mod = %d)\n", mod, this->mod);
2447: if (mod != this->mod)
2448: { toCBuffer3(buf, hgs, mod);
2449: return;
2450: }
2451: buf->writestring(dstring);
2452: }
2453:
2454: d_uns64 TypeBasic::size(Loc loc)
2455: { unsigned size;
2456:
2457: //printf("TypeBasic::size()\n");
2458: switch (ty)
2459: {
2460: case Tint8:
2461: case Tuns8: size = 1; break;
2462: case Tint16:
2463: case Tuns16: size = 2; break;
2464: case Tint32:
2465: case Tuns32:
2466: case Tfloat32:
2467: case Timaginary32:
2468: size = 4; break;
2469: case Tint64:
2470: case Tuns64:
2471: case Tfloat64:
2472: case Timaginary64:
2473: size = 8; break;
2474: case Tfloat80:
2475: case Timaginary80:
2476: size = REALSIZE; break;
2477: case Tcomplex32:
2478: size = 8; break;
2479: case Tcomplex64:
2480: size = 16; break;
2481: case Tcomplex80:
2482: size = REALSIZE * 2; break;
2483:
2484: case Tvoid:
2485: //size = Type::size(); // error message
2486: size = 1;
2487: break;
2488:
2489: case Tbool: size = 1; break;
2490: case Tascii: size = 1; break;
2491: case Twchar: size = 2; break;
2492: case Tdchar: size = 4; break;
2493:
2494: default:
2495: assert(0);
2496: break;
2497: }
2498: //printf("TypeBasic::size() = %d\n", size);
2499: return size;
2500: }
2501:
2502: unsigned TypeBasic::alignsize()
2503: { unsigned sz;
2504:
2505: switch (ty)
2506: {
2507: case Tfloat80:
2508: case Timaginary80:
2509: case Tcomplex80:
2510: sz = REALALIGNSIZE;
2511: break;
2512:
2513: #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
2514: case Tint64:
2515: case Tuns64:
2516: sz = global.params.is64bit ? 8 : 4;
2517: break;
2518:
2519: case Tfloat64:
2520: case Timaginary64:
2521: sz = global.params.is64bit ? 8 : 4;
2522: break;
2523:
2524: case Tcomplex32:
2525: sz = 4;
2526: break;
2527:
2528: case Tcomplex64:
2529: sz = global.params.is64bit ? 8 : 4;
2530: break;
2531: #endif
2532:
2533: default:
2534: sz = size(0);
warning C4244: '=' : conversion from 'd_uns64' to 'unsigned int', possible loss of data
2535: break;
2536: }
2537: return sz;
2538: }
2539:
2540:
2541: Expression *TypeBasic::getProperty(Loc loc, Identifier *ident)
2542: {
2543: Expression *e;
2544: d_int64 ivalue;
2545: #ifdef IN_GCC
2546: real_t fvalue;
2547: #else
2548: d_float80 fvalue;
2549: #endif
2550:
2551: //printf("TypeBasic::getProperty('%s')\n", ident->toChars());
2552: if (ident == Id::max)
2553: {
2554: switch (ty)
2555: {
2556: case Tint8: ivalue = 0x7F; goto Livalue;
2557: case Tuns8: ivalue = 0xFF; goto Livalue;
2558: case Tint16: ivalue = 0x7FFFUL; goto Livalue;
2559: case Tuns16: ivalue = 0xFFFFUL; goto Livalue;
2560: case Tint32: ivalue = 0x7FFFFFFFUL; goto Livalue;
2561: case Tuns32: ivalue = 0xFFFFFFFFUL; goto Livalue;
2562: case Tint64: ivalue = 0x7FFFFFFFFFFFFFFFLL; goto Livalue;
2563: case Tuns64: ivalue = 0xFFFFFFFFFFFFFFFFULL; goto Livalue;
2564: case Tbool: ivalue = 1; goto Livalue;
2565: case Tchar: ivalue = 0xFF; goto Livalue;
2566: case Twchar: ivalue = 0xFFFFUL; goto Livalue;
2567: case Tdchar: ivalue = 0x10FFFFUL; goto Livalue;
2568:
2569: case Tcomplex32:
2570: case Timaginary32:
2571: case Tfloat32: fvalue = FLT_MAX; goto Lfvalue;
2572: case Tcomplex64:
2573: case Timaginary64:
2574: case Tfloat64: fvalue = DBL_MAX; goto Lfvalue;
2575: case Tcomplex80:
2576: case Timaginary80:
2577: case Tfloat80: fvalue = Port::ldbl_max; goto Lfvalue;
2578: }
2579: }
2580: else if (ident == Id::min)
2581: {
2582: switch (ty)
2583: {
2584: case Tint8: ivalue = -128; goto Livalue;
2585: case Tuns8: ivalue = 0; goto Livalue;
2586: case Tint16: ivalue = -32768; goto Livalue;
2587: case Tuns16: ivalue = 0; goto Livalue;
2588: case Tint32: ivalue = -2147483647L - 1; goto Livalue;
2589: case Tuns32: ivalue = 0; goto Livalue;
2590: case Tint64: ivalue = (-9223372036854775807LL-1LL); goto Livalue;
2591: case Tuns64: ivalue = 0; goto Livalue;
2592: case Tbool: ivalue = 0; goto Livalue;
2593: case Tchar: ivalue = 0; goto Livalue;
2594: case Twchar: ivalue = 0; goto Livalue;
2595: case Tdchar: ivalue = 0; goto Livalue;
2596:
2597: case Tcomplex32:
2598: case Timaginary32:
2599: case Tfloat32:
2600: case Tcomplex64:
2601: case Timaginary64:
2602: case Tfloat64:
2603: case Tcomplex80:
2604: case Timaginary80:
2605: case Tfloat80:
2606: // For backwards compatibility - eventually, deprecate
2607: goto Lmin_normal;
2608: }
2609: }
2610: else if (ident == Id::min_normal)
2611: {
2612: Lmin_normal:
2613: switch (ty)
2614: {
2615: case Tcomplex32:
2616: case Timaginary32:
2617: case Tfloat32: fvalue = FLT_MIN; goto Lfvalue;
2618: case Tcomplex64:
2619: case Timaginary64:
2620: case Tfloat64: fvalue = DBL_MIN; goto Lfvalue;
2621: case Tcomplex80:
2622: case Timaginary80:
2623: case Tfloat80: fvalue = LDBL_MIN; goto Lfvalue;
2624: }
2625: }
2626: else if (ident == Id::nan)
2627: {
2628: switch (ty)
2629: {
2630: case Tcomplex32:
2631: case Tcomplex64:
2632: case Tcomplex80:
2633: case Timaginary32:
2634: case Timaginary64:
2635: case Timaginary80:
2636: case Tfloat32:
2637: case Tfloat64:
2638: case Tfloat80:
2639: {
2640: fvalue = Port::nan;
2641: goto Lfvalue;
2642: }
2643: }
2644: }
2645: else if (ident == Id::infinity)
2646: {
2647: switch (ty)
2648: {
2649: case Tcomplex32:
2650: case Tcomplex64:
2651: case Tcomplex80:
2652: case Timaginary32:
2653: case Timaginary64:
2654: case Timaginary80:
2655: case Tfloat32:
2656: case Tfloat64:
2657: case Tfloat80:
2658: fvalue = Port::infinity;
2659: goto Lfvalue;
2660: }
2661: }
2662: else if (ident == Id::dig)
2663: {
2664: switch (ty)
2665: {
2666: case Tcomplex32:
2667: case Timaginary32:
2668: case Tfloat32: ivalue = FLT_DIG; goto Lint;
2669: case Tcomplex64:
2670: case Timaginary64:
2671: case Tfloat64: ivalue = DBL_DIG; goto Lint;
2672: case Tcomplex80:
2673: case Timaginary80:
2674: case Tfloat80: ivalue = LDBL_DIG; goto Lint;
2675: }
2676: }
2677: else if (ident == Id::epsilon)
2678: {
2679: switch (ty)
2680: {
2681: case Tcomplex32:
2682: case Timaginary32:
2683: case Tfloat32: fvalue = FLT_EPSILON; goto Lfvalue;
2684: case Tcomplex64:
2685: case Timaginary64:
2686: case Tfloat64: fvalue = DBL_EPSILON; goto Lfvalue;
2687: case Tcomplex80:
2688: case Timaginary80:
2689: case Tfloat80: fvalue = LDBL_EPSILON; goto Lfvalue;
2690: }
2691: }
2692: else if (ident == Id::mant_dig)
2693: {
2694: switch (ty)
2695: {
2696: case Tcomplex32:
2697: case Timaginary32:
2698: case Tfloat32: ivalue = FLT_MANT_DIG; goto Lint;
2699: case Tcomplex64:
2700: case Timaginary64:
2701: case Tfloat64: ivalue = DBL_MANT_DIG; goto Lint;
2702: case Tcomplex80:
2703: case Timaginary80:
2704: case Tfloat80: ivalue = LDBL_MANT_DIG; goto Lint;
2705: }
2706: }
2707: else if (ident == Id::max_10_exp)
2708: {
2709: switch (ty)
2710: {
2711: case Tcomplex32:
2712: case Timaginary32:
2713: case Tfloat32: ivalue = FLT_MAX_10_EXP; goto Lint;
2714: case Tcomplex64:
2715: case Timaginary64:
2716: case Tfloat64: ivalue = DBL_MAX_10_EXP; goto Lint;
2717: case Tcomplex80:
2718: case Timaginary80:
2719: case Tfloat80: ivalue = LDBL_MAX_10_EXP; goto Lint;
2720: }
2721: }
2722: else if (ident == Id::max_exp)
2723: {
2724: switch (ty)
2725: {
2726: case Tcomplex32:
2727: case Timaginary32:
2728: case Tfloat32: ivalue = FLT_MAX_EXP; goto Lint;
2729: case Tcomplex64:
2730: case Timaginary64:
2731: case Tfloat64: ivalue = DBL_MAX_EXP; goto Lint;
2732: case Tcomplex80:
2733: case Timaginary80:
2734: case Tfloat80: ivalue = LDBL_MAX_EXP; goto Lint;
2735: }
2736: }
2737: else if (ident == Id::min_10_exp)
2738: {
2739: switch (ty)
2740: {
2741: case Tcomplex32:
2742: case Timaginary32:
2743: case Tfloat32: ivalue = FLT_MIN_10_EXP; goto Lint;
2744: case Tcomplex64:
2745: case Timaginary64:
2746: case Tfloat64: ivalue = DBL_MIN_10_EXP; goto Lint;
2747: case Tcomplex80:
2748: case Timaginary80:
2749: case Tfloat80: ivalue = LDBL_MIN_10_EXP; goto Lint;
2750: }
2751: }
2752: else if (ident == Id::min_exp)
2753: {
2754: switch (ty)
2755: {
2756: case Tcomplex32:
2757: case Timaginary32:
2758: case Tfloat32: ivalue = FLT_MIN_EXP; goto Lint;
2759: case Tcomplex64:
2760: case Timaginary64:
2761: case Tfloat64: ivalue = DBL_MIN_EXP; goto Lint;
2762: case Tcomplex80:
2763: case Timaginary80:
2764: case Tfloat80: ivalue = LDBL_MIN_EXP; goto Lint;
2765: }
2766: }
2767:
2768: Ldefault:
warning C4102: 'Ldefault' : unreferenced label
2769: return Type::getProperty(loc, ident);
2770:
2771: Livalue:
2772: e = new IntegerExp(loc, ivalue, this);
2773: return e;
2774:
2775: Lfvalue:
2776: if (isreal() || isimaginary())
2777: e = new RealExp(loc, fvalue, this);
2778: else
2779: {
2780: complex_t cvalue;
2781:
2782: #if __DMC__
2783: //((real_t *)&cvalue)[0] = fvalue;
2784: //((real_t *)&cvalue)[1] = fvalue;
2785: cvalue = fvalue + fvalue * I;
2786: #else
2787: cvalue.re = fvalue;
2788: cvalue.im = fvalue;
2789: #endif
2790: //for (int i = 0; i < 20; i++)
2791: // printf("%02x ", ((unsigned char *)&cvalue)[i]);
2792: //printf("\n");
2793: e = new ComplexExp(loc, cvalue, this);
2794: }
2795: return e;
2796:
2797: Lint:
2798: e = new IntegerExp(loc, ivalue, Type::tint32);
2799: return e;
2800: }
2801:
2802: Expression *TypeBasic::dotExp(Scope *sc, Expression *e, Identifier *ident)
2803: {
2804: #if LOGDOTEXP
2805: printf("TypeBasic::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
2806: #endif
2807: Type *t;
2808:
2809: if (ident == Id::re)
2810: {
2811: switch (ty)
2812: {
2813: case Tcomplex32: t = tfloat32; goto L1;
2814: case Tcomplex64: t = tfloat64; goto L1;
2815: case Tcomplex80: t = tfloat80; goto L1;
2816: L1:
2817: e = e->castTo(sc, t);
2818: break;
2819:
2820: case Tfloat32:
2821: case Tfloat64:
2822: case Tfloat80:
2823: break;
2824:
2825: case Timaginary32: t = tfloat32; goto L2;
2826: case Timaginary64: t = tfloat64; goto L2;
2827: case Timaginary80: t = tfloat80; goto L2;
2828: L2:
2829: e = new RealExp(0, 0.0, t);
2830: break;
2831:
2832: default:
2833: e = Type::getProperty(e->loc, ident);
2834: break;
2835: }
2836: }
2837: else if (ident == Id::im)
2838: { Type *t2;
2839:
2840: switch (ty)
2841: {
2842: case Tcomplex32: t = timaginary32; t2 = tfloat32; goto L3;
2843: case Tcomplex64: t = timaginary64; t2 = tfloat64; goto L3;
2844: case Tcomplex80: t = timaginary80; t2 = tfloat80; goto L3;
2845: L3:
2846: e = e->castTo(sc, t);
2847: e->type = t2;
2848: break;
2849:
2850: case Timaginary32: t = tfloat32; goto L4;
2851: case Timaginary64: t = tfloat64; goto L4;
2852: case Timaginary80: t = tfloat80; goto L4;
2853: L4:
2854: e = e->copy();
2855: e->type = t;
2856: break;
2857:
2858: case Tfloat32:
2859: case Tfloat64:
2860: case Tfloat80:
2861: e = new RealExp(0, 0.0, this);
2862: break;
2863:
2864: default:
2865: e = Type::getProperty(e->loc, ident);
2866: break;
2867: }
2868: }
2869: else
2870: {
2871: return Type::dotExp(sc, e, ident);
2872: }
2873: e = e->semantic(sc);
2874: return e;
2875: }
2876:
2877: Expression *TypeBasic::defaultInit(Loc loc)
2878: { dinteger_t value = 0;
2879:
2880: #if SNAN_DEFAULT_INIT
2881: /*
2882: * Use a payload which is different from the machine NaN,
2883: * so that uninitialised variables can be
2884: * detected even if exceptions are disabled.
2885: */
2886: union
2887: { unsigned short us[8];
2888: long double ld;
2889: } snan = {{ 0, 0, 0, 0xA000, 0x7FFF }};
2890: /*
2891: * Although long doubles are 10 bytes long, some
2892: * C ABIs pad them out to 12 or even 16 bytes, so
2893: * leave enough space in the snan array.
2894: */
2895: assert(REALSIZE <= sizeof(snan));
2896: d_float80 fvalue = snan.ld;
2897: #endif
2898:
2899: #if LOGDEFAULTINIT
2900: printf("TypeBasic::defaultInit() '%s'\n", toChars());
2901: #endif
2902: switch (ty)
2903: {
2904: case Tchar:
2905: value = 0xFF;
2906: break;
2907:
2908: case Twchar:
2909: case Tdchar:
2910: value = 0xFFFF;
2911: break;
2912:
2913: case Timaginary32:
2914: case Timaginary64:
2915: case Timaginary80:
2916: case Tfloat32:
2917: case Tfloat64:
2918: case Tfloat80:
2919: #if SNAN_DEFAULT_INIT
2920: return new RealExp(loc, fvalue, this);
2921: #else
2922: return getProperty(loc, Id::nan);
2923: #endif
2924:
2925: case Tcomplex32:
2926: case Tcomplex64:
2927: case Tcomplex80:
2928: #if SNAN_DEFAULT_INIT
2929: { // Can't use fvalue + I*fvalue (the im part becomes a quiet NaN).
2930: complex_t cvalue;
2931: ((real_t *)&cvalue)[0] = fvalue;
2932: ((real_t *)&cvalue)[1] = fvalue;
2933: return new ComplexExp(loc, cvalue, this);
2934: }
2935: #else
2936: return getProperty(loc, Id::nan);
2937: #endif
2938:
2939: case Tvoid:
2940: error(loc, "void does not have a default initializer");
2941: return new ErrorExp();
2942: }
2943: return new IntegerExp(loc, value, this);
2944: }
2945:
2946: int TypeBasic::isZeroInit(Loc loc)
2947: {
2948: switch (ty)
2949: {
2950: case Tchar:
2951: case Twchar:
2952: case Tdchar:
2953: case Timaginary32:
2954: case Timaginary64:
2955: case Timaginary80:
2956: case Tfloat32:
2957: case Tfloat64:
2958: case Tfloat80:
2959: case Tcomplex32:
2960: case Tcomplex64:
2961: case Tcomplex80:
2962: return 0; // no
2963: }
2964: return 1; // yes
2965: }
2966:
2967: int TypeBasic::isintegral()
2968: {
2969: //printf("TypeBasic::isintegral('%s') x%x\n", toChars(), flags);
2970: return flags & TFLAGSintegral;
2971: }
2972:
2973: int TypeBasic::isfloating()
2974: {
2975: return flags & TFLAGSfloating;
2976: }
2977:
2978: int TypeBasic::isreal()
2979: {
2980: return flags & TFLAGSreal;
2981: }
2982:
2983: int TypeBasic::isimaginary()
2984: {
2985: return flags & TFLAGSimaginary;
2986: }
2987:
2988: int TypeBasic::iscomplex()
2989: {
2990: return flags & TFLAGScomplex;
2991: }
2992:
2993: int TypeBasic::isunsigned()
2994: {
2995: return flags & TFLAGSunsigned;
2996: }
2997:
2998: int TypeBasic::isscalar()
2999: {
3000: return flags & (TFLAGSintegral | TFLAGSfloating);
3001: }
3002:
3003: MATCH TypeBasic::implicitConvTo(Type *to)
3004: {
3005: //printf("TypeBasic::implicitConvTo(%s) from %s\n", to->toChars(), toChars());
3006: if (this == to)
3007: return MATCHexact;
3008:
3009: #if DMDV2
3010: if (ty == to->ty)
3011: {
3012: return (mod == to->mod) ? MATCHexact : MATCHconst;
3013: }
3014: #endif
3015:
3016: if (ty == Tvoid || to->ty == Tvoid)
3017: return MATCHnomatch;
3018: if (to->ty == Tbool)
3019: return MATCHnomatch;
3020: if (!to->isTypeBasic())
3021: return MATCHnomatch;
3022:
3023: TypeBasic *tob = (TypeBasic *)to;
3024: if (flags & TFLAGSintegral)
3025: {
3026: // Disallow implicit conversion of integers to imaginary or complex
3027: if (tob->flags & (TFLAGSimaginary | TFLAGScomplex))
3028: return MATCHnomatch;
3029:
3030: #if DMDV2
3031: // If converting from integral to integral
3032: if (1 && tob->flags & TFLAGSintegral)
3033: { d_uns64 sz = size(0);
3034: d_uns64 tosz = tob->size(0);
3035:
3036: /* Can't convert to smaller size
3037: */
3038: if (sz > tosz)
3039: return MATCHnomatch;
3040:
3041: /* Can't change sign if same size
3042: */
3043: /*if (sz == tosz && (flags ^ tob->flags) & TFLAGSunsigned)
3044: return MATCHnomatch;*/
3045: }
3046: #endif
3047: }
3048: else if (flags & TFLAGSfloating)
3049: {
3050: // Disallow implicit conversion of floating point to integer
3051: if (tob->flags & TFLAGSintegral)
3052: return MATCHnomatch;
3053:
3054: assert(tob->flags & TFLAGSfloating);
3055:
3056: // Disallow implicit conversion from complex to non-complex
3057: if (flags & TFLAGScomplex && !(tob->flags & TFLAGScomplex))
3058: return MATCHnomatch;
3059:
3060: // Disallow implicit conversion of real or imaginary to complex
3061: if (flags & (TFLAGSreal | TFLAGSimaginary) &&
3062: tob->flags & TFLAGScomplex)
3063: return MATCHnomatch;
3064:
3065: // Disallow implicit conversion to-from real and imaginary
3066: if ((flags & (TFLAGSreal | TFLAGSimaginary)) !=
3067: (tob->flags & (TFLAGSreal | TFLAGSimaginary)))
3068: return MATCHnomatch;
3069: }
3070: return MATCHconvert;
3071: }
3072:
3073: TypeBasic *TypeBasic::isTypeBasic()
3074: {
3075: return (TypeBasic *)this;
3076: }
3077:
3078: /***************************** TypeArray *****************************/
3079:
3080: TypeArray::TypeArray(TY ty, Type *next)
3081: : TypeNext(ty, next)
3082: {
3083: }
3084:
3085: Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
3086: {
3087: Type *n = this->next->toBasetype(); // uncover any typedef's
3088:
3089: #if LOGDOTEXP
3090: printf("TypeArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
3091: #endif
3092: if (ident == Id::reverse && (n->ty == Tchar || n->ty == Twchar))
3093: {
3094: Expression *ec;
3095: FuncDeclaration *fd;
3096: Expressions *arguments;
3097: const char *nm;
3098: static const char *name[2] = { "_adReverseChar", "_adReverseWchar" };
3099:
3100: nm = name[n->ty == Twchar];
3101: fd = FuncDeclaration::genCfunc(Type::tindex, nm);
3102: ec = new VarExp(0, fd);
3103: e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
3104: arguments = new Expressions();
3105: arguments->push(e);
3106: e = new CallExp(e->loc, ec, arguments);
3107: e->type = next->arrayOf();
3108: }
3109: else if (ident == Id::sort && (n->ty == Tchar || n->ty == Twchar))
3110: {
3111: Expression *ec;
3112: FuncDeclaration *fd;
3113: Expressions *arguments;
3114: const char *nm;
3115: static const char *name[2] = { "_adSortChar", "_adSortWchar" };
3116:
3117: nm = name[n->ty == Twchar];
3118: fd = FuncDeclaration::genCfunc(Type::tindex, nm);
3119: ec = new VarExp(0, fd);
3120: e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
3121: arguments = new Expressions();
3122: arguments->push(e);
3123: e = new CallExp(e->loc, ec, arguments);
3124: e->type = next->arrayOf();
3125: }
3126: else if (ident == Id::reverse || ident == Id::dup || ident == Id::idup)
3127: {
3128: Expression *ec;
3129: FuncDeclaration *fd;
3130: Expressions *arguments;
3131: int size = next->size(e->loc);
warning C4244: 'initializing' : conversion from 'd_uns64' to 'int', possible loss of data
3132: int dup;
3133:
3134: assert(size);
3135: dup = (ident == Id::dup || ident == Id::idup);
3136: fd = FuncDeclaration::genCfunc(Type::tindex, dup ? Id::adDup : Id::adReverse);
3137: ec = new VarExp(0, fd);
warning C6211: Leaking memory 'ec' due to an exception. Consider using a local catch block to clean up memory: Lines: 3087, 3092, 3109, 3126, 3128, 3129, 3130, 3131, 3132, 3134, 3135, 3136, 3137, 3138, 3139
3138: e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
3139: arguments = new Expressions();
warning C6211: Leaking memory 'arguments' due to an exception. Consider using a local catch block to clean up memory: Lines: 3087, 3092, 3109, 3126, 3128, 3129, 3130, 3131, 3132, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3142, 3143, 3144
3140: if (dup)
3141: arguments->push(getTypeInfo(sc));
3142: arguments->push(e);
3143: if (!dup)
3144: arguments->push(new IntegerExp(0, size, Type::tsize_t));
3145: e = new CallExp(e->loc, ec, arguments);
3146: if (ident == Id::idup)
3147: { Type *einv = next->invariantOf();
3148: if (next->implicitConvTo(einv) < MATCHconst)
3149: error(e->loc, "cannot implicitly convert element type %s to immutable", next->toChars());
3150: e->type = einv->arrayOf();
3151: }
3152: else
3153: e->type = next->mutableOf()->arrayOf();
3154: }
3155: else if (ident == Id::sort)
3156: {
3157: Expression *ec;
3158: FuncDeclaration *fd;
3159: Expressions *arguments;
3160:
3161: fd = FuncDeclaration::genCfunc(tint32->arrayOf(), "_adSort");
3162: ec = new VarExp(0, fd);
3163: e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
3164: arguments = new Expressions();
3165: arguments->push(e);
3166: arguments->push(n->ty == Tsarray
3167: ? n->getTypeInfo(sc) // don't convert to dynamic array
3168: : n->getInternalTypeInfo(sc));
3169: e = new CallExp(e->loc, ec, arguments);
3170: e->type = next->arrayOf();
3171: }
3172: else
3173: {
3174: e = Type::dotExp(sc, e, ident);
3175: }
3176: e = e->semantic(sc);
3177: return e;
3178: }
3179:
3180:
3181: /***************************** TypeSArray *****************************/
3182:
3183: TypeSArray::TypeSArray(Type *t, Expression *dim)
3184: : TypeArray(Tsarray, t)
3185: {
3186: //printf("TypeSArray(%s)\n", dim->toChars());
3187: this->dim = dim;
3188: }
3189:
3190: Type *TypeSArray::syntaxCopy()
3191: {
3192: Type *t = next->syntaxCopy();
3193: Expression *e = dim->syntaxCopy();
3194: t = new TypeSArray(t, e);
3195: t->mod = mod;
3196: return t;
3197: }
3198:
3199: d_uns64 TypeSArray::size(Loc loc)
3200: { dinteger_t sz;
3201:
3202: if (!dim)
3203: return Type::size(loc);
3204: sz = dim->toInteger();
3205:
3206: { dinteger_t n, n2;
3207:
3208: n = next->size();
3209: n2 = n * sz;
3210: if (n && (n2 / n) != sz)
3211: goto Loverflow;
3212: sz = n2;
3213: }
3214: return sz;
3215:
3216: Loverflow:
3217: error(loc, "index %jd overflow for static array", sz);
3218: return 1;
3219: }
3220:
3221: unsigned TypeSArray::alignsize()
3222: {
3223: return next->alignsize();
3224: }
3225:
3226: /**************************
3227: * This evaluates exp while setting length to be the number
3228: * of elements in the tuple t.
3229: */
3230: Expression *semanticLength(Scope *sc, Type *t, Expression *exp)
3231: {
3232: if (t->ty == Ttuple)
3233: { ScopeDsymbol *sym = new ArrayScopeSymbol(sc, (TypeTuple *)t);
3234: sym->parent = sc->scopesym;
3235: sc = sc->push(sym);
3236:
3237: exp = exp->semantic(sc);
3238:
3239: sc->pop();
3240: }
3241: else
3242: exp = exp->semantic(sc);
3243: return exp;
3244: }
3245:
3246: Expression *semanticLength(Scope *sc, TupleDeclaration *s, Expression *exp)
3247: {
3248: ScopeDsymbol *sym = new ArrayScopeSymbol(sc, s);
3249: sym->parent = sc->scopesym;
3250: sc = sc->push(sym);
3251:
3252: exp = exp->semantic(sc);
3253:
3254: sc->pop();
3255: return exp;
3256: }
3257:
3258: void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
3259: {
3260: //printf("TypeSArray::resolve() %s\n", toChars());
3261: next->resolve(loc, sc, pe, pt, ps);
3262: //printf("s = %p, e = %p, t = %p\n", *ps, *pe, *pt);
3263: if (*pe)
3264: { // It's really an index expression
3265: Expression *e = new IndexExp(loc, *pe, dim);
3266: *pe = e;
3267: }
3268: else if (*ps)
3269: { Dsymbol *s = *ps;
3270: TupleDeclaration *td = s->isTupleDeclaration();
3271: if (td)
3272: {
3273: ScopeDsymbol *sym = new ArrayScopeSymbol(sc, td);
3274: sym->parent = sc->scopesym;
3275: sc = sc->push(sym);
3276:
3277: dim = dim->semantic(sc);
3278: dim = dim->optimize(WANTvalue | WANTinterpret);
3279: uinteger_t d = dim->toUInteger();
3280:
3281: sc = sc->pop();
3282:
3283: if (d >= td->objects->dim)
3284: { error(loc, "tuple index %ju exceeds length %u", d, td->objects->dim);
3285: goto Ldefault;
3286: }
3287: Object *o = td->objects->tdata()[(size_t)d];
3288: if (o->dyncast() == DYNCAST_DSYMBOL)
3289: {
3290: *ps = (Dsymbol *)o;
3291: return;
3292: }
3293: if (o->dyncast() == DYNCAST_EXPRESSION)
3294: {
3295: *ps = NULL;
3296: *pe = (Expression *)o;
3297: return;
3298: }
3299:
3300: /* Create a new TupleDeclaration which
3301: * is a slice [d..d+1] out of the old one.
3302: * Do it this way because TemplateInstance::semanticTiargs()
3303: * can handle unresolved Objects this way.
3304: */
3305: Objects *objects = new Objects;
3306: objects->setDim(1);
3307: objects->tdata()[0] = o;
3308:
3309: TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
3310: *ps = tds;
3311: }
3312: else
3313: goto Ldefault;
3314: }
3315: else
3316: {
3317: Ldefault:
3318: Type::resolve(loc, sc, pe, pt, ps);
3319: }
3320: }
3321:
3322: Type *TypeSArray::semantic(Loc loc, Scope *sc)
3323: {
3324: //printf("TypeSArray::semantic() %s\n", toChars());
3325:
3326: Type *t;
3327: Expression *e;
3328: Dsymbol *s;
3329: next->resolve(loc, sc, &e, &t, &s);
3330: if (dim && s && s->isTupleDeclaration())
3331: { TupleDeclaration *sd = s->isTupleDeclaration();
3332:
3333: dim = semanticLength(sc, sd, dim);
3334: dim = dim->optimize(WANTvalue | WANTinterpret);
3335: uinteger_t d = dim->toUInteger();
3336:
3337: if (d >= sd->objects->dim)
3338: { error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim);
3339: return Type::terror;
3340: }
3341: Object *o = sd->objects->tdata()[(size_t)d];
3342: if (o->dyncast() != DYNCAST_TYPE)
3343: { error(loc, "%s is not a type", toChars());
3344: return Type::terror;
3345: }
3346: t = (Type *)o;
3347: return t;
3348: }
3349:
3350: next = next->semantic(loc,sc);
3351: transitive();
3352:
3353: Type *tbn = next->toBasetype();
3354:
3355: if (dim)
3356: { dinteger_t n, n2;
3357:
3358: dim = semanticLength(sc, tbn, dim);
3359:
3360: dim = dim->optimize(WANTvalue);
3361: if (sc && sc->parameterSpecialization && dim->op == TOKvar &&
3362: ((VarExp *)dim)->var->storage_class & STCtemplateparameter)
3363: {
3364: /* It could be a template parameter N which has no value yet:
3365: * template Foo(T : T[N], size_t N);
3366: */
3367: return this;
3368: }
3369: dim = dim->optimize(WANTvalue | WANTinterpret);
3370: dinteger_t d1 = dim->toInteger();
3371: dim = dim->implicitCastTo(sc, tsize_t);
3372: dim = dim->optimize(WANTvalue);
3373: dinteger_t d2 = dim->toInteger();
3374:
3375: if (dim->op == TOKerror)
3376: goto Lerror;
3377:
3378: if (d1 != d2)
3379: goto Loverflow;
3380:
3381: if (tbn->isintegral() ||
3382: tbn->isfloating() ||
3383: tbn->ty == Tpointer ||
3384: tbn->ty == Tarray ||
3385: tbn->ty == Tsarray ||
3386: tbn->ty == Taarray ||
3387: tbn->ty == Tclass)
3388: {
3389: /* Only do this for types that don't need to have semantic()
3390: * run on them for the size, since they may be forward referenced.
3391: */
3392: n = tbn->size(loc);
3393: n2 = n * d2;
3394: if ((int)n2 < 0)
3395: goto Loverflow;
3396: if (n2 >= 0x1000000) // put a 'reasonable' limit on it
3397: goto Loverflow;
3398: if (n && n2 / n != d2)
3399: {
3400: Loverflow:
3401: error(loc, "index %jd overflow for static array", d1);
3402: goto Lerror;
3403: }
3404: }
3405: }
3406: switch (tbn->ty)
3407: {
3408: case Ttuple:
3409: { // Index the tuple to get the type
3410: assert(dim);
3411: TypeTuple *tt = (TypeTuple *)tbn;
3412: uinteger_t d = dim->toUInteger();
3413:
3414: if (d >= tt->arguments->dim)
3415: { error(loc, "tuple index %ju exceeds %u", d, tt->arguments->dim);
3416: goto Lerror;
3417: }
3418: Parameter *arg = tt->arguments->tdata()[(size_t)d];
3419: return arg->type;
3420: }
3421: case Tstruct:
3422: { TypeStruct *ts = (TypeStruct *)tbn;
3423: if (0 && ts->sym->isnested)
3424: { error(loc, "cannot have static array of inner struct %s", ts->toChars());
3425: goto Lerror;
3426: }
3427: break;
3428: }
3429: case Tfunction:
3430: case Tnone:
3431: error(loc, "can't have array of %s", tbn->toChars());
3432: goto Lerror;
3433: }
3434: if (tbn->isscope())
3435: { error(loc, "cannot have array of scope %s", tbn->toChars());
3436: goto Lerror;
3437: }
3438:
3439: /* Ensure things like const(immutable(T)[3]) become immutable(T[3])
3440: * and const(T)[3] become const(T[3])
3441: */
3442: t = addMod(next->mod);
3443:
3444: return t->merge();
3445:
3446: Lerror:
3447: return Type::terror;
3448: }
3449:
3450: void TypeSArray::toDecoBuffer(OutBuffer *buf, int flag)
3451: {
3452: Type::toDecoBuffer(buf, flag);
3453: if (dim)
3454: buf->printf("%ju", dim->toInteger());
3455: if (next)
3456: /* Note that static arrays are value types, so
3457: * for a parameter, propagate the 0x100 to the next
3458: * level, since for T[4][3], any const should apply to the T,
3459: * not the [4].
3460: */
3461: next->toDecoBuffer(buf, (flag & 0x100) ? flag : mod);
3462: }
3463:
3464: void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3465: {
3466: if (mod != this->mod)
3467: { toCBuffer3(buf, hgs, mod);
3468: return;
3469: }
3470: next->toCBuffer2(buf, hgs, this->mod);
3471: buf->printf("[%s]", dim->toChars());
3472: }
3473:
3474: Expression *TypeSArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
3475: {
3476: #if LOGDOTEXP
3477: printf("TypeSArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
3478: #endif
3479: if (ident == Id::length)
3480: {
3481: e = dim;
3482: }
3483: else if (ident == Id::ptr)
3484: {
3485: e = e->castTo(sc, next->pointerTo());
3486: }
3487: else
3488: {
3489: e = TypeArray::dotExp(sc, e, ident);
3490: }
3491: e = e->semantic(sc);
3492: return e;
3493: }
3494:
3495: int TypeSArray::isString()
3496: {
3497: TY nty = next->toBasetype()->ty;
3498: return nty == Tchar || nty == Twchar || nty == Tdchar;
3499: }
3500:
3501: unsigned TypeSArray::memalign(unsigned salign)
3502: {
3503: return next->memalign(salign);
3504: }
3505:
3506: MATCH TypeSArray::constConv(Type *to)
3507: {
3508: if (to->ty == Tsarray)
3509: {
3510: TypeSArray *tsa = (TypeSArray *)to;
3511: if (!dim->equals(tsa->dim))
3512: return MATCHnomatch;
3513: }
3514: return TypeNext::constConv(to);
3515: }
3516:
3517: MATCH TypeSArray::implicitConvTo(Type *to)
3518: {
3519: //printf("TypeSArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars());
3520:
3521: // Allow implicit conversion of static array to pointer or dynamic array
3522: if (IMPLICIT_ARRAY_TO_PTR && to->ty == Tpointer)
3523: {
3524: TypePointer *tp = (TypePointer *)to;
3525:
3526: if (!MODimplicitConv(next->mod, tp->next->mod))
3527: return MATCHnomatch;
3528:
3529: if (tp->next->ty == Tvoid || next->constConv(tp->next) != MATCHnomatch)
3530: {
3531: return MATCHconvert;
3532: }
3533: return MATCHnomatch;
3534: }
3535: if (to->ty == Tarray)
3536: { int offset = 0;
3537: TypeDArray *ta = (TypeDArray *)to;
3538:
3539: if (!MODimplicitConv(next->mod, ta->next->mod))
3540: return MATCHnomatch;
3541:
3542: if (next->equals(ta->next) ||
3543: // next->implicitConvTo(ta->next) >= MATCHconst ||
3544: next->constConv(ta->next) != MATCHnomatch ||
3545: (ta->next->isBaseOf(next, &offset) && offset == 0) ||
3546: ta->next->ty == Tvoid)
3547: return MATCHconvert;
3548: return MATCHnomatch;
3549: }
3550: if (to->ty == Tsarray)
3551: {
3552: if (this == to)
3553: return MATCHexact;
3554:
3555: TypeSArray *tsa = (TypeSArray *)to;
3556:
3557: if (dim->equals(tsa->dim))
3558: {
3559: /* Since static arrays are value types, allow
3560: * conversions from const elements to non-const
3561: * ones, just like we allow conversion from const int
3562: * to int.
3563: */
3564: MATCH m = next->implicitConvTo(tsa->next);
3565: if (m >= MATCHconst)
3566: {
3567: if (mod != to->mod)
3568: m = MATCHconst;
3569: return m;
3570: }
3571: }
3572: }
3573: return MATCHnomatch;
3574: }
3575:
3576: Expression *TypeSArray::defaultInit(Loc loc)
3577: {
3578: #if LOGDEFAULTINIT
3579: printf("TypeSArray::defaultInit() '%s'\n", toChars());
3580: #endif
3581: return next->defaultInit(loc);
3582: }
3583:
3584: int TypeSArray::isZeroInit(Loc loc)
3585: {
3586: return next->isZeroInit(loc);
3587: }
3588:
3589: int TypeSArray::needsDestruction()
3590: {
3591: return next->needsDestruction();
3592: }
3593:
3594: Expression *TypeSArray::defaultInitLiteral(Loc loc)
3595: {
3596: #if LOGDEFAULTINIT
3597: printf("TypeSArray::defaultInitLiteral() '%s'\n", toChars());
3598: #endif
3599: size_t d = dim->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'size_t', possible loss of data
3600: Expression *elementinit = next->defaultInitLiteral(loc);
3601: Expressions *elements = new Expressions();
3602: elements->setDim(d);
3603: for (size_t i = 0; i < d; i++)
3604: elements->tdata()[i] = elementinit;
3605: ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements);
3606: ae->type = this;
3607: return ae;
3608: }
3609:
3610: Expression *TypeSArray::toExpression()
3611: {
3612: Expression *e = next->toExpression();
3613: if (e)
3614: { Expressions *arguments = new Expressions();
3615: arguments->push(dim);
3616: e = new ArrayExp(dim->loc, e, arguments);
3617: }
3618: return e;
3619: }
3620:
3621: int TypeSArray::hasPointers()
3622: {
3623: /* Don't want to do this, because:
3624: * struct S { T* array[0]; }
3625: * may be a variable length struct.
3626: */
3627: //if (dim->toInteger() == 0)
3628: //return FALSE;
3629:
3630: if (next->ty == Tvoid)
3631: // Arrays of void contain arbitrary data, which may include pointers
3632: return TRUE;
3633: else
3634: return next->hasPointers();
3635: }
3636:
3637: /***************************** TypeDArray *****************************/
3638:
3639: TypeDArray::TypeDArray(Type *t)
3640: : TypeArray(Tarray, t)
3641: {
3642: //printf("TypeDArray(t = %p)\n", t);
3643: }
3644:
3645: Type *TypeDArray::syntaxCopy()
3646: {
3647: Type *t = next->syntaxCopy();
3648: if (t == next)
3649: t = this;
3650: else
3651: { t = new TypeDArray(t);
3652: t->mod = mod;
3653: }
3654: return t;
3655: }
3656:
3657: d_uns64 TypeDArray::size(Loc loc)
3658: {
3659: //printf("TypeDArray::size()\n");
3660: return PTRSIZE * 2;
3661: }
3662:
3663: unsigned TypeDArray::alignsize()
3664: {
3665: // A DArray consists of two ptr-sized values, so align it on pointer size
3666: // boundary
3667: return PTRSIZE;
3668: }
3669:
3670: Type *TypeDArray::semantic(Loc loc, Scope *sc)
3671: { Type *tn = next;
3672:
3673: tn = next->semantic(loc,sc);
3674: Type *tbn = tn->toBasetype();
3675: switch (tbn->ty)
3676: {
3677: case Tfunction:
3678: case Tnone:
3679: case Ttuple:
3680: error(loc, "can't have array of %s", tbn->toChars());
3681: tn = next = tint32;
3682: break;
3683: case Tstruct:
3684: { TypeStruct *ts = (TypeStruct *)tbn;
3685: if (0 && ts->sym->isnested)
3686: error(loc, "cannot have dynamic array of inner struct %s", ts->toChars());
3687: break;
3688: }
3689: }
3690: if (tn->isscope())
3691: error(loc, "cannot have array of scope %s", tn->toChars());
3692:
3693: next = tn;
3694: transitive();
3695: return merge();
3696: }
3697:
3698: void TypeDArray::toDecoBuffer(OutBuffer *buf, int flag)
3699: {
3700: Type::toDecoBuffer(buf, flag);
3701: if (next)
3702: next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod);
3703: }
3704:
3705: void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
3706: {
3707: if (mod != this->mod)
3708: { toCBuffer3(buf, hgs, mod);
3709: return;
3710: }
3711: if (equals(tstring))
3712: buf->writestring("string");
3713: else
3714: { next->toCBuffer2(buf, hgs, this->mod);
3715: buf->writestring("[]");
3716: }
3717: }
3718:
3719: Expression *TypeDArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
3720: {
3721: #if LOGDOTEXP
3722: printf("TypeDArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
3723: #endif
3724: if (ident == Id::length)
3725: {
3726: if (e->op == TOKstring)
3727: { StringExp *se = (StringExp *)e;
3728:
3729: return new IntegerExp(se->loc, se->len, Type::tindex);
3730: }
3731: e = new ArrayLengthExp(e->loc, e);
3732: e->type = Type::tsize_t;
3733: return e;
3734: }
3735: else if (ident == Id::ptr)
3736: {
3737: e = e->castTo(sc, next->pointerTo());
3738: return e;
3739: }
3740: else
3741: {
3742: e = TypeArray::dotExp(sc, e, ident);
3743: }
3744: return e;
3745: }
3746:
3747: int TypeDArray::isString()
3748: {
3749: TY nty = next->toBasetype()->ty;
3750: return nty == Tchar || nty == Twchar || nty == Tdchar;
3751: }
3752:
3753: MATCH TypeDArray::implicitConvTo(Type *to)
3754: {
3755: //printf("TypeDArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars());
3756: if (equals(to))
3757: return MATCHexact;
3758:
3759: // Allow implicit conversion of array to pointer
3760: if (IMPLICIT_ARRAY_TO_PTR && to->ty == Tpointer)
3761: {
3762: TypePointer *tp = (TypePointer *)to;
3763:
3764: /* Allow conversion to void*
3765: */
3766: if (tp->next->ty == Tvoid &&
3767: MODimplicitConv(next->mod, tp->next->mod))
3768: {
3769: return MATCHconvert;
3770: }
3771:
3772: return next->constConv(to);
3773: }
3774:
3775: if (to->ty == Tarray)
3776: { int offset = 0;
3777: TypeDArray *ta = (TypeDArray *)to;
3778:
3779: if (!MODimplicitConv(next->mod, ta->next->mod))
3780: return MATCHnomatch; // not const-compatible
3781:
3782: /* Allow conversion to void[]
3783: */
3784: if (next->ty != Tvoid && ta->next->ty == Tvoid)
3785: {
3786: return MATCHconvert;
3787: }
3788:
3789: MATCH m = next->constConv(ta->next);
3790: if (m != MATCHnomatch)
3791: {
3792: if (m == MATCHexact && mod != to->mod)
3793: m = MATCHconst;
3794: return m;
3795: }
3796:
3797: #if 0
3798: /* Allow conversions of T[][] to const(T)[][]
3799: */
3800: if (mod == ta->mod && next->ty == Tarray && ta->next->ty == Tarray)
3801: {
3802: m = next->implicitConvTo(ta->next);
3803: if (m == MATCHconst)
3804: return m;
3805: }
3806: #endif
3807:
3808: /* Conversion of array of derived to array of base
3809: */
3810: if (ta->next->isBaseOf(next, &offset) && offset == 0)
3811: return MATCHconvert;
3812: }
3813: return Type::implicitConvTo(to);
3814: }
3815:
3816: Expression *TypeDArray::defaultInit(Loc loc)
3817: {
3818: #if LOGDEFAULTINIT
3819: printf("TypeDArray::defaultInit() '%s'\n", toChars());
3820: #endif
3821: return new NullExp(loc, this);
3822: }
3823:
3824: int TypeDArray::isZeroInit(Loc loc)
3825: {
3826: return 1;
3827: }
3828:
3829: int TypeDArray::checkBoolean()
3830: {
3831: return TRUE;
3832: }
3833:
3834: int TypeDArray::hasPointers()
3835: {
3836: return TRUE;
3837: }
3838:
3839:
3840: /***************************** TypeAArray *****************************/
3841:
3842: TypeAArray::TypeAArray(Type *t, Type *index)
3843: : TypeArray(Taarray, t)
3844: {
3845: this->index = index;
3846: this->impl = NULL;
3847: this->loc = 0;
3848: this->sc = NULL;
3849: }
3850:
3851: Type *TypeAArray::syntaxCopy()
3852: {
3853: Type *t = next->syntaxCopy();
3854: Type *ti = index->syntaxCopy();
3855: if (t == next && ti == index)
3856: t = this;
3857: else
3858: { t = new TypeAArray(t, ti);
3859: t->mod = mod;
3860: }
3861: return t;
3862: }
3863:
3864: d_uns64 TypeAArray::size(Loc loc)
3865: {
3866: return PTRSIZE /* * 2*/;
3867: }
3868:
3869:
3870: Type *TypeAArray::semantic(Loc loc, Scope *sc)
3871: {
3872: //printf("TypeAArray::semantic() %s index->ty = %d\n", toChars(), index->ty);
3873: this->loc = loc;
3874: this->sc = sc;
3875: if (sc)
3876: sc->setNoFree();
3877:
3878: // Deal with the case where we thought the index was a type, but
3879: // in reality it was an expression.
3880: if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray)
3881: {
3882: Expression *e;
3883: Type *t;
3884: Dsymbol *s;
3885:
3886: index->resolve(loc, sc, &e, &t, &s);
3887: if (e)
3888: { // It was an expression -
3889: // Rewrite as a static array
3890: TypeSArray *tsa;
3891:
3892: tsa = new TypeSArray(next, e);
3893: return tsa->semantic(loc,sc);
3894: }
3895: else if (t)
3896: index = t;
3897: else
3898: { index->error(loc, "index is not a type or an expression");
3899: return Type::terror;
3900: }
3901: }
3902: else
3903: index = index->semantic(loc,sc);
3904:
3905: if (index->nextOf() && !index->nextOf()->isImmutable())
3906: {
3907: index = index->constOf()->mutableOf();
3908: #if 0
3909: printf("index is %p %s\n", index, index->toChars());
3910: index->check();
3911: printf("index->mod = x%x\n", index->mod);
3912: printf("index->ito = x%x\n", index->ito);
3913: if (index->ito) {
3914: printf("index->ito->mod = x%x\n", index->ito->mod);
3915: printf("index->ito->ito = x%x\n", index->ito->ito);
3916: }
3917: #endif
3918: }
3919:
3920: switch (index->toBasetype()->ty)
3921: {
3922: case Tfunction:
3923: case Tvoid:
3924: case Tnone:
3925: case Ttuple:
3926: error(loc, "can't have associative array key of %s", index->toBasetype()->toChars());
3927: return Type::terror;
3928: }
3929: next = next->semantic(loc,sc);
3930: transitive();
3931:
3932: switch (next->toBasetype()->ty)
3933: {
3934: case Tfunction:
3935: case Tvoid:
3936: case Tnone:
3937: error(loc, "can't have associative array of %s", next->toChars());
3938: return Type::terror;
3939: }
3940: if (next->isscope())
3941: { error(loc, "cannot have array of scope %s", next->toChars());
3942: return Type::terror;
3943: }
3944: return merge();
3945: }
3946:
3947: StructDeclaration *TypeAArray::getImpl()
3948: {
3949: // Do it lazily
3950: if (!impl)
3951: {
3952: Type *index = this->index;
3953: Type *next = this->next;
3954: if (index->reliesOnTident() || next->reliesOnTident())
3955: {
3956: error(loc, "cannot create associative array %s", toChars());
3957: index = terror;
3958: next = terror;
3959:
3960: // Head off future failures
3961: StructDeclaration *s = new StructDeclaration(0, NULL);
3962: s->type = terror;
3963: impl = s;
3964: return impl;
3965: }
3966: /* This is really a proxy for the template instance AssocArray!(index, next)
3967: * But the instantiation can fail if it is a template specialization field
3968: * which has Tident's instead of real types.
3969: */
3970: Objects *tiargs = new Objects();
3971: tiargs->push(index);
3972: tiargs->push(next);
3973:
3974: // Create AssociativeArray!(index, next)
3975: #if 1
3976: TemplateInstance *ti = new TemplateInstance(loc, Type::associativearray, tiargs);
3977: #else
3978: //Expression *e = new IdentifierExp(loc, Id::object);
3979: Expression *e = new IdentifierExp(loc, Id::empty);
3980: //e = new DotIdExp(loc, e, Id::object);
3981: DotTemplateInstanceExp *dti = new DotTemplateInstanceExp(loc,
3982: e,
3983: Id::AssociativeArray,
3984: tiargs);
3985: dti->semantic(sc);
3986: TemplateInstance *ti = dti->ti;
3987: #endif
3988: ti->semantic(sc);
3989: ti->semantic2(sc);
3990: ti->semantic3(sc);
3991: impl = ti->toAlias()->isStructDeclaration();
3992: #ifdef DEBUG
3993: if (!impl)
3994: { Dsymbol *s = ti->toAlias();
3995: printf("%s %s\n", s->kind(), s->toChars());
3996: }
3997: #endif
3998: assert(impl);
3999: }
4000: return impl;
4001: }
4002:
4003: void TypeAArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
4004: {
4005: //printf("TypeAArray::resolve() %s\n", toChars());
4006:
4007: // Deal with the case where we thought the index was a type, but
4008: // in reality it was an expression.
4009: if (index->ty == Tident || index->ty == Tinstance || index->ty == Tsarray)
4010: {
4011: Expression *e;
4012: Type *t;
4013: Dsymbol *s;
4014:
4015: index->resolve(loc, sc, &e, &t, &s);
4016: if (e)
4017: { // It was an expression -
4018: // Rewrite as a static array
4019:
4020: TypeSArray *tsa = new TypeSArray(next, e);
4021: return tsa->resolve(loc, sc, pe, pt, ps);
4022: }
4023: else if (t)
4024: index = t;
4025: else
4026: index->error(loc, "index is not a type or an expression");
4027: }
4028: Type::resolve(loc, sc, pe, pt, ps);
4029: }
4030:
4031:
4032: Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
4033: {
4034: #if LOGDOTEXP
4035: printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
4036: #endif
4037: #if 0
4038: if (ident == Id::length)
4039: {
4040: Expression *ec;
4041: FuncDeclaration *fd;
4042: Expressions *arguments;
4043:
4044: fd = FuncDeclaration::genCfunc(Type::tsize_t, Id::aaLen);
4045: ec = new VarExp(0, fd);
4046: arguments = new Expressions();
4047: arguments->push(e);
4048: e = new CallExp(e->loc, ec, arguments);
4049: e->type = ((TypeFunction *)fd->type)->next;
4050: }
4051: else
4052: if (ident == Id::keys)
4053: {
4054: Expression *ec;
4055: FuncDeclaration *fd;
4056: Expressions *arguments;
4057: int size = index->size(e->loc);
4058:
4059: assert(size);
4060: fd = FuncDeclaration::genCfunc(Type::tindex, Id::aaKeys);
4061: ec = new VarExp(0, fd);
4062: arguments = new Expressions();
4063: arguments->push(e);
4064: arguments->push(new IntegerExp(0, size, Type::tsize_t));
4065: e = new CallExp(e->loc, ec, arguments);
4066: e->type = index->arrayOf();
4067: }
4068: else if (ident == Id::values)
4069: {
4070: Expression *ec;
4071: FuncDeclaration *fd;
4072: Expressions *arguments;
4073:
4074: fd = FuncDeclaration::genCfunc(Type::tindex, Id::aaValues);
4075: ec = new VarExp(0, fd);
4076: arguments = new Expressions();
4077: arguments->push(e);
4078: size_t keysize = index->size(e->loc);
4079: keysize = (keysize + PTRSIZE - 1) & ~(PTRSIZE - 1);
4080: arguments->push(new IntegerExp(0, keysize, Type::tsize_t));
4081: arguments->push(new IntegerExp(0, next->size(e->loc), Type::tsize_t));
4082: e = new CallExp(e->loc, ec, arguments);
4083: e->type = next->arrayOf();
4084: }
4085: else if (ident == Id::rehash)
4086: {
4087: Expression *ec;
4088: FuncDeclaration *fd;
4089: Expressions *arguments;
4090:
4091: fd = FuncDeclaration::genCfunc(Type::tint64, Id::aaRehash);
4092: ec = new VarExp(0, fd);
4093: arguments = new Expressions();
4094: arguments->push(e->addressOf(sc));
4095: arguments->push(index->getInternalTypeInfo(sc));
4096: e = new CallExp(e->loc, ec, arguments);
4097: e->type = this;
4098: }
4099: else
4100: #endif
4101: {
4102: e->type = getImpl()->type;
4103: e = e->type->dotExp(sc, e, ident);
4104: //e = Type::dotExp(sc, e, ident);
4105: }
4106: return e;
4107: }
4108:
4109: void TypeAArray::toDecoBuffer(OutBuffer *buf, int flag)
4110: {
4111: Type::toDecoBuffer(buf, flag);
4112: index->toDecoBuffer(buf);
4113: next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod);
4114: }
4115:
4116: void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4117: {
4118: if (mod != this->mod)
4119: { toCBuffer3(buf, hgs, mod);
4120: return;
4121: }
4122: next->toCBuffer2(buf, hgs, this->mod);
4123: buf->writeByte('[');
4124: index->toCBuffer2(buf, hgs, 0);
4125: buf->writeByte(']');
4126: }
4127:
4128: Expression *TypeAArray::defaultInit(Loc loc)
4129: {
4130: #if LOGDEFAULTINIT
4131: printf("TypeAArray::defaultInit() '%s'\n", toChars());
4132: #endif
4133: return new NullExp(loc, this);
4134: }
4135:
4136: int TypeAArray::isZeroInit(Loc loc)
4137: {
4138: return TRUE;
4139: }
4140:
4141: int TypeAArray::checkBoolean()
4142: {
4143: return TRUE;
4144: }
4145:
4146: int TypeAArray::hasPointers()
4147: {
4148: return TRUE;
4149: }
4150:
4151: MATCH TypeAArray::implicitConvTo(Type *to)
4152: {
4153: //printf("TypeAArray::implicitConvTo(to = %s) this = %s\n", to->toChars(), toChars());
4154: if (equals(to))
4155: return MATCHexact;
4156:
4157: if (to->ty == Taarray)
4158: { TypeAArray *ta = (TypeAArray *)to;
4159:
4160: if (!MODimplicitConv(next->mod, ta->next->mod))
4161: return MATCHnomatch; // not const-compatible
4162:
4163: if (!MODimplicitConv(index->mod, ta->index->mod))
4164: return MATCHnomatch; // not const-compatible
4165:
4166: MATCH m = next->constConv(ta->next);
4167: MATCH mi = index->constConv(ta->index);
4168: if (m != MATCHnomatch && mi != MATCHnomatch)
4169: {
4170: if (m == MATCHexact && mod != to->mod)
4171: m = MATCHconst;
4172: if (mi < m)
4173: m = mi;
4174: return m;
4175: }
4176: }
4177: return Type::implicitConvTo(to);
4178: }
4179:
4180: MATCH TypeAArray::constConv(Type *to)
4181: {
4182: if (to->ty == Taarray)
4183: {
4184: TypeAArray *taa = (TypeAArray *)to;
4185: MATCH mindex = index->constConv(taa->index);
4186: MATCH mkey = next->constConv(taa->next);
4187: // Pick the worst match
4188: return mkey < mindex ? mkey : mindex;
4189: }
4190: else
4191: return Type::constConv(to);
4192: }
4193:
4194: /***************************** TypePointer *****************************/
4195:
4196: TypePointer::TypePointer(Type *t)
4197: : TypeNext(Tpointer, t)
4198: {
4199: }
4200:
4201: Type *TypePointer::syntaxCopy()
4202: {
4203: Type *t = next->syntaxCopy();
4204: if (t == next)
4205: t = this;
4206: else
4207: { t = new TypePointer(t);
4208: t->mod = mod;
4209: }
4210: return t;
4211: }
4212:
4213: Type *TypePointer::semantic(Loc loc, Scope *sc)
4214: {
4215: //printf("TypePointer::semantic()\n");
4216: if (deco)
4217: return this;
4218: Type *n = next->semantic(loc, sc);
4219: switch (n->toBasetype()->ty)
4220: {
4221: case Ttuple:
4222: error(loc, "can't have pointer to %s", n->toChars());
4223: n = tint32;
4224: break;
4225: }
4226: if (n != next)
4227: {
4228: deco = NULL;
4229: }
4230: next = n;
4231: transitive();
4232: return merge();
4233: }
4234:
4235:
4236: d_uns64 TypePointer::size(Loc loc)
4237: {
4238: return PTRSIZE;
4239: }
4240:
4241: void TypePointer::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4242: {
4243: //printf("TypePointer::toCBuffer2() next = %d\n", next->ty);
4244: if (mod != this->mod)
4245: { toCBuffer3(buf, hgs, mod);
4246: return;
4247: }
4248: next->toCBuffer2(buf, hgs, this->mod);
4249: if (next->ty != Tfunction)
4250: buf->writeByte('*');
4251: }
4252:
4253: MATCH TypePointer::implicitConvTo(Type *to)
4254: {
4255: //printf("TypePointer::implicitConvTo(to = %s) %s\n", to->toChars(), toChars());
4256:
4257: if (equals(to))
4258: return MATCHexact;
4259: if (to->ty == Tpointer)
4260: { TypePointer *tp = (TypePointer *)to;
4261: assert(tp->next);
4262:
4263: if (!MODimplicitConv(next->mod, tp->next->mod))
4264: return MATCHnomatch; // not const-compatible
4265:
4266: /* Alloc conversion to void[]
4267: */
4268: if (next->ty != Tvoid && tp->next->ty == Tvoid)
4269: {
4270: return MATCHconvert;
4271: }
4272:
4273: MATCH m = next->constConv(tp->next);
4274: if (m != MATCHnomatch)
4275: {
4276: if (m == MATCHexact && mod != to->mod)
4277: m = MATCHconst;
4278: return m;
4279: }
4280:
4281: /* Conversion of ptr to derived to ptr to base
4282: */
4283: int offset = 0;
4284: if (tp->next->isBaseOf(next, &offset) && offset == 0)
4285: return MATCHconvert;
4286: }
4287: return MATCHnomatch;
4288: }
4289:
4290: int TypePointer::isscalar()
4291: {
4292: return TRUE;
4293: }
4294:
4295: Expression *TypePointer::defaultInit(Loc loc)
4296: {
4297: #if LOGDEFAULTINIT
4298: printf("TypePointer::defaultInit() '%s'\n", toChars());
4299: #endif
4300: return new NullExp(loc, this);
4301: }
4302:
4303: int TypePointer::isZeroInit(Loc loc)
4304: {
4305: return 1;
4306: }
4307:
4308: int TypePointer::hasPointers()
4309: {
4310: return TRUE;
4311: }
4312:
4313:
4314: /***************************** TypeReference *****************************/
4315:
4316: TypeReference::TypeReference(Type *t)
4317: : TypeNext(Treference, t)
4318: {
4319: // BUG: what about references to static arrays?
4320: }
4321:
4322: Type *TypeReference::syntaxCopy()
4323: {
4324: Type *t = next->syntaxCopy();
4325: if (t == next)
4326: t = this;
4327: else
4328: { t = new TypeReference(t);
4329: t->mod = mod;
4330: }
4331: return t;
4332: }
4333:
4334: Type *TypeReference::semantic(Loc loc, Scope *sc)
4335: {
4336: //printf("TypeReference::semantic()\n");
4337: Type *n = next->semantic(loc, sc);
4338: if (n != next)
4339: deco = NULL;
4340: next = n;
4341: transitive();
4342: return merge();
4343: }
4344:
4345:
4346: d_uns64 TypeReference::size(Loc loc)
4347: {
4348: return PTRSIZE;
4349: }
4350:
4351: void TypeReference::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4352: {
4353: if (mod != this->mod)
4354: { toCBuffer3(buf, hgs, mod);
4355: return;
4356: }
4357: next->toCBuffer2(buf, hgs, this->mod);
4358: buf->writeByte('&');
4359: }
4360:
4361: Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident)
4362: {
4363: #if LOGDOTEXP
4364: printf("TypeReference::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
4365: #endif
4366:
4367: // References just forward things along
4368: return next->dotExp(sc, e, ident);
4369: }
4370:
4371: Expression *TypeReference::defaultInit(Loc loc)
4372: {
4373: #if LOGDEFAULTINIT
4374: printf("TypeReference::defaultInit() '%s'\n", toChars());
4375: #endif
4376: return new NullExp(loc, this);
4377: }
4378:
4379: int TypeReference::isZeroInit(Loc loc)
4380: {
4381: return 1;
4382: }
4383:
4384:
4385: /***************************** TypeFunction *****************************/
4386:
4387: TypeFunction::TypeFunction(Parameters *parameters, Type *treturn, int varargs, enum LINK linkage, StorageClass stc)
4388: : TypeNext(Tfunction, treturn)
4389: {
4390: //if (!treturn) *(char*)0=0;
4391: // assert(treturn);
4392: assert(0 <= varargs && varargs <= 2);
4393: this->parameters = parameters;
4394: this->varargs = varargs;
4395: this->linkage = linkage;
4396: this->inuse = 0;
4397: this->isnothrow = false;
4398: this->purity = PUREimpure;
4399: this->isproperty = false;
4400: this->isref = false;
4401: this->fargs = NULL;
4402:
4403: if (stc & STCpure)
4404: this->purity = PUREfwdref;
4405: if (stc & STCnothrow)
4406: this->isnothrow = true;
4407: if (stc & STCproperty)
4408: this->isproperty = true;
4409:
4410: this->trust = TRUSTdefault;
4411: if (stc & STCsafe)
4412: this->trust = TRUSTsafe;
4413: if (stc & STCsystem)
4414: this->trust = TRUSTsystem;
4415: if (stc & STCtrusted)
4416: this->trust = TRUSTtrusted;
4417: }
4418:
4419: Type *TypeFunction::syntaxCopy()
4420: {
4421: Type *treturn = next ? next->syntaxCopy() : NULL;
4422: Parameters *params = Parameter::arraySyntaxCopy(parameters);
4423: TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage);
4424: t->mod = mod;
4425: t->isnothrow = isnothrow;
4426: t->purity = purity;
4427: t->isproperty = isproperty;
4428: t->isref = isref;
4429: t->trust = trust;
4430: t->fargs = fargs;
4431: return t;
4432: }
4433:
4434: /*******************************
4435: * Covariant means that 'this' can substitute for 't',
4436: * i.e. a pure function is a match for an impure type.
4437: * Returns:
4438: * 0 types are distinct
4439: * 1 this is covariant with t
4440: * 2 arguments match as far as overloading goes,
4441: * but types are not covariant
4442: * 3 cannot determine covariance because of forward references
4443: */
4444:
4445: int Type::covariant(Type *t)
4446: {
4447: #if 0
4448: printf("Type::covariant(t = %s) %s\n", t->toChars(), toChars());
4449: printf("deco = %p, %p\n", deco, t->deco);
4450: // printf("ty = %d\n", next->ty);
4451: printf("mod = %x, %x\n", mod, t->mod);
4452: #endif
4453:
4454: int inoutmismatch = 0;
4455:
4456: TypeFunction *t1;
4457: TypeFunction *t2;
4458:
4459: if (equals(t))
4460: return 1; // covariant
4461:
4462: if (ty != Tfunction || t->ty != Tfunction)
4463: goto Ldistinct;
4464:
4465: t1 = (TypeFunction *)this;
4466: t2 = (TypeFunction *)t;
4467:
4468: if (t1->varargs != t2->varargs)
4469: goto Ldistinct;
4470:
4471: if (t1->parameters && t2->parameters)
4472: {
4473: size_t dim = Parameter::dim(t1->parameters);
4474: if (dim != Parameter::dim(t2->parameters))
4475: goto Ldistinct;
4476:
4477: for (size_t i = 0; i < dim; i++)
4478: { Parameter *arg1 = Parameter::getNth(t1->parameters, i);
4479: Parameter *arg2 = Parameter::getNth(t2->parameters, i);
4480:
4481: if (!arg1->type->equals(arg2->type))
4482: {
4483: #if 0 // turn on this for contravariant argument types, see bugzilla 3075
4484: // BUG: cannot convert ref to const to ref to immutable
4485: // We can add const, but not subtract it
4486: if (arg2->type->implicitConvTo(arg1->type) < MATCHconst)
4487: #endif
4488: goto Ldistinct;
4489: }
4490: const StorageClass sc = STCref | STCin | STCout | STClazy;
4491: if ((arg1->storageClass & sc) != (arg2->storageClass & sc))
4492: inoutmismatch = 1;
4493: // We can add scope, but not subtract it
4494: if (!(arg1->storageClass & STCscope) && (arg2->storageClass & STCscope))
4495: inoutmismatch = 1;
4496: }
4497: }
4498: else if (t1->parameters != t2->parameters)
4499: goto Ldistinct;
4500:
4501: // The argument lists match
4502: if (inoutmismatch)
4503: goto Lnotcovariant;
4504: if (t1->linkage != t2->linkage)
4505: goto Lnotcovariant;
4506:
4507: {
4508: // Return types
4509: Type *t1n = t1->next;
4510: Type *t2n = t2->next;
4511:
4512: if (!t1n || !t2n) // happens with return type inference
4513: goto Lnotcovariant;
4514:
4515: if (t1n->equals(t2n))
4516: goto Lcovariant;
4517: if (t1n->ty == Tclass && t2n->ty == Tclass)
4518: {
4519: /* If same class type, but t2n is const, then it's
4520: * covariant. Do this test first because it can work on
4521: * forward references.
4522: */
4523: if (((TypeClass *)t1n)->sym == ((TypeClass *)t2n)->sym &&
4524: MODimplicitConv(t1n->mod, t2n->mod))
4525: goto Lcovariant;
4526:
4527: // If t1n is forward referenced:
4528: ClassDeclaration *cd = ((TypeClass *)t1n)->sym;
4529: #if 0
4530: if (!cd->baseClass && cd->baseclasses->dim && !cd->isInterfaceDeclaration())
4531: #else
4532: if (!cd->isBaseInfoComplete())
4533: #endif
4534: {
4535: return 3; // forward references
4536: }
4537: }
4538: if (t1n->implicitConvTo(t2n))
4539: goto Lcovariant;
4540: }
4541: goto Lnotcovariant;
4542:
4543: Lcovariant:
4544: /* Can convert mutable to const
4545: */
4546: if (!MODimplicitConv(t2->mod, t1->mod))
4547: goto Lnotcovariant;
4548: #if 0
4549: if (t1->mod != t2->mod)
4550: {
4551: if (!(t1->mod & MODconst) && (t2->mod & MODconst))
4552: goto Lnotcovariant;
4553: if (!(t1->mod & MODshared) && (t2->mod & MODshared))
4554: goto Lnotcovariant;
4555: }
4556: #endif
4557:
4558: /* Can convert pure to impure, and nothrow to throw
4559: */
4560: if (!t1->purity && t2->purity)
4561: goto Lnotcovariant;
4562:
4563: if (!t1->isnothrow && t2->isnothrow)
4564: goto Lnotcovariant;
4565:
4566: if (t1->isref != t2->isref)
4567: goto Lnotcovariant;
4568:
4569: /* Can convert safe/trusted to system
4570: */
4571: if (t1->trust <= TRUSTsystem && t2->trust >= TRUSTtrusted)
4572: goto Lnotcovariant;
4573:
4574: //printf("\tcovaraint: 1\n");
4575: return 1;
4576:
4577: Ldistinct:
4578: //printf("\tcovaraint: 0\n");
4579: return 0;
4580:
4581: Lnotcovariant:
4582: //printf("\tcovaraint: 2\n");
4583: return 2;
4584: }
4585:
4586: void TypeFunction::toDecoBuffer(OutBuffer *buf, int flag)
4587: { unsigned char mc;
4588:
4589: //printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars());
4590: //static int nest; if (++nest == 50) *(char*)0=0;
4591: if (inuse)
4592: { inuse = 2; // flag error to caller
4593: return;
4594: }
4595: inuse++;
4596: MODtoDecoBuffer(buf, mod);
4597: switch (linkage)
4598: {
4599: case LINKd: mc = 'F'; break;
4600: case LINKc: mc = 'U'; break;
4601: case LINKwindows: mc = 'W'; break;
4602: case LINKpascal: mc = 'V'; break;
4603: case LINKcpp: mc = 'R'; break;
4604: default:
4605: assert(0);
4606: }
4607: buf->writeByte(mc);
4608: if (purity || isnothrow || isproperty || isref || trust)
4609: {
4610: if (purity)
4611: buf->writestring("Na");
4612: if (isnothrow)
4613: buf->writestring("Nb");
4614: if (isref)
4615: buf->writestring("Nc");
4616: if (isproperty)
4617: buf->writestring("Nd");
4618: switch (trust)
4619: {
4620: case TRUSTtrusted:
4621: buf->writestring("Ne");
4622: break;
4623: case TRUSTsafe:
4624: buf->writestring("Nf");
4625: break;
4626: }
4627: }
4628: // Write argument types
4629: Parameter::argsToDecoBuffer(buf, parameters);
4630: //if (buf->data[buf->offset - 1] == '@') halt();
4631: buf->writeByte('Z' - varargs); // mark end of arg list
4632: assert(next);
4633: next->toDecoBuffer(buf);
4634: inuse--;
4635: }
4636:
4637: void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
4638: {
4639: toCBufferWithAttributes(buf, ident, hgs, this, NULL);
4640: }
4641:
4642: void TypeFunction::toCBufferWithAttributes(OutBuffer *buf, Identifier *ident, HdrGenState* hgs, TypeFunction *attrs, TemplateDeclaration *td)
4643: {
4644: //printf("TypeFunction::toCBuffer() this = %p\n", this);
4645: const char *p = NULL;
4646:
4647: if (inuse)
4648: { inuse = 2; // flag error to caller
4649: return;
4650: }
4651: inuse++;
4652:
4653: /* Use 'storage class' style for attributes
4654: */
4655: if (attrs->mod)
4656: {
4657: MODtoBuffer(buf, attrs->mod);
4658: buf->writeByte(' ');
4659: }
4660:
4661: if (attrs->purity)
4662: buf->writestring("pure ");
4663: if (attrs->isnothrow)
4664: buf->writestring("nothrow ");
4665: if (attrs->isproperty)
4666: buf->writestring("@property ");
4667: if (attrs->isref)
4668: buf->writestring("ref ");
4669:
4670: switch (attrs->trust)
4671: {
4672: case TRUSTsystem:
4673: buf->writestring("@system ");
4674: break;
4675:
4676: case TRUSTtrusted:
4677: buf->writestring("@trusted ");
4678: break;
4679:
4680: case TRUSTsafe:
4681: buf->writestring("@safe ");
4682: break;
4683: }
4684:
4685: if (next && (!ident || ident->toHChars2() == ident->toChars()))
4686: next->toCBuffer2(buf, hgs, 0);
4687: else if (hgs->ddoc && !next)
4688: buf->writestring("auto");
4689: if (hgs->ddoc != 1)
4690: {
4691: switch (attrs->linkage)
4692: {
4693: case LINKd: p = NULL; break;
4694: case LINKc: p = "C "; break;
4695: case LINKwindows: p = "Windows "; break;
4696: case LINKpascal: p = "Pascal "; break;
4697: case LINKcpp: p = "C++ "; break;
4698: default:
4699: assert(0);
4700: }
4701: }
4702:
4703: if (!hgs->hdrgen && p)
4704: buf->writestring(p);
4705: if (ident)
4706: { buf->writeByte(' ');
4707: buf->writestring(ident->toHChars2());
4708: }
4709: if (td)
4710: { buf->writeByte('(');
4711: for (int i = 0; i < td->origParameters->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4712: {
4713: TemplateParameter *tp = td->origParameters->tdata()[i];
4714: if (i)
4715: buf->writestring(", ");
4716: tp->toCBuffer(buf, hgs);
4717: }
4718: buf->writeByte(')');
4719: }
4720: Parameter::argsToCBuffer(buf, hgs, parameters, varargs);
4721: inuse--;
4722: }
4723:
4724: void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
4725: {
4726: //printf("TypeFunction::toCBuffer2() this = %p, ref = %d\n", this, isref);
4727: const char *p = NULL;
4728:
4729: if (inuse)
4730: { inuse = 2; // flag error to caller
4731: return;
4732: }
4733: inuse++;
4734: if (next)
4735: next->toCBuffer2(buf, hgs, 0);
4736: if (hgs->ddoc != 1)
4737: {
4738: switch (linkage)
4739: {
4740: case LINKd: p = NULL; break;
4741: case LINKc: p = " C"; break;
4742: case LINKwindows: p = " Windows"; break;
4743: case LINKpascal: p = " Pascal"; break;
4744: case LINKcpp: p = " C++"; break;
4745: default:
4746: assert(0);
4747: }
4748: }
4749:
4750: if (!hgs->hdrgen && p)
4751: buf->writestring(p);
4752: buf->writestring(" function");
4753: Parameter::argsToCBuffer(buf, hgs, parameters, varargs);
4754: attributesToCBuffer(buf, mod);
4755: inuse--;
4756: }
4757:
4758: void TypeFunction::attributesToCBuffer(OutBuffer *buf, int mod)
4759: {
4760: /* Use postfix style for attributes
4761: */
4762: if (mod != this->mod)
4763: {
4764: modToBuffer(buf);
4765: }
4766: if (purity)
4767: buf->writestring(" pure");
4768: if (isnothrow)
4769: buf->writestring(" nothrow");
4770: if (isproperty)
4771: buf->writestring(" @property");
4772: if (isref)
4773: buf->writestring(" ref");
4774:
4775: switch (trust)
4776: {
4777: case TRUSTsystem:
4778: buf->writestring(" @system");
4779: break;
4780:
4781: case TRUSTtrusted:
4782: buf->writestring(" @trusted");
4783: break;
4784:
4785: case TRUSTsafe:
4786: buf->writestring(" @safe");
4787: break;
4788: }
4789: }
4790:
4791: Type *TypeFunction::semantic(Loc loc, Scope *sc)
4792: {
4793: if (deco) // if semantic() already run
4794: {
4795: //printf("already done\n");
4796: return this;
4797: }
4798: //printf("TypeFunction::semantic() this = %p\n", this);
4799: //printf("TypeFunction::semantic() %s, sc->stc = %llx, fargs = %p\n", toChars(), sc->stc, fargs);
4800:
4801: /* Copy in order to not mess up original.
4802: * This can produce redundant copies if inferring return type,
4803: * as semantic() will get called again on this.
4804: */
4805: TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
4806: memcpy(tf, this, sizeof(TypeFunction));
4807: if (parameters)
4808: { tf->parameters = (Parameters *)parameters->copy();
4809: for (size_t i = 0; i < parameters->dim; i++)
4810: { Parameter *arg = parameters->tdata()[i];
4811: Parameter *cpy = (Parameter *)mem.malloc(sizeof(Parameter));
4812: memcpy(cpy, arg, sizeof(Parameter));
4813: tf->parameters->tdata()[i] = cpy;
4814: }
4815: }
4816:
4817: if (sc->stc & STCpure)
4818: tf->purity = PUREfwdref;
4819: if (sc->stc & STCnothrow)
4820: tf->isnothrow = TRUE;
4821: if (sc->stc & STCref)
4822: tf->isref = TRUE;
4823: if (sc->stc & STCsafe)
4824: tf->trust = TRUSTsafe;
4825: if (sc->stc & STCtrusted)
4826: tf->trust = TRUSTtrusted;
4827: if (sc->stc & STCproperty)
4828: tf->isproperty = TRUE;
4829:
4830: tf->linkage = sc->linkage;
4831:
4832: /* If the parent is @safe, then this function defaults to safe
4833: * too.
4834: */
4835: if (tf->trust == TRUSTdefault)
4836: for (Dsymbol *p = sc->func; p; p = p->toParent2())
4837: { FuncDeclaration *fd = p->isFuncDeclaration();
4838: if (fd)
4839: {
4840: if (fd->isSafe())
4841: tf->trust = TRUSTsafe; // default to @safe
4842: break;
4843: }
4844: }
4845:
4846: bool wildreturn = FALSE;
4847: if (tf->next)
4848: {
4849: tf->next = tf->next->semantic(loc,sc);
4850: #if !SARRAYVALUE
4851: if (tf->next->toBasetype()->ty == Tsarray)
4852: { error(loc, "functions cannot return static array %s", tf->next->toChars());
4853: tf->next = Type::terror;
4854: }
4855: #endif
4856: if (tf->next->toBasetype()->ty == Tfunction)
4857: { error(loc, "functions cannot return a function");
4858: tf->next = Type::terror;
4859: }
4860: if (tf->next->toBasetype()->ty == Ttuple)
4861: { error(loc, "functions cannot return a tuple");
4862: tf->next = Type::terror;
4863: }
4864: if (tf->next->isscope() && !(sc->flags & SCOPEctor))
4865: error(loc, "functions cannot return scope %s", tf->next->toChars());
4866: if (tf->next->toBasetype()->ty == Tvoid)
4867: tf->isref = FALSE; // rewrite "ref void" as just "void"
4868: if (tf->next->isWild())
4869: wildreturn = TRUE;
4870: }
4871:
4872: bool wildparams = FALSE;
4873: bool wildsubparams = FALSE;
4874: if (tf->parameters)
4875: {
4876: /* Create a scope for evaluating the default arguments for the parameters
4877: */
4878: Scope *argsc = sc->push();
4879: argsc->stc = 0; // don't inherit storage class
4880: argsc->protection = PROTpublic;
4881:
4882: size_t dim = Parameter::dim(tf->parameters);
4883: for (size_t i = 0; i < dim; i++)
4884: { Parameter *fparam = Parameter::getNth(tf->parameters, i);
4885:
4886: tf->inuse++;
4887: fparam->type = fparam->type->semantic(loc, argsc);
warning C6011: Dereferencing NULL pointer 'fparam->type': Lines: 4793, 4805, 4806, 4807, 4808, 4809, 4817, 4818, 4819, 4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, 4828, 4830, 4835, 4846, 4847, 4849, 4856, 4860, 4864, 4865, 4866, 4868, 4869, 4872, 4873, 4874, 4878, 4879, 4880, 4882, 4883, 4884, 4886, 4887
4888: if (tf->inuse == 1) tf->inuse--;
4889:
4890: fparam->type = fparam->type->addStorageClass(fparam->storageClass);
4891:
4892: if (fparam->storageClass & (STCauto | STCalias | STCstatic))
4893: {
4894: if (!fparam->type)
4895: continue;
4896: }
4897:
4898: Type *t = fparam->type->toBasetype();
4899:
4900: if (fparam->storageClass & (STCout | STCref | STClazy))
4901: {
4902: //if (t->ty == Tsarray)
4903: //error(loc, "cannot have out or ref parameter of type %s", t->toChars());
4904: if (fparam->storageClass & STCout && fparam->type->mod & (STCconst | STCimmutable))
4905: error(loc, "cannot have const or immutable out parameter of type %s", t->toChars());
4906: }
4907: if (!(fparam->storageClass & STClazy) && t->ty == Tvoid)
4908: error(loc, "cannot have parameter of type %s", fparam->type->toChars());
4909:
4910: if (t->isWild())
4911: {
4912: wildparams = TRUE;
4913: if (tf->next && !wildreturn)
4914: error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')");
4915: }
4916: else if (!wildsubparams && t->hasWild())
4917: wildsubparams = TRUE;
4918:
4919: if (fparam->defaultArg)
4920: {
4921: fparam->defaultArg = fparam->defaultArg->semantic(argsc);
4922: fparam->defaultArg = resolveProperties(argsc, fparam->defaultArg);
4923: fparam->defaultArg = fparam->defaultArg->implicitCastTo(argsc, fparam->type);
4924: }
4925:
4926: /* If fparam turns out to be a tuple, the number of parameters may
4927: * change.
4928: */
4929: if (t->ty == Ttuple)
4930: {
4931: // Propagate storage class from tuple parameters to their element-parameters.
4932: TypeTuple *tt = (TypeTuple *)t;
4933: if (tt->arguments)
4934: {
4935: size_t tdim = tt->arguments->dim;
4936: for (size_t j = 0; j < tdim; j++)
4937: { Parameter *narg = tt->arguments->tdata()[j];
4938: narg->storageClass |= fparam->storageClass;
4939: }
4940: fparam->storageClass = 0;
4941: }
4942:
4943: /* Reset number of parameters, and back up one to do this fparam again,
4944: * now that it is the first element of a tuple
4945: */
4946: dim = Parameter::dim(tf->parameters);
4947: i--;
4948: continue;
4949: }
4950:
4951: /* Resolve "auto ref" storage class to be either ref or value,
4952: * based on the argument matching the parameter
4953: */
4954: if (fparam->storageClass & STCauto)
4955: {
4956: if (fargs && i < fargs->dim)
4957: { Expression *farg = fargs->tdata()[i];
4958: if (farg->isLvalue())
4959: ; // ref parameter
4960: else
4961: fparam->storageClass &= ~STCref; // value parameter
4962: }
4963: else
4964: error(loc, "auto can only be used for template function parameters");
4965: }
4966: }
4967: argsc->pop();
4968: }
4969: if (wildreturn && !wildparams)
4970: error(loc, "inout on return means inout must be on a parameter as well for %s", toChars());
4971: if (wildsubparams && wildparams)
4972: error(loc, "inout must be all or none on top level for %s", toChars());
4973:
4974: if (tf->next)
4975: tf->deco = tf->merge()->deco;
4976:
4977: if (tf->inuse)
4978: { error(loc, "recursive type");
4979: tf->inuse = 0;
4980: return terror;
4981: }
4982:
4983: if (tf->isproperty && (tf->varargs || Parameter::dim(tf->parameters) > 1))
4984: error(loc, "properties can only have zero or one parameter");
4985:
4986: if (tf->varargs == 1 && tf->linkage != LINKd && Parameter::dim(tf->parameters) == 0)
4987: error(loc, "variadic functions with non-D linkage must have at least one parameter");
4988:
4989: /* Don't return merge(), because arg identifiers and default args
4990: * can be different
4991: * even though the types match
4992: */
4993: return tf;
4994: }
4995:
4996:
4997: /********************************************
4998: * Do this lazily, as the parameter types might be forward referenced.
4999: */
5000: void TypeFunction::purityLevel()
5001: {
5002: TypeFunction *tf = this;
5003: if (tf->purity == PUREfwdref)
5004: { /* Evaluate what kind of purity based on the modifiers for the parameters
5005: */
5006: tf->purity = PUREstrong; // assume strong until something weakens it
5007: if (tf->parameters)
5008: {
5009: size_t dim = Parameter::dim(tf->parameters);
5010: for (size_t i = 0; i < dim; i++)
5011: { Parameter *fparam = Parameter::getNth(tf->parameters, i);
5012: if (fparam->storageClass & STClazy)
5013: {
5014: /* We could possibly allow this by doing further analysis on the
5015: * lazy parameter to see if it's pure.
5016: */
5017: error(0, "cannot have lazy parameters to a pure function");
5018: }
5019: if (fparam->storageClass & STCout)
5020: {
5021: tf->purity = PUREweak;
5022: break;
5023: }
5024: if (!fparam->type)
5025: continue;
5026: if (fparam->storageClass & STCref)
5027: {
5028: if (!(fparam->type->mod & (MODconst | MODimmutable | MODwild)))
5029: { tf->purity = PUREweak;
5030: break;
5031: }
5032: if (fparam->type->mod & MODconst)
5033: { tf->purity = PUREconst;
5034: continue;
5035: }
5036: }
5037: Type *t = fparam->type->toBasetype();
5038: if (!t->hasPointers())
5039: continue;
5040: if (t->mod & (MODimmutable | MODwild))
5041: continue;
5042: /* The rest of this is too strict; fix later.
5043: * For example, the only pointer members of a struct may be immutable,
5044: * which would maintain strong purity.
5045: */
5046: if (t->mod & MODconst)
5047: { tf->purity = PUREconst;
5048: continue;
5049: }
5050: Type *tn = t->nextOf();
5051: if (tn)
5052: { tn = tn->toBasetype();
5053: if (tn->ty == Tpointer || tn->ty == Tarray)
5054: { /* Accept immutable(T)* and immutable(T)[] as being strongly pure
5055: */
5056: if (tn->mod & (MODimmutable | MODwild))
5057: continue;
5058: if (tn->mod & MODconst)
5059: { tf->purity = PUREconst;
5060: continue;
5061: }
5062: }
5063: }
5064: /* Should catch delegates and function pointers, and fold in their purity
5065: */
5066: tf->purity = PUREweak; // err on the side of too strict
5067: break;
5068: }
5069: }
5070: }
5071: }
5072:
5073:
5074: /********************************
5075: * 'args' are being matched to function 'this'
5076: * Determine match level.
5077: * Input:
5078: * flag 1 performing a partial ordering match
5079: * Returns:
5080: * MATCHxxxx
5081: */
5082:
5083: int TypeFunction::callMatch(Expression *ethis, Expressions *args, int flag)
5084: {
5085: //printf("TypeFunction::callMatch() %s\n", toChars());
5086: MATCH match = MATCHexact; // assume exact match
5087: bool exactwildmatch = FALSE;
5088: bool wildmatch = FALSE;
5089:
5090: if (ethis)
5091: { Type *t = ethis->type;
5092: if (t->toBasetype()->ty == Tpointer)
5093: t = t->toBasetype()->nextOf(); // change struct* to struct
5094: if (t->mod != mod)
5095: {
5096: if (MODimplicitConv(t->mod, mod))
5097: match = MATCHconst;
5098: else
5099: return MATCHnomatch;
5100: }
5101: }
5102:
5103: size_t nparams = Parameter::dim(parameters);
5104: size_t nargs = args ? args->dim : 0;
5105: if (nparams == nargs)
5106: ;
5107: else if (nargs > nparams)
5108: {
5109: if (varargs == 0)
5110: goto Nomatch; // too many args; no match
5111: match = MATCHconvert; // match ... with a "conversion" match level
5112: }
5113:
5114: for (size_t u = 0; u < nparams; u++)
5115: { MATCH m;
5116: Expression *arg;
5117:
5118: // BUG: what about out and ref?
5119:
5120: Parameter *p = Parameter::getNth(parameters, u);
5121: assert(p);
5122: if (u >= nargs)
5123: {
5124: if (p->defaultArg)
5125: continue;
5126: if (varargs == 2 && u + 1 == nparams)
5127: goto L1;
5128: goto Nomatch; // not enough arguments
5129: }
5130: arg = args->tdata()[u];
5131: assert(arg);
5132: //printf("arg: %s, type: %s\n", arg->toChars(), arg->type->toChars());
5133:
5134: // Non-lvalues do not match ref or out parameters
5135: if (p->storageClass & (STCref | STCout))
5136: { if (!arg->isLvalue())
5137: goto Nomatch;
5138: }
5139:
5140: if (p->storageClass & STCref)
5141: {
5142: /* Don't allow static arrays to be passed to mutable references
5143: * to static arrays if the argument cannot be modified.
5144: */
5145: Type *targb = arg->type->toBasetype();
5146: Type *tparb = p->type->toBasetype();
5147: //printf("%s\n", targb->toChars());
5148: //printf("%s\n", tparb->toChars());
5149: if (targb->nextOf() && tparb->ty == Tsarray &&
5150: !MODimplicitConv(targb->nextOf()->mod, tparb->nextOf()->mod))
5151: goto Nomatch;
5152: }
5153:
5154: if (p->storageClass & STClazy && p->type->ty == Tvoid &&
5155: arg->type->ty != Tvoid)
5156: m = MATCHconvert;
5157: else
5158: {
5159: //printf("%s of type %s implicitConvTo %s\n", arg->toChars(), arg->type->toChars(), p->type->toChars());
5160: if (flag)
5161: // for partial ordering, value is an irrelevant mockup, just look at the type
5162: m = arg->type->implicitConvTo(p->type);
5163: else
5164: m = arg->implicitConvTo(p->type);
5165: //printf("match %d\n", m);
5166: if (p->type->isWild())
5167: {
5168: if (m == MATCHnomatch)
5169: {
5170: m = arg->implicitConvTo(p->type->constOf());
5171: if (m == MATCHnomatch)
5172: m = arg->implicitConvTo(p->type->sharedConstOf());
5173: if (m != MATCHnomatch)
5174: wildmatch = TRUE; // mod matched to wild
5175: }
5176: else
5177: exactwildmatch = TRUE; // wild matched to wild
5178:
5179: /* If both are allowed, then there could be more than one
5180: * binding of mod to wild, leaving a gaping type hole.
5181: */
5182: if (wildmatch && exactwildmatch)
5183: m = MATCHnomatch;
5184: }
5185: }
5186:
5187: //printf("\tm = %d\n", m);
5188: if (m == MATCHnomatch) // if no match
5189: {
5190: L1:
5191: if (varargs == 2 && u + 1 == nparams) // if last varargs param
5192: { Type *tb = p->type->toBasetype();
5193: TypeSArray *tsa;
5194: dinteger_t sz;
5195:
5196: switch (tb->ty)
5197: {
5198: case Tsarray:
5199: tsa = (TypeSArray *)tb;
5200: sz = tsa->dim->toInteger();
5201: if (sz != nargs - u)
5202: goto Nomatch;
5203: case Tarray:
5204: { TypeArray *ta = (TypeArray *)tb;
5205: for (; u < nargs; u++)
5206: {
5207: arg = args->tdata()[u];
5208: assert(arg);
5209: #if 1
5210: /* If lazy array of delegates,
5211: * convert arg(s) to delegate(s)
5212: */
5213: Type *tret = p->isLazyArray();
5214: if (tret)
5215: {
5216: if (ta->next->equals(arg->type))
5217: { m = MATCHexact;
5218: }
5219: else
5220: {
5221: m = arg->implicitConvTo(tret);
5222: if (m == MATCHnomatch)
5223: {
5224: if (tret->toBasetype()->ty == Tvoid)
5225: m = MATCHconvert;
5226: }
5227: }
5228: }
5229: else
5230: m = arg->implicitConvTo(ta->next);
5231: #else
5232: m = arg->implicitConvTo(ta->next);
5233: #endif
5234: if (m == MATCHnomatch)
5235: goto Nomatch;
5236: if (m < match)
5237: match = m;
5238: }
5239: goto Ldone;
5240: }
5241: case Tclass:
5242: // Should see if there's a constructor match?
5243: // Or just leave it ambiguous?
5244: goto Ldone;
5245:
5246: default:
5247: goto Nomatch;
5248: }
5249: }
5250: goto Nomatch;
5251: }
5252: if (m < match)
5253: match = m; // pick worst match
5254: }
5255:
5256: Ldone:
5257: //printf("match = %d\n", match);
5258: return match;
5259:
5260: Nomatch:
5261: //printf("no match\n");
5262: return MATCHnomatch;
5263: }
5264:
5265: Type *TypeFunction::reliesOnTident()
5266: {
5267: size_t dim = Parameter::dim(parameters);
5268: for (size_t i = 0; i < dim; i++)
5269: { Parameter *fparam = Parameter::getNth(parameters, i);
5270: Type *t = fparam->type->reliesOnTident();
5271: if (t)
5272: return t;
5273: }
5274: return next ? next->reliesOnTident() : NULL;
5275: }
5276:
5277: /********************************************
5278: * Return TRUE if there are lazy parameters.
5279: */
5280: bool TypeFunction::hasLazyParameters()
5281: {
5282: size_t dim = Parameter::dim(parameters);
5283: for (size_t i = 0; i < dim; i++)
5284: { Parameter *fparam = Parameter::getNth(parameters, i);
5285: if (fparam->storageClass & STClazy)
5286: return TRUE;
5287: }
5288: return FALSE;
5289: }
5290:
5291: /***************************
5292: * Examine function signature for parameter p and see if
5293: * p can 'escape' the scope of the function.
5294: */
5295:
5296: bool TypeFunction::parameterEscapes(Parameter *p)
5297: {
5298:
5299: /* Scope parameters do not escape.
5300: * Allow 'lazy' to imply 'scope' -
5301: * lazy parameters can be passed along
5302: * as lazy parameters to the next function, but that isn't
5303: * escaping.
5304: */
5305: if (p->storageClass & (STCscope | STClazy))
5306: return FALSE;
5307:
5308: if (purity)
5309: { /* With pure functions, we need only be concerned if p escapes
5310: * via any return statement.
5311: */
5312: Type* tret = nextOf()->toBasetype();
5313: if (!isref && !tret->hasPointers())
5314: { /* The result has no references, so p could not be escaping
5315: * that way.
5316: */
5317: return FALSE;
5318: }
5319: }
5320:
5321: /* Assume it escapes in the absence of better information.
5322: */
5323: return TRUE;
5324: }
5325:
5326: Expression *TypeFunction::defaultInit(Loc loc)
5327: {
5328: error(loc, "function does not have a default initializer");
5329: return new ErrorExp();
5330: }
5331:
5332: /***************************** TypeDelegate *****************************/
5333:
5334: TypeDelegate::TypeDelegate(Type *t)
5335: : TypeNext(Tfunction, t)
5336: {
5337: ty = Tdelegate;
5338: }
5339:
5340: Type *TypeDelegate::syntaxCopy()
5341: {
5342: Type *t = next->syntaxCopy();
5343: if (t == next)
5344: t = this;
5345: else
5346: { t = new TypeDelegate(t);
5347: t->mod = mod;
5348: }
5349: return t;
5350: }
5351:
5352: Type *TypeDelegate::semantic(Loc loc, Scope *sc)
5353: {
5354: if (deco) // if semantic() already run
5355: {
5356: //printf("already done\n");
5357: return this;
5358: }
5359: next = next->semantic(loc,sc);
5360: /* In order to deal with Bugzilla 4028, perhaps default arguments should
5361: * be removed from next before the merge.
5362: */
5363:
5364: /* Don't return merge(), because arg identifiers and default args
5365: * can be different
5366: * even though the types match
5367: */
5368: //deco = merge()->deco;
5369: //return this;
5370: return merge();
5371: }
5372:
5373: d_uns64 TypeDelegate::size(Loc loc)
5374: {
5375: return PTRSIZE * 2;
5376: }
5377:
5378: unsigned TypeDelegate::alignsize()
5379: {
5380: #if DMDV1
5381: // See Bugzilla 942 for discussion
5382: if (!global.params.is64bit)
5383: return PTRSIZE * 2;
5384: #endif
5385: return PTRSIZE;
5386: }
5387:
5388: MATCH TypeDelegate::implicitConvTo(Type *to)
5389: {
5390: //printf("TypeDelegate::implicitConvTo(this=%p, to=%p)\n", this, to);
5391: //printf("from: %s\n", toChars());
5392: //printf("to : %s\n", to->toChars());
5393: if (this == to)
5394: return MATCHexact;
5395: #if 1 // not allowing covariant conversions because it interferes with overriding
5396: if (to->ty == Tdelegate && this->nextOf()->covariant(to->nextOf()) == 1)
5397: return MATCHconvert;
5398: #endif
5399: return MATCHnomatch;
5400: }
5401:
5402: void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
5403: {
5404: if (mod != this->mod)
5405: { toCBuffer3(buf, hgs, mod);
5406: return;
5407: }
5408: TypeFunction *tf = (TypeFunction *)next;
5409:
5410: tf->next->toCBuffer2(buf, hgs, 0);
5411: buf->writestring(" delegate");
5412: Parameter::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs);
5413: tf->attributesToCBuffer(buf, mod);
5414: }
5415:
5416: Expression *TypeDelegate::defaultInit(Loc loc)
5417: {
5418: #if LOGDEFAULTINIT
5419: printf("TypeDelegate::defaultInit() '%s'\n", toChars());
5420: #endif
5421: return new NullExp(loc, this);
5422: }
5423:
5424: int TypeDelegate::isZeroInit(Loc loc)
5425: {
5426: return 1;
5427: }
5428:
5429: int TypeDelegate::checkBoolean()
5430: {
5431: return TRUE;
5432: }
5433:
5434: Expression *TypeDelegate::dotExp(Scope *sc, Expression *e, Identifier *ident)
5435: {
5436: #if LOGDOTEXP
5437: printf("TypeDelegate::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
5438: #endif
5439: if (ident == Id::ptr)
5440: {
5441: e->type = tvoidptr;
5442: return e;
5443: }
5444: else if (ident == Id::funcptr)
5445: {
5446: e = e->addressOf(sc);
5447: e->type = tvoidptr;
5448: e = new AddExp(e->loc, e, new IntegerExp(PTRSIZE));
5449: e->type = tvoidptr;
5450: e = new PtrExp(e->loc, e);
5451: e->type = next->pointerTo();
5452: return e;
5453: }
5454: else
5455: {
5456: e = Type::dotExp(sc, e, ident);
5457: }
5458: return e;
5459: }
5460:
5461: int TypeDelegate::hasPointers()
5462: {
5463: return TRUE;
5464: }
5465:
5466:
5467:
5468: /***************************** TypeQualified *****************************/
5469:
5470: TypeQualified::TypeQualified(TY ty, Loc loc)
5471: : Type(ty)
5472: {
5473: this->loc = loc;
5474: }
5475:
5476: void TypeQualified::syntaxCopyHelper(TypeQualified *t)
5477: {
5478: //printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t->toChars(), toChars());
5479: idents.setDim(t->idents.dim);
5480: for (int i = 0; i < idents.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5481: {
5482: Identifier *id = t->idents.tdata()[i];
5483: if (id->dyncast() == DYNCAST_DSYMBOL)
5484: {
5485: TemplateInstance *ti = (TemplateInstance *)id;
5486:
5487: ti = (TemplateInstance *)ti->syntaxCopy(NULL);
5488: id = (Identifier *)ti;
5489: }
5490: idents.tdata()[i] = id;
5491: }
5492: }
5493:
5494:
5495: void TypeQualified::addIdent(Identifier *ident)
5496: {
5497: idents.push(ident);
5498: }
5499:
5500: void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs)
5501: {
5502: int i;
5503:
5504: for (i = 0; i < idents.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5505: { Identifier *id = idents.tdata()[i];
5506:
5507: buf->writeByte('.');
5508:
5509: if (id->dyncast() == DYNCAST_DSYMBOL)
5510: {
5511: TemplateInstance *ti = (TemplateInstance *)id;
5512: ti->toCBuffer(buf, hgs);
5513: }
5514: else
5515: buf->writestring(id->toChars());
5516: }
5517: }
5518:
5519: d_uns64 TypeQualified::size(Loc loc)
5520: {
5521: error(this->loc, "size of type %s is not known", toChars());
5522: return 1;
5523: }
5524:
5525: /*************************************
5526: * Takes an array of Identifiers and figures out if
5527: * it represents a Type or an Expression.
5528: * Output:
5529: * if expression, *pe is set
5530: * if type, *pt is set
5531: */
5532:
5533: void TypeQualified::resolveHelper(Loc loc, Scope *sc,
5534: Dsymbol *s, Dsymbol *scopesym,
5535: Expression **pe, Type **pt, Dsymbol **ps)
5536: {
5537: VarDeclaration *v;
5538: FuncDeclaration *fd;
warning C4101: 'fd' : unreferenced local variable
5539: EnumMember *em;
5540: TupleDeclaration *td;
warning C4101: 'td' : unreferenced local variable
5541: Expression *e;
5542:
5543: #if 0
5544: printf("TypeQualified::resolveHelper(sc = %p, idents = '%s')\n", sc, toChars());
5545: if (scopesym)
5546: printf("\tscopesym = '%s'\n", scopesym->toChars());
5547: #endif
5548: *pe = NULL;
5549: *pt = NULL;
5550: *ps = NULL;
5551: if (s)
5552: {
5553: //printf("\t1: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
5554: s->checkDeprecated(loc, sc); // check for deprecated aliases
5555: s = s->toAlias();
5556: //printf("\t2: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
5557: for (int i = 0; i < idents.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5558: {
5559: Identifier *id = idents.tdata()[i];
5560: Dsymbol *sm = s->searchX(loc, sc, id);
5561: //printf("\t3: s = '%s' %p, kind = '%s'\n",s->toChars(), s, s->kind());
5562: //printf("\tgetType = '%s'\n", s->getType()->toChars());
5563: if (!sm)
5564: { Type *t;
5565:
5566: v = s->isVarDeclaration();
5567: if (v && id == Id::length)
5568: {
5569: e = v->getConstInitializer();
5570: if (!e)
5571: e = new VarExp(loc, v);
5572: t = e->type;
5573: if (!t)
5574: goto Lerror;
5575: goto L3;
5576: }
5577: else if (v && id == Id::stringof)
5578: {
5579: e = new DsymbolExp(loc, s, 0);
5580: do
5581: {
5582: id = idents.tdata()[i];
5583: e = new DotIdExp(loc, e, id);
5584: } while (++i < idents.dim);
warning C4018: '<' : signed/unsigned mismatch
5585: e = e->semantic(sc);
5586: *pe = e;
5587: return;
5588: }
5589:
5590: t = s->getType();
5591: if (!t && s->isDeclaration())
5592: t = s->isDeclaration()->type;
5593: if (t)
5594: {
5595: sm = t->toDsymbol(sc);
5596: if (sm)
5597: { sm = sm->search(loc, id, 0);
5598: if (sm)
5599: goto L2;
5600: }
5601: //e = t->getProperty(loc, id);
5602: e = new TypeExp(loc, t);
5603: e = t->dotExp(sc, e, id);
5604: i++;
5605: L3:
5606: for (; i < idents.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5607: {
5608: id = idents.tdata()[i];
5609: //printf("e: '%s', id: '%s', type = %p\n", e->toChars(), id->toChars(), e->type);
5610: if (id == Id::offsetof || !e->type)
5611: { e = new DotIdExp(e->loc, e, id);
5612: e = e->semantic(sc);
5613: }
5614: else
5615: e = e->type->dotExp(sc, e, id);
5616: }
5617: *pe = e;
5618: }
5619: else
5620: {
5621: Lerror:
5622: error(loc, "identifier '%s' of '%s' is not defined", id->toChars(), toChars());
5623: *pe = new ErrorExp();
5624: }
5625: return;
5626: }
5627: L2:
5628: s = sm->toAlias();
5629: }
5630:
5631: v = s->isVarDeclaration();
5632: if (v)
5633: {
5634: *pe = new VarExp(loc, v);
5635: return;
5636: }
5637: #if 0
5638: fd = s->isFuncDeclaration();
5639: if (fd)
5640: {
5641: *pe = new DsymbolExp(loc, fd, 1);
5642: return;
5643: }
5644: #endif
5645: em = s->isEnumMember();
5646: if (em)
5647: {
5648: // It's not a type, it's an expression
5649: *pe = em->value->copy();
5650: return;
5651: }
5652:
5653: L1:
5654: Type *t = s->getType();
5655: if (!t)
5656: {
5657: // If the symbol is an import, try looking inside the import
5658: Import *si;
5659:
5660: si = s->isImport();
5661: if (si)
5662: {
5663: s = si->search(loc, s->ident, 0);
5664: if (s && s != si)
5665: goto L1;
5666: s = si;
5667: }
5668: *ps = s;
5669: return;
5670: }
5671: if (t->ty == Tinstance && t != this && !t->deco)
5672: { error(loc, "forward reference to '%s'", t->toChars());
5673: return;
5674: }
5675:
5676: if (t != this)
5677: {
5678: if (t->reliesOnTident())
5679: {
5680: if (s->scope)
5681: t = t->semantic(loc, s->scope);
5682: else
5683: {
5684: /* Attempt to find correct scope in which to evaluate t.
5685: * Not sure if this is right or not, or if we should just
5686: * give forward reference error if s->scope is not set.
5687: */
5688: for (Scope *scx = sc; 1; scx = scx->enclosing)
5689: {
5690: if (!scx)
5691: { error(loc, "forward reference to '%s'", t->toChars());
5692: return;
5693: }
5694: if (scx->scopesym == scopesym)
5695: {
5696: t = t->semantic(loc, scx);
5697: break;
5698: }
5699: }
5700: }
5701: }
5702: }
5703: if (t->ty == Ttuple)
5704: *pt = t;
5705: else
5706: *pt = t->merge();
5707: }
5708: if (!s)
5709: {
5710: const char *p = toChars();
5711: const char *n = importHint(p);
5712: if (n)
5713: error(loc, "'%s' is not defined, perhaps you need to import %s; ?", p, n);
5714: else
5715: {
5716: Identifier *id = new Identifier(p, TOKidentifier);
5717: s = sc->search_correct(id);
5718: if (s)
5719: error(loc, "undefined identifier %s, did you mean %s %s?", p, s->kind(), s->toChars());
5720: else
5721: error(loc, "undefined identifier %s", p);
5722: }
5723: *pt = Type::terror;
5724: }
5725: }
5726:
5727: /***************************** TypeIdentifier *****************************/
5728:
5729: TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident)
5730: : TypeQualified(Tident, loc)
5731: {
5732: this->ident = ident;
5733: }
5734:
5735:
5736: Type *TypeIdentifier::syntaxCopy()
5737: {
5738: TypeIdentifier *t;
5739:
5740: t = new TypeIdentifier(loc, ident);
5741: t->syntaxCopyHelper(this);
5742: t->mod = mod;
5743: return t;
5744: }
5745:
5746: void TypeIdentifier::toDecoBuffer(OutBuffer *buf, int flag)
5747: { unsigned len;
5748: char *name;
5749:
5750: Type::toDecoBuffer(buf, flag);
5751: name = ident->toChars();
5752: len = strlen(name);
5753: buf->printf("%d%s", len, name);
5754: }
5755:
5756: void TypeIdentifier::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
5757: {
5758: if (mod != this->mod)
5759: { toCBuffer3(buf, hgs, mod);
5760: return;
5761: }
5762: buf->writestring(this->ident->toChars());
5763: toCBuffer2Helper(buf, hgs);
5764: }
5765:
5766: /*************************************
5767: * Takes an array of Identifiers and figures out if
5768: * it represents a Type or an Expression.
5769: * Output:
5770: * if expression, *pe is set
5771: * if type, *pt is set
5772: */
5773:
5774: void TypeIdentifier::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
5775: {
5776: Dsymbol *scopesym;
5777:
5778: //printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars());
5779: Dsymbol *s = sc->search(loc, ident, &scopesym);
5780: resolveHelper(loc, sc, s, scopesym, pe, pt, ps);
5781: if (*pt)
5782: (*pt) = (*pt)->addMod(mod);
5783: }
5784:
5785: /*****************************************
5786: * See if type resolves to a symbol, if so,
5787: * return that symbol.
5788: */
5789:
5790: Dsymbol *TypeIdentifier::toDsymbol(Scope *sc)
5791: {
5792: //printf("TypeIdentifier::toDsymbol('%s')\n", toChars());
5793: if (!sc)
5794: return NULL;
5795: //printf("ident = '%s'\n", ident->toChars());
5796:
5797: Dsymbol *scopesym;
5798: Dsymbol *s = sc->search(loc, ident, &scopesym);
5799: if (s)
5800: {
5801: for (int i = 0; i < idents.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5802: {
5803: Identifier *id = idents.tdata()[i];
5804: s = s->searchX(loc, sc, id);
5805: if (!s) // failed to find a symbol
5806: { //printf("\tdidn't find a symbol\n");
5807: break;
5808: }
5809: }
5810: }
5811: return s;
5812: }
5813:
5814: Type *TypeIdentifier::semantic(Loc loc, Scope *sc)
5815: {
5816: Type *t;
5817: Expression *e;
5818: Dsymbol *s;
5819:
5820: //printf("TypeIdentifier::semantic(%s)\n", toChars());
5821: resolve(loc, sc, &e, &t, &s);
5822: if (t)
5823: {
5824: //printf("\tit's a type %d, %s, %s\n", t->ty, t->toChars(), t->deco);
5825:
5826: if (t->ty == Ttypedef)
5827: { TypeTypedef *tt = (TypeTypedef *)t;
5828:
5829: if (tt->sym->sem == 1)
5830: error(loc, "circular reference of typedef %s", tt->toChars());
5831: }
5832: t = t->addMod(mod);
5833: }
5834: else
5835: {
5836: #ifdef DEBUG
5837: if (!global.gag)
5838: printf("1: ");
5839: #endif
5840: if (s)
5841: {
5842: s->error(loc, "is used as a type");
5843: //halt();
5844: }
5845: else
5846: error(loc, "%s is used as a type", toChars());
5847: t = terror;
5848: }
5849: //t->print();
5850: return t;
5851: }
5852:
5853: Type *TypeIdentifier::reliesOnTident()
5854: {
5855: return this;
5856: }
5857:
5858: Expression *TypeIdentifier::toExpression()
5859: {
5860: Expression *e = new IdentifierExp(loc, ident);
5861: for (int i = 0; i < idents.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5862: {
5863: Identifier *id = idents.tdata()[i];
5864: e = new DotIdExp(loc, e, id);
5865: }
5866:
5867: return e;
5868: }
5869:
5870: /***************************** TypeInstance *****************************/
5871:
5872: TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst)
5873: : TypeQualified(Tinstance, loc)
5874: {
5875: this->tempinst = tempinst;
5876: }
5877:
5878: Type *TypeInstance::syntaxCopy()
5879: {
5880: //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim);
5881: TypeInstance *t;
5882:
5883: t = new TypeInstance(loc, (TemplateInstance *)tempinst->syntaxCopy(NULL));
5884: t->syntaxCopyHelper(this);
5885: t->mod = mod;
5886: return t;
5887: }
5888:
5889:
5890: void TypeInstance::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
5891: {
5892: if (mod != this->mod)
5893: { toCBuffer3(buf, hgs, mod);
5894: return;
5895: }
5896: tempinst->toCBuffer(buf, hgs);
5897: toCBuffer2Helper(buf, hgs);
5898: }
5899:
5900: void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
5901: {
5902: // Note close similarity to TypeIdentifier::resolve()
5903:
5904: Dsymbol *s;
5905:
5906: *pe = NULL;
5907: *pt = NULL;
5908: *ps = NULL;
5909:
5910: #if 0
5911: if (!idents.dim)
5912: {
5913: error(loc, "template instance '%s' has no identifier", toChars());
5914: return;
5915: }
5916: #endif
5917: //id = (Identifier *)idents.data[0];
5918: //printf("TypeInstance::resolve(sc = %p, idents = '%s')\n", sc, id->toChars());
5919: s = tempinst;
5920: if (s)
5921: s->semantic(sc);
5922: resolveHelper(loc, sc, s, NULL, pe, pt, ps);
5923: if (*pt)
5924: *pt = (*pt)->addMod(mod);
5925: //printf("pt = '%s'\n", (*pt)->toChars());
5926: }
5927:
5928: Type *TypeInstance::semantic(Loc loc, Scope *sc)
5929: {
5930: Type *t;
5931: Expression *e;
5932: Dsymbol *s;
5933:
5934: //printf("TypeInstance::semantic(%s)\n", toChars());
5935:
5936: if (sc->parameterSpecialization)
5937: {
5938: unsigned errors = global.errors;
5939: global.gag++;
5940:
5941: resolve(loc, sc, &e, &t, &s);
5942:
5943: global.gag--;
5944: if (errors != global.errors)
5945: { if (global.gag == 0)
5946: global.errors = errors;
5947: return this;
5948: }
5949: }
5950: else
5951: resolve(loc, sc, &e, &t, &s);
5952:
5953: if (!t)
5954: {
5955: error(loc, "%s is used as a type", toChars());
5956: t = terror;
5957: }
5958: return t;
5959: }
5960:
5961: Dsymbol *TypeInstance::toDsymbol(Scope *sc)
5962: {
5963: Type *t;
5964: Expression *e;
5965: Dsymbol *s;
5966:
5967: //printf("TypeInstance::semantic(%s)\n", toChars());
5968:
5969: if (sc->parameterSpecialization)
5970: {
5971: unsigned errors = global.errors;
5972: global.gag++;
5973:
5974: resolve(loc, sc, &e, &t, &s);
5975:
5976: global.gag--;
5977: if (errors != global.errors)
5978: { if (global.gag == 0)
5979: global.errors = errors;
5980: return NULL;
5981: }
5982: }
5983: else
5984: resolve(loc, sc, &e, &t, &s);
5985:
5986: return s;
5987: }
5988:
5989:
5990: /***************************** TypeTypeof *****************************/
5991:
5992: TypeTypeof::TypeTypeof(Loc loc, Expression *exp)
5993: : TypeQualified(Ttypeof, loc)
5994: {
5995: this->exp = exp;
5996: inuse = 0;
5997: }
5998:
5999: Type *TypeTypeof::syntaxCopy()
6000: {
6001: //printf("TypeTypeof::syntaxCopy() %s\n", toChars());
6002: TypeTypeof *t;
6003:
6004: t = new TypeTypeof(loc, exp->syntaxCopy());
6005: t->syntaxCopyHelper(this);
6006: t->mod = mod;
6007: return t;
6008: }
6009:
6010: Dsymbol *TypeTypeof::toDsymbol(Scope *sc)
6011: {
6012: Type *t;
6013:
6014: t = semantic(loc, sc);
6015: if (t == this)
6016: return NULL;
6017: return t->toDsymbol(sc);
6018: }
6019:
6020: void TypeTypeof::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
6021: {
6022: if (mod != this->mod)
6023: { toCBuffer3(buf, hgs, mod);
6024: return;
6025: }
6026: buf->writestring("typeof(");
6027: exp->toCBuffer(buf, hgs);
6028: buf->writeByte(')');
6029: toCBuffer2Helper(buf, hgs);
6030: }
6031:
6032: Type *TypeTypeof::semantic(Loc loc, Scope *sc)
6033: { Expression *e;
warning C4101: 'e' : unreferenced local variable
6034: Type *t;
6035:
6036: //printf("TypeTypeof::semantic() %s\n", toChars());
6037:
6038: //static int nest; if (++nest == 50) *(char*)0=0;
6039: if (inuse)
6040: {
6041: inuse = 2;
6042: error(loc, "circular typeof definition");
6043: return Type::terror;
6044: }
6045: inuse++;
6046:
6047: #if 0
6048: /* Special case for typeof(this) and typeof(super) since both
6049: * should work even if they are not inside a non-static member function
6050: */
6051: if (exp->op == TOKthis || exp->op == TOKsuper)
6052: {
6053: // Find enclosing struct or class
6054: for (Dsymbol *s = sc->parent; 1; s = s->parent)
6055: {
6056: ClassDeclaration *cd;
6057: StructDeclaration *sd;
6058:
6059: if (!s)
6060: {
6061: error(loc, "%s is not in a struct or class scope", exp->toChars());
6062: goto Lerr;
6063: }
6064: cd = s->isClassDeclaration();
6065: if (cd)
6066: {
6067: if (exp->op == TOKsuper)
6068: {
6069: cd = cd->baseClass;
6070: if (!cd)
6071: { error(loc, "class %s has no 'super'", s->toChars());
6072: goto Lerr;
6073: }
6074: }
6075: t = cd->type;
6076: break;
6077: }
6078: sd = s->isStructDeclaration();
6079: if (sd)
6080: {
6081: if (exp->op == TOKsuper)
6082: {
6083: error(loc, "struct %s has no 'super'", sd->toChars());
6084: goto Lerr;
6085: }
6086: t = sd->type->pointerTo();
6087: break;
6088: }
6089: }
6090: }
6091: else
6092: #endif
6093: {
6094: Scope *sc2 = sc->push();
6095: sc2->intypeof++;
6096: exp = exp->semantic(sc2);
6097: #if DMDV2
6098: if (exp->type && exp->type->ty == Tfunction &&
6099: ((TypeFunction *)exp->type)->isproperty)
6100: exp = resolveProperties(sc2, exp);
6101: #endif
6102: sc2->pop();
6103: if (exp->op == TOKtype)
6104: {
6105: error(loc, "argument %s to typeof is not an expression", exp->toChars());
6106: goto Lerr;
6107: }
6108: t = exp->type;
6109: if (!t)
6110: {
6111: error(loc, "expression (%s) has no type", exp->toChars());
6112: goto Lerr;
6113: }
6114: if (t->ty == Ttypeof)
6115: { error(loc, "forward reference to %s", toChars());
6116: goto Lerr;
6117: }
6118:
6119: /* typeof should reflect the true type,
6120: * not what 'auto' would have gotten us.
6121: */
6122: //t = t->toHeadMutable();
6123: }
6124: if (idents.dim)
6125: {
6126: Dsymbol *s = t->toDsymbol(sc);
6127: for (size_t i = 0; i < idents.dim; i++)
6128: {
6129: if (!s)
6130: break;
6131: Identifier *id = idents.tdata()[i];
6132: s = s->searchX(loc, sc, id);
6133: }
6134:
6135: if (s)
6136: {
6137: t = s->getType();
6138: if (!t)
6139: { error(loc, "%s is not a type", s->toChars());
6140: goto Lerr;
6141: }
6142: }
6143: else
6144: { error(loc, "cannot resolve .property for %s", toChars());
6145: goto Lerr;
6146: }
6147: }
6148: inuse--;
6149: return t;
6150:
6151: Lerr:
6152: inuse--;
6153: return terror;
6154: }
6155:
6156: d_uns64 TypeTypeof::size(Loc loc)
6157: {
6158: if (exp->type)
6159: return exp->type->size(loc);
6160: else
6161: return TypeQualified::size(loc);
6162: }
6163:
6164:
6165:
6166: /***************************** TypeReturn *****************************/
6167:
6168: TypeReturn::TypeReturn(Loc loc)
6169: : TypeQualified(Treturn, loc)
6170: {
6171: }
6172:
6173: Type *TypeReturn::syntaxCopy()
6174: {
6175: TypeReturn *t = new TypeReturn(loc);
6176: t->syntaxCopyHelper(this);
6177: t->mod = mod;
6178: return t;
6179: }
6180:
6181: Dsymbol *TypeReturn::toDsymbol(Scope *sc)
6182: {
6183: Type *t = semantic(0, sc);
6184: if (t == this)
6185: return NULL;
6186: return t->toDsymbol(sc);
6187: }
6188:
6189: Type *TypeReturn::semantic(Loc loc, Scope *sc)
6190: {
6191: Type *t;
6192: if (!sc->func)
6193: { error(loc, "typeof(return) must be inside function");
6194: goto Lerr;
6195: }
6196: t = sc->func->type->nextOf();
6197: if (!t)
6198: {
6199: error(loc, "cannot use typeof(return) inside function %s with inferred return type", sc->func->toChars());
6200: goto Lerr;
6201: }
6202: t = t->addMod(mod);
6203:
6204: if (idents.dim)
6205: {
6206: Dsymbol *s = t->toDsymbol(sc);
6207: for (size_t i = 0; i < idents.dim; i++)
6208: {
6209: if (!s)
6210: break;
6211: Identifier *id = idents.tdata()[i];
6212: s = s->searchX(loc, sc, id);
6213: }
6214: if (s)
6215: {
6216: t = s->getType();
6217: if (!t)
6218: { error(loc, "%s is not a type", s->toChars());
6219: goto Lerr;
6220: }
6221: }
6222: else
6223: { error(loc, "cannot resolve .property for %s", toChars());
6224: goto Lerr;
6225: }
6226: }
6227: return t;
6228:
6229: Lerr:
6230: return terror;
6231: }
6232:
6233: void TypeReturn::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
6234: {
6235: if (mod != this->mod)
6236: { toCBuffer3(buf, hgs, mod);
6237: return;
6238: }
6239: buf->writestring("typeof(return)");
6240: toCBuffer2Helper(buf, hgs);
6241: }
6242:
6243:
6244: /***************************** TypeEnum *****************************/
6245:
6246: TypeEnum::TypeEnum(EnumDeclaration *sym)
6247: : Type(Tenum)
6248: {
6249: this->sym = sym;
6250: }
6251:
6252: char *TypeEnum::toChars()
6253: {
6254: if (mod)
6255: return Type::toChars();
6256: return sym->toChars();
6257: }
6258:
6259: Type *TypeEnum::syntaxCopy()
6260: {
6261: return this;
6262: }
6263:
6264: Type *TypeEnum::semantic(Loc loc, Scope *sc)
6265: {
6266: //printf("TypeEnum::semantic() %s\n", toChars());
6267: //sym->semantic(sc);
6268: return merge();
6269: }
6270:
6271: d_uns64 TypeEnum::size(Loc loc)
6272: {
6273: if (!sym->memtype)
6274: {
6275: error(loc, "enum %s is forward referenced", sym->toChars());
6276: return 4;
6277: }
6278: return sym->memtype->size(loc);
6279: }
6280:
6281: unsigned TypeEnum::alignsize()
6282: {
6283: if (!sym->memtype)
6284: {
6285: #ifdef DEBUG
6286: printf("1: ");
6287: #endif
6288: error(0, "enum %s is forward referenced", sym->toChars());
6289: return 4;
6290: }
6291: return sym->memtype->alignsize();
6292: }
6293:
6294: Dsymbol *TypeEnum::toDsymbol(Scope *sc)
6295: {
6296: return sym;
6297: }
6298:
6299: Type *TypeEnum::toBasetype()
6300: {
6301: if (sym->scope)
6302: { // Enum is forward referenced. We don't need to resolve the whole thing,
6303: // just the base type
6304: if (sym->memtype)
6305: { sym->memtype = sym->memtype->semantic(sym->loc, sym->scope);
6306: }
6307: else
6308: { if (!sym->isAnonymous())
6309: sym->memtype = Type::tint32;
6310: }
6311: }
6312: if (!sym->memtype)
6313: {
6314: #ifdef DEBUG
6315: printf("2: ");
6316: #endif
6317: error(sym->loc, "enum %s is forward referenced", sym->toChars());
6318: return tint32;
6319: }
6320: return sym->memtype->toBasetype();
6321: }
6322:
6323: void TypeEnum::toDecoBuffer(OutBuffer *buf, int flag)
6324: {
6325: const char *name = sym->mangle();
6326: Type::toDecoBuffer(buf, flag);
6327: buf->printf("%s", name);
6328: }
6329:
6330: void TypeEnum::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
6331: {
6332: if (mod != this->mod)
6333: { toCBuffer3(buf, hgs, mod);
6334: return;
6335: }
6336: buf->writestring(sym->toChars());
6337: }
6338:
6339: Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident)
6340: {
6341: #if LOGDOTEXP
6342: printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars());
6343: #endif
6344: Dsymbol *s = sym->search(e->loc, ident, 0);
6345: if (!s)
6346: {
6347: if (ident == Id::max ||
6348: ident == Id::min ||
6349: ident == Id::init ||
6350: ident == Id::mangleof ||
6351: !sym->memtype
6352: )
6353: {
6354: return getProperty(e->loc, ident);
6355: }
6356: return sym->memtype->dotExp(sc, e, ident);
6357: }
6358: EnumMember *m = s->isEnumMember();
6359: Expression *em = m->value->copy();
6360: em->loc = e->loc;
6361: return em;
6362: }
6363:
6364: Expression *TypeEnum::getProperty(Loc loc, Identifier *ident)
6365: { Expression *e;
6366:
6367: if (ident == Id::max)
6368: {
6369: if (!sym->maxval)
6370: goto Lfwd;
6371: e = sym->maxval;
6372: }
6373: else if (ident == Id::min)
6374: {
6375: if (!sym->minval)
6376: goto Lfwd;
6377: e = sym->minval;
6378: }
6379: else if (ident == Id::init)
6380: {
6381: e = defaultInitLiteral(loc);
6382: }
6383: else if (ident == Id::stringof)
6384: { char *s = toChars();
6385: e = new StringExp(loc, s, strlen(s), 'c');
6386: Scope sc;
6387: e = e->semantic(&sc);
6388: }
6389: else if (ident == Id::mangleof)
6390: {
6391: e = Type::getProperty(loc, ident);
6392: }
6393: else
6394: {
6395: e = toBasetype()->getProperty(loc, ident);
6396: }
6397: return e;
6398:
6399: Lfwd:
6400: error(loc, "forward reference of %s.%s", toChars(), ident->toChars());
6401: return new ErrorExp();
6402: }
6403:
6404: int TypeEnum::isintegral()
6405: {
6406: return sym->memtype->isintegral();
6407: }
6408:
6409: int TypeEnum::isfloating()
6410: {
6411: return sym->memtype->isfloating();
6412: }
6413:
6414: int TypeEnum::isreal()
6415: {
6416: return sym->memtype->isreal();
6417: }
6418:
6419: int TypeEnum::isimaginary()
6420: {
6421: return sym->memtype->isimaginary();
6422: }
6423:
6424: int TypeEnum::iscomplex()
6425: {
6426: return sym->memtype->iscomplex();
6427: }
6428:
6429: int TypeEnum::isunsigned()
6430: {
6431: return sym->memtype->isunsigned();
6432: }
6433:
6434: int TypeEnum::isscalar()
6435: {
6436: return sym->memtype->isscalar();
6437: }
6438:
6439: int TypeEnum::isAssignable()
6440: {
6441: return sym->memtype->isAssignable();
6442: }
6443:
6444: int TypeEnum::checkBoolean()
6445: {
6446: return sym->memtype->checkBoolean();
6447: }
6448:
6449: int TypeEnum::needsDestruction()
6450: {
6451: return sym->memtype->needsDestruction();
6452: }
6453:
6454: MATCH TypeEnum::implicitConvTo(Type *to)
6455: { MATCH m;
6456:
6457: //printf("TypeEnum::implicitConvTo()\n");
6458: if (ty == to->ty && sym == ((TypeEnum *)to)->sym)
6459: m = (mod == to->mod) ? MATCHexact : MATCHconst;
6460: else if (sym->memtype->implicitConvTo(to))
6461: m = MATCHconvert; // match with conversions
6462: else
6463: m = MATCHnomatch; // no match
6464: return m;
6465: }
6466:
6467: MATCH TypeEnum::constConv(Type *to)
6468: {
6469: if (equals(to))
6470: return MATCHexact;
6471: if (ty == to->ty && sym == ((TypeEnum *)to)->sym &&
6472: MODimplicitConv(mod, to->mod))
6473: return MATCHconst;
6474: return MATCHnomatch;
6475: }
6476:
6477:
6478: Expression *TypeEnum::defaultInit(Loc loc)
6479: {
6480: #if LOGDEFAULTINIT
6481: printf("TypeEnum::defaultInit() '%s'\n", toChars());
6482: #endif
6483: // Initialize to first member of enum
6484: //printf("%s\n", sym->defaultval->type->toChars());
6485: if (!sym->defaultval)
6486: {
6487: error(loc, "forward reference of %s.init", toChars());
6488: return new ErrorExp();
6489: }
6490: return sym->defaultval;
6491: }
6492:
6493: int TypeEnum::isZeroInit(Loc loc)
6494: {
6495: if (!sym->defaultval && sym->scope)
6496: { // Enum is forward referenced. We need to resolve the whole thing.
6497: sym->semantic(NULL);
6498: }
6499: if (!sym->defaultval)
6500: {
6501: #ifdef DEBUG
6502: printf("3: ");
6503: #endif
6504: error(loc, "enum %s is forward referenced", sym->toChars());
6505: return 0;
6506: }
6507: return sym->defaultval->isBool(FALSE);
6508: }
6509:
6510: int TypeEnum::hasPointers()
6511: {
6512: return toBasetype()->hasPointers();
6513: }
6514:
6515: /***************************** TypeTypedef *****************************/
6516:
6517: TypeTypedef::TypeTypedef(TypedefDeclaration *sym)
6518: : Type(Ttypedef)
6519: {
6520: this->sym = sym;
6521: }
6522:
6523: Type *TypeTypedef::syntaxCopy()
6524: {
6525: return this;
6526: }
6527:
6528: char *TypeTypedef::toChars()
6529: {
6530: return Type::toChars();
6531: }
6532:
6533: Type *TypeTypedef::semantic(Loc loc, Scope *sc)
6534: {
6535: //printf("TypeTypedef::semantic(%s), sem = %d\n", toChars(), sym->sem);
6536: sym->semantic(sc);
6537: return merge();
6538: }
6539:
6540: d_uns64 TypeTypedef::size(Loc loc)
6541: {
6542: return sym->basetype->size(loc);
6543: }
6544:
6545: unsigned TypeTypedef::alignsize()
6546: {
6547: return sym->basetype->alignsize();
6548: }
6549:
6550: Dsymbol *TypeTypedef::toDsymbol(Scope *sc)
6551: {
6552: return sym;
6553: }
6554:
6555: Type *TypeTypedef::toHeadMutable()
6556: {
6557: if (!mod)
6558: return this;
6559:
6560: Type *tb = toBasetype();
6561: Type *t = tb->toHeadMutable();
6562: if (t->equals(tb))
6563: return this;
6564: else
6565: return mutableOf();
6566: }
6567:
6568: void TypeTypedef::toDecoBuffer(OutBuffer *buf, int flag)
6569: {
6570: Type::toDecoBuffer(buf, flag);
6571: const char *name = sym->mangle();
6572: buf->printf("%s", name);
6573: }
6574:
6575: void TypeTypedef::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
6576: {
6577: //printf("TypeTypedef::toCBuffer2() '%s'\n", sym->toChars());
6578: if (mod != this->mod)
6579: { toCBuffer3(buf, hgs, mod);
6580: return;
6581: }
6582: buf->writestring(sym->toChars());
6583: }
6584:
6585: Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident)
6586: {
6587: #if LOGDOTEXP
6588: printf("TypeTypedef::dotExp(e = '%s', ident = '%s') '%s'\n", e->toChars(), ident->toChars(), toChars());
6589: #endif
6590: if (ident == Id::init)
6591: {
6592: return Type::dotExp(sc, e, ident);
6593: }
6594: return sym->basetype->dotExp(sc, e, ident);
6595: }
6596:
6597: Expression *TypeTypedef::getProperty(Loc loc, Identifier *ident)
6598: {
6599: #if LOGDOTEXP
6600: printf("TypeTypedef::getProperty(ident = '%s') '%s'\n", ident->toChars(), toChars());
6601: #endif
6602: if (ident == Id::init)
6603: {
6604: return Type::getProperty(loc, ident);
6605: }
6606: return sym->basetype->getProperty(loc, ident);
6607: }
6608:
6609: int TypeTypedef::isintegral()
6610: {
6611: //printf("TypeTypedef::isintegral()\n");
6612: //printf("sym = '%s'\n", sym->toChars());
6613: //printf("basetype = '%s'\n", sym->basetype->toChars());
6614: return sym->basetype->isintegral();
6615: }
6616:
6617: int TypeTypedef::isfloating()
6618: {
6619: return sym->basetype->isfloating();
6620: }
6621:
6622: int TypeTypedef::isreal()
6623: {
6624: return sym->basetype->isreal();
6625: }
6626:
6627: int TypeTypedef::isimaginary()
6628: {
6629: return sym->basetype->isimaginary();
6630: }
6631:
6632: int TypeTypedef::iscomplex()
6633: {
6634: return sym->basetype->iscomplex();
6635: }
6636:
6637: int TypeTypedef::isunsigned()
6638: {
6639: return sym->basetype->isunsigned();
6640: }
6641:
6642: int TypeTypedef::isscalar()
6643: {
6644: return sym->basetype->isscalar();
6645: }
6646:
6647: int TypeTypedef::isAssignable()
6648: {
6649: return sym->basetype->isAssignable();
6650: }
6651:
6652: int TypeTypedef::checkBoolean()
6653: {
6654: return sym->basetype->checkBoolean();
6655: }
6656:
6657: int TypeTypedef::needsDestruction()
6658: {
6659: return sym->basetype->needsDestruction();
6660: }
6661:
6662: Type *TypeTypedef::toBasetype()
6663: {
6664: if (sym->inuse)
6665: {
6666: sym->error("circular definition");
6667: sym->basetype = Type::terror;
6668: return Type::terror;
6669: }
6670: sym->inuse = 1;
6671: Type *t = sym->basetype->toBasetype();
6672: sym->inuse = 0;
6673: t = t->addMod(mod);
6674: return t;
6675: }
6676:
6677: MATCH TypeTypedef::implicitConvTo(Type *to)
6678: { MATCH m;
6679:
6680: //printf("TypeTypedef::implicitConvTo(to = %s) %s\n", to->toChars(), toChars());
6681: if (equals(to))
6682: m = MATCHexact; // exact match
6683: else if (sym->basetype->implicitConvTo(to))
6684: m = MATCHconvert; // match with conversions
6685: else if (ty == to->ty && sym == ((TypeTypedef *)to)->sym)
6686: {
6687: m = constConv(to);
6688: }
6689: else
6690: m = MATCHnomatch; // no match
6691: return m;
6692: }
6693:
6694: MATCH TypeTypedef::constConv(Type *to)
6695: {
6696: if (equals(to))
6697: return MATCHexact;
6698: if (ty == to->ty && sym == ((TypeTypedef *)to)->sym)
6699: return sym->basetype->implicitConvTo(((TypeTypedef *)to)->sym->basetype);
6700: return MATCHnomatch;
6701: }
6702:
6703:
6704: Expression *TypeTypedef::defaultInit(Loc loc)
6705: {
6706: #if LOGDEFAULTINIT
6707: printf("TypeTypedef::defaultInit() '%s'\n", toChars());
6708: #endif
6709: if (sym->init)
6710: {
6711: //sym->init->toExpression()->print();
6712: return sym->init->toExpression();
6713: }
6714: Type *bt = sym->basetype;
6715: Expression *e = bt->defaultInit(loc);
6716: e->type = this;
6717: while (bt->ty == Tsarray)
6718: { TypeSArray *tsa = (TypeSArray *)bt;
6719: e->type = tsa->next;
6720: bt = tsa->next->toBasetype();
6721: }
6722: return e;
6723: }
6724:
6725: Expression *TypeTypedef::defaultInitLiteral(Loc loc)
6726: {
6727: #if LOGDEFAULTINIT
6728: printf("TypeTypedef::defaultInitLiteral() '%s'\n", toChars());
6729: #endif
6730: if (sym->init)
6731: {
6732: //sym->init->toExpression()->print();
6733: return sym->init->toExpression();
6734: }
6735: Type *bt = sym->basetype;
6736: Expression *e = bt->defaultInitLiteral(loc);
6737: e->type = this;
6738: return e;
6739: }
6740:
6741: int TypeTypedef::isZeroInit(Loc loc)
6742: {
6743: if (sym->init)
6744: {
6745: if (sym->init->isVoidInitializer())
6746: return 1; // initialize voids to 0
6747: Expression *e = sym->init->toExpression();
6748: if (e && e->isBool(FALSE))
6749: return 1;
6750: return 0; // assume not
6751: }
6752: if (sym->inuse)
6753: {
6754: sym->error("circular definition");
6755: sym->basetype = Type::terror;
6756: }
6757: sym->inuse = 1;
6758: int result = sym->basetype->isZeroInit(loc);
6759: sym->inuse = 0;
6760: return result;
6761: }
6762:
6763: int TypeTypedef::hasPointers()
6764: {
6765: return toBasetype()->hasPointers();
6766: }
6767:
6768: int TypeTypedef::hasWild()
6769: {
6770: return mod & MODwild || toBasetype()->hasWild();
6771: }
6772:
6773: /***************************** TypeStruct *****************************/
6774:
6775: TypeStruct::TypeStruct(StructDeclaration *sym)
6776: : Type(Tstruct)
6777: {
6778: this->sym = sym;
6779: }
6780:
6781: char *TypeStruct::toChars()
6782: {
6783: //printf("sym.parent: %s, deco = %s\n", sym->parent->toChars(), deco);
6784: if (mod)
6785: return Type::toChars();
6786: TemplateInstance *ti = sym->parent->isTemplateInstance();
6787: if (ti && ti->toAlias() == sym)
6788: {
6789: return ti->toChars();
6790: }
6791: return sym->toChars();
6792: }
6793:
6794: Type *TypeStruct::syntaxCopy()
6795: {
6796: return this;
6797: }
6798:
6799: Type *TypeStruct::semantic(Loc loc, Scope *sc)
6800: {
6801: //printf("TypeStruct::semantic('%s')\n", sym->toChars());
6802:
6803: /* Cannot do semantic for sym because scope chain may not
6804: * be right.
6805: */
6806: //sym->semantic(sc);
6807:
6808: return merge();
6809: }
6810:
6811: d_uns64 TypeStruct::size(Loc loc)
6812: {
6813: return sym->size(loc);
6814: }
6815:
6816: unsigned TypeStruct::alignsize()
6817: { unsigned sz;
6818:
6819: sym->size(0); // give error for forward references
6820: sz = sym->alignsize;
6821: if (sz > sym->structalign)
6822: sz = sym->structalign;
6823: return sz;
6824: }
6825:
6826: Dsymbol *TypeStruct::toDsymbol(Scope *sc)
6827: {
6828: return sym;
6829: }
6830:
6831: void TypeStruct::toDecoBuffer(OutBuffer *buf, int flag)
6832: {
6833: const char *name = sym->mangle();
6834: //printf("TypeStruct::toDecoBuffer('%s') = '%s'\n", toChars(), name);
6835: Type::toDecoBuffer(buf, flag);
6836: buf->printf("%s", name);
6837: }
6838:
6839: void TypeStruct::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
6840: {
6841: if (mod != this->mod)
6842: { toCBuffer3(buf, hgs, mod);
6843: return;
6844: }
6845: TemplateInstance *ti = sym->parent->isTemplateInstance();
6846: if (ti && ti->toAlias() == sym)
6847: buf->writestring(ti->toChars());
6848: else
6849: buf->writestring(sym->toChars());
6850: }
6851:
6852: Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
6853: { unsigned offset;
warning C4101: 'offset' : unreferenced local variable
6854:
6855: VarDeclaration *v;
6856: Dsymbol *s;
6857: DotVarExp *de;
6858: Declaration *d;
6859:
6860: #if LOGDOTEXP
6861: printf("TypeStruct::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
6862: #endif
6863: if (!sym->members)
6864: {
6865: error(e->loc, "struct %s is forward referenced", sym->toChars());
6866: return new ErrorExp();
6867: }
6868:
6869: /* If e.tupleof
6870: */
6871: if (ident == Id::tupleof)
6872: {
6873: /* Create a TupleExp out of the fields of the struct e:
6874: * (e.field0, e.field1, e.field2, ...)
6875: */
6876: e = e->semantic(sc); // do this before turning on noaccesscheck
6877: Expressions *exps = new Expressions;
6878: exps->reserve(sym->fields.dim);
6879: for (size_t i = 0; i < sym->fields.dim; i++)
6880: { VarDeclaration *v = sym->fields.tdata()[i];
warning C6246: Local declaration of 'v' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6855' of 'c:\projects\extern\d\dmd\src\mtype.c': Lines: 6855
6881: Expression *fe = new DotVarExp(e->loc, e, v);
6882: exps->push(fe);
6883: }
6884: e = new TupleExp(e->loc, exps);
6885: sc = sc->push();
6886: sc->noaccesscheck = 1;
6887: e = e->semantic(sc);
6888: sc->pop();
6889: return e;
6890: }
6891:
6892: if (e->op == TOKdotexp)
6893: { DotExp *de = (DotExp *)e;
warning C6246: Local declaration of 'de' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6857' of 'c:\projects\extern\d\dmd\src\mtype.c': Lines: 6857
6894:
6895: if (de->e1->op == TOKimport)
6896: {
6897: assert(0); // cannot find a case where this happens; leave
6898: // assert in until we do
6899: ScopeExp *se = (ScopeExp *)de->e1;
6900:
6901: s = se->sds->search(e->loc, ident, 0);
6902: e = de->e1;
6903: goto L1;
6904: }
6905: }
6906:
6907: s = sym->search(e->loc, ident, 0);
6908: L1:
6909: if (!s)
6910: {
6911: return noMember(sc, e, ident);
6912: }
6913: if (!s->isFuncDeclaration()) // because of overloading
6914: s->checkDeprecated(e->loc, sc);
6915: s = s->toAlias();
6916:
6917: v = s->isVarDeclaration();
6918: if (v && !v->isDataseg())
6919: {
6920: Expression *ei = v->getConstInitializer();
6921: if (ei)
6922: { e = ei->copy(); // need to copy it if it's a StringExp
6923: e = e->semantic(sc);
6924: return e;
6925: }
6926: }
6927:
6928: if (s->getType())
6929: {
6930: //return new DotTypeExp(e->loc, e, s);
6931: return new TypeExp(e->loc, s->getType());
6932: }
6933:
6934: EnumMember *em = s->isEnumMember();
6935: if (em)
6936: {
6937: assert(em->value);
6938: return em->value->copy();
6939: }
6940:
6941: TemplateMixin *tm = s->isTemplateMixin();
6942: if (tm)
6943: {
6944: Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
warning C6246: Local declaration of 'de' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6857' of 'c:\projects\extern\d\dmd\src\mtype.c': Lines: 6857
6945: de->type = e->type;
6946: return de;
6947: }
6948:
6949: TemplateDeclaration *td = s->isTemplateDeclaration();
6950: if (td)
6951: {
6952: e = new DotTemplateExp(e->loc, e, td);
6953: e->semantic(sc);
6954: return e;
6955: }
6956:
6957: TemplateInstance *ti = s->isTemplateInstance();
6958: if (ti)
6959: { if (!ti->semanticRun)
6960: {
6961: if (global.errors)
6962: return new ErrorExp(); // TemplateInstance::semantic() will fail anyway
6963: ti->semantic(sc);
6964: }
6965: s = ti->inst->toAlias();
6966: if (!s->isTemplateInstance())
6967: goto L1;
6968: Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
warning C6246: Local declaration of 'de' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6857' of 'c:\projects\extern\d\dmd\src\mtype.c': Lines: 6857
6969: de->type = e->type;
6970: return de;
6971: }
6972:
6973: Import *timp = s->isImport();
6974: if (timp)
6975: {
6976: e = new DsymbolExp(e->loc, s, 0);
6977: e = e->semantic(sc);
6978: return e;
6979: }
6980:
6981: OverloadSet *o = s->isOverloadSet();
6982: if (o)
6983: {
6984: OverExp *oe = new OverExp(o);
6985: if (e->op == TOKtype)
6986: return oe;
6987: return new DotExp(e->loc, e, oe);
6988: }
6989:
6990: d = s->isDeclaration();
6991: #ifdef DEBUG
6992: if (!d)
6993: printf("d = %s '%s'\n", s->kind(), s->toChars());
6994: #endif
6995: assert(d);
6996:
6997: if (e->op == TOKtype)
6998: { FuncDeclaration *fd = sc->func;
6999:
7000: if (d->isTupleDeclaration())
7001: {
7002: e = new TupleExp(e->loc, d->isTupleDeclaration());
7003: e = e->semantic(sc);
7004: return e;
7005: }
7006: if (d->needThis() && fd && fd->vthis)
7007: {
7008: e = new DotVarExp(e->loc, new ThisExp(e->loc), d);
7009: e = e->semantic(sc);
7010: return e;
7011: }
7012: return new VarExp(e->loc, d, 1);
7013: }
7014:
7015: if (d->isDataseg())
7016: {
7017: // (e, d)
7018: VarExp *ve;
7019:
7020: accessCheck(e->loc, sc, e, d);
7021: ve = new VarExp(e->loc, d);
7022: e = new CommaExp(e->loc, e, ve);
7023: e->type = d->type;
7024: return e;
7025: }
7026:
7027: if (v)
7028: {
7029: if (v->toParent() != sym)
7030: sym->error(e->loc, "'%s' is not a member", v->toChars());
7031:
7032: // *(&e + offset)
7033: accessCheck(e->loc, sc, e, d);
7034: #if 0
7035: Expression *b = new AddrExp(e->loc, e);
7036: b->type = e->type->pointerTo();
7037: b = new AddExp(e->loc, b, new IntegerExp(e->loc, v->offset, Type::tint32));
7038: b->type = v->type->pointerTo();
7039: b = new PtrExp(e->loc, b);
7040: b->type = v->type->addMod(e->type->mod);
7041: return b;
7042: #endif
7043: }
7044:
7045: de = new DotVarExp(e->loc, e, d);
7046: return de->semantic(sc);
7047: }
7048:
7049: unsigned TypeStruct::memalign(unsigned salign)
7050: {
7051: sym->size(0); // give error for forward references
7052: return sym->structalign;
7053: }
7054:
7055: Expression *TypeStruct::defaultInit(Loc loc)
7056: {
7057: #if LOGDEFAULTINIT
7058: printf("TypeStruct::defaultInit() '%s'\n", toChars());
7059: #endif
7060: Symbol *s = sym->toInitializer();
7061: Declaration *d = new SymbolDeclaration(sym->loc, s, sym);
7062: assert(d);
7063: d->type = this;
7064: return new VarExp(sym->loc, d);
7065: }
7066:
7067: /***************************************
7068: * Use when we prefer the default initializer to be a literal,
7069: * rather than a global immutable variable.
7070: */
7071: Expression *TypeStruct::defaultInitLiteral(Loc loc)
7072: {
7073: #if LOGDEFAULTINIT
7074: printf("TypeStruct::defaultInitLiteral() '%s'\n", toChars());
7075: #endif
7076: if (sym->isNested())
7077: return defaultInit(loc);
7078: Expressions *structelems = new Expressions();
7079: structelems->setDim(sym->fields.dim);
7080: for (size_t j = 0; j < structelems->dim; j++)
7081: {
7082: VarDeclaration *vd = sym->fields.tdata()[j];
7083: Expression *e;
7084: if (vd->init)
7085: { if (vd->init->isVoidInitializer())
7086: e = NULL;
7087: else
7088: e = vd->init->toExpression();
7089: }
7090: else
7091: e = vd->type->defaultInitLiteral();
7092: structelems->tdata()[j] = e;
7093: }
7094: StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems);
7095: // Why doesn't the StructLiteralExp constructor do this, when
7096: // sym->type != NULL ?
7097: structinit->type = sym->type;
7098: return structinit;
7099: }
7100:
7101:
7102: int TypeStruct::isZeroInit(Loc loc)
7103: {
7104: return sym->zeroInit;
7105: }
7106:
7107: int TypeStruct::checkBoolean()
7108: {
7109: return FALSE;
7110: }
7111:
7112: int TypeStruct::needsDestruction()
7113: {
7114: return sym->dtor != NULL;
7115: }
7116:
7117: int TypeStruct::isAssignable()
7118: {
7119: int assignable = TRUE;
7120: unsigned offset;
7121:
7122: /* If any of the fields are const or invariant,
7123: * then one cannot assign this struct.
7124: */
7125: for (size_t i = 0; i < sym->fields.dim; i++)
7126: { VarDeclaration *v = sym->fields.tdata()[i];
7127: //printf("%s [%d] v = (%s) %s, v->offset = %d, v->parent = %s", sym->toChars(), i, v->kind(), v->toChars(), v->offset, v->parent->kind());
7128: if (i == 0)
7129: ;
7130: else if (v->offset == offset)
7131: {
7132: /* If any fields of anonymous union are assignable,
7133: * then regard union as assignable.
7134: * This is to support unsafe things like Rebindable templates.
7135: */
7136: if (assignable)
7137: continue;
7138: }
7139: else
7140: {
7141: if (!assignable)
7142: return FALSE;
7143: }
7144: assignable = v->type->isMutable() && v->type->isAssignable();
7145: offset = v->offset;
7146: //printf(" -> assignable = %d\n", assignable);
7147: }
7148:
7149: return assignable;
7150: }
7151:
7152: int TypeStruct::hasPointers()
7153: {
7154: // Probably should cache this information in sym rather than recompute
7155: StructDeclaration *s = sym;
7156:
7157: sym->size(0); // give error for forward references
7158: for (size_t i = 0; i < s->fields.dim; i++)
7159: {
7160: Dsymbol *sm = s->fields.tdata()[i];
7161: Declaration *d = sm->isDeclaration();
7162: if (d->storage_class & STCref || d->hasPointers())
7163: return TRUE;
7164: }
7165: return FALSE;
7166: }
7167:
7168: static MATCH aliasthisConvTo(AggregateDeclaration *ad, Type *from, Type *to)
7169: {
7170: assert(ad->aliasthis);
7171: Declaration *d = ad->aliasthis->isDeclaration();
7172: if (d)
7173: { assert(d->type);
7174: Type *t = d->type;
7175: if (d->isVarDeclaration() && d->needThis())
7176: {
7177: t = t->addMod(from->mod);
7178: }
7179: else if (d->isFuncDeclaration())
7180: {
7181: FuncDeclaration *fd = (FuncDeclaration *)d;
7182: Expression *ethis = from->defaultInit(0);
7183: fd = fd->overloadResolve(0, ethis, NULL);
7184: if (fd)
7185: {
7186: t = ((TypeFunction *)fd->type)->next;
7187: }
7188: }
7189: MATCH m = t->implicitConvTo(to);
7190: return m;
7191: }
7192: return MATCHnomatch;
7193: }
7194:
7195: MATCH TypeStruct::implicitConvTo(Type *to)
7196: { MATCH m;
7197:
7198: //printf("TypeStruct::implicitConvTo(%s => %s)\n", toChars(), to->toChars());
7199: if (to->ty == Taarray)
7200: {
7201: /* If there is an error instantiating AssociativeArray!(), it shouldn't
7202: * be reported -- it just means implicit conversion is impossible.
7203: */
7204: ++global.gag;
7205: int errs = global.errors;
7206: to = ((TypeAArray*)to)->getImpl()->type;
7207: --global.gag;
7208: if (errs != global.errors)
7209: {
7210: global.errors = errs;
7211: return MATCHnomatch;
7212: }
7213: }
7214:
7215: if (ty == to->ty && sym == ((TypeStruct *)to)->sym)
7216: { m = MATCHexact; // exact match
7217: if (mod != to->mod)
7218: {
7219: if (MODimplicitConv(mod, to->mod))
7220: m = MATCHconst;
7221: else
7222: { /* Check all the fields. If they can all be converted,
7223: * allow the conversion.
7224: */
7225: for (int i = 0; i < sym->fields.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
7226: { Dsymbol *s = sym->fields.tdata()[i];
7227: VarDeclaration *v = s->isVarDeclaration();
7228: assert(v && v->storage_class & STCfield);
7229:
7230: // 'from' type
7231: Type *tvf = v->type->addMod(mod);
7232:
7233: // 'to' type
7234: Type *tv = v->type->castMod(to->mod);
7235:
7236: //printf("\t%s => %s, match = %d\n", v->type->toChars(), tv->toChars(), tvf->implicitConvTo(tv));
7237: if (tvf->implicitConvTo(tv) < MATCHconst)
7238: return MATCHnomatch;
7239: }
7240: m = MATCHconst;
7241: }
7242: }
7243: }
7244: else if (sym->aliasthis)
7245: m = aliasthisConvTo(sym, this, to);
7246: else
7247: m = MATCHnomatch; // no match
7248: return m;
7249: }
7250:
7251: Type *TypeStruct::toHeadMutable()
7252: {
7253: return this;
7254: }
7255:
7256: MATCH TypeStruct::constConv(Type *to)
7257: {
7258: if (equals(to))
7259: return MATCHexact;
7260: if (ty == to->ty && sym == ((TypeStruct *)to)->sym &&
7261: MODimplicitConv(mod, to->mod))
7262: return MATCHconst;
7263: return MATCHnomatch;
7264: }
7265:
7266:
7267: /***************************** TypeClass *****************************/
7268:
7269: TypeClass::TypeClass(ClassDeclaration *sym)
7270: : Type(Tclass)
7271: {
7272: this->sym = sym;
7273: }
7274:
7275: char *TypeClass::toChars()
7276: {
7277: if (mod)
7278: return Type::toChars();
7279: return (char *)sym->toPrettyChars();
7280: }
7281:
7282: Type *TypeClass::syntaxCopy()
7283: {
7284: return this;
7285: }
7286:
7287: Type *TypeClass::semantic(Loc loc, Scope *sc)
7288: {
7289: //printf("TypeClass::semantic(%s)\n", sym->toChars());
7290: if (deco)
7291: return this;
7292: //printf("\t%s\n", merge()->deco);
7293: return merge();
7294: }
7295:
7296: d_uns64 TypeClass::size(Loc loc)
7297: {
7298: return PTRSIZE;
7299: }
7300:
7301: Dsymbol *TypeClass::toDsymbol(Scope *sc)
7302: {
7303: return sym;
7304: }
7305:
7306: void TypeClass::toDecoBuffer(OutBuffer *buf, int flag)
7307: {
7308: const char *name = sym->mangle();
7309: //printf("TypeClass::toDecoBuffer('%s' flag=%d mod=%x) = '%s'\n", toChars(), flag, mod, name);
7310: Type::toDecoBuffer(buf, flag);
7311: buf->printf("%s", name);
7312: }
7313:
7314: void TypeClass::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
7315: {
7316: if (mod != this->mod)
7317: { toCBuffer3(buf, hgs, mod);
7318: return;
7319: }
7320: buf->writestring(sym->toChars());
7321: }
7322:
7323: Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
7324: { unsigned offset;
warning C4101: 'offset' : unreferenced local variable
7325:
7326: Expression *b;
warning C4101: 'b' : unreferenced local variable
7327: VarDeclaration *v;
7328: Dsymbol *s;
7329:
7330: #if LOGDOTEXP
7331: printf("TypeClass::dotExp(e='%s', ident='%s')\n", e->toChars(), ident->toChars());
7332: #endif
7333:
7334: if (e->op == TOKdotexp)
7335: { DotExp *de = (DotExp *)e;
7336:
7337: if (de->e1->op == TOKimport)
7338: {
7339: ScopeExp *se = (ScopeExp *)de->e1;
7340:
7341: s = se->sds->search(e->loc, ident, 0);
7342: e = de->e1;
7343: goto L1;
7344: }
7345: }
7346:
7347: if (ident == Id::tupleof)
7348: {
7349: /* Create a TupleExp
7350: */
7351: e = e->semantic(sc); // do this before turning on noaccesscheck
7352: Expressions *exps = new Expressions;
7353: exps->reserve(sym->fields.dim);
7354: for (size_t i = 0; i < sym->fields.dim; i++)
7355: { VarDeclaration *v = sym->fields.tdata()[i];
warning C6246: Local declaration of 'v' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '7327' of 'c:\projects\extern\d\dmd\src\mtype.c': Lines: 7327
7356: // Don't include hidden 'this' pointer
7357: if (v->isThisDeclaration())
7358: continue;
7359: Expression *fe = new DotVarExp(e->loc, e, v);
7360: exps->push(fe);
7361: }
7362: e = new TupleExp(e->loc, exps);
7363: sc = sc->push();
7364: sc->noaccesscheck = 1;
7365: e = e->semantic(sc);
7366: sc->pop();
7367: return e;
7368: }
7369:
7370: s = sym->search(e->loc, ident, 0);
7371: L1:
7372: if (!s)
7373: {
7374: // See if it's a base class
7375: ClassDeclaration *cbase;
7376: for (cbase = sym->baseClass; cbase; cbase = cbase->baseClass)
7377: {
7378: if (cbase->ident->equals(ident))
7379: {
7380: e = new DotTypeExp(0, e, cbase);
7381: return e;
7382: }
7383: }
7384:
7385: if (ident == Id::classinfo)
7386: {
7387: assert(ClassDeclaration::classinfo);
7388: Type *t = ClassDeclaration::classinfo->type;
7389: if (e->op == TOKtype || e->op == TOKdottype)
7390: {
7391: /* For type.classinfo, we know the classinfo
7392: * at compile time.
7393: */
7394: if (!sym->vclassinfo)
7395: sym->vclassinfo = new TypeInfoClassDeclaration(sym->type);
7396: e = new VarExp(e->loc, sym->vclassinfo);
7397: e = e->addressOf(sc);
7398: e->type = t; // do this so we don't get redundant dereference
7399: }
7400: else
7401: { /* For class objects, the classinfo reference is the first
7402: * entry in the vtbl[]
7403: */
7404: e = new PtrExp(e->loc, e);
7405: e->type = t->pointerTo();
7406: if (sym->isInterfaceDeclaration())
7407: {
7408: if (sym->isCPPinterface())
7409: { /* C++ interface vtbl[]s are different in that the
7410: * first entry is always pointer to the first virtual
7411: * function, not classinfo.
7412: * We can't get a .classinfo for it.
7413: */
7414: error(e->loc, "no .classinfo for C++ interface objects");
7415: }
7416: /* For an interface, the first entry in the vtbl[]
7417: * is actually a pointer to an instance of struct Interface.
7418: * The first member of Interface is the .classinfo,
7419: * so add an extra pointer indirection.
7420: */
7421: e->type = e->type->pointerTo();
7422: e = new PtrExp(e->loc, e);
7423: e->type = t->pointerTo();
7424: }
7425: e = new PtrExp(e->loc, e, t);
7426: }
7427: return e;
7428: }
7429:
7430: if (ident == Id::__vptr)
7431: { /* The pointer to the vtbl[]
7432: * *cast(invariant(void*)**)e
7433: */
7434: e = e->castTo(sc, tvoidptr->invariantOf()->pointerTo()->pointerTo());
7435: e = new PtrExp(e->loc, e);
7436: e = e->semantic(sc);
7437: return e;
7438: }
7439:
7440: if (ident == Id::__monitor)
7441: { /* The handle to the monitor (call it a void*)
7442: * *(cast(void**)e + 1)
7443: */
7444: e = e->castTo(sc, tvoidptr->pointerTo());
7445: e = new AddExp(e->loc, e, new IntegerExp(1));
7446: e = new PtrExp(e->loc, e);
7447: e = e->semantic(sc);
7448: return e;
7449: }
7450:
7451: if (ident == Id::typeinfo)
7452: {
7453: if (!global.params.useDeprecated)
7454: error(e->loc, ".typeinfo deprecated, use typeid(type)");
7455: return getTypeInfo(sc);
7456: }
7457: if (ident == Id::outer && sym->vthis)
7458: {
7459: s = sym->vthis;
7460: }
7461: else
7462: {
7463: return noMember(sc, e, ident);
7464: }
7465: }
7466: if (!s->isFuncDeclaration()) // because of overloading
7467: s->checkDeprecated(e->loc, sc);
7468: s = s->toAlias();
7469: v = s->isVarDeclaration();
7470: if (v && !v->isDataseg())
7471: { Expression *ei = v->getConstInitializer();
7472:
7473: if (ei)
7474: { e = ei->copy(); // need to copy it if it's a StringExp
7475: e = e->semantic(sc);
7476: return e;
7477: }
7478: }
7479:
7480: if (s->getType())
7481: {
7482: // if (e->op == TOKtype)
7483: return new TypeExp(e->loc, s->getType());
7484: // return new DotTypeExp(e->loc, e, s);
7485: }
7486:
7487: EnumMember *em = s->isEnumMember();
7488: if (em)
7489: {
7490: assert(em->value);
7491: return em->value->copy();
7492: }
7493:
7494: TemplateMixin *tm = s->isTemplateMixin();
7495: if (tm)
7496: {
7497: Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, tm));
7498: de->type = e->type;
7499: return de;
7500: }
7501:
7502: TemplateDeclaration *td = s->isTemplateDeclaration();
7503: if (td)
7504: {
7505: e = new DotTemplateExp(e->loc, e, td);
7506: e->semantic(sc);
7507: return e;
7508: }
7509:
7510: TemplateInstance *ti = s->isTemplateInstance();
7511: if (ti)
7512: { if (!ti->semanticRun)
7513: {
7514: if (global.errors)
7515: return new ErrorExp(); // TemplateInstance::semantic() will fail anyway
7516: ti->semantic(sc);
7517: }
7518: s = ti->inst->toAlias();
7519: if (!s->isTemplateInstance())
7520: goto L1;
7521: Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
7522: de->type = e->type;
7523: return de;
7524: }
7525:
7526: OverloadSet *o = s->isOverloadSet();
7527: if (o)
7528: {
7529: OverExp *oe = new OverExp(o);
7530: if (e->op == TOKtype)
7531: return oe;
7532: return new DotExp(e->loc, e, oe);
7533: }
7534:
7535: Declaration *d = s->isDeclaration();
7536: if (!d)
7537: {
7538: e->error("%s.%s is not a declaration", e->toChars(), ident->toChars());
7539: return new ErrorExp();
7540: }
7541:
7542: if (e->op == TOKtype)
7543: {
7544: /* It's:
7545: * Class.d
7546: */
7547: if (d->isTupleDeclaration())
7548: {
7549: e = new TupleExp(e->loc, d->isTupleDeclaration());
7550: e = e->semantic(sc);
7551: return e;
7552: }
7553: else if (d->needThis() && (hasThis(sc) || !(sc->intypeof || d->isFuncDeclaration())))
7554: {
7555: if (sc->func)
7556: {
7557: ClassDeclaration *thiscd;
7558: thiscd = sc->func->toParent()->isClassDeclaration();
7559:
7560: if (thiscd)
7561: {
7562: ClassDeclaration *cd = e->type->isClassHandle();
7563:
7564: if (cd == thiscd)
7565: {
7566: e = new ThisExp(e->loc);
7567: e = new DotTypeExp(e->loc, e, cd);
7568: DotVarExp *de = new DotVarExp(e->loc, e, d);
7569: e = de->semantic(sc);
7570: return e;
7571: }
7572: else if ((!cd || !cd->isBaseOf(thiscd, NULL)) &&
7573: !d->isFuncDeclaration())
7574: e->error("'this' is required, but %s is not a base class of %s", e->type->toChars(), thiscd->toChars());
7575: }
7576: }
7577:
7578: /* Rewrite as:
7579: * this.d
7580: */
7581: DotVarExp *de = new DotVarExp(e->loc, new ThisExp(e->loc), d);
7582: e = de->semantic(sc);
7583: return e;
7584: }
7585: else
7586: {
7587: VarExp *ve = new VarExp(e->loc, d, 1);
7588: return ve;
7589: }
7590: }
7591:
7592: if (d->isDataseg())
7593: {
7594: // (e, d)
7595: VarExp *ve;
7596:
7597: accessCheck(e->loc, sc, e, d);
7598: ve = new VarExp(e->loc, d);
7599: e = new CommaExp(e->loc, e, ve);
7600: e->type = d->type;
7601: return e;
7602: }
7603:
7604: if (d->parent && d->toParent()->isModule())
7605: {
7606: // (e, d)
7607:
7608: VarExp *ve = new VarExp(e->loc, d, 1);
7609: e = new CommaExp(e->loc, e, ve);
7610: e->type = d->type;
7611: return e;
7612: }
7613:
7614: DotVarExp *de = new DotVarExp(e->loc, e, d);
7615: return de->semantic(sc);
7616: }
7617:
7618: ClassDeclaration *TypeClass::isClassHandle()
7619: {
7620: return sym;
7621: }
7622:
7623: int TypeClass::isscope()
7624: {
7625: return sym->isscope;
7626: }
7627:
7628: int TypeClass::isBaseOf(Type *t, int *poffset)
7629: {
7630: if (t->ty == Tclass)
7631: { ClassDeclaration *cd;
7632:
7633: cd = ((TypeClass *)t)->sym;
7634: if (sym->isBaseOf(cd, poffset))
7635: return 1;
7636: }
7637: return 0;
7638: }
7639:
7640: MATCH TypeClass::implicitConvTo(Type *to)
7641: {
7642: //printf("TypeClass::implicitConvTo(to = '%s') %s\n", to->toChars(), toChars());
7643: MATCH m = constConv(to);
7644: if (m != MATCHnomatch)
7645: return m;
7646:
7647: ClassDeclaration *cdto = to->isClassHandle();
7648: if (cdto && cdto->isBaseOf(sym, NULL))
7649: { //printf("'to' is base\n");
7650: return MATCHconvert;
7651: }
7652:
7653: if (global.params.Dversion == 1)
7654: {
7655: // Allow conversion to (void *)
7656: if (to->ty == Tpointer && ((TypePointer *)to)->next->ty == Tvoid)
7657: return MATCHconvert;
7658: }
7659:
7660: m = MATCHnomatch;
7661: if (sym->aliasthis)
7662: m = aliasthisConvTo(sym, this, to);
7663:
7664: return m;
7665: }
7666:
7667: MATCH TypeClass::constConv(Type *to)
7668: {
7669: if (equals(to))
7670: return MATCHexact;
7671: if (ty == to->ty && sym == ((TypeClass *)to)->sym &&
7672: MODimplicitConv(mod, to->mod))
7673: return MATCHconst;
7674: return MATCHnomatch;
7675: }
7676:
7677: Type *TypeClass::toHeadMutable()
7678: {
7679: return this;
7680: }
7681:
7682: Expression *TypeClass::defaultInit(Loc loc)
7683: {
7684: #if LOGDEFAULTINIT
7685: printf("TypeClass::defaultInit() '%s'\n", toChars());
7686: #endif
7687: return new NullExp(loc, this);
7688: }
7689:
7690: int TypeClass::isZeroInit(Loc loc)
7691: {
7692: return 1;
7693: }
7694:
7695: int TypeClass::checkBoolean()
7696: {
7697: return TRUE;
7698: }
7699:
7700: int TypeClass::hasPointers()
7701: {
7702: return TRUE;
7703: }
7704:
7705: /***************************** TypeTuple *****************************/
7706:
7707: TypeTuple::TypeTuple(Parameters *arguments)
7708: : Type(Ttuple)
7709: {
7710: //printf("TypeTuple(this = %p)\n", this);
7711: this->arguments = arguments;
7712: //printf("TypeTuple() %p, %s\n", this, toChars());
7713: #ifdef DEBUG
7714: if (arguments)
7715: {
7716: for (size_t i = 0; i < arguments->dim; i++)
7717: {
7718: Parameter *arg = arguments->tdata()[i];
7719: assert(arg && arg->type);
7720: }
7721: }
7722: #endif
7723: }
7724:
7725: /****************
7726: * Form TypeTuple from the types of the expressions.
7727: * Assume exps[] is already tuple expanded.
7728: */
7729:
7730: TypeTuple::TypeTuple(Expressions *exps)
7731: : Type(Ttuple)
7732: {
7733: Parameters *arguments = new Parameters;
warning C6211: Leaking memory '*this[56]' due to an exception. Consider using a local catch block to clean up memory: Lines: 7731, 7732, 7733, 7734, 7736, 7737, 7738, 7739, 7741
7734: if (exps)
7735: {
7736: arguments->setDim(exps->dim);
7737: for (size_t i = 0; i < exps->dim; i++)
7738: { Expression *e = exps->tdata()[i];
7739: if (e->type->ty == Ttuple)
7740: e->error("cannot form tuple of tuples");
7741: Parameter *arg = new Parameter(STCundefined, e->type, NULL, NULL);
7742: arguments->tdata()[i] = arg;
7743: }
7744: }
7745: this->arguments = arguments;
7746: //printf("TypeTuple() %p, %s\n", this, toChars());
7747: }
7748:
7749: /*******************************************
7750: * Type tuple with 0, 1 or 2 types in it.
7751: */
7752: TypeTuple::TypeTuple()
7753: : Type(Ttuple)
7754: {
7755: arguments = new Parameters();
7756: }
7757:
7758: TypeTuple::TypeTuple(Type *t1)
7759: : Type(Ttuple)
7760: {
7761: arguments = new Parameters();
7762: arguments->push(new Parameter(0, t1, NULL, NULL));
7763: }
7764:
7765: TypeTuple::TypeTuple(Type *t1, Type *t2)
7766: : Type(Ttuple)
7767: {
7768: arguments = new Parameters();
7769: arguments->push(new Parameter(0, t1, NULL, NULL));
7770: arguments->push(new Parameter(0, t2, NULL, NULL));
7771: }
7772:
7773: Type *TypeTuple::syntaxCopy()
7774: {
7775: Parameters *args = Parameter::arraySyntaxCopy(arguments);
7776: Type *t = new TypeTuple(args);
7777: t->mod = mod;
7778: return t;
7779: }
7780:
7781: Type *TypeTuple::semantic(Loc loc, Scope *sc)
7782: {
7783: //printf("TypeTuple::semantic(this = %p)\n", this);
7784: //printf("TypeTuple::semantic() %p, %s\n", this, toChars());
7785: if (!deco)
7786: deco = merge()->deco;
7787:
7788: /* Don't return merge(), because a tuple with one type has the
7789: * same deco as that type.
7790: */
7791: return this;
7792: }
7793:
7794: int TypeTuple::equals(Object *o)
7795: { Type *t;
7796:
7797: t = (Type *)o;
7798: //printf("TypeTuple::equals(%s, %s)\n", toChars(), t->toChars());
7799: if (this == t)
7800: {
7801: return 1;
7802: }
7803: if (t->ty == Ttuple)
7804: { TypeTuple *tt = (TypeTuple *)t;
7805:
7806: if (arguments->dim == tt->arguments->dim)
7807: {
7808: for (size_t i = 0; i < tt->arguments->dim; i++)
7809: { Parameter *arg1 = arguments->tdata()[i];
7810: Parameter *arg2 = tt->arguments->tdata()[i];
7811:
7812: if (!arg1->type->equals(arg2->type))
7813: return 0;
7814: }
7815: return 1;
7816: }
7817: }
7818: return 0;
7819: }
7820:
7821: Type *TypeTuple::reliesOnTident()
7822: {
7823: if (arguments)
7824: {
7825: for (size_t i = 0; i < arguments->dim; i++)
7826: {
7827: Parameter *arg = arguments->tdata()[i];
7828: Type *t = arg->type->reliesOnTident();
7829: if (t)
7830: return t;
7831: }
7832: }
7833: return NULL;
7834: }
7835:
7836: #if 0
7837: Type *TypeTuple::makeConst()
7838: {
7839: //printf("TypeTuple::makeConst() %s\n", toChars());
7840: if (cto)
7841: return cto;
7842: TypeTuple *t = (TypeTuple *)Type::makeConst();
7843: t->arguments = new Parameters();
7844: t->arguments->setDim(arguments->dim);
7845: for (size_t i = 0; i < arguments->dim; i++)
7846: { Parameter *arg = arguments->tdata()[i];
7847: Parameter *narg = new Parameter(arg->storageClass, arg->type->constOf(), arg->ident, arg->defaultArg);
7848: t->arguments->tdata()[i] = (Parameter *)narg;
7849: }
7850: return t;
7851: }
7852: #endif
7853:
7854: void TypeTuple::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
7855: {
7856: Parameter::argsToCBuffer(buf, hgs, arguments, 0);
7857: }
7858:
7859: void TypeTuple::toDecoBuffer(OutBuffer *buf, int flag)
7860: {
7861: //printf("TypeTuple::toDecoBuffer() this = %p, %s\n", this, toChars());
7862: Type::toDecoBuffer(buf, flag);
7863: OutBuffer buf2;
7864: Parameter::argsToDecoBuffer(&buf2, arguments);
7865: unsigned len = buf2.offset;
7866: buf->printf("%d%.*s", len, len, (char *)buf2.extractData());
7867: }
7868:
7869: Expression *TypeTuple::getProperty(Loc loc, Identifier *ident)
7870: { Expression *e;
7871:
7872: #if LOGDOTEXP
7873: printf("TypeTuple::getProperty(type = '%s', ident = '%s')\n", toChars(), ident->toChars());
7874: #endif
7875: if (ident == Id::length)
7876: {
7877: e = new IntegerExp(loc, arguments->dim, Type::tsize_t);
7878: }
7879: else
7880: {
7881: error(loc, "no property '%s' for tuple '%s'", ident->toChars(), toChars());
7882: e = new ErrorExp();
7883: }
7884: return e;
7885: }
7886:
7887: /***************************** TypeSlice *****************************/
7888:
7889: /* This is so we can slice a TypeTuple */
7890:
7891: TypeSlice::TypeSlice(Type *next, Expression *lwr, Expression *upr)
7892: : TypeNext(Tslice, next)
7893: {
7894: //printf("TypeSlice[%s .. %s]\n", lwr->toChars(), upr->toChars());
7895: this->lwr = lwr;
7896: this->upr = upr;
7897: }
7898:
7899: Type *TypeSlice::syntaxCopy()
7900: {
7901: Type *t = new TypeSlice(next->syntaxCopy(), lwr->syntaxCopy(), upr->syntaxCopy());
7902: t->mod = mod;
7903: return t;
7904: }
7905:
7906: Type *TypeSlice::semantic(Loc loc, Scope *sc)
7907: {
7908: //printf("TypeSlice::semantic() %s\n", toChars());
7909: next = next->semantic(loc, sc);
7910: transitive();
7911: //printf("next: %s\n", next->toChars());
7912:
7913: Type *tbn = next->toBasetype();
7914: if (tbn->ty != Ttuple)
7915: { error(loc, "can only slice tuple types, not %s", tbn->toChars());
7916: return Type::terror;
7917: }
7918: TypeTuple *tt = (TypeTuple *)tbn;
7919:
7920: lwr = semanticLength(sc, tbn, lwr);
7921: lwr = lwr->optimize(WANTvalue | WANTinterpret);
7922: uinteger_t i1 = lwr->toUInteger();
7923:
7924: upr = semanticLength(sc, tbn, upr);
7925: upr = upr->optimize(WANTvalue | WANTinterpret);
7926: uinteger_t i2 = upr->toUInteger();
7927:
7928: if (!(i1 <= i2 && i2 <= tt->arguments->dim))
7929: { error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, tt->arguments->dim);
7930: return Type::terror;
7931: }
7932:
7933: Parameters *args = new Parameters;
7934: args->reserve(i2 - i1);
warning C4244: 'argument' : conversion from 'uinteger_t' to 'unsigned int', possible loss of data
7935: for (size_t i = i1; i < i2; i++)
warning C4244: 'initializing' : conversion from 'uinteger_t' to 'size_t', possible loss of data
7936: { Parameter *arg = tt->arguments->tdata()[i];
7937: args->push(arg);
7938: }
7939:
7940: Type *t = (new TypeTuple(args))->semantic(loc, sc);
7941: return t;
7942: }
7943:
7944: void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
7945: {
7946: next->resolve(loc, sc, pe, pt, ps);
7947: if (*pe)
7948: { // It's really a slice expression
7949: Expression *e;
7950: e = new SliceExp(loc, *pe, lwr, upr);
7951: *pe = e;
7952: }
7953: else if (*ps)
7954: { Dsymbol *s = *ps;
7955: TupleDeclaration *td = s->isTupleDeclaration();
7956: if (td)
7957: {
7958: /* It's a slice of a TupleDeclaration
7959: */
7960: ScopeDsymbol *sym = new ArrayScopeSymbol(sc, td);
7961: sym->parent = sc->scopesym;
7962: sc = sc->push(sym);
7963:
7964: lwr = lwr->semantic(sc);
7965: lwr = lwr->optimize(WANTvalue | WANTinterpret);
7966: uinteger_t i1 = lwr->toUInteger();
7967:
7968: upr = upr->semantic(sc);
7969: upr = upr->optimize(WANTvalue | WANTinterpret);
7970: uinteger_t i2 = upr->toUInteger();
7971:
7972: sc = sc->pop();
7973:
7974: if (!(i1 <= i2 && i2 <= td->objects->dim))
7975: { error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, td->objects->dim);
7976: goto Ldefault;
7977: }
7978:
7979: if (i1 == 0 && i2 == td->objects->dim)
7980: {
7981: *ps = td;
7982: return;
7983: }
7984:
7985: /* Create a new TupleDeclaration which
7986: * is a slice [i1..i2] out of the old one.
7987: */
7988: Objects *objects = new Objects;
7989: objects->setDim(i2 - i1);
warning C4244: 'argument' : conversion from 'uinteger_t' to 'unsigned int', possible loss of data
7990: for (size_t i = 0; i < objects->dim; i++)
7991: {
7992: objects->tdata()[i] = td->objects->tdata()[(size_t)i1 + i];
7993: }
7994:
7995: TupleDeclaration *tds = new TupleDeclaration(loc, td->ident, objects);
7996: *ps = tds;
7997: }
7998: else
7999: goto Ldefault;
8000: }
8001: else
8002: {
8003: Ldefault:
8004: Type::resolve(loc, sc, pe, pt, ps);
8005: }
8006: }
8007:
8008: void TypeSlice::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
8009: {
8010: if (mod != this->mod)
8011: { toCBuffer3(buf, hgs, mod);
8012: return;
8013: }
8014: next->toCBuffer2(buf, hgs, this->mod);
8015:
8016: buf->printf("[%s .. ", lwr->toChars());
8017: buf->printf("%s]", upr->toChars());
8018: }
8019:
8020: /***************************** Parameter *****************************/
8021:
8022: Parameter::Parameter(StorageClass storageClass, Type *type, Identifier *ident, Expression *defaultArg)
8023: {
8024: this->type = type;
8025: this->ident = ident;
8026: this->storageClass = storageClass;
8027: this->defaultArg = defaultArg;
8028: }
8029:
8030: Parameter *Parameter::syntaxCopy()
8031: {
8032: Parameter *a = new Parameter(storageClass,
8033: type ? type->syntaxCopy() : NULL,
8034: ident,
8035: defaultArg ? defaultArg->syntaxCopy() : NULL);
8036: return a;
8037: }
8038:
8039: Parameters *Parameter::arraySyntaxCopy(Parameters *args)
8040: { Parameters *a = NULL;
8041:
8042: if (args)
8043: {
8044: a = new Parameters();
8045: a->setDim(args->dim);
8046: for (size_t i = 0; i < a->dim; i++)
8047: { Parameter *arg = args->tdata()[i];
8048:
8049: arg = arg->syntaxCopy();
8050: a->tdata()[i] = arg;
8051: }
8052: }
8053: return a;
8054: }
8055:
8056: char *Parameter::argsTypesToChars(Parameters *args, int varargs)
8057: {
8058: OutBuffer *buf = new OutBuffer();
8059:
8060: #if 1
8061: HdrGenState hgs;
8062: argsToCBuffer(buf, &hgs, args, varargs);
8063: #else
8064: buf->writeByte('(');
8065: if (args)
8066: { OutBuffer argbuf;
8067: HdrGenState hgs;
8068:
8069: for (int i = 0; i < args->dim; i++)
8070: { if (i)
8071: buf->writeByte(',');
8072: Parameter *arg = args->tdata()[i];
8073: argbuf.reset();
8074: arg->type->toCBuffer2(&argbuf, &hgs, 0);
8075: buf->write(&argbuf);
8076: }
8077: if (varargs)
8078: {
8079: if (i && varargs == 1)
8080: buf->writeByte(',');
8081: buf->writestring("...");
8082: }
8083: }
8084: buf->writeByte(')');
8085: #endif
8086: return buf->toChars();
8087: }
8088:
8089: void Parameter::argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Parameters *arguments, int varargs)
8090: {
8091: buf->writeByte('(');
8092: if (arguments)
8093: { int i;
8094: OutBuffer argbuf;
8095:
8096: for (i = 0; i < arguments->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
8097: {
8098: if (i)
8099: buf->writestring(", ");
8100: Parameter *arg = arguments->tdata()[i];
8101:
8102: if (arg->storageClass & STCauto)
8103: buf->writestring("auto ");
8104:
8105: if (arg->storageClass & STCout)
8106: buf->writestring("out ");
8107: else if (arg->storageClass & STCref)
8108: buf->writestring((global.params.Dversion == 1)
8109: ? "inout " : "ref ");
8110: else if (arg->storageClass & STCin)
8111: buf->writestring("in ");
8112: else if (arg->storageClass & STClazy)
8113: buf->writestring("lazy ");
8114: else if (arg->storageClass & STCalias)
8115: buf->writestring("alias ");
8116:
8117: StorageClass stc = arg->storageClass;
8118: if (arg->type && arg->type->mod & MODshared)
8119: stc &= ~STCshared;
8120:
8121: StorageClassDeclaration::stcToCBuffer(buf,
8122: stc & (STCconst | STCimmutable | STCshared | STCscope));
8123:
8124: argbuf.reset();
8125: if (arg->storageClass & STCalias)
8126: { if (arg->ident)
8127: argbuf.writestring(arg->ident->toChars());
8128: }
8129: else
8130: arg->type->toCBuffer(&argbuf, arg->ident, hgs);
warning C6011: Dereferencing NULL pointer 'arg->type': Lines: 8091, 8092, 8093, 8094, 8096, 8098, 8100, 8102, 8103, 8105, 8106, 8117, 8118, 8121, 8124, 8125, 8126, 8127, 8131, 8133, 8134, 8136, 8096, 8098, 8099, 8100, 8102, 8103, 8105, 8106, 8117, 8118, 8121, 8124, 8125, 8130
8131: if (arg->defaultArg)
8132: {
8133: argbuf.writestring(" = ");
8134: arg->defaultArg->toCBuffer(&argbuf, hgs);
8135: }
8136: buf->write(&argbuf);
8137: }
8138: if (varargs)
8139: {
8140: if (i && varargs == 1)
8141: buf->writeByte(',');
8142: buf->writestring("...");
8143: }
8144: }
8145: buf->writeByte(')');
8146: }
8147:
8148:
8149: void Parameter::argsToDecoBuffer(OutBuffer *buf, Parameters *arguments)
8150: {
8151: //printf("Parameter::argsToDecoBuffer()\n");
8152:
8153: // Write argument types
8154: if (arguments)
8155: {
8156: size_t dim = Parameter::dim(arguments);
8157: for (size_t i = 0; i < dim; i++)
8158: {
8159: Parameter *arg = Parameter::getNth(arguments, i);
8160: arg->toDecoBuffer(buf);
8161: }
8162: }
8163: }
8164:
8165:
8166: /****************************************
8167: * Determine if parameter list is really a template parameter list
8168: * (i.e. it has auto or alias parameters)
8169: */
8170:
8171: int Parameter::isTPL(Parameters *arguments)
8172: {
8173: //printf("Parameter::isTPL()\n");
8174:
8175: if (arguments)
8176: {
8177: size_t dim = Parameter::dim(arguments);
8178: for (size_t i = 0; i < dim; i++)
8179: {
8180: Parameter *arg = Parameter::getNth(arguments, i);
8181: if (arg->storageClass & (STCalias | STCauto | STCstatic))
8182: return 1;
8183: }
8184: }
8185: return 0;
8186: }
8187:
8188: /****************************************************
8189: * Determine if parameter is a lazy array of delegates.
8190: * If so, return the return type of those delegates.
8191: * If not, return NULL.
8192: */
8193:
8194: Type *Parameter::isLazyArray()
8195: {
8196: // if (inout == Lazy)
8197: {
8198: Type *tb = type->toBasetype();
8199: if (tb->ty == Tsarray || tb->ty == Tarray)
8200: {
8201: Type *tel = ((TypeArray *)tb)->next->toBasetype();
8202: if (tel->ty == Tdelegate)
8203: {
8204: TypeDelegate *td = (TypeDelegate *)tel;
8205: TypeFunction *tf = (TypeFunction *)td->next;
8206:
8207: if (!tf->varargs && Parameter::dim(tf->parameters) == 0)
8208: {
8209: return tf->next; // return type of delegate
8210: }
8211: }
8212: }
8213: }
8214: return NULL;
8215: }
8216:
8217: void Parameter::toDecoBuffer(OutBuffer *buf)
8218: {
8219: if (storageClass & STCscope)
8220: buf->writeByte('M');
8221: switch (storageClass & (STCin | STCout | STCref | STClazy))
8222: { case 0:
8223: case STCin:
8224: break;
8225: case STCout:
8226: buf->writeByte('J');
8227: break;
8228: case STCref:
8229: buf->writeByte('K');
8230: break;
8231: case STClazy:
8232: buf->writeByte('L');
8233: break;
8234: default:
8235: #ifdef DEBUG
8236: halt();
8237: #endif
8238: assert(0);
8239: }
8240: #if 0
8241: int mod = 0x100;
8242: if (type->toBasetype()->ty == Tclass)
8243: mod = 0;
8244: type->toDecoBuffer(buf, mod);
8245: #else
8246: //type->toHeadMutable()->toDecoBuffer(buf, 0);
8247: type->toDecoBuffer(buf, 0);
8248: #endif
8249: }
8250:
8251: /***************************************
8252: * Determine number of arguments, folding in tuples.
8253: */
8254:
8255: size_t Parameter::dim(Parameters *args)
8256: {
8257: size_t n = 0;
8258: if (args)
8259: {
8260: for (size_t i = 0; i < args->dim; i++)
8261: { Parameter *arg = args->tdata()[i];
8262: Type *t = arg->type->toBasetype();
8263:
8264: if (t->ty == Ttuple)
8265: { TypeTuple *tu = (TypeTuple *)t;
8266: n += dim(tu->arguments);
8267: }
8268: else
8269: n++;
8270: }
8271: }
8272: return n;
8273: }
8274:
8275: /***************************************
8276: * Get nth Parameter, folding in tuples.
8277: * Returns:
8278: * Parameter* nth Parameter
8279: * NULL not found, *pn gets incremented by the number
8280: * of Parameters
8281: */
8282:
8283: Parameter *Parameter::getNth(Parameters *args, size_t nth, size_t *pn)
8284: {
8285: if (!args)
8286: return NULL;
8287:
8288: size_t n = 0;
8289: for (size_t i = 0; i < args->dim; i++)
8290: { Parameter *arg = args->tdata()[i];
8291: Type *t = arg->type->toBasetype();
8292:
8293: if (t->ty == Ttuple)
8294: { TypeTuple *tu = (TypeTuple *)t;
8295: arg = getNth(tu->arguments, nth - n, &n);
8296: if (arg)
8297: return arg;
8298: }
8299: else if (n == nth)
8300: return arg;
8301: else
8302: n++;
8303: }
8304:
8305: if (pn)
8306: *pn += n;
8307: return NULL;
8308: }
8309: