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