]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/d/dmd/dclass.c
d: Merge upstream dmd 7132b3537
[thirdparty/gcc.git] / gcc / d / dmd / dclass.c
1
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
9 */
10
11 #include "root/dsystem.h" // mem{cpy|set}()
12 #include "root/root.h"
13 #include "root/rmem.h"
14
15 #include "errors.h"
16 #include "enum.h"
17 #include "init.h"
18 #include "attrib.h"
19 #include "declaration.h"
20 #include "aggregate.h"
21 #include "id.h"
22 #include "mtype.h"
23 #include "scope.h"
24 #include "module.h"
25 #include "expression.h"
26 #include "statement.h"
27 #include "template.h"
28 #include "target.h"
29 #include "objc.h"
30
31 bool symbolIsVisible(Dsymbol *origin, Dsymbol *s);
32 Objc *objc();
33
34
35 /********************************* ClassDeclaration ****************************/
36
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
42
43 ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject)
44 : AggregateDeclaration(loc, id ? id : Identifier::generateId("__anonclass"))
45 {
46 static const char msg[] = "only object.d can define this reserved class name";
47
48 if (baseclasses)
49 {
50 // Actually, this is a transfer
51 this->baseclasses = baseclasses;
52 }
53 else
54 this->baseclasses = new BaseClasses();
55
56 this->members = members;
57
58 baseClass = NULL;
59
60 interfaces.length = 0;
61 interfaces.ptr = NULL;
62
63 vtblInterfaces = NULL;
64
65 //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses->length);
66
67 // For forward references
68 type = new TypeClass(this);
69
70 staticCtor = NULL;
71 staticDtor = NULL;
72
73 vtblsym = NULL;
74 vclassinfo = NULL;
75
76 if (id)
77 {
78 // Look for special class names
79
80 if (id == Id::__sizeof || id == Id::__xalignof || id == Id::_mangleof)
81 error("illegal class name");
82
83 // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
84 if (id->toChars()[0] == 'T')
85 {
86 if (id == Id::TypeInfo)
87 {
88 if (!inObject)
89 error("%s", msg);
90 Type::dtypeinfo = this;
91 }
92
93 if (id == Id::TypeInfo_Class)
94 {
95 if (!inObject)
96 error("%s", msg);
97 Type::typeinfoclass = this;
98 }
99
100 if (id == Id::TypeInfo_Interface)
101 {
102 if (!inObject)
103 error("%s", msg);
104 Type::typeinfointerface = this;
105 }
106
107 if (id == Id::TypeInfo_Struct)
108 {
109 if (!inObject)
110 error("%s", msg);
111 Type::typeinfostruct = this;
112 }
113
114 if (id == Id::TypeInfo_Pointer)
115 {
116 if (!inObject)
117 error("%s", msg);
118 Type::typeinfopointer = this;
119 }
120
121 if (id == Id::TypeInfo_Array)
122 {
123 if (!inObject)
124 error("%s", msg);
125 Type::typeinfoarray = this;
126 }
127
128 if (id == Id::TypeInfo_StaticArray)
129 {
130 //if (!inObject)
131 // Type::typeinfostaticarray->error("%s", msg);
132 Type::typeinfostaticarray = this;
133 }
134
135 if (id == Id::TypeInfo_AssociativeArray)
136 {
137 if (!inObject)
138 error("%s", msg);
139 Type::typeinfoassociativearray = this;
140 }
141
142 if (id == Id::TypeInfo_Enum)
143 {
144 if (!inObject)
145 error("%s", msg);
146 Type::typeinfoenum = this;
147 }
148
149 if (id == Id::TypeInfo_Function)
150 {
151 if (!inObject)
152 error("%s", msg);
153 Type::typeinfofunction = this;
154 }
155
156 if (id == Id::TypeInfo_Delegate)
157 {
158 if (!inObject)
159 error("%s", msg);
160 Type::typeinfodelegate = this;
161 }
162
163 if (id == Id::TypeInfo_Tuple)
164 {
165 if (!inObject)
166 error("%s", msg);
167 Type::typeinfotypelist = this;
168 }
169
170 if (id == Id::TypeInfo_Const)
171 {
172 if (!inObject)
173 error("%s", msg);
174 Type::typeinfoconst = this;
175 }
176
177 if (id == Id::TypeInfo_Invariant)
178 {
179 if (!inObject)
180 error("%s", msg);
181 Type::typeinfoinvariant = this;
182 }
183
184 if (id == Id::TypeInfo_Shared)
185 {
186 if (!inObject)
187 error("%s", msg);
188 Type::typeinfoshared = this;
189 }
190
191 if (id == Id::TypeInfo_Wild)
192 {
193 if (!inObject)
194 error("%s", msg);
195 Type::typeinfowild = this;
196 }
197
198 if (id == Id::TypeInfo_Vector)
199 {
200 if (!inObject)
201 error("%s", msg);
202 Type::typeinfovector = this;
203 }
204 }
205
206 if (id == Id::Object)
207 {
208 if (!inObject)
209 error("%s", msg);
210 object = this;
211 }
212
213 if (id == Id::Throwable)
214 {
215 if (!inObject)
216 error("%s", msg);
217 throwable = this;
218 }
219
220 if (id == Id::Exception)
221 {
222 if (!inObject)
223 error("%s", msg);
224 exception = this;
225 }
226
227 if (id == Id::Error)
228 {
229 if (!inObject)
230 error("%s", msg);
231 errorException = this;
232 }
233
234 if (id == Id::cpp_type_info_ptr)
235 {
236 if (!inObject)
237 error("%s", msg);
238 cpp_type_info_ptr = this;
239 }
240 }
241
242 com = false;
243 isscope = false;
244 isabstract = ABSfwdref;
245 inuse = 0;
246 baseok = BASEOKnone;
247 cpp_type_info_ptr_sym = NULL;
248 }
249
250 ClassDeclaration *ClassDeclaration::create(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject)
251 {
252 return new ClassDeclaration(loc, id, baseclasses, members, inObject);
253 }
254
255 Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
256 {
257 //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
258 ClassDeclaration *cd =
259 s ? (ClassDeclaration *)s
260 : new ClassDeclaration(loc, ident, NULL, NULL, false);
261
262 cd->storage_class |= storage_class;
263
264 cd->baseclasses->setDim(this->baseclasses->length);
265 for (size_t i = 0; i < cd->baseclasses->length; i++)
266 {
267 BaseClass *b = (*this->baseclasses)[i];
268 BaseClass *b2 = new BaseClass(b->type->syntaxCopy());
269 (*cd->baseclasses)[i] = b2;
270 }
271
272 return ScopeDsymbol::syntaxCopy(cd);
273 }
274
275 Scope *ClassDeclaration::newScope(Scope *sc)
276 {
277 Scope *sc2 = AggregateDeclaration::newScope(sc);
278 if (isCOMclass())
279 {
280 if (global.params.isWindows)
281 sc2->linkage = LINKwindows;
282 else
283 {
284 /* This enables us to use COM objects under Linux and
285 * work with things like XPCOM
286 */
287 sc2->linkage = LINKc;
288 }
289 }
290 return sc2;
291 }
292
293 /*********************************************
294 * Determine if 'this' is a base class of cd.
295 * This is used to detect circular inheritance only.
296 */
297
298 bool ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
299 {
300 if (!cd)
301 return false;
302 //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
303 for (size_t i = 0; i < cd->baseclasses->length; i++)
304 {
305 BaseClass *b = (*cd->baseclasses)[i];
306 if (b->sym == this || isBaseOf2(b->sym))
307 return true;
308 }
309 return false;
310 }
311
312 /*******************************************
313 * Determine if 'this' is a base class of cd.
314 */
315
316 bool ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
317 {
318 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
319 if (poffset)
320 *poffset = 0;
321 while (cd)
322 {
323 /* cd->baseClass might not be set if cd is forward referenced.
324 */
325 if (!cd->baseClass && cd->semanticRun < PASSsemanticdone && !cd->isInterfaceDeclaration())
326 {
327 dsymbolSemantic(cd, NULL);
328 if (!cd->baseClass && cd->semanticRun < PASSsemanticdone)
329 cd->error("base class is forward referenced by %s", toChars());
330 }
331
332 if (this == cd->baseClass)
333 return true;
334
335 cd = cd->baseClass;
336 }
337 return false;
338 }
339
340 /*********************************************
341 * Determine if 'this' has complete base class information.
342 * This is used to detect forward references in covariant overloads.
343 */
344
345 bool ClassDeclaration::isBaseInfoComplete()
346 {
347 return baseok >= BASEOKdone;
348 }
349
350 Dsymbol *ClassDeclaration::search(const Loc &loc, Identifier *ident, int flags)
351 {
352 //printf("%s.ClassDeclaration::search('%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
353
354 //if (_scope) printf("%s baseok = %d\n", toChars(), baseok);
355 if (_scope && baseok < BASEOKdone)
356 {
357 if (!inuse)
358 {
359 // must semantic on base class/interfaces
360 ++inuse;
361 dsymbolSemantic(this, NULL);
362 --inuse;
363 }
364 }
365
366 if (!members || !symtab) // opaque or addMember is not yet done
367 {
368 error("is forward referenced when looking for `%s`", ident->toChars());
369 //*(char*)0=0;
370 return NULL;
371 }
372
373 Dsymbol *s = ScopeDsymbol::search(loc, ident, flags);
374
375 // don't search imports of base classes
376 if (flags & SearchImportsOnly)
377 return s;
378
379 if (!s)
380 {
381 // Search bases classes in depth-first, left to right order
382
383 for (size_t i = 0; i < baseclasses->length; i++)
384 {
385 BaseClass *b = (*baseclasses)[i];
386
387 if (b->sym)
388 {
389 if (!b->sym->symtab)
390 error("base %s is forward referenced", b->sym->ident->toChars());
391 else
392 {
393 s = b->sym->search(loc, ident, flags);
394 if (!s)
395 continue;
396 else if (s == this) // happens if s is nested in this and derives from this
397 s = NULL;
398 else if (!(flags & IgnoreSymbolVisibility) && !(s->prot().kind == Prot::protected_) && !symbolIsVisible(this, s))
399 s = NULL;
400 else
401 break;
402 }
403 }
404 }
405 }
406 return s;
407 }
408
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.
413 * Params:
414 * ident = identifier to search for
415 * Returns:
416 * ClassDeclaration if found, null if not
417 */
418 ClassDeclaration *ClassDeclaration::searchBase(Identifier *ident)
419 {
420 for (size_t i = 0; i < baseclasses->length; i++)
421 {
422 BaseClass *b = (*baseclasses)[i];
423 ClassDeclaration *cdb = b->type->isClassHandle();
424 if (!cdb) // Bugzilla 10616
425 return NULL;
426 if (cdb->ident->equals(ident))
427 return cdb;
428 cdb = cdb->searchBase(ident);
429 if (cdb)
430 return cdb;
431 }
432 return NULL;
433 }
434
435 /****
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.
439 * Params:
440 * cd = interface to look at
441 * baseOffset = offset of where cd will be placed
442 * Returns:
443 * subset of instantiated size used by cd for interfaces
444 */
445 static unsigned membersPlace(BaseClasses *vtblInterfaces, size_t &bi, ClassDeclaration *cd, unsigned baseOffset)
446 {
447 //printf(" membersPlace(%s, %d)\n", cd->toChars(), baseOffset);
448 unsigned offset = baseOffset;
449
450 for (size_t i = 0; i < cd->interfaces.length; i++)
451 {
452 BaseClass *b = cd->interfaces.ptr[i];
453 if (b->sym->sizeok != SIZEOKdone)
454 b->sym->finalizeSize();
455 assert(b->sym->sizeok == SIZEOKdone);
456
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)
463 {
464 //printf("\tvtblInterfaces[%d] b=%p b->sym = %s, offset = %d\n", bi, bv, bv->sym->toChars(), offset);
465 bv->offset = offset;
466 ++bi;
467 // All the base interfaces down the left side share the same offset
468 for (BaseClass *b2 = bv; b2->baseInterfaces.length; )
469 {
470 b2 = &b2->baseInterfaces.ptr[0];
471 b2->offset = offset;
472 //printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2->sym->toChars(), b2->offset);
473 }
474 }
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;
480 }
481 return offset - baseOffset;
482 }
483
484 void ClassDeclaration::finalizeSize()
485 {
486 assert(sizeok != SIZEOKdone);
487
488 // Set the offsets of the fields and determine the size of the class
489 if (baseClass)
490 {
491 assert(baseClass->sizeok == SIZEOKdone);
492
493 alignsize = baseClass->alignsize;
494 structsize = baseClass->structsize;
495 if (isCPPclass() && global.params.isWindows)
496 structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
497 }
498 else if (isInterfaceDeclaration())
499 {
500 if (interfaces.length == 0)
501 {
502 alignsize = target.ptrsize;
503 structsize = target.ptrsize; // allow room for __vptr
504 }
505 }
506 else
507 {
508 alignsize = target.ptrsize;
509 structsize = target.ptrsize; // allow room for __vptr
510 if (hasMonitor())
511 structsize += target.ptrsize; // allow room for __monitor
512 }
513
514 //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
515 size_t bi = 0; // index into vtblInterfaces[]
516
517 // Add vptr's for any interfaces implemented by this class
518 structsize += membersPlace(vtblInterfaces, bi, this, structsize);
519
520 if (isInterfaceDeclaration())
521 {
522 sizeok = SIZEOKdone;
523 return;
524 }
525
526 // FIXME: Currently setFieldOffset functions need to increase fields
527 // to calculate each variable offsets. It can be improved later.
528 fields.setDim(0);
529
530 unsigned offset = structsize;
531 for (size_t i = 0; i < members->length; i++)
532 {
533 Dsymbol *s = (*members)[i];
534 s->setFieldOffset(this, &offset, false);
535 }
536
537 sizeok = SIZEOKdone;
538
539 // Calculate fields[i]->overlapped
540 checkOverlappedFields();
541 }
542
543 /**************
544 * Returns: true if there's a __monitor field
545 */
546 bool ClassDeclaration::hasMonitor()
547 {
548 return classKind == ClassKind::d;
549 }
550
551 /**********************************************************
552 * fd is in the vtbl[] for this class.
553 * Return 1 if function is hidden (not findable through search).
554 */
555
556 int isf(void *param, Dsymbol *s)
557 {
558 FuncDeclaration *fd = s->isFuncDeclaration();
559 if (!fd)
560 return 0;
561 //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
562 return (RootObject *)param == fd;
563 }
564
565 bool ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
566 {
567 //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toPrettyChars());
568 Dsymbol *s = search(Loc(), fd->ident, IgnoreAmbiguous | IgnoreErrors);
569 if (!s)
570 {
571 //printf("not found\n");
572 /* Because, due to a hack, if there are multiple definitions
573 * of fd->ident, NULL is returned.
574 */
575 return false;
576 }
577 s = s->toAlias();
578 OverloadSet *os = s->isOverloadSet();
579 if (os)
580 {
581 for (size_t i = 0; i < os->a.length; i++)
582 {
583 Dsymbol *s2 = os->a[i];
584 FuncDeclaration *f2 = s2->isFuncDeclaration();
585 if (f2 && overloadApply(f2, (void *)fd, &isf))
586 return false;
587 }
588 return true;
589 }
590 else
591 {
592 FuncDeclaration *fdstart = s->isFuncDeclaration();
593 //printf("%s fdstart = %p\n", s->kind(), fdstart);
594 if (overloadApply(fdstart, (void *)fd, &isf))
595 return false;
596
597 return !fd->parent->isTemplateMixin();
598 }
599 }
600
601 /****************
602 * Find virtual function matching identifier and type.
603 * Used to build virtual function tables for interface implementations.
604 */
605
606 FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
607 {
608 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
609 FuncDeclaration *fdmatch = NULL;
610 FuncDeclaration *fdambig = NULL;
611
612 ClassDeclaration *cd = this;
613 Dsymbols *vtbl = &cd->vtbl;
614 while (1)
615 {
616 for (size_t i = 0; i < vtbl->length; i++)
617 {
618 FuncDeclaration *fd = (*vtbl)[i]->isFuncDeclaration();
619 if (!fd)
620 continue; // the first entry might be a ClassInfo
621
622 //printf("\t[%d] = %s\n", i, fd->toChars());
623 if (ident == fd->ident &&
624 fd->type->covariant(tf) == 1)
625 {
626 //printf("fd->parent->isClassDeclaration() = %p\n", fd->parent->isClassDeclaration());
627 if (!fdmatch)
628 goto Lfd;
629 if (fd == fdmatch)
630 goto Lfdmatch;
631
632 {
633 // Function type matcing: exact > covariant
634 MATCH m1 = tf->equals(fd ->type) ? MATCHexact : MATCHnomatch;
635 MATCH m2 = tf->equals(fdmatch->type) ? MATCHexact : MATCHnomatch;
636 if (m1 > m2)
637 goto Lfd;
638 else if (m1 < m2)
639 goto Lfdmatch;
640 }
641
642 {
643 MATCH m1 = (tf->mod == fd ->type->mod) ? MATCHexact : MATCHnomatch;
644 MATCH m2 = (tf->mod == fdmatch->type->mod) ? MATCHexact : MATCHnomatch;
645 if (m1 > m2)
646 goto Lfd;
647 else if (m1 < m2)
648 goto Lfdmatch;
649 }
650
651 {
652 // The way of definition: non-mixin > mixin
653 MATCH m1 = fd ->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch;
654 MATCH m2 = fdmatch->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch;
655 if (m1 > m2)
656 goto Lfd;
657 else if (m1 < m2)
658 goto Lfdmatch;
659 }
660
661 fdambig = fd;
662 //printf("Lambig fdambig = %s %s [%s]\n", fdambig->toChars(), fdambig->type->toChars(), fdambig->loc.toChars());
663 continue;
664
665 Lfd:
666 fdmatch = fd;
667 fdambig = NULL;
668 //printf("Lfd fdmatch = %s %s [%s]\n", fdmatch->toChars(), fdmatch->type->toChars(), fdmatch->loc.toChars());
669 continue;
670
671 Lfdmatch:
672 continue;
673 }
674 //else printf("\t\t%d\n", fd->type->covariant(tf));
675 }
676 if (!cd)
677 break;
678 vtbl = &cd->vtblFinal;
679 cd = cd->baseClass;
680 }
681
682 if (fdambig)
683 error("ambiguous virtual function %s", fdambig->toChars());
684 return fdmatch;
685 }
686
687 /****************************************
688 */
689
690 bool ClassDeclaration::isCOMclass() const
691 {
692 return com;
693 }
694
695 bool ClassDeclaration::isCOMinterface() const
696 {
697 return false;
698 }
699
700 bool ClassDeclaration::isCPPclass() const
701 {
702 return classKind == ClassKind::cpp;
703 }
704
705 bool ClassDeclaration::isCPPinterface() const
706 {
707 return false;
708 }
709
710
711 /****************************************
712 */
713
714 bool ClassDeclaration::isAbstract()
715 {
716 if (isabstract != ABSfwdref)
717 return isabstract == ABSyes;
718
719 /* Bugzilla 11169: Resolve forward references to all class member functions,
720 * and determine whether this class is abstract.
721 */
722 struct SearchAbstract
723 {
724 static int fp(Dsymbol *s, void *)
725 {
726 FuncDeclaration *fd = s->isFuncDeclaration();
727 if (!fd)
728 return 0;
729 if (fd->storage_class & STCstatic)
730 return 0;
731
732 if (fd->_scope)
733 dsymbolSemantic(fd, NULL);
734
735 if (fd->isAbstract())
736 return 1;
737 return 0;
738 }
739 };
740
741 for (size_t i = 0; i < members->length; i++)
742 {
743 Dsymbol *s = (*members)[i];
744 if (s->apply(&SearchAbstract::fp, this))
745 {
746 isabstract = ABSyes;
747 return true;
748 }
749 }
750
751 /* Iterate inherited member functions and check their abstract attribute.
752 */
753 for (size_t i = 1; i < vtbl.length; i++)
754 {
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())
758 {
759 isabstract = ABSyes;
760 return true;
761 }
762 }
763
764 isabstract = ABSno;
765 return false;
766 }
767
768
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.
774 * Returns:
775 * 0 vtbl[0] is first virtual function pointer
776 * 1 vtbl[0] is classinfo/interfaceinfo pointer
777 */
778
779 int ClassDeclaration::vtblOffset() const
780 {
781 return classKind == ClassKind::cpp ? 0 : 1;
782 }
783
784 /****************************************
785 */
786
787 const char *ClassDeclaration::kind() const
788 {
789 return "class";
790 }
791
792 /****************************************
793 */
794
795 void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses)
796 {
797 aclasses->push(this);
798 }
799
800 /********************************* InterfaceDeclaration ****************************/
801
802 InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
803 : ClassDeclaration(loc, id, baseclasses, NULL, false)
804 {
805 if (id == Id::IUnknown) // IUnknown is the root of all COM interfaces
806 {
807 com = true;
808 classKind = ClassKind::cpp; // IUnknown is also a C++ interface
809 }
810 }
811
812 Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s)
813 {
814 InterfaceDeclaration *id =
815 s ? (InterfaceDeclaration *)s
816 : new InterfaceDeclaration(loc, ident, NULL);
817 return ClassDeclaration::syntaxCopy(id);
818 }
819
820 Scope *InterfaceDeclaration::newScope(Scope *sc)
821 {
822 Scope *sc2 = ClassDeclaration::newScope(sc);
823 if (com)
824 sc2->linkage = LINKwindows;
825 else if (classKind == ClassKind::cpp)
826 sc2->linkage = LINKcpp;
827 else if (classKind == ClassKind::objc)
828 sc2->linkage = LINKobjc;
829 return sc2;
830 }
831
832 /*******************************************
833 * Determine if 'this' is a base class of cd.
834 * (Actually, if it is an interface supported by cd)
835 * Output:
836 * *poffset offset to start of class
837 * OFFSET_RUNTIME must determine offset at runtime
838 * Returns:
839 * false not a base
840 * true is a base
841 */
842
843 bool InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
844 {
845 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
846 assert(!baseClass);
847 for (size_t j = 0; j < cd->interfaces.length; j++)
848 {
849 BaseClass *b = cd->interfaces.ptr[j];
850
851 //printf("\tX base %s\n", b->sym->toChars());
852 if (this == b->sym)
853 {
854 //printf("\tfound at offset %d\n", b->offset);
855 if (poffset)
856 {
857 // don't return incorrect offsets https://issues.dlang.org/show_bug.cgi?id=16980
858 *poffset = cd->sizeok == SIZEOKdone ? b->offset : OFFSET_FWDREF;
859 }
860 //printf("\tfound at offset %d\n", b->offset);
861 return true;
862 }
863 if (isBaseOf(b, poffset))
864 return true;
865 }
866
867 if (cd->baseClass && isBaseOf(cd->baseClass, poffset))
868 return true;
869
870 if (poffset)
871 *poffset = 0;
872 return false;
873 }
874
875 bool InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset)
876 {
877 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->sym->toChars());
878 for (size_t j = 0; j < bc->baseInterfaces.length; j++)
879 {
880 BaseClass *b = &bc->baseInterfaces.ptr[j];
881
882 //printf("\tY base %s\n", b->sym->toChars());
883 if (this == b->sym)
884 {
885 //printf("\tfound at offset %d\n", b->offset);
886 if (poffset)
887 {
888 *poffset = b->offset;
889 }
890 return true;
891 }
892 if (isBaseOf(b, poffset))
893 {
894 return true;
895 }
896 }
897 if (poffset)
898 *poffset = 0;
899 return false;
900 }
901
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.
907 */
908
909 int InterfaceDeclaration::vtblOffset() const
910 {
911 if (isCOMinterface() || isCPPinterface())
912 return 0;
913 return 1;
914 }
915
916 bool InterfaceDeclaration::isCOMinterface() const
917 {
918 return com;
919 }
920
921 bool InterfaceDeclaration::isCPPinterface() const
922 {
923 return classKind == ClassKind::cpp;
924 }
925
926 /*******************************************
927 */
928
929 const char *InterfaceDeclaration::kind() const
930 {
931 return "interface";
932 }
933
934
935 /******************************** BaseClass *****************************/
936
937 BaseClass::BaseClass()
938 {
939 this->type = NULL;
940 this->sym = NULL;
941 this->offset = 0;
942
943 this->baseInterfaces.length = 0;
944 this->baseInterfaces.ptr = NULL;
945 }
946
947 BaseClass::BaseClass(Type *type)
948 {
949 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
950 this->type = type;
951 this->sym = NULL;
952 this->offset = 0;
953
954 this->baseInterfaces.length = 0;
955 this->baseInterfaces.ptr = NULL;
956 }
957
958 /****************************************
959 * Fill in vtbl[] for base class based on member functions of class cd.
960 * Input:
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.
964 * Returns:
965 * true if any entries were filled in by members of cd (not exclusively
966 * by base classes)
967 */
968
969 bool BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance)
970 {
971 bool result = false;
972
973 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", sym->toChars(), cd->toChars());
974 if (vtbl)
975 vtbl->setDim(sym->vtbl.length);
976
977 // first entry is ClassInfo reference
978 for (size_t j = sym->vtblOffset(); j < sym->vtbl.length; j++)
979 {
980 FuncDeclaration *ifd = sym->vtbl[j]->isFuncDeclaration();
981 FuncDeclaration *fd;
982 TypeFunction *tf;
983
984 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
985
986 assert(ifd);
987 // Find corresponding function in this class
988 tf = ifd->type->toTypeFunction();
989 fd = cd->findFunc(ifd->ident, tf);
990 if (fd && !fd->isAbstract())
991 {
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");
996
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());
1002
1003 if (fd->toParent() == cd)
1004 result = true;
1005 }
1006 else
1007 {
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());
1012
1013 fd = NULL;
1014 }
1015 if (vtbl)
1016 (*vtbl)[j] = fd;
1017 }
1018
1019 return result;
1020 }
1021
1022 void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces)
1023 {
1024 //printf("+copyBaseInterfaces(), %s\n", sym->toChars());
1025 // if (baseInterfaces.length)
1026 // return;
1027
1028 baseInterfaces.length = sym->interfaces.length;
1029 baseInterfaces.ptr = (BaseClass *)mem.xcalloc(baseInterfaces.length, sizeof(BaseClass));
1030
1031 //printf("%s.copyBaseInterfaces()\n", sym->toChars());
1032 for (size_t i = 0; i < baseInterfaces.length; i++)
1033 {
1034 void *pb = &baseInterfaces.ptr[i];
1035 BaseClass *b2 = sym->interfaces.ptr[i];
1036
1037 assert(b2->vtbl.length == 0); // should not be filled yet
1038 BaseClass *b = (BaseClass *)memcpy(pb, b2, sizeof(BaseClass));
1039
1040 if (i) // single inheritance is i==0
1041 vtblInterfaces->push(b); // only need for M.I.
1042 b->copyBaseInterfaces(vtblInterfaces);
1043 }
1044 //printf("-copyBaseInterfaces\n");
1045 }