comparison dmd2/attrib.c @ 758:f04dde6e882c

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