int InterfaceDeclaration::vtblOffset() { if (isCOMinterface() || isCPPinterface()) return 0; return 1; }
void InterfaceDeclaration::semantic(Scope *sc) { //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); if (inuse) return; if (!sc) sc = scope; if (!parent && sc->parent && !sc->parent->isModule()) parent = sc->parent; type = type->semantic(loc, sc); handle = type; if (!members) // if forward reference { //printf("\tinterface '%s' is forward referenced\n", toChars()); return; } if (symtab) // if already done { if (!scope) return; } else symtab = new DsymbolTable(); Scope *scx = NULL; if (scope) { sc = scope; scx = scope; // save so we don't make redundant copies scope = NULL; } #if IN_GCC if (attributes) attributes->append(sc->attributes); else attributes = sc->attributes; #endif if (sc->stc & STCdeprecated) { isdeprecated = 1; } // Expand any tuples in baseclasses[] for (size_t i = 0; i < baseclasses->dim; ) { BaseClass *b = baseclasses->tdata()[0]; b->type = b->type->semantic(loc, sc); Type *tb = b->type->toBasetype(); if (tb->ty == Ttuple) { TypeTuple *tup = (TypeTuple *)tb; enum PROT protection = b->protection; baseclasses->remove(i); size_t dim = Parameter::dim(tup->arguments); for (size_t j = 0; j < dim; j++) { Parameter *arg = Parameter::getNth(tup->arguments, j); b = new BaseClass(arg->type, protection); baseclasses->insert(i + j, b); } } else i++; } if (!baseclasses->dim && sc->linkage == LINKcpp) cpp = 1; // Check for errors, handle forward references for (size_t i = 0; i < baseclasses->dim; ) { TypeClass *tc; BaseClass *b; Type *tb; b = baseclasses->tdata()[i]; b->type = b->type->semantic(loc, sc); tb = b->type->toBasetype(); if (tb->ty == Tclass) tc = (TypeClass *)tb; else tc = NULL; if (!tc || !tc->sym->isInterfaceDeclaration()) { error("base type must be interface, not %s", b->type->toChars()); baseclasses->remove(i); continue; } else { // Check for duplicate interfaces for (size_t j = 0; j < i; j++) { BaseClass *b2 = baseclasses->tdata()[j]; if (b2->base == tc->sym) error("inherits from duplicate interface %s", b2->base->toChars()); } b->base = tc->sym; if (b->base == this || isBaseOf2(b->base)) { error("circular inheritance of interface"); baseclasses->remove(i); continue; } if (!b->base->symtab) { // Try to resolve forward reference if (sc->mustsemantic && b->base->scope) b->base->semantic(NULL); } if (!b->base->symtab || b->base->scope || b->base->inuse) { //error("forward reference of base class %s", baseClass->toChars()); // Forward reference of base, try again later //printf("\ttry later, forward reference of base %s\n", b->base->toChars()); scope = scx ? scx : new Scope(*sc); scope->setNoFree(); scope->module->addDeferredSemantic(this); return; } } #if 0 // Inherit const/invariant from base class storage_class |= b->base->storage_class & STC_TYPECTOR; #endif i++; } interfaces_dim = baseclasses->dim; interfaces = baseclasses->tdata(); interfaceSemantic(sc); if (vtblOffset()) vtbl.push(this); // leave room at vtbl[0] for classinfo // Cat together the vtbl[]'s from base interfaces for (size_t i = 0; i < interfaces_dim; i++) { BaseClass *b = interfaces[i]; // Skip if b has already appeared for (int k = 0; k < i; k++) { if (b == interfaces[k]) goto Lcontinue; } // Copy vtbl[] from base class if (b->base->vtblOffset()) { int d = b->base->vtbl.dim; if (d > 1) { vtbl.reserve(d - 1); for (int j = 1; j < d; j++) vtbl.push(b->base->vtbl.tdata()[j]); } } else { vtbl.append(&b->base->vtbl); } Lcontinue: ; } protection = sc->protection; storage_class |= sc->stc & STC_TYPECTOR; for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = members->tdata()[i]; s->addMember(sc, this, 1); } sc = sc->push(this); sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared); sc->stc |= storage_class & STC_TYPECTOR; #if IN_GCC sc->attributes = NULL; #endif sc->parent = this; if (isCOMinterface()) sc->linkage = LINKwindows; else if (isCPPinterface()) sc->linkage = LINKcpp; sc->structalign = 8; structalign = sc->structalign; sc->offset = PTRSIZE * 2; inuse++; for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = members->tdata()[i]; s->semantic(sc); } inuse--; //members->print(); sc->pop(); //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); }
void InterfaceDeclaration::semantic(Scope *sc) { //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); if (inuse) return; if (!sc) sc = scope; if (!parent && sc->parent && !sc->parent->isModule()) parent = sc->parent; type = type->semantic(loc, sc); handle = type; if (!members) // if forward reference { //printf("\tinterface '%s' is forward referenced\n", toChars()); return; } if (symtab) // if already done { if (!scope) return; } else symtab = new DsymbolTable(); Scope *scx = NULL; if (scope) { sc = scope; scx = scope; // save so we don't make redundant copies scope = NULL; } int errors = global.errors; if (sc->stc & STCdeprecated) { isdeprecated = true; } userAttributes = sc->userAttributes; // Expand any tuples in baseclasses[] for (size_t i = 0; i < baseclasses->dim; ) { BaseClass *b = (*baseclasses)[i]; b->type = b->type->semantic(loc, sc); Type *tb = b->type->toBasetype(); if (tb->ty == Ttuple) { TypeTuple *tup = (TypeTuple *)tb; enum PROT protection = b->protection; baseclasses->remove(i); size_t dim = Parameter::dim(tup->arguments); for (size_t j = 0; j < dim; j++) { Parameter *arg = Parameter::getNth(tup->arguments, j); b = new BaseClass(arg->type, protection); baseclasses->insert(i + j, b); } } else i++; } if (!baseclasses->dim && sc->linkage == LINKcpp) cpp = 1; // Check for errors, handle forward references for (size_t i = 0; i < baseclasses->dim; ) { TypeClass *tc; BaseClass *b; Type *tb; b = (*baseclasses)[i]; b->type = b->type->semantic(loc, sc); tb = b->type->toBasetype(); if (tb->ty == Tclass) tc = (TypeClass *)tb; else tc = NULL; if (!tc || !tc->sym->isInterfaceDeclaration()) { if (b->type != Type::terror) error("base type must be interface, not %s", b->type->toChars()); baseclasses->remove(i); continue; } else { // Check for duplicate interfaces for (size_t j = 0; j < i; j++) { BaseClass *b2 = (*baseclasses)[j]; if (b2->base == tc->sym) error("inherits from duplicate interface %s", b2->base->toChars()); } b->base = tc->sym; if (b->base == this || isBaseOf2(b->base)) { error("circular inheritance of interface"); baseclasses->remove(i); continue; } if (!b->base->symtab) { // Try to resolve forward reference if (doAncestorsSemantic == SemanticIn && b->base->scope) b->base->semantic(NULL); } if (!b->base->symtab || b->base->scope || b->base->inuse) { //error("forward reference of base class %s", baseClass->toChars()); // Forward reference of base, try again later //printf("\ttry later, forward reference of base %s\n", b->base->toChars()); scope = scx ? scx : new Scope(*sc); scope->setNoFree(); scope->module->addDeferredSemantic(this); return; } } #if 0 // Inherit const/invariant from base class storage_class |= b->base->storage_class & STC_TYPECTOR; #endif i++; } if (doAncestorsSemantic == SemanticIn) doAncestorsSemantic = SemanticDone; interfaces_dim = baseclasses->dim; interfaces = baseclasses->tdata(); interfaceSemantic(sc); if (vtblOffset()) vtbl.push(this); // leave room at vtbl[0] for classinfo // Cat together the vtbl[]'s from base interfaces for (size_t i = 0; i < interfaces_dim; i++) { BaseClass *b = interfaces[i]; // Skip if b has already appeared for (size_t k = 0; k < i; k++) { if (b == interfaces[k]) goto Lcontinue; } // Copy vtbl[] from base class if (b->base->vtblOffset()) { size_t d = b->base->vtbl.dim; if (d > 1) { vtbl.reserve(d - 1); for (size_t j = 1; j < d; j++) vtbl.push(b->base->vtbl[j]); } } else { vtbl.append(&b->base->vtbl); } Lcontinue: ; } protection = sc->protection; storage_class |= sc->stc & STC_TYPECTOR; for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (*members)[i]; s->addMember(sc, this, 1); } sc = sc->push(this); sc->stc &= STCsafe | STCtrusted | STCsystem; sc->parent = this; if (isCOMinterface()) sc->linkage = LINKwindows; else if (isCPPinterface()) sc->linkage = LINKcpp; sc->structalign = STRUCTALIGN_DEFAULT; sc->protection = PROTpublic; sc->explicitProtection = 0; // structalign = sc->structalign; sc->offset = Target::ptrsize * 2; sc->userAttributes = NULL; structsize = sc->offset; inuse++; /* Set scope so if there are forward references, we still might be able to * resolve individual members like enums. */ for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (*members)[i]; /* There are problems doing this in the general case because * Scope keeps track of things like 'offset' */ if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident)) { //printf("setScope %s %s\n", s->kind(), s->toChars()); s->setScope(sc); } } for (size_t i = 0; i < members->dim; i++) { Dsymbol *s = (*members)[i]; s->semantic(sc); } if (global.errors != errors) { // The type is no good. type = Type::terror; } inuse--; //members->print(); sc->pop(); //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); #if 0 if (type->ty == Tclass && ((TypeClass *)type)->sym != this) { printf("this = %p %s\n", this, this->toChars()); printf("type = %d sym = %p\n", type->ty, ((TypeClass *)type)->sym); } #endif assert(type->ty != Tclass || ((TypeClass *)type)->sym == this); }
void InterfaceDeclaration::toObjFile(int multiobj) { enum_SC scclass; //printf("InterfaceDeclaration::toObjFile('%s')\n", toChars()); if (type->ty == Terror) { error("had semantic errors when compiling"); return; } if (!members) return; if (global.params.symdebug) toDebug(this); scclass = SCglobal; if (isInstantiated()) scclass = SCcomdat; // Put out the members for (size_t i = 0; i < members->dim; i++) { Dsymbol *member = (*members)[i]; member->toObjFile(0); } // Generate C symbols toSymbol(this); ////////////////////////////////////////////// // Put out the TypeInfo type->genTypeInfo(NULL); type->vtinfo->toObjFile(multiobj); ////////////////////////////////////////////// // Put out the ClassInfo csym->Sclass = scclass; csym->Sfl = FLdata; /* The layout is: { void **vptr; monitor_t monitor; byte[] initializer; // static initialization data char[] name; // class name void *[] vtbl; Interface[] interfaces; Object *base; // base class void *destructor; void *invariant; // class invariant uint flags; void *deallocator; OffsetTypeInfo[] offTi; void *defaultConstructor; //const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function void* xgetRTInfo; //TypeInfo typeinfo; } */ dt_t *dt = NULL; if (Type::typeinfoclass) dtxoff(&dt, Type::typeinfoclass->toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo else dtsize_t(&dt, 0); // BUG: should be an assert() dtsize_t(&dt, 0); // monitor // initializer[] dtsize_t(&dt, 0); // size dtsize_t(&dt, 0); // initializer // name[] const char *name = toPrettyChars(); size_t namelen = strlen(name); dtsize_t(&dt, namelen); dtabytes(&dt, TYnptr, 0, namelen + 1, name); // vtbl[] dtsize_t(&dt, 0); dtsize_t(&dt, 0); // (*vtblInterfaces)[] unsigned offset; dtsize_t(&dt, vtblInterfaces->dim); if (vtblInterfaces->dim) { offset = global.params.isLP64 ? CLASSINFO_SIZE_64 : CLASSINFO_SIZE; // must be ClassInfo.size if (Type::typeinfoclass) { if (Type::typeinfoclass->structsize != offset) { error("mismatch between dmd and object.d or object.di found. Check installation and import paths with -v compiler switch."); fatal(); } } dtxoff(&dt, csym, offset, TYnptr); // (*) } else { offset = 0; dtsize_t(&dt, 0); } // base assert(!baseClass); dtsize_t(&dt, 0); // dtor dtsize_t(&dt, 0); // invariant dtsize_t(&dt, 0); // flags ClassFlags::Type flags = ClassFlags::hasOffTi | ClassFlags::hasTypeInfo; if (isCOMinterface()) flags |= ClassFlags::isCOMclass; dtsize_t(&dt, flags); // deallocator dtsize_t(&dt, 0); // offTi[] dtsize_t(&dt, 0); dtsize_t(&dt, 0); // null for now, fix later // defaultConstructor dtsize_t(&dt, 0); // xgetMembers //dtsize_t(&dt, 0); // xgetRTInfo // xgetRTInfo if (getRTInfo) getRTInfo->toDt(&dt); else dtsize_t(&dt, 0); // no pointers //dtxoff(&dt, toSymbol(type->vtinfo), 0, TYnptr); // typeinfo ////////////////////////////////////////////// // Put out (*vtblInterfaces)[]. Must immediately follow csym, because // of the fixup (*) offset += vtblInterfaces->dim * (4 * Target::ptrsize); for (size_t i = 0; i < vtblInterfaces->dim; i++) { BaseClass *b = (*vtblInterfaces)[i]; ClassDeclaration *id = b->base; // ClassInfo dtxoff(&dt, toSymbol(id), 0, TYnptr); // vtbl[] dtsize_t(&dt, 0); dtsize_t(&dt, 0); // this offset dtsize_t(&dt, b->offset); } csym->Sdt = dt; out_readonly(csym); outdata(csym); if (isExport()) objmod->export_symbol(csym,0); }