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