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