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