root/branches/dmdfe-2.0/declaration.c

Revision 914, 39.1 kB (checked in by Gregor, 3 months ago)

MERGE: DMD 2.019

Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2008 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
9
10 #include <stdio.h>
11 #include <assert.h>
12
13 #include "init.h"
14 #include "declaration.h"
15 #include "attrib.h"
16 #include "mtype.h"
17 #include "template.h"
18 #include "scope.h"
19 #include "aggregate.h"
20 #include "module.h"
21 #include "id.h"
22 #include "expression.h"
23 #include "hdrgen.h"
24 #include "dsymbol.h"
25
26 /********************************* Declaration ****************************/
27
28 Declaration::Declaration(Identifier *id)
29     : Dsymbol(id)
30 {
31     type = NULL;
32     originalType = NULL;
33     storage_class = STCundefined;
34     protection = PROTundefined;
35     linkage = LINKdefault;
36 }
37
38 void Declaration::semantic(Scope *sc)
39 {
40 }
41
42 const char *Declaration::kind()
43 {
44     return "declaration";
45 }
46
47 unsigned Declaration::size(Loc loc)
48 {
49     assert(type);
50     return type->size();
51 }
52
53 int Declaration::isStaticConstructor()
54 {
55     return FALSE;
56 }
57
58 int Declaration::isStaticDestructor()
59 {
60     return FALSE;
61 }
62
63 int Declaration::isDelete()
64 {
65     return FALSE;
66 }
67
68 int Declaration::isDataseg()
69 {
70     return FALSE;
71 }
72
73 int Declaration::isCodeseg()
74 {
75     return FALSE;
76 }
77
78 enum PROT Declaration::prot()
79 {
80     return protection;
81 }
82
83 /*************************************
84  * Check to see if declaration can be modified in this context (sc).
85  * Issue error if not.
86  */
87
88 #if V2
89 void Declaration::checkModify(Loc loc, Scope *sc, Type *t)
90 {
91     if (sc->incontract && isParameter())
92     error(loc, "cannot modify parameter '%s' in contract", toChars());
93
94     if (isCtorinit())
95     {   // It's only modifiable if inside the right constructor
96     Dsymbol *s = sc->func;
97     while (1)
98     {
99         FuncDeclaration *fd = NULL;
100         if (s)
101         fd = s->isFuncDeclaration();
102         if (fd &&
103         ((fd->isCtorDeclaration() && storage_class & STCfield) ||
104          (fd->isStaticCtorDeclaration() && !(storage_class & STCfield))) &&
105         fd->toParent() == toParent()
106            )
107         {
108         VarDeclaration *v = isVarDeclaration();
109         assert(v);
110         v->ctorinit = 1;
111         //printf("setting ctorinit\n");
112         }
113         else
114         {
115         if (s)
116         {   s = s->toParent2();
117             continue;
118         }
119         else
120         {
121             const char *p = isStatic() ? "static " : "";
122             error(loc, "can only initialize %sconst %s inside %sconstructor",
123             p, toChars(), p);
124         }
125         }
126         break;
127     }
128     }
129     else
130     {
131     VarDeclaration *v = isVarDeclaration();
132     if (v && v->canassign == 0)
133     {
134         const char *p = NULL;
135         if (isConst())
136         p = "const";
137         else if (isInvariant())
138         p = "invariant";
139         else if (storage_class & STCmanifest)
140         p = "manifest constant";
141         else if (!t->isAssignable())
142         p = "struct with immutable members";
143         if (p)
144         {   error(loc, "cannot modify %s", p);
145         halt();
146         }
147     }
148     }
149 }
150 #endif
151
152
153 /********************************* TupleDeclaration ****************************/
154
155 TupleDeclaration::TupleDeclaration(Loc loc, Identifier *id, Objects *objects)
156     : Declaration(id)
157 {
158     this->type = NULL;
159     this->objects = objects;
160     this->isexp = 0;
161     this->tupletype = NULL;
162 }
163
164 Dsymbol *TupleDeclaration::syntaxCopy(Dsymbol *s)
165 {
166     assert(0);
167     return NULL;
168 }
169
170 const char *TupleDeclaration::kind()
171 {
172     return "tuple";
173 }
174
175 Type *TupleDeclaration::getType()
176 {
177     /* If this tuple represents a type, return that type
178      */
179
180     //printf("TupleDeclaration::getType() %s\n", toChars());
181     if (isexp)
182     return NULL;
183     if (!tupletype)
184     {
185     /* It's only a type tuple if all the Object's are types
186      */
187     for (size_t i = 0; i < objects->dim; i++)
188     {   Object *o = (Object *)objects->data[i];
189
190         if (o->dyncast() != DYNCAST_TYPE)
191         {
192         //printf("\tnot[%d], %p, %d\n", i, o, o->dyncast());
193         return NULL;
194         }
195     }
196
197     /* We know it's a type tuple, so build the TypeTuple
198      */
199     Arguments *args = new Arguments();
200     args->setDim(objects->dim);
201     OutBuffer buf;
202     for (size_t i = 0; i < objects->dim; i++)
203     {   Type *t = (Type *)objects->data[i];
204
205         //printf("type = %s\n", t->toChars());
206 #if 0
207         buf.printf("_%s_%d", ident->toChars(), i);
208         char *name = (char *)buf.extractData();
209         Identifier *id = new Identifier(name, TOKidentifier);
210         Argument *arg = new Argument(STCin, t, id, NULL);
211 #else
212         Argument *arg = new Argument(0, t, NULL, NULL);
213 #endif
214         args->data[i] = (void *)arg;
215     }
216
217     tupletype = new TypeTuple(args);
218     }
219
220     return tupletype;
221 }
222
223 int TupleDeclaration::needThis()
224 {
225     //printf("TupleDeclaration::needThis(%s)\n", toChars());
226     for (size_t i = 0; i < objects->dim; i++)
227     {   Object *o = (Object *)objects->data[i];
228     if (o->dyncast() == DYNCAST_EXPRESSION)
229     {   Expression *e = (Expression *)o;
230         if (e->op == TOKdsymbol)
231         {   DsymbolExp *ve = (DsymbolExp *)e;
232         Declaration *d = ve->s->isDeclaration();
233         if (d && d->needThis())
234         {
235             return 1;
236         }
237         }
238     }
239     }
240     return 0;
241 }
242
243 /********************************* TypedefDeclaration ****************************/
244
245 TypedefDeclaration::TypedefDeclaration(Loc loc, Identifier *id, Type *basetype, Initializer *init)
246     : Declaration(id)
247 {
248     this->type = new TypeTypedef(this);
249     this->basetype = basetype->toBasetype();
250     this->init = init;
251 #ifdef _DH
252     this->htype = NULL;
253     this->hbasetype = NULL;
254 #endif
255     this->sem = 0;
256     this->inuse = 0;
257     this->loc = loc;
258     this->sinit = NULL;
259 }
260
261 Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s)
262 {
263     Type *basetype = this->basetype->syntaxCopy();
264
265     Initializer *init = NULL;
266     if (this->init)
267     init = this->init->syntaxCopy();
268
269     assert(!s);
270     TypedefDeclaration *st;
271     st = new TypedefDeclaration(loc, ident, basetype, init);
272 #ifdef _DH
273     // Syntax copy for header file
274     if (!htype)      // Don't overwrite original
275     {   if (type)    // Make copy for both old and new instances
276     {   htype = type->syntaxCopy();
277         st->htype = type->syntaxCopy();
278     }
279     }
280     else            // Make copy of original for new instance
281         st->htype = htype->syntaxCopy();
282     if (!hbasetype)
283     {   if (basetype)
284     {   hbasetype = basetype->syntaxCopy();
285         st->hbasetype = basetype->syntaxCopy();
286     }
287     }
288     else
289         st->hbasetype = hbasetype->syntaxCopy();
290 #endif
291     return st;
292 }
293
294 void TypedefDeclaration::semantic(Scope *sc)
295 {
296     //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem);
297     if (sem == 0)
298     {   sem = 1;
299     basetype = basetype->semantic(loc, sc);
300     sem = 2;
301     type = type->semantic(loc, sc);
302     if (sc->parent->isFuncDeclaration() && init)
303         semantic2(sc);
304     storage_class |= sc->stc & STCdeprecated;
305     }
306     else if (sem == 1)
307     {
308     error("circular definition");
309     }
310 }
311
312 void TypedefDeclaration::semantic2(Scope *sc)
313 {
314     //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem);
315     if (sem == 2)
316     {   sem = 3;
317     if (init)
318     {
319         init = init->semantic(sc, basetype);
320
321         ExpInitializer *ie = init->isExpInitializer();
322         if (ie)
323         {
324         if (ie->exp->type == basetype)
325             ie->exp->type = type;
326         }
327     }
328     }
329 }
330
331 const char *TypedefDeclaration::kind()
332 {
333     return "typedef";
334 }
335
336 Type *TypedefDeclaration::getType()
337 {
338     return type;
339 }
340
341 void TypedefDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
342 {
343     buf->writestring("typedef ");
344     basetype->toCBuffer(buf, ident, hgs);
345     if (init)
346     {
347     buf->writestring(" = ");
348     init->toCBuffer(buf, hgs);
349     }
350     buf->writeByte(';');
351     buf->writenl();
352 }
353
354 /********************************* AliasDeclaration ****************************/
355
356 AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Type *type)
357     : Declaration(id)
358 {
359     //printf("AliasDeclaration(id = '%s', type = %p)\n", id->toChars(), type);
360     //printf("type = '%s'\n", type->toChars());
361     this->loc = loc;
362     this->type = type;
363     this->aliassym = NULL;
364 #ifdef _DH
365     this->htype = NULL;
366     this->haliassym = NULL;
367 #endif
368     this->overnext = NULL;
369     this->inSemantic = 0;
370     assert(type);
371 }
372
373 AliasDeclaration::AliasDeclaration(Loc loc, Identifier *id, Dsymbol *s)
374     : Declaration(id)
375 {
376     //printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s);
377     assert(s != this);
378     this->loc = loc;
379     this->type = NULL;
380     this->aliassym = s;
381 #ifdef _DH
382     this->htype = NULL;
383     this->haliassym = NULL;
384 #endif
385     this->overnext = NULL;
386     this->inSemantic = 0;
387     assert(s);
388 }
389
390 Dsymbol *AliasDeclaration::syntaxCopy(Dsymbol *s)
391 {
392     //printf("AliasDeclaration::syntaxCopy()\n");
393     assert(!s);
394     AliasDeclaration *sa;
395     if (type)
396     sa = new AliasDeclaration(loc, ident, type->syntaxCopy());
397     else
398     sa = new AliasDeclaration(loc, ident, aliassym->syntaxCopy(NULL));
399 #ifdef _DH
400     // Syntax copy for header file
401     if (!htype)     // Don't overwrite original
402     {   if (type)   // Make copy for both old and new instances
403     {   htype = type->syntaxCopy();
404         sa->htype = type->syntaxCopy();
405     }
406     }
407     else            // Make copy of original for new instance
408     sa->htype = htype->syntaxCopy();
409     if (!haliassym)
410     {   if (aliassym)
411     {   haliassym = aliassym->syntaxCopy(s);
412         sa->haliassym = aliassym->syntaxCopy(s);
413     }
414     }
415     else
416     sa->haliassym = haliassym->syntaxCopy(s);
417 #endif
418     return sa;
419 }
420
421 void AliasDeclaration::semantic(Scope *sc)
422 {
423     //printf("AliasDeclaration::semantic() %s\n", toChars());
424     if (aliassym)
425     {
426     if (aliassym->isTemplateInstance())
427         aliassym->semantic(sc);
428     return;
429     }
430     this->inSemantic = 1;
431
432     if (storage_class & STCconst)
433     error("cannot be const");
434
435     storage_class |= sc->stc & STCdeprecated;
436
437     // Given:
438     //  alias foo.bar.abc def;
439     // it is not knowable from the syntax whether this is an alias
440     // for a type or an alias for a symbol. It is up to the semantic()
441     // pass to distinguish.
442     // If it is a type, then type is set and getType() will return that
443     // type. If it is a symbol, then aliassym is set and type is NULL -
444     // toAlias() will return aliasssym.
445
446     Dsymbol *s;
447     Type *t;
448     Expression *e;
449
450     /* This section is needed because resolve() will:
451      *   const x = 3;
452      *   alias x y;
453      * try to alias y to 3.
454      */
455     s = type->toDsymbol(sc);
456     if (s && ((s->getType() && type->equals(s->getType())) || s->isEnumMember()))
457     goto L2;            // it's a symbolic alias
458
459     //printf("alias type is %s\n", type->toChars());
460     type->resolve(loc, sc, &e, &t, &s);
461     if (s)
462     {
463     goto L2;
464     }
465     else if (e)
466     {
467     // Try to convert Expression to Dsymbol
468     s = getDsymbol(e);
469     if (s)
470         goto L2;
471
472     error("cannot alias an expression %s", e->toChars());
473     t = e->type;
474     }
475     else if (t)
476     type = t;
477     if (overnext)
478     ScopeDsymbol::multiplyDefined(0, this, overnext);
479     this->inSemantic = 0;
480     return;
481
482   L2:
483     //printf("alias is a symbol %s %s\n", s->kind(), s->toChars());
484     type = NULL;
485     VarDeclaration *v = s->isVarDeclaration();
486     if (v && v->linkage == LINKdefault)
487     {
488     error("forward reference of %s", v->toChars());
489     s = NULL;
490     }
491     else
492     {
493     FuncDeclaration *f = s->toAlias()->isFuncDeclaration();
494     if (f)
495     {
496         if (overnext)
497         {
498         FuncAliasDeclaration *fa = new FuncAliasDeclaration(f);
499         if (!fa->overloadInsert(overnext))
500             ScopeDsymbol::multiplyDefined(0, f, overnext);
501         overnext = NULL;
502         s = fa;
503         s->parent = sc->parent;
504         }
505     }
506     if (overnext)
507         ScopeDsymbol::multiplyDefined(0, s, overnext);
508     if (s == this)
509     {
510         assert(global.errors);
511         s = NULL;
512     }
513     }
514     aliassym = s;
515     this->inSemantic = 0;
516 }
517
518 int AliasDeclaration::overloadInsert(Dsymbol *s)
519 {
520     /* Don't know yet what the aliased symbol is, so assume it can
521      * be overloaded and check later for correctness.
522      */
523
524     //printf("AliasDeclaration::overloadInsert('%s')\n", s->toChars());
525     if (overnext == NULL)
526     {   overnext = s;
527     return TRUE;
528     }
529     else
530     {
531     return overnext->overloadInsert(s);
532     }
533 }
534
535 const char *AliasDeclaration::kind()
536 {
537     return "alias";
538 }
539
540 Type *AliasDeclaration::getType()
541 {
542     return type;
543 }
544
545 Dsymbol *AliasDeclaration::toAlias()
546 {
547     //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : "");
548     assert(this != aliassym);
549     //static int count; if (++count == 10) *(char*)0=0;
550     if (inSemantic)
551     {   error("recursive alias declaration");
552 //  return this;
553     }
554     Dsymbol *s = aliassym ? aliassym->toAlias() : this;
555     return s;
556 }
557
558 void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
559 {
560     buf->writestring("alias ");
561 #if 0 && _DH
562     if (hgs->hdrgen)
563     {
564     if (haliassym)
565     {
566         haliassym->toCBuffer(buf, hgs);
567         buf->writeByte(' ');
568         buf->writestring(ident->toChars());
569     }
570     else
571         htype->toCBuffer(buf, ident, hgs);
572     }
573     else
574 #endif
575     {
576     if (aliassym)
577     {
578         aliassym->toCBuffer(buf, hgs);
579         buf->writeByte(' ');
580         buf->writestring(ident->toChars());
581     }
582     else
583         type->toCBuffer(buf, ident, hgs);
584     }
585     buf->writeByte(';');
586     buf->writenl();
587 }
588
589 /********************************* VarDeclaration ****************************/
590
591 VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer *init)
592     : Declaration(id)
593 {
594     //printf("VarDeclaration('%s')\n", id->toChars());
595 #ifdef DEBUG
596     if (!type && !init)
597     {   printf("VarDeclaration('%s')\n", id->toChars());
598     //*(char*)0=0;
599     }
600 #endif
601     assert(type || init);
602     this->type = type;
603     this->init = init;
604 #ifdef _DH
605     this->htype = NULL;
606     this->hinit = NULL;
607 #endif
608     this->loc = loc;
609     offset = 0;
610     noauto = 0;
611     inuse = 0;
612     ctorinit = 0;
613     aliassym = NULL;
614     onstack = 0;
615     canassign = 0;
616     value = NULL;
617     scope = NULL;
618 }
619
620 Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
621 {
622     //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
623
624     VarDeclaration *sv;
625     if (s)
626     {   sv = (VarDeclaration *)s;
627     }
628     else
629     {
630     Initializer *init = NULL;
631     if (this->init)
632     {   init = this->init->syntaxCopy();
633         //init->isExpInitializer()->exp->print();
634         //init->isExpInitializer()->exp->dump(0);
635     }
636
637     sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init);
638     sv->storage_class = storage_class;
639     }
640 #ifdef _DH
641     // Syntax copy for header file
642     if (!htype)      // Don't overwrite original
643     {   if (type)    // Make copy for both old and new instances
644     {   htype = type->syntaxCopy();
645         sv->htype = type->syntaxCopy();
646     }
647     }
648     else            // Make copy of original for new instance
649         sv->htype = htype->syntaxCopy();
650     if (!hinit)
651     {   if (init)
652     {   hinit = init->syntaxCopy();
653         sv->hinit = init->syntaxCopy();
654     }
655     }
656     else
657         sv->hinit = hinit->syntaxCopy();
658 #endif
659     return sv;
660 }
661
662 void VarDeclaration::semantic(Scope *sc)
663 {
664 #if 0
665     printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars());
666     printf(" type = %s\n", type ? type->toChars() : "null");
667     printf(" stc = x%x\n", sc->stc);
668     printf(" storage_class = x%x\n", storage_class);
669     printf("linkage = %d\n", sc->linkage);
670     //if (strcmp(toChars(), "mul") == 0) halt();
671 #endif
672
673     storage_class |= sc->stc;
674     if (storage_class & STCextern && init)
675     error("extern symbols cannot have initializers");
676
677     /* If auto type inference, do the inference
678      */
679     int inferred = 0;
680     if (!type)
681     {   inuse++;
682     type = init->inferType(sc);
683     inuse--;
684     inferred = 1;
685
686     /* This is a kludge to support the existing syntax for RAII
687      * declarations.
688      */
689     storage_class &= ~STCauto;
690     originalType = type;
691     }
692     else
693     {   if (!originalType)
694         originalType = type;
695     type = type->semantic(loc, sc);
696     }
697     //printf(" semantic type = %s\n", type ? type->toChars() : "null");
698
699     type->checkDeprecated(loc, sc);
700     linkage = sc->linkage;
701     this->parent = sc->parent;
702     //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars());
703     protection