Fixed some lexing problems with DOS line-endings
[delight/core.git] / dmd2 / attrib.c
bloba4d301c0b6ae4735b68952bb670389feb08fef34
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, December 2006
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <assert.h>
21 #if _WIN32 || IN_GCC
22 #include "mem.h"
23 #elif linux
24 #include "../root/mem.h"
25 #endif
27 #include "init.h"
28 #include "declaration.h"
29 #include "attrib.h"
30 #include "cond.h"
31 #include "scope.h"
32 #include "id.h"
33 #include "expression.h"
34 #include "dsymbol.h"
35 #include "aggregate.h"
36 #include "module.h"
37 #include "parse.h"
38 #include "template.h"
40 extern void obj_includelib(char *name);
41 void obj_startaddress(Symbol *s);
44 /********************************* AttribDeclaration ****************************/
46 AttribDeclaration::AttribDeclaration(Array *decl)
47 : Dsymbol()
49 this->decl = decl;
52 Array *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd)
54 return decl;
57 int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
59 unsigned i;
60 int m = 0;
61 Array *d = include(sc, sd);
63 if (d)
65 for (i = 0; i < d->dim; i++)
66 { Dsymbol *s;
68 s = (Dsymbol *)d->data[i];
69 m |= s->addMember(sc, sd, m | memnum);
72 return m;
75 void AttribDeclaration::semantic(Scope *sc)
77 Array *d = include(sc, NULL);
79 //printf("\tAttribDeclaration::semantic '%s'\n",toChars());
80 if (d)
82 for (unsigned i = 0; i < d->dim; i++)
84 Dsymbol *s = (Dsymbol *)d->data[i];
86 s->semantic(sc);
91 void AttribDeclaration::semantic2(Scope *sc)
93 unsigned i;
94 Array *d = include(sc, NULL);
96 if (d)
98 for (i = 0; i < d->dim; i++)
99 { Dsymbol *s;
101 s = (Dsymbol *)d->data[i];
102 s->semantic2(sc);
107 void AttribDeclaration::semantic3(Scope *sc)
109 unsigned i;
110 Array *d = include(sc, NULL);
112 if (d)
114 for (i = 0; i < d->dim; i++)
115 { Dsymbol *s;
117 s = (Dsymbol *)d->data[i];
118 s->semantic3(sc);
123 void AttribDeclaration::inlineScan()
125 unsigned i;
126 Array *d = include(NULL, NULL);
128 if (d)
130 for (i = 0; i < d->dim; i++)
131 { Dsymbol *s;
133 s = (Dsymbol *)d->data[i];
134 //printf("AttribDeclaration::inlineScan %s\n", s->toChars());
135 s->inlineScan();
140 void AttribDeclaration::addComment(unsigned char *comment)
142 if (comment)
144 unsigned i;
145 Array *d = include(NULL, NULL);
147 if (d)
149 for (i = 0; i < d->dim; i++)
150 { Dsymbol *s;
152 s = (Dsymbol *)d->data[i];
153 //printf("AttribDeclaration::addComment %s\n", s->toChars());
154 s->addComment(comment);
160 void AttribDeclaration::emitComment(Scope *sc)
162 //printf("AttribDeclaration::emitComment(sc = %p)\n", sc);
164 /* If generating doc comment, skip this because if we're inside
165 * a template, then include(NULL, NULL) will fail.
167 // if (sc->docbuf)
168 // return;
170 unsigned i;
171 Array *d = include(NULL, NULL);
173 if (d)
175 for (i = 0; i < d->dim; i++)
176 { Dsymbol *s;
178 s = (Dsymbol *)d->data[i];
179 //printf("AttribDeclaration::emitComment %s\n", s->toChars());
180 s->emitComment(sc);
185 void AttribDeclaration::toObjFile(int multiobj)
187 unsigned i;
188 Array *d = include(NULL, NULL);
190 if (d)
192 for (i = 0; i < d->dim; i++)
193 { Dsymbol *s;
195 s = (Dsymbol *)d->data[i];
196 s->toObjFile(multiobj);
201 int AttribDeclaration::cvMember(unsigned char *p)
203 unsigned i;
204 int nwritten = 0;
205 int n;
206 Array *d = include(NULL, NULL);
208 if (d)
210 for (i = 0; i < d->dim; i++)
211 { Dsymbol *s;
213 s = (Dsymbol *)d->data[i];
214 n = s->cvMember(p);
215 if (p)
216 p += n;
217 nwritten += n;
220 return nwritten;
223 int AttribDeclaration::hasPointers()
225 Array *d = include(NULL, NULL);
227 if (d)
229 for (size_t i = 0; i < d->dim; i++)
231 Dsymbol *s = (Dsymbol *)d->data[i];
232 if (s->hasPointers())
233 return 1;
236 return 0;
239 char *AttribDeclaration::kind()
241 return "attribute";
244 int AttribDeclaration::oneMember(Dsymbol **ps)
246 Array *d = include(NULL, NULL);
248 return Dsymbol::oneMembers(d, ps);
251 void AttribDeclaration::checkCtorConstInit()
253 unsigned i;
254 Array *d = include(NULL, NULL);
256 if (d)
258 for (i = 0; i < d->dim; i++)
259 { Dsymbol *s;
261 s = (Dsymbol *)d->data[i];
262 s->checkCtorConstInit();
267 /****************************************
270 void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses)
271 { unsigned i;
272 Array *d = include(NULL, NULL);
274 if (d)
276 for (i = 0; i < d->dim; i++)
277 { Dsymbol *s;
279 s = (Dsymbol *)d->data[i];
280 s->addLocalClass(aclasses);
286 void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
288 if (decl)
290 buf->writenl();
291 buf->writeByte('{');
292 buf->writenl();
293 for (unsigned i = 0; i < decl->dim; i++)
295 Dsymbol *s = (Dsymbol *)decl->data[i];
297 buf->writestring(" ");
298 s->toCBuffer(buf, hgs);
300 buf->writeByte('}');
302 else
303 buf->writeByte(';');
304 buf->writenl();
307 /************************* StorageClassDeclaration ****************************/
309 StorageClassDeclaration::StorageClassDeclaration(unsigned stc, Array *decl)
310 : AttribDeclaration(decl)
312 this->stc = stc;
315 Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
317 StorageClassDeclaration *scd;
319 assert(!s);
320 scd = new StorageClassDeclaration(stc, Dsymbol::arraySyntaxCopy(decl));
321 return scd;
324 void StorageClassDeclaration::semantic(Scope *sc)
326 if (decl)
327 { unsigned stc_save = sc->stc;
329 /* These sets of storage classes are mutually exclusive,
330 * so choose the innermost or most recent one.
332 if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
333 sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
334 if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest))
335 sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest);
336 if (stc & (STCconst | STCinvariant | STCmanifest))
337 sc->stc &= ~(STCconst | STCinvariant | STCmanifest);
338 sc->stc |= stc;
339 for (unsigned i = 0; i < decl->dim; i++)
341 Dsymbol *s = (Dsymbol *)decl->data[i];
343 s->semantic(sc);
345 sc->stc = stc_save;
347 else
348 sc->stc = stc;
351 void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
353 struct SCstring
355 int stc;
356 enum TOK tok;
359 static SCstring table[] =
361 { STCauto, TOKauto },
362 { STCscope, TOKscope },
363 { STCstatic, TOKstatic },
364 { STCextern, TOKextern },
365 { STCconst, TOKconst },
366 { STCinvariant, TOKinvariant },
367 { STCfinal, TOKfinal },
368 { STCabstract, TOKabstract },
369 { STCsynchronized, TOKsynchronized },
370 { STCdeprecated, TOKdeprecated },
371 { STCoverride, TOKoverride },
372 { STCnothrow, TOKnothrow },
373 { STCpure, TOKpure },
374 { STCtls, TOKtls },
377 int written = 0;
378 for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
380 if (stc & table[i].stc)
382 if (written)
383 buf->writeByte(' ');
384 written = 1;
385 buf->writestring(Token::toChars(table[i].tok));
389 AttribDeclaration::toCBuffer(buf, hgs);
392 /********************************* LinkDeclaration ****************************/
394 LinkDeclaration::LinkDeclaration(enum LINK p, Array *decl)
395 : AttribDeclaration(decl)
397 //printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl);
398 linkage = p;
401 Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s)
403 LinkDeclaration *ld;
405 assert(!s);
406 ld = new LinkDeclaration(linkage, Dsymbol::arraySyntaxCopy(decl));
407 return ld;
410 void LinkDeclaration::semantic(Scope *sc)
412 //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl);
413 if (decl)
414 { enum LINK linkage_save = sc->linkage;
416 sc->linkage = linkage;
417 for (unsigned i = 0; i < decl->dim; i++)
419 Dsymbol *s = (Dsymbol *)decl->data[i];
421 s->semantic(sc);
423 sc->linkage = linkage_save;
425 else
427 sc->linkage = linkage;
431 void LinkDeclaration::semantic3(Scope *sc)
433 //printf("LinkDeclaration::semantic3(linkage = %d, decl = %p)\n", linkage, decl);
434 if (decl)
435 { enum LINK linkage_save = sc->linkage;
437 sc->linkage = linkage;
438 for (unsigned i = 0; i < decl->dim; i++)
440 Dsymbol *s = (Dsymbol *)decl->data[i];
442 s->semantic3(sc);
444 sc->linkage = linkage_save;
446 else
448 sc->linkage = linkage;
452 void LinkDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
453 { char *p;
455 switch (linkage)
457 case LINKd: p = "D"; break;
458 case LINKc: p = "C"; break;
459 case LINKcpp: p = "C++"; break;
460 case LINKwindows: p = "Windows"; break;
461 case LINKpascal: p = "Pascal"; break;
462 default:
463 assert(0);
464 break;
466 buf->writestring("extern (");
467 buf->writestring(p);
468 buf->writestring(") ");
469 AttribDeclaration::toCBuffer(buf, hgs);
472 char *LinkDeclaration::toChars()
474 return "extern ()";
477 /********************************* ProtDeclaration ****************************/
479 ProtDeclaration::ProtDeclaration(enum PROT p, Array *decl)
480 : AttribDeclaration(decl)
482 protection = p;
483 //printf("decl = %p\n", decl);
486 Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s)
488 ProtDeclaration *pd;
490 assert(!s);
491 pd = new ProtDeclaration(protection, Dsymbol::arraySyntaxCopy(decl));
492 return pd;
495 void ProtDeclaration::semantic(Scope *sc)
497 if (decl)
498 { enum PROT protection_save = sc->protection;
499 int explicitProtection_save = sc->explicitProtection;
501 sc->protection = protection;
502 sc->explicitProtection = 1;
503 for (unsigned i = 0; i < decl->dim; i++)
505 Dsymbol *s = (Dsymbol *)decl->data[i];
507 s->semantic(sc);
509 sc->protection = protection_save;
510 sc->explicitProtection = explicitProtection_save;
512 else
513 { sc->protection = protection;
514 sc->explicitProtection = 1;
518 void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
519 { char *p;
521 switch (protection)
523 case PROTprivate: p = "private"; break;
524 case PROTpackage: p = "package"; break;
525 case PROTprotected: p = "protected"; break;
526 case PROTpublic: p = "public"; break;
527 case PROTexport: p = "export"; break;
528 default:
529 assert(0);
530 break;
532 buf->writestring(p);
533 AttribDeclaration::toCBuffer(buf, hgs);
536 /********************************* AlignDeclaration ****************************/
538 AlignDeclaration::AlignDeclaration(unsigned sa, Array *decl)
539 : AttribDeclaration(decl)
541 salign = sa;
544 Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s)
546 AlignDeclaration *ad;
548 assert(!s);
549 ad = new AlignDeclaration(salign, Dsymbol::arraySyntaxCopy(decl));
550 return ad;
553 void AlignDeclaration::semantic(Scope *sc)
555 //printf("\tAlignDeclaration::semantic '%s'\n",toChars());
556 if (decl)
557 { unsigned salign_save = sc->structalign;
559 sc->structalign = salign;
560 for (unsigned i = 0; i < decl->dim; i++)
562 Dsymbol *s = (Dsymbol *)decl->data[i];
564 s->semantic(sc);
566 sc->structalign = salign_save;
568 else
569 sc->structalign = salign;
573 void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
575 buf->printf("align (%d)", salign);
576 AttribDeclaration::toCBuffer(buf, hgs);
579 /********************************* AnonDeclaration ****************************/
581 AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Array *decl)
582 : AttribDeclaration(decl)
584 this->loc = loc;
585 this->isunion = isunion;
586 this->scope = NULL;
587 this->sem = 0;
590 Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s)
592 AnonDeclaration *ad;
594 assert(!s);
595 ad = new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl));
596 return ad;
599 void AnonDeclaration::semantic(Scope *sc)
601 //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
603 Scope *scx = NULL;
604 if (scope)
605 { sc = scope;
606 scx = scope;
607 scope = NULL;
610 assert(sc->parent);
612 Dsymbol *parent = sc->parent->pastMixin();
613 AggregateDeclaration *ad = parent->isAggregateDeclaration();
615 if (!ad || (!ad->isStructDeclaration() && !ad->isClassDeclaration()))
617 error("can only be a part of an aggregate");
618 return;
621 if (decl)
623 AnonymousAggregateDeclaration aad;
624 int adisunion;
626 if (sc->anonAgg)
627 { ad = sc->anonAgg;
628 adisunion = sc->inunion;
630 else
631 adisunion = ad->isUnionDeclaration() != NULL;
633 // printf("\tsc->anonAgg = %p\n", sc->anonAgg);
634 // printf("\tad = %p\n", ad);
635 // printf("\taad = %p\n", &aad);
637 sc = sc->push();
638 sc->anonAgg = &aad;
639 sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls);
640 sc->inunion = isunion;
641 sc->offset = 0;
642 sc->flags = 0;
643 aad.structalign = sc->structalign;
644 aad.parent = ad;
646 for (unsigned i = 0; i < decl->dim; i++)
648 Dsymbol *s = (Dsymbol *)decl->data[i];
650 s->semantic(sc);
651 if (isunion)
652 sc->offset = 0;
653 if (aad.sizeok == 2)
655 break;
658 sc = sc->pop();
660 // If failed due to forward references, unwind and try again later
661 if (aad.sizeok == 2)
663 ad->sizeok = 2;
664 //printf("\tsetting ad->sizeok %p to 2\n", ad);
665 if (!sc->anonAgg)
667 scope = scx ? scx : new Scope(*sc);
668 scope->setNoFree();
669 scope->module->addDeferredSemantic(this);
671 //printf("\tforward reference %p\n", this);
672 return;
674 if (sem == 0)
675 { Module::dprogress++;
676 sem = 1;
677 //printf("\tcompleted %p\n", this);
679 else
680 ;//printf("\talready completed %p\n", this);
682 // 0 sized structs are set to 1 byte
683 if (aad.structsize == 0)
685 aad.structsize = 1;
686 aad.alignsize = 1;
689 // Align size of anonymous aggregate
690 //printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset);
691 ad->alignmember(aad.structalign, aad.alignsize, &sc->offset);
692 //ad->structsize = sc->offset;
693 //printf("sc->offset = %d\n", sc->offset);
695 // Add members of aad to ad
696 //printf("\tadding members of aad to '%s'\n", ad->toChars());
697 for (unsigned i = 0; i < aad.fields.dim; i++)
699 VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
701 v->offset += sc->offset;
702 ad->fields.push(v);
705 // Add size of aad to ad
706 if (adisunion)
708 if (aad.structsize > ad->structsize)
709 ad->structsize = aad.structsize;
710 sc->offset = 0;
712 else
714 ad->structsize = sc->offset + aad.structsize;
715 sc->offset = ad->structsize;
718 if (ad->alignsize < aad.alignsize)
719 ad->alignsize = aad.alignsize;
724 void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
726 buf->printf(isunion ? "union" : "struct");
727 buf->writestring("\n{\n");
728 if (decl)
730 for (unsigned i = 0; i < decl->dim; i++)
732 Dsymbol *s = (Dsymbol *)decl->data[i];
734 //buf->writestring(" ");
735 s->toCBuffer(buf, hgs);
738 buf->writestring("}\n");
741 char *AnonDeclaration::kind()
743 return (char *)(isunion ? "anonymous union" : "anonymous struct");
746 /********************************* PragmaDeclaration ****************************/
748 PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl)
749 : AttribDeclaration(decl)
751 this->loc = loc;
752 this->ident = ident;
753 this->args = args;
756 Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s)
758 PragmaDeclaration *pd;
760 assert(!s);
761 pd = new PragmaDeclaration(loc, ident,
762 Expression::arraySyntaxCopy(args), Dsymbol::arraySyntaxCopy(decl));
763 return pd;
766 void PragmaDeclaration::semantic(Scope *sc)
767 { // Should be merged with PragmaStatement
768 Scope sc_save;
770 //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
771 if (ident == Id::msg)
773 if (args)
775 for (size_t i = 0; i < args->dim; i++)
777 Expression *e = (Expression *)args->data[i];
779 e = e->semantic(sc);
780 e = e->optimize(WANTvalue | WANTinterpret);
781 if (e->op == TOKstring)
783 StringExp *se = (StringExp *)e;
784 fprintf(stdmsg, "%.*s", (int)se->len, se->string);
786 else
787 error("string expected for message, not '%s'", e->toChars());
789 fprintf(stdmsg, "\n");
791 goto Lnodecl;
793 else if (ident == Id::lib)
795 if (!args || args->dim != 1)
796 error("string expected for library name");
797 else
799 Expression *e = (Expression *)args->data[0];
801 e = e->semantic(sc);
802 e = e->optimize(WANTvalue | WANTinterpret);
803 args->data[0] = (void *)e;
804 if (e->op != TOKstring)
805 error("string expected for library name, not '%s'", e->toChars());
806 else if (global.params.verbose)
808 StringExp *se = (StringExp *)e;
809 char *name = (char *)mem.malloc(se->len + 1);
810 memcpy(name, se->string, se->len);
811 name[se->len] = 0;
812 printf("library %s\n", name);
813 mem.free(name);
816 goto Lnodecl;
818 #if IN_GCC
819 else if (ident == Id::GNU_asm)
821 if (! args || args->dim != 2)
822 error("identifier and string expected for asm name");
823 else
825 Expression *e;
826 Declaration *d = NULL;
827 StringExp *s = NULL;
829 e = (Expression *)args->data[0];
830 e = e->semantic(sc);
831 if (e->op == TOKvar)
833 d = ((VarExp *)e)->var;
834 if (! d->isFuncDeclaration() && ! d->isVarDeclaration())
835 d = NULL;
837 if (!d)
838 error("first argument of GNU_asm must be a function or variable declaration");
840 e = (Expression *)args->data[1];
841 e = e->semantic(sc);
842 e = e->optimize(WANTvalue | WANTinterpret);
843 if (e->op == TOKstring && ((StringExp *)e)->sz == 1)
844 s = ((StringExp *)e);
845 else
846 error("second argument of GNU_asm must be a character string");
848 if (d && s)
849 d->c_ident = Lexer::idPool((char*) s->string);
851 goto Lnodecl;
853 else if (ident == Id::GNU_attribute)
855 sc_save = *sc;
857 // An empty list is allowed.
858 if (args && args->dim)
860 Expressions * a;
862 if (sc->attributes)
863 a = (Expressions *) sc->attributes->copy();
864 else
865 a = new Expressions;
866 sc->attributes = a;
868 for (unsigned i = 0; i < args->dim; i++)
870 Expression * e = (Expression *) args->data[i];
871 //e = e->semantic(sc);
873 if (e->op == TOKidentifier) {
874 /* ok */
875 } else if (e->op == TOKcall) {
876 CallExp * c = (CallExp *) e;
877 if (c->e1->op != TOKidentifier)
878 error("identifier or call expression expected for attribute");
879 if (c->arguments)
880 for (int unsigned ai = 0; ai < c->arguments->dim; ai++)
882 c->arguments->data[ai] =
883 ((Expression *) c->arguments->data[ai])->semantic(sc);
886 else
888 error("identifier or call expression expected for attribute");
889 continue;
891 a->push(e);
895 else if (ident == Id::GNU_set_attribute)
897 if (!args || args->dim < 1)
898 error("declaration expected for setting attributes");
899 else
901 Array p_attributes_list; // of Expressions**
903 Expression * e = (Expression *) args->data[0];
904 Expressions ** pa = NULL;
906 e = e->semantic(sc);
907 if (e->op == TOKvar)
909 Declaration * d = ((VarExp *)e)->var;
910 if (d->isFuncDeclaration() || d->isVarDeclaration())
911 pa = & d->attributes;
913 else if (e->op == TOKtype)
915 Type * t = ((TypeExp *)e)->type;
916 if (t->ty == Ttypedef)
917 pa = & ((TypeTypedef *) t)->sym->attributes;
918 else if (t->ty == Tenum)
919 pa = & ((TypeEnum *) t)->sym->attributes;
920 else if (t->ty == Tstruct)
921 pa = & ((TypeStruct *) t)->sym->attributes;
922 else if (t->ty == Tclass)
923 pa = & ((TypeClass *) t)->sym->attributes;
926 if (pa)
927 p_attributes_list.push(pa);
928 else
929 error("first argument must be a function, variable, or type declaration");
932 Expressions * new_attrs = new Expressions;
933 for (unsigned i = 1; i < args->dim; i++)
935 Expression * e = (Expression *) args->data[i];
936 //e = e->semantic(sc);
938 if (e->op == TOKidentifier) {
939 /* ok */
940 } else if (e->op == TOKcall) {
941 CallExp * c = (CallExp *) e;
942 if (c->e1->op != TOKidentifier)
943 error("identifier or call expression expected for attribute");
944 if (c->arguments)
945 for (int unsigned ai = 0; ai < c->arguments->dim; ai++)
947 c->arguments->data[ai] =
948 ((Expression *) c->arguments->data[ai])->semantic(sc);
951 else
953 error("identifier or call expression expected for attribute");
954 continue;
956 new_attrs->push(e);
959 for (unsigned i = 0; i < p_attributes_list.dim; ++i)
961 Expressions ** pa = (Expressions **) p_attributes_list.data[i];
962 if (*pa)
964 *pa = (Expressions *) (*pa)->copy();
965 (*pa)->append(new_attrs);
967 else
968 *pa = new_attrs;
971 goto Lnodecl;
973 #endif
974 else if (ident == Id::startaddress)
976 if (!args || args->dim != 1)
977 error("function name expected for start address");
978 else
980 Expression *e = (Expression *)args->data[0];
981 e = e->semantic(sc);
982 e = e->optimize(WANTvalue | WANTinterpret);
983 args->data[0] = (void *)e;
984 Dsymbol *sa = getDsymbol(e);
985 if (!sa || !sa->isFuncDeclaration())
986 error("function name expected for start address, not '%s'", e->toChars());
988 goto Lnodecl;
990 else if (global.params.ignoreUnsupportedPragmas)
992 if (global.params.verbose)
994 /* Print unrecognized pragmas
996 printf("pragma %s", ident->toChars());
997 if (args)
999 for (size_t i = 0; i < args->dim; i++)
1001 Expression *e = (Expression *)args->data[i];
1002 e = e->semantic(sc);
1003 e = e->optimize(WANTvalue | WANTinterpret);
1004 if (i == 0)
1005 printf(" (");
1006 else
1007 printf(",");
1008 printf("%s", e->toChars());
1010 if (args->dim)
1011 printf(")");
1013 printf("\n");
1015 goto Lnodecl;
1017 else
1018 error("unrecognized pragma(%s)", ident->toChars());
1020 if (decl)
1022 for (unsigned i = 0; i < decl->dim; i++)
1024 Dsymbol *s = (Dsymbol *)decl->data[i];
1026 s->semantic(sc);
1030 #if IN_GCC
1031 if (decl)
1032 if (ident == Id::GNU_attribute)
1033 *sc = sc_save;
1034 #endif
1035 return;
1037 Lnodecl:
1038 if (decl)
1039 error("pragma is missing closing ';'");
1042 int PragmaDeclaration::oneMember(Dsymbol **ps)
1044 *ps = NULL;
1045 return TRUE;
1048 char *PragmaDeclaration::kind()
1050 return "pragma";
1053 void PragmaDeclaration::toObjFile(int multiobj)
1055 if (ident == Id::lib)
1057 assert(args && args->dim == 1);
1059 Expression *e = (Expression *)args->data[0];
1061 assert(e->op == TOKstring);
1063 StringExp *se = (StringExp *)e;
1064 char *name = (char *)mem.malloc(se->len + 1);
1065 memcpy(name, se->string, se->len);
1066 name[se->len] = 0;
1067 obj_includelib(name);
1069 else if (ident == Id::startaddress)
1071 assert(args && args->dim == 1);
1072 Expression *e = (Expression *)args->data[0];
1073 Dsymbol *sa = getDsymbol(e);
1074 FuncDeclaration *f = sa->isFuncDeclaration();
1075 assert(f);
1076 Symbol *s = f->toSymbol();
1077 obj_startaddress(s);
1079 AttribDeclaration::toObjFile(multiobj);
1082 void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1084 buf->printf("pragma (%s", ident->toChars());
1085 if (args && args->dim)
1087 buf->writestring(", ");
1088 argsToCBuffer(buf, args, hgs);
1090 buf->writeByte(')');
1091 AttribDeclaration::toCBuffer(buf, hgs);
1095 /********************************* ConditionalDeclaration ****************************/
1097 ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl)
1098 : AttribDeclaration(decl)
1100 //printf("ConditionalDeclaration::ConditionalDeclaration()\n");
1101 this->condition = condition;
1102 this->elsedecl = elsedecl;
1105 Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s)
1107 ConditionalDeclaration *dd;
1109 assert(!s);
1110 dd = new ConditionalDeclaration(condition->syntaxCopy(),
1111 Dsymbol::arraySyntaxCopy(decl),
1112 Dsymbol::arraySyntaxCopy(elsedecl));
1113 return dd;
1117 int ConditionalDeclaration::oneMember(Dsymbol **ps)
1119 //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition->inc);
1120 if (condition->inc)
1122 Array *d = condition->include(NULL, NULL) ? decl : elsedecl;
1123 return Dsymbol::oneMembers(d, ps);
1125 *ps = NULL;
1126 return TRUE;
1129 void ConditionalDeclaration::emitComment(Scope *sc)
1131 //printf("ConditionalDeclaration::emitComment(sc = %p)\n", sc);
1132 if (condition->inc)
1134 AttribDeclaration::emitComment(sc);
1138 // Decide if 'then' or 'else' code should be included
1140 Array *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd)
1142 //printf("ConditionalDeclaration::include()\n");
1143 assert(condition);
1144 return condition->include(sc, sd) ? decl : elsedecl;
1148 void ConditionalDeclaration::addComment(unsigned char *comment)
1150 /* Because addComment is called by the parser, if we called
1151 * include() it would define a version before it was used.
1152 * But it's no problem to drill down to both decl and elsedecl,
1153 * so that's the workaround.
1156 if (comment)
1158 Array *d = decl;
1160 for (int j = 0; j < 2; j++)
1162 if (d)
1164 for (unsigned i = 0; i < d->dim; i++)
1165 { Dsymbol *s;
1167 s = (Dsymbol *)d->data[i];
1168 //printf("ConditionalDeclaration::addComment %s\n", s->toChars());
1169 s->addComment(comment);
1172 d = elsedecl;
1177 void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1179 condition->toCBuffer(buf, hgs);
1180 if (decl || elsedecl)
1182 buf->writenl();
1183 buf->writeByte('{');
1184 buf->writenl();
1185 if (decl)
1187 for (unsigned i = 0; i < decl->dim; i++)
1189 Dsymbol *s = (Dsymbol *)decl->data[i];
1191 buf->writestring(" ");
1192 s->toCBuffer(buf, hgs);
1195 buf->writeByte('}');
1196 if (elsedecl)
1198 buf->writenl();
1199 buf->writestring("else");
1200 buf->writenl();
1201 buf->writeByte('{');
1202 buf->writenl();
1203 for (unsigned i = 0; i < elsedecl->dim; i++)
1205 Dsymbol *s = (Dsymbol *)elsedecl->data[i];
1207 buf->writestring(" ");
1208 s->toCBuffer(buf, hgs);
1210 buf->writeByte('}');
1213 else
1214 buf->writeByte(':');
1215 buf->writenl();
1218 /***************************** StaticIfDeclaration ****************************/
1220 StaticIfDeclaration::StaticIfDeclaration(Condition *condition,
1221 Array *decl, Array *elsedecl)
1222 : ConditionalDeclaration(condition, decl, elsedecl)
1224 //printf("StaticIfDeclaration::StaticIfDeclaration()\n");
1225 sd = NULL;
1226 addisdone = 0;
1230 Dsymbol *StaticIfDeclaration::syntaxCopy(Dsymbol *s)
1232 StaticIfDeclaration *dd;
1234 assert(!s);
1235 dd = new StaticIfDeclaration(condition->syntaxCopy(),
1236 Dsymbol::arraySyntaxCopy(decl),
1237 Dsymbol::arraySyntaxCopy(elsedecl));
1238 return dd;
1242 int StaticIfDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
1244 /* This is deferred until semantic(), so that
1245 * expressions in the condition can refer to declarations
1246 * in the same scope, such as:
1248 * template Foo(int i)
1250 * const int j = i + 1;
1251 * static if (j == 3)
1252 * const int k;
1255 this->sd = sd;
1256 int m = 0;
1258 if (memnum == 0)
1259 { m = AttribDeclaration::addMember(sc, sd, memnum);
1260 addisdone = 1;
1262 return m;
1266 void StaticIfDeclaration::semantic(Scope *sc)
1268 Array *d = include(sc, sd);
1270 //printf("\tStaticIfDeclaration::semantic '%s'\n",toChars());
1271 if (d)
1273 if (!addisdone)
1274 { AttribDeclaration::addMember(sc, sd, 1);
1275 addisdone = 1;
1278 for (unsigned i = 0; i < d->dim; i++)
1280 Dsymbol *s = (Dsymbol *)d->data[i];
1282 s->semantic(sc);
1287 char *StaticIfDeclaration::kind()
1289 return "static if";
1293 /***************************** CompileDeclaration *****************************/
1295 CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
1296 : AttribDeclaration(NULL)
1298 this->exp = exp;
1299 this->sd = NULL;
1302 Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *s)
1304 //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars());
1305 CompileDeclaration *sc = new CompileDeclaration(loc, exp->syntaxCopy());
1306 return sc;
1309 int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum)
1311 this->sd = sd;
1312 return memnum;
1315 void CompileDeclaration::semantic(Scope *sc)
1317 //printf("CompileDeclaration::semantic()\n");
1318 exp = exp->semantic(sc);
1319 exp = resolveProperties(sc, exp);
1320 exp = exp->optimize(WANTvalue | WANTinterpret);
1321 if (exp->op != TOKstring)
1322 { error("argument to mixin must be a string, not (%s)", exp->toChars());
1323 return;
1325 StringExp *se = (StringExp *)exp;
1326 se = se->toUTF8(sc);
1327 Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
1328 p.loc = loc;
1329 p.nextToken();
1330 decl = p.parseDeclDefs(0);
1331 if (p.token.value != TOKeof)
1333 error("incomplete mixin declaration (%s)", se->toChars());
1336 AttribDeclaration::addMember(sc, sd, 0);
1337 AttribDeclaration::semantic(sc);
1340 void CompileDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1342 buf->writestring("mixin(");
1343 exp->toCBuffer(buf, hgs);
1344 buf->writestring(");");
1345 buf->writenl();