Mercurial > projects > ldc
annotate dmd/init.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 | 8026319762be |
rev | line source |
---|---|
336 | 1 |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2008 by Digital Mars | |
4 // All Rights Reserved | |
5 // written by Walter Bright | |
6 // http://www.digitalmars.com | |
7 // License for redistribution is by either the Artistic License | |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
9 // See the included readme.txt for details. | |
10 | |
11 #include <stdio.h> | |
12 #include <assert.h> | |
13 | |
14 #include "mars.h" | |
15 #include "init.h" | |
16 #include "expression.h" | |
17 #include "statement.h" | |
18 #include "identifier.h" | |
19 #include "declaration.h" | |
20 #include "aggregate.h" | |
21 #include "scope.h" | |
22 #include "mtype.h" | |
23 #include "hdrgen.h" | |
24 | |
25 /********************************** Initializer *******************************/ | |
26 | |
27 Initializer::Initializer(Loc loc) | |
28 { | |
29 this->loc = loc; | |
30 } | |
31 | |
32 Initializer *Initializer::syntaxCopy() | |
33 { | |
34 return this; | |
35 } | |
36 | |
37 Initializer *Initializer::semantic(Scope *sc, Type *t) | |
38 { | |
39 return this; | |
40 } | |
41 | |
42 Type *Initializer::inferType(Scope *sc) | |
43 { | |
44 error(loc, "cannot infer type from initializer"); | |
45 return Type::terror; | |
46 } | |
47 | |
48 Initializers *Initializer::arraySyntaxCopy(Initializers *ai) | |
49 { Initializers *a = NULL; | |
50 | |
51 if (ai) | |
52 { | |
53 a = new Initializers(); | |
54 a->setDim(ai->dim); | |
55 for (int i = 0; i < a->dim; i++) | |
56 { Initializer *e = (Initializer *)ai->data[i]; | |
57 | |
58 e = e->syntaxCopy(); | |
59 a->data[i] = e; | |
60 } | |
61 } | |
62 return a; | |
63 } | |
64 | |
65 char *Initializer::toChars() | |
66 { OutBuffer *buf; | |
67 HdrGenState hgs; | |
68 | |
69 memset(&hgs, 0, sizeof(hgs)); | |
70 buf = new OutBuffer(); | |
71 toCBuffer(buf, &hgs); | |
72 return buf->toChars(); | |
73 } | |
74 | |
75 /********************************** VoidInitializer ***************************/ | |
76 | |
77 VoidInitializer::VoidInitializer(Loc loc) | |
78 : Initializer(loc) | |
79 { | |
80 type = NULL; | |
81 } | |
82 | |
83 | |
84 Initializer *VoidInitializer::syntaxCopy() | |
85 { | |
86 return new VoidInitializer(loc); | |
87 } | |
88 | |
89 | |
90 Initializer *VoidInitializer::semantic(Scope *sc, Type *t) | |
91 { | |
92 //printf("VoidInitializer::semantic(t = %p)\n", t); | |
93 type = t; | |
94 return this; | |
95 } | |
96 | |
97 | |
98 Expression *VoidInitializer::toExpression() | |
99 { | |
100 error(loc, "void initializer has no value"); | |
101 return new IntegerExp(0); | |
102 } | |
103 | |
104 | |
105 void VoidInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
106 { | |
107 buf->writestring("void"); | |
108 } | |
109 | |
110 | |
111 /********************************** StructInitializer *************************/ | |
112 | |
113 StructInitializer::StructInitializer(Loc loc) | |
114 : Initializer(loc) | |
115 { | |
116 ad = NULL; | |
117 } | |
118 | |
119 Initializer *StructInitializer::syntaxCopy() | |
120 { | |
121 StructInitializer *ai = new StructInitializer(loc); | |
122 | |
123 assert(field.dim == value.dim); | |
124 ai->field.setDim(field.dim); | |
125 ai->value.setDim(value.dim); | |
126 for (int i = 0; i < field.dim; i++) | |
127 { | |
128 ai->field.data[i] = field.data[i]; | |
129 | |
130 Initializer *init = (Initializer *)value.data[i]; | |
131 init = init->syntaxCopy(); | |
132 ai->value.data[i] = init; | |
133 } | |
134 return ai; | |
135 } | |
136 | |
137 void StructInitializer::addInit(Identifier *field, Initializer *value) | |
138 { | |
139 //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value); | |
140 this->field.push(field); | |
141 this->value.push(value); | |
142 } | |
143 | |
144 Initializer *StructInitializer::semantic(Scope *sc, Type *t) | |
145 { | |
146 TypeStruct *ts; | |
147 int errors = 0; | |
148 | |
149 //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars()); | |
150 vars.setDim(field.dim); | |
151 t = t->toBasetype(); | |
152 if (t->ty == Tstruct) | |
153 { unsigned i; | |
154 unsigned fieldi = 0; | |
155 | |
156 ts = (TypeStruct *)t; | |
157 ad = ts->sym; | |
158 for (i = 0; i < field.dim; i++) | |
159 { | |
160 Identifier *id = (Identifier *)field.data[i]; | |
161 Initializer *val = (Initializer *)value.data[i]; | |
162 Dsymbol *s; | |
163 VarDeclaration *v; | |
164 | |
165 if (id == NULL) | |
166 { | |
167 if (fieldi >= ad->fields.dim) | |
168 { error(loc, "too many initializers for %s", ad->toChars()); | |
169 field.remove(i); | |
170 i--; | |
171 continue; | |
172 } | |
173 else | |
174 { | |
175 s = (Dsymbol *)ad->fields.data[fieldi]; | |
176 } | |
177 } | |
178 else | |
179 { | |
180 //s = ad->symtab->lookup(id); | |
181 s = ad->search(loc, id, 0); | |
182 if (!s) | |
183 { | |
184 error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars()); | |
185 continue; | |
186 } | |
187 | |
188 // Find out which field index it is | |
189 for (fieldi = 0; 1; fieldi++) | |
190 { | |
191 if (fieldi >= ad->fields.dim) | |
192 { | |
193 s->error("is not a per-instance initializable field"); | |
194 break; | |
195 } | |
196 if (s == (Dsymbol *)ad->fields.data[fieldi]) | |
197 break; | |
198 } | |
199 } | |
200 if (s && (v = s->isVarDeclaration()) != NULL) | |
201 { | |
202 val = val->semantic(sc, v->type); | |
203 value.data[i] = (void *)val; | |
204 vars.data[i] = (void *)v; | |
205 } | |
206 else | |
207 { error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars()); | |
208 errors = 1; | |
209 } | |
210 fieldi++; | |
211 } | |
212 } | |
213 else if (t->ty == Tdelegate && value.dim == 0) | |
214 { /* Rewrite as empty delegate literal { } | |
215 */ | |
216 Arguments *arguments = new Arguments; | |
217 Type *tf = new TypeFunction(arguments, NULL, 0, LINKd); | |
218 FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL); | |
219 fd->fbody = new CompoundStatement(loc, new Statements()); | |
220 fd->endloc = loc; | |
221 Expression *e = new FuncExp(loc, fd); | |
222 ExpInitializer *ie = new ExpInitializer(loc, e); | |
223 return ie->semantic(sc, t); | |
224 } | |
225 else | |
226 { | |
227 error(loc, "a struct is not a valid initializer for a %s", t->toChars()); | |
228 errors = 1; | |
229 } | |
230 if (errors) | |
231 { | |
232 field.setDim(0); | |
233 value.setDim(0); | |
234 vars.setDim(0); | |
235 } | |
236 return this; | |
237 } | |
238 | |
239 | |
240 /*************************************** | |
241 * This works by transforming a struct initializer into | |
242 * a struct literal. In the future, the two should be the | |
243 * same thing. | |
244 */ | |
245 Expression *StructInitializer::toExpression() | |
246 { Expression *e; | |
247 | |
248 //printf("StructInitializer::toExpression() %s\n", toChars()); | |
249 if (!ad) // if fwd referenced | |
250 { | |
251 return NULL; | |
252 } | |
253 StructDeclaration *sd = ad->isStructDeclaration(); | |
254 if (!sd) | |
255 return NULL; | |
256 Expressions *elements = new Expressions(); | |
257 for (size_t i = 0; i < value.dim; i++) | |
258 { | |
259 if (field.data[i]) | |
260 goto Lno; | |
261 Initializer *iz = (Initializer *)value.data[i]; | |
262 if (!iz) | |
263 goto Lno; | |
264 Expression *ex = iz->toExpression(); | |
265 if (!ex) | |
266 goto Lno; | |
267 elements->push(ex); | |
268 } | |
269 e = new StructLiteralExp(loc, sd, elements); | |
270 e->type = sd->type; | |
271 return e; | |
272 | |
273 Lno: | |
274 delete elements; | |
275 //error(loc, "struct initializers as expressions are not allowed"); | |
276 return NULL; | |
277 } | |
278 | |
279 | |
280 void StructInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
281 { | |
282 //printf("StructInitializer::toCBuffer()\n"); | |
283 buf->writebyte('{'); | |
284 for (int i = 0; i < field.dim; i++) | |
285 { | |
286 if (i > 0) | |
287 buf->writebyte(','); | |
288 Identifier *id = (Identifier *)field.data[i]; | |
289 if (id) | |
290 { | |
291 buf->writestring(id->toChars()); | |
292 buf->writebyte(':'); | |
293 } | |
294 Initializer *iz = (Initializer *)value.data[i]; | |
295 if (iz) | |
296 iz->toCBuffer(buf, hgs); | |
297 } | |
298 buf->writebyte('}'); | |
299 } | |
300 | |
301 /********************************** ArrayInitializer ************************************/ | |
302 | |
303 ArrayInitializer::ArrayInitializer(Loc loc) | |
304 : Initializer(loc) | |
305 { | |
306 dim = 0; | |
307 type = NULL; | |
308 sem = 0; | |
309 } | |
310 | |
311 Initializer *ArrayInitializer::syntaxCopy() | |
312 { | |
313 //printf("ArrayInitializer::syntaxCopy()\n"); | |
314 | |
315 ArrayInitializer *ai = new ArrayInitializer(loc); | |
316 | |
317 assert(index.dim == value.dim); | |
318 ai->index.setDim(index.dim); | |
319 ai->value.setDim(value.dim); | |
320 for (int i = 0; i < ai->value.dim; i++) | |
321 { Expression *e = (Expression *)index.data[i]; | |
322 if (e) | |
323 e = e->syntaxCopy(); | |
324 ai->index.data[i] = e; | |
325 | |
326 Initializer *init = (Initializer *)value.data[i]; | |
327 init = init->syntaxCopy(); | |
328 ai->value.data[i] = init; | |
329 } | |
330 return ai; | |
331 } | |
332 | |
333 void ArrayInitializer::addInit(Expression *index, Initializer *value) | |
334 { | |
335 this->index.push(index); | |
336 this->value.push(value); | |
337 dim = 0; | |
338 type = NULL; | |
339 } | |
340 | |
341 Initializer *ArrayInitializer::semantic(Scope *sc, Type *t) | |
342 { unsigned i; | |
343 unsigned length; | |
344 | |
345 //printf("ArrayInitializer::semantic(%s)\n", t->toChars()); | |
346 if (sem) // if semantic() already run | |
347 return this; | |
348 sem = 1; | |
349 type = t; | |
350 t = t->toBasetype(); | |
351 switch (t->ty) | |
352 { | |
353 case Tpointer: | |
354 case Tsarray: | |
355 case Tarray: | |
356 break; | |
357 | |
358 default: | |
359 error(loc, "cannot use array to initialize %s", type->toChars()); | |
360 return this; | |
361 } | |
362 | |
363 length = 0; | |
364 for (i = 0; i < index.dim; i++) | |
365 { Expression *idx; | |
366 Initializer *val; | |
367 | |
368 idx = (Expression *)index.data[i]; | |
369 if (idx) | |
370 { idx = idx->semantic(sc); | |
371 idx = idx->optimize(WANTvalue | WANTinterpret); | |
372 index.data[i] = (void *)idx; | |
373 length = idx->toInteger(); | |
374 } | |
375 | |
376 val = (Initializer *)value.data[i]; | |
377 val = val->semantic(sc, t->next); | |
378 value.data[i] = (void *)val; | |
379 length++; | |
380 if (length == 0) | |
381 error(loc, "array dimension overflow"); | |
382 if (length > dim) | |
383 dim = length; | |
384 } | |
385 unsigned long amax = 0x80000000; | |
386 if ((unsigned long) dim * t->next->size() >= amax) | |
1133
eeb8b95ea92e
Cleanup DMD 1.041 merge.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
336
diff
changeset
|
387 error(loc, "array dimension %u exceeds max of %ju", dim, amax / t->next->size()); |
336 | 388 return this; |
389 } | |
390 | |
391 /******************************** | |
392 * If possible, convert array initializer to array literal. | |
393 */ | |
394 | |
395 Expression *ArrayInitializer::toExpression() | |
396 { Expressions *elements; | |
397 Expression *e; | |
398 | |
399 //printf("ArrayInitializer::toExpression()\n"); | |
400 //static int i; if (++i == 2) halt(); | |
401 elements = new Expressions(); | |
402 for (size_t i = 0; i < value.dim; i++) | |
403 { | |
404 if (index.data[i]) | |
405 goto Lno; | |
406 Initializer *iz = (Initializer *)value.data[i]; | |
407 if (!iz) | |
408 goto Lno; | |
409 Expression *ex = iz->toExpression(); | |
410 if (!ex) | |
411 goto Lno; | |
412 elements->push(ex); | |
413 } | |
414 e = new ArrayLiteralExp(loc, elements); | |
415 e->type = type; | |
416 return e; | |
417 | |
418 Lno: | |
419 delete elements; | |
420 error(loc, "array initializers as expressions are not allowed"); | |
421 return NULL; | |
422 } | |
423 | |
424 | |
425 /******************************** | |
426 * If possible, convert array initializer to associative array initializer. | |
427 */ | |
428 | |
429 Initializer *ArrayInitializer::toAssocArrayInitializer() | |
430 { Expressions *keys; | |
431 Expressions *values; | |
432 Expression *e; | |
433 | |
434 //printf("ArrayInitializer::toAssocArrayInitializer()\n"); | |
435 //static int i; if (++i == 2) halt(); | |
436 keys = new Expressions(); | |
437 keys->setDim(value.dim); | |
438 values = new Expressions(); | |
439 values->setDim(value.dim); | |
440 | |
441 for (size_t i = 0; i < value.dim; i++) | |
442 { | |
443 e = (Expression *)index.data[i]; | |
444 if (!e) | |
445 goto Lno; | |
446 keys->data[i] = (void *)e; | |
447 | |
448 Initializer *iz = (Initializer *)value.data[i]; | |
449 if (!iz) | |
450 goto Lno; | |
451 e = iz->toExpression(); | |
452 if (!e) | |
453 goto Lno; | |
454 values->data[i] = (void *)e; | |
455 } | |
456 e = new AssocArrayLiteralExp(loc, keys, values); | |
457 return new ExpInitializer(loc, e); | |
458 | |
459 Lno: | |
460 delete keys; | |
461 delete values; | |
462 error(loc, "not an associative array initializer"); | |
463 return this; | |
464 } | |
465 | |
466 | |
467 Type *ArrayInitializer::inferType(Scope *sc) | |
468 { | |
469 for (size_t i = 0; i < value.dim; i++) | |
470 { | |
471 if (index.data[i]) | |
472 goto Lno; | |
473 } | |
474 if (value.dim) | |
475 { | |
476 Initializer *iz = (Initializer *)value.data[0]; | |
477 if (iz) | |
478 { Type *t = iz->inferType(sc); | |
479 t = new TypeSArray(t, new IntegerExp(value.dim)); | |
480 t = t->semantic(loc, sc); | |
481 return t; | |
482 } | |
483 } | |
484 | |
485 Lno: | |
486 error(loc, "cannot infer type from this array initializer"); | |
487 return Type::terror; | |
488 } | |
489 | |
490 | |
491 void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
492 { | |
493 buf->writebyte('['); | |
494 for (int i = 0; i < index.dim; i++) | |
495 { | |
496 if (i > 0) | |
497 buf->writebyte(','); | |
498 Expression *ex = (Expression *)index.data[i]; | |
499 if (ex) | |
500 { | |
501 ex->toCBuffer(buf, hgs); | |
502 buf->writebyte(':'); | |
503 } | |
504 Initializer *iz = (Initializer *)value.data[i]; | |
505 if (iz) | |
506 iz->toCBuffer(buf, hgs); | |
507 } | |
508 buf->writebyte(']'); | |
509 } | |
510 | |
511 | |
512 /********************************** ExpInitializer ************************************/ | |
513 | |
514 ExpInitializer::ExpInitializer(Loc loc, Expression *exp) | |
515 : Initializer(loc) | |
516 { | |
517 this->exp = exp; | |
518 } | |
519 | |
520 Initializer *ExpInitializer::syntaxCopy() | |
521 { | |
522 return new ExpInitializer(loc, exp->syntaxCopy()); | |
523 } | |
524 | |
525 Initializer *ExpInitializer::semantic(Scope *sc, Type *t) | |
526 { | |
527 //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars()); | |
528 exp = exp->semantic(sc); | |
529 Type *tb = t->toBasetype(); | |
530 | |
531 /* Look for case of initializing a static array with a too-short | |
532 * string literal, such as: | |
533 * char[5] foo = "abc"; | |
534 * Allow this by doing an explicit cast, which will lengthen the string | |
535 * literal. | |
536 */ | |
537 if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray) | |
538 { StringExp *se = (StringExp *)exp; | |
539 | |
540 if (!se->committed && se->type->ty == Tsarray && | |
541 ((TypeSArray *)se->type)->dim->toInteger() < | |
542 ((TypeSArray *)t)->dim->toInteger()) | |
543 { | |
544 exp = se->castTo(sc, t); | |
545 goto L1; | |
546 } | |
547 } | |
548 | |
549 // Look for the case of statically initializing an array | |
550 // with a single member. | |
551 if (tb->ty == Tsarray && | |
552 !tb->next->equals(exp->type->toBasetype()->next) && | |
553 exp->implicitConvTo(tb->next) | |
554 ) | |
555 { | |
556 t = tb->next; | |
557 } | |
558 | |
559 exp = exp->implicitCastTo(sc, t); | |
560 L1: | |
561 exp = exp->optimize(WANTvalue | WANTinterpret); | |
562 //printf("-ExpInitializer::semantic(): "); exp->print(); | |
563 return this; | |
564 } | |
565 | |
566 Type *ExpInitializer::inferType(Scope *sc) | |
567 { | |
568 //printf("ExpInitializer::inferType() %s\n", toChars()); | |
569 exp = exp->semantic(sc); | |
570 exp = resolveProperties(sc, exp); | |
571 return exp->type; | |
572 } | |
573 | |
574 Expression *ExpInitializer::toExpression() | |
575 { | |
576 return exp; | |
577 } | |
578 | |
579 | |
580 void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
581 { | |
582 exp->toCBuffer(buf, hgs); | |
583 } | |
584 | |
585 | |
586 |