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 _dclass.d) 9 */ 10 11 module ddmd.dclass; 12 13 import core.stdc.stdio; 14 import core.stdc..string; 15 16 import ddmd.aggregate; 17 import ddmd.arraytypes; 18 import ddmd.gluelayer; 19 import ddmd.clone; 20 import ddmd.declaration; 21 import ddmd.dmodule; 22 import ddmd.dscope; 23 import ddmd.dsymbol; 24 import ddmd.dtemplate; 25 import ddmd.errors; 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.objc; 33 import ddmd.root.rmem; 34 import ddmd.statement; 35 import ddmd.target; 36 import ddmd.visitor; 37 38 enum Abstract : int 39 { 40 ABSfwdref = 0, // whether an abstract class is not yet computed 41 ABSyes, // is abstract class 42 ABSno, // is not abstract class 43 } 44 45 alias ABSfwdref = Abstract.ABSfwdref; 46 alias ABSyes = Abstract.ABSyes; 47 alias ABSno = Abstract.ABSno; 48 49 /*********************************************************** 50 */ 51 struct BaseClass 52 { 53 Type type; // (before semantic processing) 54 55 ClassDeclaration sym; 56 uint offset; // 'this' pointer offset 57 58 // for interfaces: Array of FuncDeclaration's making up the vtbl[] 59 FuncDeclarations vtbl; 60 61 // if BaseClass is an interface, these 62 // are a copy of the InterfaceDeclaration.interfaces 63 BaseClass[] baseInterfaces; 64 65 extern (D) this(Type type) 66 { 67 //printf("BaseClass(this = %p, '%s')\n", this, type.toChars()); 68 this.type = type; 69 } 70 71 /**************************************** 72 * Fill in vtbl[] for base class based on member functions of class cd. 73 * Input: 74 * vtbl if !=NULL, fill it in 75 * newinstance !=0 means all entries must be filled in by members 76 * of cd, not members of any base classes of cd. 77 * Returns: 78 * true if any entries were filled in by members of cd (not exclusively 79 * by base classes) 80 */ 81 extern (C++) bool fillVtbl(ClassDeclaration cd, FuncDeclarations* vtbl, int newinstance) 82 { 83 bool result = false; 84 85 //printf("BaseClass.fillVtbl(this='%s', cd='%s')\n", sym.toChars(), cd.toChars()); 86 if (vtbl) 87 vtbl.setDim(sym.vtbl.dim); 88 89 // first entry is ClassInfo reference 90 for (size_t j = sym.vtblOffset(); j < sym.vtbl.dim; j++) 91 { 92 FuncDeclaration ifd = sym.vtbl[j].isFuncDeclaration(); 93 FuncDeclaration fd; 94 TypeFunction tf; 95 96 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd.toChars() : "null"); 97 assert(ifd); 98 99 // Find corresponding function in this class 100 tf = (ifd.type.ty == Tfunction) ? cast(TypeFunction)ifd.type : null; 101 assert(tf); // should always be non-null 102 fd = cd.findFunc(ifd.ident, tf); 103 if (fd && !fd.isAbstract()) 104 { 105 //printf(" found\n"); 106 // Check that calling conventions match 107 if (fd.linkage != ifd.linkage) 108 fd.error("linkage doesn't match interface function"); 109 110 // Check that it is current 111 //printf("newinstance = %d fd.toParent() = %s ifd.toParent() = %s\n", 112 //newinstance, fd.toParent().toChars(), ifd.toParent().toChars()); 113 if (newinstance && fd.toParent() != cd && ifd.toParent() == sym) 114 cd.error("interface function '%s' is not implemented", ifd.toFullSignature()); 115 116 if (fd.toParent() == cd) 117 result = true; 118 } 119 else 120 { 121 //printf(" not found %p\n", fd); 122 // BUG: should mark this class as abstract? 123 if (!cd.isAbstract()) 124 cd.error("interface function '%s' is not implemented", ifd.toFullSignature()); 125 126 fd = null; 127 } 128 if (vtbl) 129 (*vtbl)[j] = fd; 130 } 131 return result; 132 } 133 134 extern (C++) void copyBaseInterfaces(BaseClasses* vtblInterfaces) 135 { 136 //printf("+copyBaseInterfaces(), %s\n", sym.toChars()); 137 // if (baseInterfaces_dim) 138 // return; 139 auto bc = cast(BaseClass*)mem.xcalloc(sym.interfaces.length, BaseClass.sizeof); 140 baseInterfaces = bc[0 .. sym.interfaces.length]; 141 //printf("%s.copyBaseInterfaces()\n", sym.toChars()); 142 for (size_t i = 0; i < baseInterfaces.length; i++) 143 { 144 BaseClass* b = &baseInterfaces[i]; 145 BaseClass* b2 = sym.interfaces[i]; 146 147 assert(b2.vtbl.dim == 0); // should not be filled yet 148 memcpy(b, b2, BaseClass.sizeof); 149 150 if (i) // single inheritance is i==0 151 vtblInterfaces.push(b); // only need for M.I. 152 b.copyBaseInterfaces(vtblInterfaces); 153 } 154 //printf("-copyBaseInterfaces\n"); 155 } 156 } 157 158 struct ClassFlags 159 { 160 alias Type = uint; 161 162 enum Enum : int 163 { 164 isCOMclass = 0x1, 165 noPointers = 0x2, 166 hasOffTi = 0x4, 167 hasCtor = 0x8, 168 hasGetMembers = 0x10, 169 hasTypeInfo = 0x20, 170 isAbstract = 0x40, 171 isCPPclass = 0x80, 172 hasDtor = 0x100, 173 } 174 175 alias isCOMclass = Enum.isCOMclass; 176 alias noPointers = Enum.noPointers; 177 alias hasOffTi = Enum.hasOffTi; 178 alias hasCtor = Enum.hasCtor; 179 alias hasGetMembers = Enum.hasGetMembers; 180 alias hasTypeInfo = Enum.hasTypeInfo; 181 alias isAbstract = Enum.isAbstract; 182 alias isCPPclass = Enum.isCPPclass; 183 alias hasDtor = Enum.hasDtor; 184 } 185 186 /*********************************************************** 187 */ 188 extern (C++) class ClassDeclaration : AggregateDeclaration 189 { 190 extern (C++) __gshared 191 { 192 // Names found by reading object.d in druntime 193 ClassDeclaration object; 194 ClassDeclaration throwable; 195 ClassDeclaration exception; 196 ClassDeclaration errorException; 197 ClassDeclaration cpp_type_info_ptr; // Object.__cpp_type_info_ptr 198 } 199 200 ClassDeclaration baseClass; // NULL only if this is Object 201 FuncDeclaration staticCtor; 202 FuncDeclaration staticDtor; 203 Dsymbols vtbl; // Array of FuncDeclaration's making up the vtbl[] 204 Dsymbols vtblFinal; // More FuncDeclaration's that aren't in vtbl[] 205 206 // Array of BaseClass's; first is super, rest are Interface's 207 BaseClasses* baseclasses; 208 209 /* Slice of baseclasses[] that does not include baseClass 210 */ 211 BaseClass*[] interfaces; 212 213 // array of base interfaces that have their own vtbl[] 214 BaseClasses* vtblInterfaces; 215 216 // the ClassInfo object for this ClassDeclaration 217 TypeInfoClassDeclaration vclassinfo; 218 219 bool com; // true if this is a COM class (meaning it derives from IUnknown) 220 bool cpp; // true if this is a C++ interface 221 bool isscope; // true if this is a scope class 222 Abstract isabstract; 223 int inuse; // to prevent recursive attempts 224 Baseok baseok; // set the progress of base classes resolving 225 226 Objc_ClassDeclaration objc; 227 228 Symbol* cpp_type_info_ptr_sym; // cached instance of class Id.cpp_type_info_ptr 229 230 final extern (D) this(Loc loc, Identifier id, BaseClasses* baseclasses, Dsymbols* members, bool inObject) 231 { 232 if (!id) 233 id = Identifier.generateId("__anonclass"); 234 assert(id); 235 236 super(loc, id); 237 238 static __gshared const(char)* msg = "only object.d can define this reserved class name"; 239 240 if (baseclasses) 241 { 242 // Actually, this is a transfer 243 this.baseclasses = baseclasses; 244 } 245 else 246 this.baseclasses = new BaseClasses(); 247 248 this.members = members; 249 250 //printf("ClassDeclaration(%s), dim = %d\n", id.toChars(), this.baseclasses.dim); 251 252 // For forward references 253 type = new TypeClass(this); 254 255 if (id) 256 { 257 // Look for special class names 258 if (id == Id.__sizeof || id == Id.__xalignof || id == Id._mangleof) 259 error("illegal class name"); 260 261 // BUG: What if this is the wrong TypeInfo, i.e. it is nested? 262 if (id.toChars()[0] == 'T') 263 { 264 if (id == Id.TypeInfo) 265 { 266 if (!inObject) 267 error("%s", msg); 268 Type.dtypeinfo = this; 269 } 270 if (id == Id.TypeInfo_Class) 271 { 272 if (!inObject) 273 error("%s", msg); 274 Type.typeinfoclass = this; 275 } 276 if (id == Id.TypeInfo_Interface) 277 { 278 if (!inObject) 279 error("%s", msg); 280 Type.typeinfointerface = this; 281 } 282 if (id == Id.TypeInfo_Struct) 283 { 284 if (!inObject) 285 error("%s", msg); 286 Type.typeinfostruct = this; 287 } 288 if (id == Id.TypeInfo_Pointer) 289 { 290 if (!inObject) 291 error("%s", msg); 292 Type.typeinfopointer = this; 293 } 294 if (id == Id.TypeInfo_Array) 295 { 296 if (!inObject) 297 error("%s", msg); 298 Type.typeinfoarray = this; 299 } 300 if (id == Id.TypeInfo_StaticArray) 301 { 302 //if (!inObject) 303 // Type.typeinfostaticarray.error("%s", msg); 304 Type.typeinfostaticarray = this; 305 } 306 if (id == Id.TypeInfo_AssociativeArray) 307 { 308 if (!inObject) 309 error("%s", msg); 310 Type.typeinfoassociativearray = this; 311 } 312 if (id == Id.TypeInfo_Enum) 313 { 314 if (!inObject) 315 error("%s", msg); 316 Type.typeinfoenum = this; 317 } 318 if (id == Id.TypeInfo_Function) 319 { 320 if (!inObject) 321 error("%s", msg); 322 Type.typeinfofunction = this; 323 } 324 if (id == Id.TypeInfo_Delegate) 325 { 326 if (!inObject) 327 error("%s", msg); 328 Type.typeinfodelegate = this; 329 } 330 if (id == Id.TypeInfo_Tuple) 331 { 332 if (!inObject) 333 error("%s", msg); 334 Type.typeinfotypelist = this; 335 } 336 if (id == Id.TypeInfo_Const) 337 { 338 if (!inObject) 339 error("%s", msg); 340 Type.typeinfoconst = this; 341 } 342 if (id == Id.TypeInfo_Invariant) 343 { 344 if (!inObject) 345 error("%s", msg); 346 Type.typeinfoinvariant = this; 347 } 348 if (id == Id.TypeInfo_Shared) 349 { 350 if (!inObject) 351 error("%s", msg); 352 Type.typeinfoshared = this; 353 } 354 if (id == Id.TypeInfo_Wild) 355 { 356 if (!inObject) 357 error("%s", msg); 358 Type.typeinfowild = this; 359 } 360 if (id == Id.TypeInfo_Vector) 361 { 362 if (!inObject) 363 error("%s", msg); 364 Type.typeinfovector = this; 365 } 366 } 367 368 if (id == Id.Object) 369 { 370 if (!inObject) 371 error("%s", msg); 372 object = this; 373 } 374 375 if (id == Id.Throwable) 376 { 377 if (!inObject) 378 error("%s", msg); 379 throwable = this; 380 } 381 if (id == Id.Exception) 382 { 383 if (!inObject) 384 error("%s", msg); 385 exception = this; 386 } 387 if (id == Id.Error) 388 { 389 if (!inObject) 390 error("%s", msg); 391 errorException = this; 392 } 393 if (id == Id.cpp_type_info_ptr) 394 { 395 if (!inObject) 396 error("%s", msg); 397 cpp_type_info_ptr = this; 398 } 399 } 400 baseok = BASEOKnone; 401 } 402 403 override Dsymbol syntaxCopy(Dsymbol s) 404 { 405 //printf("ClassDeclaration.syntaxCopy('%s')\n", toChars()); 406 ClassDeclaration cd = 407 s ? cast(ClassDeclaration)s 408 : new ClassDeclaration(loc, ident, null, null, false); 409 410 cd.storage_class |= storage_class; 411 412 cd.baseclasses.setDim(this.baseclasses.dim); 413 for (size_t i = 0; i < cd.baseclasses.dim; i++) 414 { 415 BaseClass* b = (*this.baseclasses)[i]; 416 auto b2 = new BaseClass(b.type.syntaxCopy()); 417 (*cd.baseclasses)[i] = b2; 418 } 419 420 return ScopeDsymbol.syntaxCopy(cd); 421 } 422 423 override Scope* newScope(Scope* sc) 424 { 425 auto sc2 = super.newScope(sc); 426 if (isCOMclass()) 427 { 428 if (global.params.isWindows) 429 sc2.linkage = LINKwindows; 430 else 431 { 432 /* This enables us to use COM objects under Linux and 433 * work with things like XPCOM 434 */ 435 sc2.linkage = LINKc; 436 } 437 } 438 return sc2; 439 } 440 441 override void semantic(Scope* sc) 442 { 443 //printf("ClassDeclaration.semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this); 444 //printf("\tparent = %p, '%s'\n", sc.parent, sc.parent ? sc.parent.toChars() : ""); 445 //printf("sc.stc = %x\n", sc.stc); 446 447 //{ static int n; if (++n == 20) *(char*)0=0; } 448 449 if (semanticRun >= PASSsemanticdone) 450 return; 451 int errors = global.errors; 452 453 //printf("+ClassDeclaration.semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this); 454 455 Scope* scx = null; 456 if (_scope) 457 { 458 sc = _scope; 459 scx = _scope; // save so we don't make redundant copies 460 _scope = null; 461 } 462 463 if (!parent) 464 { 465 assert(sc.parent); 466 parent = sc.parent; 467 } 468 469 if (this.errors) 470 type = Type.terror; 471 type = type.semantic(loc, sc); 472 if (type.ty == Tclass && (cast(TypeClass)type).sym != this) 473 { 474 auto ti = (cast(TypeClass)type).sym.isInstantiated(); 475 if (ti && isError(ti)) 476 (cast(TypeClass)type).sym = this; 477 } 478 479 // Ungag errors when not speculative 480 Ungag ungag = ungagSpeculative(); 481 482 if (semanticRun == PASSinit) 483 { 484 protection = sc.protection; 485 486 storage_class |= sc.stc; 487 if (storage_class & STCdeprecated) 488 isdeprecated = true; 489 if (storage_class & STCauto) 490 error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?"); 491 if (storage_class & STCscope) 492 isscope = true; 493 if (storage_class & STCabstract) 494 isabstract = ABSyes; 495 496 userAttribDecl = sc.userAttribDecl; 497 498 if (sc.linkage == LINKcpp) 499 cpp = true; 500 if (sc.linkage == LINKobjc) 501 objc_ClassDeclaration_semantic_PASSinit_LINKobjc(this); 502 } 503 else if (symtab && !scx) 504 { 505 semanticRun = PASSsemanticdone; 506 return; 507 } 508 semanticRun = PASSsemantic; 509 510 if (baseok < BASEOKdone) 511 { 512 /* Bugzilla 12078, 12143 and 15733: 513 * While resolving base classes and interfaces, a base may refer 514 * the member of this derived class. In that time, if all bases of 515 * this class can be determined, we can go forward the semantc process 516 * beyond the Lancestorsdone. To do the recursive semantic analysis, 517 * temporarily set and unset `_scope` around exp(). 518 */ 519 T resolveBase(T)(lazy T exp) 520 { 521 if (!scx) 522 { 523 scx = sc.copy(); 524 scx.setNoFree(); 525 } 526 static if (!is(T == void)) 527 { 528 _scope = scx; 529 auto r = exp(); 530 _scope = null; 531 return r; 532 } 533 else 534 { 535 _scope = scx; 536 exp(); 537 _scope = null; 538 } 539 } 540 541 baseok = BASEOKin; 542 543 // Expand any tuples in baseclasses[] 544 for (size_t i = 0; i < baseclasses.dim;) 545 { 546 auto b = (*baseclasses)[i]; 547 b.type = resolveBase(b.type.semantic(loc, sc)); 548 549 Type tb = b.type.toBasetype(); 550 if (tb.ty == Ttuple) 551 { 552 TypeTuple tup = cast(TypeTuple)tb; 553 baseclasses.remove(i); 554 size_t dim = Parameter.dim(tup.arguments); 555 for (size_t j = 0; j < dim; j++) 556 { 557 Parameter arg = Parameter.getNth(tup.arguments, j); 558 b = new BaseClass(arg.type); 559 baseclasses.insert(i + j, b); 560 } 561 } 562 else 563 i++; 564 } 565 566 if (baseok >= BASEOKdone) 567 { 568 //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun); 569 if (semanticRun >= PASSsemanticdone) 570 return; 571 goto Lancestorsdone; 572 } 573 574 // See if there's a base class as first in baseclasses[] 575 if (baseclasses.dim) 576 { 577 BaseClass* b = (*baseclasses)[0]; 578 Type tb = b.type.toBasetype(); 579 TypeClass tc = (tb.ty == Tclass) ? cast(TypeClass)tb : null; 580 if (!tc) 581 { 582 if (b.type != Type.terror) 583 error("base type must be class or interface, not %s", b.type.toChars()); 584 baseclasses.remove(0); 585 goto L7; 586 } 587 if (tc.sym.isDeprecated()) 588 { 589 if (!isDeprecated()) 590 { 591 // Deriving from deprecated class makes this one deprecated too 592 isdeprecated = true; 593 tc.checkDeprecated(loc, sc); 594 } 595 } 596 if (tc.sym.isInterfaceDeclaration()) 597 goto L7; 598 599 for (ClassDeclaration cdb = tc.sym; cdb; cdb = cdb.baseClass) 600 { 601 if (cdb == this) 602 { 603 error("circular inheritance"); 604 baseclasses.remove(0); 605 goto L7; 606 } 607 } 608 609 /* Bugzilla 11034: Essentially, class inheritance hierarchy 610 * and instance size of each classes are orthogonal information. 611 * Therefore, even if tc.sym.sizeof == SIZEOKnone, 612 * we need to set baseClass field for class covariance check. 613 */ 614 baseClass = tc.sym; 615 b.sym = baseClass; 616 617 if (tc.sym._scope && tc.sym.baseok < BASEOKdone) 618 resolveBase(tc.sym.semantic(null)); // Try to resolve forward reference 619 if (tc.sym.baseok < BASEOKdone) 620 { 621 //printf("\ttry later, forward reference of base class %s\n", tc.sym.toChars()); 622 if (tc.sym._scope) 623 tc.sym._scope._module.addDeferredSemantic(tc.sym); 624 baseok = BASEOKnone; 625 } 626 L7: 627 } 628 629 // Treat the remaining entries in baseclasses as interfaces 630 // Check for errors, handle forward references 631 for (size_t i = (baseClass ? 1 : 0); i < baseclasses.dim;) 632 { 633 BaseClass* b = (*baseclasses)[i]; 634 Type tb = b.type.toBasetype(); 635 TypeClass tc = (tb.ty == Tclass) ? cast(TypeClass)tb : null; 636 if (!tc || !tc.sym.isInterfaceDeclaration()) 637 { 638 if (b.type != Type.terror) 639 error("base type must be interface, not %s", b.type.toChars()); 640 baseclasses.remove(i); 641 continue; 642 } 643 644 // Check for duplicate interfaces 645 for (size_t j = (baseClass ? 1 : 0); j < i; j++) 646 { 647 BaseClass* b2 = (*baseclasses)[j]; 648 if (b2.sym == tc.sym) 649 { 650 error("inherits from duplicate interface %s", b2.sym.toChars()); 651 baseclasses.remove(i); 652 continue; 653 } 654 } 655 if (tc.sym.isDeprecated()) 656 { 657 if (!isDeprecated()) 658 { 659 // Deriving from deprecated class makes this one deprecated too 660 isdeprecated = true; 661 tc.checkDeprecated(loc, sc); 662 } 663 } 664 665 b.sym = tc.sym; 666 667 if (tc.sym._scope && tc.sym.baseok < BASEOKdone) 668 resolveBase(tc.sym.semantic(null)); // Try to resolve forward reference 669 if (tc.sym.baseok < BASEOKdone) 670 { 671 //printf("\ttry later, forward reference of base %s\n", tc.sym.toChars()); 672 if (tc.sym._scope) 673 tc.sym._scope._module.addDeferredSemantic(tc.sym); 674 baseok = BASEOKnone; 675 } 676 i++; 677 } 678 if (baseok == BASEOKnone) 679 { 680 // Forward referencee of one or more bases, try again later 681 _scope = scx ? scx : sc.copy(); 682 _scope.setNoFree(); 683 _scope._module.addDeferredSemantic(this); 684 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars()); 685 return; 686 } 687 baseok = BASEOKdone; 688 689 // If no base class, and this is not an Object, use Object as base class 690 if (!baseClass && ident != Id.Object && !cpp) 691 { 692 if (!object) 693 { 694 error("missing or corrupt object.d"); 695 fatal(); 696 } 697 698 Type t = object.type; 699 t = t.semantic(loc, sc).toBasetype(); 700 assert(t.ty == Tclass); 701 TypeClass tc = cast(TypeClass)t; 702 703 auto b = new BaseClass(tc); 704 baseclasses.shift(b); 705 706 baseClass = tc.sym; 707 assert(!baseClass.isInterfaceDeclaration()); 708 b.sym = baseClass; 709 } 710 if (baseClass) 711 { 712 if (baseClass.storage_class & STCfinal) 713 error("cannot inherit from final class %s", baseClass.toChars()); 714 715 // Inherit properties from base class 716 if (baseClass.isCOMclass()) 717 com = true; 718 if (baseClass.isCPPclass()) 719 cpp = true; 720 if (baseClass.isscope) 721 isscope = true; 722 enclosing = baseClass.enclosing; 723 storage_class |= baseClass.storage_class & STC_TYPECTOR; 724 } 725 726 interfaces = baseclasses.tdata()[(baseClass ? 1 : 0) .. baseclasses.dim]; 727 foreach (b; interfaces) 728 { 729 // If this is an interface, and it derives from a COM interface, 730 // then this is a COM interface too. 731 if (b.sym.isCOMinterface()) 732 com = true; 733 if (cpp && !b.sym.isCPPinterface()) 734 { 735 .error(loc, "C++ class '%s' cannot implement D interface '%s'", 736 toPrettyChars(), b.sym.toPrettyChars()); 737 } 738 } 739 interfaceSemantic(sc); 740 } 741 Lancestorsdone: 742 //printf("\tClassDeclaration.semantic(%s) baseok = %d\n", toChars(), baseok); 743 744 if (!members) // if opaque declaration 745 { 746 semanticRun = PASSsemanticdone; 747 return; 748 } 749 if (!symtab) 750 { 751 symtab = new DsymbolTable(); 752 753 /* Bugzilla 12152: The semantic analysis of base classes should be finished 754 * before the members semantic analysis of this class, in order to determine 755 * vtbl in this class. However if a base class refers the member of this class, 756 * it can be resolved as a normal forward reference. 757 * Call addMember() and setScope() to make this class members visible from the base classes. 758 */ 759 for (size_t i = 0; i < members.dim; i++) 760 { 761 auto s = (*members)[i]; 762 s.addMember(sc, this); 763 } 764 765 auto sc2 = newScope(sc); 766 767 /* Set scope so if there are forward references, we still might be able to 768 * resolve individual members like enums. 769 */ 770 for (size_t i = 0; i < members.dim; i++) 771 { 772 auto s = (*members)[i]; 773 //printf("[%d] setScope %s %s, sc2 = %p\n", i, s.kind(), s.toChars(), sc2); 774 s.setScope(sc2); 775 } 776 777 sc2.pop(); 778 } 779 780 for (size_t i = 0; i < baseclasses.dim; i++) 781 { 782 BaseClass* b = (*baseclasses)[i]; 783 Type tb = b.type.toBasetype(); 784 assert(tb.ty == Tclass); 785 TypeClass tc = cast(TypeClass)tb; 786 if (tc.sym.semanticRun < PASSsemanticdone) 787 { 788 // Forward referencee of one or more bases, try again later 789 _scope = scx ? scx : sc.copy(); 790 _scope.setNoFree(); 791 if (tc.sym._scope) 792 tc.sym._scope._module.addDeferredSemantic(tc.sym); 793 _scope._module.addDeferredSemantic(this); 794 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars()); 795 return; 796 } 797 } 798 799 if (baseok == BASEOKdone) 800 { 801 baseok = BASEOKsemanticdone; 802 803 // initialize vtbl 804 if (baseClass) 805 { 806 if (cpp && baseClass.vtbl.dim == 0) 807 { 808 error("C++ base class %s needs at least one virtual function", baseClass.toChars()); 809 } 810 811 // Copy vtbl[] from base class 812 vtbl.setDim(baseClass.vtbl.dim); 813 memcpy(vtbl.tdata(), baseClass.vtbl.tdata(), (void*).sizeof * vtbl.dim); 814 815 vthis = baseClass.vthis; 816 } 817 else 818 { 819 // No base class, so this is the root of the class hierarchy 820 vtbl.setDim(0); 821 if (vtblOffset()) 822 vtbl.push(this); // leave room for classinfo as first member 823 } 824 825 /* If this is a nested class, add the hidden 'this' 826 * member which is a pointer to the enclosing scope. 827 */ 828 if (vthis) // if inheriting from nested class 829 { 830 // Use the base class's 'this' member 831 if (storage_class & STCstatic) 832 error("static class cannot inherit from nested class %s", baseClass.toChars()); 833 if (toParent2() != baseClass.toParent2() && 834 (!toParent2() || 835 !baseClass.toParent2().getType() || 836 !baseClass.toParent2().getType().isBaseOf(toParent2().getType(), null))) 837 { 838 if (toParent2()) 839 { 840 error("is nested within %s, but super class %s is nested within %s", 841 toParent2().toChars(), 842 baseClass.toChars(), 843 baseClass.toParent2().toChars()); 844 } 845 else 846 { 847 error("is not nested, but super class %s is nested within %s", 848 baseClass.toChars(), 849 baseClass.toParent2().toChars()); 850 } 851 enclosing = null; 852 } 853 } 854 else 855 makeNested(); 856 } 857 858 auto sc2 = newScope(sc); 859 860 for (size_t i = 0; i < members.dim; ++i) 861 { 862 auto s = (*members)[i]; 863 s.importAll(sc2); 864 } 865 866 // Note that members.dim can grow due to tuple expansion during semantic() 867 for (size_t i = 0; i < members.dim; ++i) 868 { 869 auto s = (*members)[i]; 870 s.semantic(sc2); 871 } 872 873 if (!determineFields()) 874 { 875 assert(type == Type.terror); 876 sc2.pop(); 877 return; 878 } 879 /* Following special member functions creation needs semantic analysis 880 * completion of sub-structs in each field types. 881 */ 882 foreach (v; fields) 883 { 884 Type tb = v.type.baseElemOf(); 885 if (tb.ty != Tstruct) 886 continue; 887 auto sd = (cast(TypeStruct)tb).sym; 888 if (sd.semanticRun >= PASSsemanticdone) 889 continue; 890 891 sc2.pop(); 892 893 _scope = scx ? scx : sc.copy(); 894 _scope.setNoFree(); 895 _scope._module.addDeferredSemantic(this); 896 //printf("\tdeferring %s\n", toChars()); 897 return; 898 } 899 900 /* Look for special member functions. 901 * They must be in this class, not in a base class. 902 */ 903 // Can be in base class 904 aggNew = cast(NewDeclaration)search(Loc(), Id.classNew); 905 aggDelete = cast(DeleteDeclaration)search(Loc(), Id.classDelete); 906 907 // Look for the constructor 908 ctor = searchCtor(); 909 910 if (!ctor && noDefaultCtor) 911 { 912 // A class object is always created by constructor, so this check is legitimate. 913 foreach (v; fields) 914 { 915 if (v.storage_class & STCnodefaultctor) 916 .error(v.loc, "field %s must be initialized in constructor", v.toChars()); 917 } 918 } 919 920 // If this class has no constructor, but base class has a default 921 // ctor, create a constructor: 922 // this() { } 923 if (!ctor && baseClass && baseClass.ctor) 924 { 925 auto fd = resolveFuncCall(loc, sc2, baseClass.ctor, null, null, null, 1); 926 if (fd && !fd.errors) 927 { 928 //printf("Creating default this(){} for class %s\n", toChars()); 929 auto btf = cast(TypeFunction)fd.type; 930 auto tf = new TypeFunction(null, null, 0, LINKd, fd.storage_class); 931 tf.purity = btf.purity; 932 tf.isnothrow = btf.isnothrow; 933 tf.isnogc = btf.isnogc; 934 tf.trust = btf.trust; 935 936 auto ctor = new CtorDeclaration(loc, Loc(), 0, tf); 937 ctor.fbody = new CompoundStatement(Loc(), new Statements()); 938 939 members.push(ctor); 940 ctor.addMember(sc, this); 941 ctor.semantic(sc2); 942 943 this.ctor = ctor; 944 defaultCtor = ctor; 945 } 946 else 947 { 948 error("cannot implicitly generate a default ctor when base class %s is missing a default ctor", 949 baseClass.toPrettyChars()); 950 } 951 } 952 953 dtor = buildDtor(this, sc2); 954 955 if (auto f = hasIdentityOpAssign(this, sc2)) 956 { 957 if (!(f.storage_class & STCdisable)) 958 error(f.loc, "identity assignment operator overload is illegal"); 959 } 960 961 inv = buildInv(this, sc2); 962 963 Module.dprogress++; 964 semanticRun = PASSsemanticdone; 965 //printf("-ClassDeclaration.semantic(%s), type = %p\n", toChars(), type); 966 //members.print(); 967 968 sc2.pop(); 969 970 if (global.errors != errors) 971 { 972 // The type is no good. 973 type = Type.terror; 974 this.errors = true; 975 if (deferred) 976 deferred.errors = true; 977 } 978 979 // Verify fields of a synchronized class are not public 980 if (storage_class & STCsynchronized) 981 { 982 foreach (vd; this.fields) 983 { 984 if (!vd.isThisDeclaration() && 985 !vd.prot().isMoreRestrictiveThan(Prot(PROTpublic))) 986 { 987 vd.error("Field members of a synchronized class cannot be %s", 988 protectionToChars(vd.prot().kind)); 989 } 990 } 991 } 992 993 if (deferred && !global.gag) 994 { 995 deferred.semantic2(sc); 996 deferred.semantic3(sc); 997 } 998 999 version (none) 1000 { 1001 if (type.ty == Tclass && (cast(TypeClass)type).sym != this) 1002 { 1003 printf("this = %p %s\n", this, this.toChars()); 1004 printf("type = %d sym = %p\n", type.ty, (cast(TypeClass)type).sym); 1005 } 1006 } 1007 assert(type.ty != Tclass || (cast(TypeClass)type).sym == this); 1008 //printf("-ClassDeclaration.semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this); 1009 } 1010 1011 /********************************************* 1012 * Determine if 'this' is a base class of cd. 1013 * This is used to detect circular inheritance only. 1014 */ 1015 final bool isBaseOf2(ClassDeclaration cd) 1016 { 1017 if (!cd) 1018 return false; 1019 //printf("ClassDeclaration.isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd.toChars()); 1020 for (size_t i = 0; i < cd.baseclasses.dim; i++) 1021 { 1022 BaseClass* b = (*cd.baseclasses)[i]; 1023 if (b.sym == this || isBaseOf2(b.sym)) 1024 return true; 1025 } 1026 return false; 1027 } 1028 1029 enum OFFSET_RUNTIME = 0x76543210; 1030 1031 /******************************************* 1032 * Determine if 'this' is a base class of cd. 1033 */ 1034 bool isBaseOf(ClassDeclaration cd, int* poffset) 1035 { 1036 //printf("ClassDeclaration.isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd.toChars()); 1037 if (poffset) 1038 *poffset = 0; 1039 while (cd) 1040 { 1041 /* cd.baseClass might not be set if cd is forward referenced. 1042 */ 1043 if (!cd.baseClass && cd._scope && !cd.isInterfaceDeclaration()) 1044 { 1045 cd.semantic(null); 1046 if (!cd.baseClass && cd._scope) 1047 cd.error("base class is forward referenced by %s", toChars()); 1048 } 1049 1050 if (this == cd.baseClass) 1051 return true; 1052 1053 cd = cd.baseClass; 1054 } 1055 return false; 1056 } 1057 1058 /********************************************* 1059 * Determine if 'this' has complete base class information. 1060 * This is used to detect forward references in covariant overloads. 1061 */ 1062 final bool isBaseInfoComplete() const 1063 { 1064 return baseok >= BASEOKdone; 1065 } 1066 1067 override final Dsymbol search(Loc loc, Identifier ident, int flags = SearchLocalsOnly) 1068 { 1069 //printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", toChars(), ident.toChars(), flags); 1070 //if (_scope) printf("%s baseok = %d\n", toChars(), baseok); 1071 if (_scope && baseok < BASEOKdone) 1072 { 1073 if (!inuse) 1074 { 1075 // must semantic on base class/interfaces 1076 ++inuse; 1077 semantic(null); 1078 --inuse; 1079 } 1080 } 1081 1082 if (!members || !symtab) // opaque or addMember is not yet done 1083 { 1084 error("is forward referenced when looking for '%s'", ident.toChars()); 1085 //*(char*)0=0; 1086 return null; 1087 } 1088 1089 auto s = ScopeDsymbol.search(loc, ident, flags); 1090 1091 // don't search imports of base classes 1092 if (flags & SearchImportsOnly) 1093 return s; 1094 1095 if (!s) 1096 { 1097 // Search bases classes in depth-first, left to right order 1098 for (size_t i = 0; i < baseclasses.dim; i++) 1099 { 1100 BaseClass* b = (*baseclasses)[i]; 1101 if (b.sym) 1102 { 1103 if (!b.sym.symtab) 1104 error("base %s is forward referenced", b.sym.ident.toChars()); 1105 else 1106 { 1107 import ddmd.access : symbolIsVisible; 1108 1109 s = b.sym.search(loc, ident, flags); 1110 if (!s) 1111 continue; 1112 else if (s == this) // happens if s is nested in this and derives from this 1113 s = null; 1114 else if (!(flags & IgnoreSymbolVisibility) && !(s.prot().kind == PROTprotected) && !symbolIsVisible(this, s)) 1115 s = null; 1116 else 1117 break; 1118 } 1119 } 1120 } 1121 } 1122 return s; 1123 } 1124 1125 /************************************ 1126 * Search base classes in depth-first, left-to-right order for 1127 * a class or interface named 'ident'. 1128 * Stops at first found. Does not look for additional matches. 1129 * Params: 1130 * ident = identifier to search for 1131 * Returns: 1132 * ClassDeclaration if found, null if not 1133 */ 1134 final ClassDeclaration searchBase(Identifier ident) 1135 { 1136 foreach (b; *baseclasses) 1137 { 1138 auto cdb = b.type.isClassHandle(); 1139 if (!cdb) // Bugzilla 10616 1140 return null; 1141 if (cdb.ident.equals(ident)) 1142 return cdb; 1143 auto result = cdb.searchBase(ident); 1144 if (result) 1145 return result; 1146 } 1147 return null; 1148 } 1149 1150 final override void finalizeSize() 1151 { 1152 assert(sizeok != SIZEOKdone); 1153 1154 // Set the offsets of the fields and determine the size of the class 1155 if (baseClass) 1156 { 1157 assert(baseClass.sizeok == SIZEOKdone); 1158 1159 alignsize = baseClass.alignsize; 1160 structsize = baseClass.structsize; 1161 if (cpp && global.params.isWindows) 1162 structsize = (structsize + alignsize - 1) & ~(alignsize - 1); 1163 } 1164 else if (isInterfaceDeclaration()) 1165 { 1166 if (interfaces.length == 0) 1167 { 1168 alignsize = Target.ptrsize; 1169 structsize = Target.ptrsize; // allow room for __vptr 1170 } 1171 } 1172 else 1173 { 1174 alignsize = Target.ptrsize; 1175 structsize = Target.ptrsize; // allow room for __vptr 1176 if (!cpp) 1177 structsize += Target.ptrsize; // allow room for __monitor 1178 } 1179 1180 //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok); 1181 size_t bi = 0; // index into vtblInterfaces[] 1182 1183 /**** 1184 * Runs through the inheritance graph to set the BaseClass.offset fields. 1185 * Recursive in order to account for the size of the interface classes, if they are 1186 * more than just interfaces. 1187 * Params: 1188 * cd = interface to look at 1189 * baseOffset = offset of where cd will be placed 1190 * Returns: 1191 * subset of instantiated size used by cd for interfaces 1192 */ 1193 uint membersPlace(ClassDeclaration cd, uint baseOffset) 1194 { 1195 //printf(" membersPlace(%s, %d)\n", cd.toChars(), baseOffset); 1196 uint offset = baseOffset; 1197 1198 foreach (BaseClass* b; cd.interfaces) 1199 { 1200 if (b.sym.sizeok != SIZEOKdone) 1201 b.sym.finalizeSize(); 1202 assert(b.sym.sizeok == SIZEOKdone); 1203 1204 if (!b.sym.alignsize) 1205 b.sym.alignsize = Target.ptrsize; 1206 alignmember(b.sym.alignsize, b.sym.alignsize, &offset); 1207 assert(bi < vtblInterfaces.dim); 1208 1209 BaseClass* bv = (*vtblInterfaces)[bi]; 1210 if (b.sym.interfaces.length == 0) 1211 { 1212 //printf("\tvtblInterfaces[%d] b=%p b.sym = %s, offset = %d\n", bi, bv, bv.sym.toChars(), offset); 1213 bv.offset = offset; 1214 ++bi; 1215 // All the base interfaces down the left side share the same offset 1216 for (BaseClass* b2 = bv; b2.baseInterfaces.length; ) 1217 { 1218 b2 = &b2.baseInterfaces[0]; 1219 b2.offset = offset; 1220 //printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2.sym.toChars(), b2.offset); 1221 } 1222 } 1223 membersPlace(b.sym, offset); 1224 //printf(" %s size = %d\n", b.sym.toChars(), b.sym.structsize); 1225 offset += b.sym.structsize; 1226 if (alignsize < b.sym.alignsize) 1227 alignsize = b.sym.alignsize; 1228 } 1229 return offset - baseOffset; 1230 } 1231 1232 structsize += membersPlace(this, structsize); 1233 1234 if (isInterfaceDeclaration()) 1235 { 1236 sizeok = SIZEOKdone; 1237 return; 1238 } 1239 1240 // FIXME: Currently setFieldOffset functions need to increase fields 1241 // to calculate each variable offsets. It can be improved later. 1242 fields.setDim(0); 1243 1244 uint offset = structsize; 1245 foreach (s; *members) 1246 { 1247 s.setFieldOffset(this, &offset, false); 1248 } 1249 1250 sizeok = SIZEOKdone; 1251 1252 // Calculate fields[i].overlapped 1253 checkOverlappedFields(); 1254 } 1255 1256 final bool isFuncHidden(FuncDeclaration fd) 1257 { 1258 //printf("ClassDeclaration.isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toChars()); 1259 Dsymbol s = search(Loc(), fd.ident, IgnoreAmbiguous | IgnoreErrors); 1260 if (!s) 1261 { 1262 //printf("not found\n"); 1263 /* Because, due to a hack, if there are multiple definitions 1264 * of fd.ident, NULL is returned. 1265 */ 1266 return false; 1267 } 1268 s = s.toAlias(); 1269 if (auto os = s.isOverloadSet()) 1270 { 1271 foreach (sm; os.a) 1272 { 1273 auto fm = sm.isFuncDeclaration(); 1274 if (overloadApply(fm, s => fd == s.isFuncDeclaration())) 1275 return false; 1276 } 1277 return true; 1278 } 1279 else 1280 { 1281 auto f = s.isFuncDeclaration(); 1282 //printf("%s fdstart = %p\n", s.kind(), fdstart); 1283 if (overloadApply(f, s => fd == s.isFuncDeclaration())) 1284 return false; 1285 return !fd.parent.isTemplateMixin(); 1286 } 1287 } 1288 1289 /**************** 1290 * Find virtual function matching identifier and type. 1291 * Used to build virtual function tables for interface implementations. 1292 * Params: 1293 * ident = function's identifier 1294 * tf = function's type 1295 * Returns: 1296 * function symbol if found, null if not 1297 * Errors: 1298 * prints error message if more than one match 1299 */ 1300 final FuncDeclaration findFunc(Identifier ident, TypeFunction tf) 1301 { 1302 //printf("ClassDeclaration.findFunc(%s, %s) %s\n", ident.toChars(), tf.toChars(), toChars()); 1303 FuncDeclaration fdmatch = null; 1304 FuncDeclaration fdambig = null; 1305 1306 void searchVtbl(ref Dsymbols vtbl) 1307 { 1308 foreach (s; vtbl) 1309 { 1310 auto fd = s.isFuncDeclaration(); 1311 if (!fd) 1312 continue; 1313 1314 // the first entry might be a ClassInfo 1315 //printf("\t[%d] = %s\n", i, fd.toChars()); 1316 if (ident == fd.ident && fd.type.covariant(tf) == 1) 1317 { 1318 //printf("fd.parent.isClassDeclaration() = %p\n", fd.parent.isClassDeclaration()); 1319 if (!fdmatch) 1320 goto Lfd; 1321 if (fd == fdmatch) 1322 goto Lfdmatch; 1323 1324 { 1325 // Function type matcing: exact > covariant 1326 MATCH m1 = tf.equals(fd.type) ? MATCHexact : MATCHnomatch; 1327 MATCH m2 = tf.equals(fdmatch.type) ? MATCHexact : MATCHnomatch; 1328 if (m1 > m2) 1329 goto Lfd; 1330 else if (m1 < m2) 1331 goto Lfdmatch; 1332 } 1333 { 1334 MATCH m1 = (tf.mod == fd.type.mod) ? MATCHexact : MATCHnomatch; 1335 MATCH m2 = (tf.mod == fdmatch.type.mod) ? MATCHexact : MATCHnomatch; 1336 if (m1 > m2) 1337 goto Lfd; 1338 else if (m1 < m2) 1339 goto Lfdmatch; 1340 } 1341 { 1342 // The way of definition: non-mixin > mixin 1343 MATCH m1 = fd.parent.isClassDeclaration() ? MATCHexact : MATCHnomatch; 1344 MATCH m2 = fdmatch.parent.isClassDeclaration() ? MATCHexact : MATCHnomatch; 1345 if (m1 > m2) 1346 goto Lfd; 1347 else if (m1 < m2) 1348 goto Lfdmatch; 1349 } 1350 1351 fdambig = fd; 1352 //printf("Lambig fdambig = %s %s [%s]\n", fdambig.toChars(), fdambig.type.toChars(), fdambig.loc.toChars()); 1353 continue; 1354 1355 Lfd: 1356 fdmatch = fd; 1357 fdambig = null; 1358 //printf("Lfd fdmatch = %s %s [%s]\n", fdmatch.toChars(), fdmatch.type.toChars(), fdmatch.loc.toChars()); 1359 continue; 1360 1361 Lfdmatch: 1362 continue; 1363 } 1364 //else printf("\t\t%d\n", fd.type.covariant(tf)); 1365 } 1366 } 1367 1368 searchVtbl(vtbl); 1369 for (auto cd = this; cd; cd = cd.baseClass) 1370 { 1371 searchVtbl(cd.vtblFinal); 1372 } 1373 1374 if (fdambig) 1375 error("ambiguous virtual function %s", fdambig.toChars()); 1376 1377 return fdmatch; 1378 } 1379 1380 final void interfaceSemantic(Scope* sc) 1381 { 1382 vtblInterfaces = new BaseClasses(); 1383 vtblInterfaces.reserve(interfaces.length); 1384 foreach (b; interfaces) 1385 { 1386 vtblInterfaces.push(b); 1387 b.copyBaseInterfaces(vtblInterfaces); 1388 } 1389 } 1390 1391 1392 /**************************************** 1393 */ 1394 final bool isCOMclass() const 1395 { 1396 return com; 1397 } 1398 1399 bool isCOMinterface() const 1400 { 1401 return false; 1402 } 1403 1404 final bool isCPPclass() const 1405 { 1406 return cpp; 1407 } 1408 1409 bool isCPPinterface() const 1410 { 1411 return false; 1412 } 1413 1414 /**************************************** 1415 */ 1416 final bool isAbstract() 1417 { 1418 if (isabstract != ABSfwdref) 1419 return isabstract == ABSyes; 1420 1421 /* Bugzilla 11169: Resolve forward references to all class member functions, 1422 * and determine whether this class is abstract. 1423 */ 1424 extern (C++) static int func(Dsymbol s, void* param) 1425 { 1426 auto fd = s.isFuncDeclaration(); 1427 if (!fd) 1428 return 0; 1429 if (fd.storage_class & STCstatic) 1430 return 0; 1431 1432 if (fd._scope) 1433 fd.semantic(null); 1434 1435 if (fd.isAbstract()) 1436 return 1; 1437 return 0; 1438 } 1439 1440 for (size_t i = 0; i < members.dim; i++) 1441 { 1442 auto s = (*members)[i]; 1443 if (s.apply(&func, cast(void*)this)) 1444 { 1445 isabstract = ABSyes; 1446 return true; 1447 } 1448 } 1449 1450 /* Iterate inherited member functions and check their abstract attribute. 1451 */ 1452 for (size_t i = 1; i < vtbl.dim; i++) 1453 { 1454 auto fd = vtbl[i].isFuncDeclaration(); 1455 //if (fd) printf("\tvtbl[%d] = [%s] %s\n", i, fd.loc.toChars(), fd.toChars()); 1456 if (!fd || fd.isAbstract()) 1457 { 1458 isabstract = ABSyes; 1459 return true; 1460 } 1461 } 1462 1463 isabstract = ABSno; 1464 return false; 1465 } 1466 1467 /**************************************** 1468 * Determine if slot 0 of the vtbl[] is reserved for something else. 1469 * For class objects, yes, this is where the classinfo ptr goes. 1470 * For COM interfaces, no. 1471 * For non-COM interfaces, yes, this is where the Interface ptr goes. 1472 * Returns: 1473 * 0 vtbl[0] is first virtual function pointer 1474 * 1 vtbl[0] is classinfo/interfaceinfo pointer 1475 */ 1476 int vtblOffset() const 1477 { 1478 return cpp ? 0 : 1; 1479 } 1480 1481 /**************************************** 1482 */ 1483 override const(char)* kind() const 1484 { 1485 return "class"; 1486 } 1487 1488 /**************************************** 1489 */ 1490 override final void addLocalClass(ClassDeclarations* aclasses) 1491 { 1492 aclasses.push(this); 1493 } 1494 1495 // Back end 1496 Symbol* vtblsym; 1497 1498 override final inout(ClassDeclaration) isClassDeclaration() inout 1499 { 1500 return this; 1501 } 1502 1503 override void accept(Visitor v) 1504 { 1505 v.visit(this); 1506 } 1507 } 1508 1509 /*********************************************************** 1510 */ 1511 extern (C++) final class InterfaceDeclaration : ClassDeclaration 1512 { 1513 extern (D) this(Loc loc, Identifier id, BaseClasses* baseclasses) 1514 { 1515 super(loc, id, baseclasses, null, false); 1516 if (id == Id.IUnknown) // IUnknown is the root of all COM interfaces 1517 { 1518 com = true; 1519 cpp = true; // IUnknown is also a C++ interface 1520 } 1521 } 1522 1523 override Dsymbol syntaxCopy(Dsymbol s) 1524 { 1525 InterfaceDeclaration id = 1526 s ? cast(InterfaceDeclaration)s 1527 : new InterfaceDeclaration(loc, ident, null); 1528 return ClassDeclaration.syntaxCopy(id); 1529 } 1530 1531 1532 override Scope* newScope(Scope* sc) 1533 { 1534 auto sc2 = super.newScope(sc); 1535 if (com) 1536 sc2.linkage = LINKwindows; 1537 else if (cpp) 1538 sc2.linkage = LINKcpp; 1539 else if (objc.isInterface()) 1540 sc2.linkage = LINKobjc; 1541 return sc2; 1542 } 1543 1544 override void semantic(Scope* sc) 1545 { 1546 //printf("InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type); 1547 if (semanticRun >= PASSsemanticdone) 1548 return; 1549 int errors = global.errors; 1550 1551 //printf("+InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type); 1552 1553 Scope* scx = null; 1554 if (_scope) 1555 { 1556 sc = _scope; 1557 scx = _scope; // save so we don't make redundant copies 1558 _scope = null; 1559 } 1560 1561 if (!parent) 1562 { 1563 assert(sc.parent && sc.func); 1564 parent = sc.parent; 1565 } 1566 assert(parent && !isAnonymous()); 1567 1568 if (this.errors) 1569 type = Type.terror; 1570 type = type.semantic(loc, sc); 1571 if (type.ty == Tclass && (cast(TypeClass)type).sym != this) 1572 { 1573 auto ti = (cast(TypeClass)type).sym.isInstantiated(); 1574 if (ti && isError(ti)) 1575 (cast(TypeClass)type).sym = this; 1576 } 1577 1578 // Ungag errors when not speculative 1579 Ungag ungag = ungagSpeculative(); 1580 1581 if (semanticRun == PASSinit) 1582 { 1583 protection = sc.protection; 1584 1585 storage_class |= sc.stc; 1586 if (storage_class & STCdeprecated) 1587 isdeprecated = true; 1588 1589 userAttribDecl = sc.userAttribDecl; 1590 } 1591 else if (symtab) 1592 { 1593 if (sizeok == SIZEOKdone || !scx) 1594 { 1595 semanticRun = PASSsemanticdone; 1596 return; 1597 } 1598 } 1599 semanticRun = PASSsemantic; 1600 1601 if (baseok < BASEOKdone) 1602 { 1603 T resolveBase(T)(lazy T exp) 1604 { 1605 if (!scx) 1606 { 1607 scx = sc.copy(); 1608 scx.setNoFree(); 1609 } 1610 static if (!is(T == void)) 1611 { 1612 _scope = scx; 1613 auto r = exp(); 1614 _scope = null; 1615 return r; 1616 } 1617 else 1618 { 1619 _scope = scx; 1620 exp(); 1621 _scope = null; 1622 } 1623 } 1624 1625 baseok = BASEOKin; 1626 1627 // Expand any tuples in baseclasses[] 1628 for (size_t i = 0; i < baseclasses.dim;) 1629 { 1630 auto b = (*baseclasses)[i]; 1631 b.type = resolveBase(b.type.semantic(loc, sc)); 1632 1633 Type tb = b.type.toBasetype(); 1634 if (tb.ty == Ttuple) 1635 { 1636 TypeTuple tup = cast(TypeTuple)tb; 1637 baseclasses.remove(i); 1638 size_t dim = Parameter.dim(tup.arguments); 1639 for (size_t j = 0; j < dim; j++) 1640 { 1641 Parameter arg = Parameter.getNth(tup.arguments, j); 1642 b = new BaseClass(arg.type); 1643 baseclasses.insert(i + j, b); 1644 } 1645 } 1646 else 1647 i++; 1648 } 1649 1650 if (baseok >= BASEOKdone) 1651 { 1652 //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun); 1653 if (semanticRun >= PASSsemanticdone) 1654 return; 1655 goto Lancestorsdone; 1656 } 1657 1658 if (!baseclasses.dim && sc.linkage == LINKcpp) 1659 cpp = true; 1660 1661 objc_InterfaceDeclaration_semantic_objcExtern(this, sc); 1662 1663 // Check for errors, handle forward references 1664 for (size_t i = 0; i < baseclasses.dim;) 1665 { 1666 BaseClass* b = (*baseclasses)[i]; 1667 Type tb = b.type.toBasetype(); 1668 TypeClass tc = (tb.ty == Tclass) ? cast(TypeClass)tb : null; 1669 if (!tc || !tc.sym.isInterfaceDeclaration()) 1670 { 1671 if (b.type != Type.terror) 1672 error("base type must be interface, not %s", b.type.toChars()); 1673 baseclasses.remove(i); 1674 continue; 1675 } 1676 1677 // Check for duplicate interfaces 1678 for (size_t j = 0; j < i; j++) 1679 { 1680 BaseClass* b2 = (*baseclasses)[j]; 1681 if (b2.sym == tc.sym) 1682 { 1683 error("inherits from duplicate interface %s", b2.sym.toChars()); 1684 baseclasses.remove(i); 1685 continue; 1686 } 1687 } 1688 if (tc.sym == this || isBaseOf2(tc.sym)) 1689 { 1690 error("circular inheritance of interface"); 1691 baseclasses.remove(i); 1692 continue; 1693 } 1694 if (tc.sym.isDeprecated()) 1695 { 1696 if (!isDeprecated()) 1697 { 1698 // Deriving from deprecated class makes this one deprecated too 1699 isdeprecated = true; 1700 tc.checkDeprecated(loc, sc); 1701 } 1702 } 1703 1704 b.sym = tc.sym; 1705 1706 if (tc.sym._scope && tc.sym.baseok < BASEOKdone) 1707 resolveBase(tc.sym.semantic(null)); // Try to resolve forward reference 1708 if (tc.sym.baseok < BASEOKdone) 1709 { 1710 //printf("\ttry later, forward reference of base %s\n", tc.sym.toChars()); 1711 if (tc.sym._scope) 1712 tc.sym._scope._module.addDeferredSemantic(tc.sym); 1713 baseok = BASEOKnone; 1714 } 1715 i++; 1716 } 1717 if (baseok == BASEOKnone) 1718 { 1719 // Forward referencee of one or more bases, try again later 1720 _scope = scx ? scx : sc.copy(); 1721 _scope.setNoFree(); 1722 _scope._module.addDeferredSemantic(this); 1723 return; 1724 } 1725 baseok = BASEOKdone; 1726 1727 interfaces = baseclasses.tdata()[0 .. baseclasses.dim]; 1728 foreach (b; interfaces) 1729 { 1730 // If this is an interface, and it derives from a COM interface, 1731 // then this is a COM interface too. 1732 if (b.sym.isCOMinterface()) 1733 com = true; 1734 if (b.sym.isCPPinterface()) 1735 cpp = true; 1736 } 1737 1738 interfaceSemantic(sc); 1739 } 1740 Lancestorsdone: 1741 1742 if (!members) // if opaque declaration 1743 { 1744 semanticRun = PASSsemanticdone; 1745 return; 1746 } 1747 if (!symtab) 1748 symtab = new DsymbolTable(); 1749 1750 for (size_t i = 0; i < baseclasses.dim; i++) 1751 { 1752 BaseClass* b = (*baseclasses)[i]; 1753 Type tb = b.type.toBasetype(); 1754 assert(tb.ty == Tclass); 1755 TypeClass tc = cast(TypeClass)tb; 1756 if (tc.sym.semanticRun < PASSsemanticdone) 1757 { 1758 // Forward referencee of one or more bases, try again later 1759 _scope = scx ? scx : sc.copy(); 1760 _scope.setNoFree(); 1761 if (tc.sym._scope) 1762 tc.sym._scope._module.addDeferredSemantic(tc.sym); 1763 _scope._module.addDeferredSemantic(this); 1764 return; 1765 } 1766 } 1767 1768 if (baseok == BASEOKdone) 1769 { 1770 baseok = BASEOKsemanticdone; 1771 1772 // initialize vtbl 1773 if (vtblOffset()) 1774 vtbl.push(this); // leave room at vtbl[0] for classinfo 1775 1776 // Cat together the vtbl[]'s from base interfaces 1777 foreach (i, b; interfaces) 1778 { 1779 // Skip if b has already appeared 1780 for (size_t k = 0; k < i; k++) 1781 { 1782 if (b == interfaces[k]) 1783 goto Lcontinue; 1784 } 1785 1786 // Copy vtbl[] from base class 1787 if (b.sym.vtblOffset()) 1788 { 1789 size_t d = b.sym.vtbl.dim; 1790 if (d > 1) 1791 { 1792 vtbl.reserve(d - 1); 1793 for (size_t j = 1; j < d; j++) 1794 vtbl.push(b.sym.vtbl[j]); 1795 } 1796 } 1797 else 1798 { 1799 vtbl.append(&b.sym.vtbl); 1800 } 1801 1802 Lcontinue: 1803 } 1804 } 1805 1806 for (size_t i = 0; i < members.dim; i++) 1807 { 1808 Dsymbol s = (*members)[i]; 1809 s.addMember(sc, this); 1810 } 1811 1812 auto sc2 = newScope(sc); 1813 1814 /* Set scope so if there are forward references, we still might be able to 1815 * resolve individual members like enums. 1816 */ 1817 for (size_t i = 0; i < members.dim; i++) 1818 { 1819 Dsymbol s = (*members)[i]; 1820 //printf("setScope %s %s\n", s.kind(), s.toChars()); 1821 s.setScope(sc2); 1822 } 1823 1824 for (size_t i = 0; i < members.dim; i++) 1825 { 1826 Dsymbol s = (*members)[i]; 1827 s.importAll(sc2); 1828 } 1829 1830 for (size_t i = 0; i < members.dim; i++) 1831 { 1832 Dsymbol s = (*members)[i]; 1833 s.semantic(sc2); 1834 } 1835 1836 Module.dprogress++; 1837 semanticRun = PASSsemanticdone; 1838 //printf("-InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type); 1839 //members.print(); 1840 1841 sc2.pop(); 1842 1843 if (global.errors != errors) 1844 { 1845 // The type is no good. 1846 type = Type.terror; 1847 } 1848 1849 version (none) 1850 { 1851 if (type.ty == Tclass && (cast(TypeClass)type).sym != this) 1852 { 1853 printf("this = %p %s\n", this, this.toChars()); 1854 printf("type = %d sym = %p\n", type.ty, (cast(TypeClass)type).sym); 1855 } 1856 } 1857 assert(type.ty != Tclass || (cast(TypeClass)type).sym == this); 1858 } 1859 1860 /******************************************* 1861 * Determine if 'this' is a base class of cd. 1862 * (Actually, if it is an interface supported by cd) 1863 * Output: 1864 * *poffset offset to start of class 1865 * OFFSET_RUNTIME must determine offset at runtime 1866 * Returns: 1867 * false not a base 1868 * true is a base 1869 */ 1870 override bool isBaseOf(ClassDeclaration cd, int* poffset) 1871 { 1872 //printf("%s.InterfaceDeclaration.isBaseOf(cd = '%s')\n", toChars(), cd.toChars()); 1873 assert(!baseClass); 1874 foreach (j, b; cd.interfaces) 1875 { 1876 //printf("\tX base %s\n", b.sym.toChars()); 1877 if (this == b.sym) 1878 { 1879 //printf("\tfound at offset %d\n", b.offset); 1880 if (poffset) 1881 *poffset = b.offset; 1882 return true; 1883 } 1884 if (isBaseOf(b, poffset)) 1885 return true; 1886 } 1887 if (cd.baseClass && isBaseOf(cd.baseClass, poffset)) 1888 return true; 1889 1890 if (poffset) 1891 *poffset = 0; 1892 return false; 1893 } 1894 1895 bool isBaseOf(BaseClass* bc, int* poffset) 1896 { 1897 //printf("%s.InterfaceDeclaration.isBaseOf(bc = '%s')\n", toChars(), bc.sym.toChars()); 1898 for (size_t j = 0; j < bc.baseInterfaces.length; j++) 1899 { 1900 BaseClass* b = &bc.baseInterfaces[j]; 1901 //printf("\tY base %s\n", b.sym.toChars()); 1902 if (this == b.sym) 1903 { 1904 //printf("\tfound at offset %d\n", b.offset); 1905 if (poffset) 1906 { 1907 *poffset = b.offset; 1908 } 1909 return true; 1910 } 1911 if (isBaseOf(b, poffset)) 1912 { 1913 return true; 1914 } 1915 } 1916 1917 if (poffset) 1918 *poffset = 0; 1919 return false; 1920 } 1921 1922 /******************************************* 1923 */ 1924 override const(char)* kind() const 1925 { 1926 return "interface"; 1927 } 1928 1929 /**************************************** 1930 * Determine if slot 0 of the vtbl[] is reserved for something else. 1931 * For class objects, yes, this is where the ClassInfo ptr goes. 1932 * For COM interfaces, no. 1933 * For non-COM interfaces, yes, this is where the Interface ptr goes. 1934 */ 1935 override int vtblOffset() const 1936 { 1937 if (isCOMinterface() || isCPPinterface()) 1938 return 0; 1939 return 1; 1940 } 1941 1942 override bool isCPPinterface() const 1943 { 1944 return cpp; 1945 } 1946 1947 override bool isCOMinterface() const 1948 { 1949 return com; 1950 } 1951 1952 override inout(InterfaceDeclaration) isInterfaceDeclaration() inout 1953 { 1954 return this; 1955 } 1956 1957 override void accept(Visitor v) 1958 { 1959 v.visit(this); 1960 } 1961 }