Mercurial > projects > ldc
annotate dmd/declaration.c @ 1147:dbe4af57b240
Changed use of toObjFile to a new codegen method.
More versioning of DMD specific codegen code.
author | Tomas Lindquist Olsen <tomas.l.olsen gmail.com> |
---|---|
date | Fri, 27 Mar 2009 17:54:27 +0100 |
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 |