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