]>
Commit | Line | Data |
---|---|---|
b4c522fa IB |
1 | |
2 | /* Compiler implementation of the D programming language | |
8e788ac6 | 3 | * Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved |
b4c522fa IB |
4 | * written by Walter Bright |
5 | * http://www.digitalmars.com | |
6 | * Distributed under the Boost Software License, Version 1.0. | |
7 | * http://www.boost.org/LICENSE_1_0.txt | |
8 | */ | |
9 | ||
f9ab59ff | 10 | #include "root/checkedint.h" |
b4c522fa IB |
11 | #include "mars.h" |
12 | #include "init.h" | |
13 | #include "expression.h" | |
14 | #include "statement.h" | |
15 | #include "declaration.h" | |
16 | #include "aggregate.h" | |
17 | #include "scope.h" | |
18 | #include "mtype.h" | |
19 | #include "template.h" | |
20 | #include "id.h" | |
21 | ||
22 | FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL); | |
23 | Expression *semantic(Expression *e, Scope *sc); | |
24 | Initializer *inferType(Initializer *init, Scope *sc); | |
25 | Initializer *semantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret); | |
26 | bool hasNonConstPointers(Expression *e); | |
27 | ||
28 | class InitializerSemanticVisitor : public Visitor | |
29 | { | |
30 | public: | |
31 | Initializer *result; | |
32 | Scope *sc; | |
33 | Type *t; | |
34 | NeedInterpret needInterpret; | |
35 | ||
36 | InitializerSemanticVisitor(Scope *sc, Type *t, NeedInterpret needInterpret) | |
37 | { | |
38 | this->result = NULL; | |
39 | this->sc = sc; | |
40 | this->t = t; | |
41 | this->needInterpret = needInterpret; | |
42 | } | |
43 | ||
44 | void visit(ErrorInitializer *i) | |
45 | { | |
46 | //printf("ErrorInitializer::semantic(t = %p)\n", t); | |
47 | result = i; | |
48 | } | |
49 | ||
50 | void visit(VoidInitializer *i) | |
51 | { | |
52 | //printf("VoidInitializer::semantic(t = %p)\n", t); | |
53 | i->type = t; | |
54 | result = i; | |
55 | } | |
56 | ||
57 | void visit(StructInitializer *i) | |
58 | { | |
59 | //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars()); | |
60 | t = t->toBasetype(); | |
61 | if (t->ty == Tsarray && t->nextOf()->toBasetype()->ty == Tstruct) | |
62 | t = t->nextOf()->toBasetype(); | |
63 | if (t->ty == Tstruct) | |
64 | { | |
65 | StructDeclaration *sd = ((TypeStruct *)t)->sym; | |
66 | if (sd->ctor) | |
67 | { | |
68 | error(i->loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead", | |
69 | sd->kind(), sd->toChars(), sd->toChars()); | |
70 | result = new ErrorInitializer(); | |
71 | return; | |
72 | } | |
73 | sd->size(i->loc); | |
74 | if (sd->sizeok != SIZEOKdone) | |
75 | { | |
76 | result = new ErrorInitializer(); | |
77 | return; | |
78 | } | |
79 | size_t nfields = sd->fields.dim - sd->isNested(); | |
80 | ||
81 | //expandTuples for non-identity arguments? | |
82 | ||
83 | Expressions *elements = new Expressions(); | |
84 | elements->setDim(nfields); | |
85 | for (size_t j = 0; j < elements->dim; j++) | |
86 | (*elements)[j] = NULL; | |
87 | ||
88 | // Run semantic for explicitly given initializers | |
89 | // TODO: this part is slightly different from StructLiteralExp::semantic. | |
90 | bool errors = false; | |
91 | for (size_t fieldi = 0, j = 0; j < i->field.dim; j++) | |
92 | { | |
93 | if (Identifier *id = i->field[j]) | |
94 | { | |
95 | Dsymbol *s = sd->search(i->loc, id); | |
96 | if (!s) | |
97 | { | |
98 | s = sd->search_correct(id); | |
99 | if (s) | |
100 | error(i->loc, "'%s' is not a member of '%s', did you mean %s '%s'?", | |
101 | id->toChars(), sd->toChars(), s->kind(), s->toChars()); | |
102 | else | |
103 | error(i->loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars()); | |
104 | result = new ErrorInitializer(); | |
105 | return; | |
106 | } | |
107 | s = s->toAlias(); | |
108 | ||
109 | // Find out which field index it is | |
110 | for (fieldi = 0; 1; fieldi++) | |
111 | { | |
112 | if (fieldi >= nfields) | |
113 | { | |
114 | error(i->loc, "%s.%s is not a per-instance initializable field", | |
115 | sd->toChars(), s->toChars()); | |
116 | result = new ErrorInitializer(); | |
117 | return; | |
118 | } | |
119 | if (s == sd->fields[fieldi]) | |
120 | break; | |
121 | } | |
122 | } | |
123 | else if (fieldi >= nfields) | |
124 | { | |
125 | error(i->loc, "too many initializers for %s", sd->toChars()); | |
126 | result = new ErrorInitializer(); | |
127 | return; | |
128 | } | |
129 | ||
130 | VarDeclaration *vd = sd->fields[fieldi]; | |
131 | if ((*elements)[fieldi]) | |
132 | { | |
133 | error(i->loc, "duplicate initializer for field '%s'", vd->toChars()); | |
134 | errors = true; | |
135 | continue; | |
136 | } | |
137 | for (size_t k = 0; k < nfields; k++) | |
138 | { | |
139 | VarDeclaration *v2 = sd->fields[k]; | |
140 | if (vd->isOverlappedWith(v2) && (*elements)[k]) | |
141 | { | |
142 | error(i->loc, "overlapping initialization for field %s and %s", | |
143 | v2->toChars(), vd->toChars()); | |
144 | errors = true; | |
145 | continue; | |
146 | } | |
147 | } | |
148 | ||
149 | assert(sc); | |
150 | Initializer *iz = i->value[j]; | |
151 | iz = ::semantic(iz, sc, vd->type->addMod(t->mod), needInterpret); | |
152 | Expression *ex = initializerToExpression(iz); | |
153 | if (ex->op == TOKerror) | |
154 | { | |
155 | errors = true; | |
156 | continue; | |
157 | } | |
158 | i->value[j] = iz; | |
159 | (*elements)[fieldi] = doCopyOrMove(sc, ex); | |
160 | ++fieldi; | |
161 | } | |
162 | if (errors) | |
163 | { | |
164 | result = new ErrorInitializer(); | |
165 | return; | |
166 | } | |
167 | ||
168 | StructLiteralExp *sle = new StructLiteralExp(i->loc, sd, elements, t); | |
169 | if (!sd->fill(i->loc, elements, false)) | |
170 | { | |
171 | result = new ErrorInitializer(); | |
172 | return; | |
173 | } | |
174 | sle->type = t; | |
175 | ||
176 | ExpInitializer *ie = new ExpInitializer(i->loc, sle); | |
177 | result = ::semantic(ie, sc, t, needInterpret); | |
178 | return; | |
179 | } | |
180 | else if ((t->ty == Tdelegate || (t->ty == Tpointer && t->nextOf()->ty == Tfunction)) && i->value.dim == 0) | |
181 | { | |
182 | TOK tok = (t->ty == Tdelegate) ? TOKdelegate : TOKfunction; | |
183 | /* Rewrite as empty delegate literal { } | |
184 | */ | |
185 | Parameters *parameters = new Parameters; | |
186 | Type *tf = new TypeFunction(parameters, NULL, 0, LINKd); | |
187 | FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(i->loc, Loc(), tf, tok, NULL); | |
188 | fd->fbody = new CompoundStatement(i->loc, new Statements()); | |
189 | fd->endloc = i->loc; | |
190 | Expression *e = new FuncExp(i->loc, fd); | |
191 | ExpInitializer *ie = new ExpInitializer(i->loc, e); | |
192 | result = ::semantic(ie, sc, t, needInterpret); | |
193 | return; | |
194 | } | |
195 | ||
196 | error(i->loc, "a struct is not a valid initializer for a %s", t->toChars()); | |
197 | result = new ErrorInitializer(); | |
198 | } | |
199 | ||
200 | void visit(ArrayInitializer *i) | |
201 | { | |
202 | unsigned length; | |
203 | const unsigned amax = 0x80000000; | |
204 | bool errors = false; | |
205 | ||
206 | //printf("ArrayInitializer::semantic(%s)\n", t->toChars()); | |
207 | if (i->sem) // if semantic() already run | |
208 | { | |
209 | result = i; | |
210 | return; | |
211 | } | |
212 | i->sem = true; | |
213 | t = t->toBasetype(); | |
214 | switch (t->ty) | |
215 | { | |
216 | case Tsarray: | |
217 | case Tarray: | |
218 | break; | |
219 | ||
220 | case Tvector: | |
221 | t = ((TypeVector *)t)->basetype; | |
222 | break; | |
223 | ||
224 | case Taarray: | |
225 | case Tstruct: // consider implicit constructor call | |
226 | { | |
227 | Expression *e; | |
228 | // note: MyStruct foo = [1:2, 3:4] is correct code if MyStruct has a this(int[int]) | |
229 | if (t->ty == Taarray || i->isAssociativeArray()) | |
230 | e = i->toAssocArrayLiteral(); | |
231 | else | |
232 | e = initializerToExpression(i); | |
233 | if (!e) // Bugzilla 13987 | |
234 | { | |
235 | error(i->loc, "cannot use array to initialize %s", t->toChars()); | |
236 | goto Lerr; | |
237 | } | |
238 | ExpInitializer *ei = new ExpInitializer(e->loc, e); | |
239 | result = ::semantic(ei, sc, t, needInterpret); | |
240 | return; | |
241 | } | |
242 | case Tpointer: | |
243 | if (t->nextOf()->ty != Tfunction) | |
244 | break; | |
245 | /* fall through */ | |
246 | ||
247 | default: | |
248 | error(i->loc, "cannot use array to initialize %s", t->toChars()); | |
249 | goto Lerr; | |
250 | } | |
251 | ||
252 | i->type = t; | |
253 | ||
254 | length = 0; | |
255 | for (size_t j = 0; j < i->index.dim; j++) | |
256 | { | |
257 | Expression *idx = i->index[j]; | |
258 | if (idx) | |
259 | { | |
260 | sc = sc->startCTFE(); | |
261 | idx = ::semantic(idx, sc); | |
262 | sc = sc->endCTFE(); | |
263 | idx = idx->ctfeInterpret(); | |
264 | i->index[j] = idx; | |
265 | const uinteger_t idxvalue = idx->toInteger(); | |
266 | if (idxvalue >= amax) | |
267 | { | |
268 | error(i->loc, "array index %llu overflow", (ulonglong)idxvalue); | |
269 | errors = true; | |
270 | } | |
271 | length = (unsigned)idx->toInteger(); | |
272 | if (idx->op == TOKerror) | |
273 | errors = true; | |
274 | } | |
275 | ||
276 | Initializer *val = i->value[j]; | |
277 | ExpInitializer *ei = val->isExpInitializer(); | |
278 | if (ei && !idx) | |
279 | ei->expandTuples = true; | |
280 | val = ::semantic(val, sc, t->nextOf(), needInterpret); | |
281 | if (val->isErrorInitializer()) | |
282 | errors = true; | |
283 | ||
284 | ei = val->isExpInitializer(); | |
285 | // found a tuple, expand it | |
286 | if (ei && ei->exp->op == TOKtuple) | |
287 | { | |
288 | TupleExp *te = (TupleExp *)ei->exp; | |
289 | i->index.remove(j); | |
290 | i->value.remove(j); | |
291 | ||
292 | for (size_t k = 0; k < te->exps->dim; ++k) | |
293 | { | |
294 | Expression *e = (*te->exps)[k]; | |
295 | i->index.insert(j + k, (Expression *)NULL); | |
296 | i->value.insert(j + k, new ExpInitializer(e->loc, e)); | |
297 | } | |
298 | j--; | |
299 | continue; | |
300 | } | |
301 | else | |
302 | { | |
303 | i->value[j] = val; | |
304 | } | |
305 | ||
306 | length++; | |
307 | if (length == 0) | |
308 | { | |
309 | error(i->loc, "array dimension overflow"); | |
310 | goto Lerr; | |
311 | } | |
312 | if (length > i->dim) | |
313 | i->dim = length; | |
314 | } | |
315 | if (t->ty == Tsarray) | |
316 | { | |
317 | uinteger_t edim = ((TypeSArray *)t)->dim->toInteger(); | |
318 | if (i->dim > edim) | |
319 | { | |
320 | error(i->loc, "array initializer has %u elements, but array length is %llu", i->dim, (ulonglong)edim); | |
321 | goto Lerr; | |
322 | } | |
323 | } | |
324 | if (errors) | |
325 | goto Lerr; | |
326 | else | |
327 | { | |
328 | d_uns64 sz = t->nextOf()->size(); | |
329 | bool overflow = false; | |
330 | const d_uns64 max = mulu((d_uns64)i->dim, sz, overflow); | |
331 | if (overflow || max > amax) | |
332 | { | |
333 | error(i->loc, "array dimension %llu exceeds max of %llu", (ulonglong)i->dim, (ulonglong)(amax / sz)); | |
334 | goto Lerr; | |
335 | } | |
336 | result = i; | |
337 | return; | |
338 | } | |
339 | ||
340 | Lerr: | |
341 | result = new ErrorInitializer(); | |
342 | } | |
343 | ||
344 | void visit(ExpInitializer *i) | |
345 | { | |
346 | //printf("ExpInitializer::semantic(%s), type = %s\n", i->exp->toChars(), t->toChars()); | |
347 | if (needInterpret) sc = sc->startCTFE(); | |
348 | i->exp = ::semantic(i->exp, sc); | |
349 | i->exp = resolveProperties(sc, i->exp); | |
350 | if (needInterpret) sc = sc->endCTFE(); | |
351 | if (i->exp->op == TOKerror) | |
352 | { | |
353 | result = new ErrorInitializer(); | |
354 | return; | |
355 | } | |
356 | ||
357 | unsigned int olderrors = global.errors; | |
358 | if (needInterpret) | |
359 | { | |
360 | // If the result will be implicitly cast, move the cast into CTFE | |
361 | // to avoid premature truncation of polysemous types. | |
362 | // eg real [] x = [1.1, 2.2]; should use real precision. | |
363 | if (i->exp->implicitConvTo(t)) | |
364 | { | |
365 | i->exp = i->exp->implicitCastTo(sc, t); | |
366 | } | |
367 | if (!global.gag && olderrors != global.errors) | |
368 | { | |
369 | result = i; | |
370 | return; | |
371 | } | |
372 | i->exp = i->exp->ctfeInterpret(); | |
373 | } | |
374 | else | |
375 | { | |
376 | i->exp = i->exp->optimize(WANTvalue); | |
377 | } | |
378 | if (!global.gag && olderrors != global.errors) | |
379 | { | |
380 | result = i; // Failed, suppress duplicate error messages | |
381 | return; | |
382 | } | |
383 | ||
384 | if (i->exp->type->ty == Ttuple && ((TypeTuple *)i->exp->type)->arguments->dim == 0) | |
385 | { | |
386 | Type *et = i->exp->type; | |
387 | i->exp = new TupleExp(i->exp->loc, new Expressions()); | |
388 | i->exp->type = et; | |
389 | } | |
390 | if (i->exp->op == TOKtype) | |
391 | { | |
392 | i->exp->error("initializer must be an expression, not '%s'", i->exp->toChars()); | |
393 | result = new ErrorInitializer(); | |
394 | return; | |
395 | } | |
396 | ||
397 | // Make sure all pointers are constants | |
398 | if (needInterpret && hasNonConstPointers(i->exp)) | |
399 | { | |
400 | i->exp->error("cannot use non-constant CTFE pointer in an initializer '%s'", i->exp->toChars()); | |
401 | result = new ErrorInitializer(); | |
402 | return; | |
403 | } | |
404 | ||
405 | Type *tb = t->toBasetype(); | |
406 | Type *ti = i->exp->type->toBasetype(); | |
407 | ||
408 | if (i->exp->op == TOKtuple && i->expandTuples && !i->exp->implicitConvTo(t)) | |
409 | { | |
410 | result = new ExpInitializer(i->loc, i->exp); | |
411 | return; | |
412 | } | |
413 | ||
414 | /* Look for case of initializing a static array with a too-short | |
415 | * string literal, such as: | |
416 | * char[5] foo = "abc"; | |
417 | * Allow this by doing an explicit cast, which will lengthen the string | |
418 | * literal. | |
419 | */ | |
420 | if (i->exp->op == TOKstring && tb->ty == Tsarray) | |
421 | { | |
422 | StringExp *se = (StringExp *)i->exp; | |
423 | Type *typeb = se->type->toBasetype(); | |
424 | TY tynto = tb->nextOf()->ty; | |
425 | if (!se->committed && | |
426 | (typeb->ty == Tarray || typeb->ty == Tsarray) && | |
427 | (tynto == Tchar || tynto == Twchar || tynto == Tdchar) && | |
428 | se->numberOfCodeUnits(tynto) < ((TypeSArray *)tb)->dim->toInteger()) | |
429 | { | |
430 | i->exp = se->castTo(sc, t); | |
431 | goto L1; | |
432 | } | |
433 | } | |
434 | ||
435 | // Look for implicit constructor call | |
436 | if (tb->ty == Tstruct && | |
437 | !(ti->ty == Tstruct && tb->toDsymbol(sc) == ti->toDsymbol(sc)) && | |
438 | !i->exp->implicitConvTo(t)) | |
439 | { | |
440 | StructDeclaration *sd = ((TypeStruct *)tb)->sym; | |
441 | if (sd->ctor) | |
442 | { | |
443 | // Rewrite as S().ctor(exp) | |
444 | Expression *e; | |
445 | e = new StructLiteralExp(i->loc, sd, NULL); | |
446 | e = new DotIdExp(i->loc, e, Id::ctor); | |
447 | e = new CallExp(i->loc, e, i->exp); | |
448 | e = ::semantic(e, sc); | |
449 | if (needInterpret) | |
450 | i->exp = e->ctfeInterpret(); | |
451 | else | |
452 | i->exp = e->optimize(WANTvalue); | |
453 | } | |
454 | } | |
455 | ||
456 | // Look for the case of statically initializing an array | |
457 | // with a single member. | |
458 | if (tb->ty == Tsarray && | |
459 | !tb->nextOf()->equals(ti->toBasetype()->nextOf()) && | |
460 | i->exp->implicitConvTo(tb->nextOf()) | |
461 | ) | |
462 | { | |
463 | /* If the variable is not actually used in compile time, array creation is | |
464 | * redundant. So delay it until invocation of toExpression() or toDt(). | |
465 | */ | |
466 | t = tb->nextOf(); | |
467 | } | |
468 | ||
469 | if (i->exp->implicitConvTo(t)) | |
470 | { | |
471 | i->exp = i->exp->implicitCastTo(sc, t); | |
472 | } | |
473 | else | |
474 | { | |
475 | // Look for mismatch of compile-time known length to emit | |
476 | // better diagnostic message, as same as AssignExp::semantic. | |
477 | if (tb->ty == Tsarray && | |
478 | i->exp->implicitConvTo(tb->nextOf()->arrayOf()) > MATCHnomatch) | |
479 | { | |
480 | uinteger_t dim1 = ((TypeSArray *)tb)->dim->toInteger(); | |
481 | uinteger_t dim2 = dim1; | |
482 | if (i->exp->op == TOKarrayliteral) | |
483 | { | |
484 | ArrayLiteralExp *ale = (ArrayLiteralExp *)i->exp; | |
485 | dim2 = ale->elements ? ale->elements->dim : 0; | |
486 | } | |
487 | else if (i->exp->op == TOKslice) | |
488 | { | |
489 | Type *tx = toStaticArrayType((SliceExp *)i->exp); | |
490 | if (tx) | |
491 | dim2 = ((TypeSArray *)tx)->dim->toInteger(); | |
492 | } | |
493 | if (dim1 != dim2) | |
494 | { | |
495 | i->exp->error("mismatched array lengths, %d and %d", (int)dim1, (int)dim2); | |
496 | i->exp = new ErrorExp(); | |
497 | } | |
498 | } | |
499 | i->exp = i->exp->implicitCastTo(sc, t); | |
500 | } | |
501 | L1: | |
502 | if (i->exp->op == TOKerror) | |
503 | { | |
504 | result = i; | |
505 | return; | |
506 | } | |
507 | if (needInterpret) | |
508 | i->exp = i->exp->ctfeInterpret(); | |
509 | else | |
510 | i->exp = i->exp->optimize(WANTvalue); | |
511 | //printf("-ExpInitializer::semantic(): "); i->exp->print(); | |
512 | result = i; | |
513 | } | |
514 | }; | |
515 | ||
516 | // Performs semantic analisys on Initializer AST nodes | |
517 | Initializer *semantic(Initializer *init, Scope *sc, Type *t, NeedInterpret needInterpret) | |
518 | { | |
519 | InitializerSemanticVisitor v = InitializerSemanticVisitor(sc, t, needInterpret); | |
520 | init->accept(&v); | |
521 | return v.result; | |
522 | } | |
523 | ||
524 | class InferTypeVisitor : public Visitor | |
525 | { | |
526 | public: | |
527 | Initializer *result; | |
528 | Scope *sc; | |
529 | ||
530 | InferTypeVisitor(Scope *sc) | |
531 | { | |
532 | this->result = NULL; | |
533 | this->sc = sc; | |
534 | } | |
535 | ||
536 | void visit(ErrorInitializer *i) | |
537 | { | |
538 | result = i; | |
539 | } | |
540 | ||
541 | void visit(VoidInitializer *i) | |
542 | { | |
543 | error(i->loc, "cannot infer type from void initializer"); | |
544 | result = new ErrorInitializer(); | |
545 | } | |
546 | ||
547 | void visit(StructInitializer *i) | |
548 | { | |
549 | error(i->loc, "cannot infer type from struct initializer"); | |
550 | result = new ErrorInitializer(); | |
551 | } | |
552 | ||
553 | void visit(ArrayInitializer *init) | |
554 | { | |
555 | //printf("ArrayInitializer::inferType() %s\n", init->toChars()); | |
556 | Expressions *keys = NULL; | |
557 | Expressions *values; | |
558 | if (init->isAssociativeArray()) | |
559 | { | |
560 | keys = new Expressions(); | |
561 | keys->setDim(init->value.dim); | |
562 | values = new Expressions(); | |
563 | values->setDim(init->value.dim); | |
564 | ||
565 | for (size_t i = 0; i < init->value.dim; i++) | |
566 | { | |
567 | Expression *e = init->index[i]; | |
568 | if (!e) | |
569 | goto Lno; | |
570 | (*keys)[i] = e; | |
571 | ||
572 | Initializer *iz = init->value[i]; | |
573 | if (!iz) | |
574 | goto Lno; | |
575 | iz = inferType(iz, sc); | |
576 | if (iz->isErrorInitializer()) | |
577 | { | |
578 | result = iz; | |
579 | return; | |
580 | } | |
581 | assert(iz->isExpInitializer()); | |
582 | (*values)[i] = ((ExpInitializer *)iz)->exp; | |
583 | assert((*values)[i]->op != TOKerror); | |
584 | } | |
585 | ||
586 | Expression *e = new AssocArrayLiteralExp(init->loc, keys, values); | |
587 | ExpInitializer *ei = new ExpInitializer(init->loc, e); | |
588 | result = inferType(ei, sc); | |
589 | return; | |
590 | } | |
591 | else | |
592 | { | |
593 | Expressions *elements = new Expressions(); | |
594 | elements->setDim(init->value.dim); | |
595 | elements->zero(); | |
596 | ||
597 | for (size_t i = 0; i < init->value.dim; i++) | |
598 | { | |
599 | assert(!init->index[i]); // already asserted by isAssociativeArray() | |
600 | ||
601 | Initializer *iz = init->value[i]; | |
602 | if (!iz) | |
603 | goto Lno; | |
604 | iz = inferType(iz, sc); | |
605 | if (iz->isErrorInitializer()) | |
606 | { | |
607 | result = iz; | |
608 | return; | |
609 | } | |
610 | assert(iz->isExpInitializer()); | |
611 | (*elements)[i] = ((ExpInitializer *)iz)->exp; | |
612 | assert((*elements)[i]->op != TOKerror); | |
613 | } | |
614 | ||
255b2d91 | 615 | Expression *e = new ArrayLiteralExp(init->loc, NULL, elements); |
b4c522fa IB |
616 | ExpInitializer *ei = new ExpInitializer(init->loc, e); |
617 | result = inferType(ei, sc); | |
618 | return; | |
619 | } | |
620 | Lno: | |
621 | if (keys) | |
622 | { | |
623 | delete keys; | |
624 | delete values; | |
625 | error(init->loc, "not an associative array initializer"); | |
626 | } | |
627 | else | |
628 | { | |
629 | error(init->loc, "cannot infer type from array initializer"); | |
630 | } | |
631 | result = new ErrorInitializer(); | |
632 | } | |
633 | ||
634 | void visit(ExpInitializer *init) | |
635 | { | |
636 | //printf("ExpInitializer::inferType() %s\n", init->toChars()); | |
637 | init->exp = ::semantic(init->exp, sc); | |
638 | init->exp = resolveProperties(sc, init->exp); | |
639 | ||
640 | if (init->exp->op == TOKscope) | |
641 | { | |
642 | ScopeExp *se = (ScopeExp *)init->exp; | |
643 | TemplateInstance *ti = se->sds->isTemplateInstance(); | |
644 | if (ti && ti->semanticRun == PASSsemantic && !ti->aliasdecl) | |
645 | se->error("cannot infer type from %s %s, possible circular dependency", se->sds->kind(), se->toChars()); | |
646 | else | |
647 | se->error("cannot infer type from %s %s", se->sds->kind(), se->toChars()); | |
648 | result = new ErrorInitializer(); | |
649 | return; | |
650 | } | |
651 | ||
652 | // Give error for overloaded function addresses | |
653 | bool hasOverloads = false; | |
654 | if (FuncDeclaration *f = isFuncAddress(init->exp, &hasOverloads)) | |
655 | { | |
656 | if (f->checkForwardRef(init->loc)) | |
657 | { | |
658 | result = new ErrorInitializer(); | |
659 | return; | |
660 | } | |
661 | ||
662 | if (hasOverloads && !f->isUnique()) | |
663 | { | |
664 | init->exp->error("cannot infer type from overloaded function symbol %s", init->exp->toChars()); | |
665 | result = new ErrorInitializer(); | |
666 | return; | |
667 | } | |
668 | } | |
669 | if (init->exp->op == TOKaddress) | |
670 | { | |
671 | AddrExp *ae = (AddrExp *)init->exp; | |
672 | if (ae->e1->op == TOKoverloadset) | |
673 | { | |
674 | init->exp->error("cannot infer type from overloaded function symbol %s", init->exp->toChars()); | |
675 | result = new ErrorInitializer(); | |
676 | return; | |
677 | } | |
678 | } | |
679 | ||
680 | if (init->exp->op == TOKerror) | |
681 | { | |
682 | result = new ErrorInitializer(); | |
683 | return; | |
684 | } | |
685 | if (!init->exp->type) | |
686 | { | |
687 | result = new ErrorInitializer(); | |
688 | return; | |
689 | } | |
690 | result = init; | |
691 | } | |
692 | }; | |
693 | ||
694 | /* Translates to an expression to infer type. | |
695 | * Returns ExpInitializer or ErrorInitializer. | |
696 | */ | |
697 | Initializer *inferType(Initializer *init, Scope *sc) | |
698 | { | |
699 | InferTypeVisitor v = InferTypeVisitor(sc); | |
700 | init->accept(&v); | |
701 | return v.result; | |
702 | } | |
703 | ||
704 | class InitToExpressionVisitor : public Visitor | |
705 | { | |
706 | public: | |
707 | Expression *result; | |
708 | Type *itype; | |
709 | ||
710 | InitToExpressionVisitor(Type *itype) | |
711 | { | |
712 | this->result = NULL; | |
713 | this->itype = itype; | |
714 | } | |
715 | ||
716 | void visit(ErrorInitializer *) | |
717 | { | |
718 | result = new ErrorExp(); | |
719 | } | |
720 | ||
721 | void visit(VoidInitializer *) | |
722 | { | |
723 | result = NULL; | |
724 | } | |
725 | ||
726 | /*************************************** | |
727 | * This works by transforming a struct initializer into | |
728 | * a struct literal. In the future, the two should be the | |
729 | * same thing. | |
730 | */ | |
731 | void visit(StructInitializer *) | |
732 | { | |
733 | // cannot convert to an expression without target 'ad' | |
734 | result = NULL; | |
735 | } | |
736 | ||
737 | /******************************** | |
738 | * If possible, convert array initializer to array literal. | |
739 | * Otherwise return NULL. | |
740 | */ | |
741 | ||
742 | void visit(ArrayInitializer *init) | |
743 | { | |
744 | //printf("ArrayInitializer::toExpression(), dim = %d\n", init->dim); | |
745 | //static int i; if (++i == 2) halt(); | |
746 | ||
747 | Expressions *elements; | |
748 | unsigned edim; | |
749 | const unsigned amax = 0x80000000; | |
750 | Type *t = NULL; | |
751 | if (init->type) | |
752 | { | |
753 | if (init->type == Type::terror) | |
754 | { | |
755 | result = new ErrorExp(); | |
756 | return; | |
757 | } | |
758 | ||
759 | t = init->type->toBasetype(); | |
760 | switch (t->ty) | |
761 | { | |
762 | case Tvector: | |
763 | t = ((TypeVector *)t)->basetype; | |
764 | /* fall through */ | |
765 | ||
766 | case Tsarray: | |
767 | { | |
768 | uinteger_t adim = ((TypeSArray *)t)->dim->toInteger(); | |
769 | if (adim >= amax) | |
770 | goto Lno; | |
771 | edim = (unsigned)adim; | |
772 | break; | |
773 | } | |
774 | ||
775 | case Tpointer: | |
776 | case Tarray: | |
777 | edim = init->dim; | |
778 | break; | |
779 | ||
780 | default: | |
781 | assert(0); | |
782 | } | |
783 | } | |
784 | else | |
785 | { | |
786 | edim = (unsigned)init->value.dim; | |
787 | for (size_t i = 0, j = 0; i < init->value.dim; i++, j++) | |
788 | { | |
789 | if (init->index[i]) | |
790 | { | |
791 | if (init->index[i]->op == TOKint64) | |
792 | { | |
793 | const uinteger_t idxval = init->index[i]->toInteger(); | |
794 | if (idxval >= amax) | |
795 | goto Lno; | |
796 | j = (size_t)idxval; | |
797 | } | |
798 | else | |
799 | goto Lno; | |
800 | } | |
801 | if (j >= edim) | |
802 | edim = (unsigned)(j + 1); | |
803 | } | |
804 | } | |
805 | ||
806 | elements = new Expressions(); | |
807 | elements->setDim(edim); | |
808 | elements->zero(); | |
809 | for (size_t i = 0, j = 0; i < init->value.dim; i++, j++) | |
810 | { | |
811 | if (init->index[i]) | |
812 | j = (size_t)(init->index[i])->toInteger(); | |
813 | assert(j < edim); | |
814 | Initializer *iz = init->value[i]; | |
815 | if (!iz) | |
816 | goto Lno; | |
817 | Expression *ex = initializerToExpression(iz); | |
818 | if (!ex) | |
819 | { | |
820 | goto Lno; | |
821 | } | |
822 | (*elements)[j] = ex; | |
823 | } | |
824 | ||
825 | /* Fill in any missing elements with the default initializer | |
826 | */ | |
827 | { | |
828 | Expression *_init = NULL; | |
829 | for (size_t i = 0; i < edim; i++) | |
830 | { | |
831 | if (!(*elements)[i]) | |
832 | { | |
833 | if (!init->type) | |
834 | goto Lno; | |
835 | if (!_init) | |
836 | _init = ((TypeNext *)t)->next->defaultInit(); | |
837 | (*elements)[i] = _init; | |
838 | } | |
839 | } | |
840 | ||
841 | /* Expand any static array initializers that are a single expression | |
842 | * into an array of them | |
843 | */ | |
844 | if (t) | |
845 | { | |
846 | Type *tn = t->nextOf()->toBasetype(); | |
847 | if (tn->ty == Tsarray) | |
848 | { | |
849 | size_t dim = ((TypeSArray *)tn)->dim->toInteger(); | |
850 | Type *te = tn->nextOf()->toBasetype(); | |
851 | for (size_t i = 0; i < elements->dim; i++) | |
852 | { | |
853 | Expression *e = (*elements)[i]; | |
854 | if (te->equals(e->type)) | |
855 | { | |
856 | Expressions *elements2 = new Expressions(); | |
857 | elements2->setDim(dim); | |
858 | for (size_t j = 0; j < dim; j++) | |
859 | (*elements2)[j] = e; | |
255b2d91 | 860 | e = new ArrayLiteralExp(e->loc, tn, elements2); |
b4c522fa IB |
861 | (*elements)[i] = e; |
862 | } | |
863 | } | |
864 | } | |
865 | } | |
866 | ||
867 | /* If any elements are errors, then the whole thing is an error | |
868 | */ | |
869 | for (size_t i = 0; i < edim; i++) | |
870 | { | |
871 | Expression *e = (*elements)[i]; | |
872 | if (e->op == TOKerror) | |
873 | { | |
874 | result = e; | |
875 | return; | |
876 | } | |
877 | } | |
878 | ||
255b2d91 | 879 | Expression *e = new ArrayLiteralExp(init->loc, init->type, elements); |
b4c522fa IB |
880 | result = e; |
881 | return; | |
882 | } | |
883 | ||
884 | Lno: | |
885 | result = NULL; | |
886 | } | |
887 | ||
888 | void visit(ExpInitializer *i) | |
889 | { | |
890 | if (itype) | |
891 | { | |
892 | //printf("ExpInitializer::toExpression(t = %s) exp = %s\n", itype->toChars(), i->exp->toChars()); | |
893 | Type *tb = itype->toBasetype(); | |
894 | Expression *e = (i->exp->op == TOKconstruct || i->exp->op == TOKblit) ? ((AssignExp *)i->exp)->e2 : i->exp; | |
895 | if (tb->ty == Tsarray && e->implicitConvTo(tb->nextOf())) | |
896 | { | |
897 | TypeSArray *tsa = (TypeSArray *)tb; | |
898 | size_t d = (size_t)tsa->dim->toInteger(); | |
899 | Expressions *elements = new Expressions(); | |
900 | elements->setDim(d); | |
901 | for (size_t i = 0; i < d; i++) | |
902 | (*elements)[i] = e; | |
255b2d91 | 903 | ArrayLiteralExp *ae = new ArrayLiteralExp(e->loc, itype, elements); |
b4c522fa IB |
904 | result = ae; |
905 | return; | |
906 | } | |
907 | } | |
908 | result = i->exp; | |
909 | } | |
910 | }; | |
911 | ||
912 | Expression *initializerToExpression(Initializer *i, Type *t) | |
913 | { | |
914 | InitToExpressionVisitor v = InitToExpressionVisitor(t); | |
915 | i->accept(&v); | |
916 | return v.result; | |
917 | } |