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
, LINK l
)
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;
199 Dsymbol
*ClassDeclaration::syntaxCopy(Dsymbol
*s
)
201 ClassDeclaration
*cd
;
203 //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
205 cd
= (ClassDeclaration
*)s
;
207 cd
= new ClassDeclaration(loc
, ident
, NULL
, linkage
);
209 cd
->storage_class
|= storage_class
;
211 cd
->baseclasses
.setDim(this->baseclasses
.dim
);
212 for (int i
= 0; i
< cd
->baseclasses
.dim
; i
++)
214 BaseClass
*b
= (BaseClass
*)this->baseclasses
.data
[i
];
215 BaseClass
*b2
= new BaseClass(b
->type
->syntaxCopy(), b
->protection
);
216 cd
->baseclasses
.data
[i
] = b2
;
219 ScopeDsymbol::syntaxCopy(cd
);
223 void ClassDeclaration::semantic(Scope
*sc
)
226 //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
227 //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
228 //printf("sc->stc = %x\n", sc->stc);
230 //{ static int n; if (++n == 20) *(char*)0=0; }
232 if (!ident
) // if anonymous class
233 { char *id
= "__anonclass";
235 ident
= Identifier::generateId(id
);
240 if (!parent
&& sc
->parent
&& !sc
->parent
->isModule())
243 type
= type
->semantic(loc
, sc
);
244 handle
= handle
->semantic(loc
, sc
);
246 if (!members
) // if forward reference
247 { //printf("\tclass '%s' is forward referenced\n", toChars());
252 { //printf("\tsemantic for '%s' is already completed\n", toChars());
253 return; // semantic() already completed
257 symtab
= new DsymbolTable();
262 scx
= scope
; // save so we don't make redundant copies
266 attributes
->append(sc
->attributes
);
268 attributes
= sc
->attributes
;
273 if (sc
->stc
& STCdeprecated
)
278 if (sc
->linkage
== LINKcpp
)
279 error("cannot create C++ classes");
281 // Expand any tuples in baseclasses[]
282 for (i
= 0; i
< baseclasses
.dim
; )
283 { BaseClass
*b
= (BaseClass
*)baseclasses
.data
[i
];
284 b
->type
= b
->type
->semantic(loc
, sc
);
285 Type
*tb
= b
->type
->toBasetype();
287 if (tb
->ty
== Ttuple
)
288 { TypeTuple
*tup
= (TypeTuple
*)tb
;
289 enum PROT protection
= b
->protection
;
290 baseclasses
.remove(i
);
291 size_t dim
= Argument::dim(tup
->arguments
);
292 for (size_t j
= 0; j
< dim
; j
++)
293 { Argument
*arg
= Argument::getNth(tup
->arguments
, j
);
294 b
= new BaseClass(arg
->type
, protection
);
295 baseclasses
.insert(i
+ j
, b
);
302 // See if there's a base class as first in baseclasses[]
308 b
= (BaseClass
*)baseclasses
.data
[0];
309 //b->type = b->type->semantic(loc, sc);
310 tb
= b
->type
->toBasetype();
311 if (tb
->ty
!= Tclass
)
312 { error("base type must be class or interface, not %s", b
->type
->toChars());
313 baseclasses
.remove(0);
317 tc
= (TypeClass
*)(tb
);
319 if (tc
->sym
->isDeprecated())
323 // Deriving from deprecated class makes this one deprecated too
326 tc
->checkDeprecated(loc
, sc
);
330 if (tc
->sym
->isInterfaceDeclaration())
334 for (ClassDeclaration
*cdb
= tc
->sym
; cdb
; cdb
= cdb
->baseClass
)
338 error("circular inheritance");
339 baseclasses
.remove(0);
343 if (!tc
->sym
->symtab
|| tc
->sym
->scope
|| tc
->sym
->sizeok
== 0)
345 //error("forward reference of base class %s", baseClass->toChars());
346 // Forward reference of base class, try again later
347 //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
348 scope
= scx
? scx
: new Scope(*sc
);
350 scope
->module
->addDeferredSemantic(this);
354 { baseClass
= tc
->sym
;
362 // Treat the remaining entries in baseclasses as interfaces
363 // Check for errors, handle forward references
364 for (i
= (baseClass
? 1 : 0); i
< baseclasses
.dim
; )
369 b
= (BaseClass
*)baseclasses
.data
[i
];
370 b
->type
= b
->type
->semantic(loc
, sc
);
371 tb
= b
->type
->toBasetype();
372 if (tb
->ty
== Tclass
)
373 tc
= (TypeClass
*)tb
;
376 if (!tc
|| !tc
->sym
->isInterfaceDeclaration())
378 error("base type must be interface, not %s", b
->type
->toChars());
379 baseclasses
.remove(i
);
384 if (tc
->sym
->isDeprecated())
388 // Deriving from deprecated class makes this one deprecated too
391 tc
->checkDeprecated(loc
, sc
);
395 // Check for duplicate interfaces
396 for (size_t j
= (baseClass
? 1 : 0); j
< i
; j
++)
398 BaseClass
*b2
= (BaseClass
*)baseclasses
.data
[j
];
399 if (b2
->base
== tc
->sym
)
400 error("inherits from duplicate interface %s", b2
->base
->toChars());
404 if (!b
->base
->symtab
|| b
->base
->scope
)
406 //error("forward reference of base class %s", baseClass->toChars());
407 // Forward reference of base, try again later
408 //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
409 scope
= scx
? scx
: new Scope(*sc
);
411 scope
->module
->addDeferredSemantic(this);
419 // If no base class, and this is not an Object, use Object as base class
420 if (!baseClass
&& ident
!= Id::Object
)
422 // BUG: what if Object is redefined in an inner scope?
423 Type
*tbase
= new TypeIdentifier(0, Id::Object
);
430 error("missing or corrupt object.d");
433 bt
= tbase
->semantic(loc
, sc
)->toBasetype();
434 b
= new BaseClass(bt
, PROTpublic
);
435 baseclasses
.shift(b
);
436 assert(b
->type
->ty
== Tclass
);
437 tc
= (TypeClass
*)(b
->type
);
439 assert(!baseClass
->isInterfaceDeclaration());
443 interfaces_dim
= baseclasses
.dim
;
444 interfaces
= (BaseClass
**)baseclasses
.data
;
449 if (baseClass
->storage_class
& STCfinal
)
450 error("cannot inherit from final class %s", baseClass
->toChars());
455 // Copy vtbl[] from base class
456 vtbl
.setDim(baseClass
->vtbl
.dim
);
457 memcpy(vtbl
.data
, baseClass
->vtbl
.data
, sizeof(void *) * vtbl
.dim
);
459 // Inherit properties from base class
460 com
= baseClass
->isCOMclass();
461 isauto
= baseClass
->isauto
;
462 vthis
= baseClass
->vthis
;
463 storage_class
|= baseClass
->storage_class
& (STCconst
| STCinvariant
);
467 // No base class, so this is the root of the class hierarchy
469 vtbl
.push(this); // leave room for classinfo as first member
472 protection
= sc
->protection
;
473 storage_class
|= sc
->stc
;
477 interfaceSemantic(sc
);
479 for (i
= 0; i
< members
->dim
; i
++)
481 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
482 s
->addMember(sc
, this, 1);
485 /* If this is a nested class, add the hidden 'this'
486 * member which is a pointer to the enclosing scope.
488 if (vthis
) // if inheriting from nested class
489 { // Use the base class's 'this' member
491 if (storage_class
& STCstatic
)
492 error("static class cannot inherit from nested class %s", baseClass
->toChars());
493 if (toParent2() != baseClass
->toParent2())
494 error("super class %s is nested within %s, not %s",
495 baseClass
->toChars(),
496 baseClass
->toParent2()->toChars(),
497 toParent2()->toChars());
499 else if (!(storage_class
& STCstatic
))
500 { Dsymbol
*s
= toParent2();
503 ClassDeclaration
*cd
= s
->isClassDeclaration();
504 FuncDeclaration
*fd
= s
->isFuncDeclaration();
513 { AggregateDeclaration
*ad
= fd
->isMember2();
518 t
= new TypePointer(Type::tvoid
);
519 t
= t
->semantic(0, sc
);
525 vthis
= new ThisDeclaration(t
);
526 members
->push(vthis
);
532 if (storage_class
& (STCauto
| STCscope
))
534 if (storage_class
& STCabstract
)
536 if (storage_class
& STCinvariant
)
537 type
= type
->invariantOf();
538 else if (storage_class
& STCconst
)
539 type
= type
->constOf();
542 sc
->stc
&= ~(STCfinal
| STCauto
| STCscope
| STCstatic
|
543 STCabstract
| STCdeprecated
| STCconst
| STCinvariant
| STCtls
);
544 sc
->stc
|= storage_class
& (STCconst
| STCinvariant
);
545 sc
->attributes
= NULL
;
550 sc
->linkage
= LINKwindows
;
551 sc
->protection
= PROTpublic
;
552 sc
->explicitProtection
= 0;
554 structalign
= sc
->structalign
;
556 { sc
->offset
= baseClass
->structsize
;
557 alignsize
= baseClass
->alignsize
;
559 // sc->offset += PTRSIZE; // room for uplevel context pointer
562 { sc
->offset
= PTRSIZE
* 2; // allow room for vptr[] and monitor
565 structsize
= sc
->offset
;
567 int members_dim
= members
->dim
;
569 for (i
= 0; i
< members_dim
; i
++)
571 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
576 { // semantic() failed because of forward references.
577 // Unwind what we did, and defer it for later
585 scope
= scx
? scx
: new Scope(*sc
);
587 scope
->module
->addDeferredSemantic(this);
589 //printf("\tsemantic('%s') failed due to forward references\n", toChars());
593 //printf("\tsemantic('%s') successful\n", toChars());
595 structsize
= sc
->offset
;
598 /* Look for special member functions.
599 * They must be in this class, not in a base class.
601 ctor
= (CtorDeclaration
*)search(0, Id::ctor
, 0);
602 if (ctor
&& ctor
->toParent() != this)
605 // dtor = (DtorDeclaration *)search(Id::dtor, 0);
606 // if (dtor && dtor->toParent() != this)
609 // inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
610 // if (inv && inv->toParent() != this)
613 // Can be in base class
614 aggNew
= (NewDeclaration
*)search(0, Id::classNew
, 0);
615 aggDelete
= (DeleteDeclaration
*)search(0, Id::classDelete
, 0);
617 // If this class has no constructor, but base class does, create
622 // Also do this if we have some "in" fields on the class, or
623 // if there are non-null fields
626 bool hasInArgs
= false;
627 bool hasNonNull
= false;
628 for (int i
= 0; i
< fields
.dim
; i
++)
630 VarDeclaration
*var
= (VarDeclaration
*) fields
.data
[i
];
632 if (var
->storage_class
&& STCinject
) {
637 if (var
->type
->ty
== Tclass
) {
642 if (hasInArgs
|| hasNonNull
|| (baseClass
&& baseClass
->ctor
))
644 //printf("Creating default this(){} for class %s\n", toChars());
645 ctor
= new CtorDeclaration(0, 0, NULL
, 0);
646 ctor
->fbody
= new CompoundStatement(0, new Statements());
648 ctor
->addMember(sc
, this, 1);
649 *sc
= scsave
; // why? What about sc->nofree?
650 sc
->offset
= structsize
;
659 aggDelete
= baseClass
->aggDelete
;
661 aggNew
= baseClass
->aggNew
;
665 // Allocate instance of each new interface
666 for (i
= 0; i
< vtblInterfaces
->dim
; i
++)
668 BaseClass
*b
= (BaseClass
*)vtblInterfaces
->data
[i
];
669 unsigned thissize
= PTRSIZE
;
671 alignmember(structalign
, thissize
, &sc
->offset
);
672 assert(b
->offset
== 0);
673 b
->offset
= sc
->offset
;
675 // Take care of single inheritance offsets
676 while (b
->baseInterfaces_dim
)
678 b
= &b
->baseInterfaces
[0];
679 b
->offset
= sc
->offset
;
682 sc
->offset
+= thissize
;
683 if (alignsize
< thissize
)
684 alignsize
= thissize
;
686 structsize
= sc
->offset
;
690 dtor
= buildDtor(sc
);
694 #if 0 // Do not call until toObjfile() because of forward references
695 // Fill in base class vtbl[]s
696 for (i
= 0; i
< vtblInterfaces
->dim
; i
++)
698 BaseClass
*b
= (BaseClass
*)vtblInterfaces
->data
[i
];
700 //b->fillVtbl(this, &b->vtbl, 1);
703 //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
706 void ClassDeclaration::toCBuffer(OutBuffer
*buf
, HdrGenState
*hgs
)
710 buf
->printf("%s ", kind());
711 buf
->writestring(toChars());
713 buf
->writestring(" : ");
715 for (int i
= 0; i
< baseclasses
.dim
; i
++)
717 BaseClass
*b
= (BaseClass
*)baseclasses
.data
[i
];
721 //buf->writestring(b->base->ident->toChars());
722 b
->type
->toCBuffer(buf
, NULL
, hgs
);
727 for (int i
= 0; i
< members
->dim
; i
++)
729 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
731 buf
->writestring(" ");
732 s
->toCBuffer(buf
, hgs
);
734 buf
->writestring("}");
739 void ClassDeclaration::defineRef(Dsymbol
*s
)
741 ClassDeclaration
*cd
;
743 AggregateDeclaration::defineRef(s
);
744 cd
= s
->isClassDeclaration();
745 baseType
= cd
->baseType
;
750 /*********************************************
751 * Determine if 'this' is a base class of cd.
752 * This is used to detect circular inheritance only.
755 int ClassDeclaration::isBaseOf2(ClassDeclaration
*cd
)
759 //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
760 for (int i
= 0; i
< cd
->baseclasses
.dim
; i
++)
761 { BaseClass
*b
= (BaseClass
*)cd
->baseclasses
.data
[i
];
763 if (b
->base
== this || isBaseOf2(b
->base
))
769 /*******************************************
770 * Determine if 'this' is a base class of cd.
773 int ClassDeclaration::isBaseOf(ClassDeclaration
*cd
, target_ptrdiff_t
*poffset
)
775 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
780 if (this == cd
->baseClass
)
783 /* cd->baseClass might not be set if cd is forward referenced.
785 if (!cd
->baseClass
&& cd
->baseclasses
.dim
&& !cd
->isInterfaceDeclaration())
787 cd
->error("base class is forward referenced by %s", toChars());
795 Dsymbol
*ClassDeclaration::search(Loc loc
, Identifier
*ident
, int flags
)
799 //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
803 if (!members
|| !symtab
|| scope
)
804 { error("is forward referenced when looking for '%s'", ident
->toChars());
809 s
= ScopeDsymbol::search(loc
, ident
, flags
);
812 // Search bases classes in depth-first, left to right order
816 for (i
= 0; i
< baseclasses
.dim
; i
++)
818 BaseClass
*b
= (BaseClass
*)baseclasses
.data
[i
];
822 if (!b
->base
->symtab
)
823 error("base %s is forward referenced", b
->base
->ident
->toChars());
826 s
= b
->base
->search(loc
, ident
, flags
);
827 if (s
== this) // happens if s is nested in this and derives from this
838 /**********************************************************
839 * fd is in the vtbl[] for this class.
840 * Return 1 if function is hidden (not findable through search).
844 int isf(void *param
, FuncDeclaration
*fd
)
846 //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
850 int ClassDeclaration::isFuncHidden(FuncDeclaration
*fd
)
852 //printf("ClassDeclaration::isFuncHidden(%s)\n", fd->toChars());
853 Dsymbol
*s
= search(0, fd
->ident
, 4|2);
855 { //printf("not found\n");
856 /* Because, due to a hack, if there are multiple definitions
857 * of fd->ident, NULL is returned.
862 OverloadSet
*os
= s
->isOverloadSet();
865 for (int i
= 0; i
< os
->a
.dim
; i
++)
866 { Dsymbol
*s
= (Dsymbol
*)os
->a
.data
[i
];
867 FuncDeclaration
*f2
= s
->isFuncDeclaration();
868 if (f2
&& overloadApply(f2
, &isf
, fd
))
875 FuncDeclaration
*fdstart
= s
->isFuncDeclaration();
876 //printf("%s fdstart = %p\n", s->kind(), fdstart);
877 return !overloadApply(fdstart
, &isf
, fd
);
883 * Find virtual function matching identifier and type.
884 * Used to build virtual function tables for interface implementations.
887 FuncDeclaration
*ClassDeclaration::findFunc(Identifier
*ident
, TypeFunction
*tf
)
889 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
891 ClassDeclaration
*cd
= this;
892 Array
*vtbl
= &cd
->vtbl
;
895 for (size_t i
= 0; i
< vtbl
->dim
; i
++)
897 FuncDeclaration
*fd
= (FuncDeclaration
*)vtbl
->data
[i
];
899 //printf("\t[%d] = %s\n", i, fd->toChars());
900 if (ident
== fd
->ident
&&
901 //tf->equals(fd->type)
902 fd
->type
->covariant(tf
) == 1
904 { //printf("\t\tfound\n");
907 //else printf("\t\t%d\n", fd->type->covariant(tf));
911 vtbl
= &cd
->vtblFinal
;
918 void ClassDeclaration::interfaceSemantic(Scope
*sc
)
920 InterfaceDeclaration
*id
= isInterfaceDeclaration();
922 vtblInterfaces
= new BaseClasses();
923 vtblInterfaces
->reserve(interfaces_dim
);
925 for (size_t i
= 0; i
< interfaces_dim
; i
++)
927 BaseClass
*b
= interfaces
[i
];
929 // If this is an interface, and it derives from a COM interface,
930 // then this is a COM interface too.
931 if (b
->base
->isCOMinterface())
934 if (b
->base
->isCPPinterface() && id
)
937 vtblInterfaces
->push(b
);
938 b
->copyBaseInterfaces(vtblInterfaces
);
942 /****************************************
945 int ClassDeclaration::isCOMclass()
950 int ClassDeclaration::isCOMinterface()
955 int ClassDeclaration::isCPPinterface()
961 /****************************************
964 int ClassDeclaration::isAbstract()
968 for (int i
= 1; i
< vtbl
.dim
; i
++)
970 FuncDeclaration
*fd
= ((Dsymbol
*)vtbl
.data
[i
])->isFuncDeclaration();
972 //printf("\tvtbl[%d] = %p\n", i, fd);
973 if (!fd
|| fd
->isAbstract())
983 /****************************************
984 * Returns !=0 if there's an extra member which is the 'this'
985 * pointer to the enclosing context (enclosing class or function)
988 int ClassDeclaration::isNested()
993 /****************************************
994 * Determine if slot 0 of the vtbl[] is reserved for something else.
995 * For class objects, yes, this is where the classinfo ptr goes.
996 * For COM interfaces, no.
997 * For non-COM interfaces, yes, this is where the Interface ptr goes.
1000 int ClassDeclaration::vtblOffset()
1005 /****************************************
1008 char *ClassDeclaration::kind()
1013 /****************************************
1016 void ClassDeclaration::addLocalClass(ClassDeclarations
*aclasses
)
1018 aclasses
->push(this);
1021 /********************************* InterfaceDeclaration ****************************/
1023 InterfaceDeclaration::InterfaceDeclaration(Loc loc
, Identifier
*id
, BaseClasses
*baseclasses
, LINK l
)
1024 : ClassDeclaration(loc
, id
, baseclasses
, l
)
1028 if (id
== Id::IUnknown
) // IUnknown is the root of all COM interfaces
1030 cpp
= 1; // IUnknown is also a C++ interface
1034 Dsymbol
*InterfaceDeclaration::syntaxCopy(Dsymbol
*s
)
1036 InterfaceDeclaration
*id
;
1039 id
= (InterfaceDeclaration
*)s
;
1041 id
= new InterfaceDeclaration(loc
, ident
, NULL
, linkage
);
1043 ClassDeclaration::syntaxCopy(id
);
1047 void InterfaceDeclaration::semantic(Scope
*sc
)
1050 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1054 { type
= type
->semantic(loc
, sc
);
1055 handle
= handle
->semantic(loc
, sc
);
1057 if (!members
) // if forward reference
1058 { //printf("\tinterface '%s' is forward referenced\n", toChars());
1061 if (symtab
) // if already done
1066 symtab
= new DsymbolTable();
1071 scx
= scope
; // save so we don't make redundant copies
1076 attributes
->append(sc
->attributes
);
1078 attributes
= sc
->attributes
;
1080 if (sc
->stc
& STCdeprecated
)
1085 // Expand any tuples in baseclasses[]
1086 for (i
= 0; i
< baseclasses
.dim
; )
1087 { BaseClass
*b
= (BaseClass
*)baseclasses
.data
[0];
1088 b
->type
= b
->type
->semantic(loc
, sc
);
1089 Type
*tb
= b
->type
->toBasetype();
1091 if (tb
->ty
== Ttuple
)
1092 { TypeTuple
*tup
= (TypeTuple
*)tb
;
1093 enum PROT protection
= b
->protection
;
1094 baseclasses
.remove(i
);
1095 size_t dim
= Argument::dim(tup
->arguments
);
1096 for (size_t j
= 0; j
< dim
; j
++)
1097 { Argument
*arg
= Argument::getNth(tup
->arguments
, j
);
1098 b
= new BaseClass(arg
->type
, protection
);
1099 baseclasses
.insert(i
+ j
, b
);
1106 if (!baseclasses
.dim
&& sc
->linkage
== LINKcpp
)
1109 // Check for errors, handle forward references
1110 for (i
= 0; i
< baseclasses
.dim
; )
1115 b
= (BaseClass
*)baseclasses
.data
[i
];
1116 b
->type
= b
->type
->semantic(loc
, sc
);
1117 tb
= b
->type
->toBasetype();
1118 if (tb
->ty
== Tclass
)
1119 tc
= (TypeClass
*)tb
;
1122 if (!tc
|| !tc
->sym
->isInterfaceDeclaration())
1124 error("base type must be interface, not %s", b
->type
->toChars());
1125 baseclasses
.remove(i
);
1130 // Check for duplicate interfaces
1131 for (size_t j
= 0; j
< i
; j
++)
1133 BaseClass
*b2
= (BaseClass
*)baseclasses
.data
[j
];
1134 if (b2
->base
== tc
->sym
)
1135 error("inherits from duplicate interface %s", b2
->base
->toChars());
1139 if (b
->base
== this || isBaseOf2(b
->base
))
1141 error("circular inheritance of interface");
1142 baseclasses
.remove(i
);
1145 if (!b
->base
->symtab
|| b
->base
->scope
|| b
->base
->inuse
)
1147 //error("forward reference of base class %s", baseClass->toChars());
1148 // Forward reference of base, try again later
1149 //printf("\ttry later, forward reference of base %s\n", b->base->toChars());
1150 scope
= scx
? scx
: new Scope(*sc
);
1152 scope
->module
->addDeferredSemantic(this);
1157 // Inherit const/invariant from base class
1158 storage_class
|= b
->base
->storage_class
& (STCconst
| STCinvariant
);
1163 interfaces_dim
= baseclasses
.dim
;
1164 interfaces
= (BaseClass
**)baseclasses
.data
;
1166 interfaceSemantic(sc
);
1169 vtbl
.push(this); // leave room at vtbl[0] for classinfo
1171 // Cat together the vtbl[]'s from base interfaces
1172 for (i
= 0; i
< interfaces_dim
; i
++)
1173 { BaseClass
*b
= interfaces
[i
];
1175 // Skip if b has already appeared
1176 for (int k
= 0; k
< i
; k
++)
1178 if (b
== interfaces
[i
])
1182 // Copy vtbl[] from base class
1183 if (b
->base
->vtblOffset())
1184 { int d
= b
->base
->vtbl
.dim
;
1187 vtbl
.reserve(d
- 1);
1188 for (int j
= 1; j
< d
; j
++)
1189 vtbl
.push(b
->base
->vtbl
.data
[j
]);
1194 vtbl
.append(&b
->base
->vtbl
);
1201 protection
= sc
->protection
;
1202 storage_class
|= sc
->stc
& (STCconst
| STCinvariant
);
1204 for (i
= 0; i
< members
->dim
; i
++)
1206 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
1207 s
->addMember(sc
, this, 1);
1210 sc
= sc
->push(this);
1211 sc
->stc
&= ~(STCfinal
| STCauto
| STCscope
| STCstatic
|
1212 STCabstract
| STCdeprecated
| STCconst
| STCinvariant
| STCtls
);
1213 sc
->stc
|= storage_class
& (STCconst
| STCinvariant
);
1214 sc
->attributes
= NULL
;
1216 if (isCOMinterface())
1217 sc
->linkage
= LINKwindows
;
1218 else if (isCPPinterface())
1219 sc
->linkage
= LINKcpp
;
1220 sc
->structalign
= 8;
1221 structalign
= sc
->structalign
;
1222 sc
->offset
= PTRSIZE
* 2;
1224 for (i
= 0; i
< members
->dim
; i
++)
1226 Dsymbol
*s
= (Dsymbol
*)members
->data
[i
];
1232 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1236 /*******************************************
1237 * Determine if 'this' is a base class of cd.
1238 * (Actually, if it is an interface supported by cd)
1240 * *poffset offset to start of class
1241 * OFFSET_RUNTIME must determine offset at runtime
1247 int InterfaceDeclaration::isBaseOf(ClassDeclaration
*cd
, target_ptrdiff_t
*poffset
)
1251 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
1253 for (j
= 0; j
< cd
->interfaces_dim
; j
++)
1255 BaseClass
*b
= cd
->interfaces
[j
];
1257 //printf("\tbase %s\n", b->base->toChars());
1258 if (this == b
->base
)
1260 //printf("\tfound at offset %d\n", b->offset);
1262 { *poffset
= b
->offset
;
1263 if (j
&& cd
->isInterfaceDeclaration())
1264 *poffset
= OFFSET_RUNTIME
;
1268 if (isBaseOf(b
, poffset
))
1269 { if (j
&& poffset
&& cd
->isInterfaceDeclaration())
1270 *poffset
= OFFSET_RUNTIME
;
1275 if (cd
->baseClass
&& isBaseOf(cd
->baseClass
, poffset
))
1284 int InterfaceDeclaration::isBaseOf(BaseClass
*bc
, target_ptrdiff_t
*poffset
)
1286 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars());
1287 for (unsigned j
= 0; j
< bc
->baseInterfaces_dim
; j
++)
1289 BaseClass
*b
= &bc
->baseInterfaces
[j
];
1291 if (this == b
->base
)
1294 { *poffset
= b
->offset
;
1298 if (isBaseOf(b
, poffset
))
1308 /****************************************
1309 * Determine if slot 0 of the vtbl[] is reserved for something else.
1310 * For class objects, yes, this is where the ClassInfo ptr goes.
1311 * For COM interfaces, no.
1312 * For non-COM interfaces, yes, this is where the Interface ptr goes.
1315 int InterfaceDeclaration::vtblOffset()
1317 if (isCOMinterface() || isCPPinterface())
1322 int InterfaceDeclaration::isCOMinterface()
1327 int InterfaceDeclaration::isCPPinterface()
1332 /*******************************************
1335 char *InterfaceDeclaration::kind()
1341 /******************************** BaseClass *****************************/
1343 BaseClass::BaseClass()
1345 memset(this, 0, sizeof(BaseClass
));
1348 BaseClass::BaseClass(Type
*type
, enum PROT protection
)
1350 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
1352 this->protection
= protection
;
1356 baseInterfaces_dim
= 0;
1357 baseInterfaces
= NULL
;
1360 /****************************************
1361 * Fill in vtbl[] for base class based on member functions of class cd.
1363 * vtbl if !=NULL, fill it in
1364 * newinstance !=0 means all entries must be filled in by members
1365 * of cd, not members of any base classes of cd.
1367 * !=0 if any entries were filled in by members of cd (not exclusively
1371 int BaseClass::fillVtbl(ClassDeclaration
*cd
, Array
*vtbl
, int newinstance
)
1373 ClassDeclaration
*id
= base
;
1377 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars());
1379 vtbl
->setDim(base
->vtbl
.dim
);
1381 // first entry is ClassInfo reference
1382 for (j
= base
->vtblOffset(); j
< base
->vtbl
.dim
; j
++)
1384 FuncDeclaration
*ifd
= ((Dsymbol
*)base
->vtbl
.data
[j
])->isFuncDeclaration();
1385 FuncDeclaration
*fd
;
1388 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
1391 // Find corresponding function in this class
1392 tf
= (ifd
->type
->ty
== Tfunction
) ? (TypeFunction
*)(ifd
->type
) : NULL
;
1393 fd
= cd
->findFunc(ifd
->ident
, tf
);
1394 if (fd
&& !fd
->isAbstract())
1396 //printf(" found\n");
1397 // Check that calling conventions match
1398 if (fd
->linkage
!= ifd
->linkage
)
1399 fd
->error("linkage doesn't match interface function");
1401 // Check that it is current
1403 fd
->toParent() != cd
&&
1404 ifd
->toParent() == base
)
1405 cd
->error("interface function %s.%s is not implemented",
1406 id
->toChars(), ifd
->ident
->toChars());
1408 if (fd
->toParent() == cd
)
1413 //printf(" not found\n");
1414 // BUG: should mark this class as abstract?
1415 if (!cd
->isAbstract())
1416 cd
->error("interface function %s.%s isn't implemented",
1417 id
->toChars(), ifd
->ident
->toChars());
1427 void BaseClass::copyBaseInterfaces(BaseClasses
*vtblInterfaces
)
1429 //printf("+copyBaseInterfaces(), %s\n", base->toChars());
1430 // if (baseInterfaces_dim)
1433 baseInterfaces_dim
= base
->interfaces_dim
;
1434 baseInterfaces
= (BaseClass
*)mem
.calloc(baseInterfaces_dim
, sizeof(BaseClass
));
1436 //printf("%s.copyBaseInterfaces()\n", base->toChars());
1437 for (int i
= 0; i
< baseInterfaces_dim
; i
++)
1439 BaseClass
*b
= &baseInterfaces
[i
];
1440 BaseClass
*b2
= base
->interfaces
[i
];
1442 assert(b2
->vtbl
.dim
== 0); // should not be filled yet
1443 memcpy(b
, b2
, sizeof(BaseClass
));
1445 if (i
) // single inheritance is i==0
1446 vtblInterfaces
->push(b
); // only need for M.I.
1447 b
->copyBaseInterfaces(vtblInterfaces
);
1449 //printf("-copyBaseInterfaces\n");