1 
2 /* Compiler implementation of the D programming language
3  * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
4  * written by Walter Bright
5  * http://www.digitalmars.com
6  * Distributed under the Boost Software License, Version 1.0.
7  * http://www.boost.org/LICENSE_1_0.txt
8  * https://github.com/D-Programming-Language/dmd/blob/master/src/attrib.c
9  */
10 
11 #include "root/dsystem.h"               // memcmp()
12 #include "root/rmem.h"
13 
14 #include "mars.h"
15 #include "init.h"
16 #include "declaration.h"
17 #include "attrib.h"
18 #include "cond.h"
19 #include "scope.h"
20 #include "id.h"
21 #include "expression.h"
22 #include "dsymbol.h"
23 #include "aggregate.h"
24 #include "module.h"
25 #include "parse.h"
26 #include "target.h"
27 #include "template.h"
28 #include "utf.h"
29 #include "mtype.h"
30 
31 bool definitelyValueParameter(Expression *e);
32 Expression *semantic(Expression *e, Scope *sc);
33 StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
34 Dsymbols *makeTupleForeachStaticDecl(Scope *sc, ForeachStatement *fs, Dsymbols *dbody, bool needExpansion);
35 
36 /********************************* AttribDeclaration ****************************/
37 
AttribDeclaration(Dsymbols * decl)38 AttribDeclaration::AttribDeclaration(Dsymbols *decl)
39         : Dsymbol()
40 {
41     this->decl = decl;
42 }
43 
include(Scope *,ScopeDsymbol *)44 Dsymbols *AttribDeclaration::include(Scope *, ScopeDsymbol *)
45 {
46     if (errors)
47         return NULL;
48 
49     return decl;
50 }
51 
apply(Dsymbol_apply_ft_t fp,void * param)52 int AttribDeclaration::apply(Dsymbol_apply_ft_t fp, void *param)
53 {
54     Dsymbols *d = include(_scope, NULL);
55 
56     if (d)
57     {
58         for (size_t i = 0; i < d->dim; i++)
59         {
60             Dsymbol *s = (*d)[i];
61             if (s)
62             {
63                 if (s->apply(fp, param))
64                     return 1;
65             }
66         }
67     }
68     return 0;
69 }
70 
71 /****************************************
72  * Create a new scope if one or more given attributes
73  * are different from the sc's.
74  * If the returned scope != sc, the caller should pop
75  * the scope after it used.
76  */
createNewScope(Scope * sc,StorageClass stc,LINK linkage,CPPMANGLE cppmangle,Prot protection,int explicitProtection,AlignDeclaration * aligndecl,PINLINE inlining)77 Scope *AttribDeclaration::createNewScope(Scope *sc,
78         StorageClass stc, LINK linkage, CPPMANGLE cppmangle, Prot protection,
79         int explicitProtection, AlignDeclaration *aligndecl, PINLINE inlining)
80 {
81     Scope *sc2 = sc;
82     if (stc != sc->stc ||
83         linkage != sc->linkage ||
84         cppmangle != sc->cppmangle ||
85         !protection.isSubsetOf(sc->protection) ||
86         explicitProtection != sc->explicitProtection ||
87         aligndecl != sc->aligndecl ||
88         inlining != sc->inlining)
89     {
90         // create new one for changes
91         sc2 = sc->copy();
92         sc2->stc = stc;
93         sc2->linkage = linkage;
94         sc2->cppmangle = cppmangle;
95         sc2->protection = protection;
96         sc2->explicitProtection = explicitProtection;
97         sc2->aligndecl = aligndecl;
98         sc2->inlining = inlining;
99     }
100     return sc2;
101 }
102 
103 /****************************************
104  * A hook point to supply scope for members.
105  * addMember, setScope, importAll, semantic, semantic2 and semantic3 will use this.
106  */
newScope(Scope * sc)107 Scope *AttribDeclaration::newScope(Scope *sc)
108 {
109     return sc;
110 }
111 
addMember(Scope * sc,ScopeDsymbol * sds)112 void AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
113 {
114     Dsymbols *d = include(sc, sds);
115 
116     if (d)
117     {
118         Scope *sc2 = newScope(sc);
119 
120         for (size_t i = 0; i < d->dim; i++)
121         {
122             Dsymbol *s = (*d)[i];
123             //printf("\taddMember %s to %s\n", s->toChars(), sds->toChars());
124             s->addMember(sc2, sds);
125         }
126 
127         if (sc2 != sc)
128             sc2->pop();
129     }
130 }
131 
setScope(Scope * sc)132 void AttribDeclaration::setScope(Scope *sc)
133 {
134     Dsymbols *d = include(sc, NULL);
135 
136     //printf("\tAttribDeclaration::setScope '%s', d = %p\n",toChars(), d);
137     if (d)
138     {
139         Scope *sc2 = newScope(sc);
140 
141         for (size_t i = 0; i < d->dim; i++)
142         {
143             Dsymbol *s = (*d)[i];
144             s->setScope(sc2);
145         }
146 
147         if (sc2 != sc)
148             sc2->pop();
149     }
150 }
151 
importAll(Scope * sc)152 void AttribDeclaration::importAll(Scope *sc)
153 {
154     Dsymbols *d = include(sc, NULL);
155 
156     //printf("\tAttribDeclaration::importAll '%s', d = %p\n", toChars(), d);
157     if (d)
158     {
159         Scope *sc2 = newScope(sc);
160 
161         for (size_t i = 0; i < d->dim; i++)
162         {
163             Dsymbol *s = (*d)[i];
164             s->importAll(sc2);
165         }
166 
167         if (sc2 != sc)
168             sc2->pop();
169     }
170 }
171 
semantic(Scope * sc)172 void AttribDeclaration::semantic(Scope *sc)
173 {
174     if (semanticRun != PASSinit)
175         return;
176     semanticRun = PASSsemantic;
177     Dsymbols *d = include(sc, NULL);
178 
179     //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d);
180     if (d)
181     {
182         Scope *sc2 = newScope(sc);
183 
184         for (size_t i = 0; i < d->dim; i++)
185         {
186             Dsymbol *s = (*d)[i];
187             s->semantic(sc2);
188         }
189 
190         if (sc2 != sc)
191             sc2->pop();
192     }
193     semanticRun = PASSsemanticdone;
194 }
195 
semantic2(Scope * sc)196 void AttribDeclaration::semantic2(Scope *sc)
197 {
198     Dsymbols *d = include(sc, NULL);
199 
200     if (d)
201     {
202         Scope *sc2 = newScope(sc);
203 
204         for (size_t i = 0; i < d->dim; i++)
205         {
206             Dsymbol *s = (*d)[i];
207             s->semantic2(sc2);
208         }
209 
210         if (sc2 != sc)
211             sc2->pop();
212     }
213 }
214 
semantic3(Scope * sc)215 void AttribDeclaration::semantic3(Scope *sc)
216 {
217     Dsymbols *d = include(sc, NULL);
218 
219     if (d)
220     {
221         Scope *sc2 = newScope(sc);
222 
223         for (size_t i = 0; i < d->dim; i++)
224         {
225             Dsymbol *s = (*d)[i];
226             s->semantic3(sc2);
227         }
228 
229         if (sc2 != sc)
230             sc2->pop();
231     }
232 }
233 
addComment(const utf8_t * comment)234 void AttribDeclaration::addComment(const utf8_t *comment)
235 {
236     //printf("AttribDeclaration::addComment %s\n", comment);
237     if (comment)
238     {
239         Dsymbols *d = include(NULL, NULL);
240 
241         if (d)
242         {
243             for (size_t i = 0; i < d->dim; i++)
244             {
245                 Dsymbol *s = (*d)[i];
246                 //printf("AttribDeclaration::addComment %s\n", s->toChars());
247                 s->addComment(comment);
248             }
249         }
250     }
251 }
252 
setFieldOffset(AggregateDeclaration * ad,unsigned * poffset,bool isunion)253 void AttribDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
254 {
255     Dsymbols *d = include(NULL, NULL);
256 
257     if (d)
258     {
259         for (size_t i = 0; i < d->dim; i++)
260         {
261             Dsymbol *s = (*d)[i];
262             s->setFieldOffset(ad, poffset, isunion);
263         }
264     }
265 }
266 
hasPointers()267 bool AttribDeclaration::hasPointers()
268 {
269     Dsymbols *d = include(NULL, NULL);
270 
271     if (d)
272     {
273         for (size_t i = 0; i < d->dim; i++)
274         {
275             Dsymbol *s = (*d)[i];
276             if (s->hasPointers())
277                 return true;
278         }
279     }
280     return false;
281 }
282 
hasStaticCtorOrDtor()283 bool AttribDeclaration::hasStaticCtorOrDtor()
284 {
285     Dsymbols *d = include(NULL, NULL);
286 
287     if (d)
288     {
289         for (size_t i = 0; i < d->dim; i++)
290         {
291             Dsymbol *s = (*d)[i];
292             if (s->hasStaticCtorOrDtor())
293                 return true;
294         }
295     }
296     return false;
297 }
298 
kind()299 const char *AttribDeclaration::kind() const
300 {
301     return "attribute";
302 }
303 
oneMember(Dsymbol ** ps,Identifier * ident)304 bool AttribDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
305 {
306     Dsymbols *d = include(NULL, NULL);
307 
308     return Dsymbol::oneMembers(d, ps, ident);
309 }
310 
checkCtorConstInit()311 void AttribDeclaration::checkCtorConstInit()
312 {
313     Dsymbols *d = include(NULL, NULL);
314 
315     if (d)
316     {
317         for (size_t i = 0; i < d->dim; i++)
318         {
319             Dsymbol *s = (*d)[i];
320             s->checkCtorConstInit();
321         }
322     }
323 }
324 
325 /****************************************
326  */
327 
addLocalClass(ClassDeclarations * aclasses)328 void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses)
329 {
330     Dsymbols *d = include(NULL, NULL);
331 
332     if (d)
333     {
334         for (size_t i = 0; i < d->dim; i++)
335         {
336             Dsymbol *s = (*d)[i];
337             s->addLocalClass(aclasses);
338         }
339     }
340 }
341 
342 /************************* StorageClassDeclaration ****************************/
343 
StorageClassDeclaration(StorageClass stc,Dsymbols * decl)344 StorageClassDeclaration::StorageClassDeclaration(StorageClass stc, Dsymbols *decl)
345         : AttribDeclaration(decl)
346 {
347     this->stc = stc;
348 }
349 
syntaxCopy(Dsymbol * s)350 Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
351 {
352     assert(!s);
353     return new StorageClassDeclaration(stc, Dsymbol::arraySyntaxCopy(decl));
354 }
355 
oneMember(Dsymbol ** ps,Identifier * ident)356 bool StorageClassDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
357 {
358     bool t = Dsymbol::oneMembers(decl, ps, ident);
359     if (t && *ps)
360     {
361         /* This is to deal with the following case:
362          * struct Tick {
363          *   template to(T) { const T to() { ... } }
364          * }
365          * For eponymous function templates, the 'const' needs to get attached to 'to'
366          * before the semantic analysis of 'to', so that template overloading based on the
367          * 'this' pointer can be successful.
368          */
369 
370         FuncDeclaration *fd = (*ps)->isFuncDeclaration();
371         if (fd)
372         {
373             /* Use storage_class2 instead of storage_class otherwise when we do .di generation
374              * we'll wind up with 'const const' rather than 'const'.
375              */
376             /* Don't think we need to worry about mutually exclusive storage classes here
377              */
378             fd->storage_class2 |= stc;
379         }
380     }
381     return t;
382 }
383 
addMember(Scope * sc,ScopeDsymbol * sds)384 void StorageClassDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
385 {
386     Dsymbols *d = include(sc, sds);
387     if (d)
388     {
389         Scope *sc2 = newScope(sc);
390         for (size_t i = 0; i < d->dim; i++)
391         {
392             Dsymbol *s = (*d)[i];
393             //printf("\taddMember %s to %s\n", s->toChars(), sds->toChars());
394             // STClocal needs to be attached before the member is added to the scope (because it influences the parent symbol)
395             if (Declaration *decl = s->isDeclaration())
396             {
397                 decl->storage_class |= stc & STClocal;
398                 if (StorageClassDeclaration *sdecl = s->isStorageClassDeclaration())
399                 {
400                     sdecl->stc |= stc & STClocal;
401                 }
402             }
403             s->addMember(sc2, sds);
404         }
405         if (sc2 != sc)
406             sc2->pop();
407     }
408 }
409 
newScope(Scope * sc)410 Scope *StorageClassDeclaration::newScope(Scope *sc)
411 {
412     StorageClass scstc = sc->stc;
413 
414     /* These sets of storage classes are mutually exclusive,
415      * so choose the innermost or most recent one.
416      */
417     if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
418         scstc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
419     if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared))
420         scstc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared);
421     if (stc & (STCconst | STCimmutable | STCmanifest))
422         scstc &= ~(STCconst | STCimmutable | STCmanifest);
423     if (stc & (STCgshared | STCshared | STCtls))
424         scstc &= ~(STCgshared | STCshared | STCtls);
425     if (stc & (STCsafe | STCtrusted | STCsystem))
426         scstc &= ~(STCsafe | STCtrusted | STCsystem);
427     scstc |= stc;
428     //printf("scstc = x%llx\n", scstc);
429 
430     return createNewScope(sc, scstc, sc->linkage, sc->cppmangle,
431         sc->protection, sc->explicitProtection, sc->aligndecl,
432         sc->inlining);
433 }
434 
435 /********************************* DeprecatedDeclaration ****************************/
436 
DeprecatedDeclaration(Expression * msg,Dsymbols * decl)437 DeprecatedDeclaration::DeprecatedDeclaration(Expression *msg, Dsymbols *decl)
438         : StorageClassDeclaration(STCdeprecated, decl)
439 {
440     this->msg = msg;
441     this->msgstr = NULL;
442 }
443 
syntaxCopy(Dsymbol * s)444 Dsymbol *DeprecatedDeclaration::syntaxCopy(Dsymbol *s)
445 {
446     assert(!s);
447     return new DeprecatedDeclaration(msg->syntaxCopy(), Dsymbol::arraySyntaxCopy(decl));
448 }
449 
450 /**
451  * Provides a new scope with `STCdeprecated` and `Scope.depdecl` set
452  *
453  * Calls `StorageClassDeclaration.newScope` (as it must be called or copied
454  * in any function overriding `newScope`), then set the `Scope`'s depdecl.
455  *
456  * Returns:
457  *   Always a new scope, to use for this `DeprecatedDeclaration`'s members.
458  */
newScope(Scope * sc)459 Scope *DeprecatedDeclaration::newScope(Scope *sc)
460 {
461     Scope *scx = StorageClassDeclaration::newScope(sc);
462     // The enclosing scope is deprecated as well
463     if (scx == sc)
464         scx = sc->push();
465     scx->depdecl = this;
466     return scx;
467 }
468 
setScope(Scope * sc)469 void DeprecatedDeclaration::setScope(Scope *sc)
470 {
471     //printf("DeprecatedDeclaration::setScope() %p\n", this);
472     if (decl)
473         Dsymbol::setScope(sc); // for forward reference
474     return AttribDeclaration::setScope(sc);
475 }
476 
477 /**
478  * Run the DeprecatedDeclaration's semantic2 phase then its members.
479  *
480  * The message set via a `DeprecatedDeclaration` can be either of:
481  * - a string literal
482  * - an enum
483  * - a static immutable
484  * So we need to call ctfe to resolve it.
485  * Afterward forwards to the members' semantic2.
486  */
semantic2(Scope * sc)487 void DeprecatedDeclaration::semantic2(Scope *sc)
488 {
489     getMessage();
490     StorageClassDeclaration::semantic2(sc);
491 }
492 
getMessage()493 const char *DeprecatedDeclaration::getMessage()
494 {
495     if (Scope *sc = _scope)
496     {
497         _scope = NULL;
498 
499         sc = sc->startCTFE();
500         msg = ::semantic(msg, sc);
501         msg = resolveProperties(sc, msg);
502         sc = sc->endCTFE();
503         msg = msg->ctfeInterpret();
504 
505         if (StringExp *se = msg->toStringExp())
506             msgstr = (char *)se->string;
507         else
508             msg->error("compile time constant expected, not '%s'", msg->toChars());
509     }
510     return msgstr;
511 }
512 
513 /********************************* LinkDeclaration ****************************/
514 
LinkDeclaration(LINK p,Dsymbols * decl)515 LinkDeclaration::LinkDeclaration(LINK p, Dsymbols *decl)
516         : AttribDeclaration(decl)
517 {
518     //printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl);
519     linkage = (p == LINKsystem) ? Target::systemLinkage() : p;
520 }
521 
create(LINK p,Dsymbols * decl)522 LinkDeclaration *LinkDeclaration::create(LINK p, Dsymbols *decl)
523 {
524     return new LinkDeclaration(p, decl);
525 }
526 
syntaxCopy(Dsymbol * s)527 Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s)
528 {
529     assert(!s);
530     return new LinkDeclaration(linkage, Dsymbol::arraySyntaxCopy(decl));
531 }
532 
newScope(Scope * sc)533 Scope *LinkDeclaration::newScope(Scope *sc)
534 {
535     return createNewScope(sc, sc->stc, this->linkage, sc->cppmangle,
536         sc->protection, sc->explicitProtection, sc->aligndecl,
537         sc->inlining);
538 }
539 
toChars()540 const char *LinkDeclaration::toChars()
541 {
542     return "extern ()";
543 }
544 
545 /********************************* CPPMangleDeclaration ****************************/
546 
CPPMangleDeclaration(CPPMANGLE p,Dsymbols * decl)547 CPPMangleDeclaration::CPPMangleDeclaration(CPPMANGLE p, Dsymbols *decl)
548         : AttribDeclaration(decl)
549 {
550     //printf("CPPMangleDeclaration(cppmangle = %d, decl = %p)\n", p, decl);
551     cppmangle = p;
552 }
553 
syntaxCopy(Dsymbol * s)554 Dsymbol *CPPMangleDeclaration::syntaxCopy(Dsymbol *s)
555 {
556     assert(!s);
557     return new CPPMangleDeclaration(cppmangle, Dsymbol::arraySyntaxCopy(decl));
558 }
559 
newScope(Scope * sc)560 Scope *CPPMangleDeclaration::newScope(Scope *sc)
561 {
562     return createNewScope(sc, sc->stc, LINKcpp, this->cppmangle,
563         sc->protection, sc->explicitProtection, sc->aligndecl,
564         sc->inlining);
565 }
566 
toChars()567 const char *CPPMangleDeclaration::toChars()
568 {
569     return "extern ()";
570 }
571 
572 /********************************* ProtDeclaration ****************************/
573 
574 /**
575  * Params:
576  *  loc = source location of attribute token
577  *  p = protection attribute data
578  *  decl = declarations which are affected by this protection attribute
579  */
ProtDeclaration(Loc loc,Prot p,Dsymbols * decl)580 ProtDeclaration::ProtDeclaration(Loc loc, Prot p, Dsymbols *decl)
581         : AttribDeclaration(decl)
582 {
583     this->loc = loc;
584     this->protection = p;
585     this->pkg_identifiers = NULL;
586     //printf("decl = %p\n", decl);
587 }
588 
589 /**
590  * Params:
591  *  loc = source location of attribute token
592  *  pkg_identifiers = list of identifiers for a qualified package name
593  *  decl = declarations which are affected by this protection attribute
594  */
ProtDeclaration(Loc loc,Identifiers * pkg_identifiers,Dsymbols * decl)595 ProtDeclaration::ProtDeclaration(Loc loc, Identifiers* pkg_identifiers, Dsymbols *decl)
596         : AttribDeclaration(decl)
597 {
598     this->loc = loc;
599     this->protection.kind = PROTpackage;
600     this->protection.pkg  = NULL;
601     this->pkg_identifiers = pkg_identifiers;
602 }
603 
syntaxCopy(Dsymbol * s)604 Dsymbol *ProtDeclaration::syntaxCopy(Dsymbol *s)
605 {
606     assert(!s);
607     if (protection.kind == PROTpackage)
608         return new ProtDeclaration(this->loc, pkg_identifiers, Dsymbol::arraySyntaxCopy(decl));
609     else
610         return new ProtDeclaration(this->loc, protection, Dsymbol::arraySyntaxCopy(decl));
611 }
612 
newScope(Scope * sc)613 Scope *ProtDeclaration::newScope(Scope *sc)
614 {
615     if (pkg_identifiers)
616         semantic(sc);
617     return createNewScope(sc, sc->stc, sc->linkage, sc->cppmangle,
618         this->protection, 1, sc->aligndecl,
619         sc->inlining);
620 }
621 
addMember(Scope * sc,ScopeDsymbol * sds)622 void ProtDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
623 {
624     if (pkg_identifiers)
625     {
626         Dsymbol* tmp;
627         Package::resolve(pkg_identifiers, &tmp, NULL);
628         protection.pkg = tmp ? tmp->isPackage() : NULL;
629         pkg_identifiers = NULL;
630     }
631 
632     if (protection.kind == PROTpackage && protection.pkg && sc->_module)
633     {
634         Module *m = sc->_module;
635         Package* pkg = m->parent ? m->parent->isPackage() : NULL;
636         if (!pkg || !protection.pkg->isAncestorPackageOf(pkg))
637             error("does not bind to one of ancestor packages of module '%s'",
638                m->toPrettyChars(true));
639     }
640 
641     return AttribDeclaration::addMember(sc, sds);
642 }
643 
kind()644 const char *ProtDeclaration::kind() const
645 {
646     return "protection attribute";
647 }
648 
toPrettyChars(bool)649 const char *ProtDeclaration::toPrettyChars(bool)
650 {
651     assert(protection.kind > PROTundefined);
652 
653     OutBuffer buf;
654     buf.writeByte('\'');
655     protectionToBuffer(&buf, protection);
656     buf.writeByte('\'');
657     return buf.extractString();
658 }
659 
660 /********************************* AlignDeclaration ****************************/
661 
AlignDeclaration(Loc loc,Expression * ealign,Dsymbols * decl)662 AlignDeclaration::AlignDeclaration(Loc loc, Expression *ealign, Dsymbols *decl)
663         : AttribDeclaration(decl)
664 {
665     this->loc = loc;
666     this->ealign = ealign;
667     this->salign = 0;
668 }
669 
syntaxCopy(Dsymbol * s)670 Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s)
671 {
672     assert(!s);
673     return new AlignDeclaration(loc,
674         ealign ? ealign->syntaxCopy() : NULL,
675         Dsymbol::arraySyntaxCopy(decl));
676 }
677 
newScope(Scope * sc)678 Scope *AlignDeclaration::newScope(Scope *sc)
679 {
680     return createNewScope(sc, sc->stc, sc->linkage, sc->cppmangle,
681         sc->protection, sc->explicitProtection, this,
682         sc->inlining);
683 }
684 
semantic2(Scope * sc)685 void AlignDeclaration::semantic2(Scope *sc)
686 {
687     getAlignment(sc);
688     AttribDeclaration::semantic2(sc);
689 }
690 
getAlignment(Scope * sc)691 structalign_t AlignDeclaration::getAlignment(Scope *sc)
692 {
693     if (salign != 0)
694         return salign;
695 
696     if (!ealign)
697         return salign = STRUCTALIGN_DEFAULT;
698 
699     sc = sc->startCTFE();
700     ealign = ::semantic(ealign, sc);
701     ealign = resolveProperties(sc, ealign);
702     sc = sc->endCTFE();
703     ealign = ealign->ctfeInterpret();
704 
705     if (ealign->op == TOKerror)
706         return salign = STRUCTALIGN_DEFAULT;
707 
708     Type *tb = ealign->type->toBasetype();
709     sinteger_t n = ealign->toInteger();
710 
711     if (n < 1 || n & (n - 1) || STRUCTALIGN_DEFAULT < n || !tb->isintegral())
712     {
713         ::error(loc, "alignment must be an integer positive power of 2, not %s", ealign->toChars());
714         return salign = STRUCTALIGN_DEFAULT;
715     }
716 
717     return salign = (structalign_t)n;
718 }
719 
720 /********************************* AnonDeclaration ****************************/
721 
AnonDeclaration(Loc loc,bool isunion,Dsymbols * decl)722 AnonDeclaration::AnonDeclaration(Loc loc, bool isunion, Dsymbols *decl)
723         : AttribDeclaration(decl)
724 {
725     this->loc = loc;
726     this->isunion = isunion;
727     this->sem = 0;
728     this->anonoffset = 0;
729     this->anonstructsize = 0;
730     this->anonalignsize = 0;
731 }
732 
syntaxCopy(Dsymbol * s)733 Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s)
734 {
735     assert(!s);
736     return new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl));
737 }
738 
setScope(Scope * sc)739 void AnonDeclaration::setScope(Scope *sc)
740 {
741     //printf("AnonDeclaration::setScope() %p\n", this);
742     if (decl)
743         Dsymbol::setScope(sc);
744     AttribDeclaration::setScope(sc);
745 }
746 
semantic(Scope * sc)747 void AnonDeclaration::semantic(Scope *sc)
748 {
749     //printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
750 
751     assert(sc->parent);
752 
753     Dsymbol *p = sc->parent->pastMixin();
754     AggregateDeclaration *ad = p->isAggregateDeclaration();
755     if (!ad)
756     {
757         ::error(loc, "%s can only be a part of an aggregate, not %s %s",
758             kind(), p->kind(), p->toChars());
759         errors = true;
760         return;
761     }
762 
763     if (decl)
764     {
765         sc = sc->push();
766         sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
767         sc->inunion = isunion;
768         sc->flags = 0;
769 
770         for (size_t i = 0; i < decl->dim; i++)
771         {
772             Dsymbol *s = (*decl)[i];
773             s->semantic(sc);
774         }
775         sc = sc->pop();
776     }
777 }
778 
setFieldOffset(AggregateDeclaration * ad,unsigned * poffset,bool isunion)779 void AnonDeclaration::setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion)
780 {
781     //printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", this);
782 
783     if (decl)
784     {
785         /* This works by treating an AnonDeclaration as an aggregate 'member',
786          * so in order to place that member we need to compute the member's
787          * size and alignment.
788          */
789 
790         size_t fieldstart = ad->fields.dim;
791 
792         /* Hackishly hijack ad's structsize and alignsize fields
793          * for use in our fake anon aggregate member.
794          */
795         unsigned savestructsize = ad->structsize;
796         unsigned savealignsize  = ad->alignsize;
797         ad->structsize = 0;
798         ad->alignsize = 0;
799 
800         unsigned offset = 0;
801         for (size_t i = 0; i < decl->dim; i++)
802         {
803             Dsymbol *s = (*decl)[i];
804             s->setFieldOffset(ad, &offset, this->isunion);
805             if (this->isunion)
806                 offset = 0;
807         }
808 
809         /* Bugzilla 13613: If the fields in this->members had been already
810          * added in ad->fields, just update *poffset for the subsequent
811          * field offset calculation.
812          */
813         if (fieldstart == ad->fields.dim)
814         {
815             ad->structsize = savestructsize;
816             ad->alignsize  = savealignsize;
817             *poffset = ad->structsize;
818             return;
819         }
820 
821         anonstructsize = ad->structsize;
822         anonalignsize  = ad->alignsize;
823         ad->structsize = savestructsize;
824         ad->alignsize  = savealignsize;
825 
826         // 0 sized structs are set to 1 byte
827         // TODO: is this corect hebavior?
828         if (anonstructsize == 0)
829         {
830             anonstructsize = 1;
831             anonalignsize = 1;
832         }
833 
834         assert(_scope);
835         structalign_t alignment = _scope->alignment();
836 
837         /* Given the anon 'member's size and alignment,
838          * go ahead and place it.
839          */
840         anonoffset = AggregateDeclaration::placeField(
841                 poffset,
842                 anonstructsize, anonalignsize, alignment,
843                 &ad->structsize, &ad->alignsize,
844                 isunion);
845 
846         // Add to the anon fields the base offset of this anonymous aggregate
847         //printf("anon fields, anonoffset = %d\n", anonoffset);
848         for (size_t i = fieldstart; i < ad->fields.dim; i++)
849         {
850             VarDeclaration *v = ad->fields[i];
851             //printf("\t[%d] %s %d\n", i, v->toChars(), v->offset);
852             v->offset += anonoffset;
853         }
854     }
855 }
856 
kind()857 const char *AnonDeclaration::kind() const
858 {
859     return (isunion ? "anonymous union" : "anonymous struct");
860 }
861 
862 /********************************* PragmaDeclaration ****************************/
863 
PragmaDeclaration(Loc loc,Identifier * ident,Expressions * args,Dsymbols * decl)864 PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Dsymbols *decl)
865         : AttribDeclaration(decl)
866 {
867     this->loc = loc;
868     this->ident = ident;
869     this->args = args;
870 }
871 
syntaxCopy(Dsymbol * s)872 Dsymbol *PragmaDeclaration::syntaxCopy(Dsymbol *s)
873 {
874     //printf("PragmaDeclaration::syntaxCopy(%s)\n", toChars());
875     assert(!s);
876     return new PragmaDeclaration(loc, ident,
877         Expression::arraySyntaxCopy(args),
878         Dsymbol::arraySyntaxCopy(decl));
879 }
880 
newScope(Scope * sc)881 Scope *PragmaDeclaration::newScope(Scope *sc)
882 {
883     if (ident == Id::Pinline)
884     {
885         PINLINE inlining = PINLINEdefault;
886         if (!args || args->dim == 0)
887             inlining = PINLINEdefault;
888         else if (args->dim != 1)
889         {
890             error("one boolean expression expected for pragma(inline), not %d", args->dim);
891             args->setDim(1);
892             (*args)[0] = new ErrorExp();
893         }
894         else
895         {
896             Expression *e = (*args)[0];
897 
898             if (e->op != TOKint64 || !e->type->equals(Type::tbool))
899             {
900                 if (e->op != TOKerror)
901                 {
902                     error("pragma(inline, true or false) expected, not %s", e->toChars());
903                     (*args)[0] = new ErrorExp();
904                 }
905             }
906             else if (e->isBool(true))
907                 inlining = PINLINEalways;
908             else if (e->isBool(false))
909                 inlining = PINLINEnever;
910         }
911 
912         return createNewScope(sc, sc->stc, sc->linkage, sc->cppmangle,
913             sc->protection, sc->explicitProtection, sc->aligndecl,
914             inlining);
915     }
916     return sc;
917 }
918 
setMangleOverride(Dsymbol * s,char * sym)919 static unsigned setMangleOverride(Dsymbol *s, char *sym)
920 {
921     AttribDeclaration *ad = s->isAttribDeclaration();
922 
923     if (ad)
924     {
925         Dsymbols *decls = ad->include(NULL, NULL);
926         unsigned nestedCount = 0;
927 
928         if (decls && decls->dim)
929             for (size_t i = 0; i < decls->dim; ++i)
930                 nestedCount += setMangleOverride((*decls)[i], sym);
931 
932         return nestedCount;
933     }
934     else if (s->isFuncDeclaration() || s->isVarDeclaration())
935     {
936         s->isDeclaration()->mangleOverride = sym;
937         return 1;
938     }
939     else
940         return 0;
941 }
942 
semantic(Scope * sc)943 void PragmaDeclaration::semantic(Scope *sc)
944 {
945     // Should be merged with PragmaStatement
946 
947     //printf("\tPragmaDeclaration::semantic '%s'\n",toChars());
948     if (ident == Id::msg)
949     {
950         if (args)
951         {
952             for (size_t i = 0; i < args->dim; i++)
953             {
954                 Expression *e = (*args)[i];
955 
956                 sc = sc->startCTFE();
957                 e = ::semantic(e, sc);
958                 e = resolveProperties(sc, e);
959                 sc = sc->endCTFE();
960 
961                 // pragma(msg) is allowed to contain types as well as expressions
962                 e = ctfeInterpretForPragmaMsg(e);
963                 if (e->op == TOKerror)
964                 {
965                     errorSupplemental(loc, "while evaluating pragma(msg, %s)", (*args)[i]->toChars());
966                     return;
967                 }
968                 StringExp *se = e->toStringExp();
969                 if (se)
970                 {
971                     se = se->toUTF8(sc);
972                     fprintf(stderr, "%.*s", (int)se->len, (char *)se->string);
973                 }
974                 else
975                     fprintf(stderr, "%s", e->toChars());
976             }
977             fprintf(stderr, "\n");
978         }
979         goto Lnodecl;
980     }
981     else if (ident == Id::lib)
982     {
983         if (!args || args->dim != 1)
984             error("string expected for library name");
985         else
986         {
987             StringExp *se = semanticString(sc, (*args)[0], "library name");
988             if (!se)
989                 goto Lnodecl;
990             (*args)[0] = se;
991 
992             char *name = (char *)mem.xmalloc(se->len + 1);
993             memcpy(name, se->string, se->len);
994             name[se->len] = 0;
995             if (global.params.verbose)
996                 message("library   %s", name);
997             if (global.params.moduleDeps && !global.params.moduleDepsFile)
998             {
999                 OutBuffer *ob = global.params.moduleDeps;
1000                 Module *imod = sc->instantiatingModule();
1001                 ob->writestring("depsLib ");
1002                 ob->writestring(imod->toPrettyChars());
1003                 ob->writestring(" (");
1004                 escapePath(ob, imod->srcfile->toChars());
1005                 ob->writestring(") : ");
1006                 ob->writestring((char *) name);
1007                 ob->writenl();
1008             }
1009             mem.xfree(name);
1010         }
1011         goto Lnodecl;
1012     }
1013     else if (ident == Id::startaddress)
1014     {
1015         if (!args || args->dim != 1)
1016             error("function name expected for start address");
1017         else
1018         {
1019             /* Bugzilla 11980:
1020              * resolveProperties and ctfeInterpret call are not necessary.
1021              */
1022             Expression *e = (*args)[0];
1023 
1024             sc = sc->startCTFE();
1025             e = ::semantic(e, sc);
1026             sc = sc->endCTFE();
1027 
1028             (*args)[0] = e;
1029             Dsymbol *sa = getDsymbol(e);
1030             if (!sa || !sa->isFuncDeclaration())
1031                 error("function name expected for start address, not '%s'", e->toChars());
1032         }
1033         goto Lnodecl;
1034     }
1035     else if (ident == Id::Pinline)
1036     {
1037         goto Ldecl;
1038     }
1039     else if (ident == Id::mangle)
1040     {
1041         if (!args)
1042             args = new Expressions();
1043         if (args->dim != 1)
1044         {
1045             error("string expected for mangled name");
1046             args->setDim(1);
1047             (*args)[0] = new ErrorExp();    // error recovery
1048             goto Ldecl;
1049         }
1050 
1051         StringExp *se = semanticString(sc, (*args)[0], "mangled name");
1052         if (!se)
1053             goto Ldecl;
1054         (*args)[0] = se; // Will be used for later
1055 
1056         if (!se->len)
1057         {
1058             error("zero-length string not allowed for mangled name");
1059             goto Ldecl;
1060         }
1061         if (se->sz != 1)
1062         {
1063             error("mangled name characters can only be of type char");
1064             goto Ldecl;
1065         }
1066 
1067         /* Note: D language specification should not have any assumption about backend
1068          * implementation. Ideally pragma(mangle) can accept a string of any content.
1069          *
1070          * Therefore, this validation is compiler implementation specific.
1071          */
1072         for (size_t i = 0; i < se->len; )
1073         {
1074             utf8_t *p = (utf8_t *)se->string;
1075             dchar_t c = p[i];
1076             if (c < 0x80)
1077             {
1078                 if ((c >= 'A' && c <= 'Z') ||
1079                     (c >= 'a' && c <= 'z') ||
1080                     (c >= '0' && c <= '9') ||
1081                     (c != 0 && strchr("$%().:?@[]_", c)))
1082                 {
1083                     ++i;
1084                     continue;
1085                 }
1086                 else
1087                 {
1088                     error("char 0x%02x not allowed in mangled name", c);
1089                     break;
1090                 }
1091             }
1092 
1093             if (const char* msg = utf_decodeChar((utf8_t *)se->string, se->len, &i, &c))
1094             {
1095                 error("%s", msg);
1096                 break;
1097             }
1098 
1099             if (!isUniAlpha(c))
1100             {
1101                 error("char 0x%04x not allowed in mangled name", c);
1102                 break;
1103             }
1104         }
1105     }
1106     else if (global.params.ignoreUnsupportedPragmas)
1107     {
1108         if (global.params.verbose)
1109         {
1110             /* Print unrecognized pragmas
1111              */
1112             OutBuffer buf;
1113             buf.writestring(ident->toChars());
1114             if (args)
1115             {
1116                 for (size_t i = 0; i < args->dim; i++)
1117                 {
1118                     Expression *e = (*args)[i];
1119 
1120                     sc = sc->startCTFE();
1121                     e = ::semantic(e, sc);
1122                     e = resolveProperties(sc, e);
1123                     sc = sc->endCTFE();
1124 
1125                     e = e->ctfeInterpret();
1126                     if (i == 0)
1127                         buf.writestring(" (");
1128                     else
1129                         buf.writeByte(',');
1130                     buf.writestring(e->toChars());
1131                 }
1132                 if (args->dim)
1133                     buf.writeByte(')');
1134             }
1135             message("pragma    %s", buf.peekString());
1136         }
1137         goto Lnodecl;
1138     }
1139     else
1140         error("unrecognized pragma(%s)", ident->toChars());
1141 
1142 Ldecl:
1143     if (decl)
1144     {
1145         Scope *sc2 = newScope(sc);
1146 
1147         for (size_t i = 0; i < decl->dim; i++)
1148         {
1149             Dsymbol *s = (*decl)[i];
1150 
1151             s->semantic(sc2);
1152 
1153             if (ident == Id::mangle)
1154             {
1155                 assert(args && args->dim == 1);
1156                 if (StringExp *se = (*args)[0]->toStringExp())
1157                 {
1158                     char *name = (char *)mem.xmalloc(se->len + 1);
1159                     memcpy(name, se->string, se->len);
1160                     name[se->len] = 0;
1161 
1162                     unsigned cnt = setMangleOverride(s, name);
1163                     if (cnt > 1)
1164                         error("can only apply to a single declaration");
1165                 }
1166             }
1167         }
1168 
1169         if (sc2 != sc)
1170             sc2->pop();
1171     }
1172     return;
1173 
1174 Lnodecl:
1175     if (decl)
1176     {
1177         error("pragma is missing closing ';'");
1178         goto Ldecl; // do them anyway, to avoid segfaults.
1179     }
1180 }
1181 
kind()1182 const char *PragmaDeclaration::kind() const
1183 {
1184     return "pragma";
1185 }
1186 
1187 /********************************* ConditionalDeclaration ****************************/
1188 
ConditionalDeclaration(Condition * condition,Dsymbols * decl,Dsymbols * elsedecl)1189 ConditionalDeclaration::ConditionalDeclaration(Condition *condition, Dsymbols *decl, Dsymbols *elsedecl)
1190         : AttribDeclaration(decl)
1191 {
1192     //printf("ConditionalDeclaration::ConditionalDeclaration()\n");
1193     this->condition = condition;
1194     this->elsedecl = elsedecl;
1195 }
1196 
syntaxCopy(Dsymbol * s)1197 Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s)
1198 {
1199     assert(!s);
1200     return new ConditionalDeclaration(condition->syntaxCopy(),
1201         Dsymbol::arraySyntaxCopy(decl),
1202         Dsymbol::arraySyntaxCopy(elsedecl));
1203 }
1204 
oneMember(Dsymbol ** ps,Identifier * ident)1205 bool ConditionalDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
1206 {
1207     //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition->inc);
1208     if (condition->inc)
1209     {
1210         Dsymbols *d = condition->include(NULL, NULL) ? decl : elsedecl;
1211         return Dsymbol::oneMembers(d, ps, ident);
1212     }
1213     else
1214     {
1215         bool res = (Dsymbol::oneMembers(    decl, ps, ident) && *ps == NULL &&
1216                     Dsymbol::oneMembers(elsedecl, ps, ident) && *ps == NULL);
1217         *ps = NULL;
1218         return res;
1219     }
1220 }
1221 
1222 // Decide if 'then' or 'else' code should be included
1223 
include(Scope * sc,ScopeDsymbol * sds)1224 Dsymbols *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sds)
1225 {
1226     //printf("ConditionalDeclaration::include(sc = %p) _scope = %p\n", sc, _scope);
1227 
1228     if (errors)
1229         return NULL;
1230 
1231     assert(condition);
1232     return condition->include(_scope ? _scope : sc, sds) ? decl : elsedecl;
1233 }
1234 
setScope(Scope * sc)1235 void ConditionalDeclaration::setScope(Scope *sc)
1236 {
1237     Dsymbols *d = include(sc, NULL);
1238 
1239     //printf("\tConditionalDeclaration::setScope '%s', d = %p\n",toChars(), d);
1240     if (d)
1241     {
1242        for (size_t i = 0; i < d->dim; i++)
1243        {
1244            Dsymbol *s = (*d)[i];
1245            s->setScope(sc);
1246        }
1247     }
1248 }
1249 
addComment(const utf8_t * comment)1250 void ConditionalDeclaration::addComment(const utf8_t *comment)
1251 {
1252     /* Because addComment is called by the parser, if we called
1253      * include() it would define a version before it was used.
1254      * But it's no problem to drill down to both decl and elsedecl,
1255      * so that's the workaround.
1256      */
1257 
1258     if (comment)
1259     {
1260         Dsymbols *d = decl;
1261 
1262         for (int j = 0; j < 2; j++)
1263         {
1264             if (d)
1265             {
1266                 for (size_t i = 0; i < d->dim; i++)
1267                 {
1268                     Dsymbol *s = (*d)[i];
1269                     //printf("ConditionalDeclaration::addComment %s\n", s->toChars());
1270                     s->addComment(comment);
1271                 }
1272             }
1273             d = elsedecl;
1274         }
1275     }
1276 }
1277 
1278 /***************************** StaticIfDeclaration ****************************/
1279 
StaticIfDeclaration(Condition * condition,Dsymbols * decl,Dsymbols * elsedecl)1280 StaticIfDeclaration::StaticIfDeclaration(Condition *condition,
1281         Dsymbols *decl, Dsymbols *elsedecl)
1282         : ConditionalDeclaration(condition, decl, elsedecl)
1283 {
1284     //printf("StaticIfDeclaration::StaticIfDeclaration()\n");
1285     scopesym = NULL;
1286     addisdone = false;
1287     onStack = false;
1288 }
1289 
syntaxCopy(Dsymbol * s)1290 Dsymbol *StaticIfDeclaration::syntaxCopy(Dsymbol *s)
1291 {
1292     assert(!s);
1293     return new StaticIfDeclaration(condition->syntaxCopy(),
1294         Dsymbol::arraySyntaxCopy(decl),
1295         Dsymbol::arraySyntaxCopy(elsedecl));
1296 }
1297 
1298 /****************************************
1299  * Different from other AttribDeclaration subclasses, include() call requires
1300  * the completion of addMember and setScope phases.
1301  */
include(Scope * sc,ScopeDsymbol *)1302 Dsymbols *StaticIfDeclaration::include(Scope *sc, ScopeDsymbol *)
1303 {
1304     //printf("StaticIfDeclaration::include(sc = %p) _scope = %p\n", sc, _scope);
1305 
1306     if (errors || onStack)
1307         return NULL;
1308     onStack = true;
1309     Dsymbols *d;
1310 
1311     if (condition->inc == 0)
1312     {
1313         assert(scopesym);   // addMember is already done
1314         assert(_scope);      // setScope is already done
1315 
1316         d = ConditionalDeclaration::include(_scope, scopesym);
1317 
1318         if (d && !addisdone)
1319         {
1320             // Add members lazily.
1321             for (size_t i = 0; i < d->dim; i++)
1322             {
1323                 Dsymbol *s = (*d)[i];
1324                 s->addMember(_scope, scopesym);
1325             }
1326 
1327             // Set the member scopes lazily.
1328             for (size_t i = 0; i < d->dim; i++)
1329             {
1330                 Dsymbol *s = (*d)[i];
1331                 s->setScope(_scope);
1332             }
1333 
1334             addisdone = true;
1335         }
1336         onStack = false;
1337         return d;
1338     }
1339     else
1340     {
1341         d = ConditionalDeclaration::include(sc, scopesym);
1342         onStack = false;
1343         return d;
1344     }
1345 }
1346 
addMember(Scope *,ScopeDsymbol * sds)1347 void StaticIfDeclaration::addMember(Scope *, ScopeDsymbol *sds)
1348 {
1349     //printf("StaticIfDeclaration::addMember() '%s'\n", toChars());
1350     /* This is deferred until the condition evaluated later (by the include() call),
1351      * so that 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->scopesym = sds;
1362 }
1363 
importAll(Scope *)1364 void StaticIfDeclaration::importAll(Scope *)
1365 {
1366     // do not evaluate condition before semantic pass
1367 }
1368 
setScope(Scope * sc)1369 void StaticIfDeclaration::setScope(Scope *sc)
1370 {
1371     // do not evaluate condition before semantic pass
1372 
1373     // But do set the scope, in case we need it for forward referencing
1374     Dsymbol::setScope(sc);
1375 }
1376 
semantic(Scope * sc)1377 void StaticIfDeclaration::semantic(Scope *sc)
1378 {
1379     AttribDeclaration::semantic(sc);
1380 }
1381 
kind()1382 const char *StaticIfDeclaration::kind() const
1383 {
1384     return "static if";
1385 }
1386 
1387 /***************************** StaticForeachDeclaration ***********************/
1388 
1389 /* Static foreach at declaration scope, like:
1390  *     static foreach (i; [0, 1, 2]){ }
1391  */
1392 
StaticForeachDeclaration(StaticForeach * sfe,Dsymbols * decl)1393 StaticForeachDeclaration::StaticForeachDeclaration(StaticForeach *sfe, Dsymbols *decl)
1394         : AttribDeclaration(decl)
1395 {
1396     this->sfe = sfe;
1397     this->scopesym = NULL;
1398     this->onStack = false;
1399     this->cached = false;
1400     this->cache = NULL;
1401 }
1402 
syntaxCopy(Dsymbol * s)1403 Dsymbol *StaticForeachDeclaration::syntaxCopy(Dsymbol *s)
1404 {
1405     assert(!s);
1406     return new StaticForeachDeclaration(
1407         sfe->syntaxCopy(),
1408         Dsymbol::arraySyntaxCopy(decl));
1409 }
1410 
oneMember(Dsymbol ** ps,Identifier * ident)1411 bool StaticForeachDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
1412 {
1413     // Required to support IFTI on a template that contains a
1414     // `static foreach` declaration.  `super.oneMember` calls
1415     // include with a `null` scope.  As `static foreach` requires
1416     // the scope for expansion, `oneMember` can only return a
1417     // precise result once `static foreach` has been expanded.
1418     if (cached)
1419     {
1420         return AttribDeclaration::oneMember(ps, ident);
1421     }
1422     *ps = NULL; // a `static foreach` declaration may in general expand to multiple symbols
1423     return false;
1424 }
1425 
include(Scope *,ScopeDsymbol *)1426 Dsymbols *StaticForeachDeclaration::include(Scope *, ScopeDsymbol *)
1427 {
1428     if (errors || onStack)
1429         return NULL;
1430     if (cached)
1431     {
1432         assert(!onStack);
1433         return cache;
1434     }
1435     onStack = true;
1436 
1437     if (_scope)
1438     {
1439         staticForeachPrepare(sfe, _scope); // lower static foreach aggregate
1440     }
1441     if (!staticForeachReady(sfe))
1442     {
1443         onStack = false;
1444         return NULL; // TODO: ok?
1445     }
1446 
1447     // expand static foreach
1448     Dsymbols *d = makeTupleForeachStaticDecl(_scope, sfe->aggrfe, decl, sfe->needExpansion);
1449     if (d) // process generated declarations
1450     {
1451         // Add members lazily.
1452         for (size_t i = 0; i < d->dim; i++)
1453         {
1454             Dsymbol *s = (*d)[i];
1455             s->addMember(_scope, scopesym);
1456         }
1457         // Set the member scopes lazily.
1458         for (size_t i = 0; i < d->dim; i++)
1459         {
1460             Dsymbol *s = (*d)[i];
1461             s->setScope(_scope);
1462         }
1463     }
1464     onStack = false;
1465     cached = true;
1466     cache = d;
1467     return d;
1468 }
1469 
addMember(Scope *,ScopeDsymbol * sds)1470 void StaticForeachDeclaration::addMember(Scope *, ScopeDsymbol *sds)
1471 {
1472     // used only for caching the enclosing symbol
1473     this->scopesym = sds;
1474 }
1475 
addComment(const utf8_t *)1476 void StaticForeachDeclaration::addComment(const utf8_t *)
1477 {
1478     // do nothing
1479     // change this to give semantics to documentation comments on static foreach declarations
1480 }
1481 
setScope(Scope * sc)1482 void StaticForeachDeclaration::setScope(Scope *sc)
1483 {
1484     // do not evaluate condition before semantic pass
1485     // But do set the scope, in case we need it for forward referencing
1486     Dsymbol::setScope(sc);
1487 }
1488 
importAll(Scope *)1489 void StaticForeachDeclaration::importAll(Scope *)
1490 {
1491     // do not evaluate aggregate before semantic pass
1492 }
1493 
semantic(Scope * sc)1494 void StaticForeachDeclaration::semantic(Scope *sc)
1495 {
1496     AttribDeclaration::semantic(sc);
1497 }
1498 
kind()1499 const char *StaticForeachDeclaration::kind() const
1500 {
1501     return "static foreach";
1502 }
1503 
1504 /***********************************************************
1505  * Collection of declarations that stores foreach index variables in a
1506  * local symbol table.  Other symbols declared within are forwarded to
1507  * another scope, like:
1508  *
1509  *      static foreach (i; 0 .. 10) // loop variables for different indices do not conflict.
1510  *      { // this body is expanded into 10 ForwardingAttribDeclarations, where `i` has storage class STClocal
1511  *          mixin("enum x" ~ to!string(i) ~ " = i"); // ok, can access current loop variable
1512  *      }
1513  *
1514  *      static foreach (i; 0.. 10)
1515  *      {
1516  *          pragma(msg, mixin("x" ~ to!string(i))); // ok, all 10 symbols are visible as they were forwarded to the global scope
1517  *      }
1518  *
1519  *      static assert (!is(typeof(i))); // loop index variable is not visible outside of the static foreach loop
1520  *
1521  * A StaticForeachDeclaration generates one
1522  * ForwardingAttribDeclaration for each expansion of its body.  The
1523  * AST of the ForwardingAttribDeclaration contains both the `static
1524  * foreach` variables and the respective copy of the `static foreach`
1525  * body.  The functionality is achieved by using a
1526  * ForwardingScopeDsymbol as the parent symbol for the generated
1527  * declarations.
1528  */
1529 
ForwardingAttribDeclaration(Dsymbols * decl)1530 ForwardingAttribDeclaration::ForwardingAttribDeclaration(Dsymbols *decl)
1531         : AttribDeclaration(decl)
1532 {
1533     sym = new ForwardingScopeDsymbol(NULL);
1534     sym->symtab = new DsymbolTable();
1535 }
1536 
1537 /**************************************
1538  * Use the ForwardingScopeDsymbol as the parent symbol for members.
1539  */
newScope(Scope * sc)1540 Scope *ForwardingAttribDeclaration::newScope(Scope *sc)
1541 {
1542     return sc->push(sym);
1543 }
1544 
1545 /***************************************
1546  * Lazily initializes the scope to forward to.
1547  */
addMember(Scope * sc,ScopeDsymbol * sds)1548 void ForwardingAttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
1549 {
1550     parent = sym->parent = sym->forward = sds;
1551     return AttribDeclaration::addMember(sc, sym);
1552 }
1553 
1554 /***************************** CompileDeclaration *****************************/
1555 
1556 // These are mixin declarations, like mixin("int x");
1557 
CompileDeclaration(Loc loc,Expression * exp)1558 CompileDeclaration::CompileDeclaration(Loc loc, Expression *exp)
1559     : AttribDeclaration(NULL)
1560 {
1561     //printf("CompileDeclaration(loc = %d)\n", loc.linnum);
1562     this->loc = loc;
1563     this->exp = exp;
1564     this->scopesym = NULL;
1565     this->compiled = false;
1566 }
1567 
syntaxCopy(Dsymbol *)1568 Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *)
1569 {
1570     //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars());
1571     return new CompileDeclaration(loc, exp->syntaxCopy());
1572 }
1573 
addMember(Scope *,ScopeDsymbol * sds)1574 void CompileDeclaration::addMember(Scope *, ScopeDsymbol *sds)
1575 {
1576     //printf("CompileDeclaration::addMember(sc = %p, sds = %p, memnum = %d)\n", sc, sds, memnum);
1577     this->scopesym = sds;
1578 }
1579 
setScope(Scope * sc)1580 void CompileDeclaration::setScope(Scope *sc)
1581 {
1582     Dsymbol::setScope(sc);
1583 }
1584 
compileIt(Scope * sc)1585 void CompileDeclaration::compileIt(Scope *sc)
1586 {
1587     //printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars());
1588     StringExp *se = semanticString(sc, exp, "argument to mixin");
1589     if (!se)
1590         return;
1591     se = se->toUTF8(sc);
1592 
1593     unsigned errors = global.errors;
1594     Parser p(loc, sc->_module, (utf8_t *)se->string, se->len, 0);
1595     p.nextToken();
1596 
1597     decl = p.parseDeclDefs(0);
1598     if (p.token.value != TOKeof)
1599         exp->error("incomplete mixin declaration (%s)", se->toChars());
1600     if (p.errors)
1601     {
1602         assert(global.errors != errors);
1603         decl = NULL;
1604     }
1605 }
1606 
semantic(Scope * sc)1607 void CompileDeclaration::semantic(Scope *sc)
1608 {
1609     //printf("CompileDeclaration::semantic()\n");
1610 
1611     if (!compiled)
1612     {
1613         compileIt(sc);
1614         AttribDeclaration::addMember(sc, scopesym);
1615         compiled = true;
1616 
1617         if (_scope && decl)
1618         {
1619             for (size_t i = 0; i < decl->dim; i++)
1620             {
1621                 Dsymbol *s = (*decl)[i];
1622                 s->setScope(_scope);
1623             }
1624         }
1625     }
1626     AttribDeclaration::semantic(sc);
1627 }
1628 
kind()1629 const char *CompileDeclaration::kind() const
1630 {
1631     return "mixin";
1632 }
1633 
1634 /***************************** UserAttributeDeclaration *****************************/
1635 
UserAttributeDeclaration(Expressions * atts,Dsymbols * decl)1636 UserAttributeDeclaration::UserAttributeDeclaration(Expressions *atts, Dsymbols *decl)
1637         : AttribDeclaration(decl)
1638 {
1639     //printf("UserAttributeDeclaration()\n");
1640     this->atts = atts;
1641 }
1642 
syntaxCopy(Dsymbol * s)1643 Dsymbol *UserAttributeDeclaration::syntaxCopy(Dsymbol *s)
1644 {
1645     //printf("UserAttributeDeclaration::syntaxCopy('%s')\n", toChars());
1646     assert(!s);
1647     return new UserAttributeDeclaration(
1648         Expression::arraySyntaxCopy(this->atts),
1649         Dsymbol::arraySyntaxCopy(decl));
1650 }
1651 
newScope(Scope * sc)1652 Scope *UserAttributeDeclaration::newScope(Scope *sc)
1653 {
1654     Scope *sc2 = sc;
1655     if (atts && atts->dim)
1656     {
1657         // create new one for changes
1658         sc2 = sc->copy();
1659         sc2->userAttribDecl = this;
1660     }
1661     return sc2;
1662 }
1663 
setScope(Scope * sc)1664 void UserAttributeDeclaration::setScope(Scope *sc)
1665 {
1666     //printf("UserAttributeDeclaration::setScope() %p\n", this);
1667     if (decl)
1668         Dsymbol::setScope(sc);  // for forward reference of UDAs
1669 
1670     return AttribDeclaration::setScope(sc);
1671 }
1672 
semantic(Scope * sc)1673 void UserAttributeDeclaration::semantic(Scope *sc)
1674 {
1675     //printf("UserAttributeDeclaration::semantic() %p\n", this);
1676     if (decl && !_scope)
1677         Dsymbol::setScope(sc);  // for function local symbols
1678 
1679     return AttribDeclaration::semantic(sc);
1680 }
1681 
udaExpressionEval(Scope * sc,Expressions * exps)1682 static void udaExpressionEval(Scope *sc, Expressions *exps)
1683 {
1684     for (size_t i = 0; i < exps->dim; i++)
1685     {
1686         Expression *e = (*exps)[i];
1687         if (e)
1688         {
1689             e = ::semantic(e, sc);
1690             if (definitelyValueParameter(e))
1691                 e = e->ctfeInterpret();
1692             if (e->op == TOKtuple)
1693             {
1694                 TupleExp *te = (TupleExp *)e;
1695                 udaExpressionEval(sc, te->exps);
1696             }
1697             (*exps)[i] = e;
1698         }
1699     }
1700 }
1701 
semantic2(Scope * sc)1702 void UserAttributeDeclaration::semantic2(Scope *sc)
1703 {
1704     if (decl && atts && atts->dim && _scope)
1705     {
1706         _scope = NULL;
1707         udaExpressionEval(sc, atts);
1708     }
1709 
1710     AttribDeclaration::semantic2(sc);
1711 }
1712 
concat(Expressions * udas1,Expressions * udas2)1713 Expressions *UserAttributeDeclaration::concat(Expressions *udas1, Expressions *udas2)
1714 {
1715     Expressions *udas;
1716     if (!udas1 || udas1->dim == 0)
1717         udas = udas2;
1718     else if (!udas2 || udas2->dim == 0)
1719         udas = udas1;
1720     else
1721     {
1722         /* Create a new tuple that combines them
1723          * (do not append to left operand, as this is a copy-on-write operation)
1724          */
1725         udas = new Expressions();
1726         udas->push(new TupleExp(Loc(), udas1));
1727         udas->push(new TupleExp(Loc(), udas2));
1728     }
1729     return udas;
1730 }
1731 
getAttributes()1732 Expressions *UserAttributeDeclaration::getAttributes()
1733 {
1734     if (Scope *sc = _scope)
1735     {
1736         _scope = NULL;
1737         arrayExpressionSemantic(atts, sc);
1738     }
1739 
1740     Expressions *exps = new Expressions();
1741     if (userAttribDecl)
1742         exps->push(new TupleExp(Loc(), userAttribDecl->getAttributes()));
1743     if (atts && atts->dim)
1744         exps->push(new TupleExp(Loc(), atts));
1745 
1746     return exps;
1747 }
1748 
kind()1749 const char *UserAttributeDeclaration::kind() const
1750 {
1751     return "UserAttribute";
1752 }
1753