Mercurial > projects > ldc
annotate dmd/declaration.c @ 148:86d3bb8ca33e trunk
[svn r154] renaming enclosingtry to enclosingtryfinally to distinguish it from enclosingtrycatch, which will probably need to be added for exception handling
author | ChristianK |
---|---|
date | Sat, 22 Mar 2008 12:20:32 +0100 |
parents | 0ab29b838084 |
children | ccd07d9f2ce9 |
rev | line source |
---|---|
1 | 1 |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2007 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; | |
130 | 32 originalType = NULL; |
1 | 33 storage_class = STCundefined; |
34 protection = PROTundefined; | |
50
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
35 linkage = LINKdefault; |
1 | 36 } |
37 | |
38 void Declaration::semantic(Scope *sc) | |
39 { | |
40 } | |
41 | |
42 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 /********************************* TupleDeclaration ****************************/ | |
84 | |
85 TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects) | |
86 : Declaration(id) | |
87 { | |
88 this->type = NULL; | |
89 this->objects = objects; | |
90 this->isexp = 0; | |
91 this->tupletype = NULL; | |
92 } | |
93 | |
94 Dsymbol *TupleDeclaration::syntaxCopy(Dsymbol *s) | |
95 { | |
96 assert(0); | |
97 return NULL; | |
98 } | |
99 | |
100 char *TupleDeclaration::kind() | |
101 { | |
102 return "tuple"; | |
103 } | |
104 | |
105 Type *TupleDeclaration::getType() | |
106 { | |
107 /* If this tuple represents a type, return that type | |
108 */ | |
109 | |
110 //printf("TupleDeclaration::getType() %s\n", toChars()); | |
111 if (isexp) | |
112 return NULL; | |
113 if (!tupletype) | |
114 { | |
115 /* It's only a type tuple if all the Object's are types | |
116 */ | |
117 for (size_t i = 0; i < objects->dim; i++) | |
118 { Object *o = (Object *)objects->data[i]; | |
119 | |
120 if (o->dyncast() != DYNCAST_TYPE) | |
121 { | |
122 //printf("\tnot[%d], %p, %d\n", i, o, o->dyncast()); | |
123 return NULL; | |
124 } | |
125 } | |
126 | |
127 /* We know it's a type tuple, so build the TypeTuple | |
128 */ | |
129 Arguments *args = new Arguments(); | |
130 args->setDim(objects->dim); | |
131 OutBuffer buf; | |
132 for (size_t i = 0; i < objects->dim; i++) | |
133 { Type *t = (Type *)objects->data[i]; | |
134 | |
135 //printf("type = %s\n", t->toChars()); | |
136 #if 0 | |
137 buf.printf("_%s_%d", ident->toChars(), i); | |
138 char *name = (char *)buf.extractData(); | |
139 Identifier *id = new Identifier(name, TOKidentifier); | |
140 Argument *arg = new Argument(STCin, t, id, NULL); | |
141 #else | |
142 Argument *arg = new Argument(STCin, t, NULL, NULL); | |
143 #endif | |
144 args->data[i] = (void *)arg; | |
145 } | |
146 | |
147 tupletype = new TypeTuple(args); | |
148 } | |
149 | |
150 return tupletype; | |
151 } | |
152 | |
153 int TupleDeclaration::needThis() | |
154 { | |
155 //printf("TupleDeclaration::needThis(%s)\n", toChars()); | |
156 for (size_t i = 0; i < objects->dim; i++) | |
157 { Object *o = (Object *)objects->data[i]; | |
158 if (o->dyncast() == DYNCAST_EXPRESSION) | |
159 { Expression *e = (Expression *)o; | |
160 if (e->op == TOKdsymbol) | |
161 { DsymbolExp *ve = (DsymbolExp *)e; | |
162 Declaration *d = ve->s->isDeclaration(); | |
163 if (d && d->needThis()) | |
164 { | |
165 return 1; | |
166 } | |
167 } | |
168 } | |
169 } | |
170 return 0; | |
171 } | |
172 | |
173 /********************************* TypedefDeclaration ****************************/ | |
174 | |
175 TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init) | |
176 : Declaration(id) | |
177 { | |
178 this->type = new TypeTypedef(this); | |
179 this->basetype = basetype->toBasetype(); | |
180 this->init = init; | |
181 #ifdef _DH | |
182 this->htype = NULL; | |
183 this->hbasetype = NULL; | |
184 #endif | |
185 this->sem = 0; | |
186 this->inuse = 0; | |
187 this->loc = loc; | |
188 this->sinit = NULL; | |
189 } | |
190 | |
191 Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s) | |
192 { | |
193 Type *basetype = this->basetype->syntaxCopy(); | |
194 | |
195 Initializer *init = NULL; | |
196 if (this->init) | |
197 init = this->init->syntaxCopy(); | |
198 | |
199 assert(!s); | |
200 TypedefDeclaration *st; | |
201 st = new TypedefDeclaration(loc, ident, basetype, init); | |
202 #ifdef _DH | |
203 // Syntax copy for header file | |
204 if (!htype) // Don't overwrite original | |
205 { if (type) // Make copy for both old and new instances | |
206 { htype = type->syntaxCopy(); | |
207 st->htype = type->syntaxCopy(); | |
208 } | |
209 } | |
210 else // Make copy of original for new instance | |
211 st->htype = htype->syntaxCopy(); | |
212 if (!hbasetype) | |
213 { if (basetype) | |
214 { hbasetype = basetype->syntaxCopy(); | |
215 st->hbasetype = basetype->syntaxCopy(); | |
216 } | |
217 } | |
218 else | |
219 st->hbasetype = hbasetype->syntaxCopy(); | |
220 #endif | |
221 return st; | |
222 } | |
223 | |
224 void TypedefDeclaration::semantic(Scope *sc) | |
225 { | |
226 //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem); | |
227 if (sem == 0) | |
228 { sem = 1; | |
229 basetype = basetype->semantic(loc, sc); | |
230 sem = 2; | |
231 type = type->semantic(loc, sc); | |
232 if (sc->parent->isFuncDeclaration() && init) | |
233 semantic2(sc); | |
234 } | |
235 else if (sem == 1) | |
236 { | |
237 error("circular definition"); | |
238 } | |
239 } | |
240 | |
241 void TypedefDeclaration::semantic2(Scope *sc) | |
242 { | |
243 //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem); | |
244 if (sem == 2) | |
245 { sem = 3; | |
246 if (init) | |
247 { | |
248 init = init->semantic(sc, basetype); | |
249 | |
250 ExpInitializer *ie = init->isExpInitializer(); | |
251 if (ie) | |
252 { | |
253 if (ie->exp->type == basetype) | |
254 ie->exp->type = type; | |
255 } | |
256 } | |
257 } | |
258 } | |
259 | |
260 char *TypedefDeclaration::kind() | |
261 { | |
262 return "typedef"; | |
263 } | |
264 | |
265 Type *TypedefDeclaration::getType() | |
266 { | |
267 return type; | |
268 } | |
269 | |
270 void TypedefDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
271 { | |
272 buf->writestring("typedef "); | |
273 basetype->toCBuffer(buf, ident, hgs); | |
274 if (init) | |
275 { | |
276 buf->writestring(" = "); | |
277 init->toCBuffer(buf, hgs); | |
278 } | |
279 buf->writeByte(';'); | |
280 buf->writenl(); | |
281 } | |
282 | |
283 /********************************* AliasDeclaration ****************************/ | |
284 | |
285 AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type) | |
286 : Declaration(id) | |
287 { | |
288 //printf("AliasDeclaration(id = '%s', type = %p)\n", id->toChars(), type); | |
289 //printf("type = '%s'\n", type->toChars()); | |
290 this->loc = loc; | |
291 this->type = type; | |
292 this->aliassym = NULL; | |
293 #ifdef _DH | |
294 this->htype = NULL; | |
295 this->haliassym = NULL; | |
296 #endif | |
297 this->overnext = NULL; | |
298 this->inSemantic = 0; | |
299 assert(type); | |
300 } | |
301 | |
302 AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s) | |
303 : Declaration(id) | |
304 { | |
305 //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s); | |
306 assert(s != this); | |
307 this->loc = loc; | |
308 this->type = NULL; | |
309 this->aliassym = s; | |
310 #ifdef _DH | |
311 this->htype = NULL; | |
312 this->haliassym = NULL; | |
313 #endif | |
314 this->overnext = NULL; | |
315 this->inSemantic = 0; | |
316 assert(s); | |
317 } | |
318 | |
319 Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s) | |
320 { | |
321 assert(!s); | |
322 AliasDeclaration *sa; | |
323 if (type) | |
324 sa = new AliasDeclaration(loc, ident, type->syntaxCopy()); | |
325 else | |
326 sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL)); | |
327 #ifdef _DH | |
328 // Syntax copy for header file | |
329 if (!htype) // Don't overwrite original | |
330 { if (type) // Make copy for both old and new instances | |
331 { htype = type->syntaxCopy(); | |
332 sa->htype = type->syntaxCopy(); | |
333 } | |
334 } | |
335 else // Make copy of original for new instance | |
336 sa->htype = htype->syntaxCopy(); | |
337 if (!haliassym) | |
338 { if (aliassym) | |
339 { haliassym = aliassym->syntaxCopy(s); | |
340 sa->haliassym = aliassym->syntaxCopy(s); | |
341 } | |
342 } | |
343 else | |
344 sa->haliassym = haliassym->syntaxCopy(s); | |
345 #endif | |
346 return sa; | |
347 } | |
348 | |
349 void AliasDeclaration::semantic(Scope *sc) | |
350 { | |
351 //printf("AliasDeclaration::semantic() %s\n", toChars()); | |
352 if (aliassym) | |
353 { | |
354 if (aliassym->isTemplateInstance()) | |
355 aliassym->semantic(sc); | |
356 return; | |
357 } | |
358 this->inSemantic = 1; | |
359 | |
360 if (storage_class & STCconst) | |
361 error("cannot be const"); | |
362 | |
363 storage_class |= sc->stc & STCdeprecated; | |
364 | |
365 // Given: | |
366 // alias foo.bar.abc def; | |
367 // it is not knowable from the syntax whether this is an alias | |
368 // for a type or an alias for a symbol. It is up to the semantic() | |
369 // pass to distinguish. | |
370 // If it is a type, then type is set and getType() will return that | |
371 // type. If it is a symbol, then aliassym is set and type is NULL - | |
372 // toAlias() will return aliasssym. | |
373 | |
374 Dsymbol *s; | |
375 Type *t; | |
376 Expression *e; | |
377 | |
378 /* This section is needed because resolve() will: | |
379 * const x = 3; | |
380 * alias x y; | |
381 * try to alias y to 3. | |
382 */ | |
383 s = type->toDsymbol(sc); | |
384 if (s) | |
385 goto L2; // it's a symbolic alias | |
386 | |
387 //printf("alias type is %s\n", type->toChars()); | |
388 type->resolve(loc, sc, &e, &t, &s); | |
389 if (s) | |
390 { | |
391 goto L2; | |
392 } | |
393 else if (e) | |
394 { | |
395 // Try to convert Expression to Dsymbol | |
396 if (e->op == TOKvar) | |
397 { s = ((VarExp *)e)->var; | |
398 goto L2; | |
399 } | |
400 else if (e->op == TOKfunction) | |
401 { s = ((FuncExp *)e)->fd; | |
402 goto L2; | |
403 } | |
404 else | |
405 { error("cannot alias an expression %s", e->toChars()); | |
406 t = e->type; | |
407 } | |
408 } | |
409 else if (t) | |
410 type = t; | |
411 if (overnext) | |
412 ScopeDsymbol::multiplyDefined(0, this, overnext); | |
413 this->inSemantic = 0; | |
414 return; | |
415 | |
416 L2: | |
417 //printf("alias is a symbol %s %s\n", s->kind(), s->toChars()); | |
418 type = NULL; | |
419 VarDeclaration *v = s->isVarDeclaration(); | |
420 if (v && v->linkage == LINKdefault) | |
421 { | |
422 error("forward reference of %s", v->toChars()); | |
423 s = NULL; | |
424 } | |
425 else | |
426 { | |
427 FuncDeclaration *f = s->toAlias()->isFuncDeclaration(); | |
428 if (f) | |
429 { | |
430 if (overnext) | |
431 { | |
432 FuncAliasDeclaration *fa = new FuncAliasDeclaration(f); | |
433 if (!fa->overloadInsert(overnext)) | |
434 ScopeDsymbol::multiplyDefined(0, f, overnext); | |
435 overnext = NULL; | |
436 s = fa; | |
437 s->parent = sc->parent; | |
438 } | |
439 } | |
440 if (overnext) | |
441 ScopeDsymbol::multiplyDefined(0, s, overnext); | |
442 if (s == this) | |
443 { | |
444 assert(global.errors); | |
445 s = NULL; | |
446 } | |
447 } | |
448 aliassym = s; | |
449 this->inSemantic = 0; | |
450 } | |
451 | |
452 int AliasDeclaration::overloadInsert(Dsymbol *s) | |
453 { | |
454 /* Don't know yet what the aliased symbol is, so assume it can | |
455 * be overloaded and check later for correctness. | |
456 */ | |
457 | |
458 //printf("AliasDeclaration::overloadInsert('%s')\n", s->toChars()); | |
459 if (overnext == NULL) | |
460 { overnext = s; | |
461 return TRUE; | |
462 } | |
463 else | |
464 { | |
465 return overnext->overloadInsert(s); | |
466 } | |
467 } | |
468 | |
469 char *AliasDeclaration::kind() | |
470 { | |
471 return "alias"; | |
472 } | |
473 | |
474 Type *AliasDeclaration::getType() | |
475 { | |
476 return type; | |
477 } | |
478 | |
479 Dsymbol *AliasDeclaration::toAlias() | |
480 { | |
481 //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : ""); | |
482 assert(this != aliassym); | |
483 //static int count; if (++count == 10) *(char*)0=0; | |
484 if (inSemantic) | |
485 { error("recursive alias declaration"); | |
486 // return this; | |
487 } | |
488 Dsymbol *s = aliassym ? aliassym->toAlias() : this; | |
489 return s; | |
490 } | |
491 | |
492 void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
493 { | |
494 buf->writestring("alias "); | |
495 #if 0 && _DH | |
496 if (hgs->hdrgen) | |
497 { | |
498 if (haliassym) | |
499 { | |
500 haliassym->toCBuffer(buf, hgs); | |
501 buf->writeByte(' '); | |
502 buf->writestring(ident->toChars()); | |
503 } | |
504 else | |
505 htype->toCBuffer(buf, ident, hgs); | |
506 } | |
507 else | |
508 #endif | |
509 { | |
510 if (aliassym) | |
511 { | |
512 aliassym->toCBuffer(buf, hgs); | |
513 buf->writeByte(' '); | |
514 buf->writestring(ident->toChars()); | |
515 } | |
516 else | |
517 type->toCBuffer(buf, ident, hgs); | |
518 } | |
519 buf->writeByte(';'); | |
520 buf->writenl(); | |
521 } | |
522 | |
523 /********************************* VarDeclaration ****************************/ | |
524 | |
525 VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer *init) | |
526 : Declaration(id) | |
527 { | |
528 //printf("VarDeclaration('%s')\n", id->toChars()); | |
529 #ifdef DEBUG | |
530 if (!type && !init) | |
531 { printf("VarDeclaration('%s')\n", id->toChars()); | |
532 //*(char*)0=0; | |
533 } | |
534 #endif | |
535 assert(type || init); | |
536 this->type = type; | |
537 this->init = init; | |
538 #ifdef _DH | |
539 this->htype = NULL; | |
540 this->hinit = NULL; | |
541 #endif | |
542 this->loc = loc; | |
543 offset = 0; | |
544 noauto = 0; | |
545 nestedref = 0; | |
546 inuse = 0; | |
547 ctorinit = 0; | |
548 aliassym = NULL; | |
549 onstack = 0; | |
550 canassign = 0; | |
551 value = NULL; | |
136
0e28624814e8
[svn r140] did a lot of the work towards being able to pass multiple modules on the command line. not complete yet though
lindquist
parents:
130
diff
changeset
|
552 irGlobal = NULL; |
0e28624814e8
[svn r140] did a lot of the work towards being able to pass multiple modules on the command line. not complete yet though
lindquist
parents:
130
diff
changeset
|
553 irLocal = NULL; |
0e28624814e8
[svn r140] did a lot of the work towards being able to pass multiple modules on the command line. not complete yet though
lindquist
parents:
130
diff
changeset
|
554 irField = NULL; |
0e28624814e8
[svn r140] did a lot of the work towards being able to pass multiple modules on the command line. not complete yet though
lindquist
parents:
130
diff
changeset
|
555 needsStorage = false; |
1 | 556 } |
557 | |
558 Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) | |
559 { | |
560 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars()); | |
561 | |
562 VarDeclaration *sv; | |
563 if (s) | |
564 { sv = (VarDeclaration *)s; | |
565 } | |
566 else | |
567 { | |
568 Initializer *init = NULL; | |
569 if (this->init) | |
570 { init = this->init->syntaxCopy(); | |
571 //init->isExpInitializer()->exp->print(); | |
572 //init->isExpInitializer()->exp->dump(0); | |
573 } | |
574 | |
575 sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init); | |
576 sv->storage_class = storage_class; | |
577 } | |
578 #ifdef _DH | |
579 // Syntax copy for header file | |
580 if (!htype) // Don't overwrite original | |
581 { if (type) // Make copy for both old and new instances | |
582 { htype = type->syntaxCopy(); | |
583 sv->htype = type->syntaxCopy(); | |
584 } | |
585 } | |
586 else // Make copy of original for new instance | |
587 sv->htype = htype->syntaxCopy(); | |
588 if (!hinit) | |
589 { if (init) | |
590 { hinit = init->syntaxCopy(); | |
591 sv->hinit = init->syntaxCopy(); | |
592 } | |
593 } | |
594 else | |
595 sv->hinit = hinit->syntaxCopy(); | |
596 #endif | |
597 return sv; | |
598 } | |
599 | |
600 void VarDeclaration::semantic(Scope *sc) | |
601 { | |
602 //printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars()); | |
603 //printf("type = %s\n", type->toChars()); | |
604 //printf("linkage = %d\n", sc->linkage); | |
605 //if (strcmp(toChars(), "mul") == 0) halt(); | |
606 | |
607 storage_class |= sc->stc; | |
608 if (storage_class & STCextern && init) | |
609 error("extern symbols cannot have initializers"); | |
610 | |
611 /* If auto type inference, do the inference | |
612 */ | |
613 int inferred = 0; | |
614 if (!type) | |
615 { inuse++; | |
616 type = init->inferType(sc); | |
617 inuse--; | |
618 inferred = 1; | |
619 | |
620 /* This is a kludge to support the existing syntax for RAII | |
621 * declarations. | |
622 */ | |
623 storage_class &= ~STCauto; | |
130 | 624 originalType = type; |
1 | 625 } |
626 else | |
130 | 627 { if (!originalType) |
628 originalType = type; | |
1 | 629 type = type->semantic(loc, sc); |
130 | 630 } |
1 | 631 |
632 type->checkDeprecated(loc, sc); | |
633 linkage = sc->linkage; | |
634 this->parent = sc->parent; | |
635 //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars()); | |
636 protection = sc->protection; | |
637 //printf("sc->stc = %x\n", sc->stc); | |
638 //printf("storage_class = %x\n", storage_class); | |
639 | |
640 Dsymbol *parent = toParent(); | |
641 FuncDeclaration *fd = parent->isFuncDeclaration(); | |
642 | |
643 Type *tb = type->toBasetype(); | |
644 if (tb->ty == Tvoid && !(storage_class & STClazy)) | |
645 { error("voids have no value"); | |
646 type = Type::terror; | |
647 tb = type; | |
648 } | |
649 if (tb->ty == Tfunction) | |
650 { error("cannot be declared to be a function"); | |
651 type = Type::terror; | |
652 tb = type; | |
653 } | |
654 if (tb->ty == Tstruct) | |
655 { TypeStruct *ts = (TypeStruct *)tb; | |
656 | |
657 if (!ts->sym->members) | |
658 { | |
659 error("no definition of struct %s", ts->toChars()); | |
660 } | |
661 } | |
662 | |
663 if (tb->ty == Ttuple) | |
664 { /* Instead, declare variables for each of the tuple elements | |
665 * and add those. | |
666 */ | |
667 TypeTuple *tt = (TypeTuple *)tb; | |
668 size_t nelems = Argument::dim(tt->arguments); | |
669 Objects *exps = new Objects(); | |
670 exps->setDim(nelems); | |
671 | |
672 for (size_t i = 0; i < nelems; i++) | |
673 { Argument *arg = Argument::getNth(tt->arguments, i); | |
674 | |
675 OutBuffer buf; | |
676 buf.printf("_%s_field_%zu", ident->toChars(), i); | |
677 buf.writeByte(0); | |
678 char *name = (char *)buf.extractData(); | |
679 Identifier *id = new Identifier(name, TOKidentifier); | |
680 | |
681 VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL); | |
682 //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars()); | |
683 v->semantic(sc); | |
684 | |
685 if (sc->scopesym) | |
686 { //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars()); | |
687 if (sc->scopesym->members) | |
688 sc->scopesym->members->push(v); | |
689 } | |
690 | |
691 Expression *e = new DsymbolExp(loc, v); | |
692 exps->data[i] = e; | |
693 } | |
694 TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps); | |
695 v2->isexp = 1; | |
696 aliassym = v2; | |
697 return; | |
698 } | |
699 | |
700 if (storage_class & STCconst && !init && !fd) | |
701 // Initialize by constructor only | |
702 storage_class = (storage_class & ~STCconst) | STCctorinit; | |
703 | |
704 if (isConst()) | |
705 { | |
706 } | |
707 else if (isStatic()) | |
708 { | |
709 } | |
710 else if (isSynchronized()) | |
711 { | |
712 error("variable %s cannot be synchronized", toChars()); | |
713 } | |
714 else if (isOverride()) | |
715 { | |
716 error("override cannot be applied to variable"); | |
717 } | |
718 else if (isAbstract()) | |
719 { | |
720 error("abstract cannot be applied to variable"); | |
721 } | |
722 else if (storage_class & STCtemplateparameter) | |
723 { | |
724 } | |
725 else | |
726 { | |
727 AggregateDeclaration *aad = sc->anonAgg; | |
728 if (!aad) | |
729 aad = parent->isAggregateDeclaration(); | |
730 if (aad) | |
731 { | |
732 aad->addField(sc, this); | |
733 } | |
734 | |
735 InterfaceDeclaration *id = parent->isInterfaceDeclaration(); | |
736 if (id) | |
737 { | |
738 error("field not allowed in interface"); | |
739 } | |
740 | |
741 TemplateInstance *ti = parent->isTemplateInstance(); | |
742 if (ti) | |
743 { | |
744 // Take care of nested templates | |
745 while (1) | |
746 { | |
747 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); | |
748 if (!ti2) | |
749 break; | |
750 ti = ti2; | |
751 } | |
752 | |
753 // If it's a member template | |
754 AggregateDeclaration *ad = ti->tempdecl->isMember(); | |
755 if (ad && storage_class != STCundefined) | |
756 { | |
757 error("cannot use template to add field to aggregate '%s'", ad->toChars()); | |
758 } | |
759 } | |
760 } | |
761 | |
762 if (type->isauto() && !noauto) | |
763 { | |
764 if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd) | |
765 { | |
766 error("globals, statics, fields, ref and out parameters cannot be auto"); | |
767 } | |
768 | |
769 if (!(storage_class & (STCauto | STCscope))) | |
770 { | |
771 if (!(storage_class & STCparameter) && ident != Id::withSym) | |
772 error("reference to scope class must be scope"); | |
773 } | |
774 } | |
775 | |
776 if (!init && !sc->inunion && !isStatic() && !isConst() && fd && | |
92 | 777 !(storage_class & (STCfield | STCin | STCforeach)) && |
778 type->size() != 0) | |
1 | 779 { |
780 // Provide a default initializer | |
781 //printf("Providing default initializer for '%s'\n", toChars()); | |
782 if (type->ty == Tstruct && | |
783 ((TypeStruct *)type)->sym->zeroInit == 1) | |
19 | 784 { /* If a struct is all zeros, as a special case |
785 * set it's initializer to the integer 0. | |
786 * In AssignExp::toElem(), we check for this and issue | |
787 * a memset() to initialize the struct. | |
788 * Must do same check in interpreter. | |
789 */ | |
1 | 790 Expression *e = new IntegerExp(loc, 0, Type::tint32); |
791 Expression *e1; | |
792 e1 = new VarExp(loc, this); | |
793 e = new AssignExp(loc, e1, e); | |
794 e->type = e1->type; | |
795 init = new ExpInitializer(loc, e/*->type->defaultInit()*/); | |
796 return; | |
797 } | |
798 else if (type->ty == Ttypedef) | |
799 { TypeTypedef *td = (TypeTypedef *)type; | |
800 if (td->sym->init) | |
801 { init = td->sym->init; | |
802 ExpInitializer *ie = init->isExpInitializer(); | |
803 if (ie) | |
804 // Make copy so we can modify it | |
805 init = new ExpInitializer(ie->loc, ie->exp); | |
806 } | |
807 else | |
808 init = getExpInitializer(); | |
809 } | |
810 else | |
811 { | |
812 init = getExpInitializer(); | |
813 } | |
814 } | |
815 | |
816 if (init) | |
817 { | |
818 ArrayInitializer *ai = init->isArrayInitializer(); | |
19 | 819 if (ai && tb->ty == Taarray) |
1 | 820 { |
821 init = ai->toAssocArrayInitializer(); | |
822 } | |
823 | |
19 | 824 StructInitializer *si = init->isStructInitializer(); |
1 | 825 ExpInitializer *ei = init->isExpInitializer(); |
826 | |
827 // See if we can allocate on the stack | |
828 if (ei && isScope() && ei->exp->op == TOKnew) | |
829 { NewExp *ne = (NewExp *)ei->exp; | |
830 if (!(ne->newargs && ne->newargs->dim)) | |
831 { ne->onstack = 1; | |
832 onstack = 1; | |
833 if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL)) | |
834 onstack = 2; | |
835 } | |
836 } | |
837 | |
838 // If inside function, there is no semantic3() call | |
839 if (sc->func) | |
840 { | |
841 // If local variable, use AssignExp to handle all the various | |
842 // possibilities. | |
843 if (fd && !isStatic() && !isConst() && !init->isVoidInitializer()) | |
844 { | |
845 Expression *e1; | |
846 Type *t; | |
847 int dim; | |
848 | |
849 //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); | |
850 if (!ei) | |
851 { | |
852 Expression *e = init->toExpression(); | |
853 if (!e) | |
854 { | |
855 init = init->semantic(sc, type); | |
856 e = init->toExpression(); | |
857 if (!e) | |
858 { error("is not a static and cannot have static initializer"); | |
859 return; | |
860 } | |
861 } | |
862 ei = new ExpInitializer(init->loc, e); | |
863 init = ei; | |
864 } | |
865 | |
866 e1 = new VarExp(loc, this); | |
867 | |
868 t = type->toBasetype(); | |
869 if (t->ty == Tsarray) | |
870 { | |
92 | 871 ei->exp = ei->exp->semantic(sc); |
872 if (!ei->exp->implicitConvTo(type)) | |
1 | 873 { |
92 | 874 dim = ((TypeSArray *)t)->dim->toInteger(); |
875 // If multidimensional static array, treat as one large array | |
876 while (1) | |
877 { | |
878 t = t->nextOf()->toBasetype(); | |
879 if (t->ty != Tsarray) | |
880 break; | |
1 | 881 dim *= ((TypeSArray *)t)->dim->toInteger(); |
92 | 882 e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex)); |
883 } | |
1 | 884 } |
885 e1 = new SliceExp(loc, e1, NULL, NULL); | |
886 } | |
887 else if (t->ty == Tstruct) | |
888 { | |
889 ei->exp = ei->exp->semantic(sc); | |
890 if (!ei->exp->implicitConvTo(type)) | |
891 ei->exp = new CastExp(loc, ei->exp, type); | |
892 } | |
893 ei->exp = new AssignExp(loc, e1, ei->exp); | |
894 ei->exp->op = TOKconstruct; | |
895 canassign++; | |
896 ei->exp = ei->exp->semantic(sc); | |
897 canassign--; | |
898 ei->exp->optimize(WANTvalue); | |
899 } | |
900 else | |
901 { | |
902 init = init->semantic(sc, type); | |
903 if (fd && isConst() && !isStatic()) | |
904 { // Make it static | |
905 storage_class |= STCstatic; | |
906 } | |
907 } | |
908 } | |
909 else if (isConst() || isFinal()) | |
910 { | |
911 /* Because we may need the results of a const declaration in a | |
912 * subsequent type, such as an array dimension, before semantic2() | |
913 * gets ordinarily run, try to run semantic2() now. | |
914 * Ignore failure. | |
915 */ | |
916 | |
19 | 917 if (!global.errors && !inferred) |
1 | 918 { |
919 unsigned errors = global.errors; | |
920 global.gag++; | |
921 //printf("+gag\n"); | |
19 | 922 Expression *e; |
923 Initializer *i2 = init; | |
1 | 924 inuse++; |
19 | 925 if (ei) |
926 { | |
927 e = ei->exp->syntaxCopy(); | |
928 e = e->semantic(sc); | |
929 e = e->implicitCastTo(sc, type); | |
930 } | |
931 else if (si || ai) | |
932 { i2 = init->syntaxCopy(); | |
933 i2 = i2->semantic(sc, type); | |
934 } | |
1 | 935 inuse--; |
936 global.gag--; | |
937 //printf("-gag\n"); | |
938 if (errors != global.errors) // if errors happened | |
939 { | |
940 if (global.gag == 0) | |
941 global.errors = errors; // act as if nothing happened | |
942 } | |
19 | 943 else if (ei) |
1 | 944 { |
945 e = e->optimize(WANTvalue | WANTinterpret); | |
946 if (e->op == TOKint64 || e->op == TOKstring) | |
947 { | |
948 ei->exp = e; // no errors, keep result | |
949 } | |
950 } | |
19 | 951 else |
952 init = i2; // no errors, keep result | |
1 | 953 } |
954 } | |
955 } | |
956 } | |
957 | |
958 ExpInitializer *VarDeclaration::getExpInitializer() | |
959 { | |
960 ExpInitializer *ei; | |
961 | |
962 if (init) | |
963 ei = init->isExpInitializer(); | |
964 else | |
965 { | |
966 Expression *e = type->defaultInit(); | |
967 if (e) | |
968 ei = new ExpInitializer(loc, e); | |
969 else | |
970 ei = NULL; | |
971 } | |
972 return ei; | |
973 } | |
974 | |
975 void VarDeclaration::semantic2(Scope *sc) | |
976 { | |
977 //printf("VarDeclaration::semantic2('%s')\n", toChars()); | |
978 if (init && !toParent()->isFuncDeclaration()) | |
979 { inuse++; | |
980 #if 0 | |
981 ExpInitializer *ei = init->isExpInitializer(); | |
982 if (ei) | |
983 { | |
984 ei->exp->dump(0); | |
985 printf("type = %p\n", ei->exp->type); | |
986 } | |
987 #endif | |
988 init = init->semantic(sc, type); | |
989 inuse--; | |
990 } | |
991 } | |
992 | |
993 char *VarDeclaration::kind() | |
994 { | |
995 return "variable"; | |
996 } | |
997 | |
998 Dsymbol *VarDeclaration::toAlias() | |
999 { | |
1000 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); | |
1001 assert(this != aliassym); | |
1002 Dsymbol *s = aliassym ? aliassym->toAlias() : this; | |
1003 return s; | |
1004 } | |
1005 | |
1006 void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1007 { | |
1008 if (storage_class & STCconst) | |
1009 buf->writestring("const "); | |
1010 if (storage_class & STCstatic) | |
1011 buf->writestring("static "); | |
1012 if (type) | |
1013 type->toCBuffer(buf, ident, hgs); | |
1014 else | |
1015 buf->writestring(ident->toChars()); | |
1016 if (init) | |
1017 { buf->writestring(" = "); | |
1018 init->toCBuffer(buf, hgs); | |
1019 } | |
1020 buf->writeByte(';'); | |
1021 buf->writenl(); | |
1022 } | |
1023 | |
1024 int VarDeclaration::needThis() | |
1025 { | |
1026 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class); | |
1027 return storage_class & STCfield; | |
1028 } | |
1029 | |
1030 int VarDeclaration::isImportedSymbol() | |
1031 { | |
1032 if (protection == PROTexport && !init && (isStatic() || isConst() || parent->isModule())) | |
1033 return TRUE; | |
1034 return FALSE; | |
1035 } | |
1036 | |
1037 void VarDeclaration::checkCtorConstInit() | |
1038 { | |
1039 if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield)) | |
1040 error("missing initializer in static constructor for const variable"); | |
1041 } | |
1042 | |
1043 /************************************ | |
1044 * Check to see if variable is a reference to an enclosing function | |
1045 * or not. | |
1046 */ | |
1047 | |
1048 void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) | |
1049 { | |
92 | 1050 if (parent && !isDataseg() && parent != sc->parent) |
1 | 1051 { |
1052 FuncDeclaration *fdv = toParent()->isFuncDeclaration(); | |
1053 FuncDeclaration *fdthis = sc->parent->isFuncDeclaration(); | |
1054 | |
1055 if (fdv && fdthis) | |
1056 { | |
1057 if (loc.filename) | |
1058 fdthis->getLevel(loc, fdv); | |
1059 nestedref = 1; | |
1060 fdv->nestedFrameRef = 1; | |
136
0e28624814e8
[svn r140] did a lot of the work towards being able to pass multiple modules on the command line. not complete yet though
lindquist
parents:
130
diff
changeset
|
1061 fdv->nestedVars.insert(this); |
1 | 1062 //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars()); |
1063 } | |
1064 } | |
1065 } | |
1066 | |
1067 /******************************* | |
1068 * Does symbol go into data segment? | |
1069 */ | |
1070 | |
1071 int VarDeclaration::isDataseg() | |
1072 { | |
1073 #if 0 | |
1074 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars()); | |
1075 printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance()); | |
1076 printf("parent = '%s'\n", parent->toChars()); | |
1077 #endif | |
1078 Dsymbol *parent = this->toParent(); | |
1079 if (!parent && !(storage_class & (STCstatic | STCconst))) | |
1080 { error("forward referenced"); | |
1081 type = Type::terror; | |
1082 return 0; | |
1083 } | |
1084 return (storage_class & (STCstatic | STCconst) || | |
1085 parent->isModule() || | |
1086 parent->isTemplateInstance()); | |
1087 } | |
1088 | |
1089 int VarDeclaration::hasPointers() | |
1090 { | |
1091 return (!isDataseg() && type->hasPointers()); | |
1092 } | |
1093 | |
1094 /****************************************** | |
1095 * If a variable has an auto destructor call, return call for it. | |
1096 * Otherwise, return NULL. | |
1097 */ | |
1098 | |
1099 Expression *VarDeclaration::callAutoDtor() | |
1100 { Expression *e = NULL; | |
1101 | |
139
0ab29b838084
[svn r143] Fixed: a few bugs in debug information, still only line info, but should be correct files now :)
lindquist
parents:
136
diff
changeset
|
1102 //printf("VarDeclaration::callAutoDtor() %s\n", toChars()); |
1 | 1103 if (storage_class & (STCauto | STCscope) && !noauto) |
1104 { | |
1105 for (ClassDeclaration *cd = type->isClassHandle(); | |
1106 cd; | |
1107 cd = cd->baseClass) | |
1108 { | |
1109 /* We can do better if there's a way with onstack | |
1110 * classes to determine if there's no way the monitor | |
1111 * could be set. | |
1112 */ | |
139
0ab29b838084
[svn r143] Fixed: a few bugs in debug information, still only line info, but should be correct files now :)
lindquist
parents:
136
diff
changeset
|
1113 if (cd->isInterfaceDeclaration()) |
0ab29b838084
[svn r143] Fixed: a few bugs in debug information, still only line info, but should be correct files now :)
lindquist
parents:
136
diff
changeset
|
1114 error("interface %s cannot be scope", cd->toChars()); |
1 | 1115 if (1 || onstack || cd->dtors.dim) // if any destructors |
1116 { | |
1117 // delete this; | |
1118 Expression *ec; | |
1119 | |
1120 ec = new VarExp(loc, this); | |
1121 e = new DeleteExp(loc, ec); | |
1122 e->type = Type::tvoid; | |
1123 break; | |
1124 } | |
1125 } | |
1126 } | |
1127 return e; | |
1128 } | |
1129 | |
1130 | |
1131 /********************************* ClassInfoDeclaration ****************************/ | |
1132 | |
1133 ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd) | |
1134 : VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL) | |
1135 { | |
1136 this->cd = cd; | |
1137 storage_class = STCstatic; | |
1138 } | |
1139 | |
1140 Dsymbol *ClassInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1141 { | |
1142 assert(0); // should never be produced by syntax | |
1143 return NULL; | |
1144 } | |
1145 | |
1146 void ClassInfoDeclaration::semantic(Scope *sc) | |
1147 { | |
1148 } | |
1149 | |
1150 /********************************* ModuleInfoDeclaration ****************************/ | |
1151 | |
1152 ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod) | |
1153 : VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL) | |
1154 { | |
1155 this->mod = mod; | |
1156 storage_class = STCstatic; | |
1157 } | |
1158 | |
1159 Dsymbol *ModuleInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1160 { | |
1161 assert(0); // should never be produced by syntax | |
1162 return NULL; | |
1163 } | |
1164 | |
1165 void ModuleInfoDeclaration::semantic(Scope *sc) | |
1166 { | |
1167 } | |
1168 | |
1169 /********************************* TypeInfoDeclaration ****************************/ | |
1170 | |
1171 TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal) | |
1172 : VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL) | |
1173 { | |
1174 this->tinfo = tinfo; | |
1175 storage_class = STCstatic; | |
1176 protection = PROTpublic; | |
1177 linkage = LINKc; | |
1178 } | |
1179 | |
1180 Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1181 { | |
1182 assert(0); // should never be produced by syntax | |
1183 return NULL; | |
1184 } | |
1185 | |
1186 void TypeInfoDeclaration::semantic(Scope *sc) | |
1187 { | |
1188 assert(linkage == LINKc); | |
1189 } | |
1190 | |
92 | 1191 /***************************** TypeInfoConstDeclaration **********************/ |
1192 | |
1193 #if V2 | |
1194 TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo) | |
1195 : TypeInfoDeclaration(tinfo, 0) | |
1196 { | |
1197 } | |
1198 #endif | |
1199 | |
1200 /***************************** TypeInfoInvariantDeclaration **********************/ | |
1201 | |
1202 #if V2 | |
1203 TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo) | |
1204 : TypeInfoDeclaration(tinfo, 0) | |
1205 { | |
1206 } | |
1207 #endif | |
1208 | |
1 | 1209 /***************************** TypeInfoStructDeclaration **********************/ |
1210 | |
1211 TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo) | |
1212 : TypeInfoDeclaration(tinfo, 0) | |
1213 { | |
1214 } | |
1215 | |
1216 /***************************** TypeInfoClassDeclaration ***********************/ | |
1217 | |
1218 TypeInfoClassDeclaration::TypeInfoClassDeclaration(Type *tinfo) | |
1219 : TypeInfoDeclaration(tinfo, 0) | |
1220 { | |
1221 } | |
1222 | |
1223 /***************************** TypeInfoInterfaceDeclaration *******************/ | |
1224 | |
1225 TypeInfoInterfaceDeclaration::TypeInfoInterfaceDeclaration(Type *tinfo) | |
1226 : TypeInfoDeclaration(tinfo, 0) | |
1227 { | |
1228 } | |
1229 | |
1230 /***************************** TypeInfoTypedefDeclaration *********************/ | |
1231 | |
1232 TypeInfoTypedefDeclaration::TypeInfoTypedefDeclaration(Type *tinfo) | |
1233 : TypeInfoDeclaration(tinfo, 0) | |
1234 { | |
1235 } | |
1236 | |
1237 /***************************** TypeInfoPointerDeclaration *********************/ | |
1238 | |
1239 TypeInfoPointerDeclaration::TypeInfoPointerDeclaration(Type *tinfo) | |
1240 : TypeInfoDeclaration(tinfo, 0) | |
1241 { | |
1242 } | |
1243 | |
1244 /***************************** TypeInfoArrayDeclaration ***********************/ | |
1245 | |
1246 TypeInfoArrayDeclaration::TypeInfoArrayDeclaration(Type *tinfo) | |
1247 : TypeInfoDeclaration(tinfo, 0) | |
1248 { | |
1249 } | |
1250 | |
1251 /***************************** TypeInfoStaticArrayDeclaration *****************/ | |
1252 | |
1253 TypeInfoStaticArrayDeclaration::TypeInfoStaticArrayDeclaration(Type *tinfo) | |
1254 : TypeInfoDeclaration(tinfo, 0) | |
1255 { | |
1256 } | |
1257 | |
1258 /***************************** TypeInfoAssociativeArrayDeclaration ************/ | |
1259 | |
1260 TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *tinfo) | |
1261 : TypeInfoDeclaration(tinfo, 0) | |
1262 { | |
1263 } | |
1264 | |
1265 /***************************** TypeInfoEnumDeclaration ***********************/ | |
1266 | |
1267 TypeInfoEnumDeclaration::TypeInfoEnumDeclaration(Type *tinfo) | |
1268 : TypeInfoDeclaration(tinfo, 0) | |
1269 { | |
1270 } | |
1271 | |
1272 /***************************** TypeInfoFunctionDeclaration ********************/ | |
1273 | |
1274 TypeInfoFunctionDeclaration::TypeInfoFunctionDeclaration(Type *tinfo) | |
1275 : TypeInfoDeclaration(tinfo, 0) | |
1276 { | |
1277 } | |
1278 | |
1279 /***************************** TypeInfoDelegateDeclaration ********************/ | |
1280 | |
1281 TypeInfoDelegateDeclaration::TypeInfoDelegateDeclaration(Type *tinfo) | |
1282 : TypeInfoDeclaration(tinfo, 0) | |
1283 { | |
1284 } | |
1285 | |
1286 /***************************** TypeInfoTupleDeclaration **********************/ | |
1287 | |
1288 TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo) | |
1289 : TypeInfoDeclaration(tinfo, 0) | |
1290 { | |
1291 } | |
1292 | |
1293 /********************************* ThisDeclaration ****************************/ | |
1294 | |
1295 // For the "this" parameter to member functions | |
1296 | |
1297 ThisDeclaration::ThisDeclaration(Type *t) | |
1298 : VarDeclaration(0, t, Id::This, NULL) | |
1299 { | |
1300 noauto = 1; | |
1301 } | |
1302 | |
1303 Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s) | |
1304 { | |
1305 assert(0); // should never be produced by syntax | |
1306 return NULL; | |
1307 } | |
1308 | |
1309 |