Mercurial > projects > ldc
comparison dmd2/declaration.c @ 758:f04dde6e882c
Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 11 Nov 2008 01:38:48 +0100 |
parents | |
children | 340acf1535d0 |
comparison
equal
deleted
inserted
replaced
757:2c730d530c98 | 758:f04dde6e882c |
---|---|
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 "init.h" | |
15 #include "declaration.h" | |
16 #include "attrib.h" | |
17 #include "mtype.h" | |
18 #include "template.h" | |
19 #include "scope.h" | |
20 #include "aggregate.h" | |
21 #include "module.h" | |
22 #include "id.h" | |
23 #include "expression.h" | |
24 #include "hdrgen.h" | |
25 | |
26 /********************************* Declaration ****************************/ | |
27 | |
28 Declaration::Declaration(Identifier *id) | |
29 : Dsymbol(id) | |
30 { | |
31 type = NULL; | |
32 originalType = NULL; | |
33 storage_class = STCundefined; | |
34 protection = PROTundefined; | |
35 linkage = LINKdefault; | |
36 } | |
37 | |
38 void Declaration::semantic(Scope *sc) | |
39 { | |
40 } | |
41 | |
42 const char *Declaration::kind() | |
43 { | |
44 return "declaration"; | |
45 } | |
46 | |
47 unsigned Declaration::size(Loc loc) | |
48 { | |
49 assert(type); | |
50 return type->size(); | |
51 } | |
52 | |
53 int Declaration::isStaticConstructor() | |
54 { | |
55 return FALSE; | |
56 } | |
57 | |
58 int Declaration::isStaticDestructor() | |
59 { | |
60 return FALSE; | |
61 } | |
62 | |
63 int Declaration::isDelete() | |
64 { | |
65 return FALSE; | |
66 } | |
67 | |
68 int Declaration::isDataseg() | |
69 { | |
70 return FALSE; | |
71 } | |
72 | |
73 int Declaration::isCodeseg() | |
74 { | |
75 return FALSE; | |
76 } | |
77 | |
78 enum PROT Declaration::prot() | |
79 { | |
80 return protection; | |
81 } | |
82 | |
83 /************************************* | |
84 * Check to see if declaration can be modified in this context (sc). | |
85 * Issue error if not. | |
86 */ | |
87 | |
88 #if DMDV2 | |
89 void Declaration::checkModify(Loc loc, Scope *sc, Type *t) | |
90 { | |
91 if (sc->incontract && isParameter()) | |
92 error(loc, "cannot modify parameter '%s' in contract", toChars()); | |
93 | |
94 if (isCtorinit()) | |
95 { // It's only modifiable if inside the right constructor | |
96 Dsymbol *s = sc->func; | |
97 while (1) | |
98 { | |
99 FuncDeclaration *fd = NULL; | |
100 if (s) | |
101 fd = s->isFuncDeclaration(); | |
102 if (fd && | |
103 ((fd->isCtorDeclaration() && storage_class & STCfield) || | |
104 (fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) && | |
105 fd->toParent() == toParent() | |
106 ) | |
107 { | |
108 VarDeclaration *v = isVarDeclaration(); | |
109 assert(v); | |
110 v->ctorinit = 1; | |
111 //printf("setting ctorinit\n"); | |
112 } | |
113 else | |
114 { | |
115 if (s) | |
116 { s = s->toParent2(); | |
117 continue; | |
118 } | |
119 else | |
120 { | |
121 const char *p = isStatic() ? "static " : ""; | |
122 error(loc, "can only initialize %sconst %s inside %sconstructor", | |
123 p, toChars(), p); | |
124 } | |
125 } | |
126 break; | |
127 } | |
128 } | |
129 else | |
130 { | |
131 VarDeclaration *v = isVarDeclaration(); | |
132 if (v && v->canassign == 0) | |
133 { | |
134 const char *p = NULL; | |
135 if (isConst()) | |
136 p = "const"; | |
137 else if (isInvariant()) | |
138 p = "invariant"; | |
139 else if (storage_class & STCmanifest) | |
140 p = "manifest constant"; | |
141 else if (!t->isAssignable()) | |
142 p = "struct with immutable members"; | |
143 if (p) | |
144 { error(loc, "cannot modify %s", p); | |
145 halt(); | |
146 } | |
147 } | |
148 } | |
149 } | |
150 #endif | |
151 | |
152 | |
153 /********************************* TupleDeclaration ****************************/ | |
154 | |
155 TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects) | |
156 : Declaration(id) | |
157 { | |
158 this->type = NULL; | |
159 this->objects = objects; | |
160 this->isexp = 0; | |
161 this->tupletype = NULL; | |
162 } | |
163 | |
164 Dsymbol *TupleDeclaration::syntaxCopy(Dsymbol *s) | |
165 { | |
166 assert(0); | |
167 return NULL; | |
168 } | |
169 | |
170 const char *TupleDeclaration::kind() | |
171 { | |
172 return "tuple"; | |
173 } | |
174 | |
175 Type *TupleDeclaration::getType() | |
176 { | |
177 /* If this tuple represents a type, return that type | |
178 */ | |
179 | |
180 //printf("TupleDeclaration::getType() %s\n", toChars()); | |
181 if (isexp) | |
182 return NULL; | |
183 if (!tupletype) | |
184 { | |
185 /* It's only a type tuple if all the Object's are types | |
186 */ | |
187 for (size_t i = 0; i < objects->dim; i++) | |
188 { Object *o = (Object *)objects->data[i]; | |
189 | |
190 if (o->dyncast() != DYNCAST_TYPE) | |
191 { | |
192 //printf("\tnot[%d], %p, %d\n", i, o, o->dyncast()); | |
193 return NULL; | |
194 } | |
195 } | |
196 | |
197 /* We know it's a type tuple, so build the TypeTuple | |
198 */ | |
199 Arguments *args = new Arguments(); | |
200 args->setDim(objects->dim); | |
201 OutBuffer buf; | |
202 for (size_t i = 0; i < objects->dim; i++) | |
203 { Type *t = (Type *)objects->data[i]; | |
204 | |
205 //printf("type = %s\n", t->toChars()); | |
206 #if 0 | |
207 buf.printf("_%s_%d", ident->toChars(), i); | |
208 char *name = (char *)buf.extractData(); | |
209 Identifier *id = new Identifier(name, TOKidentifier); | |
210 Argument *arg = new Argument(STCin, t, id, NULL); | |
211 #else | |
212 Argument *arg = new Argument(0, t, NULL, NULL); | |
213 #endif | |
214 args->data[i] = (void *)arg; | |
215 } | |
216 | |
217 tupletype = new TypeTuple(args); | |
218 } | |
219 | |
220 return tupletype; | |
221 } | |
222 | |
223 int TupleDeclaration::needThis() | |
224 { | |
225 //printf("TupleDeclaration::needThis(%s)\n", toChars()); | |
226 for (size_t i = 0; i < objects->dim; i++) | |
227 { Object *o = (Object *)objects->data[i]; | |
228 if (o->dyncast() == DYNCAST_EXPRESSION) | |
229 { Expression *e = (Expression *)o; | |
230 if (e->op == TOKdsymbol) | |
231 { DsymbolExp *ve = (DsymbolExp *)e; | |
232 Declaration *d = ve->s->isDeclaration(); | |
233 if (d && d->needThis()) | |
234 { | |
235 return 1; | |
236 } | |
237 } | |
238 } | |
239 } | |
240 return 0; | |
241 } | |
242 | |
243 /********************************* TypedefDeclaration ****************************/ | |
244 | |
245 TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init) | |
246 : Declaration(id) | |
247 { | |
248 this->type = new TypeTypedef(this); | |
249 this->basetype = basetype->toBasetype(); | |
250 this->init = init; | |
251 #ifdef _DH | |
252 this->htype = NULL; | |
253 this->hbasetype = NULL; | |
254 #endif | |
255 this->sem = 0; | |
256 this->inuse = 0; | |
257 this->loc = loc; | |
258 this->sinit = NULL; | |
259 } | |
260 | |
261 Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s) | |
262 { | |
263 Type *basetype = this->basetype->syntaxCopy(); | |
264 | |
265 Initializer *init = NULL; | |
266 if (this->init) | |
267 init = this->init->syntaxCopy(); | |
268 | |
269 assert(!s); | |
270 TypedefDeclaration *st; | |
271 st = new TypedefDeclaration(loc, ident, basetype, init); | |
272 #ifdef _DH | |
273 // Syntax copy for header file | |
274 if (!htype) // Don't overwrite original | |
275 { if (type) // Make copy for both old and new instances | |
276 { htype = type->syntaxCopy(); | |
277 st->htype = type->syntaxCopy(); | |
278 } | |
279 } | |
280 else // Make copy of original for new instance | |
281 st->htype = htype->syntaxCopy(); | |
282 if (!hbasetype) | |
283 { if (basetype) | |
284 { hbasetype = basetype->syntaxCopy(); | |
285 st->hbasetype = basetype->syntaxCopy(); | |
286 } | |
287 } | |
288 else | |
289 st->hbasetype = hbasetype->syntaxCopy(); | |
290 #endif | |
291 return st; | |
292 } | |
293 | |
294 void TypedefDeclaration::semantic(Scope *sc) | |
295 { | |
296 //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem); | |
297 if (sem == 0) | |
298 { sem = 1; | |
299 basetype = basetype->semantic(loc, sc); | |
300 sem = 2; | |
301 type = type->semantic(loc, sc); | |
302 if (sc->parent->isFuncDeclaration() && init) | |
303 semantic2(sc); | |
304 storage_class |= sc->stc & STCdeprecated; | |
305 } | |
306 else if (sem == 1) | |
307 { | |
308 error("circular definition"); | |
309 } | |
310 } | |
311 | |
312 void TypedefDeclaration::semantic2(Scope *sc) | |
313 { | |
314 //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem); | |
315 if (sem == 2) | |
316 { sem = 3; | |
317 if (init) | |
318 { | |
319 init = init->semantic(sc, basetype); | |
320 | |
321 ExpInitializer *ie = init->isExpInitializer(); | |
322 if (ie) | |
323 { | |
324 if (ie->exp->type == basetype) | |
325 ie->exp->type = type; | |
326 } | |
327 } | |
328 } | |
329 } | |
330 | |
331 const char *TypedefDeclaration::kind() | |
332 { | |
333 return "typedef"; | |
334 } | |
335 | |
336 Type *TypedefDeclaration::getType() | |
337 { | |
338 return type; | |
339 } | |
340 | |
341 void TypedefDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
342 { | |
343 buf->writestring("typedef "); | |
344 basetype->toCBuffer(buf, ident, hgs); | |
345 if (init) | |
346 { | |
347 buf->writestring(" = "); | |
348 init->toCBuffer(buf, hgs); | |
349 } | |
350 buf->writeByte(';'); | |
351 buf->writenl(); | |
352 } | |
353 | |
354 /********************************* AliasDeclaration ****************************/ | |
355 | |
356 AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type) | |
357 : Declaration(id) | |
358 { | |
359 //printf("AliasDeclaration(id = '%s', type = %p)\n", id->toChars(), type); | |
360 //printf("type = '%s'\n", type->toChars()); | |
361 this->loc = loc; | |
362 this->type = type; | |
363 this->aliassym = NULL; | |
364 #ifdef _DH | |
365 this->htype = NULL; | |
366 this->haliassym = NULL; | |
367 #endif | |
368 this->overnext = NULL; | |
369 this->inSemantic = 0; | |
370 assert(type); | |
371 } | |
372 | |
373 AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s) | |
374 : Declaration(id) | |
375 { | |
376 //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s); | |
377 assert(s != this); | |
378 this->loc = loc; | |
379 this->type = NULL; | |
380 this->aliassym = s; | |
381 #ifdef _DH | |
382 this->htype = NULL; | |
383 this->haliassym = NULL; | |
384 #endif | |
385 this->overnext = NULL; | |
386 this->inSemantic = 0; | |
387 assert(s); | |
388 } | |
389 | |
390 Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s) | |
391 { | |
392 //printf("AliasDeclaration::syntaxCopy()\n"); | |
393 assert(!s); | |
394 AliasDeclaration *sa; | |
395 if (type) | |
396 sa = new AliasDeclaration(loc, ident, type->syntaxCopy()); | |
397 else | |
398 sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL)); | |
399 #ifdef _DH | |
400 // Syntax copy for header file | |
401 if (!htype) // Don't overwrite original | |
402 { if (type) // Make copy for both old and new instances | |
403 { htype = type->syntaxCopy(); | |
404 sa->htype = type->syntaxCopy(); | |
405 } | |
406 } | |
407 else // Make copy of original for new instance | |
408 sa->htype = htype->syntaxCopy(); | |
409 if (!haliassym) | |
410 { if (aliassym) | |
411 { haliassym = aliassym->syntaxCopy(s); | |
412 sa->haliassym = aliassym->syntaxCopy(s); | |
413 } | |
414 } | |
415 else | |
416 sa->haliassym = haliassym->syntaxCopy(s); | |
417 #endif | |
418 return sa; | |
419 } | |
420 | |
421 void AliasDeclaration::semantic(Scope *sc) | |
422 { | |
423 //printf("AliasDeclaration::semantic() %s\n", toChars()); | |
424 if (aliassym) | |
425 { | |
426 if (aliassym->isTemplateInstance()) | |
427 aliassym->semantic(sc); | |
428 return; | |
429 } | |
430 this->inSemantic = 1; | |
431 | |
432 if (storage_class & STCconst) | |
433 error("cannot be const"); | |
434 | |
435 storage_class |= sc->stc & STCdeprecated; | |
436 | |
437 // Given: | |
438 // alias foo.bar.abc def; | |
439 // it is not knowable from the syntax whether this is an alias | |
440 // for a type or an alias for a symbol. It is up to the semantic() | |
441 // pass to distinguish. | |
442 // If it is a type, then type is set and getType() will return that | |
443 // type. If it is a symbol, then aliassym is set and type is NULL - | |
444 // toAlias() will return aliasssym. | |
445 | |
446 Dsymbol *s; | |
447 Type *t; | |
448 Expression *e; | |
449 | |
450 /* This section is needed because resolve() will: | |
451 * const x = 3; | |
452 * alias x y; | |
453 * try to alias y to 3. | |
454 */ | |
455 s = type->toDsymbol(sc); | |
456 if (s && ((s->getType() && type->equals(s->getType())) || s->isEnumMember())) | |
457 goto L2; // it's a symbolic alias | |
458 | |
459 //printf("alias type is %s\n", type->toChars()); | |
460 type->resolve(loc, sc, &e, &t, &s); | |
461 if (s) | |
462 { | |
463 goto L2; | |
464 } | |
465 else if (e) | |
466 { | |
467 // Try to convert Expression to Dsymbol | |
468 s = getDsymbol(e); | |
469 if (s) | |
470 goto L2; | |
471 | |
472 error("cannot alias an expression %s", e->toChars()); | |
473 t = e->type; | |
474 } | |
475 else if (t) | |
476 type = t; | |
477 if (overnext) | |
478 ScopeDsymbol::multiplyDefined(0, this, overnext); | |
479 this->inSemantic = 0; | |
480 return; | |
481 | |
482 L2: | |
483 //printf("alias is a symbol %s %s\n", s->kind(), s->toChars()); | |
484 type = NULL; | |
485 VarDeclaration *v = s->isVarDeclaration(); | |
486 if (v && v->linkage == LINKdefault) | |
487 { | |
488 error("forward reference of %s", v->toChars()); | |
489 s = NULL; | |
490 } | |
491 else | |
492 { | |
493 FuncDeclaration *f = s->toAlias()->isFuncDeclaration(); | |
494 if (f) | |
495 { | |
496 if (overnext) | |
497 { | |
498 FuncAliasDeclaration *fa = new FuncAliasDeclaration(f); | |
499 if (!fa->overloadInsert(overnext)) | |
500 ScopeDsymbol::multiplyDefined(0, f, overnext); | |
501 overnext = NULL; | |
502 s = fa; | |
503 s->parent = sc->parent; | |
504 } | |
505 } | |
506 if (overnext) | |
507 ScopeDsymbol::multiplyDefined(0, s, overnext); | |
508 if (s == this) | |
509 { | |
510 assert(global.errors); | |
511 s = NULL; | |
512 } | |
513 } | |
514 aliassym = s; | |
515 this->inSemantic = 0; | |
516 } | |
517 | |
518 int AliasDeclaration::overloadInsert(Dsymbol *s) | |
519 { | |
520 /* Don't know yet what the aliased symbol is, so assume it can | |
521 * be overloaded and check later for correctness. | |
522 */ | |
523 | |
524 //printf("AliasDeclaration::overloadInsert('%s')\n", s->toChars()); | |
525 if (overnext == NULL) | |
526 { overnext = s; | |
527 return TRUE; | |
528 } | |
529 else | |
530 { | |
531 return overnext->overloadInsert(s); | |
532 } | |
533 } | |
534 | |
535 const char *AliasDeclaration::kind() | |
536 { | |
537 return "alias"; | |
538 } | |
539 | |
540 Type *AliasDeclaration::getType() | |
541 { | |
542 return type; | |
543 } | |
544 | |
545 Dsymbol *AliasDeclaration::toAlias() | |
546 { | |
547 //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : ""); | |
548 assert(this != aliassym); | |
549 //static int count; if (++count == 10) *(char*)0=0; | |
550 if (inSemantic) | |
551 { error("recursive alias declaration"); | |
552 // return this; | |
553 } | |
554 Dsymbol *s = aliassym ? aliassym->toAlias() : this; | |
555 return s; | |
556 } | |
557 | |
558 void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
559 { | |
560 buf->writestring("alias "); | |
561 #if 0 && _DH | |
562 if (hgs->hdrgen) | |
563 { | |
564 if (haliassym) | |
565 { | |
566 haliassym->toCBuffer(buf, hgs); | |
567 buf->writeByte(' '); | |
568 buf->writestring(ident->toChars()); | |
569 } | |
570 else | |
571 htype->toCBuffer(buf, ident, hgs); | |
572 } | |
573 else | |
574 #endif | |
575 { | |
576 if (aliassym) | |
577 { | |
578 aliassym->toCBuffer(buf, hgs); | |
579 buf->writeByte(' '); | |
580 buf->writestring(ident->toChars()); | |
581 } | |
582 else | |
583 type->toCBuffer(buf, ident, hgs); | |
584 } | |
585 buf->writeByte(';'); | |
586 buf->writenl(); | |
587 } | |
588 | |
589 /********************************* VarDeclaration ****************************/ | |
590 | |
591 VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer *init) | |
592 : Declaration(id) | |
593 { | |
594 //printf("VarDeclaration('%s')\n", id->toChars()); | |
595 #ifdef DEBUG | |
596 if (!type && !init) | |
597 { printf("VarDeclaration('%s')\n", id->toChars()); | |
598 //*(char*)0=0; | |
599 } | |
600 #endif | |
601 assert(type || init); | |
602 this->type = type; | |
603 this->init = init; | |
604 #ifdef _DH | |
605 this->htype = NULL; | |
606 this->hinit = NULL; | |
607 #endif | |
608 this->loc = loc; | |
609 offset = 0; | |
610 noauto = 0; | |
611 inuse = 0; | |
612 ctorinit = 0; | |
613 aliassym = NULL; | |
614 onstack = 0; | |
615 canassign = 0; | |
616 value = NULL; | |
617 scope = NULL; | |
618 | |
619 // LDC | |
620 anonDecl = NULL; | |
621 } | |
622 | |
623 Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) | |
624 { | |
625 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars()); | |
626 | |
627 VarDeclaration *sv; | |
628 if (s) | |
629 { sv = (VarDeclaration *)s; | |
630 } | |
631 else | |
632 { | |
633 Initializer *init = NULL; | |
634 if (this->init) | |
635 { init = this->init->syntaxCopy(); | |
636 //init->isExpInitializer()->exp->print(); | |
637 //init->isExpInitializer()->exp->dump(0); | |
638 } | |
639 | |
640 sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init); | |
641 sv->storage_class = storage_class; | |
642 } | |
643 #ifdef _DH | |
644 // Syntax copy for header file | |
645 if (!htype) // Don't overwrite original | |
646 { if (type) // Make copy for both old and new instances | |
647 { htype = type->syntaxCopy(); | |
648 sv->htype = type->syntaxCopy(); | |
649 } | |
650 } | |
651 else // Make copy of original for new instance | |
652 sv->htype = htype->syntaxCopy(); | |
653 if (!hinit) | |
654 { if (init) | |
655 { hinit = init->syntaxCopy(); | |
656 sv->hinit = init->syntaxCopy(); | |
657 } | |
658 } | |
659 else | |
660 sv->hinit = hinit->syntaxCopy(); | |
661 #endif | |
662 return sv; | |
663 } | |
664 | |
665 void VarDeclaration::semantic(Scope *sc) | |
666 { | |
667 #if 0 | |
668 printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars()); | |
669 printf(" type = %s\n", type ? type->toChars() : "null"); | |
670 printf(" stc = x%x\n", sc->stc); | |
671 printf(" storage_class = x%x\n", storage_class); | |
672 printf("linkage = %d\n", sc->linkage); | |
673 //if (strcmp(toChars(), "mul") == 0) halt(); | |
674 #endif | |
675 | |
676 storage_class |= sc->stc; | |
677 if (storage_class & STCextern && init) | |
678 error("extern symbols cannot have initializers"); | |
679 | |
680 /* If auto type inference, do the inference | |
681 */ | |
682 int inferred = 0; | |
683 if (!type) | |
684 { inuse++; | |
685 type = init->inferType(sc); | |
686 inuse--; | |
687 inferred = 1; | |
688 | |
689 /* This is a kludge to support the existing syntax for RAII | |
690 * declarations. | |
691 */ | |
692 storage_class &= ~STCauto; | |
693 originalType = type; | |
694 } | |
695 else | |
696 { if (!originalType) | |
697 originalType = type; | |
698 type = type->semantic(loc, sc); | |
699 } | |
700 //printf(" semantic type = %s\n", type ? type->toChars() : "null"); | |
701 | |
702 type->checkDeprecated(loc, sc); | |
703 linkage = sc->linkage; | |
704 this->parent = sc->parent; | |
705 //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars()); | |
706 protection = sc->protection; | |
707 //printf("sc->stc = %x\n", sc->stc); | |
708 //printf("storage_class = x%x\n", storage_class); | |
709 | |
710 Dsymbol *parent = toParent(); | |
711 FuncDeclaration *fd = parent->isFuncDeclaration(); | |
712 | |
713 Type *tb = type->toBasetype(); | |
714 if (tb->ty == Tvoid && !(storage_class & STClazy)) | |
715 { error("voids have no value"); | |
716 type = Type::terror; | |
717 tb = type; | |
718 } | |
719 if (tb->ty == Tfunction) | |
720 { error("cannot be declared to be a function"); | |
721 type = Type::terror; | |
722 tb = type; | |
723 } | |
724 if (tb->ty == Tstruct) | |
725 { TypeStruct *ts = (TypeStruct *)tb; | |
726 | |
727 if (!ts->sym->members) | |
728 { | |
729 error("no definition of struct %s", ts->toChars()); | |
730 } | |
731 } | |
732 | |
733 if (tb->ty == Ttuple) | |
734 { /* Instead, declare variables for each of the tuple elements | |
735 * and add those. | |
736 */ | |
737 TypeTuple *tt = (TypeTuple *)tb; | |
738 size_t nelems = Argument::dim(tt->arguments); | |
739 Objects *exps = new Objects(); | |
740 exps->setDim(nelems); | |
741 Expression *ie = init ? init->toExpression() : NULL; | |
742 | |
743 for (size_t i = 0; i < nelems; i++) | |
744 { Argument *arg = Argument::getNth(tt->arguments, i); | |
745 | |
746 OutBuffer buf; | |
747 buf.printf("_%s_field_%"PRIuSIZE, ident->toChars(), i); | |
748 buf.writeByte(0); | |
749 char *name = (char *)buf.extractData(); | |
750 Identifier *id = new Identifier(name, TOKidentifier); | |
751 | |
752 Expression *einit = ie; | |
753 if (ie && ie->op == TOKtuple) | |
754 { einit = (Expression *)((TupleExp *)ie)->exps->data[i]; | |
755 } | |
756 Initializer *ti = init; | |
757 if (einit) | |
758 { ti = new ExpInitializer(einit->loc, einit); | |
759 } | |
760 | |
761 VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti); | |
762 //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars()); | |
763 v->semantic(sc); | |
764 | |
765 if (sc->scopesym) | |
766 { //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars()); | |
767 if (sc->scopesym->members) | |
768 sc->scopesym->members->push(v); | |
769 } | |
770 | |
771 Expression *e = new DsymbolExp(loc, v); | |
772 exps->data[i] = e; | |
773 } | |
774 TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps); | |
775 v2->isexp = 1; | |
776 aliassym = v2; | |
777 return; | |
778 } | |
779 | |
780 Lagain: | |
781 if (storage_class & STCinvariant) | |
782 { | |
783 type = type->invariantOf(); | |
784 } | |
785 else if (storage_class & (STCconst | STCin)) | |
786 { | |
787 if (!type->isInvariant()) | |
788 type = type->constOf(); | |
789 } | |
790 else if (type->isConst()) | |
791 storage_class |= STCconst; | |
792 else if (type->isInvariant()) | |
793 storage_class |= STCinvariant; | |
794 | |
795 if (isSynchronized()) | |
796 { | |
797 error("variable %s cannot be synchronized", toChars()); | |
798 } | |
799 else if (isOverride()) | |
800 { | |
801 error("override cannot be applied to variable"); | |
802 } | |
803 else if (isAbstract()) | |
804 { | |
805 error("abstract cannot be applied to variable"); | |
806 } | |
807 else if (storage_class & STCfinal) | |
808 { | |
809 error("final cannot be applied to variable"); | |
810 } | |
811 | |
812 if (storage_class & (STCstatic | STCextern | STCmanifest | STCtemplateparameter | STCtls)) | |
813 { | |
814 } | |
815 else | |
816 { | |
817 AggregateDeclaration *aad = sc->anonAgg; | |
818 if (!aad) | |
819 aad = parent->isAggregateDeclaration(); | |
820 if (aad) | |
821 { assert(!(storage_class & (STCextern | STCstatic | STCtls))); | |
822 | |
823 if (storage_class & (STCconst | STCinvariant) && init) | |
824 { | |
825 if (!type->toBasetype()->isTypeBasic()) | |
826 storage_class |= STCstatic; | |
827 } | |
828 else | |
829 aad->addField(sc, this); | |
830 } | |
831 | |
832 InterfaceDeclaration *id = parent->isInterfaceDeclaration(); | |
833 if (id) | |
834 { | |
835 error("field not allowed in interface"); | |
836 } | |
837 | |
838 /* Templates cannot add fields to aggregates | |
839 */ | |
840 TemplateInstance *ti = parent->isTemplateInstance(); | |
841 if (ti) | |
842 { | |
843 // Take care of nested templates | |
844 while (1) | |
845 { | |
846 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); | |
847 if (!ti2) | |
848 break; | |
849 ti = ti2; | |
850 } | |
851 | |
852 // If it's a member template | |
853 AggregateDeclaration *ad = ti->tempdecl->isMember(); | |
854 if (ad && storage_class != STCundefined) | |
855 { | |
856 error("cannot use template to add field to aggregate '%s'", ad->toChars()); | |
857 } | |
858 } | |
859 } | |
860 | |
861 if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref) | |
862 error("only parameters or foreach declarations can be ref"); | |
863 | |
864 if (type->isauto() && !noauto) | |
865 { | |
866 if (storage_class & (STCfield | STCout | STCref | STCstatic | STCmanifest | STCtls) || !fd) | |
867 { | |
868 error("globals, statics, fields, manifest constants, ref and out parameters cannot be auto"); | |
869 } | |
870 | |
871 if (!(storage_class & (STCauto | STCscope))) | |
872 { | |
873 if (!(storage_class & STCparameter) && ident != Id::withSym) | |
874 error("reference to scope class must be scope"); | |
875 } | |
876 } | |
877 | |
878 if ((isConst() || isInvariant()) && !init && !fd) | |
879 { // Initialize by constructor only | |
880 storage_class |= STCctorinit; | |
881 } | |
882 | |
883 if (init) | |
884 storage_class |= STCinit; // remember we had an explicit initializer | |
885 else if (storage_class & STCmanifest) | |
886 error("manifest constants must have initializers"); | |
887 | |
888 enum TOK op = TOKconstruct; | |
889 if (!init && !sc->inunion && !isStatic() && fd && | |
890 (!(storage_class & (STCfield | STCin | STCforeach | STCparameter)) || (storage_class & STCout)) && | |
891 type->size() != 0) | |
892 { | |
893 // Provide a default initializer | |
894 //printf("Providing default initializer for '%s'\n", toChars()); | |
895 if (type->ty == Tstruct && | |
896 ((TypeStruct *)type)->sym->zeroInit == 1) | |
897 { /* If a struct is all zeros, as a special case | |
898 * set it's initializer to the integer 0. | |
899 * In AssignExp::toElem(), we check for this and issue | |
900 * a memset() to initialize the struct. | |
901 * Must do same check in interpreter. | |
902 */ | |
903 Expression *e = new IntegerExp(loc, 0, Type::tint32); | |
904 Expression *e1; | |
905 e1 = new VarExp(loc, this); | |
906 e = new AssignExp(loc, e1, e); | |
907 e->type = e1->type; // don't type check this, it would fail | |
908 init = new ExpInitializer(loc, e); | |
909 return; | |
910 } | |
911 else if (type->ty == Ttypedef) | |
912 { TypeTypedef *td = (TypeTypedef *)type; | |
913 if (td->sym->init) | |
914 { init = td->sym->init; | |
915 ExpInitializer *ie = init->isExpInitializer(); | |
916 if (ie) | |
917 // Make copy so we can modify it | |
918 init = new ExpInitializer(ie->loc, ie->exp); | |
919 } | |
920 else | |
921 init = getExpInitializer(); | |
922 } | |
923 else | |
924 { | |
925 init = getExpInitializer(); | |
926 } | |
927 // Default initializer is always a blit | |
928 op = TOKblit; | |
929 } | |
930 | |
931 if (init) | |
932 { | |
933 sc = sc->push(); | |
934 sc->stc &= ~(STCconst | STCinvariant | STCpure | STCnothrow | STCref | STCshared); | |
935 | |
936 ArrayInitializer *ai = init->isArrayInitializer(); | |
937 if (ai && tb->ty == Taarray) | |
938 { | |
939 init = ai->toAssocArrayInitializer(); | |
940 } | |
941 | |
942 StructInitializer *si = init->isStructInitializer(); | |
943 ExpInitializer *ei = init->isExpInitializer(); | |
944 | |
945 // See if initializer is a NewExp that can be allocated on the stack | |
946 if (ei && isScope() && ei->exp->op == TOKnew) | |
947 { NewExp *ne = (NewExp *)ei->exp; | |
948 if (!(ne->newargs && ne->newargs->dim)) | |
949 { ne->onstack = 1; | |
950 onstack = 1; | |
951 if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL)) | |
952 onstack = 2; | |
953 } | |
954 } | |
955 | |
956 // If inside function, there is no semantic3() call | |
957 if (sc->func) | |
958 { | |
959 // If local variable, use AssignExp to handle all the various | |
960 // possibilities. | |
961 if (fd && !isStatic() && !(storage_class & STCmanifest) && | |
962 !init->isVoidInitializer()) | |
963 { | |
964 //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); | |
965 if (!ei) | |
966 { | |
967 Expression *e = init->toExpression(); | |
968 if (!e) | |
969 { | |
970 init = init->semantic(sc, type); | |
971 e = init->toExpression(); | |
972 if (!e) | |
973 { error("is not a static and cannot have static initializer"); | |
974 return; | |
975 } | |
976 } | |
977 ei = new ExpInitializer(init->loc, e); | |
978 init = ei; | |
979 } | |
980 | |
981 Expression *e1 = new VarExp(loc, this); | |
982 | |
983 Type *t = type->toBasetype(); | |
984 if (t->ty == Tsarray) | |
985 { | |
986 ei->exp = ei->exp->semantic(sc); | |
987 if (!ei->exp->implicitConvTo(type)) | |
988 { | |
989 int dim = ((TypeSArray *)t)->dim->toInteger(); | |
990 // If multidimensional static array, treat as one large array | |
991 while (1) | |
992 { | |
993 t = t->nextOf()->toBasetype(); | |
994 if (t->ty != Tsarray) | |
995 break; | |
996 dim *= ((TypeSArray *)t)->dim->toInteger(); | |
997 e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex)); | |
998 } | |
999 } | |
1000 e1 = new SliceExp(loc, e1, NULL, NULL); | |
1001 } | |
1002 else if (t->ty == Tstruct) | |
1003 { | |
1004 ei->exp = ei->exp->semantic(sc); | |
1005 | |
1006 /* Look to see if initializer is a call to the constructor | |
1007 */ | |
1008 StructDeclaration *sd = ((TypeStruct *)t)->sym; | |
1009 if (sd->ctor && // there are constructors | |
1010 ei->exp->type->ty == Tstruct && // rvalue is the same struct | |
1011 ((TypeStruct *)ei->exp->type)->sym == sd && | |
1012 ei->exp->op == TOKstar) | |
1013 { | |
1014 /* Look for form of constructor call which is: | |
1015 * *__ctmp.ctor(arguments...) | |
1016 */ | |
1017 PtrExp *pe = (PtrExp *)ei->exp; | |
1018 if (pe->e1->op == TOKcall) | |
1019 { CallExp *ce = (CallExp *)pe->e1; | |
1020 if (ce->e1->op == TOKdotvar) | |
1021 { DotVarExp *dve = (DotVarExp *)ce->e1; | |
1022 if (dve->var->isCtorDeclaration()) | |
1023 { /* It's a constructor call, currently constructing | |
1024 * a temporary __ctmp. | |
1025 */ | |
1026 /* Before calling the constructor, initialize | |
1027 * variable with a bit copy of the default | |
1028 * initializer | |
1029 */ | |
1030 Expression *e = new AssignExp(loc, new VarExp(loc, this), t->defaultInit(loc)); | |
1031 e->op = TOKblit; | |
1032 e->type = t; | |
1033 ei->exp = new CommaExp(loc, e, ei->exp); | |
1034 | |
1035 /* Replace __ctmp being constructed with e1 | |
1036 */ | |
1037 dve->e1 = e1; | |
1038 return; | |
1039 } | |
1040 } | |
1041 } | |
1042 } | |
1043 | |
1044 if (!ei->exp->implicitConvTo(type)) | |
1045 { Type *ti = ei->exp->type->toBasetype(); | |
1046 // Don't cast away invariant or mutability in initializer | |
1047 if (!(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc))) | |
1048 ei->exp = new CastExp(loc, ei->exp, type); | |
1049 } | |
1050 } | |
1051 ei->exp = new AssignExp(loc, e1, ei->exp); | |
1052 ei->exp->op = op; | |
1053 canassign++; | |
1054 ei->exp = ei->exp->semantic(sc); | |
1055 canassign--; | |
1056 ei->exp->optimize(WANTvalue); | |
1057 } | |
1058 else | |
1059 { | |
1060 init = init->semantic(sc, type); | |
1061 } | |
1062 } | |
1063 else if (storage_class & (STCconst | STCinvariant | STCmanifest) || | |
1064 type->isConst() || type->isInvariant()) | |
1065 { | |
1066 /* Because we may need the results of a const declaration in a | |
1067 * subsequent type, such as an array dimension, before semantic2() | |
1068 * gets ordinarily run, try to run semantic2() now. | |
1069 * Ignore failure. | |
1070 */ | |
1071 | |
1072 if (!global.errors && !inferred) | |
1073 { | |
1074 unsigned errors = global.errors; | |
1075 global.gag++; | |
1076 //printf("+gag\n"); | |
1077 Expression *e; | |
1078 Initializer *i2 = init; | |
1079 inuse++; | |
1080 if (ei) | |
1081 { | |
1082 e = ei->exp->syntaxCopy(); | |
1083 e = e->semantic(sc); | |
1084 e = e->implicitCastTo(sc, type); | |
1085 } | |
1086 else if (si || ai) | |
1087 { i2 = init->syntaxCopy(); | |
1088 i2 = i2->semantic(sc, type); | |
1089 } | |
1090 inuse--; | |
1091 global.gag--; | |
1092 //printf("-gag\n"); | |
1093 if (errors != global.errors) // if errors happened | |
1094 { | |
1095 if (global.gag == 0) | |
1096 global.errors = errors; // act as if nothing happened | |
1097 | |
1098 /* Save scope for later use, to try again | |
1099 */ | |
1100 scope = new Scope(*sc); | |
1101 scope->setNoFree(); | |
1102 } | |
1103 else if (ei) | |
1104 { | |
1105 if (isDataseg()) | |
1106 /* static const/invariant does CTFE | |
1107 */ | |
1108 e = e->optimize(WANTvalue | WANTinterpret); | |
1109 else | |
1110 e = e->optimize(WANTvalue); | |
1111 if (e->op == TOKint64 || e->op == TOKstring) | |
1112 { | |
1113 ei->exp = e; // no errors, keep result | |
1114 } | |
1115 else | |
1116 { | |
1117 /* Save scope for later use, to try again | |
1118 */ | |
1119 scope = new Scope(*sc); | |
1120 scope->setNoFree(); | |
1121 } | |
1122 } | |
1123 else | |
1124 init = i2; // no errors, keep result | |
1125 } | |
1126 } | |
1127 sc = sc->pop(); | |
1128 } | |
1129 } | |
1130 | |
1131 void VarDeclaration::semantic2(Scope *sc) | |
1132 { | |
1133 //printf("VarDeclaration::semantic2('%s')\n", toChars()); | |
1134 if (init && !toParent()->isFuncDeclaration()) | |
1135 { inuse++; | |
1136 #if 0 | |
1137 ExpInitializer *ei = init->isExpInitializer(); | |
1138 if (ei) | |
1139 { | |
1140 ei->exp->dump(0); | |
1141 printf("type = %p\n", ei->exp->type); | |
1142 } | |
1143 #endif | |
1144 init = init->semantic(sc, type); | |
1145 inuse--; | |
1146 } | |
1147 } | |
1148 | |
1149 const char *VarDeclaration::kind() | |
1150 { | |
1151 return "variable"; | |
1152 } | |
1153 | |
1154 Dsymbol *VarDeclaration::toAlias() | |
1155 { | |
1156 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); | |
1157 assert(this != aliassym); | |
1158 Dsymbol *s = aliassym ? aliassym->toAlias() : this; | |
1159 return s; | |
1160 } | |
1161 | |
1162 void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1163 { | |
1164 if (storage_class & STCconst) | |
1165 buf->writestring("const "); | |
1166 if (storage_class & STCstatic) | |
1167 buf->writestring("static "); | |
1168 if (storage_class & STCauto) | |
1169 buf->writestring("auto "); | |
1170 #if DMDV2 | |
1171 if (storage_class & STCmanifest) | |
1172 buf->writestring("manifest "); | |
1173 if (storage_class & STCinvariant) | |
1174 buf->writestring("invariant "); | |
1175 if (storage_class & STCtls) | |
1176 buf->writestring("__thread "); | |
1177 #endif | |
1178 | |
1179 if (type) | |
1180 type->toCBuffer(buf, ident, hgs); | |
1181 else | |
1182 buf->writestring(ident->toChars()); | |
1183 if (init) | |
1184 { buf->writestring(" = "); | |
1185 ExpInitializer *ie = init->isExpInitializer(); | |
1186 if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit)) | |
1187 ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs); | |
1188 else | |
1189 init->toCBuffer(buf, hgs); | |
1190 } | |
1191 buf->writeByte(';'); | |
1192 buf->writenl(); | |
1193 } | |
1194 | |
1195 int VarDeclaration::needThis() | |
1196 { | |
1197 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class); | |
1198 return storage_class & STCfield; | |
1199 } | |
1200 | |
1201 int VarDeclaration::isImportedSymbol() | |
1202 { | |
1203 if (protection == PROTexport && !init && | |
1204 (storage_class & STCstatic || parent->isModule())) | |
1205 return TRUE; | |
1206 return FALSE; | |
1207 } | |
1208 | |
1209 void VarDeclaration::checkCtorConstInit() | |
1210 { | |
1211 #if 0 /* doesn't work if more than one static ctor */ | |
1212 if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield)) | |
1213 error("missing initializer in static constructor for const variable"); | |
1214 #endif | |
1215 } | |
1216 | |
1217 /************************************ | |
1218 * Check to see if this variable is actually in an enclosing function | |
1219 * rather than the current one. | |
1220 */ | |
1221 | |
1222 void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) | |
1223 { | |
1224 if (parent && !isDataseg() && parent != sc->parent && | |
1225 !(storage_class & STCmanifest)) | |
1226 { | |
1227 // The function that this variable is in | |
1228 FuncDeclaration *fdv = toParent()->isFuncDeclaration(); | |
1229 // The current function | |
1230 FuncDeclaration *fdthis = sc->parent->isFuncDeclaration(); | |
1231 | |
1232 if (fdv && fdthis && fdv != fdthis) | |
1233 { | |
1234 if (loc.filename) | |
1235 fdthis->getLevel(loc, fdv); | |
1236 | |
1237 for (int i = 0; i < nestedrefs.dim; i++) | |
1238 { FuncDeclaration *f = (FuncDeclaration *)nestedrefs.data[i]; | |
1239 if (f == fdthis) | |
1240 goto L1; | |
1241 } | |
1242 fdv->nestedVars.insert(this); | |
1243 nestedrefs.push(fdthis); | |
1244 L1: ; | |
1245 | |
1246 | |
1247 for (int i = 0; i < fdv->closureVars.dim; i++) | |
1248 { Dsymbol *s = (Dsymbol *)fdv->closureVars.data[i]; | |
1249 if (s == this) | |
1250 goto L2; | |
1251 } | |
1252 | |
1253 fdv->closureVars.push(this); | |
1254 L2: ; | |
1255 | |
1256 //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars()); | |
1257 } | |
1258 } | |
1259 } | |
1260 | |
1261 /**************************** | |
1262 * Get ExpInitializer for a variable, if there is one. | |
1263 */ | |
1264 | |
1265 ExpInitializer *VarDeclaration::getExpInitializer() | |
1266 { | |
1267 ExpInitializer *ei; | |
1268 | |
1269 if (init) | |
1270 ei = init->isExpInitializer(); | |
1271 else | |
1272 { | |
1273 Expression *e = type->defaultInit(loc); | |
1274 if (e) | |
1275 ei = new ExpInitializer(loc, e); | |
1276 else | |
1277 ei = NULL; | |
1278 } | |
1279 return ei; | |
1280 } | |
1281 | |
1282 /******************************************* | |
1283 * If variable has a constant expression initializer, get it. | |
1284 * Otherwise, return NULL. | |
1285 */ | |
1286 | |
1287 Expression *VarDeclaration::getConstInitializer() | |
1288 { | |
1289 if ((isConst() || isInvariant() || storage_class & STCmanifest) && | |
1290 storage_class & STCinit) | |
1291 { | |
1292 ExpInitializer *ei = getExpInitializer(); | |
1293 if (ei) | |
1294 return ei->exp; | |
1295 } | |
1296 | |
1297 return NULL; | |
1298 } | |
1299 | |
1300 /************************************* | |
1301 * Return !=0 if we can take the address of this variable. | |
1302 */ | |
1303 | |
1304 int VarDeclaration::canTakeAddressOf() | |
1305 { | |
1306 #if 0 | |
1307 /* Global variables and struct/class fields of the form: | |
1308 * const int x = 3; | |
1309 * are not stored and hence cannot have their address taken. | |
1310 */ | |
1311 if ((isConst() || isInvariant()) && | |
1312 storage_class & STCinit && | |
1313 (!(storage_class & (STCstatic | STCextern)) || (storage_class & STCfield)) && | |
1314 (!parent || toParent()->isModule() || toParent()->isTemplateInstance()) && | |
1315 type->toBasetype()->isTypeBasic() | |
1316 ) | |
1317 { | |
1318 return 0; | |
1319 } | |
1320 #else | |
1321 if (storage_class & STCmanifest) | |
1322 return 0; | |
1323 #endif | |
1324 return 1; | |
1325 } | |
1326 | |
1327 /******************************* | |
1328 * Does symbol go into data segment? | |
1329 * Includes extern variables. | |
1330 */ | |
1331 | |
1332 int VarDeclaration::isDataseg() | |
1333 { | |
1334 #if 0 | |
1335 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars()); | |
1336 printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance()); | |
1337 printf("parent = '%s'\n", parent->toChars()); | |
1338 #endif | |
1339 if (storage_class & STCmanifest) | |
1340 return 0; | |
1341 Dsymbol *parent = this->toParent(); | |
1342 if (!parent && !(storage_class & STCstatic)) | |
1343 { error("forward referenced"); | |
1344 type = Type::terror; | |
1345 return 0; | |
1346 } | |
1347 return canTakeAddressOf() && | |
1348 (storage_class & (STCstatic | STCextern | STCtls) || | |
1349 toParent()->isModule() || | |
1350 toParent()->isTemplateInstance()); | |
1351 } | |
1352 | |
1353 int VarDeclaration::hasPointers() | |
1354 { | |
1355 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty); | |
1356 return (!isDataseg() && type->hasPointers()); | |
1357 } | |
1358 | |
1359 /****************************************** | |
1360 * Return TRUE if variable needs to call the destructor. | |
1361 */ | |
1362 | |
1363 int VarDeclaration::needsAutoDtor() | |
1364 { | |
1365 //printf("VarDeclaration::needsAutoDtor() %s\n", toChars()); | |
1366 | |
1367 if (noauto || storage_class & STCnodtor) | |
1368 return FALSE; | |
1369 | |
1370 // Destructors for structs and arrays of structs | |
1371 Type *tv = type->toBasetype(); | |
1372 while (tv->ty == Tsarray) | |
1373 { TypeSArray *ta = (TypeSArray *)tv; | |
1374 tv = tv->nextOf()->toBasetype(); | |
1375 } | |
1376 if (tv->ty == Tstruct) | |
1377 { TypeStruct *ts = (TypeStruct *)tv; | |
1378 StructDeclaration *sd = ts->sym; | |
1379 if (sd->dtor) | |
1380 return TRUE; | |
1381 } | |
1382 | |
1383 // Destructors for classes | |
1384 if (storage_class & (STCauto | STCscope)) | |
1385 { | |
1386 if (type->isClassHandle()) | |
1387 return TRUE; | |
1388 } | |
1389 return FALSE; | |
1390 } | |
1391 | |
1392 | |
1393 /****************************************** | |
1394 * If a variable has an auto destructor call, return call for it. | |
1395 * Otherwise, return NULL. | |
1396 */ | |
1397 | |
1398 Expression *VarDeclaration::callAutoDtor(Scope *sc) | |
1399 { Expression *e = NULL; | |
1400 | |
1401 //printf("VarDeclaration::callAutoDtor() %s\n", toChars()); | |
1402 | |
1403 if (noauto || storage_class & STCnodtor) | |
1404 return NULL; | |
1405 | |
1406 // Destructors for structs and arrays of structs | |
1407 bool array = false; | |
1408 Type *tv = type->toBasetype(); | |
1409 while (tv->ty == Tsarray) | |
1410 { TypeSArray *ta = (TypeSArray *)tv; | |
1411 array = true; | |
1412 tv = tv->nextOf()->toBasetype(); | |
1413 } | |
1414 if (tv->ty == Tstruct) | |
1415 { TypeStruct *ts = (TypeStruct *)tv; | |
1416 StructDeclaration *sd = ts->sym; | |
1417 if (sd->dtor) | |
1418 { | |
1419 if (array) | |
1420 { | |
1421 // Typeinfo.destroy(cast(void*)&v); | |
1422 Expression *ea = new SymOffExp(loc, this, 0, 0); | |
1423 ea = new CastExp(loc, ea, Type::tvoid->pointerTo()); | |
1424 Expressions *args = new Expressions(); | |
1425 args->push(ea); | |
1426 | |
1427 Expression *et = type->getTypeInfo(sc); | |
1428 et = new DotIdExp(loc, et, Id::destroy); | |
1429 | |
1430 e = new CallExp(loc, et, args); | |
1431 } | |
1432 else | |
1433 { | |
1434 e = new VarExp(loc, this); | |
1435 e = new DotVarExp(loc, e, sd->dtor, 0); | |
1436 e = new CallExp(loc, e); | |
1437 } | |
1438 return e; | |
1439 } | |
1440 } | |
1441 | |
1442 // Destructors for classes | |
1443 if (storage_class & (STCauto | STCscope)) | |
1444 { | |
1445 for (ClassDeclaration *cd = type->isClassHandle(); | |
1446 cd; | |
1447 cd = cd->baseClass) | |
1448 { | |
1449 /* We can do better if there's a way with onstack | |
1450 * classes to determine if there's no way the monitor | |
1451 * could be set. | |
1452 */ | |
1453 //if (cd->isInterfaceDeclaration()) | |
1454 //error("interface %s cannot be scope", cd->toChars()); | |
1455 if (1 || onstack || cd->dtors.dim) // if any destructors | |
1456 { | |
1457 // delete this; | |
1458 Expression *ec; | |
1459 | |
1460 ec = new VarExp(loc, this); | |
1461 e = new DeleteExp(loc, ec); | |
1462 e->type = Type::tvoid; | |
1463 break; | |
1464 } | |
1465 } | |
1466 } | |
1467 return e; | |
1468 } | |
1469 | |
1470 | |
1471 /********************************* ClassInfoDeclaration ****************************/ | |
1472 | |
1473 ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd) | |
1474 : VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL) | |
1475 { | |
1476 this->cd = cd; | |
1477 storage_class = STCstatic; | |
1478 } | |
1479 | |
1480 Dsymbol *ClassInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1481 { | |
1482 assert(0); // should never be produced by syntax | |
1483 return NULL; | |
1484 } | |
1485 | |
1486 void ClassInfoDeclaration::semantic(Scope *sc) | |
1487 { | |
1488 } | |
1489 | |
1490 /********************************* ModuleInfoDeclaration ****************************/ | |
1491 | |
1492 ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod) | |
1493 : VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL) | |
1494 { | |
1495 this->mod = mod; | |
1496 storage_class = STCstatic; | |
1497 } | |
1498 | |
1499 Dsymbol *ModuleInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1500 { | |
1501 assert(0); // should never be produced by syntax | |
1502 return NULL; | |
1503 } | |
1504 | |
1505 void ModuleInfoDeclaration::semantic(Scope *sc) | |
1506 { | |
1507 } | |
1508 | |
1509 /********************************* TypeInfoDeclaration ****************************/ | |
1510 | |
1511 TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal) | |
1512 : VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL) | |
1513 { | |
1514 this->tinfo = tinfo; | |
1515 storage_class = STCstatic; | |
1516 protection = PROTpublic; | |
1517 linkage = LINKc; | |
1518 } | |
1519 | |
1520 Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1521 { | |
1522 assert(0); // should never be produced by syntax | |
1523 return NULL; | |
1524 } | |
1525 | |
1526 void TypeInfoDeclaration::semantic(Scope *sc) | |
1527 { | |
1528 assert(linkage == LINKc); | |
1529 } | |
1530 | |
1531 /***************************** TypeInfoConstDeclaration **********************/ | |
1532 | |
1533 #if DMDV2 | |
1534 TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo) | |
1535 : TypeInfoDeclaration(tinfo, 0) | |
1536 { | |
1537 } | |
1538 #endif | |
1539 | |
1540 /***************************** TypeInfoInvariantDeclaration **********************/ | |
1541 | |
1542 #if DMDV2 | |
1543 TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo) | |
1544 : TypeInfoDeclaration(tinfo, 0) | |
1545 { | |
1546 } | |
1547 #endif | |
1548 | |
1549 /***************************** TypeInfoStructDeclaration **********************/ | |
1550 | |
1551 TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo) | |
1552 : TypeInfoDeclaration(tinfo, 0) | |
1553 { | |
1554 } | |
1555 | |
1556 /***************************** TypeInfoClassDeclaration ***********************/ | |
1557 | |
1558 TypeInfoClassDeclaration::TypeInfoClassDeclaration(Type *tinfo) | |
1559 : TypeInfoDeclaration(tinfo, 0) | |
1560 { | |
1561 } | |
1562 | |
1563 /***************************** TypeInfoInterfaceDeclaration *******************/ | |
1564 | |
1565 TypeInfoInterfaceDeclaration::TypeInfoInterfaceDeclaration(Type *tinfo) | |
1566 : TypeInfoDeclaration(tinfo, 0) | |
1567 { | |
1568 } | |
1569 | |
1570 /***************************** TypeInfoTypedefDeclaration *********************/ | |
1571 | |
1572 TypeInfoTypedefDeclaration::TypeInfoTypedefDeclaration(Type *tinfo) | |
1573 : TypeInfoDeclaration(tinfo, 0) | |
1574 { | |
1575 } | |
1576 | |
1577 /***************************** TypeInfoPointerDeclaration *********************/ | |
1578 | |
1579 TypeInfoPointerDeclaration::TypeInfoPointerDeclaration(Type *tinfo) | |
1580 : TypeInfoDeclaration(tinfo, 0) | |
1581 { | |
1582 } | |
1583 | |
1584 /***************************** TypeInfoArrayDeclaration ***********************/ | |
1585 | |
1586 TypeInfoArrayDeclaration::TypeInfoArrayDeclaration(Type *tinfo) | |
1587 : TypeInfoDeclaration(tinfo, 0) | |
1588 { | |
1589 } | |
1590 | |
1591 /***************************** TypeInfoStaticArrayDeclaration *****************/ | |
1592 | |
1593 TypeInfoStaticArrayDeclaration::TypeInfoStaticArrayDeclaration(Type *tinfo) | |
1594 : TypeInfoDeclaration(tinfo, 0) | |
1595 { | |
1596 } | |
1597 | |
1598 /***************************** TypeInfoAssociativeArrayDeclaration ************/ | |
1599 | |
1600 TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *tinfo) | |
1601 : TypeInfoDeclaration(tinfo, 0) | |
1602 { | |
1603 } | |
1604 | |
1605 /***************************** TypeInfoEnumDeclaration ***********************/ | |
1606 | |
1607 TypeInfoEnumDeclaration::TypeInfoEnumDeclaration(Type *tinfo) | |
1608 : TypeInfoDeclaration(tinfo, 0) | |
1609 { | |
1610 } | |
1611 | |
1612 /***************************** TypeInfoFunctionDeclaration ********************/ | |
1613 | |
1614 TypeInfoFunctionDeclaration::TypeInfoFunctionDeclaration(Type *tinfo) | |
1615 : TypeInfoDeclaration(tinfo, 0) | |
1616 { | |
1617 } | |
1618 | |
1619 /***************************** TypeInfoDelegateDeclaration ********************/ | |
1620 | |
1621 TypeInfoDelegateDeclaration::TypeInfoDelegateDeclaration(Type *tinfo) | |
1622 : TypeInfoDeclaration(tinfo, 0) | |
1623 { | |
1624 } | |
1625 | |
1626 /***************************** TypeInfoTupleDeclaration **********************/ | |
1627 | |
1628 TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo) | |
1629 : TypeInfoDeclaration(tinfo, 0) | |
1630 { | |
1631 } | |
1632 | |
1633 /********************************* ThisDeclaration ****************************/ | |
1634 | |
1635 // For the "this" parameter to member functions | |
1636 | |
1637 ThisDeclaration::ThisDeclaration(Type *t) | |
1638 : VarDeclaration(0, t, Id::This, NULL) | |
1639 { | |
1640 noauto = 1; | |
1641 } | |
1642 | |
1643 Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s) | |
1644 { | |
1645 assert(0); // should never be produced by syntax | |
1646 return NULL; | |
1647 } | |
1648 | |
1649 |