root/trunk/rebuild/declaration.c

Revision 921, 39.2 kB (checked in by Gregor, 3 months ago)

rebuild/*: Removed some needless error messages.

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     // error("cannot alias an expression %s", e->toChars());
472     t = e->type;
473     }
474     else if (t)
475     type = t;
476     if (overnext)
477     ScopeDsymbol::multiplyDefined(0, this, overnext);
478     this->inSemantic = 0;
479     return;
480
481   L2:
482     //printf("alias is a symbol %s %s\n", s->kind(), s->toChars());
483     type = NULL;
484     VarDeclaration *v = s->isVarDeclaration();
485     if (v && v->linkage == LINKdefault)
486     {
487     //error("forward reference of %s", v->toChars());
488     s = NULL;
489     }
490     else
491     {
492     FuncDeclaration *f = s->toAlias()->isFuncDeclaration();
493     if (f)
494     {
495         if (overnext)
496         {
497         FuncAliasDeclaration *fa = new FuncAliasDeclaration(f);
498         if (!fa->overloadInsert(overnext))
499             ScopeDsymbol::multiplyDefined(0, f, overnext);
500         overnext = NULL;
501         s = fa;
502         s->parent = sc->parent;
503         }
504     }
505     if (overnext)
506         ScopeDsymbol::multiplyDefined(0, s, overnext);
507     if (s == this)
508     {
509         assert(global.errors);
510         s = NULL;
511     }
512     }
513     aliassym = s;
514     this->inSemantic = 0;
515 }
516
517 int AliasDeclaration::overloadInsert(Dsymbol *s)
518 {
519     /* Don't know yet what the aliased symbol is, so assume it can
520      * be overloaded and check later for correctness.
521      */
522
523     //printf("AliasDeclaration::overloadInsert('%s')\n", s->toChars());
524     if (overnext == NULL)
525     {   overnext = s;
526     return TRUE;
527     }
528     else
529     {
530     return overnext->overloadInsert(s);
531     }
532 }
533
534 const char *AliasDeclaration::kind()
535 {
536     return "alias";
537 }
538
539 Type *AliasDeclaration::getType()
540 {
541     return type;
542 }
543
544 Dsymbol *AliasDeclaration::toAlias()
545 {
546     //printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : "");
547     assert(this != aliassym);
548     //static int count; if (++count == 10) *(char*)0=0;
549     if (inSemantic)
550     {   //error("recursive alias declaration");
551 //  return this;
552     }
553     Dsymbol *s = aliassym ? aliassym->toAlias() : this;
554     return s;
555 }
556
557 void AliasDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
558 {
559     buf->writestring("alias ");
560 #if 0 && _DH
561     if (hgs->hdrgen)
562     {
563     if (haliassym)
564     {
565         haliassym->toCBuffer(buf, hgs);
566         buf->writeByte(' ');
567         buf->writestring(ident->toChars());
568     }
569     else
570         htype->toCBuffer(buf, ident, hgs);
571     }
572     else
573 #endif
574     {
575     if (aliassym)
576     {
577         aliassym->toCBuffer(buf, hgs);
578         buf->writeByte(' ');
579         buf->writestring(ident->toChars());
580     }
581     else
582         type->toCBuffer(buf, ident, hgs);
583     }
584     buf->writeByte(';');
585     buf->writenl();
586 }
587
588 /********************************* VarDeclaration ****************************/
589
590 VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer *init)
591     : Declaration(id)
592 {
593     //printf("VarDeclaration('%s')\n", id->toChars());
594 #ifdef DEBUG
595     if (!type && !init)
596     {   printf("VarDeclaration('%s')\n", id->toChars());
597     //*(char*)0=0;
598     }
599 #endif
600     assert(type || init);
601     this->type = type;
602     this->init = init;
603 #ifdef _DH
604     this->htype = NULL;
605     this->hinit = NULL;
606 #endif
607     this->loc = loc;
608     offset = 0;
609     noauto = 0;
610     inuse = 0;
611     ctorinit = 0;
612     aliassym = NULL;
613     onstack = 0;
614     canassign = 0;
615     value = NULL;
616     scope = NULL;
617 }
618
619 Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)
620 {
621     //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
622
623     VarDeclaration *sv;
624     if (s)
625     {   sv = (VarDeclaration *)s;
626     }
627     else
628     {
629     Initializer *init = NULL;
630     if (this->init)
631     {   init = this->init->syntaxCopy();
632         //init->isExpInitializer()->exp->print();
633         //init->isExpInitializer()->exp->dump(0);
634     }
635
636     sv = new VarDeclaration(loc, type ? type->syntaxCopy() : NULL, ident, init);
637     sv->storage_class = storage_class;
638     }
639 #ifdef _DH
640     // Syntax copy for header file
641     if (!htype)      // Don't overwrite original
642     {   if (type)    // Make copy for both old and new instances
643     {   htype = type->syntaxCopy();
644         sv->htype = type->syntaxCopy();
645     }
646     }
647     else            // Make copy of original for new instance
648         sv->htype = htype->syntaxCopy();
649     if (!hinit)
650     {   if (init)
651     {   hinit = init->syntaxCopy();
652         sv->hinit = init->syntaxCopy();
653     }
654     }
655     else
656         sv->hinit = hinit->syntaxCopy();
657 #endif
658     return sv;
659 }
660
661 void VarDeclaration::semantic(Scope *sc)
662 {
663 #if 0
664     printf("VarDeclaration::semantic('%s', parent = '%s')\n", toChars(), sc->parent->toChars());
665     printf(" type = %s\n", type ? type->toChars() : "null");
666     printf(" stc = x%x\n", sc->stc);
667     printf(" storage_class = x%x\n", storage_class);
668     printf("linkage = %d\n", sc->linkage);
669     //if (strcmp(toChars(), "mul") == 0) halt();
670 #endif
671
672     storage_class |= sc->stc;
673     /*if (storage_class & STCextern && init)
674     error("extern symbols cannot have initializers"); */
675
676     /* If auto type inference, do the inference
677      */
678     int inferred = 0;
679     if (!type)
680     {   inuse++;
681     type = init->inferType(sc);
682     inuse--;
683     inferred = 1;
684
685     /* This is a kludge to support the existing syntax for RAII
686      * declarations.
687      */
688     storage_class &= ~STCauto;
689     originalType = type;
690     }
691     else
692     {   if (!originalType)
693         originalType = type;
694     type = type->semantic(loc, sc);
695     }
696     //printf(" semantic type = %s\n", type ? type->toChars() : "null");
697
698     type->checkDeprecated(loc, sc);
699     linkage = sc->linkage;
700     this->parent = sc->parent;
701     //printf("this = %p, parent = %p, '%s'\n", this, parent, parent->toChars());
702     protection = sc->protection;
703     //printf("sc->stc = %x\n", sc->stc);
704     //printf("storage_class = x%x\n", storage_class);
705
706     Dsymbol *parent = toParent();
707     FuncDeclaration *fd = parent->isFuncDeclaration();
708
709     Type *tb = type->toBasetype();
710     if (tb->ty == Tvoid &&