root/branches/dmdfe/declaration.c

Revision 657, 29.3 kB (checked in by Gregor, 1 year ago)

MERGE: DMD 1.015

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