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