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