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