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