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