Mercurial > projects > ldc
annotate dmd/attrib.c @ 86:fd32135dca3e trunk
[svn r90] Major updates to the gen directory. Redesigned the 'elem' struct. Much more... !!!
Lots of bugfixes.
Added support for special foreach on strings.
Added std.array, std.utf, std.ctype and std.uni to phobos.
Changed all the .c files in the gen dir to .cpp (it *is* C++ after all)
author | lindquist |
---|---|
date | Sat, 03 Nov 2007 14:44:58 +0100 |
parents | eb379601d445 |
children | 61615fa85940 |
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 } | |
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
|
866 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
|
867 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
|
868 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
|
869 } |
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
|
870 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
|
871 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
|
872 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
|
873 } |
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
|
874 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
|
875 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
|
876 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
|
877 } |
73 | 878 else if (strcmp(str,"notypeinfo")==0) { |
879 llvm_internal = LLVMnotypeinfo; | |
880 assert(args->dim == 1); | |
881 } | |
1 | 882 else { |
883 error("unknown pragma command: %s", str); | |
884 } | |
885 } | |
886 else | |
887 error("1st argument must be a string"); | |
73 | 888 |
1 | 889 if (llvm_internal) |
890 switch (llvm_internal) | |
891 { | |
892 case LLVMintrinsic: | |
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
|
893 case LLVMva_intrinsic: |
1 | 894 e = (Expression *)args->data[1]; |
895 e = e->semantic(sc); | |
896 e = e->optimize(WANTvalue); | |
897 if (e->op == TOKstring && (s = (StringExp *)e)) { | |
898 llvm_str1 = (char*)s->string; | |
899 } | |
900 else | |
901 error("2nd argument must be a string"); | |
902 break; | |
73 | 903 |
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
|
904 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
|
905 case LLVMva_start: |
73 | 906 case LLVMnotypeinfo: |
1 | 907 break; |
73 | 908 |
1 | 909 default: |
910 assert(0); | |
911 } | |
912 } | |
913 } | |
914 #endif | |
915 else | |
916 error("unrecognized pragma(%s)", ident->toChars()); | |
917 | |
918 if (decl) | |
919 { | |
920 for (unsigned i = 0; i < decl->dim; i++) | |
921 { | |
922 Dsymbol *s = (Dsymbol *)decl->data[i]; | |
923 | |
924 s->semantic(sc); | |
925 | |
926 #if IN_LLVM | |
927 if (llvm_internal) | |
928 { | |
929 switch(llvm_internal) | |
930 { | |
931 case LLVMintrinsic: | |
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
|
932 case LLVMva_intrinsic: |
1 | 933 if (FuncDeclaration* fd = s->isFuncDeclaration()) { |
934 fd->llvmInternal = llvm_internal; | |
935 fd->llvmInternal1 = llvm_str1; | |
936 } | |
937 else { | |
938 error("may only be used on function declarations"); | |
939 assert(0); | |
940 } | |
941 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
|
942 |
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
|
943 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
|
944 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
|
945 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
|
946 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
|
947 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
|
948 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
|
949 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
|
950 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
|
951 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
|
952 } |
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
|
953 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
|
954 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
|
955 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
|
956 } |
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
|
957 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
|
958 |
73 | 959 case LLVMnotypeinfo: |
960 s->llvmInternal = llvm_internal; | |
961 break; | |
962 | |
1 | 963 default: |
964 assert(0 && "invalid LLVM_internal pragma got through :/"); | |
965 } | |
966 } | |
967 | |
968 #endif | |
969 } | |
970 } | |
971 return; | |
972 | |
973 Lnodecl: | |
974 if (decl) | |
975 error("pragma is missing closing ';'"); | |
976 } | |
977 | |
978 int PragmaDeclaration::oneMember(Dsymbol **ps) | |
979 { | |
980 *ps = NULL; | |
981 return TRUE; | |
982 } | |
983 | |
984 char *PragmaDeclaration::kind() | |
985 { | |
986 return "pragma"; | |
987 } | |
988 | |
989 void PragmaDeclaration::toObjFile() | |
990 { | |
991 if (ident == Id::lib) | |
992 { | |
993 assert(args && args->dim == 1); | |
994 | |
995 Expression *e = (Expression *)args->data[0]; | |
996 | |
997 assert(e->op == TOKstring); | |
998 | |
999 StringExp *se = (StringExp *)e; | |
1000 char *name = (char *)mem.malloc(se->len + 1); | |
1001 memcpy(name, se->string, se->len); | |
1002 name[se->len] = 0; | |
1003 obj_includelib(name); | |
1004 } | |
1005 AttribDeclaration::toObjFile(); | |
1006 } | |
1007 | |
1008 void PragmaDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1009 { | |
1010 buf->printf("pragma(%s", ident->toChars()); | |
1011 if (args) | |
1012 { | |
1013 for (size_t i = 0; i < args->dim; i++) | |
1014 { | |
1015 Expression *e = (Expression *)args->data[i]; | |
1016 | |
1017 buf->writestring(", "); | |
1018 e->toCBuffer(buf, hgs); | |
1019 } | |
1020 } | |
1021 buf->writestring(")"); | |
1022 AttribDeclaration::toCBuffer(buf, hgs); | |
1023 } | |
1024 | |
1025 | |
1026 /********************************* ConditionalDeclaration ****************************/ | |
1027 | |
1028 ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Array *decl, Array *elsedecl) | |
1029 : AttribDeclaration(decl) | |
1030 { | |
1031 //printf("ConditionalDeclaration::ConditionalDeclaration()\n"); | |
1032 this->condition = condition; | |
1033 this->elsedecl = elsedecl; | |
1034 } | |
1035 | |
1036 Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s) | |
1037 { | |
1038 ConditionalDeclaration *dd; | |
1039 | |
1040 assert(!s); | |
1041 dd = new ConditionalDeclaration(condition->syntaxCopy(), | |
1042 Dsymbol::arraySyntaxCopy(decl), | |
1043 Dsymbol::arraySyntaxCopy(elsedecl)); | |
1044 return dd; | |
1045 } | |
1046 | |
1047 | |
1048 int ConditionalDeclaration::oneMember(Dsymbol **ps) | |
1049 { | |
1050 //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition->inc); | |
1051 if (condition->inc) | |
1052 { | |
1053 Array *d = condition->include(NULL, NULL) ? decl : elsedecl; | |
1054 return Dsymbol::oneMembers(d, ps); | |
1055 } | |
1056 *ps = NULL; | |
1057 return TRUE; | |
1058 } | |
1059 | |
1060 void ConditionalDeclaration::emitComment(Scope *sc) | |
1061 { | |
1062 //printf("ConditionalDeclaration::emitComment(sc = %p)\n", sc); | |
1063 if (condition->inc) | |
1064 { | |
1065 AttribDeclaration::emitComment(sc); | |
1066 } | |
1067 } | |
1068 | |
1069 // Decide if 'then' or 'else' code should be included | |
1070 | |
1071 Array *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sd) | |
1072 { | |
1073 //printf("ConditionalDeclaration::include()\n"); | |
1074 assert(condition); | |
1075 return condition->include(sc, sd) ? decl : elsedecl; | |
1076 } | |
1077 | |
1078 | |
1079 void ConditionalDeclaration::addComment(unsigned char *comment) | |
1080 { | |
1081 /* Because addComment is called by the parser, if we called | |
1082 * include() it would define a version before it was used. | |
1083 * But it's no problem to drill down to both decl and elsedecl, | |
1084 * so that's the workaround. | |
1085 */ | |
1086 | |
1087 if (comment) | |
1088 { | |
1089 Array *d = decl; | |
1090 | |
1091 for (int j = 0; j < 2; j++) | |
1092 { | |
1093 if (d) | |
1094 { | |
1095 for (unsigned i = 0; i < d->dim; i++) | |
1096 { Dsymbol *s; | |
1097 | |
1098 s = (Dsymbol *)d->data[i]; | |
1099 //printf("ConditionalDeclaration::addComment %s\n", s->toChars()); | |
1100 s->addComment(comment); | |
1101 } | |
1102 } | |
1103 d = elsedecl; | |
1104 } | |
1105 } | |
1106 } | |
1107 | |
1108 void ConditionalDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1109 { | |
1110 condition->toCBuffer(buf, hgs); | |
1111 if (decl || elsedecl) | |
1112 { | |
1113 buf->writenl(); | |
1114 buf->writeByte('{'); | |
1115 buf->writenl(); | |
1116 if (decl) | |
1117 { | |
1118 for (unsigned i = 0; i < decl->dim; i++) | |
1119 { | |
1120 Dsymbol *s = (Dsymbol *)decl->data[i]; | |
1121 | |
1122 buf->writestring(" "); | |
1123 s->toCBuffer(buf, hgs); | |
1124 } | |
1125 } | |
1126 buf->writeByte('}'); | |
1127 if (elsedecl) | |
1128 { | |
1129 buf->writenl(); | |
1130 buf->writestring("else"); | |
1131 buf->writenl(); | |
1132 buf->writeByte('{'); | |
1133 buf->writenl(); | |
1134 for (unsigned i = 0; i < elsedecl->dim; i++) | |
1135 { | |
1136 Dsymbol *s = (Dsymbol *)elsedecl->data[i]; | |
1137 | |
1138 buf->writestring(" "); | |
1139 s->toCBuffer(buf, hgs); | |
1140 } | |
1141 buf->writeByte('}'); | |
1142 } | |
1143 } | |
1144 else | |
1145 buf->writeByte(':'); | |
1146 buf->writenl(); | |
1147 } | |
1148 | |
1149 /***************************** StaticIfDeclaration ****************************/ | |
1150 | |
1151 StaticIfDeclaration::StaticIfDeclaration(Condition *condition, | |
1152 Array *decl, Array *elsedecl) | |
1153 : ConditionalDeclaration(condition, decl, elsedecl) | |
1154 { | |
1155 //printf("StaticIfDeclaration::StaticIfDeclaration()\n"); | |
1156 sd = NULL; | |
1157 addisdone = 0; | |
1158 } | |
1159 | |
1160 | |
1161 Dsymbol *StaticIfDeclaration::syntaxCopy(Dsymbol *s) | |
1162 { | |
1163 StaticIfDeclaration *dd; | |
1164 | |
1165 assert(!s); | |
1166 dd = new StaticIfDeclaration(condition->syntaxCopy(), | |
1167 Dsymbol::arraySyntaxCopy(decl), | |
1168 Dsymbol::arraySyntaxCopy(elsedecl)); | |
1169 return dd; | |
1170 } | |
1171 | |
1172 | |
1173 int StaticIfDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) | |
1174 { | |
1175 /* This is deferred until semantic(), so that | |
1176 * expressions in the condition can refer to declarations | |
1177 * in the same scope, such as: | |
1178 * | |
1179 * template Foo(int i) | |
1180 * { | |
1181 * const int j = i + 1; | |
1182 * static if (j == 3) | |
1183 * const int k; | |
1184 * } | |
1185 */ | |
1186 this->sd = sd; | |
1187 int m = 0; | |
1188 | |
1189 if (memnum == 0) | |
1190 { m = AttribDeclaration::addMember(sc, sd, memnum); | |
1191 addisdone = 1; | |
1192 } | |
1193 return m; | |
1194 } | |
1195 | |
1196 | |
1197 void StaticIfDeclaration::semantic(Scope *sc) | |
1198 { | |
1199 Array *d = include(sc, sd); | |
1200 | |
1201 //printf("\tStaticIfDeclaration::semantic '%s'\n",toChars()); | |
1202 if (d) | |
1203 { | |
1204 if (!addisdone) | |
1205 { AttribDeclaration::addMember(sc, sd, 1); | |
1206 addisdone = 1; | |
1207 } | |
1208 | |
1209 for (unsigned i = 0; i < d->dim; i++) | |
1210 { | |
1211 Dsymbol *s = (Dsymbol *)d->data[i]; | |
1212 | |
1213 s->semantic(sc); | |
1214 } | |
1215 } | |
1216 } | |
1217 | |
1218 char *StaticIfDeclaration::kind() | |
1219 { | |
1220 return "static if"; | |
1221 } | |
1222 | |
1223 | |
1224 /***************************** CompileDeclaration *****************************/ | |
1225 | |
1226 CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp) | |
1227 : AttribDeclaration(NULL) | |
1228 { | |
1229 this->exp = exp; | |
1230 this->sd = NULL; | |
1231 } | |
1232 | |
1233 Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *s) | |
1234 { | |
1235 //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars()); | |
1236 CompileDeclaration *sc = new CompileDeclaration(loc, exp->syntaxCopy()); | |
1237 return sc; | |
1238 } | |
1239 | |
1240 int CompileDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) | |
1241 { | |
1242 this->sd = sd; | |
1243 return memnum; | |
1244 } | |
1245 | |
1246 void CompileDeclaration::semantic(Scope *sc) | |
1247 { | |
1248 //printf("CompileDeclaration::semantic()\n"); | |
1249 exp = exp->semantic(sc); | |
1250 exp = resolveProperties(sc, exp); | |
1251 exp = exp->optimize(WANTvalue | WANTinterpret); | |
1252 if (exp->op != TOKstring) | |
1253 { error("argument to mixin must be a string, not (%s)", exp->toChars()); | |
1254 return; | |
1255 } | |
1256 StringExp *se = (StringExp *)exp; | |
1257 se = se->toUTF8(sc); | |
1258 Parser p(sc->module, (unsigned char *)se->string, se->len, 0); | |
1259 p.loc = loc; | |
1260 p.nextToken(); | |
1261 decl = p.parseDeclDefs(0); | |
1262 if (p.token.value != TOKeof) | |
1263 { | |
1264 error("incomplete mixin declaration (%s)", se->toChars()); | |
1265 } | |
1266 | |
1267 AttribDeclaration::addMember(sc, sd, 0); | |
1268 AttribDeclaration::semantic(sc); | |
1269 } | |
1270 | |
1271 void CompileDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
1272 { | |
1273 buf->writestring("mixin("); | |
1274 exp->toCBuffer(buf, hgs); | |
1275 buf->writestring(");"); | |
1276 buf->writenl(); | |
1277 } |