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