root/trunk/src/attrib.c

Revision 886, 37.9 kB (checked in by walter, 1 year ago)

bugzilla 2581 DDoc doesn't work for functions with auto return type.

  • Property svn:eol-style set to native
Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2010 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 #include "rmem.h"
15
16 #include "init.h"
17 #include "declaration.h"
18 #include "attrib.h"
19 #include "cond.h"
20 #include "scope.h"
21 #include "id.h"
22 #include "expression.h"
23 #include "dsymbol.h"
24 #include "aggregate.h"
25 #include "module.h"
26 #include "parse.h"
27 #include "template.h"
28 #if TARGET_NET
29  #include "frontend.net/pragma.h"
30 #endif
31
32 extern void obj_includelib(const char *name);
33 void obj_startaddress(Symbol *s);
34
35
36 /********************************* AttribDeclaration ****************************/
37
38 AttribDeclaration::AttribDeclaration(Dsymbols *decl)
39         : Dsymbol()
40 {
41     this->decl = decl;
42 }
43
44 Dsymbols *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd)
45 {
46     return decl;
47 }
48
49 int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
50 {
51     int m = 0;
52     Dsymbols *d = include(sc, sd);
53
54     if (d)
55     {
56         for (unsigned i = 0; i < d->dim; i++)
57         {   Dsymbol *s = (Dsymbol *)d->data[i];
58             //printf("\taddMember %s to %s\n", s->toChars(), sd->toChars());
59             m |= s->addMember(sc, sd, m | memnum);
60         }
61     }
62     return m;
63 }
64
65 void AttribDeclaration::setScopeNewSc(Scope *sc,
66         StorageClass stc, enum LINK linkage, enum PROT protection, int explicitProtection,
67         unsigned structalign)
68 {
69     if (decl)
70     {
71         Scope *newsc = sc;
72         if (stc != sc->stc ||
73             linkage != sc->linkage ||
74             protection != sc->protection ||
75             explicitProtection != sc->explicitProtection ||
76             structalign != sc->structalign)
77         {
78             // create new one for changes
79             newsc = new Scope(*sc);
80             newsc->flags &= ~SCOPEfree;
81             newsc->stc = stc;
82             newsc->linkage = linkage;
83             newsc->protection = protection;
84             newsc->explicitProtection = explicitProtection;
85             newsc->structalign = structalign;
86         }
87         for (unsigned i = 0; i < decl->dim; i++)
88         {   Dsymbol *s = (Dsymbol *)decl->data[i];
89
90             s->setScope(newsc); // yes, the only difference from semanticNewSc()
91         }
92         if (newsc != sc)
93         {
94             sc->offset = newsc->offset;
95             newsc->pop();
96         }
97     }
98 }
99
100 void AttribDeclaration::semanticNewSc(Scope *sc,
101         StorageClass stc, enum LINK linkage, enum PROT protection, int explicitProtection,
102         unsigned structalign)
103 {
104     if (decl)
105     {
106         Scope *newsc = sc;
107         if (stc != sc->stc ||
108             linkage != sc->linkage ||
109             protection != sc->protection ||
110             explicitProtection != sc->explicitProtection ||
111             structalign != sc->structalign)
112         {
113             // create new one for changes
114             newsc = new Scope(*sc);
115             newsc->flags &= ~SCOPEfree;
116             newsc->stc = stc;
117             newsc->linkage = linkage;
118             newsc->protection = protection;
119             newsc->explicitProtection = explicitProtection;
120             newsc->structalign = structalign;
121         }
122         for (unsigned i = 0; i < decl->dim; i++)
123         {   Dsymbol *s = (Dsymbol *)decl->data[i];
124
125             s->semantic(newsc);
126         }
127         if (newsc != sc)
128         {
129             sc->offset = newsc->offset;
130             newsc->pop();
131         }
132     }
133 }
134
135 void AttribDeclaration::semantic(Scope *sc)
136 {
137     Dsymbols *d = include(sc, NULL);
138
139     //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d);
140     if (d)
141     {
142         for (unsigned i = 0; i < d->dim; i++)
143         {
144             Dsymbol *s = (Dsymbol *)d->data[i];
145
146             s->semantic(sc);
147         }
148     }
149 }
150
151 void AttribDeclaration::semantic2(Scope *sc)
152 {
153     Dsymbols *d = include(sc, NULL);
154
155     if (d)
156     {
157         for (unsigned i = 0; i < d->dim; i++)
158         {   Dsymbol *s = (Dsymbol *)d->data[i];
159             s->semantic2(sc);
160         }
161     }
162 }
163
164 void AttribDeclaration::semantic3(Scope *sc)
165 {
166     Dsymbols *d = include(sc, NULL);
167
168     if (d)
169     {
170         for (unsigned i = 0; i < d->dim; i++)
171         {   Dsymbol *s = (Dsymbol *)d->data[i];
172             s->semantic3(sc);
173         }
174     }
175 }
176
177 void AttribDeclaration::inlineScan()
178 {
179     Dsymbols *d = include(NULL, NULL);
180
181     if (d)
182     {
183         for (unsigned i = 0; i < d->dim; i++)
184         {   Dsymbol *s = (Dsymbol *)d->data[i];
185             //printf("AttribDeclaration::inlineScan %s\n", s->toChars());
186             s->inlineScan();
187         }
188     }
189 }
190
191 void AttribDeclaration::addComment(unsigned char *comment)
192 {
193     //printf("AttribDeclaration::addComment %s\n", comment);
194     if (comment)
195     {
196         Dsymbols *d = include(NULL, NULL);
197
198         if (d)
199         {
200             for (unsigned i = 0; i < d->dim; i++)
201             {   Dsymbol *s = (Dsymbol *)d->data[i];
202                 //printf("AttribDeclaration::addComment %s\n", s->toChars());
203                 s->addComment(comment);
204             }
205         }
206     }
207 }
208
209 void AttribDeclaration::emitComment(Scope *sc)
210 {
211     //printf("AttribDeclaration::emitComment(sc = %p)\n", sc);
212
213     /* A general problem with this, illustrated by BUGZILLA 2516,
214      * is that attributes are not transmitted through to the underlying
215      * member declarations for template bodies, because semantic analysis
216      * is not done for template declaration bodies
217      * (only template instantiations).
218      * Hence, Ddoc omits attributes from template members.
219      */
220
221     Dsymbols *d = include(NULL, NULL);
222
223     if (d)
224     {
225         for (unsigned i = 0; i < d->dim; i++)
226         {   Dsymbol *s = (Dsymbol *)d->data[i];
227             //printf("AttribDeclaration::emitComment %s\n", s->toChars());
228             s->emitComment(sc);
229         }
230     }
231 }
232
233 void AttribDeclaration::toObjFile(int multiobj)
234 {
235     Dsymbols *d = include(NULL, NULL);
236
237     if (d)
238     {
239         for (unsigned i = 0; i < d->dim; i++)
240         {   Dsymbol *s = (Dsymbol *)d->data[i];
241             s->toObjFile(multiobj);
242         }
243     }
244 }
245
246 int AttribDeclaration::cvMember(unsigned char *p)
247 {
248     int nwritten = 0;
249     int n;
250     Dsymbols *d = include(NULL, NULL);
251
252     if (d)
253     {
254         for (unsigned i = 0; i < d->dim; i++)
255         {   Dsymbol *s = (Dsymbol *)d->data[i];
256             n = s->cvMember(p);
257             if (p)
258                 p += n;
259             nwritten += n;
260         }
261     }
262     return nwritten;
263 }
264
265 int AttribDeclaration::hasPointers()
266 {
267     Dsymbols *d = include(NULL, NULL);
268
269     if (d)
270     {
271         for (size_t i = 0; i < d->dim; i++)
272         {
273             Dsymbol *s = (Dsymbol *)d->data[i];
274             if (s->hasPointers())
275                 return 1;
276         }
277     }
278     return 0;
279 }
280
281 const char *AttribDeclaration::kind()
282 {
283     return "attribute";
284 }
285
286 int AttribDeclaration::oneMember(Dsymbol **ps)
287 {
288     Dsymbols *d = include(NULL, NULL);
289
290     return Dsymbol::oneMembers(d, ps);
291 }
292
293 void AttribDeclaration::checkCtorConstInit()
294 {
295     Dsymbols *d = include(NULL, NULL);
296
297     if (d)
298     {
299         for (unsigned i = 0; i < d->dim; i++)
300         {   Dsymbol *s = (Dsymbol *)d->data[i];
301             s->checkCtorConstInit();
302         }
303     }
304 }
305
306 /****************************************
307  */
308
309 void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses)
310 {
311     Dsymbols *d = include(NULL, NULL);
312
313     if (d)
314     {
315         for (unsigned i = 0; i < d->dim; i++)
316         {   Dsymbol *s = (Dsymbol *)d->data[i];
317             s->addLocalClass(aclasses);
318         }
319     }
320 }
321
322
323 void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
324 {
325     if (decl)
326     {
327         if (decl->dim == 0)
328             buf->writestring("{}");
329         else if (decl->dim == 1)
330             ((Dsymbol *)decl->data[0])->toCBuffer(buf, hgs);
331         else
332         {
333             buf->writenl();
334             buf->writeByte('{');
335             buf->writenl();
336             for (unsigned i = 0; i < decl->dim; i++)
337             {
338                 Dsymbol *s = (Dsymbol *)decl->data[i];
339
340                 buf->writestring("    ");
341                 s->toCBuffer(buf, hgs);
342             }
343             buf->writeByte('}');
344         }
345     }
346     else
347         buf->writeByte(';');
348     buf->writenl();
349 }
350
351 /************************* StorageClassDeclaration ****************************/
352
353 StorageClassDeclaration::StorageClassDeclaration(StorageClass stc, Dsymbols *decl)
354         : AttribDeclaration(decl)
355 {
356     this->stc = stc;
357 }
358
359 Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
360 {
361     StorageClassDeclaration *scd;
362
363     assert(!s);
364     scd = new StorageClassDeclaration(stc, Dsymbol::arraySyntaxCopy(decl));
365     return scd;
366 }
367
368 void StorageClassDeclaration::setScope(Scope *sc)
369 {
370     if (decl)
371     {
372         StorageClass scstc = sc->stc;
373
374         /* These sets of storage classes are mutually exclusive,
375          * so choose the innermost or most recent one.
376          */
377         if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
378             scstc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
379         if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared))
380             scstc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared);
381         if (stc & (STCconst | STCimmutable | STCmanifest))
382             scstc &= ~(STCconst | STCimmutable | STCmanifest);
383         if (stc & (STCgshared | STCshared | STCtls))
384             scstc &= ~(STCgshared | STCshared | STCtls);
385         if (stc & (STCsafe | STCtrusted | STCsystem))
386             scstc &= ~(STCsafe | STCtrusted | STCsystem);
387         scstc |= stc;
388
389         setScopeNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
390     }
391 }
392
393 void StorageClassDeclaration::semantic(Scope *sc)
394 {
395     if (decl)
396     {
397         StorageClass scstc = sc->stc;
398
399         /* These sets of storage classes are mutually exclusive,
400          * so choose the innermost or most recent one.
401          */
402         if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
403             scstc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
404         if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared))
405             scstc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared);
406         if (stc & (STCconst | STCimmutable | STCmanifest))
407             scstc &= ~(STCconst | STCimmutable | STCmanifest);
408         if (stc & (STCgshared | STCshared | STCtls))
409             scstc &= ~(STCgshared | STCshared | STCtls);
410         if (stc & (STCsafe | STCtrusted | STCsystem))
411             scstc &= ~(STCsafe | STCtrusted | STCsystem);
412         scstc |= stc;
413
414         semanticNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
415     }
416 }
417
418 void StorageClassDeclaration::stcToCBuffer(OutBuffer *buf, StorageClass stc)
419 {
420     struct SCstring
421     {
422         StorageClass stc;
423         enum TOK tok;
424         Identifier *id;
425     };
426
427     static SCstring table[] =
428     {
429         { STCauto,         TOKauto },
430         { STCscope,        TOKscope },
431         { STCstatic,       TOKstatic },
432         { STCextern,       TOKextern },
433         { STCconst,        TOKconst },
434         { STCfinal,        TOKfinal },
435         { STCabstract,     TOKabstract },
436         { STCsynchronized, TOKsynchronized },
437         { STCdeprecated,   TOKdeprecated },
438         { STCoverride,     TOKoverride },
439         { STClazy,         TOKlazy },
440         { STCalias,        TOKalias },
441         { STCout,          TOKout },
442         { STCin,           TOKin },
443 #if DMDV2
444         { STCmanifest,     TOKenum },
445         { STCimmutable,    TOKimmutable },
446         { STCshared,       TOKshared },
447         { STCnothrow,      TOKnothrow },
448         { STCpure,         TOKpure },
449         { STCref,          TOKref },
450         { STCtls,          TOKtls },
451         { STCgshared,      TOKgshared },
452         { STCproperty,     TOKat,       Id::property },
453         { STCsafe,         TOKat,       Id::safe },
454         { STCtrusted,      TOKat,       Id::trusted },
455         { STCsystem,       TOKat,       Id::system },
456         { STCdisable,      TOKat,       Id::disable },
457 #endif
458     };
459
460     for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
461     {
462         if (stc & table[i].stc)
463         {
464             enum TOK tok = table[i].tok;
465 #if DMDV2
466             if (tok == TOKat)
467             {
468                 buf->writeByte('@');
469                 buf->writestring(table[i].id->toChars());
470             }
471             else
472 #endif
473                 buf->writestring(Token::toChars(tok));
474             buf->writeByte(' ');
475         }
476     }
477 }
478
479 void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
480 {
481     stcToCBuffer(buf, stc);
482     AttribDeclaration::toCBuffer(buf, hgs);
483 }
484
485 /********************************* LinkDeclaration ****************************/
486
487 LinkDeclaration::LinkDeclaration(enum LINK p, Dsymbols *decl)
488         : AttribDeclaration(decl)
489 {
490     //printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl);
491     linkage = p;
492 }
493
494 Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s)
495 {
496     LinkDeclaration *ld;
497
498     assert(!s);
499     ld = new LinkDeclaration(linkage, Dsymbol::arraySyntaxCopy(decl));
500     return ld;
501 }
502
503 void LinkDeclaration::setScope(Scope *sc)
504 {
505     //printf("LinkDeclaration::setScope(linkage = %d, decl = %p)\n", linkage, decl);
506     if (decl)
507     {
508         setScopeNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign);
509     }
510 }
511
512 void LinkDeclaration::semantic(Scope *sc)
513 {
514     //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl);
515     if (decl)
516     {
517         semanticNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign);
518     }
519 }
520
521 void LinkDeclaration::semantic3(Scope *sc)
522 {
523     //printf("LinkDeclaration::semantic3(linkage = %d, decl = %p)\n", linkage, decl);
524     if (decl)
525     {   enum LINK linkage_save = sc->linkage;
526
527         sc->linkage = linkage;
528         for (unsigned i = 0; i < decl->dim; i++)
529         {
530             Dsymbol *s = (Dsymbol *)decl->data[i];
531
532             s->semantic3(sc);
533         }
534         sc->linkage = linkage_save;
535     }
536     else
537     {
538         sc->linkage = linkage;
539     }
540 }
541
542 void LinkDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
543 {   const char *p;
544
545     switch (linkage)
546     {
547         case LINKd:             p = "D";                break;
548         case LINKc:             p = "C";                break;
549         case LINKcpp:           p = "C++";              break;
550         case LINKwindows:       p = "Windows";          break;
551         case LINKpascal:        p = "Pascal";           break;
552         default:
553             assert(0);
554             break;
555     }
556     buf->writestring("extern (");
557     buf->writestring(p);
558     buf->writestring(") ");
559     AttribDeclaration::toCBuffer(buf, hgs);
560 }
561
562 char *LinkDeclaration::toChars()
563 {
564     return (char *)"extern ()";
565 }
566
567 /********************************* ProtDeclaration ****************************/
568
569 ProtDeclaration::ProtDeclaration(enum PROT p, Dsymbols *decl)
570         : AttribDeclaration(decl)
571 {
572     protection = p;
573     //printf("decl = %p\n", decl);
574 }
575
576 Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s)
577 {
578     ProtDeclaration *pd;
579
580     assert(!s);
581     pd = new ProtDeclaration(protection, Dsymbol::arraySyntaxCopy(decl));
582     return pd;
583 }
584
585 void ProtDeclaration::setScope(Scope *sc)
586 {
587     if (decl)
588     {
589         setScopeNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign);
590     }
591 }
592
593 void ProtDeclaration::importAll(Scope *sc)
594 {
595     Scope *newsc = sc;
596     if (sc->protection != protection ||
597        sc->explicitProtection != 1)
598     {
599        // create new one for changes
600        newsc = new Scope(*sc);
601        newsc->flags &= ~SCOPEfree;
602        newsc->protection = protection;
603        newsc->explicitProtection = 1;
604     }
605
606     for (int i = 0; i < decl->dim; i++)
607     {
608        Dsymbol *s = (Dsymbol *)decl->data[i];
609        s->importAll(newsc);
610     }
611
612     if (newsc != sc)
613        newsc->pop();
614 }
615
616 void ProtDeclaration::semantic(Scope *sc)
617 {
618     if (decl)
619     {
620         semanticNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign);
621     }
622 }
623
624 void ProtDeclaration::protectionToCBuffer(OutBuffer *buf, enum PROT protection)
625 {
626     const char *p;
627
628     switch (protection)
629     {
630         case PROTprivate:       p = "private";          break;
631         case PROTpackage:       p = "package";          break;
632         case PROTprotected:     p = "protected";        break;
633         case PROTpublic:        p = "public";           break;
634         case PROTexport:        p = "export";           break;
635         default:
636             assert(0);
637             break;
638     }
639     buf->writestring(p);
640     buf->writeByte(' ');
641 }
642
643 void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
644 {
645     protectionToCBuffer(buf, protection);
646     AttribDeclaration::toCBuffer(buf, hgs);
647 }
648
649 /********************************* AlignDeclaration ****************************/
650
651 AlignDeclaration::AlignDeclaration(unsigned sa, Dsymbols *decl)
652         : AttribDeclaration(decl)
653 {
654     salign = sa;
655 }
656
657 Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s)
658 {
659     AlignDeclaration *ad;
660
661     assert(!s);
662     ad = new AlignDeclaration(salign, Dsymbol::arraySyntaxCopy(decl));
663     return ad;
664 }
665
666 void AlignDeclaration::setScope(Scope *sc)
667 {
668     //printf("\tAlignDeclaration::setScope '%s'\n",toChars());
669     if (decl)
670     {
671         setScopeNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign);
672     }
673 }
674
675 void AlignDeclaration::semantic(Scope *sc)
676 {
677     //printf("\tAlignDeclaration::semantic '%s'\n",toChars());
678     if (decl)
679     {
680         semanticNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign);
681     }
682 }
683
684
685 void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
686 {
687     buf->printf("align (%d)", salign);
688     AttribDeclaration::toCBuffer(buf, hgs);
689 }
690
691 /********************************* AnonDeclaration ****************************/
692
693 AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Dsymbols *decl)
694         : AttribDeclaration(decl)
695 {
696     this->loc = loc;
697     this->isunion = isunion;
698     this->sem = 0;
699 }
700
701 Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s)
702 {
703     AnonDeclaration *ad;
704
705     assert(!s);
706     ad = new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl));
707     return ad;
708 }
709
710 void AnonDeclaration::semantic(Scope *sc)
711 {
712     //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
713
714     Scope *scx = NULL;
715     if (scope)
716     {   sc = scope;
717         scx = scope;
718         scope = NULL;
719     }
720
721     unsigned dprogress_save = Module::dprogress;
722
723     assert(sc->parent);
724
725     Dsymbol *parent = sc->parent->pastMixin();
726     AggregateDeclaration *ad = parent->isAggregateDeclaration();
727
728     if (!ad || (!ad->isStructDeclaration() && !ad->isClassDeclaration()))
729     {
730         error("can only be a part of an aggregate");
731         return;
732     }
733
734     if (decl)
735     {
736         AnonymousAggregateDeclaration aad;
737         int adisunion;
738
739         if (sc->anonAgg)
740         {   ad = sc->anonAgg;
741             adisunion = sc->inunion;
742         }
743         else
744             adisunion = ad->isUnionDeclaration() != NULL;
745
746 //      printf("\tsc->anonAgg = %p\n", sc->anonAgg);
747 //      printf("\tad  = %p\n", ad);
748 //      printf("\taad = %p\n", &aad);
749
750         sc = sc->push();
751         sc->anonAgg = &aad;
752         sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
753         sc->inunion = isunion;
754         sc->offset = 0;
755         sc->flags = 0;
756         aad.structalign = sc->structalign;
757         aad.parent = ad;
758
759         for (unsigned i = 0; i < decl->dim; i++)
760         {
761             Dsymbol *s = (Dsymbol *)decl->data[i];
762
763             s->semantic(sc);
764             if (isunion)
765                 sc->offset = 0;
766             if (aad.sizeok == 2)
767             {
768                 break;
769             }
770         }
771         sc = sc->pop();
772
773         // If failed due to forward references, unwind and try again later
774         if (aad.sizeok == 2)
775         {
776             ad->sizeok = 2;
777             //printf("\tsetting ad->sizeok %p to 2\n", ad);
778             if (!sc->anonAgg)
779             {
780                 scope = scx ? scx : new Scope(*sc);
781                 scope->setNoFree();
782                 scope->module->addDeferredSemantic(this);
783             }
784             Module::dprogress = dprogress_save;
785             //printf("\tforward reference %p\n", this);
786             return;
787         }
788         if (sem == 0)
789         {   Module::dprogress++;
790             sem = 1;
791             //printf("\tcompleted %p\n", this);
792         }
793         else
794             ;//printf("\talready completed %p\n", this);
795
796         // 0 sized structs are set to 1 byte
797         if (aad.structsize == 0)
798         {
799             aad.structsize = 1;
800             aad.alignsize = 1;
801         }
802
803         // Align size of anonymous aggregate
804 //printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset);
805         ad->alignmember(aad.structalign, aad.alignsize, &sc->offset);
806         //ad->structsize = sc->offset;
807 //printf("sc->offset = %d\n", sc->offset);
808
809         // Add members of aad to ad
810         //printf("\tadding members of aad to '%s'\n", ad->toChars());
811         for (unsigned i = 0; i < aad.fields.dim; i++)
812         {
813             VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
814
815             v->offset += sc->offset;
816             ad->fields.push(v);
817         }
818
819         // Add size of aad to ad
820         if (adisunion)
821         {
822             if (aad.structsize > ad->structsize)
823                 ad->structsize = aad.structsize;
824             sc->offset = 0;
825         }
826         else
827         {
828             ad->structsize = sc->offset + aad.structsize;
829             sc->offset = ad->structsize;
830         }
831
832         if (ad->alignsize < aad.alignsize)
833             ad->alignsize = aad.alignsize;
834     }
835 }
836
837
838 void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
839 {
840     buf->printf(isunion ? "union" : "struct");
841     buf->writestring("\n{\n");
842     if (decl)
843     {
844         for (unsigned i = 0; i < decl->dim; i++)
845         {
846             Dsymbol *s = (Dsymbol *)decl->data[i];
847
848             //buf->writestring("    ");
849             s->toCBuffer(buf, hgs);
850         }
851     }
852     buf->writestring("}\n");
853 }
854
855 const char *AnonDeclaration::kind()
856 {
857     return (isunion ? "anonymous union" : "anonymous struct");
858 }
859
860 /********************************* PragmaDeclaration ****************************/
861
862 PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Dsymbols *decl)
863         : AttribDeclaration(decl)
864 {
865     this->loc = loc;
866     this->ident = ident;
867     this->args = args;
868 }
869
870 Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s)
871 {
872     //printf("PragmaDeclaration::syntaxCopy(%s)\n", toChars());
873     PragmaDeclaration *pd;
874
875     assert(!s);
876     pd = new PragmaDeclaration(loc, ident,
877         Expression::arraySyntaxCopy(args), Dsymbol::arraySyntaxCopy(decl));
878     return pd;
879 }
880
881 void PragmaDeclaration::setScope(Scope *sc)
882 {
883 #if TARGET_NET
884     if (ident == Lexer::idPool("assembly"))
885     {
886         if (!args || args->dim != 1)
887         {
888             error("pragma has invalid number of arguments");
889         }
890         else
891         {
892             Expression *e = (Expression *)args->data[0];
893             e = e->semantic(sc);
894             e = e->optimize(WANTvalue | WANTinterpret);
895             args->data[0] = (void *)e;
896             if (e->op != TOKstring)
897             {
898                 error("string expected, not '%s'", e->toChars());
899             }
900             PragmaScope* pragma = new PragmaScope(this, sc->parent, static_cast<StringExp*>(e));
901
902             assert(sc);
903             pragma->setScope(sc);
904
905             //add to module members
906             assert(sc->module);
907             assert(sc->module->members);
908             sc->module->members->push(pragma);
909         }
910     }
911 #endif // TARGET_NET
912 }
913
914 void PragmaDeclaration::semantic(Scope *sc)
915 {   // Should be merged with PragmaStatement
916
917     //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
918     if (ident == Id::msg)
919     {
920         if (args)
921         {
922             for (size_t i = 0; i < args->dim; i++)
923             {
924                 Expression *e = (Expression *)args->data[i];
925
926                 e = e->semantic(sc);
927                 e = e->optimize(WANTvalue | WANTinterpret);
928                 if (e->op == TOKstring)
929                 {
930                     StringExp *se = (StringExp *)e;
931                     fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
932                 }
933                 else
934                     fprintf(stdmsg, "%s", e->toChars());
935             }
936             fprintf(stdmsg, "\n");
937         }
938         goto Lnodecl;
939     }
940     else if (ident == Id::lib)
941     {
942         if (!args || args->dim != 1)
943             error("string expected for library name");
944         else
945         {
946             Expression *e = (Expression *)args->data[0];
947
948             e = e->semantic(sc);
949             e = e->optimize(WANTvalue | WANTinterpret);
950             args->data[0] = (void *)e;
951             if (e->op != TOKstring)
952                 error("string expected for library name, not '%s'", e->toChars());
953             else if (global.params.verbose)
954             {
955                 StringExp *se = (StringExp *)e;
956                 char *name = (char *)mem.malloc(se->len + 1);
957                 memcpy(name, se->string, se->len);
958                 name[se->len] = 0;
959                 printf("library   %s\n", name);
960                 mem.free(name);
961             }
962         }
963         goto Lnodecl;
964     }
965 #if IN_GCC
966     else if (ident == Id::GNU_asm)
967     {
968         if (! args || args->dim != 2)
969             error("identifier and string expected for asm name");
970         else
971         {
972             Expression *e;
973             Declaration *d = NULL;
974             StringExp *s = NULL;
975
976             e = (Expression *)args->data[0];
977             e = e->semantic(sc);
978             if (e->op == TOKvar)
979             {
980                 d = ((VarExp *)e)->var;
981                 if (! d->isFuncDeclaration() && ! d->isVarDeclaration())
982                     d = NULL;
983             }
984             if (!d)
985                 error("first argument of GNU_asm must be a function or variable declaration");
986
987             e = (Expression *)args->data[1];
988             e = e->semantic(sc);
989             e = e->optimize(WANTvalue);
990             if (e->op == TOKstring && ((StringExp *)e)->sz == 1)
991                 s = ((StringExp *)e);
992             else
993                 error("second argument of GNU_asm must be a char string");
994
995             if (d && s)
996                 d->c_ident = Lexer::idPool((char*) s->string);
997         }
998         goto Lnodecl;
999     }
1000 #endif
1001 #if DMDV2
1002     else if (ident == Id::startaddress)
1003     {
1004         if (!args || args->dim != 1)
1005             error("function name expected for start address");
1006         else
1007         {
1008             Expression *e = (Expression *)args->data[0];
1009             e = e->semantic(sc);
1010             e = e->optimize(WANTvalue | WANTinterpret);
1011             args->data[0] = (void *)e;
1012             Dsymbol *sa = getDsymbol(e);
1013             if (!sa || !sa->isFuncDeclaration())
1014                 error("function name expected for start address, not '%s'", e->toChars());
1015         }
1016         goto Lnodecl;
1017     }
1018 #endif
1019 #if TARGET_NET
1020     else if (ident == Lexer::idPool("assembly"))
1021     {
1022     }
1023 #endif // TARGET_NET
1024     else if (global.params.ignoreUnsupportedPragmas)
1025     {
1026         if (global.params.verbose)
1027         {
1028             /* Print unrecognized pragmas
1029              */
1030             printf("pragma    %s", ident->toChars());
1031             if (args)
1032             {
1033                 for (size_t i = 0; i < args->dim; i++)
1034                 {
1035                     Expression *e = (Expression *)args->data[i];
1036                     e = e->semantic(sc);
1037                     e = e->optimize(WANTvalue | WANTinterpret);
1038                     if (i == 0)
1039                         printf(" (");
1040                     else
1041                         printf(",");
1042                     printf("%s", e->toChars());
1043                 }
1044                 if (args->dim)
1045                     printf(")");
1046             }
1047             printf("\n");
1048         }
1049         goto Lnodecl;
1050     }
1051     else
1052         error("unrecognized pragma(%s)", ident->toChars());
1053
1054     if (decl)
1055     {
1056         for (unsigned i = 0; i < decl->dim; i++)
1057         {
1058             Dsymbol *s = (Dsymbol *)decl->data[i];
1059
1060             s->semantic(sc);
1061         }
1062     }
1063     return;
1064
1065 Lnodecl:
1066     if (decl)
1067         error("pragma is missing closing ';'");
1068 }
1069
1070 int PragmaDeclaration::oneMember(Dsymbol **ps)
1071 {
1072     *ps = NULL;
1073     return TRUE;
1074 }
1075
1076 const char *PragmaDeclaration::kind()
1077 {
1078     return "pragma";
1079 }
1080
1081 void PragmaDeclaration::toObjFile(int multiobj)
1082 {
1083     if (ident == Id::lib)
1084     {
1085         assert(args && args->dim == 1);
1086
1087         Expression *e = (Expression *)args->data[0];
1088
1089         assert(e->op == TOKstring);
1090
1091         StringExp *se = (StringExp *)e;
1092         char *name = (char *)mem.malloc(se->len + 1);
1093         memcpy(name, se->string, se->len);
1094         name[se->len] = 0;
1095 #if OMFOBJ
1096         /* The OMF format allows library names to be inserted
1097          * into the object file. The linker will then automatically
1098          * search that library, too.
1099          */
1100         obj_includelib(name);
1101 #elif ELFOBJ || MACHOBJ
1102         /* The format does not allow embedded library names,
1103          * so instead append the library name to the list to be passed
1104          * to the linker.
1105          */
1106         global.params.libfiles->push((void *) name);
1107 #else
1108         error("pragma lib not supported");
1109 #endif
1110     }
1111 #if DMDV2
1112     else if (ident == Id::startaddress)
1113     {
1114         assert(args && args->dim == 1);
1115         Expression *e = (Expression *)args->data[0];
1116         Dsymbol *sa = getDsymbol(e);
1117         FuncDeclaration *f = sa->isFuncDeclaration();
1118         assert(f);
1119         Symbol *s = f->toSymbol();
1120         obj_startaddress(s);
1121     }
1122 #endif
1123     AttribDeclaration::toObjFile(multiobj);
1124 }
1125
1126 void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1127 {
1128     buf->printf("pragma (%s", ident->toChars());
1129     if (args && args->dim)
1130     {
1131         buf->writestring(", ");
1132         argsToCBuffer(buf, args, hgs);
1133     }
1134     buf->writeByte(')');
1135     AttribDeclaration::toCBuffer(buf, hgs);
1136 }
1137
1138
1139 /********************************* ConditionalDeclaration ****************************/
1140
1141 ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl)
1142         : AttribDeclaration(decl)
1143 {
1144     //printf("ConditionalDeclaration::ConditionalDeclaration()\n");
1145     this->condition = condition;
1146     this->elsedecl = elsedecl;
1147 }
1148
1149 Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s)
1150 {
1151     ConditionalDeclaration *dd;
1152
1153     assert(!s);
1154     dd = new ConditionalDeclaration(condition->syntaxCopy(),
1155         Dsymbol::arraySyntaxCopy(decl),
1156         Dsymbol::arraySyntaxCopy(elsedecl));
1157     return dd;
1158 }
1159
1160
1161 int ConditionalDeclaration::oneMember(Dsymbol **ps)
1162 {
1163     //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition->inc);
1164     if (condition->inc)
1165     {
1166         Dsymbols *d = condition->include(NULL, NULL) ? decl : elsedecl;
1167         return Dsymbol::oneMembers(d, ps);
1168     }
1169     *ps = NULL;
1170     return TRUE;
1171 }
1172
1173 void ConditionalDeclaration::emitComment(Scope *sc)
1174 {
1175     //printf("ConditionalDeclaration::emitComment(sc = %p)\n", sc);
1176     if (condition->inc)
1177     {
1178         AttribDeclaration::emitComment(sc);
1179     }
1180     else if (sc->docbuf)
1181     {
1182         /* If generating doc comment, be careful because if we're inside
1183          * a template, then include(NULL, NULL) will fail.
1184          */
1185         Dsymbols *d = decl ? decl : elsedecl;
1186         for (unsigned i = 0; i < d->dim; i++)
1187         {   Dsymbol *s = (Dsymbol *)d->data[i];
1188             s->emitComment(sc);
1189         }
1190     }
1191 }
1192
1193 // Decide if 'then' or 'else' code should be included
1194
1195 Dsymbols *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd)
1196 {
1197     //printf("ConditionalDeclaration::include()\n");
1198     assert(condition);
1199     return condition->include(sc, sd) ? decl : elsedecl;
1200 }
1201
1202 void ConditionalDeclaration::setScope(Scope *sc)
1203 {
1204     Dsymbols *d = include(sc, NULL);
1205
1206     //printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d);
1207     if (d)
1208     {
1209        for (unsigned i = 0; i < d->dim; i++)
1210        {
1211            Dsymbol *s = (Dsymbol *)d->data[i];
1212
1213            s->setScope(sc);
1214        }
1215     }
1216 }
1217
1218 void ConditionalDeclaration::importAll(Scope *sc)
1219 {
1220     Dsymbols *d = include(sc, NULL);
1221
1222     //printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d);
1223     if (d)
1224     {
1225        for (unsigned i = 0; i < d->dim; i++)
1226        {
1227            Dsymbol *s = (Dsymbol *)d->data[i];
1228
1229            s->importAll(sc);
1230        }
1231     }
1232 }
1233
1234 void ConditionalDeclaration::addComment(unsigned char *comment)
1235 {
1236     /* Because addComment is called by the parser, if we called
1237      * include() it would define a version before it was used.
1238      * But it's no problem to drill down to both decl and elsedecl,
1239      * so that's the workaround.
1240      */
1241
1242     if (comment)
1243     {
1244         Dsymbols *d = decl;
1245
1246         for (int j = 0; j < 2; j++)
1247         {
1248             if (d)
1249             {
1250                 for (unsigned i = 0; i < d->dim; i++)
1251                 {   Dsymbol *s;
1252
1253                     s = (Dsymbol *)d->data[i];
1254                     //printf("ConditionalDeclaration::addComment %s\n", s->toChars());
1255                     s->addComment(comment);
1256                 }
1257             }
1258             d = elsedecl;
1259         }
1260     }
1261 }
1262
1263 void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1264 {
1265     condition->toCBuffer(buf, hgs);
1266     if (decl || elsedecl)
1267     {
1268         buf->writenl();
1269         buf->writeByte('{');
1270         buf->writenl();
1271         if (decl)
1272         {
1273             for (unsigned i = 0; i < decl->dim; i++)
1274             {
1275                 Dsymbol *s = (Dsymbol *)decl->data[i];
1276
1277                 buf->writestring("    ");
1278                 s->toCBuffer(buf, hgs);
1279             }
1280         }
1281         buf->writeByte('}');
1282         if (elsedecl)
1283         {
1284             buf->writenl();
1285             buf->writestring("else");
1286             buf->writenl();
1287             buf->writeByte('{');
1288             buf->writenl();
1289             for (unsigned i = 0; i < elsedecl->dim; i++)
1290             {
1291                 Dsymbol *s = (Dsymbol *)elsedecl->data[i];
1292
1293                 buf->writestring("    ");
1294                 s->toCBuffer(buf, hgs);
1295             }
1296             buf->writeByte('}');
1297         }
1298     }
1299     else
1300         buf->writeByte(':');
1301     buf->writenl();
1302 }
1303
1304 /***************************** StaticIfDeclaration ****************************/
1305
1306 StaticIfDeclaration::StaticIfDeclaration(Condition *condition,
1307         Dsymbols *decl, Dsymbols *elsedecl)
1308         : ConditionalDeclaration(condition, decl, elsedecl)
1309 {
1310     //printf("StaticIfDeclaration::StaticIfDeclaration()\n");
1311     sd = NULL;
1312     addisdone = 0;
1313 }
1314
1315
1316 Dsymbol *StaticIfDeclaration::syntaxCopy(Dsymbol *s)
1317 {
1318     StaticIfDeclaration *dd;
1319
1320     assert(!s);
1321     dd = new StaticIfDeclaration(condition->syntaxCopy(),
1322         Dsymbol::arraySyntaxCopy(decl),
1323         Dsymbol::arraySyntaxCopy(elsedecl));
1324     return dd;
1325 }
1326
1327
1328 int StaticIfDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
1329 {
1330     //printf("StaticIfDeclaration::addMember() '%s'\n",toChars());
1331     /* This is deferred until semantic(), so that
1332      * expressions in the condition can refer to declarations
1333      * in the same scope, such as:
1334      *
1335      * template Foo(int i)
1336      * {
1337      *     const int j = i + 1;
1338      *     static if (j == 3)
1339      *         const int k;
1340      * }
1341      */
1342     this->sd = sd;
1343     int m = 0;
1344
1345     if (memnum == 0)
1346     {   m = AttribDeclaration::addMember(sc, sd, memnum);
1347         addisdone = 1;
1348     }
1349     return m;
1350 }
1351
1352
1353 void StaticIfDeclaration::importAll(Scope *sc)
1354 {
1355     // do not evaluate condition before semantic pass
1356 }
1357
1358 void StaticIfDeclaration::setScope(Scope *sc)
1359 {
1360     // do not evaluate condition before semantic pass
1361 }
1362
1363 void StaticIfDeclaration::semantic(Scope *sc)
1364 {
1365     Dsymbols *d = include(sc, sd);
1366
1367     //printf("\tStaticIfDeclaration::semantic '%s', d = %p\n",toChars(), d);
1368     if (d)
1369     {
1370         if (!addisdone)
1371         {   AttribDeclaration::addMember(sc, sd, 1);
1372             addisdone = 1;
1373         }
1374
1375         for (unsigned i = 0; i < d->dim; i++)
1376         {
1377             Dsymbol *s = (Dsymbol *)d->data[i];
1378
1379             s->semantic(sc);
1380         }
1381     }
1382 }
1383
1384 const char *StaticIfDeclaration::kind()
1385 {
1386     return "static if";
1387 }
1388
1389
1390 /***************************** CompileDeclaration *****************************/
1391
1392 CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
1393     : AttribDeclaration(NULL)
1394 {
1395     //printf("CompileDeclaration(loc = %d)\n", loc.linnum);
1396     this->loc = loc;
1397     this->exp = exp;
1398     this->sd = NULL;
1399     this->compiled = 0;
1400 }
1401
1402 Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *s)
1403 {
1404     //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars());
1405     CompileDeclaration *sc = new CompileDeclaration(loc, exp->syntaxCopy());
1406     return sc;
1407 }
1408
1409 int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
1410 {
1411     //printf("CompileDeclaration::addMember(sc = %p, sd = %p, memnum = %d)\n", sc, sd, memnum);
1412     this->sd = sd;
1413     if (memnum == 0)
1414     {   /* No members yet, so parse the mixin now
1415          */
1416         compileIt(sc);
1417         memnum |= AttribDeclaration::addMember(sc, sd, memnum);
1418         compiled = 1;
1419     }
1420     return memnum;
1421 }
1422
1423 void CompileDeclaration::compileIt(Scope *sc)
1424 {
1425     //printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars());
1426     exp = exp->semantic(sc);
1427     exp = resolveProperties(sc, exp);
1428     exp = exp->optimize(WANTvalue | WANTinterpret);
1429     if (exp->op != TOKstring)
1430     {   exp->error("argument to mixin must be a string, not (%s)", exp->toChars());
1431     }
1432     else
1433     {
1434         StringExp *se = (StringExp *)exp;
1435         se = se->toUTF8(sc);
1436         Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
1437         p.loc = loc;
1438         p.nextToken();
1439         decl = p.parseDeclDefs(0);
1440         if (p.token.value != TOKeof)
1441             exp->error("incomplete mixin declaration (%s)", se->toChars());
1442     }
1443 }
1444
1445 void CompileDeclaration::semantic(Scope *sc)
1446 {
1447     //printf("CompileDeclaration::semantic()\n");
1448
1449     if (!compiled)
1450     {
1451         compileIt(sc);
1452         AttribDeclaration::addMember(sc, sd, 0);
1453         compiled = 1;
1454     }
1455     AttribDeclaration::semantic(sc);
1456 }
1457
1458 void CompileDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1459 {
1460     buf->writestring("mixin(");
1461     exp->toCBuffer(buf, hgs);
1462     buf->writestring(");");
1463     buf->writenl();
1464 }
Note: See TracBrowser for help on using the browser.