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 37 AttribDeclaration::AttribDeclaration(Dsymbols *decl) 38 : Dsymbol() 39 { 40 this->decl = decl; 41 } 42 43 Dsymbols *AttribDeclaration::include(Scope *, ScopeDsymbol *) 44 { 45 return decl; 46 } 47 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 */ 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 */ 103 Scope *AttribDeclaration::newScope(Scope *sc) 104 { 105 return sc; 106 } 107 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 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 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 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 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 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 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 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 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 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 295 const char *AttribDeclaration::kind() const 296 { 297 return "attribute"; 298 } 299 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 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 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 340 StorageClassDeclaration::StorageClassDeclaration(StorageClass stc, Dsymbols *decl) 341 : AttribDeclaration(decl) 342 { 343 this->stc = stc; 344 } 345 346 Dsymbol *StorageClassDeclaration::syntaxCopy(Dsymbol *s) 347 { 348 assert(!s); 349 return new StorageClassDeclaration(stc, Dsymbol::arraySyntaxCopy(decl)); 350 } 351 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 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 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 433 DeprecatedDeclaration::DeprecatedDeclaration(Expression *msg, Dsymbols *decl) 434 : StorageClassDeclaration(STCdeprecated, decl) 435 { 436 this->msg = msg; 437 this->msgstr = NULL; 438 } 439 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 */ 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 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 */ 483 void DeprecatedDeclaration::semantic2(Scope *sc) 484 { 485 getMessage(); 486 StorageClassDeclaration::semantic2(sc); 487 } 488 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 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 518 LinkDeclaration *LinkDeclaration::create(LINK p, Dsymbols *decl) 519 { 520 return new LinkDeclaration(p, decl); 521 } 522 523 Dsymbol *LinkDeclaration::syntaxCopy(Dsymbol *s) 524 { 525 assert(!s); 526 return new LinkDeclaration(linkage, Dsymbol::arraySyntaxCopy(decl)); 527 } 528 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 536 const char *LinkDeclaration::toChars() 537 { 538 return "extern ()"; 539 } 540 541 /********************************* CPPMangleDeclaration ****************************/ 542 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 550 Dsymbol *CPPMangleDeclaration::syntaxCopy(Dsymbol *s) 551 { 552 assert(!s); 553 return new CPPMangleDeclaration(cppmangle, Dsymbol::arraySyntaxCopy(decl)); 554 } 555 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 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 */ 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 */ 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 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 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 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 640 const char *ProtDeclaration::kind() const 641 { 642 return "protection attribute"; 643 } 644 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 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 666 Dsymbol *AlignDeclaration::syntaxCopy(Dsymbol *s) 667 { 668 assert(!s); 669 return new AlignDeclaration(loc, 670 ealign->syntaxCopy(), Dsymbol::arraySyntaxCopy(decl)); 671 } 672 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 680 void AlignDeclaration::semantic2(Scope *sc) 681 { 682 getAlignment(sc); 683 AttribDeclaration::semantic2(sc); 684 } 685 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 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 728 Dsymbol *AnonDeclaration::syntaxCopy(Dsymbol *s) 729 { 730 assert(!s); 731 return new AnonDeclaration(loc, isunion, Dsymbol::arraySyntaxCopy(decl)); 732 } 733 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 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 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 851 const char *AnonDeclaration::kind() const 852 { 853 return (isunion ? "anonymous union" : "anonymous struct"); 854 } 855 856 /********************************* PragmaDeclaration ****************************/ 857 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 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 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 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 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 1176 const char *PragmaDeclaration::kind() const 1177 { 1178 return "pragma"; 1179 } 1180 1181 /********************************* ConditionalDeclaration ****************************/ 1182 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 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 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 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 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 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 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 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 */ 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 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 1345 void StaticIfDeclaration::importAll(Scope *) 1346 { 1347 // do not evaluate condition before semantic pass 1348 } 1349 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 1358 void StaticIfDeclaration::semantic(Scope *sc) 1359 { 1360 AttribDeclaration::semantic(sc); 1361 } 1362 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 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 1382 Dsymbol *CompileDeclaration::syntaxCopy(Dsymbol *) 1383 { 1384 //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars()); 1385 return new CompileDeclaration(loc, exp->syntaxCopy()); 1386 } 1387 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 1394 void CompileDeclaration::setScope(Scope *sc) 1395 { 1396 Dsymbol::setScope(sc); 1397 } 1398 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 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 1443 const char *CompileDeclaration::kind() const 1444 { 1445 return "mixin"; 1446 } 1447 1448 /***************************** UserAttributeDeclaration *****************************/ 1449 1450 UserAttributeDeclaration::UserAttributeDeclaration(Expressions *atts, Dsymbols *decl) 1451 : AttribDeclaration(decl) 1452 { 1453 //printf("UserAttributeDeclaration()\n"); 1454 this->atts = atts; 1455 } 1456 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 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 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 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 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 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 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 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 1563 const char *UserAttributeDeclaration::kind() const 1564 { 1565 return "UserAttribute"; 1566 } 1567