root/branches/dmdfe-2.0/attrib.c

Revision 914, 24.8 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 <stdlib.h>
12 #include <assert.h>
13
14 #if _WIN32 || IN_GCC || IN_DMDFE
15 #include "mem.h"
16 #elif linux
17 #include "../root/mem.h"
18 #endif
19
20 #include "init.h"
21 #include "declaration.h"
22 #include "attrib.h"
23 #include "cond.h"
24 #include "scope.h"
25 #include "id.h"
26 #include "expression.h"
27 #include "dsymbol.h"
28 #include "aggregate.h"
29 #include "module.h"
30 #include "parse.h"
31 #include "template.h"
32
33 extern void obj_includelib(const char *name);
34 void obj_startaddress(Symbol *s);
35
36
37 /********************************* AttribDeclaration ****************************/
38
39 AttribDeclaration::AttribDeclaration(Array *decl)
40     : Dsymbol()
41 {
42     this->decl = decl;
43 }
44
45 Array *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd)
46 {
47     return decl;
48 }
49
50 int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
51 {
52     int m = 0;
53     Array *d = include(sc, sd);
54
55     if (d)
56     {
57     for (unsigned i = 0; i < d->dim; i++)
58     {   Dsymbol *s = (Dsymbol *)d->data[i];
59         m |= s->addMember(sc, sd, m | memnum);
60     }
61     }
62     return m;
63 }
64
65 void AttribDeclaration::semantic(Scope *sc)
66 {
67     Array *d = include(sc, NULL);
68
69     //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d);
70     if (d)
71     {
72     for (unsigned i = 0; i < d->dim; i++)
73     {
74         Dsymbol *s = (Dsymbol *)d->data[i];
75
76         s->semantic(sc);
77     }
78     }
79 }
80
81 void AttribDeclaration::semantic2(Scope *sc)
82 {
83     Array *d = include(sc, NULL);
84
85     if (d)
86     {
87     for (unsigned i = 0; i < d->dim; i++)
88     {   Dsymbol *s = (Dsymbol *)d->data[i];
89         s->semantic2(sc);
90     }
91     }
92 }
93
94 void AttribDeclaration::semantic3(Scope *sc)
95 {
96     Array *d = include(sc, NULL);
97
98     if (d)
99     {
100     for (unsigned i = 0; i < d->dim; i++)
101     {   Dsymbol *s = (Dsymbol *)d->data[i];
102         s->semantic3(sc);
103     }
104     }
105 }
106
107 void AttribDeclaration::inlineScan()
108 {
109     Array *d = include(NULL, NULL);
110
111     if (d)
112     {
113     for (unsigned i = 0; i < d->dim; i++)
114     {   Dsymbol *s = (Dsymbol *)d->data[i];
115         //printf("AttribDeclaration::inlineScan %s\n", s->toChars());
116         s->inlineScan();
117     }
118     }
119 }
120
121 void AttribDeclaration::addComment(unsigned char *comment)
122 {
123     if (comment)
124     {
125     Array *d = include(NULL, NULL);
126
127     if (d)
128     {
129         for (unsigned i = 0; i < d->dim; i++)
130         {   Dsymbol *s = (Dsymbol *)d->data[i];
131         //printf("AttribDeclaration::addComment %s\n", s->toChars());
132         s->addComment(comment);
133         }
134     }
135     }
136 }
137
138 void AttribDeclaration::emitComment(Scope *sc)
139 {
140     //printf("AttribDeclaration::emitComment(sc = %p)\n", sc);
141
142     /* If generating doc comment, skip this because if we're inside
143      * a template, then include(NULL, NULL) will fail.
144      */
145 //    if (sc->docbuf)
146 //  return;
147
148     Array *d = include(NULL, NULL);
149
150     if (d)
151     {
152     for (unsigned i = 0; i < d->dim; i++)
153     {   Dsymbol *s = (Dsymbol *)d->data[i];
154         //printf("AttribDeclaration::emitComment %s\n", s->toChars());
155         s->emitComment(sc);
156     }
157     }
158 }
159
160 int AttribDeclaration::hasPointers()
161 {
162     Array *d = include(NULL, NULL);
163
164     if (d)
165     {
166     for (size_t i = 0; i < d->dim; i++)
167     {
168         Dsymbol *s = (Dsymbol *)d->data[i];
169         if (s->hasPointers())
170         return 1;
171     }
172     }
173     return 0;
174 }
175
176 const char *AttribDeclaration::kind()
177 {
178     return "attribute";
179 }
180
181 int AttribDeclaration::oneMember(Dsymbol **ps)
182 {
183     Array *d = include(NULL, NULL);
184
185     return Dsymbol::oneMembers(d, ps);
186 }
187
188 void AttribDeclaration::checkCtorConstInit()
189 {
190     Array *d = include(NULL, NULL);
191
192     if (d)
193     {
194     for (unsigned i = 0; i < d->dim; i++)
195     {   Dsymbol *s = (Dsymbol *)d->data[i];
196         s->checkCtorConstInit();
197     }
198     }
199 }
200
201 /****************************************
202  */
203
204 void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses)
205 {
206     Array *d = include(NULL, NULL);
207
208     if (d)
209     {
210     for (unsigned i = 0; i < d->dim; i++)
211     {   Dsymbol *s = (Dsymbol *)d->data[i];
212         s->addLocalClass(aclasses);
213     }
214     }
215 }
216
217
218 void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
219 {
220     if (decl)
221     {
222     buf->writenl();
223     buf->writeByte('{');
224     buf->writenl();
225     for (unsigned i = 0; i < decl->dim; i++)
226     {
227         Dsymbol *s = (Dsymbol *)decl->data[i];
228
229         buf->writestring("    ");
230         s->toCBuffer(buf, hgs);
231     }
232     buf->writeByte('}');
233     }
234     else
235     buf->writeByte(';');
236     buf->writenl();
237 }
238
239 /************************* StorageClassDeclaration ****************************/
240
241 StorageClassDeclaration::StorageClassDeclaration(unsigned stc, Array *decl)
242     : AttribDeclaration(decl)
243 {
244     this->stc = stc;
245 }
246
247 Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
248 {
249     StorageClassDeclaration *scd;
250
251     assert(!s);
252     scd = new StorageClassDeclaration(stc, Dsymbol::arraySyntaxCopy(decl));
253     return scd;
254 }
255
256 void StorageClassDeclaration::semantic(Scope *sc)
257 {
258     if (decl)
259     {   unsigned stc_save = sc->stc;
260
261     /* These sets of storage classes are mutually exclusive,
262      * so choose the innermost or most recent one.
263      */
264     if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
265         sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
266     if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest))
267         sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest);
268     if (stc & (STCconst | STCinvariant | STCmanifest))
269         sc->stc &= ~(STCconst | STCinvariant | STCmanifest);
270     sc->stc |= stc;
271     for (unsigned i = 0; i < decl->dim; i++)
272     {
273         Dsymbol *s = (Dsymbol *)decl->data[i];
274
275         s->semantic(sc);
276     }
277     sc->stc = stc_save;
278     }
279     else
280     sc->stc = stc;
281 }
282
283 void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
284 {
285     struct SCstring
286     {
287     int stc;
288     enum TOK tok;
289     };
290
291     static SCstring table[] =
292     {
293     { STCauto,         TOKauto },
294     { STCscope,        TOKscope },
295     { STCstatic,       TOKstatic },
296     { STCextern,       TOKextern },
297     { STCconst,        TOKconst },
298     { STCinvariant,    TOKinvariant },
299     { STCfinal,        TOKfinal },
300     { STCabstract,     TOKabstract },
301     { STCsynchronized, TOKsynchronized },
302     { STCdeprecated,   TOKdeprecated },
303     { STCoverride,     TOKoverride },
304     { STCnothrow,      TOKnothrow },
305     { STCpure,         TOKpure },
306     { STCtls,          TOKtls },
307     };
308
309     int written = 0;
310     for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
311     {
312     if (stc & table[i].stc)
313     {
314         if (written)
315         buf->writeByte(' ');
316         written = 1;
317         buf->writestring(Token::toChars(table[i].tok));
318     }
319     }
320
321     AttribDeclaration::toCBuffer(buf, hgs);
322 }
323
324 /********************************* LinkDeclaration ****************************/
325
326 LinkDeclaration::LinkDeclaration(enum LINK p, Array *decl)
327     : AttribDeclaration(decl)
328 {
329     //printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl);
330     linkage = p;
331 }
332
333 Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s)
334 {
335     LinkDeclaration *ld;
336
337     assert(!s);
338     ld = new LinkDeclaration(linkage, Dsymbol::arraySyntaxCopy(decl));
339     return ld;
340 }
341
342 void LinkDeclaration::semantic(Scope *sc)
343 {
344     //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl);
345     if (decl)
346     {   enum LINK linkage_save = sc->linkage;
347
348     sc->linkage = linkage;
349     for (unsigned i = 0; i < decl->dim; i++)
350     {
351         Dsymbol *s = (Dsymbol *)decl->data[i];
352
353         s->semantic(sc);
354     }
355     sc->linkage = linkage_save;
356     }
357     else
358     {
359     sc->linkage = linkage;
360     }
361 }
362
363 void LinkDeclaration::semantic3(Scope *sc)
364 {
365     //printf("LinkDeclaration::semantic3(linkage = %d, decl = %p)\n", linkage, decl);
366     if (decl)
367     {   enum LINK linkage_save = sc->linkage;
368
369     sc->linkage = linkage;
370     for (unsigned i = 0; i < decl->dim; i++)
371     {
372         Dsymbol *s = (Dsymbol *)decl->data[i];
373
374         s->semantic3(sc);
375     }
376     sc->linkage = linkage_save;
377     }
378     else
379     {
380     sc->linkage = linkage;
381     }
382 }
383
384 void LinkDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
385 {   const char *p;
386
387     switch (linkage)
388     {
389     case LINKd:     p = "D";        break;
390     case LINKc:     p = "C";        break;
391     case LINKcpp:       p = "C++";      break;
392     case LINKwindows:   p = "Windows";      break;
393     case LINKpascal:    p = "Pascal";       break;
394     default:
395         assert(0);
396         break;
397     }
398     buf->writestring("extern (");
399     buf->writestring(p);
400     buf->writestring(") ");
401     AttribDeclaration::toCBuffer(buf, hgs);
402 }
403
404 char *LinkDeclaration::toChars()
405 {
406     return (char *)"extern ()";
407 }
408
409 /********************************* ProtDeclaration ****************************/
410
411 ProtDeclaration::ProtDeclaration(enum PROT p, Array *decl)
412     : AttribDeclaration(decl)
413 {
414     protection = p;
415     //printf("decl = %p\n", decl);
416 }
417
418 Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s)
419 {
420     ProtDeclaration *pd;
421
422     assert(!s);
423     pd = new ProtDeclaration(protection, Dsymbol::arraySyntaxCopy(decl));
424     return pd;
425 }
426
427 void ProtDeclaration::semantic(Scope *sc)
428 {
429     if (decl)
430     {   enum PROT protection_save = sc->protection;
431     int explicitProtection_save = sc->explicitProtection;
432
433     sc->protection = protection;
434     sc->explicitProtection = 1;
435     for (unsigned i = 0; i < decl->dim; i++)
436     {
437         Dsymbol *s = (Dsymbol *)decl->data[i];
438
439         s->semantic(sc);
440     }
441     sc->protection = protection_save;
442     sc->explicitProtection = explicitProtection_save;
443     }
444     else
445     {   sc->protection = protection;
446     sc->explicitProtection = 1;
447     }
448 }
449
450 void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
451 {   const char *p;
452
453     switch (protection)
454     {
455     case PROTprivate:   p = "private";      break;
456     case PROTpackage:   p = "package";      break;
457     case PROTprotected: p = "protected";    break;
458     case PROTpublic:    p = "public";       break;
459     case PROTexport:    p = "export";       break;
460     default:
461         assert(0);
462         break;
463     }
464     buf->writestring(p);
465     AttribDeclaration::toCBuffer(buf, hgs);
466 }
467
468 /********************************* AlignDeclaration ****************************/
469
470 AlignDeclaration::AlignDeclaration(unsigned sa, Array *decl)
471     : AttribDeclaration(decl)
472 {
473     salign = sa;
474 }
475
476 Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s)
477 {
478     AlignDeclaration *ad;
479
480     assert(!s);
481     ad = new AlignDeclaration(salign, Dsymbol::arraySyntaxCopy(decl));
482     return ad;
483 }
484
485 void AlignDeclaration::semantic(Scope *sc)
486 {
487     //printf("\tAlignDeclaration::semantic '%s'\n",toChars());
488     if (decl)
489     {   unsigned salign_save = sc->structalign;
490
491     sc->structalign = salign;
492     for (unsigned i = 0; i < decl->dim; i++)
493     {
494         Dsymbol *s = (Dsymbol *)decl->data[i];
495
496         s->semantic(sc);
497     }
498     sc->structalign = salign_save;
499     }
500     else
501     sc->structalign = salign;
502 }
503
504
505 void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
506 {
507     buf->printf("align (%d)", salign);
508     AttribDeclaration::toCBuffer(buf, hgs);
509 }
510
511 /********************************* AnonDeclaration ****************************/
512
513 AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Array *decl)
514     : AttribDeclaration(decl)
515 {
516     this->loc = loc;
517     this->isunion = isunion;
518     this->scope = NULL;
519     this->sem = 0;
520 }
521
522 Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s)
523 {
524     AnonDeclaration *ad;
525
526     assert(!s);
527     ad = new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl));
528     return ad;
529 }
530
531 void AnonDeclaration::semantic(Scope *sc)
532 {
533     //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
534
535     Scope *scx = NULL;
536     if (scope)
537     {   sc = scope;
538     scx = scope;
539     scope = NULL;
540     }
541
542     assert(sc->parent);
543
544     Dsymbol *parent = sc->parent->pastMixin();
545     AggregateDeclaration *ad = parent->isAggregateDeclaration();
546
547     if (!ad || (!ad->isStructDeclaration() && !ad->isClassDeclaration()))
548     {
549     error("can only be a part of an aggregate");
550     return;
551     }
552
553     if (decl)
554     {
555     AnonymousAggregateDeclaration aad;
556     int adisunion;
557
558     if (sc->anonAgg)
559     {   ad = sc->anonAgg;
560         adisunion = sc->inunion;
561     }
562     else
563         adisunion = ad->isUnionDeclaration() != NULL;
564
565 //  printf("\tsc->anonAgg = %p\n", sc->anonAgg);
566 //  printf("\tad  = %p\n", ad);
567 //  printf("\taad = %p\n", &aad);
568
569     sc = sc->push();
570     sc->anonAgg = &aad;
571     sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls);
572     sc->inunion = isunion;
573     sc->offset = 0;
574     sc->flags = 0;
575     aad.structalign = sc->structalign;
576     aad.parent = ad;
577
578     for (unsigned i = 0; i < decl->dim; i++)
579     {
580         Dsymbol *s = (Dsymbol *)decl->data[i];
581
582         s->semantic(sc);
583         if (isunion)
584         sc->offset = 0;
585         if (aad.sizeok == 2)
586         {
587         break;
588         }
589     }
590     sc = sc->pop();
591
592     // If failed due to forward references, unwind and try again later
593     if (aad.sizeok == 2)
594     {
595         ad->sizeok = 2;
596         //printf("\tsetting ad->sizeok %p to 2\n", ad);
597         if (!sc->anonAgg)
598         {
599         scope = scx ? scx : new Scope(*sc);
600         scope->setNoFree();
601         scope->module->addDeferredSemantic(this);
602         }
603         //printf("\tforward reference %p\n", this);
604         return;
605     }
606     if (sem == 0)
607     {   Module::dprogress++;
608         sem = 1;
609         //printf("\tcompleted %p\n", this);
610     }
611     else
612         ;//printf("\talready completed %p\n", this);
613
614     // 0 sized structs are set to 1 byte
615     if (aad.structsize == 0)
616     {
617         aad.structsize = 1;
618         aad.alignsize = 1;
619     }
620
621     // Align size of anonymous aggregate
622 //printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset);
623     ad->alignmember(aad.structalign, aad.alignsize, &sc->offset);
624     //ad->structsize = sc->offset;
625 //printf("sc->offset = %d\n", sc->offset);
626
627     // Add members of aad to ad
628     //printf("\tadding members of aad to '%s'\n", ad->toChars());
629     for (unsigned i = 0; i < aad.fields.dim; i++)
630     {
631         VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
632
633         v->offset += sc->offset;
634         ad->fields.push(v);
635     }
636
637     // Add size of aad to ad
638     if (adisunion)
639     {
640         if (aad.structsize > ad->structsize)
641         ad->structsize = aad.structsize;
642         sc->offset = 0;
643     }
644     else
645     {
646         ad->structsize = sc->offset + aad.structsize;
647         sc->offset = ad->structsize;
648     }
649
650     if (ad->alignsize < aad.alignsize)
651         ad->alignsize = aad.alignsize;
652     }
653 }
654
655
656 void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
657 {
658     buf->printf(isunion ? "union" : "struct");
659     buf->writestring("\n{\n");
660     if (decl)
661     {
662     for (unsigned i = 0; i < decl->dim; i++)
663 &nb