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