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