2 * Defines a `class` declaration.
4 * Specification: $(LINK2 https://dlang.org/spec/class.html, Classes)
6 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
7 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
8 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dclass.d, _dclass.d)
10 * Documentation: https://dlang.org/phobos/dmd_dclass.html
11 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dclass.d
16 import core.stdc.stdio;
17 import core.stdc.string;
21 import dmd.arraytypes;
25 import dmd.declaration;
28 import dmd.dsymbolsem;
32 import dmd.identifier;
40 /***********************************************************
42 extern (C++) struct BaseClass
44 Type type; // (before semantic processing)
47 uint offset; // 'this' pointer offset
49 // for interfaces: Array of FuncDeclaration's making up the vtbl[]
50 FuncDeclarations vtbl;
52 // if BaseClass is an interface, these
53 // are a copy of the InterfaceDeclaration.interfaces
54 BaseClass[] baseInterfaces;
56 extern (D) this(Type type)
58 //printf("BaseClass(this = %p, '%s')\n", this, type.toChars());
62 /****************************************
63 * Fill in vtbl[] for base class based on member functions of class cd.
65 * vtbl if !=NULL, fill it in
66 * newinstance !=0 means all entries must be filled in by members
67 * of cd, not members of any base classes of cd.
69 * true if any entries were filled in by members of cd (not exclusively
72 extern (C++) bool fillVtbl(ClassDeclaration cd, FuncDeclarations* vtbl, int newinstance)
76 //printf("BaseClass.fillVtbl(this='%s', cd='%s')\n", sym.toChars(), cd.toChars());
78 vtbl.setDim(sym.vtbl.length);
80 // first entry is ClassInfo reference
81 for (size_t j = sym.vtblOffset(); j < sym.vtbl.length; j++)
83 FuncDeclaration ifd = sym.vtbl[j].isFuncDeclaration();
85 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd.toChars() : "null");
88 // Find corresponding function in this class
89 auto tf = ifd.type.toTypeFunction();
90 auto fd = cd.findFunc(ifd.ident, tf);
91 if (fd && !fd.isAbstract())
93 if (fd.toParent() == cd)
104 extern (D) void copyBaseInterfaces(BaseClasses* vtblInterfaces)
106 //printf("+copyBaseInterfaces(), %s\n", sym.toChars());
107 // if (baseInterfaces.length)
109 auto bc = cast(BaseClass*)mem.xcalloc(sym.interfaces.length, BaseClass.sizeof);
110 baseInterfaces = bc[0 .. sym.interfaces.length];
111 //printf("%s.copyBaseInterfaces()\n", sym.toChars());
112 for (size_t i = 0; i < baseInterfaces.length; i++)
114 BaseClass* b = &baseInterfaces[i];
115 BaseClass* b2 = sym.interfaces[i];
117 assert(b2.vtbl.length == 0); // should not be filled yet
118 memcpy(b, b2, BaseClass.sizeof);
120 if (i) // single inheritance is i==0
121 vtblInterfaces.push(b); // only need for M.I.
122 b.copyBaseInterfaces(vtblInterfaces);
124 //printf("-copyBaseInterfaces\n");
128 enum ClassFlags : uint
135 hasGetMembers = 0x10,
142 /***********************************************************
144 extern (C++) class ClassDeclaration : AggregateDeclaration
146 extern (C++) __gshared
148 // Names found by reading object.d in druntime
149 ClassDeclaration object;
150 ClassDeclaration throwable;
151 ClassDeclaration exception;
152 ClassDeclaration errorException;
153 ClassDeclaration cpp_type_info_ptr; // Object.__cpp_type_info_ptr
156 ClassDeclaration baseClass; // NULL only if this is Object
157 FuncDeclaration staticCtor;
158 FuncDeclaration staticDtor;
159 Dsymbols vtbl; // Array of FuncDeclaration's making up the vtbl[]
160 Dsymbols vtblFinal; // More FuncDeclaration's that aren't in vtbl[]
162 // Array of BaseClass's; first is super, rest are Interface's
163 BaseClasses* baseclasses;
165 /* Slice of baseclasses[] that does not include baseClass
167 BaseClass*[] interfaces;
169 // array of base interfaces that have their own vtbl[]
170 BaseClasses* vtblInterfaces;
172 // the ClassInfo object for this ClassDeclaration
173 TypeInfoClassDeclaration vclassinfo;
175 // true if this is a COM class
178 /// true if this is a scope class
181 /// if this is a C++ class, this is the slot reserved for the virtual destructor
182 int cppDtorVtblIndex = -1;
184 /// to prevent recursive attempts
187 ThreeState isabstract;
189 /// set the progress of base classes resolving
193 * Data for a class declaration that is needed for the Objective-C
196 ObjcClassDeclaration objc;
198 Symbol* cpp_type_info_ptr_sym; // cached instance of class Id.cpp_type_info_ptr
200 final extern (D) this(const ref Loc loc, Identifier id, BaseClasses* baseclasses, Dsymbols* members, bool inObject)
202 objc = ObjcClassDeclaration(this);
205 id = Identifier.generateAnonymousId("class");
209 static immutable msg = "only object.d can define this reserved class name";
213 // Actually, this is a transfer
214 this.baseclasses = baseclasses;
217 this.baseclasses = new BaseClasses();
219 this.members = members;
221 //printf("ClassDeclaration(%s), dim = %d\n", ident.toChars(), this.baseclasses.length);
223 // For forward references
224 type = new TypeClass(this);
226 // Look for special class names
227 if (id == Id.__sizeof || id == Id.__xalignof || id == Id._mangleof)
228 error("illegal class name");
230 // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
231 if (id.toChars()[0] == 'T')
233 if (id == Id.TypeInfo)
236 error("%s", msg.ptr);
237 Type.dtypeinfo = this;
239 if (id == Id.TypeInfo_Class)
242 error("%s", msg.ptr);
243 Type.typeinfoclass = this;
245 if (id == Id.TypeInfo_Interface)
248 error("%s", msg.ptr);
249 Type.typeinfointerface = this;
251 if (id == Id.TypeInfo_Struct)
254 error("%s", msg.ptr);
255 Type.typeinfostruct = this;
257 if (id == Id.TypeInfo_Pointer)
260 error("%s", msg.ptr);
261 Type.typeinfopointer = this;
263 if (id == Id.TypeInfo_Array)
266 error("%s", msg.ptr);
267 Type.typeinfoarray = this;
269 if (id == Id.TypeInfo_StaticArray)
272 // Type.typeinfostaticarray.error("%s", msg);
273 Type.typeinfostaticarray = this;
275 if (id == Id.TypeInfo_AssociativeArray)
278 error("%s", msg.ptr);
279 Type.typeinfoassociativearray = this;
281 if (id == Id.TypeInfo_Enum)
284 error("%s", msg.ptr);
285 Type.typeinfoenum = this;
287 if (id == Id.TypeInfo_Function)
290 error("%s", msg.ptr);
291 Type.typeinfofunction = this;
293 if (id == Id.TypeInfo_Delegate)
296 error("%s", msg.ptr);
297 Type.typeinfodelegate = this;
299 if (id == Id.TypeInfo_Tuple)
302 error("%s", msg.ptr);
303 Type.typeinfotypelist = this;
305 if (id == Id.TypeInfo_Const)
308 error("%s", msg.ptr);
309 Type.typeinfoconst = this;
311 if (id == Id.TypeInfo_Invariant)
314 error("%s", msg.ptr);
315 Type.typeinfoinvariant = this;
317 if (id == Id.TypeInfo_Shared)
320 error("%s", msg.ptr);
321 Type.typeinfoshared = this;
323 if (id == Id.TypeInfo_Wild)
326 error("%s", msg.ptr);
327 Type.typeinfowild = this;
329 if (id == Id.TypeInfo_Vector)
332 error("%s", msg.ptr);
333 Type.typeinfovector = this;
340 error("%s", msg.ptr);
344 if (id == Id.Throwable)
347 error("%s", msg.ptr);
350 if (id == Id.Exception)
353 error("%s", msg.ptr);
359 error("%s", msg.ptr);
360 errorException = this;
362 if (id == Id.cpp_type_info_ptr)
365 error("%s", msg.ptr);
366 cpp_type_info_ptr = this;
369 baseok = Baseok.none;
372 static ClassDeclaration create(const ref Loc loc, Identifier id, BaseClasses* baseclasses, Dsymbols* members, bool inObject)
374 return new ClassDeclaration(loc, id, baseclasses, members, inObject);
377 override const(char)* toPrettyChars(bool qualifyTypes = false)
380 return .objc.toPrettyChars(this, qualifyTypes);
382 return super.toPrettyChars(qualifyTypes);
385 override ClassDeclaration syntaxCopy(Dsymbol s)
387 //printf("ClassDeclaration.syntaxCopy('%s')\n", toChars());
388 ClassDeclaration cd =
389 s ? cast(ClassDeclaration)s
390 : new ClassDeclaration(loc, ident, null, null, false);
392 cd.storage_class |= storage_class;
394 cd.baseclasses.setDim(this.baseclasses.length);
395 for (size_t i = 0; i < cd.baseclasses.length; i++)
397 BaseClass* b = (*this.baseclasses)[i];
398 auto b2 = new BaseClass(b.type.syntaxCopy());
399 (*cd.baseclasses)[i] = b2;
402 ScopeDsymbol.syntaxCopy(cd);
406 override Scope* newScope(Scope* sc)
408 auto sc2 = super.newScope(sc);
411 /* This enables us to use COM objects under Linux and
412 * work with things like XPCOM
414 sc2.linkage = target.systemLinkage();
419 /*********************************************
420 * Determine if 'this' is a base class of cd.
421 * This is used to detect circular inheritance only.
423 final bool isBaseOf2(ClassDeclaration cd) pure nothrow @nogc
427 //printf("ClassDeclaration.isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
428 for (size_t i = 0; i < cd.baseclasses.length; i++)
430 BaseClass* b = (*cd.baseclasses)[i];
431 if (b.sym == this || isBaseOf2(b.sym))
437 enum OFFSET_RUNTIME = 0x76543210;
438 enum OFFSET_FWDREF = 0x76543211;
440 /*******************************************
441 * Determine if 'this' is a base class of cd.
443 bool isBaseOf(ClassDeclaration cd, int* poffset) pure nothrow @nogc
445 //printf("ClassDeclaration.isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
450 assert(cd.baseClass || cd.semanticRun >= PASS.semanticdone || cd.isInterfaceDeclaration());
451 if (this == cd.baseClass)
459 /*********************************************
460 * Determine if 'this' has complete base class information.
461 * This is used to detect forward references in covariant overloads.
463 final bool isBaseInfoComplete() const
465 return baseok >= Baseok.done;
468 override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
470 //printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", toChars(), ident.toChars(), flags);
471 //if (_scope) printf("%s baseok = %d\n", toChars(), baseok);
472 if (_scope && baseok < Baseok.semanticdone)
476 // must semantic on base class/interfaces
478 dsymbolSemantic(this, null);
483 if (!members || !symtab) // opaque or addMember is not yet done
485 // .stringof is always defined (but may be hidden by some other symbol)
486 if (ident != Id.stringof && !(flags & IgnoreErrors) && semanticRun < PASS.semanticdone)
487 error("is forward referenced when looking for `%s`", ident.toChars());
492 auto s = ScopeDsymbol.search(loc, ident, flags);
494 // don't search imports of base classes
495 if (flags & SearchImportsOnly)
501 // Search bases classes in depth-first, left to right order
502 foreach (b; (*baseclasses)[])
509 error("base `%s` is forward referenced", b.sym.ident.toChars());
513 import dmd.access : symbolIsVisible;
515 s = b.sym.search(loc, ident, flags);
518 else if (s == this) // happens if s is nested in this and derives from this
520 else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(this, s))
529 /************************************
530 * Search base classes in depth-first, left-to-right order for
531 * a class or interface named 'ident'.
532 * Stops at first found. Does not look for additional matches.
534 * ident = identifier to search for
536 * ClassDeclaration if found, null if not
538 final ClassDeclaration searchBase(Identifier ident)
540 foreach (b; *baseclasses)
542 auto cdb = b.type.isClassHandle();
543 if (!cdb) // https://issues.dlang.org/show_bug.cgi?id=10616
545 if (cdb.ident.equals(ident))
547 auto result = cdb.searchBase(ident);
554 final override void finalizeSize()
556 assert(sizeok != Sizeok.done);
558 // Set the offsets of the fields and determine the size of the class
561 assert(baseClass.sizeok == Sizeok.done);
563 alignsize = baseClass.alignsize;
564 if (classKind == ClassKind.cpp)
565 structsize = target.cpp.derivedClassOffset(baseClass);
567 structsize = baseClass.structsize;
569 else if (classKind == ClassKind.objc)
570 structsize = 0; // no hidden member for an Objective-C class
571 else if (isInterfaceDeclaration())
573 if (interfaces.length == 0)
575 alignsize = target.ptrsize;
576 structsize = target.ptrsize; // allow room for __vptr
581 alignsize = target.ptrsize;
582 structsize = target.ptrsize; // allow room for __vptr
584 structsize += target.ptrsize; // allow room for __monitor
587 //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
588 size_t bi = 0; // index into vtblInterfaces[]
591 * Runs through the inheritance graph to set the BaseClass.offset fields.
592 * Recursive in order to account for the size of the interface classes, if they are
593 * more than just interfaces.
595 * cd = interface to look at
596 * baseOffset = offset of where cd will be placed
598 * subset of instantiated size used by cd for interfaces
600 uint membersPlace(ClassDeclaration cd, uint baseOffset)
602 //printf(" membersPlace(%s, %d)\n", cd.toChars(), baseOffset);
603 uint offset = baseOffset;
605 foreach (BaseClass* b; cd.interfaces)
607 if (b.sym.sizeok != Sizeok.done)
608 b.sym.finalizeSize();
609 assert(b.sym.sizeok == Sizeok.done);
611 if (!b.sym.alignsize)
612 b.sym.alignsize = target.ptrsize;
613 alignmember(structalign_t(cast(ushort)b.sym.alignsize), b.sym.alignsize, &offset);
614 assert(bi < vtblInterfaces.length);
616 BaseClass* bv = (*vtblInterfaces)[bi];
617 if (b.sym.interfaces.length == 0)
619 //printf("\tvtblInterfaces[%d] b=%p b.sym = %s, offset = %d\n", bi, bv, bv.sym.toChars(), offset);
622 // All the base interfaces down the left side share the same offset
623 for (BaseClass* b2 = bv; b2.baseInterfaces.length; )
625 b2 = &b2.baseInterfaces[0];
627 //printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2.sym.toChars(), b2.offset);
630 membersPlace(b.sym, offset);
631 //printf(" %s size = %d\n", b.sym.toChars(), b.sym.structsize);
632 offset += b.sym.structsize;
633 if (alignsize < b.sym.alignsize)
634 alignsize = b.sym.alignsize;
636 return offset - baseOffset;
639 structsize += membersPlace(this, structsize);
641 if (isInterfaceDeclaration())
643 sizeok = Sizeok.done;
647 // FIXME: Currently setFieldOffset functions need to increase fields
648 // to calculate each variable offsets. It can be improved later.
651 FieldState fieldState;
652 fieldState.offset = structsize;
653 foreach (s; *members)
655 s.setFieldOffset(this, fieldState, false);
658 sizeok = Sizeok.done;
660 // Calculate fields[i].overlapped
661 checkOverlappedFields();
665 * Returns: true if there's a __monitor field
667 final bool hasMonitor()
669 return classKind == ClassKind.d;
672 final bool isFuncHidden(FuncDeclaration fd)
674 //printf("ClassDeclaration.isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toPrettyChars());
675 Dsymbol s = search(Loc.initial, fd.ident, IgnoreAmbiguous | IgnoreErrors);
678 //printf("not found\n");
679 /* Because, due to a hack, if there are multiple definitions
680 * of fd.ident, NULL is returned.
685 if (auto os = s.isOverloadSet())
689 auto fm = sm.isFuncDeclaration();
690 if (overloadApply(fm, s => fd == s.isFuncDeclaration()))
697 auto f = s.isFuncDeclaration();
698 //printf("%s fdstart = %p\n", s.kind(), fdstart);
699 if (overloadApply(f, s => fd == s.isFuncDeclaration()))
701 return !fd.parent.isTemplateMixin();
706 * Find virtual function matching identifier and type.
707 * Used to build virtual function tables for interface implementations.
709 * ident = function's identifier
710 * tf = function's type
712 * function symbol if found, null if not
714 * prints error message if more than one match
716 final FuncDeclaration findFunc(Identifier ident, TypeFunction tf)
718 //printf("ClassDeclaration.findFunc(%s, %s) %s\n", ident.toChars(), tf.toChars(), toChars());
719 FuncDeclaration fdmatch = null;
720 FuncDeclaration fdambig = null;
722 void updateBestMatch(FuncDeclaration fd)
726 //printf("Lfd fdmatch = %s %s [%s]\n", fdmatch.toChars(), fdmatch.type.toChars(), fdmatch.loc.toChars());
729 void searchVtbl(ref Dsymbols vtbl)
731 bool seenInterfaceVirtual;
734 auto fd = s.isFuncDeclaration();
738 // the first entry might be a ClassInfo
739 //printf("\t[%d] = %s\n", i, fd.toChars());
740 if (ident != fd.ident || fd.type.covariant(tf) != Covariant.yes)
742 //printf("\t\t%d\n", fd.type.covariant(tf));
746 //printf("fd.parent.isClassDeclaration() = %p\n", fd.parent.isClassDeclaration());
755 /* Functions overriding interface functions for extern(C++) with VC++
756 * are not in the normal vtbl, but in vtblFinal. If the implementation
757 * is again overridden in a child class, both would be found here.
758 * The function in the child class should override the function
759 * in the base class, which is done here, because searchVtbl is first
760 * called for the child class. Checking seenInterfaceVirtual makes
761 * sure, that the compared functions are not in the same vtbl.
763 if (fd.interfaceVirtual &&
764 fd.interfaceVirtual is fdmatch.interfaceVirtual &&
765 !seenInterfaceVirtual &&
766 fdmatch.type.covariant(fd.type) == Covariant.yes)
768 seenInterfaceVirtual = true;
773 // Function type matching: exact > covariant
774 MATCH m1 = tf.equals(fd.type) ? MATCH.exact : MATCH.nomatch;
775 MATCH m2 = tf.equals(fdmatch.type) ? MATCH.exact : MATCH.nomatch;
785 MATCH m1 = (tf.mod == fd.type.mod) ? MATCH.exact : MATCH.nomatch;
786 MATCH m2 = (tf.mod == fdmatch.type.mod) ? MATCH.exact : MATCH.nomatch;
796 // The way of definition: non-mixin > mixin
797 MATCH m1 = fd.parent.isClassDeclaration() ? MATCH.exact : MATCH.nomatch;
798 MATCH m2 = fdmatch.parent.isClassDeclaration() ? MATCH.exact : MATCH.nomatch;
809 //printf("Lambig fdambig = %s %s [%s]\n", fdambig.toChars(), fdambig.type.toChars(), fdambig.loc.toChars());
814 for (auto cd = this; cd; cd = cd.baseClass)
816 searchVtbl(cd.vtblFinal);
820 error("ambiguous virtual function `%s`", fdambig.toChars());
825 /****************************************
827 final bool isCOMclass() const
832 bool isCOMinterface() const
837 final bool isCPPclass() const
839 return classKind == ClassKind.cpp;
842 bool isCPPinterface() const
847 /****************************************
849 final bool isAbstract()
852 if (isabstract != ThreeState.none)
853 return isabstract == ThreeState.yes;
855 if (log) printf("isAbstract(%s)\n", toChars());
857 bool no() { if (log) printf("no\n"); isabstract = ThreeState.no; return false; }
858 bool yes() { if (log) printf("yes\n"); isabstract = ThreeState.yes; return true; }
860 if (storage_class & STC.abstract_ || _scope && _scope.stc & STC.abstract_)
866 /* https://issues.dlang.org/show_bug.cgi?id=11169
867 * Resolve forward references to all class member functions,
868 * and determine whether this class is abstract.
870 static int func(Dsymbol s)
872 auto fd = s.isFuncDeclaration();
875 if (fd.storage_class & STC.static_)
883 for (size_t i = 0; i < members.length; i++)
885 auto s = (*members)[i];
892 /* If the base class is not abstract, then this class cannot
895 if (!isInterfaceDeclaration() && (!baseClass || !baseClass.isAbstract()))
898 /* If any abstract functions are inherited, but not overridden,
899 * then the class is abstract. Do this by checking the vtbl[].
900 * Need to do semantic() on class to fill the vtbl[].
902 this.dsymbolSemantic(null);
904 /* The next line should work, but does not because when ClassDeclaration.dsymbolSemantic()
905 * is called recursively it can set PASS.semanticdone without finishing it.
907 //if (semanticRun < PASS.semanticdone)
909 /* Could not complete semantic(). Try running semantic() on
910 * each of the virtual functions,
911 * which will fill in the vtbl[] overrides.
913 static int virtualSemantic(Dsymbol s)
915 auto fd = s.isFuncDeclaration();
916 if (fd && !(fd.storage_class & STC.static_) && !fd.isUnitTestDeclaration())
917 fd.dsymbolSemantic(null);
921 for (size_t i = 0; i < members.length; i++)
923 auto s = (*members)[i];
924 s.apply(&virtualSemantic);
928 /* Finally, check the vtbl[]
930 foreach (i; 1 .. vtbl.length)
932 auto fd = vtbl[i].isFuncDeclaration();
933 //if (fd) printf("\tvtbl[%d] = [%s] %s\n", i, fd.loc.toChars(), fd.toPrettyChars());
934 if (!fd || fd.isAbstract())
943 /****************************************
944 * Determine if slot 0 of the vtbl[] is reserved for something else.
945 * For class objects, yes, this is where the classinfo ptr goes.
946 * For COM interfaces, no.
947 * For non-COM interfaces, yes, this is where the Interface ptr goes.
949 * 0 vtbl[0] is first virtual function pointer
950 * 1 vtbl[0] is classinfo/interfaceinfo pointer
952 int vtblOffset() const
954 return classKind == ClassKind.cpp ? 0 : 1;
957 /****************************************
959 override const(char)* kind() const
964 /****************************************
966 override final void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories)
968 .objc.addSymbols(this, classes, categories);
974 final Dsymbol vtblSymbol()
978 auto vtype = Type.tvoidptr.immutableOf().sarrayOf(vtbl.length);
979 auto var = new VarDeclaration(loc, vtype, Identifier.idPool("__vtbl"), null, STC.immutable_ | STC.static_);
980 var.addMember(null, this);
982 var._linkage = LINK.d;
983 var.semanticRun = PASS.semanticdone; // no more semantic wanted
989 extern (D) final bool isErrorException()
991 return errorException && (this == errorException || errorException.isBaseOf(this, null));
994 override final inout(ClassDeclaration) isClassDeclaration() inout @nogc nothrow pure @safe
999 override void accept(Visitor v)
1005 /***********************************************************
1007 extern (C++) final class InterfaceDeclaration : ClassDeclaration
1009 extern (D) this(const ref Loc loc, Identifier id, BaseClasses* baseclasses)
1011 super(loc, id, baseclasses, null, false);
1012 if (id == Id.IUnknown) // IUnknown is the root of all COM interfaces
1015 classKind = ClassKind.cpp; // IUnknown is also a C++ interface
1019 override InterfaceDeclaration syntaxCopy(Dsymbol s)
1021 InterfaceDeclaration id =
1022 s ? cast(InterfaceDeclaration)s
1023 : new InterfaceDeclaration(loc, ident, null);
1024 ClassDeclaration.syntaxCopy(id);
1029 override Scope* newScope(Scope* sc)
1031 auto sc2 = super.newScope(sc);
1033 sc2.linkage = LINK.windows;
1034 else if (classKind == ClassKind.cpp)
1035 sc2.linkage = LINK.cpp;
1036 else if (classKind == ClassKind.objc)
1037 sc2.linkage = LINK.objc;
1041 /*******************************************
1042 * Determine if 'this' is a base class of cd.
1043 * (Actually, if it is an interface supported by cd)
1045 * *poffset offset to start of class
1046 * OFFSET_RUNTIME must determine offset at runtime
1051 override bool isBaseOf(ClassDeclaration cd, int* poffset) pure nothrow @nogc
1053 //printf("%s.InterfaceDeclaration.isBaseOf(cd = '%s')\n", toChars(), cd.toChars());
1055 foreach (b; cd.interfaces)
1057 //printf("\tX base %s\n", b.sym.toChars());
1060 //printf("\tfound at offset %d\n", b.offset);
1063 // don't return incorrect offsets
1064 // https://issues.dlang.org/show_bug.cgi?id=16980
1065 *poffset = cd.sizeok == Sizeok.done ? b.offset : OFFSET_FWDREF;
1067 // printf("\tfound at offset %d\n", b.offset);
1070 if (baseClassImplementsInterface(this, b, poffset))
1073 if (cd.baseClass && isBaseOf(cd.baseClass, poffset))
1081 /*******************************************
1083 override const(char)* kind() const
1088 /****************************************
1089 * Determine if slot 0 of the vtbl[] is reserved for something else.
1090 * For class objects, yes, this is where the ClassInfo ptr goes.
1091 * For COM interfaces, no.
1092 * For non-COM interfaces, yes, this is where the Interface ptr goes.
1094 override int vtblOffset() const
1096 if (isCOMinterface() || isCPPinterface())
1101 override bool isCPPinterface() const
1103 return classKind == ClassKind.cpp;
1106 override bool isCOMinterface() const
1111 override inout(InterfaceDeclaration) isInterfaceDeclaration() inout
1116 override void accept(Visitor v)
1123 * Returns whether `bc` implements `id`, including indirectly (`bc` implements an interfaces
1124 * that inherits from `id`)
1127 * id = the interface
1128 * bc = the base class
1129 * poffset = out parameter, offset of the interface in an object
1132 * true if the `bc` implements `id`, false otherwise
1134 private bool baseClassImplementsInterface(InterfaceDeclaration id, BaseClass* bc, int* poffset) pure nothrow @nogc
1136 //printf("%s.InterfaceDeclaration.isBaseOf(bc = '%s')\n", id.toChars(), bc.sym.toChars());
1137 for (size_t j = 0; j < bc.baseInterfaces.length; j++)
1139 BaseClass* b = &bc.baseInterfaces[j];
1140 //printf("\tY base %s\n", b.sym.toChars());
1143 //printf("\tfound at offset %d\n", b.offset);
1146 *poffset = b.offset;
1150 if (baseClassImplementsInterface(id, b, poffset))