Mercurial > projects > ldc
comparison dmd/attrib.c @ 1:c53b6e3fe49a trunk
[svn r5] Initial commit. Most things are very rough.
author | lindquist |
---|---|
date | Sat, 01 Sep 2007 21:43:27 +0200 |
parents | |
children | 788401029ecf |
comparison
equal
deleted
inserted
replaced
0:a9e71648e74d | 1:c53b6e3fe49a |
---|---|
1 | |
2 // Compiler implementation of the D programming language | |
3 // Copyright (c) 1999-2007 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 linux | |
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 | |
33 #include "../gen/enums.h" | |
34 | |
35 extern void obj_includelib(char *name); | |
36 | |
37 | |
38 /********************************* AttribDeclaration ****************************/ | |
39 | |
40 AttribDeclaration::AttribDeclaration(Array *decl) | |
41 : Dsymbol() | |
42 { | |
43 this->decl = decl; | |
44 } | |
45 | |
46 Array *AttribDeclaration::include(Scope *sc, ScopeDsymbol *sd) | |
47 { | |
48 return decl; | |
49 } | |
50 | |
51 int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) | |
52 { | |
53 unsigned i; | |
54 int m = 0; | |
55 Array *d = include(sc, sd); | |
56 | |
57 if (d) | |
58 { | |
59 for (i = 0; i < d->dim; i++) | |
60 { Dsymbol *s; | |
61 | |
62 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'\n",toChars()); | |
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 unsigned i; | |
88 Array *d = include(sc, NULL); | |
89 | |
90 if (d) | |
91 { | |
92 for (i = 0; i < d->dim; i++) | |
93 { Dsymbol *s; | |
94 | |
95 s = (Dsymbol *)d->data[i]; | |
96 s->semantic2(sc); | |
97 } | |
98 } | |
99 } | |
100 | |
101 void AttribDeclaration::semantic3(Scope *sc) | |
102 { | |
103 unsigned i; | |
104 Array *d = include(sc, NULL); | |
105 | |
106 if (d) | |
107 { | |
108 for (i = 0; i < d->dim; i++) | |
109 { Dsymbol *s; | |
110 | |
111 s = (Dsymbol *)d->data[i]; | |
112 s->semantic3(sc); | |
113 } | |
114 } | |
115 } | |
116 | |
117 void AttribDeclaration::inlineScan() | |
118 { | |
119 unsigned i; | |
120 Array *d = include(NULL, NULL); | |
121 | |
122 if (d) | |
123 { | |
124 for (i = 0; i < d->dim; i++) | |
125 { Dsymbol *s; | |
126 | |
127 s = (Dsymbol *)d->data[i]; | |
128 //printf("AttribDeclaration::inlineScan %s\n", s->toChars()); | |
129 s->inlineScan(); | |
130 } | |
131 } | |
132 } | |
133 | |
134 void AttribDeclaration::addComment(unsigned char *comment) | |
135 { | |
136 if (comment) | |
137 { | |
138 unsigned i; | |
139 Array *d = include(NULL, NULL); | |
140 | |
141 if (d) | |
142 { | |
143 for (i = 0; i < d->dim; i++) | |
144 { Dsymbol *s; | |
145 | |
146 s = (Dsymbol *)d->data[i]; | |
147 //printf("AttribDeclaration::addComment %s\n", s->toChars()); | |
148 s->addComment(comment); | |
149 } | |
150 } | |
151 } | |
152 } | |
153 | |
154 void AttribDeclaration::emitComment(Scope *sc) | |
155 { | |
156 //printf("AttribDeclaration::emitComment(sc = %p)\n", sc); | |
157 | |
158 /* If generating doc comment, skip this because if we're inside | |
159 * a template, then include(NULL, NULL) will fail. | |
160 */ | |
161 // if (sc->docbuf) | |
162 // return; | |
163 | |
164 unsigned i; | |
165 Array *d = include(NULL, NULL); | |
166 | |
167 if (d) | |
168 { | |
169 for (i = 0; i < d->dim; i++) | |
170 { Dsymbol *s; | |
171 | |
172 s = (Dsymbol *)d->data[i]; | |
173 //printf("AttribDeclaration::emitComment %s\n", s->toChars()); | |
174 s->emitComment(sc); | |
175 } | |
176 } | |
177 } | |
178 | |
179 void AttribDeclaration::toObjFile() | |
180 { | |
181 unsigned i; | |
182 Array *d = include(NULL, NULL); | |
183 | |
184 if (d) | |
185 { | |
186 for (i = 0; i < d->dim; i++) | |
187 { Dsymbol *s; | |
188 | |
189 s = (Dsymbol *)d->data[i]; | |
190 s->toObjFile(); | |
191 } | |
192 } | |
193 } | |
194 | |
195 int AttribDeclaration::hasPointers() | |
196 { | |
197 Array *d = include(NULL, NULL); | |
198 | |
199 if (d) | |
200 { | |
201 for (size_t i = 0; i < d->dim; i++) | |
202 { | |
203 Dsymbol *s = (Dsymbol *)d->data[i]; | |
204 if (s->hasPointers()) | |
205 return 1; | |
206 } | |
207 } | |
208 return 0; | |
209 } | |
210 | |
211 char *AttribDeclaration::kind() | |
212 { | |
213 return "attribute"; | |
214 } | |
215 | |
216 int AttribDeclaration::oneMember(Dsymbol **ps) | |
217 { | |
218 Array *d = include(NULL, NULL); | |
219 | |
220 return Dsymbol::oneMembers(d, ps); | |
221 } | |
222 | |
223 void AttribDeclaration::checkCtorConstInit() | |
224 { | |
225 unsigned i; | |
226 Array *d = include(NULL, NULL); | |
227 | |
228 if (d) | |
229 { | |
230 for (i = 0; i < d->dim; i++) | |
231 { Dsymbol *s; | |
232 | |
233 s = (Dsymbol *)d->data[i]; | |
234 s->checkCtorConstInit(); | |
235 } | |
236 } | |
237 } | |
238 | |
239 /**************************************** | |
240 */ | |
241 | |
242 void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses) | |
243 { unsigned i; | |
244 Array *d = include(NULL, NULL); | |
245 | |
246 if (d) | |
247 { | |
248 for (i = 0; i < d->dim; i++) | |
249 { Dsymbol *s; | |
250 | |
251 s = (Dsymbol *)d->data[i]; | |
252 s->addLocalClass(aclasses); | |
253 } | |
254 } | |
255 } | |
256 | |
257 | |
258 void AttribDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
259 { | |
260 if (decl) | |
261 { | |
262 buf->writenl(); | |
263 buf->writeByte('{'); | |
264 buf->writenl(); | |
265 for (unsigned i = 0; i < decl->dim; i++) | |
266 { | |
267 Dsymbol *s = (Dsymbol *)decl->data[i]; | |
268 | |
269 buf->writestring(" "); | |
270 s->toCBuffer(buf, hgs); | |
271 } | |
272 buf->writeByte('}'); | |
273 } | |
274 else | |
275 buf->writeByte(';'); | |
276 buf->writenl(); | |
277 } | |
278 | |
279 /************************* StorageClassDeclaration ****************************/ | |
280 | |
281 StorageClassDeclaration::StorageClassDeclaration(unsigned stc, Array *decl) | |
282 : AttribDeclaration(decl) | |
283 { | |
284 this->stc = stc; | |
285 } | |
286 | |
287 Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s) | |
288 { | |
289 StorageClassDeclaration *scd; | |
290 | |
291 assert(!s); | |
292 scd = new StorageClassDeclaration(stc, Dsymbol::arraySyntaxCopy(decl)); | |
293 return scd; | |
294 } | |
295 | |
296 void StorageClassDeclaration::semantic(Scope *sc) | |
297 { | |
298 if (decl) | |
299 { unsigned stc_save = sc->stc; | |
300 | |
301 if (stc & (STCauto | STCscope | STCstatic | STCextern)) | |
302 sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern); | |
303 sc->stc |= stc; | |
304 for (unsigned i = 0; i < decl->dim; i++) | |
305 { | |
306 Dsymbol *s = (Dsymbol *)decl->data[i]; | |
307 | |
308 s->semantic(sc); | |
309 } | |
310 sc->stc = stc_save; | |
311 } | |
312 else | |
313 sc->stc = stc; | |
314 } | |
315 | |
316 void StorageClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
317 { | |
318 struct SCstring | |
319 { | |
320 int stc; | |
321 enum TOK tok; | |
322 }; | |
323 | |
324 static SCstring table[] = | |
325 { | |
326 { STCauto, TOKauto }, | |
327 { STCscope, TOKscope }, | |
328 { STCstatic, TOKstatic }, | |
329 { STCextern, TOKextern }, | |
330 { STCconst, TOKconst }, | |
331 { STCfinal, TOKfinal }, | |
332 { STCabstract, TOKabstract }, | |
333 { STCsynchronized, TOKsynchronized }, | |
334 { STCdeprecated, TOKdeprecated }, | |
335 { STCoverride, TOKoverride }, | |
336 }; | |
337 | |
338 int written = 0; | |
339 for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++) | |
340 { | |
341 if (stc & table[i].stc) | |
342 { | |
343 if (written) | |
344 buf->writeByte(' '); | |
345 written = 1; | |
346 buf->writestring(Token::toChars(table[i].tok)); | |
347 } | |
348 } | |
349 | |
350 AttribDeclaration::toCBuffer(buf, hgs); | |
351 } | |
352 | |
353 /********************************* LinkDeclaration ****************************/ | |
354 | |
355 LinkDeclaration::LinkDeclaration(enum LINK p, Array *decl) | |
356 : AttribDeclaration(decl) | |
357 { | |
358 //printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl); | |
359 linkage = p; | |
360 } | |
361 | |
362 Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s) | |
363 { | |
364 LinkDeclaration *ld; | |
365 | |
366 assert(!s); | |
367 ld = new LinkDeclaration(linkage, Dsymbol::arraySyntaxCopy(decl)); | |
368 return ld; | |
369 } | |
370 | |
371 void LinkDeclaration::semantic(Scope *sc) | |
372 { | |
373 //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl); | |
374 if (decl) | |
375 { enum LINK linkage_save = sc->linkage; | |
376 | |
377 sc->linkage = linkage; | |
378 for (unsigned i = 0; i < decl->dim; i++) | |
379 { | |
380 Dsymbol *s = (Dsymbol *)decl->data[i]; | |
381 | |
382 s->semantic(sc); | |
383 } | |
384 sc->linkage = linkage_save; | |
385 } | |
386 else | |
387 { | |
388 sc->linkage = linkage; | |
389 } | |
390 } | |
391 | |
392 void LinkDeclaration::semantic3(Scope *sc) | |
393 { | |
394 //printf("LinkDeclaration::semantic3(linkage = %d, decl = %p)\n", linkage, decl); | |
395 if (decl) | |
396 { enum LINK linkage_save = sc->linkage; | |
397 | |
398 sc->linkage = linkage; | |
399 for (unsigned i = 0; i < decl->dim; i++) | |
400 { | |
401 Dsymbol *s = (Dsymbol *)decl->data[i]; | |
402 | |
403 s->semantic3(sc); | |
404 } | |
405 sc->linkage = linkage_save; | |
406 } | |
407 else | |
408 { | |
409 sc->linkage = linkage; | |
410 } | |
411 } | |
412 | |
413 void LinkDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
414 { char *p; | |
415 | |
416 switch (linkage) | |
417 { | |
418 case LINKd: p = "D"; break; | |
419 case LINKc: p = "C"; break; | |
420 case LINKcpp: p = "C++"; break; | |
421 case LINKwindows: p = "Windows"; break; | |
422 case LINKpascal: p = "Pascal"; break; | |
423 default: | |
424 assert(0); | |
425 break; | |
426 } | |
427 buf->writestring("extern ("); | |
428 buf->writestring(p); | |
429 buf->writestring(") "); | |
430 AttribDeclaration::toCBuffer(buf, hgs); | |
431 } | |
432 | |
433 char *LinkDeclaration::toChars() | |
434 { | |
435 return "extern ()"; | |
436 } | |
437 | |
438 /********************************* ProtDeclaration ****************************/ | |
439 | |
440 ProtDeclaration::ProtDeclaration(enum PROT p, Array *decl) | |
441 : AttribDeclaration(decl) | |
442 { | |
443 protection = p; | |
444 //printf("decl = %p\n", decl); | |
445 } | |
446 | |
447 Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s) | |
448 { | |
449 ProtDeclaration *pd; | |
450 | |
451 assert(!s); | |
452 pd = new ProtDeclaration(protection, Dsymbol::arraySyntaxCopy(decl)); | |
453 return pd; | |
454 } | |
455 | |
456 void ProtDeclaration::semantic(Scope *sc) | |
457 { | |
458 if (decl) | |
459 { enum PROT protection_save = sc->protection; | |
460 int explicitProtection_save = sc->explicitProtection; | |
461 | |
462 sc->protection = protection; | |
463 sc->explicitProtection = 1; | |
464 for (unsigned i = 0; i < decl->dim; i++) | |
465 { | |
466 Dsymbol *s = (Dsymbol *)decl->data[i]; | |
467 | |
468 s->semantic(sc); | |
469 } | |
470 sc->protection = protection_save; | |
471 sc->explicitProtection = explicitProtection_save; | |
472 } | |
473 else | |
474 { sc->protection = protection; | |
475 sc->explicitProtection = 1; | |
476 } | |
477 } | |
478 | |
479 void ProtDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
480 { char *p; | |
481 | |
482 switch (protection) | |
483 { | |
484 case PROTprivate: p = "private"; break; | |
485 case PROTpackage: p = "package"; break; | |
486 case PROTprotected: p = "protected"; break; | |
487 case PROTpublic: p = "public"; break; | |
488 case PROTexport: p = "export"; break; | |
489 default: | |
490 assert(0); | |
491 break; | |
492 } | |
493 buf->writestring(p); | |
494 AttribDeclaration::toCBuffer(buf, hgs); | |
495 } | |
496 | |
497 /********************************* AlignDeclaration ****************************/ | |
498 | |
499 AlignDeclaration::AlignDeclaration(unsigned sa, Array *decl) | |
500 : AttribDeclaration(decl) | |
501 { | |
502 salign = sa; | |
503 } | |
504 | |
505 Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s) | |
506 { | |
507 AlignDeclaration *ad; | |
508 | |
509 assert(!s); | |
510 ad = new AlignDeclaration(salign, Dsymbol::arraySyntaxCopy(decl)); | |
511 return ad; | |
512 } | |
513 | |
514 void AlignDeclaration::semantic(Scope *sc) | |
515 { | |
516 //printf("\tAlignDeclaration::semantic '%s'\n",toChars()); | |
517 if (decl) | |
518 { unsigned salign_save = sc->structalign; | |
519 | |
520 sc->structalign = salign; | |
521 for (unsigned i = 0; i < decl->dim; i++) | |
522 { | |
523 Dsymbol *s = (Dsymbol *)decl->data[i]; | |
524 | |
525 s->semantic(sc); | |
526 } | |
527 sc->structalign = salign_save; | |
528 } | |
529 else | |
530 sc->structalign = salign; | |
531 } | |
532 | |
533 | |
534 void AlignDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
535 { | |
536 buf->printf("align (%d)", salign); | |
537 AttribDeclaration::toCBuffer(buf, hgs); | |
538 } | |
539 | |
540 /********************************* AnonDeclaration ****************************/ | |
541 | |
542 AnonDeclaration::AnonDeclaration(Loc loc, int isunion, Array *decl) | |
543 : AttribDeclaration(decl) | |
544 { | |
545 this->loc = loc; | |
546 this->isunion = isunion; | |
547 this->scope = NULL; | |
548 this->sem = 0; | |
549 } | |
550 | |
551 Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s) | |
552 { | |
553 AnonDeclaration *ad; | |
554 | |
555 assert(!s); | |
556 ad = new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl)); | |
557 return ad; | |
558 } | |
559 | |
560 void AnonDeclaration::semantic(Scope *sc) | |
561 { | |
562 //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this); | |
563 | |
564 Scope *scx = NULL; | |
565 if (scope) | |
566 { sc = scope; | |
567 scx = scope; | |
568 scope = NULL; | |
569 } | |
570 | |
571 assert(sc->parent); | |
572 | |
573 Dsymbol *parent = sc->parent->pastMixin(); | |
574 AggregateDeclaration *ad = parent->isAggregateDeclaration(); | |
575 | |
576 if (!ad || (!ad->isStructDeclaration() && !ad->isClassDeclaration())) | |
577 { | |
578 error("can only be a part of an aggregate"); | |
579 return; | |
580 } | |
581 | |
582 if (decl) | |
583 { | |
584 AnonymousAggregateDeclaration aad; | |
585 int adisunion; | |
586 | |
587 if (sc->anonAgg) | |
588 { ad = sc->anonAgg; | |
589 adisunion = sc->inunion; | |
590 } | |
591 else | |
592 adisunion = ad->isUnionDeclaration() != NULL; | |
593 | |
594 // printf("\tsc->anonAgg = %p\n", sc->anonAgg); | |
595 // printf("\tad = %p\n", ad); | |
596 // printf("\taad = %p\n", &aad); | |
597 | |
598 sc = sc->push(); | |
599 sc->anonAgg = &aad; | |
600 sc->stc &= ~(STCauto | STCscope | STCstatic); | |
601 sc->inunion = isunion; | |
602 sc->offset = 0; | |
603 sc->flags = 0; | |
604 aad.structalign = sc->structalign; | |
605 aad.parent = ad; | |
606 | |
607 for (unsigned i = 0; i < decl->dim; i++) | |
608 { | |
609 Dsymbol *s = (Dsymbol *)decl->data[i]; | |
610 | |
611 s->semantic(sc); | |
612 if (isunion) | |
613 sc->offset = 0; | |
614 if (aad.sizeok == 2) | |
615 { | |
616 break; | |
617 } | |
618 } | |
619 sc = sc->pop(); | |
620 | |
621 // If failed due to forward references, unwind and try again later | |
622 if (aad.sizeok == 2) | |
623 { | |
624 ad->sizeok = 2; | |
625 //printf("\tsetting ad->sizeok %p to 2\n", ad); | |
626 if (!sc->anonAgg) | |
627 { | |
628 scope = scx ? scx : new Scope(*sc); | |
629 scope->setNoFree(); | |
630 scope->module->addDeferredSemantic(this); | |
631 } | |
632 //printf("\tforward reference %p\n", this); | |
633 return; | |
634 } | |
635 if (sem == 0) | |
636 { Module::dprogress++; | |
637 sem = 1; | |
638 //printf("\tcompleted %p\n", this); | |
639 } | |
640 else | |
641 ;//printf("\talready completed %p\n", this); | |
642 | |
643 // 0 sized structs are set to 1 byte | |
644 if (aad.structsize == 0) | |
645 { | |
646 aad.structsize = 1; | |
647 aad.alignsize = 1; | |
648 } | |
649 | |
650 // Align size of anonymous aggregate | |
651 //printf("aad.structalign = %d, aad.alignsize = %d, sc->offset = %d\n", aad.structalign, aad.alignsize, sc->offset); | |
652 ad->alignmember(aad.structalign, aad.alignsize, &sc->offset); | |
653 //ad->structsize = sc->offset; | |
654 //printf("sc->offset = %d\n", sc->offset); | |
655 | |
656 // Add members of aad to ad | |
657 //printf("\tadding members of aad to '%s'\n", ad->toChars()); | |
658 for (unsigned i = 0; i < aad.fields.dim; i++) | |
659 { | |
660 VarDeclaration *v = (VarDeclaration *)aad.fields.data[i]; | |
661 | |
662 v->offset += sc->offset; | |
663 ad->fields.push(v); | |
664 } | |
665 | |
666 // Add size of aad to ad | |
667 if (adisunion) | |
668 { | |
669 if (aad.structsize > ad->structsize) | |
670 ad->structsize = aad.structsize; | |
671 sc->offset = 0; | |
672 } | |
673 else | |
674 { | |
675 ad->structsize = sc->offset + aad.structsize; | |
676 sc->offset = ad->structsize; | |
677 } | |
678 | |
679 if (ad->alignsize < aad.alignsize) | |
680 ad->alignsize = aad.alignsize; | |
681 } | |
682 } | |
683 | |
684 | |
685 void AnonDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
686 { | |
687 buf->printf(isunion ? "union" : "struct"); | |
688 buf->writestring("\n{\n"); | |
689 if (decl) | |
690 { | |
691 for (unsigned i = 0; i < decl->dim; i++) | |
692 { | |
693 Dsymbol *s = (Dsymbol *)decl->data[i]; | |
694 | |
695 //buf->writestring(" "); | |
696 s->toCBuffer(buf, hgs); | |
697 } | |
698 } | |
699 buf->writestring("}\n"); | |
700 } | |
701 | |
702 char *AnonDeclaration::kind() | |
703 { | |
704 return (char *)(isunion ? "anonymous union" : "anonymous struct"); | |
705 } | |
706 | |
707 /********************************* PragmaDeclaration ****************************/ | |
708 | |
709 PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl) | |
710 : AttribDeclaration(decl) | |
711 { | |
712 this->loc = loc; | |
713 this->ident = ident; | |
714 this->args = args; | |
715 } | |
716 | |
717 Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s) | |
718 { | |
719 PragmaDeclaration *pd; | |
720 | |
721 assert(!s); | |
722 pd = new PragmaDeclaration(loc, ident, | |
723 Expression::arraySyntaxCopy(args), Dsymbol::arraySyntaxCopy(decl)); | |
724 return pd; | |
725 } | |
726 | |
727 void PragmaDeclaration::semantic(Scope *sc) | |
728 { // Should be merged with PragmaStatement | |
729 | |
730 #if IN_LLVM | |
731 int llvm_internal = 0; | |
732 char* llvm_str1 = NULL; | |
733 | |
734 #endif | |
735 | |
736 //printf("\tPragmaDeclaration::semantic '%s'\n",toChars()); | |
737 if (ident == Id::msg) | |
738 { | |
739 if (args) | |
740 { | |
741 for (size_t i = 0; i < args->dim; i++) | |
742 { | |
743 Expression *e = (Expression *)args->data[i]; | |
744 | |
745 e = e->semantic(sc); | |
746 e = e->optimize(WANTvalue | WANTinterpret); | |
747 if (e->op == TOKstring) | |
748 { | |
749 StringExp *se = (StringExp *)e; | |
750 fprintf(stdmsg, "%.*s", (int)se->len, se->string); | |
751 } | |
752 else | |
753 error("string expected for message, not '%s'", e->toChars()); | |
754 } | |
755 fprintf(stdmsg, "\n"); | |
756 } | |
757 goto Lnodecl; | |
758 } | |
759 else if (ident == Id::lib) | |
760 { | |
761 if (!args || args->dim != 1) | |
762 error("string expected for library name"); | |
763 else | |
764 { | |
765 Expression *e = (Expression *)args->data[0]; | |
766 | |
767 e = e->semantic(sc); | |
768 e = e->optimize(WANTvalue | WANTinterpret); | |
769 args->data[0] = (void *)e; | |
770 if (e->op != TOKstring) | |
771 error("string expected for library name, not '%s'", e->toChars()); | |
772 else if (global.params.verbose) | |
773 { | |
774 StringExp *se = (StringExp *)e; | |
775 char *name = (char *)mem.malloc(se->len + 1); | |
776 memcpy(name, se->string, se->len); | |
777 name[se->len] = 0; | |
778 printf("library %s\n", name); | |
779 mem.free(name); | |
780 } | |
781 } | |
782 goto Lnodecl; | |
783 } | |
784 #if IN_GCC | |
785 else if (ident == Id::GNU_asm) | |
786 { | |
787 if (! args || args->dim != 2) | |
788 error("identifier and string expected for asm name"); | |
789 else | |
790 { | |
791 Expression *e; | |
792 Declaration *d = NULL; | |
793 StringExp *s = NULL; | |
794 | |
795 e = (Expression *)args->data[0]; | |
796 e = e->semantic(sc); | |
797 if (e->op == TOKvar) | |
798 { | |
799 d = ((VarExp *)e)->var; | |
800 if (! d->isFuncDeclaration() && ! d->isVarDeclaration()) | |
801 d = NULL; | |
802 } | |
803 if (!d) | |
804 error("first argument of GNU_asm must be a function or variable declaration"); | |
805 | |
806 e = (Expression *)args->data[1]; | |
807 e = e->semantic(sc); | |
808 e = e->optimize(WANTvalue); | |
809 if (e->op == TOKstring && ((StringExp *)e)->sz == 1) | |
810 s = ((StringExp *)e); | |
811 else | |
812 error("second argument of GNU_asm must be a char string"); | |
813 | |
814 if (d && s) | |
815 d->c_ident = Lexer::idPool((char*) s->string); | |
816 } | |
817 goto Lnodecl; | |
818 } | |
819 #endif | |
820 #if IN_LLVM | |
821 else if (ident == Id::LLVM_internal) | |
822 { | |
823 if (!args || args->dim < 1 || args->dim > 2) | |
824 error("needs 1-3 parameters"); | |
825 else if (!decl || decl->dim < 1) | |
826 error("must apply to at least one declaration"); | |
827 else | |
828 { | |
829 Expression *e; | |
830 StringExp *s = NULL; | |
831 | |
832 e = (Expression *)args->data[0]; | |
833 e = e->semantic(sc); | |
834 e = e->optimize(WANTvalue); | |
835 if (e->op == TOKstring && (s = (StringExp *)e)) | |
836 { | |
837 char* str = (char*)s->string; | |
838 if (strcmp(str,"intrinsic")==0) { | |
839 llvm_internal = LLVMintrinsic; | |
840 assert(args->dim == 2); | |
841 } | |
842 else if (strcmp(str,"null")==0) { | |
843 llvm_internal = LLVMnull; | |
844 assert(args->dim == 1); | |
845 } | |
846 else if (strcmp(str,"mangle")==0) { | |
847 llvm_internal = LLVMmangle; | |
848 assert(args->dim == 2); | |
849 } | |
850 else if (strcmp(str,"bind")==0) { | |
851 llvm_internal = LLVMbind; | |
852 assert(args->dim == 2); | |
853 } | |
854 else { | |
855 error("unknown pragma command: %s", str); | |
856 } | |
857 } | |
858 else | |
859 error("1st argument must be a string"); | |
860 | |
861 if (llvm_internal) | |
862 switch (llvm_internal) | |
863 { | |
864 case LLVMintrinsic: | |
865 case LLVMmangle: | |
866 case LLVMbind: | |
867 e = (Expression *)args->data[1]; | |
868 e = e->semantic(sc); | |
869 e = e->optimize(WANTvalue); | |
870 if (e->op == TOKstring && (s = (StringExp *)e)) { | |
871 llvm_str1 = (char*)s->string; | |
872 } | |
873 else | |
874 error("2nd argument must be a string"); | |
875 break; | |
876 | |
877 case LLVMnull: | |
878 break; | |
879 | |
880 default: | |
881 assert(0); | |
882 } | |
883 } | |
884 } | |
885 #endif | |
886 else | |
887 error("unrecognized pragma(%s)", ident->toChars()); | |
888 | |
889 if (decl) | |
890 { | |
891 for (unsigned i = 0; i < decl->dim; i++) | |
892 { | |
893 Dsymbol *s = (Dsymbol *)decl->data[i]; | |
894 | |
895 s->semantic(sc); | |
896 | |
897 #if IN_LLVM | |
898 if (llvm_internal) | |
899 { | |
900 switch(llvm_internal) | |
901 { | |
902 case LLVMintrinsic: | |
903 case LLVMmangle: | |
904 if (FuncDeclaration* fd = s->isFuncDeclaration()) { | |
905 fd->llvmInternal = llvm_internal; | |
906 fd->llvmInternal1 = llvm_str1; | |
907 } | |
908 else { | |
909 error("may only be used on function declarations"); | |
910 assert(0); | |
911 } | |
912 break; | |
913 | |
914 case LLVMnull: | |
915 if (StaticCtorDeclaration* sd = s->isStaticCtorDeclaration()) { | |
916 sd->llvmInternal = llvm_internal; | |
917 } | |
918 else { | |
919 error("may only be used on static constructors"); | |
920 assert(0); | |
921 } | |
922 break; | |
923 | |
924 case LLVMbind: | |
925 if (VarDeclaration* vd = s->isVarDeclaration()) { | |
926 vd->llvmInternal = llvm_internal; | |
927 vd->llvmInternal1 = llvm_str1; | |
928 } | |
929 else { | |
930 error("may only be used on var declarations"); | |
931 assert(0); | |
932 } | |
933 break; | |
934 | |
935 default: | |
936 assert(0 && "invalid LLVM_internal pragma got through :/"); | |
937 } | |
938 } | |
939 | |
940 #endif | |
941 } | |
942 } | |
943 return; | |
944 | |
945 Lnodecl: | |
946 if (decl) | |
947 error("pragma is missing closing ';'"); | |
948 } | |
949 | |
950 int PragmaDeclaration::oneMember(Dsymbol **ps) | |
951 { | |
952 *ps = NULL; | |
953 return TRUE; | |
954 } | |
955 | |
956 char *PragmaDeclaration::kind() | |
957 { | |
958 return "pragma"; | |
959 } | |
960 | |
961 void PragmaDeclaration::toObjFile() | |
962 { | |
963 if (ident == Id::lib) | |
964 { | |
965 assert(args && args->dim == 1); | |
966 | |
967 Expression *e = (Expression *)args->data[0]; | |
968 | |
969 assert(e->op == TOKstring); | |
970 | |
971 StringExp *se = (StringExp *)e; | |
972 char *name = (char *)mem.malloc(se->len + 1); | |
973 memcpy(name, se->string, se->len); | |
974 name[se->len] = 0; | |
975 obj_includelib(name); | |
976 } | |
977 AttribDeclaration::toObjFile(); | |
978 } | |
979 | |
980 void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
981 { | |
982 buf->printf("pragma(%s", ident->toChars()); | |
983 if (args) | |
984 { | |
985 for (size_t i = 0; i < args->dim; i++) | |
986 { | |
987 Expression *e = (Expression *)args->data[i]; | |
988 | |
989 buf->writestring(", "); | |
990 e->toCBuffer(buf, hgs); | |
991 } | |
992 } | |
993 buf->writestring(")"); | |
994 AttribDeclaration::toCBuffer(buf, hgs); | |
995 } | |
996 | |
997 | |
998 /********************************* ConditionalDeclaration ****************************/ | |
999 | |
1000 ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl) | |
1001 : AttribDeclaration(decl) | |
1002 { | |
1003 //printf("ConditionalDeclaration::ConditionalDeclaration()\n"); | |
1004 this->condition = condition; | |
1005 this->elsedecl = elsedecl; | |
1006 } | |
1007 | |
1008 Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s) | |
1009 { | |
1010 ConditionalDeclaration *dd; | |
1011 | |
1012 assert(!s); | |
1013 dd = new ConditionalDeclaration(condition->syntaxCopy(), | |
1014 Dsymbol::arraySyntaxCopy(decl), | |
1015 Dsymbol::arraySyntaxCopy(elsedecl)); | |
1016 return dd; | |
1017 } | |
1018 | |
1019 | |
1020 int ConditionalDeclaration::oneMember(Dsymbol **ps) | |
1021 { | |
1022 //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition->inc); | |
1023 if (condition->inc) | |
1024 { | |
1025 Array *d = condition->include(NULL, NULL) ? decl : elsedecl; | |
1026 return Dsymbol::oneMembers(d, ps); | |
1027 } | |
1028 *ps = NULL; | |
1029 return TRUE; | |
1030 } | |
1031 | |
1032 void ConditionalDeclaration::emitComment(Scope *sc) | |
1033 { | |
1034 //printf("ConditionalDeclaration::emitComment(sc = %p)\n", sc); | |
1035 if (condition->inc) | |
1036 { | |
1037 AttribDeclaration::emitComment(sc); | |
1038 } | |
1039 } | |
1040 | |
1041 // Decide if 'then' or 'else' code should be included | |
1042 | |
1043 Array *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd) | |
1044 { | |
1045 //printf("ConditionalDeclaration::include()\n"); | |
1046 assert(condition); | |
1047 return condition->include(sc, sd) ? decl : elsedecl; | |
1048 } | |
1049 | |
1050 | |
1051 void ConditionalDeclaration::addComment(unsigned char *comment) | |
1052 { | |
1053 /* Because addComment is called by the parser, if we called | |
1054 * include() it would define a version before it was used. | |
1055 * But it's no problem to drill down to both decl and elsedecl, | |
1056 * so that's the workaround. | |
1057 */ | |
1058 | |
1059 if (comment) | |
1060 { | |
1061 Array *d = decl; | |
1062 | |
1063 for (int j = 0; j < 2; j++) | |
1064 { | |
1065 if (d) | |
1066 { | |
1067 for (unsigned i = 0; i < d->dim; i++) | |
1068 { Dsymbol *s; | |
1069 | |
1070 s = (Dsymbol *)d->data[i]; | |
1071 //printf("ConditionalDeclaration::addComment %s\n", s->toChars()); | |
1072 s->addComment(comment); | |
1073 } | |
1074 } | |
1075 d = elsedecl; | |
1076 } | |
1077 } | |
1078 } | |
1079 | |
1080 void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1081 { | |
1082 condition->toCBuffer(buf, hgs); | |
1083 if (decl || elsedecl) | |
1084 { | |
1085 buf->writenl(); | |
1086 buf->writeByte('{'); | |
1087 buf->writenl(); | |
1088 if (decl) | |
1089 { | |
1090 for (unsigned i = 0; i < decl->dim; i++) | |
1091 { | |
1092 Dsymbol *s = (Dsymbol *)decl->data[i]; | |
1093 | |
1094 buf->writestring(" "); | |
1095 s->toCBuffer(buf, hgs); | |
1096 } | |
1097 } | |
1098 buf->writeByte('}'); | |
1099 if (elsedecl) | |
1100 { | |
1101 buf->writenl(); | |
1102 buf->writestring("else"); | |
1103 buf->writenl(); | |
1104 buf->writeByte('{'); | |
1105 buf->writenl(); | |
1106 for (unsigned i = 0; i < elsedecl->dim; i++) | |
1107 { | |
1108 Dsymbol *s = (Dsymbol *)elsedecl->data[i]; | |
1109 | |
1110 buf->writestring(" "); | |
1111 s->toCBuffer(buf, hgs); | |
1112 } | |
1113 buf->writeByte('}'); | |
1114 } | |
1115 } | |
1116 else | |
1117 buf->writeByte(':'); | |
1118 buf->writenl(); | |
1119 } | |
1120 | |
1121 /***************************** StaticIfDeclaration ****************************/ | |
1122 | |
1123 StaticIfDeclaration::StaticIfDeclaration(Condition *condition, | |
1124 Array *decl, Array *elsedecl) | |
1125 : ConditionalDeclaration(condition, decl, elsedecl) | |
1126 { | |
1127 //printf("StaticIfDeclaration::StaticIfDeclaration()\n"); | |
1128 sd = NULL; | |
1129 addisdone = 0; | |
1130 } | |
1131 | |
1132 | |
1133 Dsymbol *StaticIfDeclaration::syntaxCopy(Dsymbol *s) | |
1134 { | |
1135 StaticIfDeclaration *dd; | |
1136 | |
1137 assert(!s); | |
1138 dd = new StaticIfDeclaration(condition->syntaxCopy(), | |
1139 Dsymbol::arraySyntaxCopy(decl), | |
1140 Dsymbol::arraySyntaxCopy(elsedecl)); | |
1141 return dd; | |
1142 } | |
1143 | |
1144 | |
1145 int StaticIfDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) | |
1146 { | |
1147 /* This is deferred until semantic(), so that | |
1148 * expressions in the condition can refer to declarations | |
1149 * in the same scope, such as: | |
1150 * | |
1151 * template Foo(int i) | |
1152 * { | |
1153 * const int j = i + 1; | |
1154 * static if (j == 3) | |
1155 * const int k; | |
1156 * } | |
1157 */ | |
1158 this->sd = sd; | |
1159 int m = 0; | |
1160 | |
1161 if (memnum == 0) | |
1162 { m = AttribDeclaration::addMember(sc, sd, memnum); | |
1163 addisdone = 1; | |
1164 } | |
1165 return m; | |
1166 } | |
1167 | |
1168 | |
1169 void StaticIfDeclaration::semantic(Scope *sc) | |
1170 { | |
1171 Array *d = include(sc, sd); | |
1172 | |
1173 //printf("\tStaticIfDeclaration::semantic '%s'\n",toChars()); | |
1174 if (d) | |
1175 { | |
1176 if (!addisdone) | |
1177 { AttribDeclaration::addMember(sc, sd, 1); | |
1178 addisdone = 1; | |
1179 } | |
1180 | |
1181 for (unsigned i = 0; i < d->dim; i++) | |
1182 { | |
1183 Dsymbol *s = (Dsymbol *)d->data[i]; | |
1184 | |
1185 s->semantic(sc); | |
1186 } | |
1187 } | |
1188 } | |
1189 | |
1190 char *StaticIfDeclaration::kind() | |
1191 { | |
1192 return "static if"; | |
1193 } | |
1194 | |
1195 | |
1196 /***************************** CompileDeclaration *****************************/ | |
1197 | |
1198 CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp) | |
1199 : AttribDeclaration(NULL) | |
1200 { | |
1201 this->exp = exp; | |
1202 this->sd = NULL; | |
1203 } | |
1204 | |
1205 Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *s) | |
1206 { | |
1207 //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars()); | |
1208 CompileDeclaration *sc = new CompileDeclaration(loc, exp->syntaxCopy()); | |
1209 return sc; | |
1210 } | |
1211 | |
1212 int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) | |
1213 { | |
1214 this->sd = sd; | |
1215 return memnum; | |
1216 } | |
1217 | |
1218 void CompileDeclaration::semantic(Scope *sc) | |
1219 { | |
1220 //printf("CompileDeclaration::semantic()\n"); | |
1221 exp = exp->semantic(sc); | |
1222 exp = resolveProperties(sc, exp); | |
1223 exp = exp->optimize(WANTvalue | WANTinterpret); | |
1224 if (exp->op != TOKstring) | |
1225 { error("argument to mixin must be a string, not (%s)", exp->toChars()); | |
1226 return; | |
1227 } | |
1228 StringExp *se = (StringExp *)exp; | |
1229 se = se->toUTF8(sc); | |
1230 Parser p(sc->module, (unsigned char *)se->string, se->len, 0); | |
1231 p.loc = loc; | |
1232 p.nextToken(); | |
1233 decl = p.parseDeclDefs(0); | |
1234 if (p.token.value != TOKeof) | |
1235 { | |
1236 error("incomplete mixin declaration (%s)", se->toChars()); | |
1237 } | |
1238 | |
1239 AttribDeclaration::addMember(sc, sd, 0); | |
1240 AttribDeclaration::semantic(sc); | |
1241 } | |
1242 | |
1243 void CompileDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1244 { | |
1245 buf->writestring("mixin("); | |
1246 exp->toCBuffer(buf, hgs); | |
1247 buf->writestring(");"); | |
1248 buf->writenl(); | |
1249 } |