]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/dmd/attrib.c
d/dmd: Merge upstream dmd e9420cfbf
[thirdparty/gcc.git] / gcc / d / dmd / attrib.c
CommitLineData
b4c522fa
IB
1
2/* Compiler implementation of the D programming language
f3ed896c 3 * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
b4c522fa
IB
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
f9ab59ff 11#include "root/dsystem.h" // memcmp()
b4c522fa
IB
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
31bool definitelyValueParameter(Expression *e);
32Expression *semantic(Expression *e, Scope *sc);
8f5439be 33StringExp *semanticString(Scope *sc, Expression *exp, const char *s);
5b74dd0a 34Dsymbols *makeTupleForeachStaticDecl(Scope *sc, ForeachStatement *fs, Dsymbols *dbody, bool needExpansion);
b4c522fa
IB
35
36/********************************* AttribDeclaration ****************************/
37
38AttribDeclaration::AttribDeclaration(Dsymbols *decl)
39 : Dsymbol()
40{
41 this->decl = decl;
42}
43
44Dsymbols *AttribDeclaration::include(Scope *, ScopeDsymbol *)
45{
5b74dd0a
IB
46 if (errors)
47 return NULL;
48
b4c522fa
IB
49 return decl;
50}
51
52int 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 */
77Scope *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 */
107Scope *AttribDeclaration::newScope(Scope *sc)
108{
109 return sc;
110}
111
112void 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
132void 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
152void 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
172void 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
196void 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
215void 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
234void 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
253void 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
267bool 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
283bool 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
299const char *AttribDeclaration::kind() const
300{
301 return "attribute";
302}
303
304bool AttribDeclaration::oneMember(Dsymbol **ps, Identifier *ident)
305{
306 Dsymbols *d = include(NULL, NULL);
307
308 return Dsymbol::oneMembers(d, ps, ident);
309}
310
311void 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
328void 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
344StorageClassDeclaration::StorageClassDeclaration(StorageClass stc, Dsymbols *decl)
345 : AttribDeclaration(decl)
346{
347 this->stc = stc;
348}
349
350Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s)
351{
352 assert(!s);
353 return new StorageClassDeclaration(stc, Dsymbol::arraySyntaxCopy(decl));
354}
355
356bool 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
384void 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
410Scope *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
437DeprecatedDeclaration::DeprecatedDeclaration(Expression *msg, Dsymbols *decl)
438 : StorageClassDeclaration(STCdeprecated, decl)
439{
440 this->msg = msg;
441 this->msgstr = NULL;
442}
443
444Dsymbol *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 */
459Scope *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
469void 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 */
487void DeprecatedDeclaration::semantic2(Scope *sc)
488{
489 getMessage();
490 StorageClassDeclaration::semantic2(sc);
491}
492
493const 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
515LinkDeclaration::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
522LinkDeclaration *LinkDeclaration::create(LINK p, Dsymbols *decl)
523{
524 return new LinkDeclaration(p, decl);
525}
526
527Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s)
528{
529 assert(!s);
530 return new LinkDeclaration(linkage, Dsymbol::arraySyntaxCopy(decl));
531}
532
533Scope *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
540const char *LinkDeclaration::toChars()
541{
542 return "extern ()";
543}
544
545/********************************* CPPMangleDeclaration ****************************/
546
547CPPMangleDeclaration::CPPMangleDeclaration(CPPMANGLE p, Dsymbols *decl)
548 : AttribDeclaration(decl)
549{
550 //printf("CPPMangleDeclaration(cppmangle = %d, decl = %p)\n", p, decl);
551 cppmangle = p;
552}
553
554Dsymbol *CPPMangleDeclaration::syntaxCopy(Dsymbol *s)
555{
556 assert(!s);
557 return new CPPMangleDeclaration(cppmangle, Dsymbol::arraySyntaxCopy(decl));
558}
559
560Scope *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
567const 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 */
580ProtDeclaration::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 */
595ProtDeclaration::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
604Dsymbol *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
613Scope *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
622void 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
644const char *ProtDeclaration::kind() const
645{
646 return "protection attribute";
647}
648
649const 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
662AlignDeclaration::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
670Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s)
671{
672 assert(!s);
673 return new AlignDeclaration(loc,
22682e5b
IB
674 ealign ? ealign->syntaxCopy() : NULL,
675 Dsymbol::arraySyntaxCopy(decl));
b4c522fa
IB
676}
677
678Scope *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
685void AlignDeclaration::semantic2(Scope *sc)
686{
687 getAlignment(sc);
688 AttribDeclaration::semantic2(sc);
689}
690
691structalign_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
722AnonDeclaration::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
733Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s)
734{
735 assert(!s);
736 return new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl));
737}
738
739void 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
747void 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());
5b74dd0a 759 errors = true;
b4c522fa
IB
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
779void 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
857const char *AnonDeclaration::kind() const
858{
859 return (isunion ? "anonymous union" : "anonymous struct");
860}
861
862/********************************* PragmaDeclaration ****************************/
863
864PragmaDeclaration::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
872Dsymbol *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
881Scope *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
919static 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
943void 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 {
8f5439be 987 StringExp *se = semanticString(sc, (*args)[0], "library name");
b4c522fa 988 if (!se)
8f5439be
IB
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)
b4c522fa 998 {
8f5439be
IB
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();
b4c522fa 1008 }
8f5439be 1009 mem.xfree(name);
b4c522fa
IB
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
8f5439be 1051 StringExp *se = semanticString(sc, (*args)[0], "mangled name");
b4c522fa 1052 if (!se)
b4c522fa 1053 goto Ldecl;
8f5439be
IB
1054 (*args)[0] = se; // Will be used for later
1055
b4c522fa
IB
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
1142Ldecl:
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
1174Lnodecl:
1175 if (decl)
1176 {
1177 error("pragma is missing closing ';'");
1178 goto Ldecl; // do them anyway, to avoid segfaults.
1179 }
1180}
1181
1182const char *PragmaDeclaration::kind() const
1183{
1184 return "pragma";
1185}
1186
1187/********************************* ConditionalDeclaration ****************************/
1188
1189ConditionalDeclaration::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
1197Dsymbol *ConditionalDeclaration::syntaxCopy(Dsymbol *s)
1198{
1199 assert(!s);
1200 return new ConditionalDeclaration(condition->syntaxCopy(),
1201 Dsymbol::arraySyntaxCopy(decl),
1202 Dsymbol::arraySyntaxCopy(elsedecl));
1203}
1204
1205bool 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
1224Dsymbols *ConditionalDeclaration::include(Scope *sc, ScopeDsymbol *sds)
1225{
1226 //printf("ConditionalDeclaration::include(sc = %p) _scope = %p\n", sc, _scope);
5b74dd0a
IB
1227
1228 if (errors)
1229 return NULL;
1230
b4c522fa
IB
1231 assert(condition);
1232 return condition->include(_scope ? _scope : sc, sds) ? decl : elsedecl;
1233}
1234
1235void 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
1250void 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
1280StaticIfDeclaration::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;
5b74dd0a 1287 onStack = false;
b4c522fa
IB
1288}
1289
1290Dsymbol *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 */
1302Dsymbols *StaticIfDeclaration::include(Scope *sc, ScopeDsymbol *)
1303{
1304 //printf("StaticIfDeclaration::include(sc = %p) _scope = %p\n", sc, _scope);
1305
5b74dd0a
IB
1306 if (errors || onStack)
1307 return NULL;
1308 onStack = true;
1309 Dsymbols *d;
1310
b4c522fa
IB
1311 if (condition->inc == 0)
1312 {
1313 assert(scopesym); // addMember is already done
1314 assert(_scope); // setScope is already done
1315
5b74dd0a 1316 d = ConditionalDeclaration::include(_scope, scopesym);
b4c522fa
IB
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 }
5b74dd0a 1336 onStack = false;
b4c522fa
IB
1337 return d;
1338 }
1339 else
1340 {
5b74dd0a
IB
1341 d = ConditionalDeclaration::include(sc, scopesym);
1342 onStack = false;
1343 return d;
b4c522fa
IB
1344 }
1345}
1346
1347void 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
1364void StaticIfDeclaration::importAll(Scope *)
1365{
1366 // do not evaluate condition before semantic pass
1367}
1368
1369void 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
1377void StaticIfDeclaration::semantic(Scope *sc)
1378{
1379 AttribDeclaration::semantic(sc);
1380}
1381
1382const char *StaticIfDeclaration::kind() const
1383{
1384 return "static if";
1385}
1386
5b74dd0a
IB
1387/***************************** StaticForeachDeclaration ***********************/
1388
1389/* Static foreach at declaration scope, like:
1390 * static foreach (i; [0, 1, 2]){ }
1391 */
1392
1393StaticForeachDeclaration::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
1403Dsymbol *StaticForeachDeclaration::syntaxCopy(Dsymbol *s)
1404{
1405 assert(!s);
1406 return new StaticForeachDeclaration(
1407 sfe->syntaxCopy(),
1408 Dsymbol::arraySyntaxCopy(decl));
1409}
1410
1411bool 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
1426Dsymbols *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
1470void StaticForeachDeclaration::addMember(Scope *, ScopeDsymbol *sds)
1471{
1472 // used only for caching the enclosing symbol
1473 this->scopesym = sds;
1474}
1475
1476void StaticForeachDeclaration::addComment(const utf8_t *)
1477{
1478 // do nothing
1479 // change this to give semantics to documentation comments on static foreach declarations
1480}
1481
1482void 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
1489void StaticForeachDeclaration::importAll(Scope *)
1490{
1491 // do not evaluate aggregate before semantic pass
1492}
1493
1494void StaticForeachDeclaration::semantic(Scope *sc)
1495{
1496 AttribDeclaration::semantic(sc);
1497}
1498
1499const 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
1530ForwardingAttribDeclaration::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 */
1540Scope *ForwardingAttribDeclaration::newScope(Scope *sc)
1541{
1542 return sc->push(sym);
1543}
1544
1545/***************************************
1546 * Lazily initializes the scope to forward to.
1547 */
1548void ForwardingAttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sds)
1549{
1550 parent = sym->parent = sym->forward = sds;
1551 return AttribDeclaration::addMember(sc, sym);
1552}
1553
b4c522fa
IB
1554/***************************** CompileDeclaration *****************************/
1555
1556// These are mixin declarations, like mixin("int x");
1557
1558CompileDeclaration::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
1568Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *)
1569{
1570 //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars());
1571 return new CompileDeclaration(loc, exp->syntaxCopy());
1572}
1573
1574void 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
1580void CompileDeclaration::setScope(Scope *sc)
1581{
1582 Dsymbol::setScope(sc);
1583}
1584
1585void CompileDeclaration::compileIt(Scope *sc)
1586{
1587 //printf("CompileDeclaration::compileIt(loc = %d) %s\n", loc.linnum, exp->toChars());
8f5439be
IB
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();
b4c522fa 1596
8f5439be
IB
1597 decl = p.parseDeclDefs(0);
1598 if (p.token.value != TOKeof)
1599 exp->error("incomplete mixin declaration (%s)", se->toChars());
1600 if (p.errors)
b4c522fa 1601 {
8f5439be
IB
1602 assert(global.errors != errors);
1603 decl = NULL;
b4c522fa
IB
1604 }
1605}
1606
1607void 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
1629const char *CompileDeclaration::kind() const
1630{
1631 return "mixin";
1632}
1633
1634/***************************** UserAttributeDeclaration *****************************/
1635
1636UserAttributeDeclaration::UserAttributeDeclaration(Expressions *atts, Dsymbols *decl)
1637 : AttribDeclaration(decl)
1638{
1639 //printf("UserAttributeDeclaration()\n");
1640 this->atts = atts;
1641}
1642
1643Dsymbol *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
1652Scope *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
1664void 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
1673void 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
1682static 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
1702void 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
1713Expressions *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
1732Expressions *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
1749const char *UserAttributeDeclaration::kind() const
1750{
1751 return "UserAttribute";
1752}