Mercurial > projects > ldc
annotate dmd/declaration.c @ 1626:8fa4ab3dcc88
Merge DMD r320: refactor
---
dmd/expression.c | 7 +++----
dmd/expression.h | 2 +-
dmd/mtype.c | 34 ++++++++--------------------------
3 files changed, 12 insertions(+), 31 deletions(-)
author | Leandro Lucarella <llucax@gmail.com> |
---|---|
date | Wed, 06 Jan 2010 15:18:23 -0300 |
parents | fb2e6707ad17 |
children | 44b145be2ef5 |
rev | line source |
---|---|
1587 | 1 |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2009 by Digital Mars | |
4 // All Rights Reserved | |
5 // written by Walter Bright | |
6 // http://www.digitalmars.com | |
7 // License for redistribution is by either the Artistic License | |
8 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
9 // See the included readme.txt for details. | |
10 | |
11 #include <stdio.h> | |
12 #include <assert.h> | |
13 | |
14 #include "init.h" | |
15 #include "declaration.h" | |
16 #include "attrib.h" | |
17 #include "mtype.h" | |
18 #include "template.h" | |
19 #include "scope.h" | |
20 #include "aggregate.h" | |
21 #include "module.h" | |
22 #include "id.h" | |
23 #include "expression.h" | |
24 #include "hdrgen.h" | |
25 | |
26 /********************************* Declaration ****************************/ | |
27 | |
28 Declaration::Declaration(Identifier *id) | |
29 : Dsymbol(id) | |
30 { | |
31 type = NULL; | |
32 originalType = NULL; | |
33 storage_class = STCundefined; | |
34 protection = PROTundefined; | |
35 linkage = LINKdefault; | |
36 inuse = 0; | |
37 } | |
38 | |
39 void Declaration::semantic(Scope *sc) | |
40 { | |
41 } | |
42 | |
43 const char *Declaration::kind() | |
44 { | |
45 return "declaration"; | |
46 } | |
47 | |
48 unsigned Declaration::size(Loc loc) | |
49 { | |
50 assert(type); | |
51 return type->size(); | |
52 } | |
53 | |
54 int Declaration::isStaticConstructor() | |
55 { | |
56 return FALSE; | |
57 } | |
58 | |
59 int Declaration::isStaticDestructor() | |
60 { | |
61 return FALSE; | |
62 } | |
63 | |
64 int Declaration::isDelete() | |
65 { | |
66 return FALSE; | |
67 } | |
68 | |
69 int Declaration::isDataseg() | |
70 { | |
71 return FALSE; | |
72 } | |
73 | |
74 int Declaration::isThreadlocal() | |
75 { | |
76 return FALSE; | |
77 } | |
78 | |
79 int Declaration::isCodeseg() | |
80 { | |
81 return FALSE; | |
82 } | |
83 | |
84 enum PROT Declaration::prot() | |
85 { | |
86 return protection; | |
87 } | |
88 | |
89 /************************************* | |
90 * Check to see if declaration can be modified in this context (sc). | |
91 * Issue error if not. | |
92 */ | |
93 | |
94 #if DMDV2 | |
95 void Declaration::checkModify(Loc loc, Scope *sc, Type *t) | |
96 { | |
97 if (sc->incontract && isParameter()) | |
98 error(loc, "cannot modify parameter '%s' in contract", toChars()); | |
99 | |
100 if (isCtorinit()) | |
101 { // It's only modifiable if inside the right constructor | |
102 Dsymbol *s = sc->func; | |
103 while (1) | |
104 { | |
105 FuncDeclaration *fd = NULL; | |
106 if (s) | |
107 fd = s->isFuncDeclaration(); | |
108 if (fd && | |
109 ((fd->isCtorDeclaration() && storage_class & STCfield) || | |
110 (fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) && | |
111 fd->toParent() == toParent() | |
112 ) | |
113 { | |
114 VarDeclaration *v = isVarDeclaration(); | |
115 assert(v); | |
116 v->ctorinit = 1; | |
117 //printf("setting ctorinit\n"); | |
118 } | |
119 else | |
120 { | |
121 if (s) | |
122 { s = s->toParent2(); | |
123 continue; | |
124 } | |
125 else | |
126 { | |
127 const char *p = isStatic() ? "static " : ""; | |
128 error(loc, "can only initialize %sconst %s inside %sconstructor", | |
129 p, toChars(), p); | |
130 } | |
131 } | |
132 break; | |
133 } | |
134 } | |
135 else | |
136 { | |
137 VarDeclaration *v = isVarDeclaration(); | |
138 if (v && v->canassign == 0) | |
139 { | |
140 const char *p = NULL; | |
141 if (isConst()) | |
142 p = "const"; | |
1619
c61782a76dff
Merge DMD r304: refactor invariant => immutable
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
143 else if (isImmutable()) |
1587 | 144 p = "immutable"; |
145 else if (storage_class & STCmanifest) | |
146 p = "enum"; | |
147 else if (!t->isAssignable()) | |
148 p = "struct with immutable members"; | |
149 if (p) | |
150 { error(loc, "cannot modify %s", p); | |
151 } | |
152 } | |
153 } | |
154 } | |
155 #endif | |
156 | |
157 | |
158 /********************************* TupleDeclaration ****************************/ | |
159 | |
160 TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects) | |
161 : Declaration(id) | |
162 { | |
163 this->type = NULL; | |
164 this->objects = objects; | |
165 this->isexp = 0; | |
166 this->tupletype = NULL; | |
167 } | |
168 | |
169 Dsymbol *TupleDeclaration::syntaxCopy(Dsymbol *s) | |
170 { | |
171 assert(0); | |
172 return NULL; | |
173 } | |
174 | |
175 const char *TupleDeclaration::kind() | |
176 { | |
177 return "tuple"; | |
178 } | |
179 | |
180 Type *TupleDeclaration::getType() | |
181 { | |
182 /* If this tuple represents a type, return that type | |
183 */ | |
184 | |
185 //printf("TupleDeclaration::getType() %s\n", toChars()); | |
186 if (isexp) | |
187 return NULL; | |
188 if (!tupletype) | |
189 { | |
190 /* It's only a type tuple if all the Object's are types | |
191 */ | |
192 for (size_t i = 0; i < objects->dim; i++) | |
193 { Object *o = (Object *)objects->data[i]; | |
194 | |
195 if (o->dyncast() != DYNCAST_TYPE) | |
196 { | |
197 //printf("\tnot[%d], %p, %d\n", i, o, o->dyncast()); | |
198 return NULL; | |
199 } | |
200 } | |
201 | |
202 /* We know it's a type tuple, so build the TypeTuple | |
203 */ | |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
204 Parameters *args = new Parameters(); |
1587 | 205 args->setDim(objects->dim); |
206 OutBuffer buf; | |
207 int hasdeco = 1; | |
208 for (size_t i = 0; i < objects->dim; i++) | |
209 { Type *t = (Type *)objects->data[i]; | |
210 | |
211 //printf("type = %s\n", t->toChars()); | |
212 #if 0 | |
213 buf.printf("_%s_%d", ident->toChars(), i); | |
214 char *name = (char *)buf.extractData(); | |
215 Identifier *id = new Identifier(name, TOKidentifier); | |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
216 Parameter *arg = new Parameter(STCin, t, id, NULL); |
1587 | 217 #else |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
218 Parameter *arg = new Parameter(STCin, t, NULL, NULL); |
1587 | 219 #endif |
220 args->data[i] = (void *)arg; | |
221 if (!t->deco) | |
222 hasdeco = 0; | |
223 } | |
224 | |
225 tupletype = new TypeTuple(args); | |
226 if (hasdeco) | |
227 return tupletype->semantic(0, NULL); | |
228 } | |
229 | |
230 return tupletype; | |
231 } | |
232 | |
233 int TupleDeclaration::needThis() | |
234 { | |
235 //printf("TupleDeclaration::needThis(%s)\n", toChars()); | |
236 for (size_t i = 0; i < objects->dim; i++) | |
237 { Object *o = (Object *)objects->data[i]; | |
238 if (o->dyncast() == DYNCAST_EXPRESSION) | |
239 { Expression *e = (Expression *)o; | |
240 if (e->op == TOKdsymbol) | |
241 { DsymbolExp *ve = (DsymbolExp *)e; | |
242 Declaration *d = ve->s->isDeclaration(); | |
243 if (d && d->needThis()) | |
244 { | |
245 return 1; | |
246 } | |
247 } | |
248 } | |
249 } | |
250 return 0; | |
251 } | |
252 | |
253 /********************************* TypedefDeclaration ****************************/ | |
254 | |
255 TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init) | |
256 : Declaration(id) | |
257 { | |
258 this->type = new TypeTypedef(this); | |
259 this->basetype = basetype->toBasetype(); | |
260 this->init = init; | |
261 #ifdef _DH | |
262 this->htype = NULL; | |
263 this->hbasetype = NULL; | |
264 #endif | |
265 this->sem = 0; | |
266 this->loc = loc; | |
267 #if IN_DMD | |
268 this->sinit = NULL; | |
269 #endif | |
270 } | |
271 | |
272 Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s) | |
273 { | |
274 Type *basetype = this->basetype->syntaxCopy(); | |
275 | |
276 Initializer *init = NULL; | |
277 if (this->init) | |
278 init = this->init->syntaxCopy(); | |
279 | |
280 assert(!s); | |
281 TypedefDeclaration *st; | |
282 st = new TypedefDeclaration(loc, ident, basetype, init); | |
283 #ifdef _DH | |
284 // Syntax copy for header file | |
285 if (!htype) // Don't overwrite original | |
286 { if (type) // Make copy for both old and new instances | |
287 { htype = type->syntaxCopy(); | |
288 st->htype = type->syntaxCopy(); | |
289 } | |
290 } | |
291 else // Make copy of original for new instance | |
292 st->htype = htype->syntaxCopy(); | |
293 if (!hbasetype) | |
294 { if (basetype) | |
295 { hbasetype = basetype->syntaxCopy(); | |
296 st->hbasetype = basetype->syntaxCopy(); | |
297 } | |
298 } | |
299 else | |
300 st->hbasetype = hbasetype->syntaxCopy(); | |
301 #endif | |
302 return st; | |
303 } | |
304 | |
305 void TypedefDeclaration::semantic(Scope *sc) | |
306 { | |
307 //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem); | |
308 if (sem == 0) | |
309 { sem = 1; | |
310 basetype = basetype->semantic(loc, sc); | |
311 sem = 2; | |
1621
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
312 #if DMDV2 |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
313 type = type->addStorageClass(storage_class); |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
314 #endif |
1587 | 315 type = type->semantic(loc, sc); |
316 if (sc->parent->isFuncDeclaration() && init) | |
317 semantic2(sc); | |
318 storage_class |= sc->stc & STCdeprecated; | |
319 } | |
320 else if (sem == 1) | |
321 { | |
322 error("circular definition"); | |
323 } | |
324 } | |
325 | |
326 void TypedefDeclaration::semantic2(Scope *sc) | |
327 { | |
328 //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem); | |
329 if (sem == 2) | |
330 { sem = 3; | |
331 if (init) | |
332 { | |
333 init = init->semantic(sc, basetype); | |
334 | |
335 ExpInitializer *ie = init->isExpInitializer(); | |
336 if (ie) | |
337 { | |
338 if (ie->exp->type == basetype) | |
339 ie->exp->type = type; | |
340 } | |
341 } | |
342 } | |
343 } | |
344 | |
345 const char *TypedefDeclaration::kind() | |
346 { | |
347 return "typedef"; | |
348 } | |
349 | |
350 Type *TypedefDeclaration::getType() | |
351 { | |
352 return type; | |
353 } | |
354 | |
355 void TypedefDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
356 { | |
357 buf->writestring("typedef "); | |
358 basetype->toCBuffer(buf, ident, hgs); | |
359 if (init) | |
360 { | |
361 buf->writestring(" = "); | |
362 init->toCBuffer(buf, hgs); | |
363 } | |
364 buf->writeByte(';'); | |
365 buf->writenl(); | |
366 } | |
367 | |
368 /********************************* AliasDeclaration ****************************/ | |
369 | |
370 AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type) | |
371 : Declaration(id) | |
372 { | |
373 //printf("AliasDeclaration(id = '%s', type = %p)\n", id->toChars(), type); | |
374 //printf("type = '%s'\n", type->toChars()); | |
375 this->loc = loc; | |
376 this->type = type; | |
377 this->aliassym = NULL; | |
378 #ifdef _DH | |
379 this->htype = NULL; | |
380 this->haliassym = NULL; | |
381 #endif | |
382 this->overnext = NULL; | |
383 this->inSemantic = 0; | |
384 this->importprot = PROTundefined; | |
385 assert(type); | |
386 } | |
387 | |
388 AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s) | |
389 : Declaration(id) | |
390 { | |
391 //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s); | |
392 assert(s != this); | |
393 this->loc = loc; | |
394 this->type = NULL; | |
395 this->aliassym = s; | |
396 #ifdef _DH | |
397 this->htype = NULL; | |
398 this->haliassym = NULL; | |
399 #endif | |
400 this->overnext = NULL; | |
401 this->inSemantic = 0; | |
402 assert(s); | |
403 } | |
404 | |
405 Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s) | |
406 { | |
407 //printf("AliasDeclaration::syntaxCopy()\n"); | |
408 assert(!s); | |
409 AliasDeclaration *sa; | |
410 if (type) | |
411 sa = new AliasDeclaration(loc, ident, type->syntaxCopy()); | |
412 else | |
413 sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL)); | |
414 #ifdef _DH | |
415 // Syntax copy for header file | |
416 if (!htype) // Don't overwrite original | |
417 { if (type) // Make copy for both old and new instances | |
418 { htype = type->syntaxCopy(); | |
419 sa->htype = type->syntaxCopy(); | |
420 } | |
421 } | |
422 else // Make copy of original for new instance | |
423 sa->htype = htype->syntaxCopy(); | |
424 if (!haliassym) | |
425 { if (aliassym) | |
426 { haliassym = aliassym->syntaxCopy(s); | |
427 sa->haliassym = aliassym->syntaxCopy(s); | |
428 } | |
429 } | |
430 else | |
431 sa->haliassym = haliassym->syntaxCopy(s); | |
432 #endif | |
433 return sa; | |
434 } | |
435 | |
436 void AliasDeclaration::semantic(Scope *sc) | |
437 { | |
438 //printf("AliasDeclaration::semantic() %s\n", toChars()); | |
439 if (aliassym) | |
440 { | |
441 if (aliassym->isTemplateInstance()) | |
442 aliassym->semantic(sc); | |
443 return; | |
444 } | |
445 this->inSemantic = 1; | |
446 | |
1621
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
447 #if DMDV1 // don't really know why this is here |
1587 | 448 if (storage_class & STCconst) |
449 error("cannot be const"); | |
1621
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
450 #endif |
1587 | 451 |
452 storage_class |= sc->stc & STCdeprecated; | |
453 | |
454 // Given: | |
455 // alias foo.bar.abc def; | |
456 // it is not knowable from the syntax whether this is an alias | |
457 // for a type or an alias for a symbol. It is up to the semantic() | |
458 // pass to distinguish. | |
459 // If it is a type, then type is set and getType() will return that | |
460 // type. If it is a symbol, then aliassym is set and type is NULL - | |
461 // toAlias() will return aliasssym. | |
462 | |
463 Dsymbol *s; | |
464 Type *t; | |
465 Expression *e; | |
466 | |
467 /* This section is needed because resolve() will: | |
468 * const x = 3; | |
469 * alias x y; | |
470 * try to alias y to 3. | |
471 */ | |
472 s = type->toDsymbol(sc); | |
473 if (s | |
474 #if DMDV2 | |
475 ` && ((s->getType() && type->equals(s->getType())) || s->isEnumMember()) | |
476 #endif | |
477 ) | |
478 goto L2; // it's a symbolic alias | |
479 | |
480 #if DMDV2 | |
1621
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
481 type = type->addStorageClass(storage_class); |
1587 | 482 if (storage_class & (STCref | STCnothrow | STCpure)) |
483 { // For 'ref' to be attached to function types, and picked | |
484 // up by Type::resolve(), it has to go into sc. | |
485 sc = sc->push(); | |
1621
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
486 sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared); |
1587 | 487 type->resolve(loc, sc, &e, &t, &s); |
488 sc = sc->pop(); | |
489 } | |
490 else | |
491 #endif | |
492 type->resolve(loc, sc, &e, &t, &s); | |
493 if (s) | |
494 { | |
495 goto L2; | |
496 } | |
497 else if (e) | |
498 { | |
499 // Try to convert Expression to Dsymbol | |
500 if (e->op == TOKvar) | |
501 { s = ((VarExp *)e)->var; | |
502 goto L2; | |
503 } | |
504 else if (e->op == TOKfunction) | |
505 { s = ((FuncExp *)e)->fd; | |
506 goto L2; | |
507 } | |
508 else | |
509 { error("cannot alias an expression %s", e->toChars()); | |
510 t = e->type; | |
511 } | |
512 } | |
513 else if (t) | |
514 { | |
515 type = t; | |
516 } | |
517 if (overnext) | |
518 ScopeDsymbol::multiplyDefined(0, this, overnext); | |
519 this->inSemantic = 0; | |
520 return; | |
521 | |
522 L2: | |
523 //printf("alias is a symbol %s %s\n", s->kind(), s->toChars()); | |
524 type = NULL; | |
525 VarDeclaration *v = s->isVarDeclaration(); | |
526 if (v && v->linkage == LINKdefault) | |
527 { | |
528 error("forward reference of %s", v->toChars()); | |
529 s = NULL; | |
530 } | |
531 else | |
532 { | |
533 FuncDeclaration *f = s->toAlias()->isFuncDeclaration(); | |
534 if (f) | |
535 { | |
536 if (overnext) | |
537 { | |
538 FuncAliasDeclaration *fa = new FuncAliasDeclaration(f); | |
539 fa->importprot = importprot; | |
540 if (!fa->overloadInsert(overnext)) | |
541 ScopeDsymbol::multiplyDefined(0, f, overnext); | |
542 overnext = NULL; | |
543 s = fa; | |
544 s->parent = sc->parent; | |
545 } | |
546 } | |
547 if (overnext) | |
548 ScopeDsymbol::multiplyDefined(0, s, overnext); | |
549 if (s == this) | |
550 { | |
551 assert(global.errors); | |
552 s = NULL; | |
553 } | |
554 } | |
555 if (!aliassym) | |
556 aliassym = s; | |
557 this->inSemantic = 0; | |
558 } | |
559 | |
560 int AliasDeclaration::overloadInsert(Dsymbol *s) | |
561 { | |
562 /* Don't know yet what the aliased symbol is, so assume it can | |
563 * be overloaded and check later for correctness. | |
564 */ | |
565 | |
566 //printf("AliasDeclaration::overloadInsert('%s')\n", s->toChars()); | |
567 if (overnext == NULL) | |
568 { | |
569 if (s == this) | |
570 { | |
571 return TRUE; | |
572 } | |
573 overnext = s; | |
574 return TRUE; | |
575 } | |
576 else | |
577 { | |
578 return overnext->overloadInsert(s); | |
579 } | |
580 } | |
581 | |
582 const char *AliasDeclaration::kind() | |
583 { | |
584 return "alias"; | |
585 } | |
586 | |
587 Type *AliasDeclaration::getType() | |
588 { | |
589 //printf("AliasDeclaration::getType() %s\n", type->toChars()); | |
590 #if 0 | |
591 if (!type->deco && scope) | |
592 semantic(scope); | |
593 if (type && !type->deco) | |
594 error("forward reference to alias %s\n", toChars()); | |
595 #endif | |
596 return type; | |
597 } | |
598 | |
599 Dsymbol *AliasDeclaration::toAlias() | |
600 { | |
601 //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : ""); | |
602 assert(this != aliassym); | |
603 //static int count; if (++count == 75) exit(0); //*(char*)0=0; | |
604 if (inSemantic) | |
605 { error("recursive alias declaration"); | |
606 aliassym = new TypedefDeclaration(loc, ident, Type::terror, NULL); | |
607 } | |
608 Dsymbol *s = aliassym ? aliassym->toAlias() : this; | |
609 return s; | |
610 } | |
611 | |
612 void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
613 { | |
614 buf->writestring("alias "); | |
615 #if 0 && _DH | |
616 if (hgs->hdrgen) | |
617 { | |
618 if (haliassym) | |
619 { | |
620 buf->writestring(haliassym->toChars()); | |
621 buf->writeByte(' '); | |
622 buf->writestring(ident->toChars()); | |
623 } | |
624 else | |
625 htype->toCBuffer(buf, ident, hgs); | |
626 } | |
627 else | |
628 #endif | |
629 { | |
630 if (aliassym) | |
631 { | |
632 buf->writestring(aliassym->toChars()); | |
633 buf->writeByte(' '); | |
634 buf->writestring(ident->toChars()); | |
635 } | |
636 else | |
637 type->toCBuffer(buf, ident, hgs); | |
638 } | |
639 buf->writeByte(';'); | |
640 buf->writenl(); | |
641 } | |
642 | |
643 /********************************* VarDeclaration ****************************/ | |
644 | |
645 VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer *init) | |
646 : Declaration(id) | |
647 { | |
648 //printf("VarDeclaration('%s')\n", id->toChars()); | |
649 #ifdef DEBUG | |
650 if (!type && !init) | |
651 { printf("VarDeclaration('%s')\n", id->toChars()); | |
652 //*(char*)0=0; | |
653 } | |
654 #endif | |
655 assert(type || init); | |
656 this->type = type; | |
657 this->init = init; | |
658 #ifdef _DH | |
659 this->htype = NULL; | |
660 this->hinit = NULL; | |
661 #endif | |
662 this->loc = loc; | |
663 offset = 0; | |
664 noscope = 0; | |
665 #if DMDV1 | |
666 nestedref = 0; | |
667 #endif | |
668 ctorinit = 0; | |
669 aliassym = NULL; | |
670 onstack = 0; | |
671 canassign = 0; | |
672 value = NULL; | |
673 | |
674 #if IN_LLVM | |
675 aggrIndex = 0; | |
676 | |
677 // LDC | |
678 anonDecl = NULL; | |
679 offset2 = 0; | |
680 | |
681 nakedUse = false; | |
682 | |
683 availableExternally = true; // assume this unless proven otherwise | |
684 #endif | |
685 } | |
686 | |
687 Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s) | |
688 { | |
689 //printf("VarDeclaration::syntaxCopy(%s)\n", toChars()); | |
690 | |
691 VarDeclaration *sv; | |
692 if (s) | |
693 { sv = (VarDeclaration *)s; | |
694 } | |
695 else | |
696 { | |
697 Initializer *init = NULL; | |
698 if (this->init) | |
699 { init = this->init->syntaxCopy(); | |
700 //init->isExpInitializer()->exp->print(); | |
701 //init->isExpInitializer()->exp->dump(0); | |
702 } | |
703 | |
704 sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init); | |
705 sv->storage_class = storage_class; | |
706 } | |
707 #ifdef _DH | |
708 // Syntax copy for header file | |
709 if (!htype) // Don't overwrite original | |
710 { if (type) // Make copy for both old and new instances | |
711 { htype = type->syntaxCopy(); | |
712 sv->htype = type->syntaxCopy(); | |
713 } | |
714 } | |
715 else // Make copy of original for new instance | |
716 sv->htype = htype->syntaxCopy(); | |
717 if (!hinit) | |
718 { if (init) | |
719 { hinit = init->syntaxCopy(); | |
720 sv->hinit = init->syntaxCopy(); | |
721 } | |
722 } | |
723 else | |
724 sv->hinit = hinit->syntaxCopy(); | |
725 #endif | |
726 return sv; | |
727 } | |
728 | |
729 void VarDeclaration::semantic(Scope *sc) | |
730 { | |
731 #if 0 | |
732 printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars()); | |
733 printf(" type = %s\n", type ? type->toChars() : "null"); | |
734 printf(" stc = x%x\n", sc->stc); | |
735 printf(" storage_class = x%x\n", storage_class); | |
736 printf("linkage = %d\n", sc->linkage); | |
737 //if (strcmp(toChars(), "mul") == 0) halt(); | |
738 #endif | |
739 | |
740 storage_class |= sc->stc; | |
741 if (storage_class & STCextern && init) | |
742 error("extern symbols cannot have initializers"); | |
743 | |
744 /* If auto type inference, do the inference | |
745 */ | |
746 int inferred = 0; | |
747 if (!type) | |
748 { inuse++; | |
749 type = init->inferType(sc); | |
750 inuse--; | |
751 inferred = 1; | |
752 | |
753 /* This is a kludge to support the existing syntax for RAII | |
754 * declarations. | |
755 */ | |
756 storage_class &= ~STCauto; | |
757 originalType = type; | |
758 } | |
759 else | |
760 { if (!originalType) | |
761 originalType = type; | |
762 type = type->semantic(loc, sc); | |
763 } | |
764 //printf(" semantic type = %s\n", type ? type->toChars() : "null"); | |
765 | |
766 type->checkDeprecated(loc, sc); | |
767 linkage = sc->linkage; | |
768 this->parent = sc->parent; | |
769 //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars()); | |
770 protection = sc->protection; | |
771 //printf("sc->stc = %x\n", sc->stc); | |
772 //printf("storage_class = x%x\n", storage_class); | |
773 | |
774 #if DMDV2 | |
775 if (storage_class & STCgshared && global.params.safe && !sc->module->safe) | |
776 { | |
777 error("__gshared not allowed in safe mode; use shared"); | |
778 } | |
779 #endif | |
780 | |
781 Dsymbol *parent = toParent(); | |
782 FuncDeclaration *fd = parent->isFuncDeclaration(); | |
783 | |
784 Type *tb = type->toBasetype(); | |
785 if (tb->ty == Tvoid && !(storage_class & STClazy)) | |
786 { error("voids have no value"); | |
787 type = Type::terror; | |
788 tb = type; | |
789 } | |
790 if (tb->ty == Tfunction) | |
791 { error("cannot be declared to be a function"); | |
792 type = Type::terror; | |
793 tb = type; | |
794 } | |
795 if (tb->ty == Tstruct) | |
796 { TypeStruct *ts = (TypeStruct *)tb; | |
797 | |
798 if (!ts->sym->members) | |
799 { | |
800 error("no definition of struct %s", ts->toChars()); | |
801 } | |
802 } | |
803 if ((storage_class & STCauto) && !inferred) | |
804 error("both auto and explicit type given"); | |
805 | |
806 if (tb->ty == Ttuple) | |
807 { /* Instead, declare variables for each of the tuple elements | |
808 * and add those. | |
809 */ | |
810 TypeTuple *tt = (TypeTuple *)tb; | |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
811 size_t nelems = Parameter::dim(tt->arguments); |
1587 | 812 Objects *exps = new Objects(); |
813 exps->setDim(nelems); | |
814 Expression *ie = init ? init->toExpression() : NULL; | |
815 | |
816 for (size_t i = 0; i < nelems; i++) | |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
817 { Parameter *arg = Parameter::getNth(tt->arguments, i); |
1587 | 818 |
819 OutBuffer buf; | |
820 buf.printf("_%s_field_%zu", ident->toChars(), i); | |
821 buf.writeByte(0); | |
822 char *name = (char *)buf.extractData(); | |
823 Identifier *id = new Identifier(name, TOKidentifier); | |
824 | |
825 Expression *einit = ie; | |
826 if (ie && ie->op == TOKtuple) | |
827 { einit = (Expression *)((TupleExp *)ie)->exps->data[i]; | |
828 } | |
829 Initializer *ti = init; | |
830 if (einit) | |
831 { ti = new ExpInitializer(einit->loc, einit); | |
832 } | |
833 | |
834 VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti); | |
835 //printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars()); | |
836 v->semantic(sc); | |
837 | |
838 /* | |
839 // removed for LDC since TupleDeclaration::toObj already creates the fields; | |
840 // adding them to the scope again leads to duplicates | |
841 if (sc->scopesym) | |
842 { //printf("adding %s to %s\n", v->toChars(), sc->scopesym->toChars()); | |
843 if (sc->scopesym->members) | |
844 sc->scopesym->members->push(v); | |
845 } | |
846 */ | |
847 Expression *e = new DsymbolExp(loc, v); | |
848 exps->data[i] = e; | |
849 } | |
850 TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps); | |
851 v2->isexp = 1; | |
852 aliassym = v2; | |
853 return; | |
854 } | |
855 | |
856 if (storage_class & STCconst && !init && !fd) | |
857 // Initialize by constructor only | |
858 storage_class = (storage_class & ~STCconst) | STCctorinit; | |
859 | |
860 if (isConst()) | |
861 { | |
862 } | |
863 else if (isStatic()) | |
864 { | |
865 } | |
866 else if (isSynchronized()) | |
867 { | |
868 error("variable %s cannot be synchronized", toChars()); | |
869 } | |
870 else if (isOverride()) | |
871 { | |
872 error("override cannot be applied to variable"); | |
873 } | |
874 else if (isAbstract()) | |
875 { | |
876 error("abstract cannot be applied to variable"); | |
877 } | |
878 else if (storage_class & STCtemplateparameter) | |
879 { | |
880 } | |
881 else | |
882 { | |
883 AggregateDeclaration *aad = sc->anonAgg; | |
884 if (!aad) | |
885 aad = parent->isAggregateDeclaration(); | |
886 if (aad) | |
887 { | |
888 #if DMDV2 | |
889 assert(!(storage_class & (STCextern | STCstatic | STCtls | STCgshared))); | |
890 | |
891 if (storage_class & (STCconst | STCimmutable) && init) | |
892 { | |
893 if (!type->toBasetype()->isTypeBasic()) | |
894 storage_class |= STCstatic; | |
895 } | |
896 else | |
897 #endif | |
898 aad->addField(sc, this); | |
899 } | |
900 | |
901 InterfaceDeclaration *id = parent->isInterfaceDeclaration(); | |
902 if (id) | |
903 { | |
904 error("field not allowed in interface"); | |
905 } | |
906 | |
907 /* Templates cannot add fields to aggregates | |
908 */ | |
909 TemplateInstance *ti = parent->isTemplateInstance(); | |
910 if (ti) | |
911 { | |
912 // Take care of nested templates | |
913 while (1) | |
914 { | |
915 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); | |
916 if (!ti2) | |
917 break; | |
918 ti = ti2; | |
919 } | |
920 | |
921 // If it's a member template | |
922 AggregateDeclaration *ad = ti->tempdecl->isMember(); | |
923 if (ad && storage_class != STCundefined) | |
924 { | |
925 error("cannot use template to add field to aggregate '%s'", ad->toChars()); | |
926 } | |
927 } | |
928 } | |
929 | |
930 #if DMDV2 | |
931 if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref && | |
932 ident != Id::This) | |
933 { | |
934 error("only parameters or foreach declarations can be ref"); | |
935 } | |
936 #endif | |
937 | |
938 if (type->isscope() && !noscope) | |
939 { | |
940 if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd) | |
941 { | |
942 error("globals, statics, fields, ref and out parameters cannot be scope"); | |
943 } | |
944 | |
945 if (!(storage_class & STCscope)) | |
946 { | |
947 if (!(storage_class & STCparameter) && ident != Id::withSym) | |
948 error("reference to scope class must be scope"); | |
949 } | |
950 } | |
951 | |
952 enum TOK op = TOKconstruct; | |
953 if (!init && !sc->inunion && !isStatic() && !isConst() && fd && | |
954 !(storage_class & (STCfield | STCin | STCforeach)) && | |
955 type->size() != 0) | |
956 { | |
957 // Provide a default initializer | |
958 //printf("Providing default initializer for '%s'\n", toChars()); | |
959 if (type->ty == Tstruct && | |
960 ((TypeStruct *)type)->sym->zeroInit == 1) | |
961 { /* If a struct is all zeros, as a special case | |
962 * set it's initializer to the integer 0. | |
963 * In AssignExp::toElem(), we check for this and issue | |
964 * a memset() to initialize the struct. | |
965 * Must do same check in interpreter. | |
966 */ | |
967 Expression *e = new IntegerExp(loc, 0, Type::tint32); | |
968 Expression *e1; | |
969 e1 = new VarExp(loc, this); | |
970 e = new AssignExp(loc, e1, e); | |
971 e->op = TOKconstruct; | |
972 e->type = e1->type; // don't type check this, it would fail | |
973 init = new ExpInitializer(loc, e); | |
974 return; | |
975 } | |
976 else if (type->ty == Ttypedef) | |
977 { TypeTypedef *td = (TypeTypedef *)type; | |
978 if (td->sym->init) | |
979 { init = td->sym->init; | |
980 ExpInitializer *ie = init->isExpInitializer(); | |
981 if (ie) | |
982 // Make copy so we can modify it | |
983 init = new ExpInitializer(ie->loc, ie->exp); | |
984 } | |
985 else | |
986 init = getExpInitializer(); | |
987 } | |
988 else | |
989 { | |
990 init = getExpInitializer(); | |
991 } | |
992 // Default initializer is always a blit | |
993 op = TOKblit; | |
994 } | |
995 | |
996 if (init) | |
997 { | |
998 sc = sc->push(); | |
999 sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCref); | |
1000 | |
1001 ArrayInitializer *ai = init->isArrayInitializer(); | |
1002 if (ai && tb->ty == Taarray) | |
1003 { | |
1004 init = ai->toAssocArrayInitializer(); | |
1005 } | |
1006 | |
1007 StructInitializer *si = init->isStructInitializer(); | |
1008 ExpInitializer *ei = init->isExpInitializer(); | |
1009 | |
1010 // See if initializer is a NewExp that can be allocated on the stack | |
1011 if (ei && isScope() && ei->exp->op == TOKnew) | |
1012 { NewExp *ne = (NewExp *)ei->exp; | |
1013 if (!(ne->newargs && ne->newargs->dim)) | |
1014 { ne->onstack = 1; | |
1015 onstack = 1; | |
1016 if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL)) | |
1017 onstack = 2; | |
1018 } | |
1019 } | |
1020 | |
1021 // If inside function, there is no semantic3() call | |
1022 if (sc->func) | |
1023 { | |
1024 // If local variable, use AssignExp to handle all the various | |
1025 // possibilities. | |
1026 if (fd && !isStatic() && !isConst() && !init->isVoidInitializer()) | |
1027 { | |
1028 //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); | |
1029 if (!ei) | |
1030 { | |
1031 Expression *e = init->toExpression(); | |
1032 if (!e) | |
1033 { | |
1034 init = init->semantic(sc, type); | |
1035 e = init->toExpression(); | |
1036 if (!e) | |
1037 { error("is not a static and cannot have static initializer"); | |
1038 return; | |
1039 } | |
1040 } | |
1041 ei = new ExpInitializer(init->loc, e); | |
1042 init = ei; | |
1043 } | |
1044 | |
1045 Expression *e1 = new VarExp(loc, this); | |
1046 | |
1047 Type *t = type->toBasetype(); | |
1048 if (t->ty == Tsarray && !(storage_class & (STCref | STCout))) | |
1049 { | |
1050 ei->exp = ei->exp->semantic(sc); | |
1051 if (!ei->exp->implicitConvTo(type)) | |
1052 { | |
1053 int dim = ((TypeSArray *)t)->dim->toInteger(); | |
1054 // If multidimensional static array, treat as one large array | |
1055 while (1) | |
1056 { | |
1057 t = t->nextOf()->toBasetype(); | |
1058 if (t->ty != Tsarray) | |
1059 break; | |
1060 dim *= ((TypeSArray *)t)->dim->toInteger(); | |
1061 e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex)); | |
1062 } | |
1063 } | |
1064 e1 = new SliceExp(loc, e1, NULL, NULL); | |
1065 } | |
1066 else if (t->ty == Tstruct) | |
1067 { | |
1068 ei->exp = ei->exp->semantic(sc); | |
1069 ei->exp = resolveProperties(sc, ei->exp); | |
1070 StructDeclaration *sd = ((TypeStruct *)t)->sym; | |
1071 #if DMDV2 | |
1072 /* Look to see if initializer is a call to the constructor | |
1073 */ | |
1074 if (sd->ctor && // there are constructors | |
1075 ei->exp->type->ty == Tstruct && // rvalue is the same struct | |
1076 ((TypeStruct *)ei->exp->type)->sym == sd && | |
1077 ei->exp->op == TOKstar) | |
1078 { | |
1079 /* Look for form of constructor call which is: | |
1080 * *__ctmp.ctor(arguments...) | |
1081 */ | |
1082 PtrExp *pe = (PtrExp *)ei->exp; | |
1083 if (pe->e1->op == TOKcall) | |
1084 { CallExp *ce = (CallExp *)pe->e1; | |
1085 if (ce->e1->op == TOKdotvar) | |
1086 { DotVarExp *dve = (DotVarExp *)ce->e1; | |
1087 if (dve->var->isCtorDeclaration()) | |
1088 { /* It's a constructor call, currently constructing | |
1089 * a temporary __ctmp. | |
1090 */ | |
1091 /* Before calling the constructor, initialize | |
1092 * variable with a bit copy of the default | |
1093 * initializer | |
1094 */ | |
1095 Expression *e = new AssignExp(loc, new VarExp(loc, this), t->defaultInit(loc)); | |
1096 e->op = TOKblit; | |
1097 e->type = t; | |
1098 ei->exp = new CommaExp(loc, e, ei->exp); | |
1099 | |
1100 /* Replace __ctmp being constructed with e1 | |
1101 */ | |
1102 dve->e1 = e1; | |
1103 return; | |
1104 } | |
1105 } | |
1106 } | |
1107 } | |
1108 #endif | |
1109 if (!ei->exp->implicitConvTo(type)) | |
1110 { | |
1111 /* Look for opCall | |
1112 * See bugzilla 2702 for more discussion | |
1113 */ | |
1114 Type *ti = ei->exp->type->toBasetype(); | |
1115 // Don't cast away invariant or mutability in initializer | |
1116 if (search_function(sd, Id::call) && | |
1117 /* Initializing with the same type is done differently | |
1118 */ | |
1119 !(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc))) | |
1120 { // Rewrite as e1.call(arguments) | |
1121 Expression * eCall = new DotIdExp(loc, e1, Id::call); | |
1122 ei->exp = new CallExp(loc, eCall, ei->exp); | |
1123 } | |
1124 } | |
1125 } | |
1126 ei->exp = new AssignExp(loc, e1, ei->exp); | |
1127 ei->exp->op = TOKconstruct; | |
1128 canassign++; | |
1129 ei->exp = ei->exp->semantic(sc); | |
1130 canassign--; | |
1131 ei->exp->optimize(WANTvalue); | |
1132 } | |
1133 else | |
1134 { | |
1135 init = init->semantic(sc, type); | |
1136 if (fd && isConst() && !isStatic()) | |
1137 { // Make it static | |
1138 storage_class |= STCstatic; | |
1139 } | |
1140 } | |
1141 } | |
1142 else if (isConst() || isFinal() || | |
1143 parent->isAggregateDeclaration()) | |
1144 { | |
1145 /* Because we may need the results of a const declaration in a | |
1146 * subsequent type, such as an array dimension, before semantic2() | |
1147 * gets ordinarily run, try to run semantic2() now. | |
1148 * Ignore failure. | |
1149 */ | |
1150 | |
1151 if (!global.errors && !inferred) | |
1152 { | |
1153 unsigned errors = global.errors; | |
1154 global.gag++; | |
1155 //printf("+gag\n"); | |
1156 Expression *e; | |
1157 Initializer *i2 = init; | |
1158 inuse++; | |
1159 if (ei) | |
1160 { | |
1161 e = ei->exp->syntaxCopy(); | |
1162 e = e->semantic(sc); | |
1163 e = e->implicitCastTo(sc, type); | |
1164 } | |
1165 else if (si || ai) | |
1166 { i2 = init->syntaxCopy(); | |
1167 i2 = i2->semantic(sc, type); | |
1168 } | |
1169 inuse--; | |
1170 global.gag--; | |
1171 //printf("-gag\n"); | |
1172 if (errors != global.errors) // if errors happened | |
1173 { | |
1174 if (global.gag == 0) | |
1175 global.errors = errors; // act as if nothing happened | |
1176 #if DMDV2 | |
1177 /* Save scope for later use, to try again | |
1178 */ | |
1179 scope = new Scope(*sc); | |
1180 scope->setNoFree(); | |
1181 #endif | |
1182 } | |
1183 else if (ei) | |
1184 { | |
1185 e = e->optimize(WANTvalue | WANTinterpret); | |
1186 if (e->op == TOKint64 || e->op == TOKstring || e->op == TOKfloat64) | |
1187 { | |
1188 ei->exp = e; // no errors, keep result | |
1189 } | |
1190 #if DMDV2 | |
1191 else | |
1192 { | |
1193 /* Save scope for later use, to try again | |
1194 */ | |
1195 scope = new Scope(*sc); | |
1196 scope->setNoFree(); | |
1197 } | |
1198 #endif | |
1199 } | |
1200 else | |
1201 init = i2; // no errors, keep result | |
1202 } | |
1203 } | |
1204 sc = sc->pop(); | |
1205 } | |
1206 } | |
1207 | |
1208 ExpInitializer *VarDeclaration::getExpInitializer() | |
1209 { | |
1210 ExpInitializer *ei; | |
1211 | |
1212 if (init) | |
1213 ei = init->isExpInitializer(); | |
1214 else | |
1215 { | |
1216 Expression *e = type->defaultInit(loc); | |
1217 if (e) | |
1218 ei = new ExpInitializer(loc, e); | |
1219 else | |
1220 ei = NULL; | |
1221 } | |
1222 return ei; | |
1223 } | |
1224 | |
1225 void VarDeclaration::semantic2(Scope *sc) | |
1226 { | |
1227 //printf("VarDeclaration::semantic2('%s')\n", toChars()); | |
1228 if (init && !toParent()->isFuncDeclaration()) | |
1229 { inuse++; | |
1230 #if 0 | |
1231 ExpInitializer *ei = init->isExpInitializer(); | |
1232 if (ei) | |
1233 { | |
1234 ei->exp->dump(0); | |
1235 printf("type = %p\n", ei->exp->type); | |
1236 } | |
1237 #endif | |
1238 init = init->semantic(sc, type); | |
1239 inuse--; | |
1240 } | |
1241 } | |
1242 | |
1243 void VarDeclaration::semantic3(Scope *sc) | |
1244 { | |
1245 // LDC | |
1246 if (!global.params.useAvailableExternally) | |
1247 availableExternally = false; | |
1248 | |
1249 // Preserve call chain | |
1250 Declaration::semantic3(sc); | |
1251 } | |
1252 | |
1253 const char *VarDeclaration::kind() | |
1254 { | |
1255 return "variable"; | |
1256 } | |
1257 | |
1258 Dsymbol *VarDeclaration::toAlias() | |
1259 { | |
1260 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); | |
1261 assert(this != aliassym); | |
1262 Dsymbol *s = aliassym ? aliassym->toAlias() : this; | |
1263 return s; | |
1264 } | |
1265 | |
1266 void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1267 { | |
1268 StorageClassDeclaration::stcToCBuffer(buf, storage_class); | |
1269 | |
1270 /* If changing, be sure and fix CompoundDeclarationStatement::toCBuffer() | |
1271 * too. | |
1272 */ | |
1273 if (type) | |
1274 type->toCBuffer(buf, ident, hgs); | |
1275 else | |
1276 buf->writestring(ident->toChars()); | |
1277 if (init) | |
1278 { buf->writestring(" = "); | |
1279 #if DMDV2 | |
1280 ExpInitializer *ie = init->isExpInitializer(); | |
1281 if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit)) | |
1282 ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs); | |
1283 else | |
1284 #endif | |
1285 init->toCBuffer(buf, hgs); | |
1286 } | |
1287 buf->writeByte(';'); | |
1288 buf->writenl(); | |
1289 } | |
1290 | |
1291 int VarDeclaration::needThis() | |
1292 { | |
1293 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class); | |
1294 return storage_class & STCfield; | |
1295 } | |
1296 | |
1297 int VarDeclaration::isImportedSymbol() | |
1298 { | |
1299 if (protection == PROTexport && !init && (isStatic() || isConst() || parent->isModule())) | |
1300 return TRUE; | |
1301 return FALSE; | |
1302 } | |
1303 | |
1304 void VarDeclaration::checkCtorConstInit() | |
1305 { | |
1306 if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield)) | |
1307 error("missing initializer in static constructor for const variable"); | |
1308 } | |
1309 | |
1310 /************************************ | |
1311 * Check to see if this variable is actually in an enclosing function | |
1312 * rather than the current one. | |
1313 */ | |
1314 | |
1315 void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) | |
1316 { | |
1317 //printf("VarDeclaration::checkNestedReference() %s\n", toChars()); | |
1318 if (parent && !isDataseg() && parent != sc->parent) | |
1319 { | |
1320 // The function that this variable is in | |
1321 FuncDeclaration *fdv = toParent()->isFuncDeclaration(); | |
1322 // The current function | |
1323 FuncDeclaration *fdthis = sc->parent->isFuncDeclaration(); | |
1324 | |
1325 if (fdv && fdthis) | |
1326 { | |
1327 if (loc.filename) | |
1328 fdthis->getLevel(loc, fdv); | |
1329 nestedref = 1; | |
1330 fdv->nestedFrameRef = 1; | |
1331 #if IN_LLVM | |
1332 #if DMDV1 | |
1333 fdv->nestedVars.insert(this); | |
1334 #endif | |
1335 #endif | |
1336 //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars()); | |
1337 } | |
1338 } | |
1339 } | |
1340 | |
1341 /******************************* | |
1342 * Does symbol go into data segment? | |
1343 * Includes extern variables. | |
1344 */ | |
1345 | |
1346 int VarDeclaration::isDataseg() | |
1347 { | |
1348 #if 0 | |
1349 printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars()); | |
1621
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1350 printf("%llx, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance()); |
1587 | 1351 printf("parent = '%s'\n", parent->toChars()); |
1352 #endif | |
1353 Dsymbol *parent = this->toParent(); | |
1354 if (!parent && !(storage_class & (STCstatic | STCconst))) | |
1355 { error("forward referenced"); | |
1356 type = Type::terror; | |
1357 return 0; | |
1358 } | |
1359 return (storage_class & (STCstatic | STCconst) || | |
1360 parent->isModule() || | |
1361 parent->isTemplateInstance()); | |
1362 } | |
1363 | |
1364 /************************************ | |
1365 * Does symbol go into thread local storage? | |
1366 */ | |
1367 | |
1368 int VarDeclaration::isThreadlocal() | |
1369 { | |
1370 return 0; | |
1371 } | |
1372 | |
1621
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1373 /******************************************** |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1374 * Can variable be read and written by CTFE? |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1375 */ |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1376 |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1377 int VarDeclaration::isCTFE() |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1378 { |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1379 //printf("VarDeclaration::isCTFE(%p, '%s')\n", this, toChars()); |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1380 //printf("%llx\n", storage_class); |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1381 return (storage_class & STCctfe) || !isDataseg(); |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1382 } |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1383 |
1587 | 1384 int VarDeclaration::hasPointers() |
1385 { | |
1386 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty); | |
1387 return (!isDataseg() && type->hasPointers()); | |
1388 } | |
1389 | |
1390 int VarDeclaration::isSameAsInitializer() | |
1391 { | |
1392 if (init && init->isExpInitializer() && | |
1393 init->isExpInitializer()->exp->op == TOKstructliteral) | |
1394 return 0; | |
1395 return isConst(); | |
1396 } | |
1397 | |
1398 /****************************************** | |
1399 * If a variable has an scope destructor call, return call for it. | |
1400 * Otherwise, return NULL. | |
1401 */ | |
1402 | |
1403 Expression *VarDeclaration::callScopeDtor(Scope *sc) | |
1404 { Expression *e = NULL; | |
1405 | |
1406 //printf("VarDeclaration::callScopeDtor() %s\n", toChars()); | |
1407 if (storage_class & STCscope && !noscope) | |
1408 { | |
1409 for (ClassDeclaration *cd = type->isClassHandle(); | |
1410 cd; | |
1411 cd = cd->baseClass) | |
1412 { | |
1413 /* We can do better if there's a way with onstack | |
1414 * classes to determine if there's no way the monitor | |
1415 * could be set. | |
1416 */ | |
1417 //if (cd->isInterfaceDeclaration()) | |
1418 //error("interface %s cannot be scope", cd->toChars()); | |
1419 if (1 || onstack || cd->dtors.dim) // if any destructors | |
1420 { | |
1421 // delete this; | |
1422 Expression *ec; | |
1423 | |
1424 ec = new VarExp(loc, this); | |
1425 e = new DeleteExp(loc, ec); | |
1426 e->type = Type::tvoid; | |
1427 break; | |
1428 } | |
1429 } | |
1430 } | |
1431 return e; | |
1432 } | |
1433 | |
1434 | |
1435 /********************************* ClassInfoDeclaration ****************************/ | |
1436 | |
1437 ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd) | |
1438 : VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL) | |
1439 { | |
1440 this->cd = cd; | |
1441 storage_class = STCstatic; | |
1442 } | |
1443 | |
1444 Dsymbol *ClassInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1445 { | |
1446 assert(0); // should never be produced by syntax | |
1447 return NULL; | |
1448 } | |
1449 | |
1450 void ClassInfoDeclaration::semantic(Scope *sc) | |
1451 { | |
1452 } | |
1453 | |
1454 /********************************* ModuleInfoDeclaration ****************************/ | |
1455 | |
1456 ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod) | |
1457 : VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL) | |
1458 { | |
1459 this->mod = mod; | |
1460 storage_class = STCstatic; | |
1461 } | |
1462 | |
1463 Dsymbol *ModuleInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1464 { | |
1465 assert(0); // should never be produced by syntax | |
1466 return NULL; | |
1467 } | |
1468 | |
1469 void ModuleInfoDeclaration::semantic(Scope *sc) | |
1470 { | |
1471 } | |
1472 | |
1473 /********************************* TypeInfoDeclaration ****************************/ | |
1474 | |
1475 TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal) | |
1476 : VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL) | |
1477 { | |
1478 this->tinfo = tinfo; | |
1479 storage_class = STCstatic; | |
1480 protection = PROTpublic; | |
1481 linkage = LINKc; | |
1482 } | |
1483 | |
1484 Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1485 { | |
1486 assert(0); // should never be produced by syntax | |
1487 return NULL; | |
1488 } | |
1489 | |
1490 void TypeInfoDeclaration::semantic(Scope *sc) | |
1491 { | |
1492 assert(linkage == LINKc); | |
1493 // LDC | |
1494 if (!global.params.useAvailableExternally) | |
1495 availableExternally = false; | |
1496 } | |
1497 | |
1498 /***************************** TypeInfoConstDeclaration **********************/ | |
1499 | |
1500 #if DMDV2 | |
1501 TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo) | |
1502 : TypeInfoDeclaration(tinfo, 0) | |
1503 { | |
1504 } | |
1505 #endif | |
1506 | |
1507 /***************************** TypeInfoInvariantDeclaration **********************/ | |
1508 | |
1509 #if DMDV2 | |
1510 TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo) | |
1511 : TypeInfoDeclaration(tinfo, 0) | |
1512 { | |
1513 } | |
1514 #endif | |
1515 | |
1516 /***************************** TypeInfoSharedDeclaration **********************/ | |
1517 | |
1518 #if DMDV2 | |
1519 TypeInfoSharedDeclaration::TypeInfoSharedDeclaration(Type *tinfo) | |
1520 : TypeInfoDeclaration(tinfo, 0) | |
1521 { | |
1522 } | |
1523 #endif | |
1524 | |
1525 /***************************** TypeInfoStructDeclaration **********************/ | |
1526 | |
1527 TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo) | |
1528 : TypeInfoDeclaration(tinfo, 0) | |
1529 { | |
1530 } | |
1531 | |
1532 /***************************** TypeInfoClassDeclaration ***********************/ | |
1533 | |
1534 TypeInfoClassDeclaration::TypeInfoClassDeclaration(Type *tinfo) | |
1535 : TypeInfoDeclaration(tinfo, 0) | |
1536 { | |
1537 } | |
1538 | |
1539 /***************************** TypeInfoInterfaceDeclaration *******************/ | |
1540 | |
1541 TypeInfoInterfaceDeclaration::TypeInfoInterfaceDeclaration(Type *tinfo) | |
1542 : TypeInfoDeclaration(tinfo, 0) | |
1543 { | |
1544 } | |
1545 | |
1546 /***************************** TypeInfoTypedefDeclaration *********************/ | |
1547 | |
1548 TypeInfoTypedefDeclaration::TypeInfoTypedefDeclaration(Type *tinfo) | |
1549 : TypeInfoDeclaration(tinfo, 0) | |
1550 { | |
1551 } | |
1552 | |
1553 /***************************** TypeInfoPointerDeclaration *********************/ | |
1554 | |
1555 TypeInfoPointerDeclaration::TypeInfoPointerDeclaration(Type *tinfo) | |
1556 : TypeInfoDeclaration(tinfo, 0) | |
1557 { | |
1558 } | |
1559 | |
1560 /***************************** TypeInfoArrayDeclaration ***********************/ | |
1561 | |
1562 TypeInfoArrayDeclaration::TypeInfoArrayDeclaration(Type *tinfo) | |
1563 : TypeInfoDeclaration(tinfo, 0) | |
1564 { | |
1565 } | |
1566 | |
1567 /***************************** TypeInfoStaticArrayDeclaration *****************/ | |
1568 | |
1569 TypeInfoStaticArrayDeclaration::TypeInfoStaticArrayDeclaration(Type *tinfo) | |
1570 : TypeInfoDeclaration(tinfo, 0) | |
1571 { | |
1572 } | |
1573 | |
1574 /***************************** TypeInfoAssociativeArrayDeclaration ************/ | |
1575 | |
1576 TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *tinfo) | |
1577 : TypeInfoDeclaration(tinfo, 0) | |
1578 { | |
1579 } | |
1580 | |
1581 /***************************** TypeInfoEnumDeclaration ***********************/ | |
1582 | |
1583 TypeInfoEnumDeclaration::TypeInfoEnumDeclaration(Type *tinfo) | |
1584 : TypeInfoDeclaration(tinfo, 0) | |
1585 { | |
1586 } | |
1587 | |
1588 /***************************** TypeInfoFunctionDeclaration ********************/ | |
1589 | |
1590 TypeInfoFunctionDeclaration::TypeInfoFunctionDeclaration(Type *tinfo) | |
1591 : TypeInfoDeclaration(tinfo, 0) | |
1592 { | |
1593 } | |
1594 | |
1595 /***************************** TypeInfoDelegateDeclaration ********************/ | |
1596 | |
1597 TypeInfoDelegateDeclaration::TypeInfoDelegateDeclaration(Type *tinfo) | |
1598 : TypeInfoDeclaration(tinfo, 0) | |
1599 { | |
1600 } | |
1601 | |
1602 /***************************** TypeInfoTupleDeclaration **********************/ | |
1603 | |
1604 TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo) | |
1605 : TypeInfoDeclaration(tinfo, 0) | |
1606 { | |
1607 } | |
1608 | |
1609 /********************************* ThisDeclaration ****************************/ | |
1610 | |
1611 // For the "this" parameter to member functions | |
1612 | |
1613 ThisDeclaration::ThisDeclaration(Loc loc, Type *t) | |
1614 : VarDeclaration(loc, t, Id::This, NULL) | |
1615 { | |
1616 noscope = 1; | |
1617 } | |
1618 | |
1619 Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s) | |
1620 { | |
1621 assert(0); // should never be produced by syntax | |
1622 return NULL; | |
1623 } | |
1624 | |
1625 /********************** StaticStructInitDeclaration ***************************/ | |
1626 | |
1627 StaticStructInitDeclaration::StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym) | |
1628 : Declaration(new Identifier("", TOKidentifier)) | |
1629 { | |
1630 this->loc = loc; | |
1631 this->dsym = dsym; | |
1632 storage_class |= STCconst; | |
1633 } |