Mercurial > projects > ldc
annotate dmd/init.c @ 1650:40bd4a0d4870
Update to work with LLVM 2.7.
Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).
Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.
Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.
author | Tomas Lindquist Olsen |
---|---|
date | Wed, 19 May 2010 12:42:32 +0200 |
parents | 207a8a438dea |
children |
rev | line source |
---|---|
336 | 1 |
2 // Compiler implementation of the D programming language | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1133
diff
changeset
|
3 // Copyright (c) 1999-2009 by Digital Mars |
336 | 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 */ | |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
216 Parameters *arguments = new Parameters; |
336 | 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 | |
1587 | 399 //printf("ArrayInitializer::toExpression(), dim = %d\n", dim); |
336 | 400 //static int i; if (++i == 2) halt(); |
1587 | 401 |
402 size_t edim; | |
403 Type *t = NULL; | |
404 if (type) | |
405 { | |
406 if (type == Type::terror) | |
407 return new ErrorExp(); | |
408 | |
409 t = type->toBasetype(); | |
410 switch (t->ty) | |
411 { | |
412 case Tsarray: | |
413 edim = ((TypeSArray *)t)->dim->toInteger(); | |
414 break; | |
415 | |
416 case Tpointer: | |
417 case Tarray: | |
418 edim = dim; | |
419 break; | |
420 | |
421 default: | |
422 assert(0); | |
423 } | |
424 } | |
425 else | |
426 { | |
427 edim = value.dim; | |
428 for (size_t i = 0, j = 0; i < value.dim; i++, j++) | |
429 { | |
430 if (index.data[i]) | |
431 j = ((Expression *)index.data[i])->toInteger(); | |
432 if (j >= edim) | |
433 edim = j + 1; | |
434 } | |
435 } | |
436 | |
336 | 437 elements = new Expressions(); |
1587 | 438 elements->setDim(edim); |
439 for (size_t i = 0, j = 0; i < value.dim; i++, j++) | |
336 | 440 { |
441 if (index.data[i]) | |
1587 | 442 j = ((Expression *)index.data[i])->toInteger(); |
443 assert(j < edim); | |
336 | 444 Initializer *iz = (Initializer *)value.data[i]; |
445 if (!iz) | |
446 goto Lno; | |
447 Expression *ex = iz->toExpression(); | |
448 if (!ex) | |
1587 | 449 { |
336 | 450 goto Lno; |
1587 | 451 } |
452 elements->data[j] = ex; | |
336 | 453 } |
1587 | 454 |
455 /* Fill in any missing elements with the default initializer | |
456 */ | |
457 { | |
458 Expression *init = NULL; | |
459 for (size_t i = 0; i < edim; i++) | |
460 { | |
461 if (!elements->data[i]) | |
462 { | |
463 if (!type) | |
464 goto Lno; | |
465 if (!init) | |
466 init = t->next->defaultInit(); | |
467 elements->data[i] = init; | |
468 } | |
469 } | |
470 | |
471 Expression *e = new ArrayLiteralExp(loc, elements); | |
336 | 472 e->type = type; |
473 return e; | |
1587 | 474 } |
336 | 475 |
476 Lno: | |
477 delete elements; | |
478 error(loc, "array initializers as expressions are not allowed"); | |
1587 | 479 return new ErrorExp(); |
336 | 480 } |
481 | |
482 /******************************** | |
483 * If possible, convert array initializer to associative array initializer. | |
484 */ | |
485 | |
486 Initializer *ArrayInitializer::toAssocArrayInitializer() | |
487 { Expressions *keys; | |
488 Expressions *values; | |
489 Expression *e; | |
490 | |
491 //printf("ArrayInitializer::toAssocArrayInitializer()\n"); | |
492 //static int i; if (++i == 2) halt(); | |
493 keys = new Expressions(); | |
494 keys->setDim(value.dim); | |
495 values = new Expressions(); | |
496 values->setDim(value.dim); | |
497 | |
498 for (size_t i = 0; i < value.dim; i++) | |
499 { | |
500 e = (Expression *)index.data[i]; | |
501 if (!e) | |
502 goto Lno; | |
503 keys->data[i] = (void *)e; | |
504 | |
505 Initializer *iz = (Initializer *)value.data[i]; | |
506 if (!iz) | |
507 goto Lno; | |
508 e = iz->toExpression(); | |
509 if (!e) | |
510 goto Lno; | |
511 values->data[i] = (void *)e; | |
512 } | |
513 e = new AssocArrayLiteralExp(loc, keys, values); | |
514 return new ExpInitializer(loc, e); | |
515 | |
516 Lno: | |
517 delete keys; | |
518 delete values; | |
519 error(loc, "not an associative array initializer"); | |
520 return this; | |
521 } | |
522 | |
523 | |
524 Type *ArrayInitializer::inferType(Scope *sc) | |
525 { | |
526 for (size_t i = 0; i < value.dim; i++) | |
527 { | |
528 if (index.data[i]) | |
1587 | 529 goto Laa; |
336 | 530 } |
531 if (value.dim) | |
532 { | |
533 Initializer *iz = (Initializer *)value.data[0]; | |
534 if (iz) | |
535 { Type *t = iz->inferType(sc); | |
536 t = new TypeSArray(t, new IntegerExp(value.dim)); | |
537 t = t->semantic(loc, sc); | |
538 return t; | |
539 } | |
540 } | |
541 | |
1587 | 542 Laa: |
543 /* It's possibly an associative array initializer | |
544 */ | |
545 Initializer *iz = (Initializer *)value.data[0]; | |
546 Expression *indexinit = (Expression *)index.data[0]; | |
547 if (iz && indexinit) | |
548 { Type *t = iz->inferType(sc); | |
549 indexinit = indexinit->semantic(sc); | |
550 Type *indext = indexinit->type; | |
551 t = new TypeAArray(t, indext); | |
552 type = t->semantic(loc, sc); | |
553 } | |
554 else | |
555 error(loc, "cannot infer type from this array initializer"); | |
556 return type; | |
336 | 557 } |
558 | |
559 | |
560 void ArrayInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
561 { | |
562 buf->writebyte('['); | |
563 for (int i = 0; i < index.dim; i++) | |
564 { | |
565 if (i > 0) | |
566 buf->writebyte(','); | |
567 Expression *ex = (Expression *)index.data[i]; | |
568 if (ex) | |
569 { | |
570 ex->toCBuffer(buf, hgs); | |
571 buf->writebyte(':'); | |
572 } | |
573 Initializer *iz = (Initializer *)value.data[i]; | |
574 if (iz) | |
575 iz->toCBuffer(buf, hgs); | |
576 } | |
577 buf->writebyte(']'); | |
578 } | |
579 | |
580 | |
581 /********************************** ExpInitializer ************************************/ | |
582 | |
583 ExpInitializer::ExpInitializer(Loc loc, Expression *exp) | |
584 : Initializer(loc) | |
585 { | |
586 this->exp = exp; | |
587 } | |
588 | |
589 Initializer *ExpInitializer::syntaxCopy() | |
590 { | |
591 return new ExpInitializer(loc, exp->syntaxCopy()); | |
592 } | |
593 | |
594 Initializer *ExpInitializer::semantic(Scope *sc, Type *t) | |
595 { | |
596 //printf("ExpInitializer::semantic(%s), type = %s\n", exp->toChars(), t->toChars()); | |
597 exp = exp->semantic(sc); | |
598 Type *tb = t->toBasetype(); | |
599 | |
600 /* Look for case of initializing a static array with a too-short | |
601 * string literal, such as: | |
602 * char[5] foo = "abc"; | |
603 * Allow this by doing an explicit cast, which will lengthen the string | |
604 * literal. | |
605 */ | |
606 if (exp->op == TOKstring && tb->ty == Tsarray && exp->type->ty == Tsarray) | |
607 { StringExp *se = (StringExp *)exp; | |
608 | |
609 if (!se->committed && se->type->ty == Tsarray && | |
610 ((TypeSArray *)se->type)->dim->toInteger() < | |
611 ((TypeSArray *)t)->dim->toInteger()) | |
612 { | |
613 exp = se->castTo(sc, t); | |
614 goto L1; | |
615 } | |
616 } | |
617 | |
618 // Look for the case of statically initializing an array | |
619 // with a single member. | |
620 if (tb->ty == Tsarray && | |
621 !tb->next->equals(exp->type->toBasetype()->next) && | |
622 exp->implicitConvTo(tb->next) | |
623 ) | |
624 { | |
625 t = tb->next; | |
626 } | |
627 | |
628 exp = exp->implicitCastTo(sc, t); | |
629 L1: | |
630 exp = exp->optimize(WANTvalue | WANTinterpret); | |
631 //printf("-ExpInitializer::semantic(): "); exp->print(); | |
632 return this; | |
633 } | |
634 | |
635 Type *ExpInitializer::inferType(Scope *sc) | |
636 { | |
637 //printf("ExpInitializer::inferType() %s\n", toChars()); | |
638 exp = exp->semantic(sc); | |
639 exp = resolveProperties(sc, exp); | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1133
diff
changeset
|
640 |
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1133
diff
changeset
|
641 // Give error for overloaded function addresses |
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1133
diff
changeset
|
642 if (exp->op == TOKsymoff) |
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1133
diff
changeset
|
643 { SymOffExp *se = (SymOffExp *)exp; |
1587 | 644 if ( |
645 #if DMDV2 | |
646 se->hasOverloads && | |
647 #else | |
648 se->var->isFuncDeclaration() && | |
649 #endif | |
650 !se->var->isFuncDeclaration()->isUnique()) | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1133
diff
changeset
|
651 exp->error("cannot infer type from overloaded function symbol %s", exp->toChars()); |
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1133
diff
changeset
|
652 } |
1587 | 653 |
654 // Give error for overloaded function addresses | |
655 if (exp->op == TOKdelegate) | |
656 { DelegateExp *se = (DelegateExp *)exp; | |
657 if ( | |
658 se->func->isFuncDeclaration() && | |
659 !se->func->isFuncDeclaration()->isUnique()) | |
660 exp->error("cannot infer type from overloaded function symbol %s", exp->toChars()); | |
661 } | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1133
diff
changeset
|
662 |
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1133
diff
changeset
|
663 Type *t = exp->type; |
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1133
diff
changeset
|
664 if (!t) |
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1133
diff
changeset
|
665 t = Initializer::inferType(sc); |
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1133
diff
changeset
|
666 return t; |
336 | 667 } |
668 | |
669 Expression *ExpInitializer::toExpression() | |
670 { | |
671 return exp; | |
672 } | |
673 | |
674 | |
675 void ExpInitializer::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
676 { | |
677 exp->toCBuffer(buf, hgs); | |
678 } | |
679 | |
680 | |
681 |