Mercurial > projects > ldc
annotate dmd/declaration.c @ 54:28e99b04a132 trunk
[svn r58] Fixed cond expression resulting in a non-basic type.
Fixed identity expression for dynamic arrays.
Revamped the system to keep track of lvalues and rvalues and their relations.
Typedef declaration now generate the custom typeinfo.
Other bugfixes.
author | lindquist |
---|---|
date | Wed, 24 Oct 2007 01:37:34 +0200 |
parents | 6fcc08a4d406 |
children | b706170e24a9 |
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; | |
32 storage_class = STCundefined; | |
33 protection = PROTundefined; | |
50
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
34 linkage = LINKdefault; |
40 | 35 llvmTouched = false; |
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; | |
50
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
552 llvmNestedIndex = -1; |
1 | 553 } |
554 | |
555 Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) | |
556 { | |
557 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars()); | |
558 | |
559 VarDeclaration *sv; | |
560 if (s) | |
561 { sv = (VarDeclaration *)s; | |
562 } | |
563 else | |
564 { | |
565 Initializer *init = NULL; | |
566 if (this->init) | |
567 { init = this->init->syntaxCopy(); | |
568 //init->isExpInitializer()->exp->print(); | |
569 //init->isExpInitializer()->exp->dump(0); | |
570 } | |
571 | |
572 sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init); | |
573 sv->storage_class = storage_class; | |
574 } | |
575 #ifdef _DH | |
576 // Syntax copy for header file | |
577 if (!htype) // Don't overwrite original | |
578 { if (type) // Make copy for both old and new instances | |
579 { htype = type->syntaxCopy(); | |
580 sv->htype = type->syntaxCopy(); | |
581 } | |
582 } | |
583 else // Make copy of original for new instance | |
584 sv->htype = htype->syntaxCopy(); | |
585 if (!hinit) | |
586 { if (init) | |
587 { hinit = init->syntaxCopy(); | |
588 sv->hinit = init->syntaxCopy(); | |
589 } | |
590 } | |
591 else | |
592 sv->hinit = hinit->syntaxCopy(); | |
593 #endif | |
594 return sv; | |
595 } | |
596 | |
597 void VarDeclaration::semantic(Scope *sc) | |
598 { | |
599 //printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars()); | |
600 //printf("type = %s\n", type->toChars()); | |
601 //printf("linkage = %d\n", sc->linkage); | |
602 //if (strcmp(toChars(), "mul") == 0) halt(); | |
603 | |
604 storage_class |= sc->stc; | |
605 if (storage_class & STCextern && init) | |
606 error("extern symbols cannot have initializers"); | |
607 | |
608 /* If auto type inference, do the inference | |
609 */ | |
610 int inferred = 0; | |
611 if (!type) | |
612 { inuse++; | |
613 type = init->inferType(sc); | |
614 inuse--; | |
615 inferred = 1; | |
616 | |
617 /* This is a kludge to support the existing syntax for RAII | |
618 * declarations. | |
619 */ | |
620 storage_class &= ~STCauto; | |
621 } | |
622 else | |
623 type = type->semantic(loc, sc); | |
624 | |
625 type->checkDeprecated(loc, sc); | |
626 linkage = sc->linkage; | |
627 this->parent = sc->parent; | |
628 //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars()); | |
629 protection = sc->protection; | |
630 //printf("sc->stc = %x\n", sc->stc); | |
631 //printf("storage_class = %x\n", storage_class); | |
632 | |
633 Dsymbol *parent = toParent(); | |
634 FuncDeclaration *fd = parent->isFuncDeclaration(); | |
635 | |
636 Type *tb = type->toBasetype(); | |
637 if (tb->ty == Tvoid && !(storage_class & STClazy)) | |
638 { error("voids have no value"); | |
639 type = Type::terror; | |
640 tb = type; | |
641 } | |
642 if (tb->ty == Tfunction) | |
643 { error("cannot be declared to be a function"); | |
644 type = Type::terror; | |
645 tb = type; | |
646 } | |
647 if (tb->ty == Tstruct) | |
648 { TypeStruct *ts = (TypeStruct *)tb; | |
649 | |
650 if (!ts->sym->members) | |
651 { | |
652 error("no definition of struct %s", ts->toChars()); | |
653 } | |
654 } | |
655 | |
656 if (tb->ty == Ttuple) | |
657 { /* Instead, declare variables for each of the tuple elements | |
658 * and add those. | |
659 */ | |
660 TypeTuple *tt = (TypeTuple *)tb; | |
661 size_t nelems = Argument::dim(tt->arguments); | |
662 Objects *exps = new Objects(); | |
663 exps->setDim(nelems); | |
664 | |
665 for (size_t i = 0; i < nelems; i++) | |
666 { Argument *arg = Argument::getNth(tt->arguments, i); | |
667 | |
668 OutBuffer buf; | |
669 buf.printf("_%s_field_%zu", ident->toChars(), i); | |
670 buf.writeByte(0); | |
671 char *name = (char *)buf.extractData(); | |
672 Identifier *id = new Identifier(name, TOKidentifier); | |
673 | |
674 VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL); | |
675 //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars()); | |
676 v->semantic(sc); | |
677 | |
678 if (sc->scopesym) | |
679 { //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars()); | |
680 if (sc->scopesym->members) | |
681 sc->scopesym->members->push(v); | |
682 } | |
683 | |
684 Expression *e = new DsymbolExp(loc, v); | |
685 exps->data[i] = e; | |
686 } | |
687 TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps); | |
688 v2->isexp = 1; | |
689 aliassym = v2; | |
690 return; | |
691 } | |
692 | |
693 if (storage_class & STCconst && !init && !fd) | |
694 // Initialize by constructor only | |
695 storage_class = (storage_class & ~STCconst) | STCctorinit; | |
696 | |
697 if (isConst()) | |
698 { | |
699 } | |
700 else if (isStatic()) | |
701 { | |
702 } | |
703 else if (isSynchronized()) | |
704 { | |
705 error("variable %s cannot be synchronized", toChars()); | |
706 } | |
707 else if (isOverride()) | |
708 { | |
709 error("override cannot be applied to variable"); | |
710 } | |
711 else if (isAbstract()) | |
712 { | |
713 error("abstract cannot be applied to variable"); | |
714 } | |
715 else if (storage_class & STCtemplateparameter) | |
716 { | |
717 } | |
718 else | |
719 { | |
720 AggregateDeclaration *aad = sc->anonAgg; | |
721 if (!aad) | |
722 aad = parent->isAggregateDeclaration(); | |
723 if (aad) | |
724 { | |
725 aad->addField(sc, this); | |
726 } | |
727 | |
728 InterfaceDeclaration *id = parent->isInterfaceDeclaration(); | |
729 if (id) | |
730 { | |
731 error("field not allowed in interface"); | |
732 } | |
733 | |
734 TemplateInstance *ti = parent->isTemplateInstance(); | |
735 if (ti) | |
736 { | |
737 // Take care of nested templates | |
738 while (1) | |
739 { | |
740 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); | |
741 if (!ti2) | |
742 break; | |
743 ti = ti2; | |
744 } | |
745 | |
746 // If it's a member template | |
747 AggregateDeclaration *ad = ti->tempdecl->isMember(); | |
748 if (ad && storage_class != STCundefined) | |
749 { | |
750 error("cannot use template to add field to aggregate '%s'", ad->toChars()); | |
751 } | |
752 } | |
753 } | |
754 | |
755 if (type->isauto() && !noauto) | |
756 { | |
757 if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd) | |
758 { | |
759 error("globals, statics, fields, ref and out parameters cannot be auto"); | |
760 } | |
761 | |
762 if (!(storage_class & (STCauto | STCscope))) | |
763 { | |
764 if (!(storage_class & STCparameter) && ident != Id::withSym) | |
765 error("reference to scope class must be scope"); | |
766 } | |
767 } | |
768 | |
769 if (!init && !sc->inunion && !isStatic() && !isConst() && fd && | |
770 !(storage_class & (STCfield | STCin | STCforeach))) | |
771 { | |
772 // Provide a default initializer | |
773 //printf("Providing default initializer for '%s'\n", toChars()); | |
774 if (type->ty == Tstruct && | |
775 ((TypeStruct *)type)->sym->zeroInit == 1) | |
19 | 776 { /* If a struct is all zeros, as a special case |
777 * set it's initializer to the integer 0. | |
778 * In AssignExp::toElem(), we check for this and issue | |
779 * a memset() to initialize the struct. | |
780 * Must do same check in interpreter. | |
781 */ | |
1 | 782 Expression *e = new IntegerExp(loc, 0, Type::tint32); |
783 Expression *e1; | |
784 e1 = new VarExp(loc, this); | |
785 e = new AssignExp(loc, e1, e); | |
786 e->type = e1->type; | |
787 init = new ExpInitializer(loc, e/*->type->defaultInit()*/); | |
788 return; | |
789 } | |
790 else if (type->ty == Ttypedef) | |
791 { TypeTypedef *td = (TypeTypedef *)type; | |
792 if (td->sym->init) | |
793 { init = td->sym->init; | |
794 ExpInitializer *ie = init->isExpInitializer(); | |
795 if (ie) | |
796 // Make copy so we can modify it | |
797 init = new ExpInitializer(ie->loc, ie->exp); | |
798 } | |
799 else | |
800 init = getExpInitializer(); | |
801 } | |
802 else | |
803 { | |
804 init = getExpInitializer(); | |
805 } | |
806 } | |
807 | |
808 if (init) | |
809 { | |
810 ArrayInitializer *ai = init->isArrayInitializer(); | |
19 | 811 if (ai && tb->ty == Taarray) |
1 | 812 { |
813 init = ai->toAssocArrayInitializer(); | |
814 } | |
815 | |
19 | 816 StructInitializer *si = init->isStructInitializer(); |
1 | 817 ExpInitializer *ei = init->isExpInitializer(); |
818 | |
819 // See if we can allocate on the stack | |
820 if (ei && isScope() && ei->exp->op == TOKnew) | |
821 { NewExp *ne = (NewExp *)ei->exp; | |
822 if (!(ne->newargs && ne->newargs->dim)) | |
823 { ne->onstack = 1; | |
824 onstack = 1; | |
825 if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL)) | |
826 onstack = 2; | |
827 } | |
828 } | |
829 | |
830 // If inside function, there is no semantic3() call | |
831 if (sc->func) | |
832 { | |
833 // If local variable, use AssignExp to handle all the various | |
834 // possibilities. | |
835 if (fd && !isStatic() && !isConst() && !init->isVoidInitializer()) | |
836 { | |
837 Expression *e1; | |
838 Type *t; | |
839 int dim; | |
840 | |
841 //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); | |
842 if (!ei) | |
843 { | |
844 Expression *e = init->toExpression(); | |
845 if (!e) | |
846 { | |
847 init = init->semantic(sc, type); | |
848 e = init->toExpression(); | |
849 if (!e) | |
850 { error("is not a static and cannot have static initializer"); | |
851 return; | |
852 } | |
853 } | |
854 ei = new ExpInitializer(init->loc, e); | |
855 init = ei; | |
856 } | |
857 | |
858 e1 = new VarExp(loc, this); | |
859 | |
860 t = type->toBasetype(); | |
861 if (t->ty == Tsarray) | |
862 { | |
863 dim = ((TypeSArray *)t)->dim->toInteger(); | |
864 // If multidimensional static array, treat as one large array | |
865 while (1) | |
866 { | |
867 t = t->next->toBasetype(); | |
868 if (t->ty != Tsarray) | |
869 break; | |
870 if (t->next->toBasetype()->ty == Tbit) | |
871 // t->size() gives size in bytes, convert to bits | |
872 dim *= t->size() * 8; | |
873 else | |
874 dim *= ((TypeSArray *)t)->dim->toInteger(); | |
875 e1->type = new TypeSArray(t->next, new IntegerExp(0, dim, Type::tindex)); | |
876 } | |
877 e1 = new SliceExp(loc, e1, NULL, NULL); | |
878 } | |
879 else if (t->ty == Tstruct) | |
880 { | |
881 ei->exp = ei->exp->semantic(sc); | |
882 if (!ei->exp->implicitConvTo(type)) | |
883 ei->exp = new CastExp(loc, ei->exp, type); | |
884 } | |
885 ei->exp = new AssignExp(loc, e1, ei->exp); | |
886 ei->exp->op = TOKconstruct; | |
887 canassign++; | |
888 ei->exp = ei->exp->semantic(sc); | |
889 canassign--; | |
890 ei->exp->optimize(WANTvalue); | |
891 } | |
892 else | |
893 { | |
894 init = init->semantic(sc, type); | |
895 if (fd && isConst() && !isStatic()) | |
896 { // Make it static | |
897 storage_class |= STCstatic; | |
898 } | |
899 } | |
900 } | |
901 else if (isConst() || isFinal()) | |
902 { | |
903 /* Because we may need the results of a const declaration in a | |
904 * subsequent type, such as an array dimension, before semantic2() | |
905 * gets ordinarily run, try to run semantic2() now. | |
906 * Ignore failure. | |
907 */ | |
908 | |
19 | 909 if (!global.errors && !inferred) |
1 | 910 { |
911 unsigned errors = global.errors; | |
912 global.gag++; | |
913 //printf("+gag\n"); | |
19 | 914 Expression *e; |
915 Initializer *i2 = init; | |
1 | 916 inuse++; |
19 | 917 if (ei) |
918 { | |
919 e = ei->exp->syntaxCopy(); | |
920 e = e->semantic(sc); | |
921 e = e->implicitCastTo(sc, type); | |
922 } | |
923 else if (si || ai) | |
924 { i2 = init->syntaxCopy(); | |
925 i2 = i2->semantic(sc, type); | |
926 } | |
1 | 927 inuse--; |
928 global.gag--; | |
929 //printf("-gag\n"); | |
930 if (errors != global.errors) // if errors happened | |
931 { | |
932 if (global.gag == 0) | |
933 global.errors = errors; // act as if nothing happened | |
934 } | |
19 | 935 else if (ei) |
1 | 936 { |
937 e = e->optimize(WANTvalue | WANTinterpret); | |
938 if (e->op == TOKint64 || e->op == TOKstring) | |
939 { | |
940 ei->exp = e; // no errors, keep result | |
941 } | |
942 } | |
19 | 943 else |
944 init = i2; // no errors, keep result | |
1 | 945 } |
946 } | |
947 } | |
948 } | |
949 | |
950 ExpInitializer *VarDeclaration::getExpInitializer() | |
951 { | |
952 ExpInitializer *ei; | |
953 | |
954 if (init) | |
955 ei = init->isExpInitializer(); | |
956 else | |
957 { | |
958 Expression *e = type->defaultInit(); | |
959 if (e) | |
960 ei = new ExpInitializer(loc, e); | |
961 else | |
962 ei = NULL; | |
963 } | |
964 return ei; | |
965 } | |
966 | |
967 void VarDeclaration::semantic2(Scope *sc) | |
968 { | |
969 //printf("VarDeclaration::semantic2('%s')\n", toChars()); | |
970 if (init && !toParent()->isFuncDeclaration()) | |
971 { inuse++; | |
972 #if 0 | |
973 ExpInitializer *ei = init->isExpInitializer(); | |
974 if (ei) | |
975 { | |
976 ei->exp->dump(0); | |
977 printf("type = %p\n", ei->exp->type); | |
978 } | |
979 #endif | |
980 init = init->semantic(sc, type); | |
981 inuse--; | |
982 } | |
983 } | |
984 | |
985 char *VarDeclaration::kind() | |
986 { | |
987 return "variable"; | |
988 } | |
989 | |
990 Dsymbol *VarDeclaration::toAlias() | |
991 { | |
992 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); | |
993 assert(this != aliassym); | |
994 Dsymbol *s = aliassym ? aliassym->toAlias() : this; | |
995 return s; | |
996 } | |
997 | |
998 void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
999 { | |
1000 if (storage_class & STCconst) | |
1001 buf->writestring("const "); | |
1002 if (storage_class & STCstatic) | |
1003 buf->writestring("static "); | |
1004 if (type) | |
1005 type->toCBuffer(buf, ident, hgs); | |
1006 else | |
1007 buf->writestring(ident->toChars()); | |
1008 if (init) | |
1009 { buf->writestring(" = "); | |
1010 init->toCBuffer(buf, hgs); | |
1011 } | |
1012 buf->writeByte(';'); | |
1013 buf->writenl(); | |
1014 } | |
1015 | |
1016 int VarDeclaration::needThis() | |
1017 { | |
1018 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class); | |
1019 return storage_class & STCfield; | |
1020 } | |
1021 | |
1022 int VarDeclaration::isImportedSymbol() | |
1023 { | |
1024 if (protection == PROTexport && !init && (isStatic() || isConst() || parent->isModule())) | |
1025 return TRUE; | |
1026 return FALSE; | |
1027 } | |
1028 | |
1029 void VarDeclaration::checkCtorConstInit() | |
1030 { | |
1031 if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield)) | |
1032 error("missing initializer in static constructor for const variable"); | |
1033 } | |
1034 | |
1035 /************************************ | |
1036 * Check to see if variable is a reference to an enclosing function | |
1037 * or not. | |
1038 */ | |
1039 | |
1040 void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) | |
1041 { | |
1042 if (!isDataseg() && parent != sc->parent && parent) | |
1043 { | |
1044 FuncDeclaration *fdv = toParent()->isFuncDeclaration(); | |
1045 FuncDeclaration *fdthis = sc->parent->isFuncDeclaration(); | |
1046 | |
1047 if (fdv && fdthis) | |
1048 { | |
1049 if (loc.filename) | |
1050 fdthis->getLevel(loc, fdv); | |
1051 nestedref = 1; | |
1052 fdv->nestedFrameRef = 1; | |
50
6fcc08a4d406
[svn r54] Added support for nested delegates referencing parent's stack variables.
lindquist
parents:
40
diff
changeset
|
1053 fdv->llvmNestedVars.insert(this); |
1 | 1054 //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars()); |
1055 } | |
1056 } | |
1057 } | |
1058 | |
1059 /******************************* | |
1060 * Does symbol go into data segment? | |
1061 */ | |
1062 | |
1063 int VarDeclaration::isDataseg() | |
1064 { | |
1065 #if 0 | |
1066 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars()); | |
1067 printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance()); | |
1068 printf("parent = '%s'\n", parent->toChars()); | |
1069 #endif | |
1070 Dsymbol *parent = this->toParent(); | |
1071 if (!parent && !(storage_class & (STCstatic | STCconst))) | |
1072 { error("forward referenced"); | |
1073 type = Type::terror; | |
1074 return 0; | |
1075 } | |
1076 return (storage_class & (STCstatic | STCconst) || | |
1077 parent->isModule() || | |
1078 parent->isTemplateInstance()); | |
1079 } | |
1080 | |
1081 int VarDeclaration::hasPointers() | |
1082 { | |
1083 return (!isDataseg() && type->hasPointers()); | |
1084 } | |
1085 | |
1086 /****************************************** | |
1087 * If a variable has an auto destructor call, return call for it. | |
1088 * Otherwise, return NULL. | |
1089 */ | |
1090 | |
1091 Expression *VarDeclaration::callAutoDtor() | |
1092 { Expression *e = NULL; | |
1093 | |
1094 if (storage_class & (STCauto | STCscope) && !noauto) | |
1095 { | |
1096 for (ClassDeclaration *cd = type->isClassHandle(); | |
1097 cd; | |
1098 cd = cd->baseClass) | |
1099 { | |
1100 /* We can do better if there's a way with onstack | |
1101 * classes to determine if there's no way the monitor | |
1102 * could be set. | |
1103 */ | |
1104 if (1 || onstack || cd->dtors.dim) // if any destructors | |
1105 { | |
1106 // delete this; | |
1107 Expression *ec; | |
1108 | |
1109 ec = new VarExp(loc, this); | |
1110 e = new DeleteExp(loc, ec); | |
1111 e->type = Type::tvoid; | |
1112 break; | |
1113 } | |
1114 } | |
1115 } | |
1116 return e; | |
1117 } | |
1118 | |
1119 | |
1120 /********************************* ClassInfoDeclaration ****************************/ | |
1121 | |
1122 ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd) | |
1123 : VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL) | |
1124 { | |
1125 this->cd = cd; | |
1126 storage_class = STCstatic; | |
1127 } | |
1128 | |
1129 Dsymbol *ClassInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1130 { | |
1131 assert(0); // should never be produced by syntax | |
1132 return NULL; | |
1133 } | |
1134 | |
1135 void ClassInfoDeclaration::semantic(Scope *sc) | |
1136 { | |
1137 } | |
1138 | |
1139 /********************************* ModuleInfoDeclaration ****************************/ | |
1140 | |
1141 ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod) | |
1142 : VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL) | |
1143 { | |
1144 this->mod = mod; | |
1145 storage_class = STCstatic; | |
1146 } | |
1147 | |
1148 Dsymbol *ModuleInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1149 { | |
1150 assert(0); // should never be produced by syntax | |
1151 return NULL; | |
1152 } | |
1153 | |
1154 void ModuleInfoDeclaration::semantic(Scope *sc) | |
1155 { | |
1156 } | |
1157 | |
1158 /********************************* TypeInfoDeclaration ****************************/ | |
1159 | |
1160 TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal) | |
1161 : VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL) | |
1162 { | |
1163 this->tinfo = tinfo; | |
1164 storage_class = STCstatic; | |
1165 protection = PROTpublic; | |
1166 linkage = LINKc; | |
1167 } | |
1168 | |
1169 Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1170 { | |
1171 assert(0); // should never be produced by syntax | |
1172 return NULL; | |
1173 } | |
1174 | |
1175 void TypeInfoDeclaration::semantic(Scope *sc) | |
1176 { | |
1177 assert(linkage == LINKc); | |
1178 } | |
1179 | |
1180 /***************************** TypeInfoStructDeclaration **********************/ | |
1181 | |
1182 TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo) | |
1183 : TypeInfoDeclaration(tinfo, 0) | |
1184 { | |
1185 } | |
1186 | |
1187 /***************************** TypeInfoClassDeclaration ***********************/ | |
1188 | |
1189 TypeInfoClassDeclaration::TypeInfoClassDeclaration(Type *tinfo) | |
1190 : TypeInfoDeclaration(tinfo, 0) | |
1191 { | |
1192 } | |
1193 | |
1194 /***************************** TypeInfoInterfaceDeclaration *******************/ | |
1195 | |
1196 TypeInfoInterfaceDeclaration::TypeInfoInterfaceDeclaration(Type *tinfo) | |
1197 : TypeInfoDeclaration(tinfo, 0) | |
1198 { | |
1199 } | |
1200 | |
1201 /***************************** TypeInfoTypedefDeclaration *********************/ | |
1202 | |
1203 TypeInfoTypedefDeclaration::TypeInfoTypedefDeclaration(Type *tinfo) | |
1204 : TypeInfoDeclaration(tinfo, 0) | |
1205 { | |
1206 } | |
1207 | |
1208 /***************************** TypeInfoPointerDeclaration *********************/ | |
1209 | |
1210 TypeInfoPointerDeclaration::TypeInfoPointerDeclaration(Type *tinfo) | |
1211 : TypeInfoDeclaration(tinfo, 0) | |
1212 { | |
1213 } | |
1214 | |
1215 /***************************** TypeInfoArrayDeclaration ***********************/ | |
1216 | |
1217 TypeInfoArrayDeclaration::TypeInfoArrayDeclaration(Type *tinfo) | |
1218 : TypeInfoDeclaration(tinfo, 0) | |
1219 { | |
1220 } | |
1221 | |
1222 /***************************** TypeInfoStaticArrayDeclaration *****************/ | |
1223 | |
1224 TypeInfoStaticArrayDeclaration::TypeInfoStaticArrayDeclaration(Type *tinfo) | |
1225 : TypeInfoDeclaration(tinfo, 0) | |
1226 { | |
1227 } | |
1228 | |
1229 /***************************** TypeInfoAssociativeArrayDeclaration ************/ | |
1230 | |
1231 TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *tinfo) | |
1232 : TypeInfoDeclaration(tinfo, 0) | |
1233 { | |
1234 } | |
1235 | |
1236 /***************************** TypeInfoEnumDeclaration ***********************/ | |
1237 | |
1238 TypeInfoEnumDeclaration::TypeInfoEnumDeclaration(Type *tinfo) | |
1239 : TypeInfoDeclaration(tinfo, 0) | |
1240 { | |
1241 } | |
1242 | |
1243 /***************************** TypeInfoFunctionDeclaration ********************/ | |
1244 | |
1245 TypeInfoFunctionDeclaration::TypeInfoFunctionDeclaration(Type *tinfo) | |
1246 : TypeInfoDeclaration(tinfo, 0) | |
1247 { | |
1248 } | |
1249 | |
1250 /***************************** TypeInfoDelegateDeclaration ********************/ | |
1251 | |
1252 TypeInfoDelegateDeclaration::TypeInfoDelegateDeclaration(Type *tinfo) | |
1253 : TypeInfoDeclaration(tinfo, 0) | |
1254 { | |
1255 } | |
1256 | |
1257 /***************************** TypeInfoTupleDeclaration **********************/ | |
1258 | |
1259 TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo) | |
1260 : TypeInfoDeclaration(tinfo, 0) | |
1261 { | |
1262 } | |
1263 | |
1264 /********************************* ThisDeclaration ****************************/ | |
1265 | |
1266 // For the "this" parameter to member functions | |
1267 | |
1268 ThisDeclaration::ThisDeclaration(Type *t) | |
1269 : VarDeclaration(0, t, Id::This, NULL) | |
1270 { | |
1271 noauto = 1; | |
1272 } | |
1273 | |
1274 Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s) | |
1275 { | |
1276 assert(0); // should never be produced by syntax | |
1277 return NULL; | |
1278 } | |
1279 | |
1280 |