2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved
4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/class.c
11 #include "root/dsystem.h" // mem{cpy|set}()
12 #include "root/root.h"
13 #include "root/rmem.h"
19 #include "declaration.h"
20 #include "aggregate.h"
25 #include "expression.h"
26 #include "statement.h"
31 bool symbolIsVisible(Dsymbol
*origin
, Dsymbol
*s
);
35 /********************************* ClassDeclaration ****************************/
37 ClassDeclaration
*ClassDeclaration::object
;
38 ClassDeclaration
*ClassDeclaration::throwable
;
39 ClassDeclaration
*ClassDeclaration::exception
;
40 ClassDeclaration
*ClassDeclaration::errorException
;
41 ClassDeclaration
*ClassDeclaration::cpp_type_info_ptr
; // Object.__cpp_type_info_ptr
43 ClassDeclaration::ClassDeclaration(Loc loc
, Identifier
*id
, BaseClasses
*baseclasses
, Dsymbols
*members
, bool inObject
)
44 : AggregateDeclaration(loc
, id
? id
: Identifier::generateId("__anonclass"))
46 static const char msg
[] = "only object.d can define this reserved class name";
50 // Actually, this is a transfer
51 this->baseclasses
= baseclasses
;
54 this->baseclasses
= new BaseClasses();
56 this->members
= members
;
60 interfaces
.length
= 0;
61 interfaces
.ptr
= NULL
;
63 vtblInterfaces
= NULL
;
65 //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses->length);
67 // For forward references
68 type
= new TypeClass(this);
78 // Look for special class names
80 if (id
== Id::__sizeof
|| id
== Id::__xalignof
|| id
== Id::_mangleof
)
81 error("illegal class name");
83 // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
84 if (id
->toChars()[0] == 'T')
86 if (id
== Id::TypeInfo
)
90 Type::dtypeinfo
= this;
93 if (id
== Id::TypeInfo_Class
)
97 Type::typeinfoclass
= this;
100 if (id
== Id::TypeInfo_Interface
)
104 Type::typeinfointerface
= this;
107 if (id
== Id::TypeInfo_Struct
)
111 Type::typeinfostruct
= this;
114 if (id
== Id::TypeInfo_Pointer
)
118 Type::typeinfopointer
= this;
121 if (id
== Id::TypeInfo_Array
)
125 Type::typeinfoarray
= this;
128 if (id
== Id::TypeInfo_StaticArray
)
131 // Type::typeinfostaticarray->error("%s", msg);
132 Type::typeinfostaticarray
= this;
135 if (id
== Id::TypeInfo_AssociativeArray
)
139 Type::typeinfoassociativearray
= this;
142 if (id
== Id::TypeInfo_Enum
)
146 Type::typeinfoenum
= this;
149 if (id
== Id::TypeInfo_Function
)
153 Type::typeinfofunction
= this;
156 if (id
== Id::TypeInfo_Delegate
)
160 Type::typeinfodelegate
= this;
163 if (id
== Id::TypeInfo_Tuple
)
167 Type::typeinfotypelist
= this;
170 if (id
== Id::TypeInfo_Const
)
174 Type::typeinfoconst
= this;
177 if (id
== Id::TypeInfo_Invariant
)
181 Type::typeinfoinvariant
= this;
184 if (id
== Id::TypeInfo_Shared
)
188 Type::typeinfoshared
= this;
191 if (id
== Id::TypeInfo_Wild
)
195 Type::typeinfowild
= this;
198 if (id
== Id::TypeInfo_Vector
)
202 Type::typeinfovector
= this;
206 if (id
== Id::Object
)
213 if (id
== Id::Throwable
)
220 if (id
== Id::Exception
)
231 errorException
= this;
234 if (id
== Id::cpp_type_info_ptr
)
238 cpp_type_info_ptr
= this;
244 isabstract
= ABSfwdref
;
247 cpp_type_info_ptr_sym
= NULL
;
250 ClassDeclaration
*ClassDeclaration::create(Loc loc
, Identifier
*id
, BaseClasses
*baseclasses
, Dsymbols
*members
, bool inObject
)
252 return new ClassDeclaration(loc
, id
, baseclasses
, members
, inObject
);
255 Dsymbol
*ClassDeclaration::syntaxCopy(Dsymbol
*s
)
257 //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
258 ClassDeclaration
*cd
=
259 s
? (ClassDeclaration
*)s
260 : new ClassDeclaration(loc
, ident
, NULL
, NULL
, false);
262 cd
->storage_class
|= storage_class
;
264 cd
->baseclasses
->setDim(this->baseclasses
->length
);
265 for (size_t i
= 0; i
< cd
->baseclasses
->length
; i
++)
267 BaseClass
*b
= (*this->baseclasses
)[i
];
268 BaseClass
*b2
= new BaseClass(b
->type
->syntaxCopy());
269 (*cd
->baseclasses
)[i
] = b2
;
272 return ScopeDsymbol::syntaxCopy(cd
);
275 Scope
*ClassDeclaration::newScope(Scope
*sc
)
277 Scope
*sc2
= AggregateDeclaration::newScope(sc
);
280 if (global
.params
.isWindows
)
281 sc2
->linkage
= LINKwindows
;
284 /* This enables us to use COM objects under Linux and
285 * work with things like XPCOM
287 sc2
->linkage
= LINKc
;
293 /*********************************************
294 * Determine if 'this' is a base class of cd.
295 * This is used to detect circular inheritance only.
298 bool ClassDeclaration::isBaseOf2(ClassDeclaration
*cd
)
302 //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
303 for (size_t i
= 0; i
< cd
->baseclasses
->length
; i
++)
305 BaseClass
*b
= (*cd
->baseclasses
)[i
];
306 if (b
->sym
== this || isBaseOf2(b
->sym
))
312 /*******************************************
313 * Determine if 'this' is a base class of cd.
316 bool ClassDeclaration::isBaseOf(ClassDeclaration
*cd
, int *poffset
)
318 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
323 /* cd->baseClass might not be set if cd is forward referenced.
325 if (!cd
->baseClass
&& cd
->semanticRun
< PASSsemanticdone
&& !cd
->isInterfaceDeclaration())
327 dsymbolSemantic(cd
, NULL
);
328 if (!cd
->baseClass
&& cd
->semanticRun
< PASSsemanticdone
)
329 cd
->error("base class is forward referenced by %s", toChars());
332 if (this == cd
->baseClass
)
340 /*********************************************
341 * Determine if 'this' has complete base class information.
342 * This is used to detect forward references in covariant overloads.
345 bool ClassDeclaration::isBaseInfoComplete()
347 return baseok
>= BASEOKdone
;
350 Dsymbol
*ClassDeclaration::search(const Loc
&loc
, Identifier
*ident
, int flags
)
352 //printf("%s.ClassDeclaration::search('%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
354 //if (_scope) printf("%s baseok = %d\n", toChars(), baseok);
355 if (_scope
&& baseok
< BASEOKdone
)
359 // must semantic on base class/interfaces
361 dsymbolSemantic(this, NULL
);
366 if (!members
|| !symtab
) // opaque or addMember is not yet done
368 error("is forward referenced when looking for `%s`", ident
->toChars());
373 Dsymbol
*s
= ScopeDsymbol::search(loc
, ident
, flags
);
375 // don't search imports of base classes
376 if (flags
& SearchImportsOnly
)
381 // Search bases classes in depth-first, left to right order
383 for (size_t i
= 0; i
< baseclasses
->length
; i
++)
385 BaseClass
*b
= (*baseclasses
)[i
];
390 error("base %s is forward referenced", b
->sym
->ident
->toChars());
393 s
= b
->sym
->search(loc
, ident
, flags
);
396 else if (s
== this) // happens if s is nested in this and derives from this
398 else if (!(flags
& IgnoreSymbolVisibility
) && !(s
->prot().kind
== Prot::protected_
) && !symbolIsVisible(this, s
))
409 /************************************
410 * Search base classes in depth-first, left-to-right order for
411 * a class or interface named 'ident'.
412 * Stops at first found. Does not look for additional matches.
414 * ident = identifier to search for
416 * ClassDeclaration if found, null if not
418 ClassDeclaration
*ClassDeclaration::searchBase(Identifier
*ident
)
420 for (size_t i
= 0; i
< baseclasses
->length
; i
++)
422 BaseClass
*b
= (*baseclasses
)[i
];
423 ClassDeclaration
*cdb
= b
->type
->isClassHandle();
424 if (!cdb
) // Bugzilla 10616
426 if (cdb
->ident
->equals(ident
))
428 cdb
= cdb
->searchBase(ident
);
436 * Runs through the inheritance graph to set the BaseClass.offset fields.
437 * Recursive in order to account for the size of the interface classes, if they are
438 * more than just interfaces.
440 * cd = interface to look at
441 * baseOffset = offset of where cd will be placed
443 * subset of instantiated size used by cd for interfaces
445 static unsigned membersPlace(BaseClasses
*vtblInterfaces
, size_t &bi
, ClassDeclaration
*cd
, unsigned baseOffset
)
447 //printf(" membersPlace(%s, %d)\n", cd->toChars(), baseOffset);
448 unsigned offset
= baseOffset
;
450 for (size_t i
= 0; i
< cd
->interfaces
.length
; i
++)
452 BaseClass
*b
= cd
->interfaces
.ptr
[i
];
453 if (b
->sym
->sizeok
!= SIZEOKdone
)
454 b
->sym
->finalizeSize();
455 assert(b
->sym
->sizeok
== SIZEOKdone
);
457 if (!b
->sym
->alignsize
)
458 b
->sym
->alignsize
= target
.ptrsize
;
459 cd
->alignmember(b
->sym
->alignsize
, b
->sym
->alignsize
, &offset
);
460 assert(bi
< vtblInterfaces
->length
);
461 BaseClass
*bv
= (*vtblInterfaces
)[bi
];
462 if (b
->sym
->interfaces
.length
== 0)
464 //printf("\tvtblInterfaces[%d] b=%p b->sym = %s, offset = %d\n", bi, bv, bv->sym->toChars(), offset);
467 // All the base interfaces down the left side share the same offset
468 for (BaseClass
*b2
= bv
; b2
->baseInterfaces
.length
; )
470 b2
= &b2
->baseInterfaces
.ptr
[0];
472 //printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2->sym->toChars(), b2->offset);
475 membersPlace(vtblInterfaces
, bi
, b
->sym
, offset
);
476 //printf(" %s size = %d\n", b->sym->toChars(), b->sym->structsize);
477 offset
+= b
->sym
->structsize
;
478 if (cd
->alignsize
< b
->sym
->alignsize
)
479 cd
->alignsize
= b
->sym
->alignsize
;
481 return offset
- baseOffset
;
484 void ClassDeclaration::finalizeSize()
486 assert(sizeok
!= SIZEOKdone
);
488 // Set the offsets of the fields and determine the size of the class
491 assert(baseClass
->sizeok
== SIZEOKdone
);
493 alignsize
= baseClass
->alignsize
;
494 structsize
= baseClass
->structsize
;
495 if (isCPPclass() && global
.params
.isWindows
)
496 structsize
= (structsize
+ alignsize
- 1) & ~(alignsize
- 1);
498 else if (isInterfaceDeclaration())
500 if (interfaces
.length
== 0)
502 alignsize
= target
.ptrsize
;
503 structsize
= target
.ptrsize
; // allow room for __vptr
508 alignsize
= target
.ptrsize
;
509 structsize
= target
.ptrsize
; // allow room for __vptr
511 structsize
+= target
.ptrsize
; // allow room for __monitor
514 //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
515 size_t bi
= 0; // index into vtblInterfaces[]
517 // Add vptr's for any interfaces implemented by this class
518 structsize
+= membersPlace(vtblInterfaces
, bi
, this, structsize
);
520 if (isInterfaceDeclaration())
526 // FIXME: Currently setFieldOffset functions need to increase fields
527 // to calculate each variable offsets. It can be improved later.
530 unsigned offset
= structsize
;
531 for (size_t i
= 0; i
< members
->length
; i
++)
533 Dsymbol
*s
= (*members
)[i
];
534 s
->setFieldOffset(this, &offset
, false);
539 // Calculate fields[i]->overlapped
540 checkOverlappedFields();
544 * Returns: true if there's a __monitor field
546 bool ClassDeclaration::hasMonitor()
548 return classKind
== ClassKind::d
;
551 /**********************************************************
552 * fd is in the vtbl[] for this class.
553 * Return 1 if function is hidden (not findable through search).
556 int isf(void *param
, Dsymbol
*s
)
558 FuncDeclaration
*fd
= s
->isFuncDeclaration();
561 //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
562 return (RootObject
*)param
== fd
;
565 bool ClassDeclaration::isFuncHidden(FuncDeclaration
*fd
)
567 //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toPrettyChars());
568 Dsymbol
*s
= search(Loc(), fd
->ident
, IgnoreAmbiguous
| IgnoreErrors
);
571 //printf("not found\n");
572 /* Because, due to a hack, if there are multiple definitions
573 * of fd->ident, NULL is returned.
578 OverloadSet
*os
= s
->isOverloadSet();
581 for (size_t i
= 0; i
< os
->a
.length
; i
++)
583 Dsymbol
*s2
= os
->a
[i
];
584 FuncDeclaration
*f2
= s2
->isFuncDeclaration();
585 if (f2
&& overloadApply(f2
, (void *)fd
, &isf
))
592 FuncDeclaration
*fdstart
= s
->isFuncDeclaration();
593 //printf("%s fdstart = %p\n", s->kind(), fdstart);
594 if (overloadApply(fdstart
, (void *)fd
, &isf
))
597 return !fd
->parent
->isTemplateMixin();
602 * Find virtual function matching identifier and type.
603 * Used to build virtual function tables for interface implementations.
606 FuncDeclaration
*ClassDeclaration::findFunc(Identifier
*ident
, TypeFunction
*tf
)
608 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
609 FuncDeclaration
*fdmatch
= NULL
;
610 FuncDeclaration
*fdambig
= NULL
;
612 ClassDeclaration
*cd
= this;
613 Dsymbols
*vtbl
= &cd
->vtbl
;
616 for (size_t i
= 0; i
< vtbl
->length
; i
++)
618 FuncDeclaration
*fd
= (*vtbl
)[i
]->isFuncDeclaration();
620 continue; // the first entry might be a ClassInfo
622 //printf("\t[%d] = %s\n", i, fd->toChars());
623 if (ident
== fd
->ident
&&
624 fd
->type
->covariant(tf
) == 1)
626 //printf("fd->parent->isClassDeclaration() = %p\n", fd->parent->isClassDeclaration());
633 // Function type matcing: exact > covariant
634 MATCH m1
= tf
->equals(fd
->type
) ? MATCHexact
: MATCHnomatch
;
635 MATCH m2
= tf
->equals(fdmatch
->type
) ? MATCHexact
: MATCHnomatch
;
643 MATCH m1
= (tf
->mod
== fd
->type
->mod
) ? MATCHexact
: MATCHnomatch
;
644 MATCH m2
= (tf
->mod
== fdmatch
->type
->mod
) ? MATCHexact
: MATCHnomatch
;
652 // The way of definition: non-mixin > mixin
653 MATCH m1
= fd
->parent
->isClassDeclaration() ? MATCHexact
: MATCHnomatch
;
654 MATCH m2
= fdmatch
->parent
->isClassDeclaration() ? MATCHexact
: MATCHnomatch
;
662 //printf("Lambig fdambig = %s %s [%s]\n", fdambig->toChars(), fdambig->type->toChars(), fdambig->loc.toChars());
668 //printf("Lfd fdmatch = %s %s [%s]\n", fdmatch->toChars(), fdmatch->type->toChars(), fdmatch->loc.toChars());
674 //else printf("\t\t%d\n", fd->type->covariant(tf));
678 vtbl
= &cd
->vtblFinal
;
683 error("ambiguous virtual function %s", fdambig
->toChars());
687 /****************************************
690 bool ClassDeclaration::isCOMclass() const
695 bool ClassDeclaration::isCOMinterface() const
700 bool ClassDeclaration::isCPPclass() const
702 return classKind
== ClassKind::cpp
;
705 bool ClassDeclaration::isCPPinterface() const
711 /****************************************
714 bool ClassDeclaration::isAbstract()
716 if (isabstract
!= ABSfwdref
)
717 return isabstract
== ABSyes
;
719 /* Bugzilla 11169: Resolve forward references to all class member functions,
720 * and determine whether this class is abstract.
722 struct SearchAbstract
724 static int fp(Dsymbol
*s
, void *)
726 FuncDeclaration
*fd
= s
->isFuncDeclaration();
729 if (fd
->storage_class
& STCstatic
)
733 dsymbolSemantic(fd
, NULL
);
735 if (fd
->isAbstract())
741 for (size_t i
= 0; i
< members
->length
; i
++)
743 Dsymbol
*s
= (*members
)[i
];
744 if (s
->apply(&SearchAbstract::fp
, this))
751 /* Iterate inherited member functions and check their abstract attribute.
753 for (size_t i
= 1; i
< vtbl
.length
; i
++)
755 FuncDeclaration
*fd
= vtbl
[i
]->isFuncDeclaration();
756 //if (fd) printf("\tvtbl[%d] = [%s] %s\n", i, fd->loc.toChars(), fd->toChars());
757 if (!fd
|| fd
->isAbstract())
769 /****************************************
770 * Determine if slot 0 of the vtbl[] is reserved for something else.
771 * For class objects, yes, this is where the classinfo ptr goes.
772 * For COM interfaces, no.
773 * For non-COM interfaces, yes, this is where the Interface ptr goes.
775 * 0 vtbl[0] is first virtual function pointer
776 * 1 vtbl[0] is classinfo/interfaceinfo pointer
779 int ClassDeclaration::vtblOffset() const
781 return classKind
== ClassKind::cpp
? 0 : 1;
784 /****************************************
787 const char *ClassDeclaration::kind() const
792 /****************************************
795 void ClassDeclaration::addLocalClass(ClassDeclarations
*aclasses
)
797 aclasses
->push(this);
800 /********************************* InterfaceDeclaration ****************************/
802 InterfaceDeclaration::InterfaceDeclaration(Loc loc
, Identifier
*id
, BaseClasses
*baseclasses
)
803 : ClassDeclaration(loc
, id
, baseclasses
, NULL
, false)
805 if (id
== Id::IUnknown
) // IUnknown is the root of all COM interfaces
808 classKind
= ClassKind::cpp
; // IUnknown is also a C++ interface
812 Dsymbol
*InterfaceDeclaration::syntaxCopy(Dsymbol
*s
)
814 InterfaceDeclaration
*id
=
815 s
? (InterfaceDeclaration
*)s
816 : new InterfaceDeclaration(loc
, ident
, NULL
);
817 return ClassDeclaration::syntaxCopy(id
);
820 Scope
*InterfaceDeclaration::newScope(Scope
*sc
)
822 Scope
*sc2
= ClassDeclaration::newScope(sc
);
824 sc2
->linkage
= LINKwindows
;
825 else if (classKind
== ClassKind::cpp
)
826 sc2
->linkage
= LINKcpp
;
827 else if (classKind
== ClassKind::objc
)
828 sc2
->linkage
= LINKobjc
;
832 /*******************************************
833 * Determine if 'this' is a base class of cd.
834 * (Actually, if it is an interface supported by cd)
836 * *poffset offset to start of class
837 * OFFSET_RUNTIME must determine offset at runtime
843 bool InterfaceDeclaration::isBaseOf(ClassDeclaration
*cd
, int *poffset
)
845 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
847 for (size_t j
= 0; j
< cd
->interfaces
.length
; j
++)
849 BaseClass
*b
= cd
->interfaces
.ptr
[j
];
851 //printf("\tX base %s\n", b->sym->toChars());
854 //printf("\tfound at offset %d\n", b->offset);
857 // don't return incorrect offsets https://issues.dlang.org/show_bug.cgi?id=16980
858 *poffset
= cd
->sizeok
== SIZEOKdone
? b
->offset
: OFFSET_FWDREF
;
860 //printf("\tfound at offset %d\n", b->offset);
863 if (isBaseOf(b
, poffset
))
867 if (cd
->baseClass
&& isBaseOf(cd
->baseClass
, poffset
))
875 bool InterfaceDeclaration::isBaseOf(BaseClass
*bc
, int *poffset
)
877 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->sym->toChars());
878 for (size_t j
= 0; j
< bc
->baseInterfaces
.length
; j
++)
880 BaseClass
*b
= &bc
->baseInterfaces
.ptr
[j
];
882 //printf("\tY base %s\n", b->sym->toChars());
885 //printf("\tfound at offset %d\n", b->offset);
888 *poffset
= b
->offset
;
892 if (isBaseOf(b
, poffset
))
902 /****************************************
903 * Determine if slot 0 of the vtbl[] is reserved for something else.
904 * For class objects, yes, this is where the ClassInfo ptr goes.
905 * For COM interfaces, no.
906 * For non-COM interfaces, yes, this is where the Interface ptr goes.
909 int InterfaceDeclaration::vtblOffset() const
911 if (isCOMinterface() || isCPPinterface())
916 bool InterfaceDeclaration::isCOMinterface() const
921 bool InterfaceDeclaration::isCPPinterface() const
923 return classKind
== ClassKind::cpp
;
926 /*******************************************
929 const char *InterfaceDeclaration::kind() const
935 /******************************** BaseClass *****************************/
937 BaseClass::BaseClass()
943 this->baseInterfaces
.length
= 0;
944 this->baseInterfaces
.ptr
= NULL
;
947 BaseClass::BaseClass(Type
*type
)
949 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
954 this->baseInterfaces
.length
= 0;
955 this->baseInterfaces
.ptr
= NULL
;
958 /****************************************
959 * Fill in vtbl[] for base class based on member functions of class cd.
961 * vtbl if !=NULL, fill it in
962 * newinstance !=0 means all entries must be filled in by members
963 * of cd, not members of any base classes of cd.
965 * true if any entries were filled in by members of cd (not exclusively
969 bool BaseClass::fillVtbl(ClassDeclaration
*cd
, FuncDeclarations
*vtbl
, int newinstance
)
973 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", sym->toChars(), cd->toChars());
975 vtbl
->setDim(sym
->vtbl
.length
);
977 // first entry is ClassInfo reference
978 for (size_t j
= sym
->vtblOffset(); j
< sym
->vtbl
.length
; j
++)
980 FuncDeclaration
*ifd
= sym
->vtbl
[j
]->isFuncDeclaration();
984 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
987 // Find corresponding function in this class
988 tf
= ifd
->type
->toTypeFunction();
989 fd
= cd
->findFunc(ifd
->ident
, tf
);
990 if (fd
&& !fd
->isAbstract())
992 //printf(" found\n");
993 // Check that calling conventions match
994 if (fd
->linkage
!= ifd
->linkage
)
995 fd
->error("linkage doesn't match interface function");
997 // Check that it is current
998 //printf("newinstance = %d fd->toParent() = %s ifd->toParent() = %s\n",
999 //newinstance, fd->toParent()->toChars(), ifd->toParent()->toChars());
1000 if (newinstance
&& fd
->toParent() != cd
&& ifd
->toParent() == sym
)
1001 cd
->error("interface function `%s` is not implemented", ifd
->toFullSignature());
1003 if (fd
->toParent() == cd
)
1008 //printf(" not found %p\n", fd);
1009 // BUG: should mark this class as abstract?
1010 if (!cd
->isAbstract())
1011 cd
->error("interface function `%s` is not implemented", ifd
->toFullSignature());
1022 void BaseClass::copyBaseInterfaces(BaseClasses
*vtblInterfaces
)
1024 //printf("+copyBaseInterfaces(), %s\n", sym->toChars());
1025 // if (baseInterfaces.length)
1028 baseInterfaces
.length
= sym
->interfaces
.length
;
1029 baseInterfaces
.ptr
= (BaseClass
*)mem
.xcalloc(baseInterfaces
.length
, sizeof(BaseClass
));
1031 //printf("%s.copyBaseInterfaces()\n", sym->toChars());
1032 for (size_t i
= 0; i
< baseInterfaces
.length
; i
++)
1034 void *pb
= &baseInterfaces
.ptr
[i
];
1035 BaseClass
*b2
= sym
->interfaces
.ptr
[i
];
1037 assert(b2
->vtbl
.length
== 0); // should not be filled yet
1038 BaseClass
*b
= (BaseClass
*)memcpy(pb
, b2
, sizeof(BaseClass
));
1040 if (i
) // single inheritance is i==0
1041 vtblInterfaces
->push(b
); // only need for M.I.
1042 b
->copyBaseInterfaces(vtblInterfaces
);
1044 //printf("-copyBaseInterfaces\n");