Mercurial > projects > ldc
annotate dmd/declaration.c @ 1650:40bd4a0d4870
Update to work with LLVM 2.7.
Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).
Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.
Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.
author | Tomas Lindquist Olsen |
---|---|
date | Wed, 19 May 2010 12:42:32 +0200 |
parents | 44b145be2ef5 |
children |
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 | |
1630
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1621
diff
changeset
|
838 #if !IN_LLVM |
1587 | 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 } | |
1630
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1621
diff
changeset
|
846 #endif |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1621
diff
changeset
|
847 |
1587 | 848 Expression *e = new DsymbolExp(loc, v); |
849 exps->data[i] = e; | |
850 } | |
851 TupleDeclaration *v2 = new TupleDeclaration(loc, ident, exps); | |
852 v2->isexp = 1; | |
853 aliassym = v2; | |
854 return; | |
855 } | |
856 | |
857 if (storage_class & STCconst && !init && !fd) | |
858 // Initialize by constructor only | |
859 storage_class = (storage_class & ~STCconst) | STCctorinit; | |
860 | |
861 if (isConst()) | |
862 { | |
863 } | |
864 else if (isStatic()) | |
865 { | |
866 } | |
867 else if (isSynchronized()) | |
868 { | |
869 error("variable %s cannot be synchronized", toChars()); | |
870 } | |
871 else if (isOverride()) | |
872 { | |
873 error("override cannot be applied to variable"); | |
874 } | |
875 else if (isAbstract()) | |
876 { | |
877 error("abstract cannot be applied to variable"); | |
878 } | |
879 else if (storage_class & STCtemplateparameter) | |
880 { | |
881 } | |
882 else | |
883 { | |
884 AggregateDeclaration *aad = sc->anonAgg; | |
885 if (!aad) | |
886 aad = parent->isAggregateDeclaration(); | |
887 if (aad) | |
888 { | |
889 #if DMDV2 | |
890 assert(!(storage_class & (STCextern | STCstatic | STCtls | STCgshared))); | |
891 | |
892 if (storage_class & (STCconst | STCimmutable) && init) | |
893 { | |
894 if (!type->toBasetype()->isTypeBasic()) | |
895 storage_class |= STCstatic; | |
896 } | |
897 else | |
898 #endif | |
899 aad->addField(sc, this); | |
900 } | |
901 | |
902 InterfaceDeclaration *id = parent->isInterfaceDeclaration(); | |
903 if (id) | |
904 { | |
905 error("field not allowed in interface"); | |
906 } | |
907 | |
908 /* Templates cannot add fields to aggregates | |
909 */ | |
910 TemplateInstance *ti = parent->isTemplateInstance(); | |
911 if (ti) | |
912 { | |
913 // Take care of nested templates | |
914 while (1) | |
915 { | |
916 TemplateInstance *ti2 = ti->tempdecl->parent->isTemplateInstance(); | |
917 if (!ti2) | |
918 break; | |
919 ti = ti2; | |
920 } | |
921 | |
922 // If it's a member template | |
923 AggregateDeclaration *ad = ti->tempdecl->isMember(); | |
924 if (ad && storage_class != STCundefined) | |
925 { | |
926 error("cannot use template to add field to aggregate '%s'", ad->toChars()); | |
927 } | |
928 } | |
929 } | |
930 | |
931 #if DMDV2 | |
932 if ((storage_class & (STCref | STCparameter | STCforeach)) == STCref && | |
933 ident != Id::This) | |
934 { | |
935 error("only parameters or foreach declarations can be ref"); | |
936 } | |
937 #endif | |
938 | |
939 if (type->isscope() && !noscope) | |
940 { | |
941 if (storage_class & (STCfield | STCout | STCref | STCstatic) || !fd) | |
942 { | |
943 error("globals, statics, fields, ref and out parameters cannot be scope"); | |
944 } | |
945 | |
946 if (!(storage_class & STCscope)) | |
947 { | |
948 if (!(storage_class & STCparameter) && ident != Id::withSym) | |
949 error("reference to scope class must be scope"); | |
950 } | |
951 } | |
952 | |
953 enum TOK op = TOKconstruct; | |
954 if (!init && !sc->inunion && !isStatic() && !isConst() && fd && | |
955 !(storage_class & (STCfield | STCin | STCforeach)) && | |
956 type->size() != 0) | |
957 { | |
958 // Provide a default initializer | |
959 //printf("Providing default initializer for '%s'\n", toChars()); | |
960 if (type->ty == Tstruct && | |
961 ((TypeStruct *)type)->sym->zeroInit == 1) | |
962 { /* If a struct is all zeros, as a special case | |
963 * set it's initializer to the integer 0. | |
964 * In AssignExp::toElem(), we check for this and issue | |
965 * a memset() to initialize the struct. | |
966 * Must do same check in interpreter. | |
967 */ | |
968 Expression *e = new IntegerExp(loc, 0, Type::tint32); | |
969 Expression *e1; | |
970 e1 = new VarExp(loc, this); | |
971 e = new AssignExp(loc, e1, e); | |
972 e->op = TOKconstruct; | |
973 e->type = e1->type; // don't type check this, it would fail | |
974 init = new ExpInitializer(loc, e); | |
975 return; | |
976 } | |
977 else if (type->ty == Ttypedef) | |
978 { TypeTypedef *td = (TypeTypedef *)type; | |
979 if (td->sym->init) | |
980 { init = td->sym->init; | |
981 ExpInitializer *ie = init->isExpInitializer(); | |
982 if (ie) | |
983 // Make copy so we can modify it | |
984 init = new ExpInitializer(ie->loc, ie->exp); | |
985 } | |
986 else | |
987 init = getExpInitializer(); | |
988 } | |
989 else | |
990 { | |
991 init = getExpInitializer(); | |
992 } | |
993 // Default initializer is always a blit | |
994 op = TOKblit; | |
995 } | |
996 | |
997 if (init) | |
998 { | |
999 sc = sc->push(); | |
1000 sc->stc &= ~(STC_TYPECTOR | STCpure | STCnothrow | STCref); | |
1001 | |
1002 ArrayInitializer *ai = init->isArrayInitializer(); | |
1003 if (ai && tb->ty == Taarray) | |
1004 { | |
1005 init = ai->toAssocArrayInitializer(); | |
1006 } | |
1007 | |
1008 StructInitializer *si = init->isStructInitializer(); | |
1009 ExpInitializer *ei = init->isExpInitializer(); | |
1010 | |
1011 // See if initializer is a NewExp that can be allocated on the stack | |
1012 if (ei && isScope() && ei->exp->op == TOKnew) | |
1013 { NewExp *ne = (NewExp *)ei->exp; | |
1014 if (!(ne->newargs && ne->newargs->dim)) | |
1015 { ne->onstack = 1; | |
1016 onstack = 1; | |
1017 if (type->isBaseOf(ne->newtype->semantic(loc, sc), NULL)) | |
1018 onstack = 2; | |
1019 } | |
1020 } | |
1021 | |
1022 // If inside function, there is no semantic3() call | |
1023 if (sc->func) | |
1024 { | |
1025 // If local variable, use AssignExp to handle all the various | |
1026 // possibilities. | |
1027 if (fd && !isStatic() && !isConst() && !init->isVoidInitializer()) | |
1028 { | |
1029 //printf("fd = '%s', var = '%s'\n", fd->toChars(), toChars()); | |
1030 if (!ei) | |
1031 { | |
1032 Expression *e = init->toExpression(); | |
1033 if (!e) | |
1034 { | |
1035 init = init->semantic(sc, type); | |
1036 e = init->toExpression(); | |
1037 if (!e) | |
1038 { error("is not a static and cannot have static initializer"); | |
1039 return; | |
1040 } | |
1041 } | |
1042 ei = new ExpInitializer(init->loc, e); | |
1043 init = ei; | |
1044 } | |
1045 | |
1046 Expression *e1 = new VarExp(loc, this); | |
1047 | |
1048 Type *t = type->toBasetype(); | |
1049 if (t->ty == Tsarray && !(storage_class & (STCref | STCout))) | |
1050 { | |
1051 ei->exp = ei->exp->semantic(sc); | |
1052 if (!ei->exp->implicitConvTo(type)) | |
1053 { | |
1054 int dim = ((TypeSArray *)t)->dim->toInteger(); | |
1055 // If multidimensional static array, treat as one large array | |
1056 while (1) | |
1057 { | |
1058 t = t->nextOf()->toBasetype(); | |
1059 if (t->ty != Tsarray) | |
1060 break; | |
1061 dim *= ((TypeSArray *)t)->dim->toInteger(); | |
1062 e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex)); | |
1063 } | |
1064 } | |
1065 e1 = new SliceExp(loc, e1, NULL, NULL); | |
1066 } | |
1067 else if (t->ty == Tstruct) | |
1068 { | |
1069 ei->exp = ei->exp->semantic(sc); | |
1070 ei->exp = resolveProperties(sc, ei->exp); | |
1071 StructDeclaration *sd = ((TypeStruct *)t)->sym; | |
1072 #if DMDV2 | |
1073 /* Look to see if initializer is a call to the constructor | |
1074 */ | |
1075 if (sd->ctor && // there are constructors | |
1076 ei->exp->type->ty == Tstruct && // rvalue is the same struct | |
1077 ((TypeStruct *)ei->exp->type)->sym == sd && | |
1078 ei->exp->op == TOKstar) | |
1079 { | |
1080 /* Look for form of constructor call which is: | |
1081 * *__ctmp.ctor(arguments...) | |
1082 */ | |
1083 PtrExp *pe = (PtrExp *)ei->exp; | |
1084 if (pe->e1->op == TOKcall) | |
1085 { CallExp *ce = (CallExp *)pe->e1; | |
1086 if (ce->e1->op == TOKdotvar) | |
1087 { DotVarExp *dve = (DotVarExp *)ce->e1; | |
1088 if (dve->var->isCtorDeclaration()) | |
1089 { /* It's a constructor call, currently constructing | |
1090 * a temporary __ctmp. | |
1091 */ | |
1092 /* Before calling the constructor, initialize | |
1093 * variable with a bit copy of the default | |
1094 * initializer | |
1095 */ | |
1096 Expression *e = new AssignExp(loc, new VarExp(loc, this), t->defaultInit(loc)); | |
1097 e->op = TOKblit; | |
1098 e->type = t; | |
1099 ei->exp = new CommaExp(loc, e, ei->exp); | |
1100 | |
1101 /* Replace __ctmp being constructed with e1 | |
1102 */ | |
1103 dve->e1 = e1; | |
1104 return; | |
1105 } | |
1106 } | |
1107 } | |
1108 } | |
1109 #endif | |
1110 if (!ei->exp->implicitConvTo(type)) | |
1111 { | |
1112 /* Look for opCall | |
1113 * See bugzilla 2702 for more discussion | |
1114 */ | |
1115 Type *ti = ei->exp->type->toBasetype(); | |
1116 // Don't cast away invariant or mutability in initializer | |
1117 if (search_function(sd, Id::call) && | |
1118 /* Initializing with the same type is done differently | |
1119 */ | |
1120 !(ti->ty == Tstruct && t->toDsymbol(sc) == ti->toDsymbol(sc))) | |
1121 { // Rewrite as e1.call(arguments) | |
1122 Expression * eCall = new DotIdExp(loc, e1, Id::call); | |
1123 ei->exp = new CallExp(loc, eCall, ei->exp); | |
1124 } | |
1125 } | |
1126 } | |
1127 ei->exp = new AssignExp(loc, e1, ei->exp); | |
1128 ei->exp->op = TOKconstruct; | |
1129 canassign++; | |
1130 ei->exp = ei->exp->semantic(sc); | |
1131 canassign--; | |
1132 ei->exp->optimize(WANTvalue); | |
1133 } | |
1134 else | |
1135 { | |
1136 init = init->semantic(sc, type); | |
1137 if (fd && isConst() && !isStatic()) | |
1138 { // Make it static | |
1139 storage_class |= STCstatic; | |
1140 } | |
1141 } | |
1142 } | |
1143 else if (isConst() || isFinal() || | |
1144 parent->isAggregateDeclaration()) | |
1145 { | |
1146 /* Because we may need the results of a const declaration in a | |
1147 * subsequent type, such as an array dimension, before semantic2() | |
1148 * gets ordinarily run, try to run semantic2() now. | |
1149 * Ignore failure. | |
1150 */ | |
1151 | |
1152 if (!global.errors && !inferred) | |
1153 { | |
1154 unsigned errors = global.errors; | |
1155 global.gag++; | |
1156 //printf("+gag\n"); | |
1157 Expression *e; | |
1158 Initializer *i2 = init; | |
1159 inuse++; | |
1160 if (ei) | |
1161 { | |
1162 e = ei->exp->syntaxCopy(); | |
1163 e = e->semantic(sc); | |
1164 e = e->implicitCastTo(sc, type); | |
1165 } | |
1166 else if (si || ai) | |
1167 { i2 = init->syntaxCopy(); | |
1168 i2 = i2->semantic(sc, type); | |
1169 } | |
1170 inuse--; | |
1171 global.gag--; | |
1172 //printf("-gag\n"); | |
1173 if (errors != global.errors) // if errors happened | |
1174 { | |
1175 if (global.gag == 0) | |
1176 global.errors = errors; // act as if nothing happened | |
1177 #if DMDV2 | |
1178 /* Save scope for later use, to try again | |
1179 */ | |
1180 scope = new Scope(*sc); | |
1181 scope->setNoFree(); | |
1182 #endif | |
1183 } | |
1184 else if (ei) | |
1185 { | |
1186 e = e->optimize(WANTvalue | WANTinterpret); | |
1187 if (e->op == TOKint64 || e->op == TOKstring || e->op == TOKfloat64) | |
1188 { | |
1189 ei->exp = e; // no errors, keep result | |
1190 } | |
1191 #if DMDV2 | |
1192 else | |
1193 { | |
1194 /* Save scope for later use, to try again | |
1195 */ | |
1196 scope = new Scope(*sc); | |
1197 scope->setNoFree(); | |
1198 } | |
1199 #endif | |
1200 } | |
1201 else | |
1202 init = i2; // no errors, keep result | |
1203 } | |
1204 } | |
1205 sc = sc->pop(); | |
1206 } | |
1207 } | |
1208 | |
1209 ExpInitializer *VarDeclaration::getExpInitializer() | |
1210 { | |
1211 ExpInitializer *ei; | |
1212 | |
1213 if (init) | |
1214 ei = init->isExpInitializer(); | |
1215 else | |
1216 { | |
1217 Expression *e = type->defaultInit(loc); | |
1218 if (e) | |
1219 ei = new ExpInitializer(loc, e); | |
1220 else | |
1221 ei = NULL; | |
1222 } | |
1223 return ei; | |
1224 } | |
1225 | |
1226 void VarDeclaration::semantic2(Scope *sc) | |
1227 { | |
1228 //printf("VarDeclaration::semantic2('%s')\n", toChars()); | |
1229 if (init && !toParent()->isFuncDeclaration()) | |
1230 { inuse++; | |
1231 #if 0 | |
1232 ExpInitializer *ei = init->isExpInitializer(); | |
1233 if (ei) | |
1234 { | |
1235 ei->exp->dump(0); | |
1236 printf("type = %p\n", ei->exp->type); | |
1237 } | |
1238 #endif | |
1239 init = init->semantic(sc, type); | |
1240 inuse--; | |
1241 } | |
1242 } | |
1243 | |
1244 void VarDeclaration::semantic3(Scope *sc) | |
1245 { | |
1246 // LDC | |
1247 if (!global.params.useAvailableExternally) | |
1248 availableExternally = false; | |
1249 | |
1250 // Preserve call chain | |
1251 Declaration::semantic3(sc); | |
1252 } | |
1253 | |
1254 const char *VarDeclaration::kind() | |
1255 { | |
1256 return "variable"; | |
1257 } | |
1258 | |
1259 Dsymbol *VarDeclaration::toAlias() | |
1260 { | |
1261 //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym); | |
1262 assert(this != aliassym); | |
1263 Dsymbol *s = aliassym ? aliassym->toAlias() : this; | |
1264 return s; | |
1265 } | |
1266 | |
1267 void VarDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1268 { | |
1269 StorageClassDeclaration::stcToCBuffer(buf, storage_class); | |
1270 | |
1271 /* If changing, be sure and fix CompoundDeclarationStatement::toCBuffer() | |
1272 * too. | |
1273 */ | |
1274 if (type) | |
1275 type->toCBuffer(buf, ident, hgs); | |
1276 else | |
1277 buf->writestring(ident->toChars()); | |
1278 if (init) | |
1279 { buf->writestring(" = "); | |
1280 #if DMDV2 | |
1281 ExpInitializer *ie = init->isExpInitializer(); | |
1282 if (ie && (ie->exp->op == TOKconstruct || ie->exp->op == TOKblit)) | |
1283 ((AssignExp *)ie->exp)->e2->toCBuffer(buf, hgs); | |
1284 else | |
1285 #endif | |
1286 init->toCBuffer(buf, hgs); | |
1287 } | |
1288 buf->writeByte(';'); | |
1289 buf->writenl(); | |
1290 } | |
1291 | |
1292 int VarDeclaration::needThis() | |
1293 { | |
1294 //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class); | |
1295 return storage_class & STCfield; | |
1296 } | |
1297 | |
1298 int VarDeclaration::isImportedSymbol() | |
1299 { | |
1300 if (protection == PROTexport && !init && (isStatic() || isConst() || parent->isModule())) | |
1301 return TRUE; | |
1302 return FALSE; | |
1303 } | |
1304 | |
1305 void VarDeclaration::checkCtorConstInit() | |
1306 { | |
1307 if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield)) | |
1308 error("missing initializer in static constructor for const variable"); | |
1309 } | |
1310 | |
1311 /************************************ | |
1312 * Check to see if this variable is actually in an enclosing function | |
1313 * rather than the current one. | |
1314 */ | |
1315 | |
1316 void VarDeclaration::checkNestedReference(Scope *sc, Loc loc) | |
1317 { | |
1318 //printf("VarDeclaration::checkNestedReference() %s\n", toChars()); | |
1319 if (parent && !isDataseg() && parent != sc->parent) | |
1320 { | |
1321 // The function that this variable is in | |
1322 FuncDeclaration *fdv = toParent()->isFuncDeclaration(); | |
1323 // The current function | |
1324 FuncDeclaration *fdthis = sc->parent->isFuncDeclaration(); | |
1325 | |
1326 if (fdv && fdthis) | |
1327 { | |
1328 if (loc.filename) | |
1329 fdthis->getLevel(loc, fdv); | |
1330 nestedref = 1; | |
1331 fdv->nestedFrameRef = 1; | |
1332 #if IN_LLVM | |
1333 #if DMDV1 | |
1334 fdv->nestedVars.insert(this); | |
1335 #endif | |
1336 #endif | |
1337 //printf("var %s in function %s is nested ref\n", toChars(), fdv->toChars()); | |
1338 } | |
1339 } | |
1340 } | |
1341 | |
1342 /******************************* | |
1343 * Does symbol go into data segment? | |
1344 * Includes extern variables. | |
1345 */ | |
1346 | |
1347 int VarDeclaration::isDataseg() | |
1348 { | |
1349 #if 0 | |
1350 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
|
1351 printf("%llx, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance()); |
1587 | 1352 printf("parent = '%s'\n", parent->toChars()); |
1353 #endif | |
1354 Dsymbol *parent = this->toParent(); | |
1355 if (!parent && !(storage_class & (STCstatic | STCconst))) | |
1356 { error("forward referenced"); | |
1357 type = Type::terror; | |
1358 return 0; | |
1359 } | |
1360 return (storage_class & (STCstatic | STCconst) || | |
1361 parent->isModule() || | |
1362 parent->isTemplateInstance()); | |
1363 } | |
1364 | |
1365 /************************************ | |
1366 * Does symbol go into thread local storage? | |
1367 */ | |
1368 | |
1369 int VarDeclaration::isThreadlocal() | |
1370 { | |
1371 return 0; | |
1372 } | |
1373 | |
1621
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1374 /******************************************** |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1375 * 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
|
1376 */ |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1377 |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1378 int VarDeclaration::isCTFE() |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1379 { |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1380 //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
|
1381 //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
|
1382 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
|
1383 } |
fb2e6707ad17
Merge DMD r314+r315: bugzilla 2029 Typesafe variadic functions don't...
Leandro Lucarella <llucax@gmail.com>
parents:
1619
diff
changeset
|
1384 |
1587 | 1385 int VarDeclaration::hasPointers() |
1386 { | |
1387 //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty); | |
1388 return (!isDataseg() && type->hasPointers()); | |
1389 } | |
1390 | |
1391 int VarDeclaration::isSameAsInitializer() | |
1392 { | |
1393 if (init && init->isExpInitializer() && | |
1394 init->isExpInitializer()->exp->op == TOKstructliteral) | |
1395 return 0; | |
1396 return isConst(); | |
1397 } | |
1398 | |
1399 /****************************************** | |
1400 * If a variable has an scope destructor call, return call for it. | |
1401 * Otherwise, return NULL. | |
1402 */ | |
1403 | |
1404 Expression *VarDeclaration::callScopeDtor(Scope *sc) | |
1405 { Expression *e = NULL; | |
1406 | |
1407 //printf("VarDeclaration::callScopeDtor() %s\n", toChars()); | |
1408 if (storage_class & STCscope && !noscope) | |
1409 { | |
1410 for (ClassDeclaration *cd = type->isClassHandle(); | |
1411 cd; | |
1412 cd = cd->baseClass) | |
1413 { | |
1414 /* We can do better if there's a way with onstack | |
1415 * classes to determine if there's no way the monitor | |
1416 * could be set. | |
1417 */ | |
1418 //if (cd->isInterfaceDeclaration()) | |
1419 //error("interface %s cannot be scope", cd->toChars()); | |
1420 if (1 || onstack || cd->dtors.dim) // if any destructors | |
1421 { | |
1422 // delete this; | |
1423 Expression *ec; | |
1424 | |
1425 ec = new VarExp(loc, this); | |
1426 e = new DeleteExp(loc, ec); | |
1427 e->type = Type::tvoid; | |
1428 break; | |
1429 } | |
1430 } | |
1431 } | |
1432 return e; | |
1433 } | |
1434 | |
1435 | |
1436 /********************************* ClassInfoDeclaration ****************************/ | |
1437 | |
1438 ClassInfoDeclaration::ClassInfoDeclaration(ClassDeclaration *cd) | |
1439 : VarDeclaration(0, ClassDeclaration::classinfo->type, cd->ident, NULL) | |
1440 { | |
1441 this->cd = cd; | |
1442 storage_class = STCstatic; | |
1443 } | |
1444 | |
1445 Dsymbol *ClassInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1446 { | |
1447 assert(0); // should never be produced by syntax | |
1448 return NULL; | |
1449 } | |
1450 | |
1451 void ClassInfoDeclaration::semantic(Scope *sc) | |
1452 { | |
1453 } | |
1454 | |
1455 /********************************* ModuleInfoDeclaration ****************************/ | |
1456 | |
1457 ModuleInfoDeclaration::ModuleInfoDeclaration(Module *mod) | |
1458 : VarDeclaration(0, Module::moduleinfo->type, mod->ident, NULL) | |
1459 { | |
1460 this->mod = mod; | |
1461 storage_class = STCstatic; | |
1462 } | |
1463 | |
1464 Dsymbol *ModuleInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1465 { | |
1466 assert(0); // should never be produced by syntax | |
1467 return NULL; | |
1468 } | |
1469 | |
1470 void ModuleInfoDeclaration::semantic(Scope *sc) | |
1471 { | |
1472 } | |
1473 | |
1474 /********************************* TypeInfoDeclaration ****************************/ | |
1475 | |
1476 TypeInfoDeclaration::TypeInfoDeclaration(Type *tinfo, int internal) | |
1477 : VarDeclaration(0, Type::typeinfo->type, tinfo->getTypeInfoIdent(internal), NULL) | |
1478 { | |
1479 this->tinfo = tinfo; | |
1480 storage_class = STCstatic; | |
1481 protection = PROTpublic; | |
1482 linkage = LINKc; | |
1483 } | |
1484 | |
1485 Dsymbol *TypeInfoDeclaration::syntaxCopy(Dsymbol *s) | |
1486 { | |
1487 assert(0); // should never be produced by syntax | |
1488 return NULL; | |
1489 } | |
1490 | |
1491 void TypeInfoDeclaration::semantic(Scope *sc) | |
1492 { | |
1493 assert(linkage == LINKc); | |
1630
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1621
diff
changeset
|
1494 #if IN_LLVM |
1587 | 1495 if (!global.params.useAvailableExternally) |
1496 availableExternally = false; | |
1630
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1621
diff
changeset
|
1497 #endif |
1587 | 1498 } |
1499 | |
1500 /***************************** TypeInfoConstDeclaration **********************/ | |
1501 | |
1502 #if DMDV2 | |
1503 TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo) | |
1504 : TypeInfoDeclaration(tinfo, 0) | |
1505 { | |
1506 } | |
1507 #endif | |
1508 | |
1509 /***************************** TypeInfoInvariantDeclaration **********************/ | |
1510 | |
1511 #if DMDV2 | |
1512 TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo) | |
1513 : TypeInfoDeclaration(tinfo, 0) | |
1514 { | |
1515 } | |
1516 #endif | |
1517 | |
1518 /***************************** TypeInfoSharedDeclaration **********************/ | |
1519 | |
1520 #if DMDV2 | |
1521 TypeInfoSharedDeclaration::TypeInfoSharedDeclaration(Type *tinfo) | |
1522 : TypeInfoDeclaration(tinfo, 0) | |
1523 { | |
1524 } | |
1525 #endif | |
1526 | |
1527 /***************************** TypeInfoStructDeclaration **********************/ | |
1528 | |
1529 TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo) | |
1530 : TypeInfoDeclaration(tinfo, 0) | |
1531 { | |
1532 } | |
1533 | |
1534 /***************************** TypeInfoClassDeclaration ***********************/ | |
1535 | |
1536 TypeInfoClassDeclaration::TypeInfoClassDeclaration(Type *tinfo) | |
1537 : TypeInfoDeclaration(tinfo, 0) | |
1538 { | |
1539 } | |
1540 | |
1541 /***************************** TypeInfoInterfaceDeclaration *******************/ | |
1542 | |
1543 TypeInfoInterfaceDeclaration::TypeInfoInterfaceDeclaration(Type *tinfo) | |
1544 : TypeInfoDeclaration(tinfo, 0) | |
1545 { | |
1546 } | |
1547 | |
1548 /***************************** TypeInfoTypedefDeclaration *********************/ | |
1549 | |
1550 TypeInfoTypedefDeclaration::TypeInfoTypedefDeclaration(Type *tinfo) | |
1551 : TypeInfoDeclaration(tinfo, 0) | |
1552 { | |
1553 } | |
1554 | |
1555 /***************************** TypeInfoPointerDeclaration *********************/ | |
1556 | |
1557 TypeInfoPointerDeclaration::TypeInfoPointerDeclaration(Type *tinfo) | |
1558 : TypeInfoDeclaration(tinfo, 0) | |
1559 { | |
1560 } | |
1561 | |
1562 /***************************** TypeInfoArrayDeclaration ***********************/ | |
1563 | |
1564 TypeInfoArrayDeclaration::TypeInfoArrayDeclaration(Type *tinfo) | |
1565 : TypeInfoDeclaration(tinfo, 0) | |
1566 { | |
1567 } | |
1568 | |
1569 /***************************** TypeInfoStaticArrayDeclaration *****************/ | |
1570 | |
1571 TypeInfoStaticArrayDeclaration::TypeInfoStaticArrayDeclaration(Type *tinfo) | |
1572 : TypeInfoDeclaration(tinfo, 0) | |
1573 { | |
1574 } | |
1575 | |
1576 /***************************** TypeInfoAssociativeArrayDeclaration ************/ | |
1577 | |
1578 TypeInfoAssociativeArrayDeclaration::TypeInfoAssociativeArrayDeclaration(Type *tinfo) | |
1579 : TypeInfoDeclaration(tinfo, 0) | |
1580 { | |
1581 } | |
1582 | |
1583 /***************************** TypeInfoEnumDeclaration ***********************/ | |
1584 | |
1585 TypeInfoEnumDeclaration::TypeInfoEnumDeclaration(Type *tinfo) | |
1586 : TypeInfoDeclaration(tinfo, 0) | |
1587 { | |
1588 } | |
1589 | |
1590 /***************************** TypeInfoFunctionDeclaration ********************/ | |
1591 | |
1592 TypeInfoFunctionDeclaration::TypeInfoFunctionDeclaration(Type *tinfo) | |
1593 : TypeInfoDeclaration(tinfo, 0) | |
1594 { | |
1595 } | |
1596 | |
1597 /***************************** TypeInfoDelegateDeclaration ********************/ | |
1598 | |
1599 TypeInfoDelegateDeclaration::TypeInfoDelegateDeclaration(Type *tinfo) | |
1600 : TypeInfoDeclaration(tinfo, 0) | |
1601 { | |
1602 } | |
1603 | |
1604 /***************************** TypeInfoTupleDeclaration **********************/ | |
1605 | |
1606 TypeInfoTupleDeclaration::TypeInfoTupleDeclaration(Type *tinfo) | |
1607 : TypeInfoDeclaration(tinfo, 0) | |
1608 { | |
1609 } | |
1610 | |
1611 /********************************* ThisDeclaration ****************************/ | |
1612 | |
1613 // For the "this" parameter to member functions | |
1614 | |
1615 ThisDeclaration::ThisDeclaration(Loc loc, Type *t) | |
1616 : VarDeclaration(loc, t, Id::This, NULL) | |
1617 { | |
1618 noscope = 1; | |
1619 } | |
1620 | |
1621 Dsymbol *ThisDeclaration::syntaxCopy(Dsymbol *s) | |
1622 { | |
1623 assert(0); // should never be produced by syntax | |
1624 return NULL; | |
1625 } | |
1626 | |
1627 /********************** StaticStructInitDeclaration ***************************/ | |
1628 | |
1629 StaticStructInitDeclaration::StaticStructInitDeclaration(Loc loc, StructDeclaration *dsym) | |
1630 : Declaration(new Identifier("", TOKidentifier)) | |
1631 { | |
1632 this->loc = loc; | |
1633 this->dsym = dsym; | |
1634 storage_class |= STCconst; | |
1635 } |