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