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