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