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