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