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_Array
)
115 { if (Type::typeinfoarray
)
116 Type::typeinfoarray
->error("%s", msg
);
117 Type::typeinfoarray
= this;
120 if (id
== Id::TypeInfo_StaticArray
)
121 { //if (Type::typeinfostaticarray)
122 //Type::typeinfostaticarray->error("%s", msg);
123 Type::typeinfostaticarray
= this;
126 if (id
== Id::TypeInfo_AssociativeArray
)
127 { if (Type::typeinfoassociativearray
)
128 Type::typeinfoassociativearray
->error("%s", msg
);
129 Type::typeinfoassociativearray
= this;
132 if (id
== Id::TypeInfo_Enum
)
133 { if (Type::typeinfoenum
)
134 Type::typeinfoenum
->error("%s", msg
);
135 Type::typeinfoenum
= this;
138 if (id
== Id::TypeInfo_Function
)
139 { if (Type::typeinfofunction
)
140 Type::typeinfofunction
->error("%s", msg
);
141 Type::typeinfofunction
= this;
144 if (id
== Id::TypeInfo_Delegate
)
145 { if (Type::typeinfodelegate
)
146 Type::typeinfodelegate
->error("%s", msg
);
147 Type::typeinfodelegate
= this;
150 if (id
== Id::TypeInfo_Tuple
)
151 { if (Type::typeinfotypelist
)
152 Type::typeinfotypelist
->error("%s", msg
);
153 Type::typeinfotypelist
= this;
157 if (id
== Id::TypeInfo_Const
)
158 { if (Type::typeinfoconst
)
159 Type::typeinfoconst
->error("%s", msg
);
160 Type::typeinfoconst
= this;
163 if (id
== Id::TypeInfo_Invariant
)
164 { if (Type::typeinfoinvariant
)
165 Type::typeinfoinvariant
->error("%s", msg
);
166 Type::typeinfoinvariant
= this;
171 if (id
== Id::Object
)
173 object
->error("%s", msg
);
177 if (id
== Id::ClassInfo
)
179 classinfo
->error("%s", msg
);
183 if (id
== Id::ModuleInfo
)
184 { if (Module::moduleinfo
)
185 Module::moduleinfo
->error("%s", msg
);
186 Module::moduleinfo
= this;
198 Dsymbol
*ClassDeclaration::syntaxCopy(Dsymbol
*s
)
200 ClassDeclaration
*cd
;
202 //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
204 cd
= (ClassDeclaration
*)s
;
206 cd
= new ClassDeclaration(loc
, ident
, NULL
);
208 cd
->storage_class
|= storage_class
;
210 cd
->baseclasses
.setDim(this->baseclasses
.dim
);
211 for (int i
= 0; i
< cd
->baseclasses
.dim
; i
++)
213 BaseClass
*b
= (BaseClass
*)this->baseclasses
.data
[i
];
214 BaseClass
*b2
= new BaseClass(b
->type
->syntaxCopy(), b
->protection
);
215 cd
->baseclasses
.data
[i
] = b2
;
218 ScopeDsymbol::syntaxCopy(cd
);
222 void ClassDeclaration::semantic(Scope
*sc
)
225 //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
226 //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
227 //printf("sc->stc = %x\n", sc->stc);
229 //{ static int n; if (++n == 20) *(char*)0=0; }
231 if (!ident
) // if anonymous class
232 { char *id
= "__anonclass";
234 ident
= Identifier::generateId(id
);
239 if (!parent
&& sc
->parent
&& !sc
->parent
->isModule())
242 type
= type
->semantic(loc
, sc
);
243 handle
= handle
->semantic(loc
, sc
);
245 if (!members
) // if forward reference
246 { //printf("\tclass '%s' is forward referenced\n", toChars());
251 { //printf("\tsemantic for '%s' is already completed\n", toChars());
252 return; // semantic() already completed
256 symtab
= new DsymbolTable();
261 scx
= scope
; // save so we don't make redundant copies
265 attributes
->append(sc
->attributes
);
267 attributes
= sc
->attributes
;
272 if (sc
->stc
& STCdeprecated
)
277 if (sc
->linkage
== LINKcpp
)
278 error("cannot create C++ classes");
280 // Expand any tuples in baseclasses[]
281 for (i
= 0; i
< baseclasses
.dim
; )
282 { BaseClass
*b
= (BaseClass
*)baseclasses
.data
[i
];
283 b
->type
= b
->type
->semantic(loc
, sc
);
284 Type
*tb
= b
->type
->toBasetype();
286 if (tb
->ty
== Ttuple
)
287 { TypeTuple
*tup
= (TypeTuple
*)tb
;
288 enum PROT protection
= b
->protection
;
289 baseclasses
.remove(i
);
290 size_t dim
= Argument::dim(tup
->arguments
);
291 for (size_t j
= 0; j
< dim
; j
++)
292 { Argument
*arg
= Argument::getNth(tup
->arguments
, j
);
293 b
= new BaseClass(arg
->type
, protection
);
294 baseclasses
.insert(i
+ j
, b
);
301 // See if there's a base class as first in baseclasses[]
307 b
= (BaseClass
*)baseclasses
.data
[0];
308 //b->type = b->type->semantic(loc, sc);
309 tb
= b
->type
->toBasetype();
310 if (tb
->ty
!= Tclass
)
311 { error("base type must be class or interface, not %s", b
->type
->toChars());
312 baseclasses
.remove(0);
316 tc
= (TypeClass
*)(tb
);
318 if (tc
->sym
->isDeprecated())
322 // Deriving from deprecated class makes this one deprecated too
325 tc
->checkDeprecated(loc
, sc
);
329 if (tc
->sym
->isInterfaceDeclaration())
333 for (ClassDeclaration
*cdb
= tc
->sym
; cdb
; cdb
= cdb
->baseClass
)
337 error("circular inheritance");
338 baseclasses
.remove(0);
342 if (!tc
->sym
->symtab
|| tc
->sym
->scope
|| tc
->sym
->sizeok
== 0)
344 //error("forward reference of base class %s", baseClass->toChars());
345 // Forward reference of base class, try again later
346 //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
347 scope
= scx
? scx
: new Scope(*sc
);
349 scope
->module
->addDeferredSemantic(this);
353 { baseClass
= tc
->sym
;
361 // Treat the remaining entries in baseclasses as interfaces
362 // Check for errors, handle forward references
363 for (i
= (baseClass
? 1 : 0); i
< baseclasses
.dim
; )
368 b
= (BaseClass
*)baseclasses
.data
[i
];
369 b
->type
= b
->type
->semantic(loc
, sc
);
370 tb
= b
->type
->toBasetype();
371 if (tb
->ty
== Tclass
)
372 tc
= (TypeClass
*)tb
;
375 if (!tc
|| !tc
->sym
->isInterfaceDeclaration())
377 error("base type must be interface, not %s", b
->type
->toChars());
378 baseclasses
.remove(i
);
383 if (tc
->sym
->isDeprecated())
387 // Deriving from deprecated class makes this one deprecated too
390 tc
->checkDeprecated(loc
, sc
);
394 // Check for duplicate interfaces
395 for (size_t j
= (baseClass
? 1 : 0); j
< i
; j
++)
397 BaseClass
*b2
= (BaseClass
*)baseclasses
.data
[j
];
398 if (b2
->base
== tc
->sym
)
399 error("inherits from duplicate interface %s", b2
->base
->toChars());
403 if (!b
->base
->symtab
|| b
->base
->scope
)
405 //error("forward reference of base class %s", baseClass->toChars());
406 // Forward reference of base, try again later
407 //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
408 scope
= scx
? scx
: new Scope(*sc
);
410 scope
->module
->addDeferredSemantic(this);
418 // If no base class, and this is not an Object, use Object as base class
419 if (!baseClass
&& ident
!= Id::Object
)
421 // BUG: what if Object is redefined in an inner scope?
422 Type
*tbase
= new TypeIdentifier(0, Id::Object
);
429 error("missing or corrupt object.d");
432 bt
= tbase
->semantic(loc
, sc
)->toBasetype();
433 b
= new BaseClass(bt
, PROTpublic
);
434 baseclasses
.shift(b
);
435 assert(b
->type
->ty
== Tclass
);
436 tc
= (TypeClass
*)(b
->type
);
438 assert(!baseClass
->isInterfaceDeclaration());
442 interfaces_dim
= baseclasses
.dim
;
443 interfaces
= (BaseClass
**)baseclasses
.data
;
448 if (baseClass
->storage_class
& STCfinal
)
449 error("cannot inherit from final class %s", baseClass
->toChars());
454 // Copy vtbl[] from base class
455 vtbl
.setDim(baseClass
->vtbl
.dim
);
456 memcpy(vtbl
.data
, baseClass
->vtbl
.data
, sizeof(void *) * vtbl
.dim
);
458 // Inherit properties from base class
459 com
= baseClass
->isCOMclass();
460 isauto
= baseClass
->isauto
;
461 vthis
= baseClass
->vthis
;
462 storage_class
|= baseClass
->storage_class
& (STCconst
| STCinvariant
);
466 // No base class, so this is the root of the class hierarchy
468 vtbl
.push(this); // leave room for classinfo as first member
471 protection
= sc
->protection
;
472 storage_class
|= sc
->stc
;
476 interfaceSemantic(sc
);
478 for (i
= 0; i
< members
->dim
; i
++)
480 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
481 s
->addMember(sc
, this, 1);
484 /* If this is a nested class, add the hidden 'this'
485 * member which is a pointer to the enclosing scope.
487 if (vthis
) // if inheriting from nested class
488 { // Use the base class's 'this' member
490 if (storage_class
& STCstatic
)
491 error("static class cannot inherit from nested class %s", baseClass
->toChars());
492 if (toParent2() != baseClass
->toParent2())
493 error("super class %s is nested within %s, not %s",
494 baseClass
->toChars(),
495 baseClass
->toParent2()->toChars(),
496 toParent2()->toChars());
498 else if (!(storage_class
& STCstatic
))
499 { Dsymbol
*s
= toParent2();
502 ClassDeclaration
*cd
= s
->isClassDeclaration();
503 FuncDeclaration
*fd
= s
->isFuncDeclaration();
512 { AggregateDeclaration
*ad
= fd
->isMember2();
517 t
= new TypePointer(Type::tvoid
);
518 t
= t
->semantic(0, sc
);
524 vthis
= new ThisDeclaration(t
);
525 members
->push(vthis
);
531 if (storage_class
& (STCauto
| STCscope
))
533 if (storage_class
& STCabstract
)
535 if (storage_class
& STCinvariant
)
536 type
= type
->invariantOf();
537 else if (storage_class
& STCconst
)
538 type
= type
->constOf();
541 sc
->stc
&= ~(STCfinal
| STCauto
| STCscope
| STCstatic
|
542 STCabstract
| STCdeprecated
| STCconst
| STCinvariant
| STCtls
);
543 sc
->stc
|= storage_class
& (STCconst
| STCinvariant
);
544 sc
->attributes
= NULL
;
549 sc
->linkage
= LINKwindows
;
550 sc
->protection
= PROTpublic
;
551 sc
->explicitProtection
= 0;
553 structalign
= sc
->structalign
;
555 { sc
->offset
= baseClass
->structsize
;
556 alignsize
= baseClass
->alignsize
;
558 // sc->offset += PTRSIZE; // room for uplevel context pointer
561 { sc
->offset
= PTRSIZE
* 2; // allow room for vptr[] and monitor
564 structsize
= sc
->offset
;
566 int members_dim
= members
->dim
;
568 for (i
= 0; i
< members_dim
; i
++)
570 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
575 { // semantic() failed because of forward references.
576 // Unwind what we did, and defer it for later
584 scope
= scx
? scx
: new Scope(*sc
);
586 scope
->module
->addDeferredSemantic(this);
588 //printf("\tsemantic('%s') failed due to forward references\n", toChars());
592 //printf("\tsemantic('%s') successful\n", toChars());
594 structsize
= sc
->offset
;
597 /* Look for special member functions.
598 * They must be in this class, not in a base class.
600 ctor
= (CtorDeclaration
*)search(0, Id::ctor
, 0);
601 if (ctor
&& ctor
->toParent() != this)
604 // dtor = (DtorDeclaration *)search(Id::dtor, 0);
605 // if (dtor && dtor->toParent() != this)
608 // inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
609 // if (inv && inv->toParent() != this)
612 // Can be in base class
613 aggNew
= (NewDeclaration
*)search(0, Id::classNew
, 0);
614 aggDelete
= (DeleteDeclaration
*)search(0, Id::classDelete
, 0);
616 // If this class has no constructor, but base class does, create
619 if (!ctor
&& baseClass
&& baseClass
->ctor
)
621 //printf("Creating default this(){} for class %s\n", toChars());
622 ctor
= new CtorDeclaration(0, 0, NULL
, 0);
623 ctor
->fbody
= new CompoundStatement(0, new Statements());
625 ctor
->addMember(sc
, this, 1);
626 *sc
= scsave
; // why? What about sc->nofree?
627 sc
->offset
= structsize
;
635 aggDelete
= baseClass
->aggDelete
;
637 aggNew
= baseClass
->aggNew
;
641 // Allocate instance of each new interface
642 for (i
= 0; i
< vtblInterfaces
->dim
; i
++)
644 BaseClass
*b
= (BaseClass
*)vtblInterfaces
->data
[i
];
645 unsigned thissize
= PTRSIZE
;
647 alignmember(structalign
, thissize
, &sc
->offset
);
648 assert(b
->offset
== 0);
649 b
->offset
= sc
->offset
;
651 // Take care of single inheritance offsets
652 while (b
->baseInterfaces_dim
)
654 b
= &b
->baseInterfaces
[0];
655 b
->offset
= sc
->offset
;
658 sc
->offset
+= thissize
;
659 if (alignsize
< thissize
)
660 alignsize
= thissize
;
662 structsize
= sc
->offset
;
666 dtor
= buildDtor(sc
);
670 #if 0 // Do not call until toObjfile() because of forward references
671 // Fill in base class vtbl[]s
672 for (i
= 0; i
< vtblInterfaces
->dim
; i
++)
674 BaseClass
*b
= (BaseClass
*)vtblInterfaces
->data
[i
];
676 //b->fillVtbl(this, &b->vtbl, 1);
679 //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
682 void ClassDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
686 buf
->printf("%s ", kind());
687 buf
->writestring(toChars());
689 buf
->writestring(" : ");
691 for (int i
= 0; i
< baseclasses
.dim
; i
++)
693 BaseClass
*b
= (BaseClass
*)baseclasses
.data
[i
];
697 //buf->writestring(b->base->ident->toChars());
698 b
->type
->toCBuffer(buf
, NULL
, hgs
);
703 for (int i
= 0; i
< members
->dim
; i
++)
705 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
707 buf
->writestring(" ");
708 s
->toCBuffer(buf
, hgs
);
710 buf
->writestring("}");
715 void ClassDeclaration::defineRef(Dsymbol
*s
)
717 ClassDeclaration
*cd
;
719 AggregateDeclaration::defineRef(s
);
720 cd
= s
->isClassDeclaration();
721 baseType
= cd
->baseType
;
726 /*********************************************
727 * Determine if 'this' is a base class of cd.
728 * This is used to detect circular inheritance only.
731 int ClassDeclaration::isBaseOf2(ClassDeclaration
*cd
)
735 //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
736 for (int i
= 0; i
< cd
->baseclasses
.dim
; i
++)
737 { BaseClass
*b
= (BaseClass
*)cd
->baseclasses
.data
[i
];
739 if (b
->base
== this || isBaseOf2(b
->base
))
745 /*******************************************
746 * Determine if 'this' is a base class of cd.
749 int ClassDeclaration::isBaseOf(ClassDeclaration
*cd
, target_ptrdiff_t
*poffset
)
751 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
756 if (this == cd
->baseClass
)
759 /* cd->baseClass might not be set if cd is forward referenced.
761 if (!cd
->baseClass
&& cd
->baseclasses
.dim
&& !cd
->isInterfaceDeclaration())
763 cd
->error("base class is forward referenced by %s", toChars());
771 Dsymbol
*ClassDeclaration::search(Loc loc
, Identifier
*ident
, int flags
)
775 //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
779 if (!members
|| !symtab
|| scope
)
780 { error("is forward referenced when looking for '%s'", ident
->toChars());
785 s
= ScopeDsymbol::search(loc
, ident
, flags
);
788 // Search bases classes in depth-first, left to right order
792 for (i
= 0; i
< baseclasses
.dim
; i
++)
794 BaseClass
*b
= (BaseClass
*)baseclasses
.data
[i
];
798 if (!b
->base
->symtab
)
799 error("base %s is forward referenced", b
->base
->ident
->toChars());
802 s
= b
->base
->search(loc
, ident
, flags
);
803 if (s
== this) // happens if s is nested in this and derives from this
814 /**********************************************************
815 * fd is in the vtbl[] for this class.
816 * Return 1 if function is hidden (not findable through search).
820 int isf(void *param
, FuncDeclaration
*fd
)
822 //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
826 int ClassDeclaration::isFuncHidden(FuncDeclaration
*fd
)
828 //printf("ClassDeclaration::isFuncHidden(%s)\n", fd->toChars());
829 Dsymbol
*s
= search(0, fd
->ident
, 4|2);
831 { //printf("not found\n");
832 /* Because, due to a hack, if there are multiple definitions
833 * of fd->ident, NULL is returned.
838 OverloadSet
*os
= s
->isOverloadSet();
841 for (int i
= 0; i
< os
->a
.dim
; i
++)
842 { Dsymbol
*s
= (Dsymbol
*)os
->a
.data
[i
];
843 FuncDeclaration
*f2
= s
->isFuncDeclaration();
844 if (f2
&& overloadApply(f2
, &isf
, fd
))
851 FuncDeclaration
*fdstart
= s
->isFuncDeclaration();
852 //printf("%s fdstart = %p\n", s->kind(), fdstart);
853 return !overloadApply(fdstart
, &isf
, fd
);
859 * Find virtual function matching identifier and type.
860 * Used to build virtual function tables for interface implementations.
863 FuncDeclaration
*ClassDeclaration::findFunc(Identifier
*ident
, TypeFunction
*tf
)
865 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
867 ClassDeclaration
*cd
= this;
868 Array
*vtbl
= &cd
->vtbl
;
871 for (size_t i
= 0; i
< vtbl
->dim
; i
++)
873 FuncDeclaration
*fd
= (FuncDeclaration
*)vtbl
->data
[i
];
875 //printf("\t[%d] = %s\n", i, fd->toChars());
876 if (ident
== fd
->ident
&&
877 //tf->equals(fd->type)
878 fd
->type
->covariant(tf
) == 1
880 { //printf("\t\tfound\n");
883 //else printf("\t\t%d\n", fd->type->covariant(tf));
887 vtbl
= &cd
->vtblFinal
;
894 void ClassDeclaration::interfaceSemantic(Scope
*sc
)
896 InterfaceDeclaration
*id
= isInterfaceDeclaration();
898 vtblInterfaces
= new BaseClasses();
899 vtblInterfaces
->reserve(interfaces_dim
);
901 for (size_t i
= 0; i
< interfaces_dim
; i
++)
903 BaseClass
*b
= interfaces
[i
];
905 // If this is an interface, and it derives from a COM interface,
906 // then this is a COM interface too.
907 if (b
->base
->isCOMinterface())
910 if (b
->base
->isCPPinterface() && id
)
913 vtblInterfaces
->push(b
);
914 b
->copyBaseInterfaces(vtblInterfaces
);
918 /****************************************
921 int ClassDeclaration::isCOMclass()
926 int ClassDeclaration::isCOMinterface()
931 int ClassDeclaration::isCPPinterface()
937 /****************************************
940 int ClassDeclaration::isAbstract()
944 for (int i
= 1; i
< vtbl
.dim
; i
++)
946 FuncDeclaration
*fd
= ((Dsymbol
*)vtbl
.data
[i
])->isFuncDeclaration();
948 //printf("\tvtbl[%d] = %p\n", i, fd);
949 if (!fd
|| fd
->isAbstract())
959 /****************************************
960 * Returns !=0 if there's an extra member which is the 'this'
961 * pointer to the enclosing context (enclosing class or function)
964 int ClassDeclaration::isNested()
969 /****************************************
970 * Determine if slot 0 of the vtbl[] is reserved for something else.
971 * For class objects, yes, this is where the classinfo ptr goes.
972 * For COM interfaces, no.
973 * For non-COM interfaces, yes, this is where the Interface ptr goes.
976 int ClassDeclaration::vtblOffset()
981 /****************************************
984 char *ClassDeclaration::kind()
989 /****************************************
992 void ClassDeclaration::addLocalClass(ClassDeclarations
*aclasses
)
994 aclasses
->push(this);
997 /********************************* InterfaceDeclaration ****************************/
999 InterfaceDeclaration::InterfaceDeclaration(Loc loc
, Identifier
*id
, BaseClasses
*baseclasses
)
1000 : ClassDeclaration(loc
, id
, baseclasses
)
1004 if (id
== Id::IUnknown
) // IUnknown is the root of all COM interfaces
1006 cpp
= 1; // IUnknown is also a C++ interface
1010 Dsymbol
*InterfaceDeclaration::syntaxCopy(Dsymbol
*s
)
1012 InterfaceDeclaration
*id
;
1015 id
= (InterfaceDeclaration
*)s
;
1017 id
= new InterfaceDeclaration(loc
, ident
, NULL
);
1019 ClassDeclaration::syntaxCopy(id
);
1023 void InterfaceDeclaration::semantic(Scope
*sc
)
1026 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1030 { type
= type
->semantic(loc
, sc
);
1031 handle
= handle
->semantic(loc
, sc
);
1033 if (!members
) // if forward reference
1034 { //printf("\tinterface '%s' is forward referenced\n", toChars());
1037 if (symtab
) // if already done
1042 symtab
= new DsymbolTable();
1047 scx
= scope
; // save so we don't make redundant copies
1052 attributes
->append(sc
->attributes
);
1054 attributes
= sc
->attributes
;
1056 if (sc
->stc
& STCdeprecated
)
1061 // Expand any tuples in baseclasses[]
1062 for (i
= 0; i
< baseclasses
.dim
; )
1063 { BaseClass
*b
= (BaseClass
*)baseclasses
.data
[0];
1064 b
->type
= b
->type
->semantic(loc
, sc
);
1065 Type
*tb
= b
->type
->toBasetype();
1067 if (tb
->ty
== Ttuple
)
1068 { TypeTuple
*tup
= (TypeTuple
*)tb
;
1069 enum PROT protection
= b
->protection
;
1070 baseclasses
.remove(i
);
1071 size_t dim
= Argument::dim(tup
->arguments
);
1072 for (size_t j
= 0; j
< dim
; j
++)
1073 { Argument
*arg
= Argument::getNth(tup
->arguments
, j
);
1074 b
= new BaseClass(arg
->type
, protection
);
1075 baseclasses
.insert(i
+ j
, b
);
1082 if (!baseclasses
.dim
&& sc
->linkage
== LINKcpp
)
1085 // Check for errors, handle forward references
1086 for (i
= 0; i
< baseclasses
.dim
; )
1091 b
= (BaseClass
*)baseclasses
.data
[i
];
1092 b
->type
= b
->type
->semantic(loc
, sc
);
1093 tb
= b
->type
->toBasetype();
1094 if (tb
->ty
== Tclass
)
1095 tc
= (TypeClass
*)tb
;
1098 if (!tc
|| !tc
->sym
->isInterfaceDeclaration())
1100 error("base type must be interface, not %s", b
->type
->toChars());
1101 baseclasses
.remove(i
);
1106 // Check for duplicate interfaces
1107 for (size_t j
= 0; j
< i
; j
++)
1109 BaseClass
*b2
= (BaseClass
*)baseclasses
.data
[j
];
1110 if (b2
->base
== tc
->sym
)
1111 error("inherits from duplicate interface %s", b2
->base
->toChars());
1115 if (b
->base
== this || isBaseOf2(b
->base
))
1117 error("circular inheritance of interface");
1118 baseclasses
.remove(i
);
1121 if (!b
->base
->symtab
|| b
->base
->scope
|| b
->base
->inuse
)
1123 //error("forward reference of base class %s", baseClass->toChars());
1124 // Forward reference of base, try again later
1125 //printf("\ttry later, forward reference of base %s\n", b->base->toChars());
1126 scope
= scx
? scx
: new Scope(*sc
);
1128 scope
->module
->addDeferredSemantic(this);
1133 // Inherit const/invariant from base class
1134 storage_class
|= b
->base
->storage_class
& (STCconst
| STCinvariant
);
1139 interfaces_dim
= baseclasses
.dim
;
1140 interfaces
= (BaseClass
**)baseclasses
.data
;
1142 interfaceSemantic(sc
);
1145 vtbl
.push(this); // leave room at vtbl[0] for classinfo
1147 // Cat together the vtbl[]'s from base interfaces
1148 for (i
= 0; i
< interfaces_dim
; i
++)
1149 { BaseClass
*b
= interfaces
[i
];
1151 // Skip if b has already appeared
1152 for (int k
= 0; k
< i
; k
++)
1154 if (b
== interfaces
[i
])
1158 // Copy vtbl[] from base class
1159 if (b
->base
->vtblOffset())
1160 { int d
= b
->base
->vtbl
.dim
;
1163 vtbl
.reserve(d
- 1);
1164 for (int j
= 1; j
< d
; j
++)
1165 vtbl
.push(b
->base
->vtbl
.data
[j
]);
1170 vtbl
.append(&b
->base
->vtbl
);
1177 protection
= sc
->protection
;
1178 storage_class
|= sc
->stc
& (STCconst
| STCinvariant
);
1180 for (i
= 0; i
< members
->dim
; i
++)
1182 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
1183 s
->addMember(sc
, this, 1);
1186 sc
= sc
->push(this);
1187 sc
->stc
&= ~(STCfinal
| STCauto
| STCscope
| STCstatic
|
1188 STCabstract
| STCdeprecated
| STCconst
| STCinvariant
| STCtls
);
1189 sc
->stc
|= storage_class
& (STCconst
| STCinvariant
);
1190 sc
->attributes
= NULL
;
1192 if (isCOMinterface())
1193 sc
->linkage
= LINKwindows
;
1194 else if (isCPPinterface())
1195 sc
->linkage
= LINKcpp
;
1196 sc
->structalign
= 8;
1197 structalign
= sc
->structalign
;
1198 sc
->offset
= PTRSIZE
* 2;
1200 for (i
= 0; i
< members
->dim
; i
++)
1202 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
1208 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1212 /*******************************************
1213 * Determine if 'this' is a base class of cd.
1214 * (Actually, if it is an interface supported by cd)
1216 * *poffset offset to start of class
1217 * OFFSET_RUNTIME must determine offset at runtime
1223 int InterfaceDeclaration::isBaseOf(ClassDeclaration
*cd
, target_ptrdiff_t
*poffset
)
1227 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
1229 for (j
= 0; j
< cd
->interfaces_dim
; j
++)
1231 BaseClass
*b
= cd
->interfaces
[j
];
1233 //printf("\tbase %s\n", b->base->toChars());
1234 if (this == b
->base
)
1236 //printf("\tfound at offset %d\n", b->offset);
1238 { *poffset
= b
->offset
;
1239 if (j
&& cd
->isInterfaceDeclaration())
1240 *poffset
= OFFSET_RUNTIME
;
1244 if (isBaseOf(b
, poffset
))
1245 { if (j
&& poffset
&& cd
->isInterfaceDeclaration())
1246 *poffset
= OFFSET_RUNTIME
;
1251 if (cd
->baseClass
&& isBaseOf(cd
->baseClass
, poffset
))
1260 int InterfaceDeclaration::isBaseOf(BaseClass
*bc
, target_ptrdiff_t
*poffset
)
1262 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars());
1263 for (unsigned j
= 0; j
< bc
->baseInterfaces_dim
; j
++)
1265 BaseClass
*b
= &bc
->baseInterfaces
[j
];
1267 if (this == b
->base
)
1270 { *poffset
= b
->offset
;
1274 if (isBaseOf(b
, poffset
))
1284 /****************************************
1285 * Determine if slot 0 of the vtbl[] is reserved for something else.
1286 * For class objects, yes, this is where the ClassInfo ptr goes.
1287 * For COM interfaces, no.
1288 * For non-COM interfaces, yes, this is where the Interface ptr goes.
1291 int InterfaceDeclaration::vtblOffset()
1293 if (isCOMinterface() || isCPPinterface())
1298 int InterfaceDeclaration::isCOMinterface()
1303 int InterfaceDeclaration::isCPPinterface()
1308 /*******************************************
1311 char *InterfaceDeclaration::kind()
1317 /******************************** BaseClass *****************************/
1319 BaseClass::BaseClass()
1321 memset(this, 0, sizeof(BaseClass
));
1324 BaseClass::BaseClass(Type
*type
, enum PROT protection
)
1326 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
1328 this->protection
= protection
;
1332 baseInterfaces_dim
= 0;
1333 baseInterfaces
= NULL
;
1336 /****************************************
1337 * Fill in vtbl[] for base class based on member functions of class cd.
1339 * vtbl if !=NULL, fill it in
1340 * newinstance !=0 means all entries must be filled in by members
1341 * of cd, not members of any base classes of cd.
1343 * !=0 if any entries were filled in by members of cd (not exclusively
1347 int BaseClass::fillVtbl(ClassDeclaration
*cd
, Array
*vtbl
, int newinstance
)
1349 ClassDeclaration
*id
= base
;
1353 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars());
1355 vtbl
->setDim(base
->vtbl
.dim
);
1357 // first entry is ClassInfo reference
1358 for (j
= base
->vtblOffset(); j
< base
->vtbl
.dim
; j
++)
1360 FuncDeclaration
*ifd
= ((Dsymbol
*)base
->vtbl
.data
[j
])->isFuncDeclaration();
1361 FuncDeclaration
*fd
;
1364 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
1367 // Find corresponding function in this class
1368 tf
= (ifd
->type
->ty
== Tfunction
) ? (TypeFunction
*)(ifd
->type
) : NULL
;
1369 fd
= cd
->findFunc(ifd
->ident
, tf
);
1370 if (fd
&& !fd
->isAbstract())
1372 //printf(" found\n");
1373 // Check that calling conventions match
1374 if (fd
->linkage
!= ifd
->linkage
)
1375 fd
->error("linkage doesn't match interface function");
1377 // Check that it is current
1379 fd
->toParent() != cd
&&
1380 ifd
->toParent() == base
)
1381 cd
->error("interface function %s.%s is not implemented",
1382 id
->toChars(), ifd
->ident
->toChars());
1384 if (fd
->toParent() == cd
)
1389 //printf(" not found\n");
1390 // BUG: should mark this class as abstract?
1391 if (!cd
->isAbstract())
1392 cd
->error("interface function %s.%s isn't implemented",
1393 id
->toChars(), ifd
->ident
->toChars());
1403 void BaseClass::copyBaseInterfaces(BaseClasses
*vtblInterfaces
)
1405 //printf("+copyBaseInterfaces(), %s\n", base->toChars());
1406 // if (baseInterfaces_dim)
1409 baseInterfaces_dim
= base
->interfaces_dim
;
1410 baseInterfaces
= (BaseClass
*)mem
.calloc(baseInterfaces_dim
, sizeof(BaseClass
));
1412 //printf("%s.copyBaseInterfaces()\n", base->toChars());
1413 for (int i
= 0; i
< baseInterfaces_dim
; i
++)
1415 BaseClass
*b
= &baseInterfaces
[i
];
1416 BaseClass
*b2
= base
->interfaces
[i
];
1418 assert(b2
->vtbl
.dim
== 0); // should not be filled yet
1419 memcpy(b
, b2
, sizeof(BaseClass
));
1421 if (i
) // single inheritance is i==0
1422 vtblInterfaces
->push(b
); // only need for M.I.
1423 b
->copyBaseInterfaces(vtblInterfaces
);
1425 //printf("-copyBaseInterfaces\n");