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