1:
2: // Compiler implementation of the D programming language
3: // Copyright (c) 1999-2011 by Digital Mars
4: // All Rights Reserved
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.
10:
11: #include <stdio.h>
12: #include <stdlib.h>
13: static char __file__[] = __FILE__; /* for tassert.h */
14: #include "tassert.h"
15:
16: #include "root.h"
17: #include "rmem.h"
18:
19: #include "enum.h"
20: #include "init.h"
21: #include "attrib.h"
22: #include "declaration.h"
23: #include "aggregate.h"
24: #include "id.h"
25: #include "mtype.h"
26: #include "scope.h"
27: #include "module.h"
28: #include "expression.h"
29: #include "statement.h"
30:
31: /********************************* ClassDeclaration ****************************/
32:
33: ClassDeclaration *ClassDeclaration::classinfo;
34: ClassDeclaration *ClassDeclaration::object;
35: ClassDeclaration *ClassDeclaration::throwable;
36: ClassDeclaration *ClassDeclaration::exception;
37:
38: ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
39: : AggregateDeclaration(loc, id)
40: {
41: static char msg[] = "only object.d can define this reserved class name";
42:
43: if (baseclasses)
44: // Actually, this is a transfer
45: this->baseclasses = baseclasses;
46: else
47: this->baseclasses = new BaseClasses();
48: baseClass = NULL;
49:
50: interfaces_dim = 0;
51: interfaces = NULL;
52:
53: vtblInterfaces = NULL;
54:
55: //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses->dim);
56:
57: // For forward references
58: type = new TypeClass(this);
59: handle = type;
60:
61: staticCtor = NULL;
62: staticDtor = NULL;
63:
64: vtblsym = NULL;
65: vclassinfo = NULL;
66:
67: if (id)
68: { // Look for special class names
69:
70: if (id == Id::__sizeof || id == Id::__xalignof || id == Id::mangleof)
71: error("illegal class name");
72:
73: // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
74: if (id->toChars()[0] == 'T')
75: {
76: if (id == Id::TypeInfo)
77: { if (Type::typeinfo)
78: Type::typeinfo->error("%s", msg);
79: Type::typeinfo = this;
80: }
81:
82: if (id == Id::TypeInfo_Class)
83: { if (Type::typeinfoclass)
84: Type::typeinfoclass->error("%s", msg);
85: Type::typeinfoclass = this;
86: }
87:
88: if (id == Id::TypeInfo_Interface)
89: { if (Type::typeinfointerface)
90: Type::typeinfointerface->error("%s", msg);
91: Type::typeinfointerface = this;
92: }
93:
94: if (id == Id::TypeInfo_Struct)
95: { if (Type::typeinfostruct)
96: Type::typeinfostruct->error("%s", msg);
97: Type::typeinfostruct = this;
98: }
99:
100: if (id == Id::TypeInfo_Typedef)
101: { if (Type::typeinfotypedef)
102: Type::typeinfotypedef->error("%s", msg);
103: Type::typeinfotypedef = this;
104: }
105:
106: if (id == Id::TypeInfo_Pointer)
107: { if (Type::typeinfopointer)
108: Type::typeinfopointer->error("%s", msg);
109: Type::typeinfopointer = this;
110: }
111:
112: if (id == Id::TypeInfo_Array)
113: { if (Type::typeinfoarray)
114: Type::typeinfoarray->error("%s", msg);
115: Type::typeinfoarray = this;
116: }
117:
118: if (id == Id::TypeInfo_StaticArray)
119: { //if (Type::typeinfostaticarray)
120: //Type::typeinfostaticarray->error("%s", msg);
121: Type::typeinfostaticarray = this;
122: }
123:
124: if (id == Id::TypeInfo_AssociativeArray)
125: { if (Type::typeinfoassociativearray)
126: Type::typeinfoassociativearray->error("%s", msg);
127: Type::typeinfoassociativearray = this;
128: }
129:
130: if (id == Id::TypeInfo_Enum)
131: { if (Type::typeinfoenum)
132: Type::typeinfoenum->error("%s", msg);
133: Type::typeinfoenum = this;
134: }
135:
136: if (id == Id::TypeInfo_Function)
137: { if (Type::typeinfofunction)
138: Type::typeinfofunction->error("%s", msg);
139: Type::typeinfofunction = this;
140: }
141:
142: if (id == Id::TypeInfo_Delegate)
143: { if (Type::typeinfodelegate)
144: Type::typeinfodelegate->error("%s", msg);
145: Type::typeinfodelegate = this;
146: }
147:
148: if (id == Id::TypeInfo_Tuple)
149: { if (Type::typeinfotypelist)
150: Type::typeinfotypelist->error("%s", msg);
151: Type::typeinfotypelist = this;
152: }
153:
154: #if DMDV2
155: if (id == Id::TypeInfo_Const)
156: { if (Type::typeinfoconst)
157: Type::typeinfoconst->error("%s", msg);
158: Type::typeinfoconst = this;
159: }
160:
161: if (id == Id::TypeInfo_Invariant)
162: { if (Type::typeinfoinvariant)
163: Type::typeinfoinvariant->error("%s", msg);
164: Type::typeinfoinvariant = this;
165: }
166:
167: if (id == Id::TypeInfo_Shared)
168: { if (Type::typeinfoshared)
169: Type::typeinfoshared->error("%s", msg);
170: Type::typeinfoshared = this;
171: }
172:
173: if (id == Id::TypeInfo_Wild)
174: { if (Type::typeinfowild)
175: Type::typeinfowild->error("%s", msg);
176: Type::typeinfowild = this;
177: }
178: #endif
179: }
180:
181: if (id == Id::Object)
182: { if (object)
183: object->error("%s", msg);
184: object = this;
185: }
186:
187: if (id == Id::Throwable)
188: { if (throwable)
189: throwable->error("%s", msg);
190: throwable = this;
191: }
192:
193: if (id == Id::Exception)
194: { if (exception)
195: exception->error("%s", msg);
196: exception = this;
197: }
198:
199: //if (id == Id::ClassInfo)
200: if (id == Id::TypeInfo_Class)
201: { if (classinfo)
202: classinfo->error("%s", msg);
203: classinfo = this;
204: }
205:
206: if (id == Id::ModuleInfo)
207: { if (Module::moduleinfo)
208: Module::moduleinfo->error("%s", msg);
209: Module::moduleinfo = this;
210: }
211: }
212:
213: com = 0;
214: isscope = 0;
215: isabstract = 0;
216: inuse = 0;
217: }
218:
219: Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
220: {
221: ClassDeclaration *cd;
222:
223: //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
224: if (s)
225: cd = (ClassDeclaration *)s;
226: else
227: cd = new ClassDeclaration(loc, ident, NULL);
warning C6211: Leaking memory 'return value' due to an exception. Consider using a local catch block to clean up memory: Lines: 221, 224, 227, 229, 231, 232, 234, 235
228:
229: cd->storage_class |= storage_class;
230:
231: cd->baseclasses->setDim(this->baseclasses->dim);
232: for (int i = 0; i < cd->baseclasses->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
233: {
234: BaseClass *b = this->baseclasses->tdata()[i];
235: BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
236: cd->baseclasses->tdata()[i] = b2;
237: }
238:
239: ScopeDsymbol::syntaxCopy(cd);
240: return cd;
241: }
242:
243: void ClassDeclaration::semantic(Scope *sc)
244: { int i;
245: unsigned offset;
warning C4101: 'offset' : unreferenced local variable
246:
247: //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
248: //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
249: //printf("sc->stc = %x\n", sc->stc);
250:
251: //{ static int n; if (++n == 20) *(char*)0=0; }
252:
253: if (!ident) // if anonymous class
254: { const char *id = "__anonclass";
255:
256: ident = Identifier::generateId(id);
257: }
258:
259: if (!sc)
260: sc = scope;
261: if (!parent && sc->parent && !sc->parent->isModule())
262: parent = sc->parent;
263:
264: type = type->semantic(loc, sc);
265: handle = type;
266:
267: if (!members) // if forward reference
268: { //printf("\tclass '%s' is forward referenced\n", toChars());
269: return;
270: }
271: if (symtab)
272: { if (sizeok == 1 || !scope)
273: { //printf("\tsemantic for '%s' is already completed\n", toChars());
274: return; // semantic() already completed
275: }
276: }
277: else
278: symtab = new DsymbolTable();
279:
280: Scope *scx = NULL;
281: if (scope)
282: { sc = scope;
283: scx = scope; // save so we don't make redundant copies
284: scope = NULL;
285: }
286: unsigned dprogress_save = Module::dprogress;
287: #ifdef IN_GCC
288: methods.setDim(0);
289: #endif
290:
291: if (sc->stc & STCdeprecated)
292: {
293: isdeprecated = 1;
294: }
295:
296: if (sc->linkage == LINKcpp)
297: error("cannot create C++ classes");
298:
299: // Expand any tuples in baseclasses[]
300: for (i = 0; i < baseclasses->dim; )
warning C4018: '<' : signed/unsigned mismatch
301: { BaseClass *b = baseclasses->tdata()[i];
302: //printf("test1 %s %s\n", toChars(), b->type->toChars());
303: b->type = b->type->semantic(loc, sc);
304: //printf("test2\n");
305: Type *tb = b->type->toBasetype();
306:
307: if (tb->ty == Ttuple)
308: { TypeTuple *tup = (TypeTuple *)tb;
309: enum PROT protection = b->protection;
310: baseclasses->remove(i);
311: size_t dim = Parameter::dim(tup->arguments);
312: for (size_t j = 0; j < dim; j++)
313: { Parameter *arg = Parameter::getNth(tup->arguments, j);
314: b = new BaseClass(arg->type, protection);
315: baseclasses->insert(i + j, b);
316: }
317: }
318: else
319: i++;
320: }
321:
322: // See if there's a base class as first in baseclasses[]
323: if (baseclasses->dim)
324: { TypeClass *tc;
325: BaseClass *b;
326: Type *tb;
327:
328: b = baseclasses->tdata()[0];
329: //b->type = b->type->semantic(loc, sc);
330: tb = b->type->toBasetype();
331: if (tb->ty != Tclass)
332: { error("base type must be class or interface, not %s", b->type->toChars());
333: baseclasses->remove(0);
334: }
335: else
336: {
337: tc = (TypeClass *)(tb);
338:
339: if (tc->sym->isDeprecated())
340: {
341: if (!isDeprecated())
342: {
343: // Deriving from deprecated class makes this one deprecated too
344: isdeprecated = 1;
345:
346: tc->checkDeprecated(loc, sc);
347: }
348: }
349:
350: if (tc->sym->isInterfaceDeclaration())
351: ;
352: else
353: {
354: for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
355: {
356: if (cdb == this)
357: {
358: error("circular inheritance");
359: baseclasses->remove(0);
360: goto L7;
361: }
362: }
363: if (!tc->sym->symtab || tc->sym->sizeok == 0)
364: { // Try to resolve forward reference
365: if (/*sc->mustsemantic &&*/ tc->sym->scope)
366: tc->sym->semantic(NULL);
367: }
368: if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
369: {
370: //printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars());
371: //error("forward reference of base class %s", baseClass->toChars());
372: // Forward reference of base class, try again later
373: //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
374: scope = scx ? scx : new Scope(*sc);
375: scope->setNoFree();
376: if (tc->sym->scope)
377: tc->sym->scope->module->addDeferredSemantic(tc->sym);
378: scope->module->addDeferredSemantic(this);
379: return;
380: }
381: else
382: { baseClass = tc->sym;
383: b->base = baseClass;
384: }
385: L7: ;
386: }
387: }
388: }
389:
390: // Treat the remaining entries in baseclasses as interfaces
391: // Check for errors, handle forward references
392: for (i = (baseClass ? 1 : 0); i < baseclasses->dim; )
warning C4018: '<' : signed/unsigned mismatch
393: { TypeClass *tc;
394: BaseClass *b;
395: Type *tb;
396:
397: b = baseclasses->tdata()[i];
398: b->type = b->type->semantic(loc, sc);
399: tb = b->type->toBasetype();
400: if (tb->ty == Tclass)
401: tc = (TypeClass *)tb;
402: else
403: tc = NULL;
404: if (!tc || !tc->sym->isInterfaceDeclaration())
405: {
406: error("base type must be interface, not %s", b->type->toChars());
407: baseclasses->remove(i);
408: continue;
409: }
410: else
411: {
412: if (tc->sym->isDeprecated())
413: {
414: if (!isDeprecated())
415: {
416: // Deriving from deprecated class makes this one deprecated too
417: isdeprecated = 1;
418:
419: tc->checkDeprecated(loc, sc);
420: }
421: }
422:
423: // Check for duplicate interfaces
424: for (size_t j = (baseClass ? 1 : 0); j < i; j++)
warning C4018: '<' : signed/unsigned mismatch
425: {
426: BaseClass *b2 = baseclasses->tdata()[j];
427: if (b2->base == tc->sym)
428: error("inherits from duplicate interface %s", b2->base->toChars());
429: }
430:
431: if (!tc->sym->symtab)
432: { // Try to resolve forward reference
433: if (/*sc->mustsemantic &&*/ tc->sym->scope)
434: tc->sym->semantic(NULL);
435: }
436:
437: b->base = tc->sym;
438: if (!b->base->symtab || b->base->scope)
439: {
440: //error("forward reference of base class %s", baseClass->toChars());
441: // Forward reference of base, try again later
442: //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
443: scope = scx ? scx : new Scope(*sc);
444: scope->setNoFree();
445: if (tc->sym->scope)
446: tc->sym->scope->module->addDeferredSemantic(tc->sym);
447: scope->module->addDeferredSemantic(this);
448: return;
449: }
450: }
451: i++;
452: }
453:
454:
455: // If no base class, and this is not an Object, use Object as base class
456: if (!baseClass && ident != Id::Object)
457: {
458: // BUG: what if Object is redefined in an inner scope?
459: Type *tbase = new TypeIdentifier(0, Id::Object);
460: BaseClass *b;
461: TypeClass *tc;
462: Type *bt;
463:
464: if (!object)
465: {
466: error("missing or corrupt object.d");
467: fatal();
468: }
469: bt = tbase->semantic(loc, sc)->toBasetype();
470: b = new BaseClass(bt, PROTpublic);
471: baseclasses->shift(b);
472: assert(b->type->ty == Tclass);
473: tc = (TypeClass *)(b->type);
474: baseClass = tc->sym;
475: assert(!baseClass->isInterfaceDeclaration());
476: b->base = baseClass;
477: }
478:
479: interfaces_dim = baseclasses->dim;
480: interfaces = baseclasses->tdata();
481:
482:
483: if (baseClass)
484: {
485: if (baseClass->storage_class & STCfinal)
486: error("cannot inherit from final class %s", baseClass->toChars());
487:
488: interfaces_dim--;
489: interfaces++;
490:
491: // Copy vtbl[] from base class
492: vtbl.setDim(baseClass->vtbl.dim);
493: memcpy(vtbl.tdata(), baseClass->vtbl.tdata(), sizeof(void *) * vtbl.dim);
494:
495: // Inherit properties from base class
496: com = baseClass->isCOMclass();
497: isscope = baseClass->isscope;
498: vthis = baseClass->vthis;
499: storage_class |= baseClass->storage_class & STC_TYPECTOR;
500: }
501: else
502: {
503: // No base class, so this is the root of the class hierarchy
504: vtbl.setDim(0);
505: vtbl.push(this); // leave room for classinfo as first member
506: }
507:
508: protection = sc->protection;
509: storage_class |= sc->stc;
510:
511: if (sizeok == 0)
512: {
513: interfaceSemantic(sc);
514:
515: for (i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
516: {
517: Dsymbol *s = members->tdata()[i];
518: s->addMember(sc, this, 1);
519: }
520:
521: /* If this is a nested class, add the hidden 'this'
522: * member which is a pointer to the enclosing scope.
523: */
524: if (vthis) // if inheriting from nested class
525: { // Use the base class's 'this' member
526: isnested = 1;
527: if (storage_class & STCstatic)
528: error("static class cannot inherit from nested class %s", baseClass->toChars());
529: if (toParent2() != baseClass->toParent2())
530: {
531: if (toParent2())
532: {
533: error("is nested within %s, but super class %s is nested within %s",
534: toParent2()->toChars(),
535: baseClass->toChars(),
536: baseClass->toParent2()->toChars());
537: }
538: else
539: {
540: error("is not nested, but super class %s is nested within %s",
541: baseClass->toChars(),
542: baseClass->toParent2()->toChars());
543: }
544: isnested = 0;
545: }
546: }
547: else if (!(storage_class & STCstatic))
548: { Dsymbol *s = toParent2();
549: if (s)
550: {
551: AggregateDeclaration *ad = s->isClassDeclaration();
552: FuncDeclaration *fd = s->isFuncDeclaration();
553:
554:
555: if (ad || fd)
556: { isnested = 1;
557: Type *t;
558: if (ad)
559: t = ad->handle;
560: else if (fd)
561: { AggregateDeclaration *ad = fd->isMember2();
warning C6246: Local declaration of 'ad' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '551' of 'c:\projects\extern\d\dmd\src\class.c': Lines: 551
562: if (ad)
563: t = ad->handle;
564: else
565: {
566: t = Type::tvoidptr;
567: }
568: }
569: else
570: assert(0);
571: if (t->ty == Tstruct) // ref to struct
572: t = Type::tvoidptr;
573: assert(!vthis);
574: vthis = new ThisDeclaration(loc, t);
575: members->push(vthis);
576: }
577: }
578: }
579: }
580:
581: if (storage_class & STCauto)
582: error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?");
583: if (storage_class & STCscope)
584: isscope = 1;
585: if (storage_class & STCabstract)
586: isabstract = 1;
587:
588: if (storage_class & STCimmutable)
589: type = type->addMod(MODimmutable);
590: if (storage_class & STCconst)
591: type = type->addMod(MODconst);
592: if (storage_class & STCshared)
593: type = type->addMod(MODshared);
594:
595: sc = sc->push(this);
596: //sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared);
597: //sc->stc |= storage_class & STC_TYPECTOR;
598: sc->stc &= STCsafe | STCtrusted | STCsystem;
599: sc->parent = this;
600: sc->inunion = 0;
601:
602: if (isCOMclass())
603: {
604: #if _WIN32
605: sc->linkage = LINKwindows;
606: #else
607: /* This enables us to use COM objects under Linux and
608: * work with things like XPCOM
609: */
610: sc->linkage = LINKc;
611: #endif
612: }
613: sc->protection = PROTpublic;
614: sc->explicitProtection = 0;
615: sc->structalign = 8;
616: structalign = sc->structalign;
617: if (baseClass)
618: { sc->offset = baseClass->structsize;
619: alignsize = baseClass->alignsize;
620: // if (isnested)
621: // sc->offset += PTRSIZE; // room for uplevel context pointer
622: }
623: else
624: { sc->offset = PTRSIZE * 2; // allow room for __vptr and __monitor
625: alignsize = PTRSIZE;
626: }
627: structsize = sc->offset;
628: Scope scsave = *sc;
629: int members_dim = members->dim;
630: sizeok = 0;
631:
632: /* Set scope so if there are forward references, we still might be able to
633: * resolve individual members like enums.
634: */
635: for (i = 0; i < members_dim; i++)
636: { Dsymbol *s = members->tdata()[i];
637: /* There are problems doing this in the general case because
638: * Scope keeps track of things like 'offset'
639: */
640: if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
641: {
642: //printf("setScope %s %s\n", s->kind(), s->toChars());
643: s->setScope(sc);
644: }
645: }
646:
647: for (i = 0; i < members_dim; i++)
648: { Dsymbol *s = members->tdata()[i];
649: s->semantic(sc);
650: }
651:
652: if (sizeok == 2)
653: { // semantic() failed because of forward references.
654: // Unwind what we did, and defer it for later
655: fields.setDim(0);
656: structsize = 0;
657: alignsize = 0;
658: structalign = 0;
659:
660: sc = sc->pop();
661:
662: scope = scx ? scx : new Scope(*sc);
663: scope->setNoFree();
664: scope->module->addDeferredSemantic(this);
665:
666: Module::dprogress = dprogress_save;
667:
668: //printf("\tsemantic('%s') failed due to forward references\n", toChars());
669: return;
670: }
671:
672: //printf("\tsemantic('%s') successful\n", toChars());
673:
674: structsize = sc->offset;
675: //members->print();
676:
677: /* Look for special member functions.
678: * They must be in this class, not in a base class.
679: */
680: ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
681: if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration()))
682: ctor = NULL;
683:
684: // dtor = (DtorDeclaration *)search(Id::dtor, 0);
685: // if (dtor && dtor->toParent() != this)
686: // dtor = NULL;
687:
688: // inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
689: // if (inv && inv->toParent() != this)
690: // inv = NULL;
691:
692: // Can be in base class
693: aggNew = (NewDeclaration *)search(0, Id::classNew, 0);
694: aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
695:
696: // If this class has no constructor, but base class does, create
697: // a constructor:
698: // this() { }
699: if (!ctor && baseClass && baseClass->ctor)
700: {
701: //printf("Creating default this(){} for class %s\n", toChars());
702: Type *tf = new TypeFunction(NULL, NULL, 0, LINKd, 0);
703: CtorDeclaration *ctor = new CtorDeclaration(loc, 0, 0, tf);
704: ctor->fbody = new CompoundStatement(0, new Statements());
705: members->push(ctor);
706: ctor->addMember(sc, this, 1);
707: *sc = scsave; // why? What about sc->nofree?
708: sc->offset = structsize;
709: ctor->semantic(sc);
710: this->ctor = ctor;
711: defaultCtor = ctor;
712: }
713:
714: #if 0
715: if (baseClass)
716: { if (!aggDelete)
717: aggDelete = baseClass->aggDelete;
718: if (!aggNew)
719: aggNew = baseClass->aggNew;
720: }
721: #endif
722:
723: // Allocate instance of each new interface
724: for (i = 0; i < vtblInterfaces->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
725: {
726: BaseClass *b = vtblInterfaces->tdata()[i];
727: unsigned thissize = PTRSIZE;
728:
729: alignmember(structalign, thissize, &sc->offset);
730: assert(b->offset == 0);
731: b->offset = sc->offset;
732:
733: // Take care of single inheritance offsets
734: while (b->baseInterfaces_dim)
735: {
736: b = &b->baseInterfaces[0];
737: b->offset = sc->offset;
738: }
739:
740: sc->offset += thissize;
741: if (alignsize < thissize)
742: alignsize = thissize;
743: }
744: structsize = sc->offset;
745: sizeok = 1;
746: Module::dprogress++;
747:
748: dtor = buildDtor(sc);
749:
750: sc->pop();
751:
752: #if 0 // Do not call until toObjfile() because of forward references
753: // Fill in base class vtbl[]s
754: for (i = 0; i < vtblInterfaces->dim; i++)
755: {
756: BaseClass *b = vtblInterfaces->tdata()[i];
757:
758: //b->fillVtbl(this, &b->vtbl, 1);
759: }
760: #endif
761: //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
762:
763: if (deferred)
764: {
765: deferred->semantic2(sc);
766: deferred->semantic3(sc);
767: }
768: }
769:
770: void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
771: {
772: if (!isAnonymous())
773: {
774: buf->printf("%s ", kind());
775: buf->writestring(toChars());
776: if (baseclasses->dim)
777: buf->writestring(" : ");
778: }
779: for (int i = 0; i < baseclasses->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
780: {
781: BaseClass *b = baseclasses->tdata()[i];
782:
783: if (i)
784: buf->writeByte(',');
785: //buf->writestring(b->base->ident->toChars());
786: b->type->toCBuffer(buf, NULL, hgs);
787: }
788: if (members)
789: {
790: buf->writenl();
791: buf->writeByte('{');
792: buf->writenl();
793: for (int i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
794: {
795: Dsymbol *s = members->tdata()[i];
796:
797: buf->writestring(" ");
798: s->toCBuffer(buf, hgs);
799: }
800: buf->writestring("}");
801: }
802: else
803: buf->writeByte(';');
804: buf->writenl();
805: }
806:
807: #if 0
808: void ClassDeclaration::defineRef(Dsymbol *s)
809: {
810: ClassDeclaration *cd;
811:
812: AggregateDeclaration::defineRef(s);
813: cd = s->isClassDeclaration();
814: baseType = cd->baseType;
815: cd->baseType = NULL;
816: }
817: #endif
818:
819: /*********************************************
820: * Determine if 'this' is a base class of cd.
821: * This is used to detect circular inheritance only.
822: */
823:
824: int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
825: {
826: if (!cd)
827: return 0;
828: //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
829: for (int i = 0; i < cd->baseclasses->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
830: { BaseClass *b = cd->baseclasses->tdata()[i];
831:
832: if (b->base == this || isBaseOf2(b->base))
833: return 1;
834: }
835: return 0;
836: }
837:
838: /*******************************************
839: * Determine if 'this' is a base class of cd.
840: */
841:
842: int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
843: {
844: //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
845: if (poffset)
846: *poffset = 0;
847: while (cd)
848: {
849: /* cd->baseClass might not be set if cd is forward referenced.
850: */
851: if (!cd->baseClass && cd->baseclasses->dim && !cd->isInterfaceDeclaration())
852: {
853: cd->semantic(NULL);
854: if (!cd->baseClass)
855: cd->error("base class is forward referenced by %s", toChars());
856: }
857:
858: if (this == cd->baseClass)
859: return 1;
860:
861: cd = cd->baseClass;
862: }
863: return 0;
864: }
865:
866: /*********************************************
867: * Determine if 'this' has complete base class information.
868: * This is used to detect forward references in covariant overloads.
869: */
870:
871: int ClassDeclaration::isBaseInfoComplete()
872: {
873: if (!baseClass)
874: return ident == Id::Object;
875: for (int i = 0; i < baseclasses->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
876: { BaseClass *b = baseclasses->tdata()[i];
877: if (!b->base || !b->base->isBaseInfoComplete())
878: return 0;
879: }
880: return 1;
881: }
882:
883: Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
884: {
885: Dsymbol *s;
886: //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
887:
888: if (scope && !symtab)
889: { Scope *sc = scope;
890: sc->mustsemantic++;
891: semantic(sc);
892: sc->mustsemantic--;
893: }
894:
895: if (!members || !symtab)
896: {
897: error("is forward referenced when looking for '%s'", ident->toChars());
898: //*(char*)0=0;
899: return NULL;
900: }
901:
902: s = ScopeDsymbol::search(loc, ident, flags);
903: if (!s)
904: {
905: // Search bases classes in depth-first, left to right order
906:
907: int i;
908:
909: for (i = 0; i < baseclasses->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
910: {
911: BaseClass *b = baseclasses->tdata()[i];
912:
913: if (b->base)
914: {
915: if (!b->base->symtab)
916: error("base %s is forward referenced", b->base->ident->toChars());
917: else
918: {
919: s = b->base->search(loc, ident, flags);
920: if (s == this) // happens if s is nested in this and derives from this
921: s = NULL;
922: else if (s)
923: break;
924: }
925: }
926: }
927: }
928: return s;
929: }
930:
931: /**********************************************************
932: * fd is in the vtbl[] for this class.
933: * Return 1 if function is hidden (not findable through search).
934: */
935:
936: #if DMDV2
937: int isf(void *param, FuncDeclaration *fd)
938: {
939: //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
940: return param == fd;
941: }
942:
943: int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
944: {
945: //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toChars());
946: Dsymbol *s = search(0, fd->ident, 4|2);
947: if (!s)
948: { //printf("not found\n");
949: /* Because, due to a hack, if there are multiple definitions
950: * of fd->ident, NULL is returned.
951: */
952: return 0;
953: }
954: s = s->toAlias();
955: OverloadSet *os = s->isOverloadSet();
956: if (os)
957: {
958: for (int i = 0; i < os->a.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
959: { Dsymbol *s = os->a.tdata()[i];
warning C6246: Local declaration of 's' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '946' of 'c:\projects\extern\d\dmd\src\class.c': Lines: 946
960: FuncDeclaration *f2 = s->isFuncDeclaration();
961: if (f2 && overloadApply(f2, &isf, fd))
962: return 0;
963: }
964: return 1;
965: }
966: else
967: {
968: FuncDeclaration *fdstart = s->isFuncDeclaration();
969: //printf("%s fdstart = %p\n", s->kind(), fdstart);
970: return !overloadApply(fdstart, &isf, fd);
971: }
972: }
973: #endif
974:
975: /****************
976: * Find virtual function matching identifier and type.
977: * Used to build virtual function tables for interface implementations.
978: */
979:
980: FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
981: {
982: //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
983:
984: ClassDeclaration *cd = this;
985: Dsymbols *vtbl = &cd->vtbl;
986: while (1)
987: {
988: for (size_t i = 0; i < vtbl->dim; i++)
989: {
990: FuncDeclaration *fd = vtbl->tdata()[i]->isFuncDeclaration();
991: if (!fd)
992: continue; // the first entry might be a ClassInfo
993:
994: //printf("\t[%d] = %s\n", i, fd->toChars());
995: if (ident == fd->ident &&
996: //tf->equals(fd->type)
997: fd->type->covariant(tf) == 1
998: )
999: { //printf("\t\tfound\n");
1000: return fd;
1001: }
1002: //else printf("\t\t%d\n", fd->type->covariant(tf));
1003: }
1004: if (!cd)
1005: break;
1006: vtbl = &cd->vtblFinal;
1007: cd = cd->baseClass;
1008: }
1009:
1010: return NULL;
1011: }
1012:
1013: void ClassDeclaration::interfaceSemantic(Scope *sc)
1014: {
1015: InterfaceDeclaration *id = isInterfaceDeclaration();
1016:
1017: vtblInterfaces = new BaseClasses();
1018: vtblInterfaces->reserve(interfaces_dim);
1019:
1020: for (size_t i = 0; i < interfaces_dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1021: {
1022: BaseClass *b = interfaces[i];
1023:
1024: // If this is an interface, and it derives from a COM interface,
1025: // then this is a COM interface too.
1026: if (b->base->isCOMinterface())
1027: com = 1;
1028:
1029: if (b->base->isCPPinterface() && id)
1030: id->cpp = 1;
1031:
1032: vtblInterfaces->push(b);
1033: b->copyBaseInterfaces(vtblInterfaces);
1034: }
1035: }
1036:
1037: /****************************************
1038: */
1039:
1040: int ClassDeclaration::isCOMclass()
1041: {
1042: return com;
1043: }
1044:
1045: int ClassDeclaration::isCOMinterface()
1046: {
1047: return 0;
1048: }
1049:
1050: #if DMDV2
1051: int ClassDeclaration::isCPPinterface()
1052: {
1053: return 0;
1054: }
1055: #endif
1056:
1057:
1058: /****************************************
1059: */
1060:
1061: int ClassDeclaration::isAbstract()
1062: {
1063: if (isabstract)
1064: return TRUE;
1065: for (int i = 1; i < vtbl.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1066: {
1067: FuncDeclaration *fd = vtbl.tdata()[i]->isFuncDeclaration();
1068:
1069: //printf("\tvtbl[%d] = %p\n", i, fd);
1070: if (!fd || fd->isAbstract())
1071: {
1072: isabstract |= 1;
1073: return TRUE;
1074: }
1075: }
1076: return FALSE;
1077: }
1078:
1079:
1080: /****************************************
1081: * Determine if slot 0 of the vtbl[] is reserved for something else.
1082: * For class objects, yes, this is where the classinfo ptr goes.
1083: * For COM interfaces, no.
1084: * For non-COM interfaces, yes, this is where the Interface ptr goes.
1085: */
1086:
1087: int ClassDeclaration::vtblOffset()
1088: {
1089: return 1;
1090: }
1091:
1092: /****************************************
1093: */
1094:
1095: const char *ClassDeclaration::kind()
1096: {
1097: return "class";
1098: }
1099:
1100: /****************************************
1101: */
1102:
1103: void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses)
1104: {
1105: aclasses->push(this);
1106: }
1107:
1108: /********************************* InterfaceDeclaration ****************************/
1109:
1110: InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
1111: : ClassDeclaration(loc, id, baseclasses)
1112: {
1113: com = 0;
1114: cpp = 0;
1115: if (id == Id::IUnknown) // IUnknown is the root of all COM interfaces
1116: { com = 1;
1117: cpp = 1; // IUnknown is also a C++ interface
1118: }
1119: }
1120:
1121: Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s)
1122: {
1123: InterfaceDeclaration *id;
1124:
1125: if (s)
1126: id = (InterfaceDeclaration *)s;
1127: else
1128: id = new InterfaceDeclaration(loc, ident, NULL);
1129:
1130: ClassDeclaration::syntaxCopy(id);
1131: return id;
1132: }
1133:
1134: void InterfaceDeclaration::semantic(Scope *sc)
1135: { int i;
1136:
1137: //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1138: if (inuse)
1139: return;
1140:
1141: if (!sc)
1142: sc = scope;
1143: if (!parent && sc->parent && !sc->parent->isModule())
1144: parent = sc->parent;
1145:
1146: type = type->semantic(loc, sc);
1147: handle = type;
1148:
1149: if (!members) // if forward reference
1150: { //printf("\tinterface '%s' is forward referenced\n", toChars());
1151: return;
1152: }
1153: if (symtab) // if already done
1154: { if (!scope)
1155: return;
1156: }
1157: else
1158: symtab = new DsymbolTable();
1159:
1160: Scope *scx = NULL;
1161: if (scope)
1162: { sc = scope;
1163: scx = scope; // save so we don't make redundant copies
1164: scope = NULL;
1165: }
1166:
1167: if (sc->stc & STCdeprecated)
1168: {
1169: isdeprecated = 1;
1170: }
1171:
1172: // Expand any tuples in baseclasses[]
1173: for (i = 0; i < baseclasses->dim; )
warning C4018: '<' : signed/unsigned mismatch
1174: { BaseClass *b = baseclasses->tdata()[0];
1175: b->type = b->type->semantic(loc, sc);
1176: Type *tb = b->type->toBasetype();
1177:
1178: if (tb->ty == Ttuple)
1179: { TypeTuple *tup = (TypeTuple *)tb;
1180: enum PROT protection = b->protection;
1181: baseclasses->remove(i);
1182: size_t dim = Parameter::dim(tup->arguments);
1183: for (size_t j = 0; j < dim; j++)
1184: { Parameter *arg = Parameter::getNth(tup->arguments, j);
1185: b = new BaseClass(arg->type, protection);
1186: baseclasses->insert(i + j, b);
1187: }
1188: }
1189: else
1190: i++;
1191: }
1192:
1193: if (!baseclasses->dim && sc->linkage == LINKcpp)
1194: cpp = 1;
1195:
1196: // Check for errors, handle forward references
1197: for (i = 0; i < baseclasses->dim; )
warning C4018: '<' : signed/unsigned mismatch
1198: { TypeClass *tc;
1199: BaseClass *b;
1200: Type *tb;
1201:
1202: b = baseclasses->tdata()[i];
1203: b->type = b->type->semantic(loc, sc);
1204: tb = b->type->toBasetype();
1205: if (tb->ty == Tclass)
1206: tc = (TypeClass *)tb;
1207: else
1208: tc = NULL;
1209: if (!tc || !tc->sym->isInterfaceDeclaration())
1210: {
1211: error("base type must be interface, not %s", b->type->toChars());
1212: baseclasses->remove(i);
1213: continue;
1214: }
1215: else
1216: {
1217: // Check for duplicate interfaces
1218: for (size_t j = 0; j < i; j++)
warning C4018: '<' : signed/unsigned mismatch
1219: {
1220: BaseClass *b2 = baseclasses->tdata()[j];
1221: if (b2->base == tc->sym)
1222: error("inherits from duplicate interface %s", b2->base->toChars());
1223: }
1224:
1225: b->base = tc->sym;
1226: if (b->base == this || isBaseOf2(b->base))
1227: {
1228: error("circular inheritance of interface");
1229: baseclasses->remove(i);
1230: continue;
1231: }
1232: if (!b->base->symtab)
1233: { // Try to resolve forward reference
1234: if (sc->mustsemantic && b->base->scope)
1235: b->base->semantic(NULL);
1236: }
1237: if (!b->base->symtab || b->base->scope || b->base->inuse)
1238: {
1239: //error("forward reference of base class %s", baseClass->toChars());
1240: // Forward reference of base, try again later
1241: //printf("\ttry later, forward reference of base %s\n", b->base->toChars());
1242: scope = scx ? scx : new Scope(*sc);
1243: scope->setNoFree();
1244: scope->module->addDeferredSemantic(this);
1245: return;
1246: }
1247: }
1248: #if 0
1249: // Inherit const/invariant from base class
1250: storage_class |= b->base->storage_class & STC_TYPECTOR;
1251: #endif
1252: i++;
1253: }
1254:
1255: interfaces_dim = baseclasses->dim;
1256: interfaces = baseclasses->tdata();
1257:
1258: interfaceSemantic(sc);
1259:
1260: if (vtblOffset())
1261: vtbl.push(this); // leave room at vtbl[0] for classinfo
1262:
1263: // Cat together the vtbl[]'s from base interfaces
1264: for (i = 0; i < interfaces_dim; i++)
1265: { BaseClass *b = interfaces[i];
1266:
1267: // Skip if b has already appeared
1268: for (int k = 0; k < i; k++)
1269: {
1270: if (b == interfaces[k])
1271: goto Lcontinue;
1272: }
1273:
1274: // Copy vtbl[] from base class
1275: if (b->base->vtblOffset())
1276: { int d = b->base->vtbl.dim;
1277: if (d > 1)
1278: {
1279: vtbl.reserve(d - 1);
1280: for (int j = 1; j < d; j++)
1281: vtbl.push(b->base->vtbl.tdata()[j]);
1282: }
1283: }
1284: else
1285: {
1286: vtbl.append(&b->base->vtbl);
1287: }
1288:
1289: Lcontinue:
1290: ;
1291: }
1292:
1293: protection = sc->protection;
1294: storage_class |= sc->stc & STC_TYPECTOR;
1295:
1296: for (i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1297: {
1298: Dsymbol *s = members->tdata()[i];
1299: s->addMember(sc, this, 1);
1300: }
1301:
1302: sc = sc->push(this);
1303: sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
1304: STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared);
1305: sc->stc |= storage_class & STC_TYPECTOR;
1306: sc->parent = this;
1307: if (isCOMinterface())
1308: sc->linkage = LINKwindows;
1309: else if (isCPPinterface())
1310: sc->linkage = LINKcpp;
1311: sc->structalign = 8;
1312: structalign = sc->structalign;
1313: sc->offset = PTRSIZE * 2;
1314: inuse++;
1315: for (i = 0; i < members->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1316: {
1317: Dsymbol *s = members->tdata()[i];
1318: s->semantic(sc);
1319: }
1320: inuse--;
1321: //members->print();
1322: sc->pop();
1323: //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1324: }
1325:
1326:
1327: /*******************************************
1328: * Determine if 'this' is a base class of cd.
1329: * (Actually, if it is an interface supported by cd)
1330: * Output:
1331: * *poffset offset to start of class
1332: * OFFSET_RUNTIME must determine offset at runtime
1333: * Returns:
1334: * 0 not a base
1335: * 1 is a base
1336: */
1337:
1338: int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
1339: {
1340: unsigned j;
1341:
1342: //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
1343: assert(!baseClass);
1344: for (j = 0; j < cd->interfaces_dim; j++)
warning C4018: '<' : signed/unsigned mismatch
1345: {
1346: BaseClass *b = cd->interfaces[j];
1347:
1348: //printf("\tbase %s\n", b->base->toChars());
1349: if (this == b->base)
1350: {
1351: //printf("\tfound at offset %d\n", b->offset);
1352: if (poffset)
1353: { *poffset = b->offset;
1354: if (j && cd->isInterfaceDeclaration())
1355: *poffset = OFFSET_RUNTIME;
1356: }
1357: return 1;
1358: }
1359: if (isBaseOf(b, poffset))
1360: { if (j && poffset && cd->isInterfaceDeclaration())
1361: *poffset = OFFSET_RUNTIME;
1362: return 1;
1363: }
1364: }
1365:
1366: if (cd->baseClass && isBaseOf(cd->baseClass, poffset))
1367: return 1;
1368:
1369: if (poffset)
1370: *poffset = 0;
1371: return 0;
1372: }
1373:
1374:
1375: int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset)
1376: {
1377: //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars());
1378: for (unsigned j = 0; j < bc->baseInterfaces_dim; j++)
warning C4018: '<' : signed/unsigned mismatch
1379: {
1380: BaseClass *b = &bc->baseInterfaces[j];
1381:
1382: if (this == b->base)
1383: {
1384: if (poffset)
1385: { *poffset = b->offset;
1386: if (j && bc->base->isInterfaceDeclaration())
1387: *poffset = OFFSET_RUNTIME;
1388: }
1389: return 1;
1390: }
1391: if (isBaseOf(b, poffset))
1392: { if (j && poffset && bc->base->isInterfaceDeclaration())
1393: *poffset = OFFSET_RUNTIME;
1394: return 1;
1395: }
1396: }
1397: if (poffset)
1398: *poffset = 0;
1399: return 0;
1400: }
1401:
1402: /*********************************************
1403: * Determine if 'this' has clomplete base class information.
1404: * This is used to detect forward references in covariant overloads.
1405: */
1406:
1407: int InterfaceDeclaration::isBaseInfoComplete()
1408: {
1409: assert(!baseClass);
1410: for (int i = 0; i < baseclasses->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1411: { BaseClass *b = baseclasses->tdata()[i];
1412: if (!b->base || !b->base->isBaseInfoComplete ())
1413: return 0;
1414: }
1415: return 1;
1416: }
1417:
1418: /****************************************
1419: * Determine if slot 0 of the vtbl[] is reserved for something else.
1420: * For class objects, yes, this is where the ClassInfo ptr goes.
1421: * For COM interfaces, no.
1422: * For non-COM interfaces, yes, this is where the Interface ptr goes.
1423: */
1424:
1425: int InterfaceDeclaration::vtblOffset()
1426: {
1427: if (isCOMinterface() || isCPPinterface())
1428: return 0;
1429: return 1;
1430: }
1431:
1432: int InterfaceDeclaration::isCOMinterface()
1433: {
1434: return com;
1435: }
1436:
1437: #if DMDV2
1438: int InterfaceDeclaration::isCPPinterface()
1439: {
1440: return cpp;
1441: }
1442: #endif
1443:
1444: /*******************************************
1445: */
1446:
1447: const char *InterfaceDeclaration::kind()
1448: {
1449: return "interface";
1450: }
1451:
1452:
1453: /******************************** BaseClass *****************************/
1454:
1455: BaseClass::BaseClass()
1456: {
1457: memset(this, 0, sizeof(BaseClass));
1458: }
1459:
1460: BaseClass::BaseClass(Type *type, enum PROT protection)
1461: {
1462: //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
1463: this->type = type;
1464: this->protection = protection;
1465: base = NULL;
1466: offset = 0;
1467:
1468: baseInterfaces_dim = 0;
1469: baseInterfaces = NULL;
1470: }
1471:
1472: /****************************************
1473: * Fill in vtbl[] for base class based on member functions of class cd.
1474: * Input:
1475: * vtbl if !=NULL, fill it in
1476: * newinstance !=0 means all entries must be filled in by members
1477: * of cd, not members of any base classes of cd.
1478: * Returns:
1479: * !=0 if any entries were filled in by members of cd (not exclusively
1480: * by base classes)
1481: */
1482:
1483: int BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance)
1484: {
1485: ClassDeclaration *id = base;
1486: int j;
1487: int result = 0;
1488:
1489: //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars());
1490: if (vtbl)
1491: vtbl->setDim(base->vtbl.dim);
1492:
1493: // first entry is ClassInfo reference
1494: for (j = base->vtblOffset(); j < base->vtbl.dim; j++)
warning C4018: '<' : signed/unsigned mismatch
1495: {
1496: FuncDeclaration *ifd = base->vtbl.tdata()[j]->isFuncDeclaration();
1497: FuncDeclaration *fd;
1498: TypeFunction *tf;
1499:
1500: //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
1501:
1502: assert(ifd);
1503: // Find corresponding function in this class
1504: tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL;
1505: fd = cd->findFunc(ifd->ident, tf);
1506: if (fd && !fd->isAbstract())
1507: {
1508: //printf(" found\n");
1509: // Check that calling conventions match
1510: if (fd->linkage != ifd->linkage)
1511: fd->error("linkage doesn't match interface function");
1512:
1513: // Check that it is current
1514: if (newinstance &&
1515: fd->toParent() != cd &&
1516: ifd->toParent() == base)
1517: cd->error("interface function %s.%s is not implemented",
1518: id->toChars(), ifd->ident->toChars());
1519:
1520: if (fd->toParent() == cd)
1521: result = 1;
1522: }
1523: else
1524: {
1525: //printf(" not found\n");
1526: // BUG: should mark this class as abstract?
1527: if (!cd->isAbstract())
1528: cd->error("interface function %s.%s isn't implemented",
1529: id->toChars(), ifd->ident->toChars());
1530: fd = NULL;
1531: }
1532: if (vtbl)
1533: vtbl->tdata()[j] = fd;
1534: }
1535:
1536: return result;
1537: }
1538:
1539: void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces)
1540: {
1541: //printf("+copyBaseInterfaces(), %s\n", base->toChars());
1542: // if (baseInterfaces_dim)
1543: // return;
1544:
1545: baseInterfaces_dim = base->interfaces_dim;
1546: baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass));
1547:
1548: //printf("%s.copyBaseInterfaces()\n", base->toChars());
1549: for (int i = 0; i < baseInterfaces_dim; i++)
1550: {
1551: BaseClass *b = &baseInterfaces[i];
1552: BaseClass *b2 = base->interfaces[i];
1553:
1554: assert(b2->vtbl.dim == 0); // should not be filled yet
1555: memcpy(b, b2, sizeof(BaseClass));
1556:
1557: if (i) // single inheritance is i==0
1558: vtblInterfaces->push(b); // only need for M.I.
1559: b->copyBaseInterfaces(vtblInterfaces);
1560: }
1561: //printf("-copyBaseInterfaces\n");
1562: }
1563: