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