2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, December 2006
27 #include "declaration.h"
28 #include "aggregate.h"
33 #include "expression.h"
34 #include "statement.h"
36 /********************************* ClassDeclaration ****************************/
38 ClassDeclaration
*ClassDeclaration::classinfo
;
39 ClassDeclaration
*ClassDeclaration::object
;
41 ClassDeclaration::ClassDeclaration(Loc loc
, Identifier
*id
, BaseClasses
*baseclasses
)
42 : AggregateDeclaration(loc
, id
)
44 static char msg
[] = "only object.d can define this reserved class name";
47 this->baseclasses
= *baseclasses
;
53 vtblInterfaces
= NULL
;
55 //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses.dim);
57 // For forward references
58 type
= new TypeClass(this);
70 { // Look for special class names
72 if (id
== Id::__sizeof
|| id
== Id::alignof
|| id
== Id::mangleof
)
73 error("illegal class name");
75 // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
76 if (id
->toChars()[0] == 'T')
78 if (id
== Id::TypeInfo
)
80 Type::typeinfo
->error("%s", msg
);
81 Type::typeinfo
= this;
84 if (id
== Id::TypeInfo_Class
)
85 { if (Type::typeinfoclass
)
86 Type::typeinfoclass
->error("%s", msg
);
87 Type::typeinfoclass
= this;
90 if (id
== Id::TypeInfo_Interface
)
91 { if (Type::typeinfointerface
)
92 Type::typeinfointerface
->error("%s", msg
);
93 Type::typeinfointerface
= this;
96 if (id
== Id::TypeInfo_Struct
)
97 { if (Type::typeinfostruct
)
98 Type::typeinfostruct
->error("%s", msg
);
99 Type::typeinfostruct
= this;
102 if (id
== Id::TypeInfo_Typedef
)
103 { if (Type::typeinfotypedef
)
104 Type::typeinfotypedef
->error("%s", msg
);
105 Type::typeinfotypedef
= this;
108 if (id
== Id::TypeInfo_Pointer
)
109 { if (Type::typeinfopointer
)
110 Type::typeinfopointer
->error("%s", msg
);
111 Type::typeinfopointer
= this;
114 if (id
== Id::TypeInfo_Maybe
)
115 { if (Type::typeinfomaybe
)
116 Type::typeinfomaybe
->error("%s", msg
);
117 Type::typeinfomaybe
= this;
120 if (id
== Id::TypeInfo_Array
)
121 { if (Type::typeinfoarray
)
122 Type::typeinfoarray
->error("%s", msg
);
123 Type::typeinfoarray
= this;
126 if (id
== Id::TypeInfo_StaticArray
)
127 { //if (Type::typeinfostaticarray)
128 //Type::typeinfostaticarray->error("%s", msg);
129 Type::typeinfostaticarray
= this;
132 if (id
== Id::TypeInfo_AssociativeArray
)
133 { if (Type::typeinfoassociativearray
)
134 Type::typeinfoassociativearray
->error("%s", msg
);
135 Type::typeinfoassociativearray
= this;
138 if (id
== Id::TypeInfo_Enum
)
139 { if (Type::typeinfoenum
)
140 Type::typeinfoenum
->error("%s", msg
);
141 Type::typeinfoenum
= this;
144 if (id
== Id::TypeInfo_Function
)
145 { if (Type::typeinfofunction
)
146 Type::typeinfofunction
->error("%s", msg
);
147 Type::typeinfofunction
= this;
150 if (id
== Id::TypeInfo_Delegate
)
151 { if (Type::typeinfodelegate
)
152 Type::typeinfodelegate
->error("%s", msg
);
153 Type::typeinfodelegate
= this;
156 if (id
== Id::TypeInfo_Tuple
)
157 { if (Type::typeinfotypelist
)
158 Type::typeinfotypelist
->error("%s", msg
);
159 Type::typeinfotypelist
= this;
163 if (id
== Id::TypeInfo_Const
)
164 { if (Type::typeinfoconst
)
165 Type::typeinfoconst
->error("%s", msg
);
166 Type::typeinfoconst
= this;
169 if (id
== Id::TypeInfo_Invariant
)
170 { if (Type::typeinfoinvariant
)
171 Type::typeinfoinvariant
->error("%s", msg
);
172 Type::typeinfoinvariant
= this;
177 if (id
== Id::Object
)
179 object
->error("%s", msg
);
183 if (id
== Id::ClassInfo
)
185 classinfo
->error("%s", msg
);
189 if (id
== Id::ModuleInfo
)
190 { if (Module::moduleinfo
)
191 Module::moduleinfo
->error("%s", msg
);
192 Module::moduleinfo
= this;
204 Dsymbol
*ClassDeclaration::syntaxCopy(Dsymbol
*s
)
206 ClassDeclaration
*cd
;
208 //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
210 cd
= (ClassDeclaration
*)s
;
212 cd
= new ClassDeclaration(loc
, ident
, NULL
);
214 cd
->storage_class
|= storage_class
;
216 cd
->baseclasses
.setDim(this->baseclasses
.dim
);
217 for (int i
= 0; i
< cd
->baseclasses
.dim
; i
++)
219 BaseClass
*b
= (BaseClass
*)this->baseclasses
.data
[i
];
220 BaseClass
*b2
= new BaseClass(b
->type
->syntaxCopy(), b
->protection
);
221 cd
->baseclasses
.data
[i
] = b2
;
224 ScopeDsymbol::syntaxCopy(cd
);
228 void ClassDeclaration::semantic(Scope
*sc
)
231 //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
232 //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
233 //printf("sc->stc = %x\n", sc->stc);
235 //{ static int n; if (++n == 20) *(char*)0=0; }
237 if (!ident
) // if anonymous class
238 { char *id
= "__anonclass";
240 ident
= Identifier::generateId(id
);
245 if (!parent
&& sc
->parent
&& !sc
->parent
->isModule())
248 type
= type
->semantic(loc
, sc
);
249 handle
= handle
->semantic(loc
, sc
);
251 if (!members
) // if forward reference
252 { //printf("\tclass '%s' is forward referenced\n", toChars());
257 { //printf("\tsemantic for '%s' is already completed\n", toChars());
258 return; // semantic() already completed
262 symtab
= new DsymbolTable();
267 scx
= scope
; // save so we don't make redundant copies
271 attributes
->append(sc
->attributes
);
273 attributes
= sc
->attributes
;
278 if (sc
->stc
& STCdeprecated
)
283 if (sc
->linkage
== LINKcpp
)
284 error("cannot create C++ classes");
286 // Expand any tuples in baseclasses[]
287 for (i
= 0; i
< baseclasses
.dim
; )
288 { BaseClass
*b
= (BaseClass
*)baseclasses
.data
[i
];
289 b
->type
= b
->type
->semantic(loc
, sc
);
290 Type
*tb
= b
->type
->toBasetype();
292 if (tb
->ty
== Ttuple
)
293 { TypeTuple
*tup
= (TypeTuple
*)tb
;
294 enum PROT protection
= b
->protection
;
295 baseclasses
.remove(i
);
296 size_t dim
= Argument::dim(tup
->arguments
);
297 for (size_t j
= 0; j
< dim
; j
++)
298 { Argument
*arg
= Argument::getNth(tup
->arguments
, j
);
299 b
= new BaseClass(arg
->type
, protection
);
300 baseclasses
.insert(i
+ j
, b
);
307 // See if there's a base class as first in baseclasses[]
313 b
= (BaseClass
*)baseclasses
.data
[0];
314 //b->type = b->type->semantic(loc, sc);
315 tb
= b
->type
->toBasetype();
316 if (tb
->ty
!= Tclass
)
317 { error("base type must be class or interface, not %s", b
->type
->toChars());
318 baseclasses
.remove(0);
322 tc
= (TypeClass
*)(tb
);
324 if (tc
->sym
->isDeprecated())
328 // Deriving from deprecated class makes this one deprecated too
331 tc
->checkDeprecated(loc
, sc
);
335 if (tc
->sym
->isInterfaceDeclaration())
339 for (ClassDeclaration
*cdb
= tc
->sym
; cdb
; cdb
= cdb
->baseClass
)
343 error("circular inheritance");
344 baseclasses
.remove(0);
348 if (!tc
->sym
->symtab
|| tc
->sym
->scope
|| tc
->sym
->sizeok
== 0)
350 //error("forward reference of base class %s", baseClass->toChars());
351 // Forward reference of base class, try again later
352 //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
353 scope
= scx
? scx
: new Scope(*sc
);
355 scope
->module
->addDeferredSemantic(this);
359 { baseClass
= tc
->sym
;
367 // Treat the remaining entries in baseclasses as interfaces
368 // Check for errors, handle forward references
369 for (i
= (baseClass
? 1 : 0); i
< baseclasses
.dim
; )
374 b
= (BaseClass
*)baseclasses
.data
[i
];
375 b
->type
= b
->type
->semantic(loc
, sc
);
376 tb
= b
->type
->toBasetype();
377 if (tb
->ty
== Tclass
)
378 tc
= (TypeClass
*)tb
;
381 if (!tc
|| !tc
->sym
->isInterfaceDeclaration())
383 error("base type must be interface, not %s", b
->type
->toChars());
384 baseclasses
.remove(i
);
389 if (tc
->sym
->isDeprecated())
393 // Deriving from deprecated class makes this one deprecated too
396 tc
->checkDeprecated(loc
, sc
);
400 // Check for duplicate interfaces
401 for (size_t j
= (baseClass
? 1 : 0); j
< i
; j
++)
403 BaseClass
*b2
= (BaseClass
*)baseclasses
.data
[j
];
404 if (b2
->base
== tc
->sym
)
405 error("inherits from duplicate interface %s", b2
->base
->toChars());
409 if (!b
->base
->symtab
|| b
->base
->scope
)
411 //error("forward reference of base class %s", baseClass->toChars());
412 // Forward reference of base, try again later
413 //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
414 scope
= scx
? scx
: new Scope(*sc
);
416 scope
->module
->addDeferredSemantic(this);
424 // If no base class, and this is not an Object, use Object as base class
425 if (!baseClass
&& ident
!= Id::Object
)
427 // BUG: what if Object is redefined in an inner scope?
428 Type
*tbase
= new TypeIdentifier(0, Id::Object
);
435 error("missing or corrupt object.d");
438 bt
= tbase
->semantic(loc
, sc
)->toBasetype();
439 b
= new BaseClass(bt
, PROTpublic
);
440 baseclasses
.shift(b
);
441 assert(b
->type
->ty
== Tclass
);
442 tc
= (TypeClass
*)(b
->type
);
444 assert(!baseClass
->isInterfaceDeclaration());
448 interfaces_dim
= baseclasses
.dim
;
449 interfaces
= (BaseClass
**)baseclasses
.data
;
454 if (baseClass
->storage_class
& STCfinal
)
455 error("cannot inherit from final class %s", baseClass
->toChars());
460 // Copy vtbl[] from base class
461 vtbl
.setDim(baseClass
->vtbl
.dim
);
462 memcpy(vtbl
.data
, baseClass
->vtbl
.data
, sizeof(void *) * vtbl
.dim
);
464 // Inherit properties from base class
465 com
= baseClass
->isCOMclass();
466 isauto
= baseClass
->isauto
;
467 vthis
= baseClass
->vthis
;
468 storage_class
|= baseClass
->storage_class
& (STCconst
| STCinvariant
);
472 // No base class, so this is the root of the class hierarchy
474 vtbl
.push(this); // leave room for classinfo as first member
477 protection
= sc
->protection
;
478 storage_class
|= sc
->stc
;
482 interfaceSemantic(sc
);
484 for (i
= 0; i
< members
->dim
; i
++)
486 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
487 s
->addMember(sc
, this, 1);
490 /* If this is a nested class, add the hidden 'this'
491 * member which is a pointer to the enclosing scope.
493 if (vthis
) // if inheriting from nested class
494 { // Use the base class's 'this' member
496 if (storage_class
& STCstatic
)
497 error("static class cannot inherit from nested class %s", baseClass
->toChars());
498 if (toParent2() != baseClass
->toParent2())
499 error("super class %s is nested within %s, not %s",
500 baseClass
->toChars(),
501 baseClass
->toParent2()->toChars(),
502 toParent2()->toChars());
504 else if (!(storage_class
& STCstatic
))
505 { Dsymbol
*s
= toParent2();
508 ClassDeclaration
*cd
= s
->isClassDeclaration();
509 FuncDeclaration
*fd
= s
->isFuncDeclaration();
518 { AggregateDeclaration
*ad
= fd
->isMember2();
523 t
= new TypePointer(Type::tvoid
);
524 t
= t
->semantic(0, sc
);
530 vthis
= new ThisDeclaration(t
);
531 members
->push(vthis
);
537 if (storage_class
& (STCauto
| STCscope
))
539 if (storage_class
& STCabstract
)
541 if (storage_class
& STCinvariant
)
542 type
= type
->invariantOf();
543 else if (storage_class
& STCconst
)
544 type
= type
->constOf();
547 sc
->stc
&= ~(STCfinal
| STCauto
| STCscope
| STCstatic
|
548 STCabstract
| STCdeprecated
| STCconst
| STCinvariant
| STCtls
);
549 sc
->stc
|= storage_class
& (STCconst
| STCinvariant
);
550 sc
->attributes
= NULL
;
555 sc
->linkage
= LINKwindows
;
556 sc
->protection
= PROTpublic
;
557 sc
->explicitProtection
= 0;
559 structalign
= sc
->structalign
;
561 { sc
->offset
= baseClass
->structsize
;
562 alignsize
= baseClass
->alignsize
;
564 // sc->offset += PTRSIZE; // room for uplevel context pointer
567 { sc
->offset
= PTRSIZE
* 2; // allow room for vptr[] and monitor
570 structsize
= sc
->offset
;
572 int members_dim
= members
->dim
;
574 for (i
= 0; i
< members_dim
; i
++)
576 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
581 { // semantic() failed because of forward references.
582 // Unwind what we did, and defer it for later
590 scope
= scx
? scx
: new Scope(*sc
);
592 scope
->module
->addDeferredSemantic(this);
594 //printf("\tsemantic('%s') failed due to forward references\n", toChars());
598 //printf("\tsemantic('%s') successful\n", toChars());
600 structsize
= sc
->offset
;
603 /* Look for special member functions.
604 * They must be in this class, not in a base class.
606 ctor
= (CtorDeclaration
*)search(0, Id::ctor
, 0);
607 if (ctor
&& ctor
->toParent() != this)
610 // dtor = (DtorDeclaration *)search(Id::dtor, 0);
611 // if (dtor && dtor->toParent() != this)
614 // inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
615 // if (inv && inv->toParent() != this)
618 // Can be in base class
619 aggNew
= (NewDeclaration
*)search(0, Id::classNew
, 0);
620 aggDelete
= (DeleteDeclaration
*)search(0, Id::classDelete
, 0);
622 // If this class has no constructor, but base class does, create
627 // Also do this if we have some "in" fields on the class, or
628 // if there are non-null fields
631 bool hasInArgs
= false;
632 bool hasNonNull
= false;
633 for (int i
= 0; i
< fields
.dim
; i
++)
635 VarDeclaration
*var
= (VarDeclaration
*) fields
.data
[i
];
642 if (var
->type
->ty
== Tclass
) {
647 if (hasInArgs
|| hasNonNull
|| (baseClass
&& baseClass
->ctor
))
649 //printf("Creating default this(){} for class %s\n", toChars());
650 ctor
= new CtorDeclaration(0, 0, NULL
, 0);
651 ctor
->fbody
= new CompoundStatement(0, new Statements());
653 ctor
->addMember(sc
, this, 1);
654 *sc
= scsave
; // why? What about sc->nofree?
655 sc
->offset
= structsize
;
664 aggDelete
= baseClass
->aggDelete
;
666 aggNew
= baseClass
->aggNew
;
670 // Allocate instance of each new interface
671 for (i
= 0; i
< vtblInterfaces
->dim
; i
++)
673 BaseClass
*b
= (BaseClass
*)vtblInterfaces
->data
[i
];
674 unsigned thissize
= PTRSIZE
;
676 alignmember(structalign
, thissize
, &sc
->offset
);
677 assert(b
->offset
== 0);
678 b
->offset
= sc
->offset
;
680 // Take care of single inheritance offsets
681 while (b
->baseInterfaces_dim
)
683 b
= &b
->baseInterfaces
[0];
684 b
->offset
= sc
->offset
;
687 sc
->offset
+= thissize
;
688 if (alignsize
< thissize
)
689 alignsize
= thissize
;
691 structsize
= sc
->offset
;
695 dtor
= buildDtor(sc
);
699 #if 0 // Do not call until toObjfile() because of forward references
700 // Fill in base class vtbl[]s
701 for (i
= 0; i
< vtblInterfaces
->dim
; i
++)
703 BaseClass
*b
= (BaseClass
*)vtblInterfaces
->data
[i
];
705 //b->fillVtbl(this, &b->vtbl, 1);
708 //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
711 void ClassDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
715 buf
->printf("%s ", kind());
716 buf
->writestring(toChars());
718 buf
->writestring(" : ");
720 for (int i
= 0; i
< baseclasses
.dim
; i
++)
722 BaseClass
*b
= (BaseClass
*)baseclasses
.data
[i
];
726 //buf->writestring(b->base->ident->toChars());
727 b
->type
->toCBuffer(buf
, NULL
, hgs
);
732 for (int i
= 0; i
< members
->dim
; i
++)
734 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
736 buf
->writestring(" ");
737 s
->toCBuffer(buf
, hgs
);
739 buf
->writestring("}");
744 void ClassDeclaration::defineRef(Dsymbol
*s
)
746 ClassDeclaration
*cd
;
748 AggregateDeclaration::defineRef(s
);
749 cd
= s
->isClassDeclaration();
750 baseType
= cd
->baseType
;
755 /*********************************************
756 * Determine if 'this' is a base class of cd.
757 * This is used to detect circular inheritance only.
760 int ClassDeclaration::isBaseOf2(ClassDeclaration
*cd
)
764 //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
765 for (int i
= 0; i
< cd
->baseclasses
.dim
; i
++)
766 { BaseClass
*b
= (BaseClass
*)cd
->baseclasses
.data
[i
];
768 if (b
->base
== this || isBaseOf2(b
->base
))
774 /*******************************************
775 * Determine if 'this' is a base class of cd.
778 int ClassDeclaration::isBaseOf(ClassDeclaration
*cd
, target_ptrdiff_t
*poffset
)
780 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
785 if (this == cd
->baseClass
)
788 /* cd->baseClass might not be set if cd is forward referenced.
790 if (!cd
->baseClass
&& cd
->baseclasses
.dim
&& !cd
->isInterfaceDeclaration())
792 cd
->error("base class is forward referenced by %s", toChars());
800 Dsymbol
*ClassDeclaration::search(Loc loc
, Identifier
*ident
, int flags
)
804 //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
808 if (!members
|| !symtab
|| scope
)
809 { error("is forward referenced when looking for '%s'", ident
->toChars());
814 s
= ScopeDsymbol::search(loc
, ident
, flags
);
817 // Search bases classes in depth-first, left to right order
821 for (i
= 0; i
< baseclasses
.dim
; i
++)
823 BaseClass
*b
= (BaseClass
*)baseclasses
.data
[i
];
827 if (!b
->base
->symtab
)
828 error("base %s is forward referenced", b
->base
->ident
->toChars());
831 s
= b
->base
->search(loc
, ident
, flags
);
832 if (s
== this) // happens if s is nested in this and derives from this
843 /**********************************************************
844 * fd is in the vtbl[] for this class.
845 * Return 1 if function is hidden (not findable through search).
849 int isf(void *param
, FuncDeclaration
*fd
)
851 //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
855 int ClassDeclaration::isFuncHidden(FuncDeclaration
*fd
)
857 //printf("ClassDeclaration::isFuncHidden(%s)\n", fd->toChars());
858 Dsymbol
*s
= search(0, fd
->ident
, 4|2);
860 { //printf("not found\n");
861 /* Because, due to a hack, if there are multiple definitions
862 * of fd->ident, NULL is returned.
867 OverloadSet
*os
= s
->isOverloadSet();
870 for (int i
= 0; i
< os
->a
.dim
; i
++)
871 { Dsymbol
*s
= (Dsymbol
*)os
->a
.data
[i
];
872 FuncDeclaration
*f2
= s
->isFuncDeclaration();
873 if (f2
&& overloadApply(f2
, &isf
, fd
))
880 FuncDeclaration
*fdstart
= s
->isFuncDeclaration();
881 //printf("%s fdstart = %p\n", s->kind(), fdstart);
882 return !overloadApply(fdstart
, &isf
, fd
);
888 * Find virtual function matching identifier and type.
889 * Used to build virtual function tables for interface implementations.
892 FuncDeclaration
*ClassDeclaration::findFunc(Identifier
*ident
, TypeFunction
*tf
)
894 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
896 ClassDeclaration
*cd
= this;
897 Array
*vtbl
= &cd
->vtbl
;
900 for (size_t i
= 0; i
< vtbl
->dim
; i
++)
902 FuncDeclaration
*fd
= (FuncDeclaration
*)vtbl
->data
[i
];
904 //printf("\t[%d] = %s\n", i, fd->toChars());
905 if (ident
== fd
->ident
&&
906 //tf->equals(fd->type)
907 fd
->type
->covariant(tf
) == 1
909 { //printf("\t\tfound\n");
912 //else printf("\t\t%d\n", fd->type->covariant(tf));
916 vtbl
= &cd
->vtblFinal
;
923 void ClassDeclaration::interfaceSemantic(Scope
*sc
)
925 InterfaceDeclaration
*id
= isInterfaceDeclaration();
927 vtblInterfaces
= new BaseClasses();
928 vtblInterfaces
->reserve(interfaces_dim
);
930 for (size_t i
= 0; i
< interfaces_dim
; i
++)
932 BaseClass
*b
= interfaces
[i
];
934 // If this is an interface, and it derives from a COM interface,
935 // then this is a COM interface too.
936 if (b
->base
->isCOMinterface())
939 if (b
->base
->isCPPinterface() && id
)
942 vtblInterfaces
->push(b
);
943 b
->copyBaseInterfaces(vtblInterfaces
);
947 /****************************************
950 int ClassDeclaration::isCOMclass()
955 int ClassDeclaration::isCOMinterface()
960 int ClassDeclaration::isCPPinterface()
966 /****************************************
969 int ClassDeclaration::isAbstract()
973 for (int i
= 1; i
< vtbl
.dim
; i
++)
975 FuncDeclaration
*fd
= ((Dsymbol
*)vtbl
.data
[i
])->isFuncDeclaration();
977 //printf("\tvtbl[%d] = %p\n", i, fd);
978 if (!fd
|| fd
->isAbstract())
988 /****************************************
989 * Returns !=0 if there's an extra member which is the 'this'
990 * pointer to the enclosing context (enclosing class or function)
993 int ClassDeclaration::isNested()
998 /****************************************
999 * Determine if slot 0 of the vtbl[] is reserved for something else.
1000 * For class objects, yes, this is where the classinfo ptr goes.
1001 * For COM interfaces, no.
1002 * For non-COM interfaces, yes, this is where the Interface ptr goes.
1005 int ClassDeclaration::vtblOffset()
1010 /****************************************
1013 char *ClassDeclaration::kind()
1018 /****************************************
1021 void ClassDeclaration::addLocalClass(ClassDeclarations
*aclasses
)
1023 aclasses
->push(this);
1026 /********************************* InterfaceDeclaration ****************************/
1028 InterfaceDeclaration::InterfaceDeclaration(Loc loc
, Identifier
*id
, BaseClasses
*baseclasses
)
1029 : ClassDeclaration(loc
, id
, baseclasses
)
1033 if (id
== Id::IUnknown
) // IUnknown is the root of all COM interfaces
1035 cpp
= 1; // IUnknown is also a C++ interface
1039 Dsymbol
*InterfaceDeclaration::syntaxCopy(Dsymbol
*s
)
1041 InterfaceDeclaration
*id
;
1044 id
= (InterfaceDeclaration
*)s
;
1046 id
= new InterfaceDeclaration(loc
, ident
, NULL
);
1048 ClassDeclaration::syntaxCopy(id
);
1052 void InterfaceDeclaration::semantic(Scope
*sc
)
1055 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1059 { type
= type
->semantic(loc
, sc
);
1060 handle
= handle
->semantic(loc
, sc
);
1062 if (!members
) // if forward reference
1063 { //printf("\tinterface '%s' is forward referenced\n", toChars());
1066 if (symtab
) // if already done
1071 symtab
= new DsymbolTable();
1076 scx
= scope
; // save so we don't make redundant copies
1081 attributes
->append(sc
->attributes
);
1083 attributes
= sc
->attributes
;
1085 if (sc
->stc
& STCdeprecated
)
1090 // Expand any tuples in baseclasses[]
1091 for (i
= 0; i
< baseclasses
.dim
; )
1092 { BaseClass
*b
= (BaseClass
*)baseclasses
.data
[0];
1093 b
->type
= b
->type
->semantic(loc
, sc
);
1094 Type
*tb
= b
->type
->toBasetype();
1096 if (tb
->ty
== Ttuple
)
1097 { TypeTuple
*tup
= (TypeTuple
*)tb
;
1098 enum PROT protection
= b
->protection
;
1099 baseclasses
.remove(i
);
1100 size_t dim
= Argument::dim(tup
->arguments
);
1101 for (size_t j
= 0; j
< dim
; j
++)
1102 { Argument
*arg
= Argument::getNth(tup
->arguments
, j
);
1103 b
= new BaseClass(arg
->type
, protection
);
1104 baseclasses
.insert(i
+ j
, b
);
1111 if (!baseclasses
.dim
&& sc
->linkage
== LINKcpp
)
1114 // Check for errors, handle forward references
1115 for (i
= 0; i
< baseclasses
.dim
; )
1120 b
= (BaseClass
*)baseclasses
.data
[i
];
1121 b
->type
= b
->type
->semantic(loc
, sc
);
1122 tb
= b
->type
->toBasetype();
1123 if (tb
->ty
== Tclass
)
1124 tc
= (TypeClass
*)tb
;
1127 if (!tc
|| !tc
->sym
->isInterfaceDeclaration())
1129 error("base type must be interface, not %s", b
->type
->toChars());
1130 baseclasses
.remove(i
);
1135 // Check for duplicate interfaces
1136 for (size_t j
= 0; j
< i
; j
++)
1138 BaseClass
*b2
= (BaseClass
*)baseclasses
.data
[j
];
1139 if (b2
->base
== tc
->sym
)
1140 error("inherits from duplicate interface %s", b2
->base
->toChars());
1144 if (b
->base
== this || isBaseOf2(b
->base
))
1146 error("circular inheritance of interface");
1147 baseclasses
.remove(i
);
1150 if (!b
->base
->symtab
|| b
->base
->scope
|| b
->base
->inuse
)
1152 //error("forward reference of base class %s", baseClass->toChars());
1153 // Forward reference of base, try again later
1154 //printf("\ttry later, forward reference of base %s\n", b->base->toChars());
1155 scope
= scx
? scx
: new Scope(*sc
);
1157 scope
->module
->addDeferredSemantic(this);
1162 // Inherit const/invariant from base class
1163 storage_class
|= b
->base
->storage_class
& (STCconst
| STCinvariant
);
1168 interfaces_dim
= baseclasses
.dim
;
1169 interfaces
= (BaseClass
**)baseclasses
.data
;
1171 interfaceSemantic(sc
);
1174 vtbl
.push(this); // leave room at vtbl[0] for classinfo
1176 // Cat together the vtbl[]'s from base interfaces
1177 for (i
= 0; i
< interfaces_dim
; i
++)
1178 { BaseClass
*b
= interfaces
[i
];
1180 // Skip if b has already appeared
1181 for (int k
= 0; k
< i
; k
++)
1183 if (b
== interfaces
[i
])
1187 // Copy vtbl[] from base class
1188 if (b
->base
->vtblOffset())
1189 { int d
= b
->base
->vtbl
.dim
;
1192 vtbl
.reserve(d
- 1);
1193 for (int j
= 1; j
< d
; j
++)
1194 vtbl
.push(b
->base
->vtbl
.data
[j
]);
1199 vtbl
.append(&b
->base
->vtbl
);
1206 protection
= sc
->protection
;
1207 storage_class
|= sc
->stc
& (STCconst
| STCinvariant
);
1209 for (i
= 0; i
< members
->dim
; i
++)
1211 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
1212 s
->addMember(sc
, this, 1);
1215 sc
= sc
->push(this);
1216 sc
->stc
&= ~(STCfinal
| STCauto
| STCscope
| STCstatic
|
1217 STCabstract
| STCdeprecated
| STCconst
| STCinvariant
| STCtls
);
1218 sc
->stc
|= storage_class
& (STCconst
| STCinvariant
);
1219 sc
->attributes
= NULL
;
1221 if (isCOMinterface())
1222 sc
->linkage
= LINKwindows
;
1223 else if (isCPPinterface())
1224 sc
->linkage
= LINKcpp
;
1225 sc
->structalign
= 8;
1226 structalign
= sc
->structalign
;
1227 sc
->offset
= PTRSIZE
* 2;
1229 for (i
= 0; i
< members
->dim
; i
++)
1231 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
1237 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1241 /*******************************************
1242 * Determine if 'this' is a base class of cd.
1243 * (Actually, if it is an interface supported by cd)
1245 * *poffset offset to start of class
1246 * OFFSET_RUNTIME must determine offset at runtime
1252 int InterfaceDeclaration::isBaseOf(ClassDeclaration
*cd
, target_ptrdiff_t
*poffset
)
1256 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
1258 for (j
= 0; j
< cd
->interfaces_dim
; j
++)
1260 BaseClass
*b
= cd
->interfaces
[j
];
1262 //printf("\tbase %s\n", b->base->toChars());
1263 if (this == b
->base
)
1265 //printf("\tfound at offset %d\n", b->offset);
1267 { *poffset
= b
->offset
;
1268 if (j
&& cd
->isInterfaceDeclaration())
1269 *poffset
= OFFSET_RUNTIME
;
1273 if (isBaseOf(b
, poffset
))
1274 { if (j
&& poffset
&& cd
->isInterfaceDeclaration())
1275 *poffset
= OFFSET_RUNTIME
;
1280 if (cd
->baseClass
&& isBaseOf(cd
->baseClass
, poffset
))
1289 int InterfaceDeclaration::isBaseOf(BaseClass
*bc
, target_ptrdiff_t
*poffset
)
1291 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars());
1292 for (unsigned j
= 0; j
< bc
->baseInterfaces_dim
; j
++)
1294 BaseClass
*b
= &bc
->baseInterfaces
[j
];
1296 if (this == b
->base
)
1299 { *poffset
= b
->offset
;
1303 if (isBaseOf(b
, poffset
))
1313 /****************************************
1314 * Determine if slot 0 of the vtbl[] is reserved for something else.
1315 * For class objects, yes, this is where the ClassInfo ptr goes.
1316 * For COM interfaces, no.
1317 * For non-COM interfaces, yes, this is where the Interface ptr goes.
1320 int InterfaceDeclaration::vtblOffset()
1322 if (isCOMinterface() || isCPPinterface())
1327 int InterfaceDeclaration::isCOMinterface()
1332 int InterfaceDeclaration::isCPPinterface()
1337 /*******************************************
1340 char *InterfaceDeclaration::kind()
1346 /******************************** BaseClass *****************************/
1348 BaseClass::BaseClass()
1350 memset(this, 0, sizeof(BaseClass
));
1353 BaseClass::BaseClass(Type
*type
, enum PROT protection
)
1355 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
1357 this->protection
= protection
;
1361 baseInterfaces_dim
= 0;
1362 baseInterfaces
= NULL
;
1365 /****************************************
1366 * Fill in vtbl[] for base class based on member functions of class cd.
1368 * vtbl if !=NULL, fill it in
1369 * newinstance !=0 means all entries must be filled in by members
1370 * of cd, not members of any base classes of cd.
1372 * !=0 if any entries were filled in by members of cd (not exclusively
1376 int BaseClass::fillVtbl(ClassDeclaration
*cd
, Array
*vtbl
, int newinstance
)
1378 ClassDeclaration
*id
= base
;
1382 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars());
1384 vtbl
->setDim(base
->vtbl
.dim
);
1386 // first entry is ClassInfo reference
1387 for (j
= base
->vtblOffset(); j
< base
->vtbl
.dim
; j
++)
1389 FuncDeclaration
*ifd
= ((Dsymbol
*)base
->vtbl
.data
[j
])->isFuncDeclaration();
1390 FuncDeclaration
*fd
;
1393 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
1396 // Find corresponding function in this class
1397 tf
= (ifd
->type
->ty
== Tfunction
) ? (TypeFunction
*)(ifd
->type
) : NULL
;
1398 fd
= cd
->findFunc(ifd
->ident
, tf
);
1399 if (fd
&& !fd
->isAbstract())
1401 //printf(" found\n");
1402 // Check that calling conventions match
1403 if (fd
->linkage
!= ifd
->linkage
)
1404 fd
->error("linkage doesn't match interface function");
1406 // Check that it is current
1408 fd
->toParent() != cd
&&
1409 ifd
->toParent() == base
)
1410 cd
->error("interface function %s.%s is not implemented",
1411 id
->toChars(), ifd
->ident
->toChars());
1413 if (fd
->toParent() == cd
)
1418 //printf(" not found\n");
1419 // BUG: should mark this class as abstract?
1420 if (!cd
->isAbstract())
1421 cd
->error("interface function %s.%s isn't implemented",
1422 id
->toChars(), ifd
->ident
->toChars());
1432 void BaseClass::copyBaseInterfaces(BaseClasses
*vtblInterfaces
)
1434 //printf("+copyBaseInterfaces(), %s\n", base->toChars());
1435 // if (baseInterfaces_dim)
1438 baseInterfaces_dim
= base
->interfaces_dim
;
1439 baseInterfaces
= (BaseClass
*)mem
.calloc(baseInterfaces_dim
, sizeof(BaseClass
));
1441 //printf("%s.copyBaseInterfaces()\n", base->toChars());
1442 for (int i
= 0; i
< baseInterfaces_dim
; i
++)
1444 BaseClass
*b
= &baseInterfaces
[i
];
1445 BaseClass
*b2
= base
->interfaces
[i
];
1447 assert(b2
->vtbl
.dim
== 0); // should not be filled yet
1448 memcpy(b
, b2
, sizeof(BaseClass
));
1450 if (i
) // single inheritance is i==0
1451 vtblInterfaces
->push(b
); // only need for M.I.
1452 b
->copyBaseInterfaces(vtblInterfaces
);
1454 //printf("-copyBaseInterfaces\n");