void Scope::deprecation10378(Loc loc, Dsymbol *sold, Dsymbol *snew) { // Bugzilla 15857 // // The overloadset found via the new lookup rules is either // equal or a subset of the overloadset found via the old // lookup rules, so it suffices to compare the dimension to // check for equality. OverloadSet *osold = NULL; OverloadSet *osnew = NULL; if (sold && (osold = sold->isOverloadSet()) != NULL && snew && (osnew = snew->isOverloadSet()) != NULL && osold->a.dim == osnew->a.dim) return; OutBuffer buf; buf.writestring("local import search method found "); if (osold) buf.printf("%s %s (%d overloads)", sold->kind(), sold->toPrettyChars(), (int)osold->a.dim); else if (sold) buf.printf("%s %s", sold->kind(), sold->toPrettyChars()); else buf.writestring("nothing"); buf.writestring(" instead of "); if (osnew) buf.printf("%s %s (%d overloads)", snew->kind(), snew->toPrettyChars(), (int)osnew->a.dim); else if (snew) buf.printf("%s %s", snew->kind(), snew->toPrettyChars()); else buf.writestring("nothing"); deprecation(loc, "%s", buf.peekString()); }
void Dsymbol::checkDeprecated(Loc loc, Scope *sc) { if (global.params.useDeprecated != 1 && isDeprecated()) { // Don't complain if we're inside a deprecated symbol's scope for (Dsymbol *sp = sc->parent; sp; sp = sp->parent) { if (sp->isDeprecated()) goto L1; } for (Scope *sc2 = sc; sc2; sc2 = sc2->enclosing) { if (sc2->scopesym && sc2->scopesym->isDeprecated()) goto L1; // If inside a StorageClassDeclaration that is deprecated if (sc2->stc & STCdeprecated) goto L1; } char *message = NULL; for (Dsymbol *p = this; p; p = p->parent) { message = p->depmsg; if (message) break; } if (message) deprecation(loc, "is deprecated - %s", message); else deprecation(loc, "is deprecated"); } L1: Declaration *d = isDeclaration(); if (d && d->storage_class & STCdisable) { if (!(sc->func && sc->func->storage_class & STCdisable)) { if (d->ident == Id::cpctor && d->toParent()) d->toParent()->error(loc, "is not copyable because it is annotated with @disable"); else error(loc, "is not callable because it is annotated with @disable"); } } }
void ClassDeclaration::toObjFile(int multiobj) { unsigned offset; Symbol *sinit; enum_SC scclass; //printf("ClassDeclaration::toObjFile('%s')\n", toChars()); if (type->ty == Terror) { error("had semantic errors when compiling"); return; } if (!members) return; if (multiobj && !hasStaticCtorOrDtor()) { obj_append(this); return; } if (global.params.symdebug) toDebug(this); assert(!scope); // semantic() should have been run to completion scclass = SCglobal; if (isInstantiated()) scclass = SCcomdat; // Put out the members for (size_t i = 0; i < members->dim; i++) { Dsymbol *member = (*members)[i]; /* There might be static ctors in the members, and they cannot * be put in separate obj files. */ member->toObjFile(multiobj); } // Generate C symbols toSymbol(this); toVtblSymbol(); sinit = toInitializer(); ////////////////////////////////////////////// // Generate static initializer sinit->Sclass = scclass; sinit->Sfl = FLdata; ClassDeclaration_toDt(this, &sinit->Sdt); out_readonly(sinit); outdata(sinit); ////////////////////////////////////////////// // 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; ClassInfo *base; // base class void *destructor; void *invariant; // class invariant ClassFlags flags; void *deallocator; OffsetTypeInfo[] offTi; void *defaultConstructor; //const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function void *xgetRTInfo; //TypeInfo typeinfo; } */ dt_t *dt = NULL; unsigned classinfo_size = global.params.isLP64 ? CLASSINFO_SIZE_64 : CLASSINFO_SIZE; // must be ClassInfo.size offset = classinfo_size; if (Type::typeinfoclass) { if (Type::typeinfoclass->structsize != classinfo_size) { #ifdef DEBUG printf("CLASSINFO_SIZE = x%x, Type::typeinfoclass->structsize = x%x\n", offset, Type::typeinfoclass->structsize); #endif error("mismatch between dmd and object.d or object.di found. Check installation and import paths with -v compiler switch."); fatal(); } } 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[] assert(structsize >= 8 || (cpp && structsize >= 4)); dtsize_t(&dt, structsize); // size dtxoff(&dt, sinit, 0, TYnptr); // initializer // name[] const char *name = ident->toChars(); size_t namelen = strlen(name); if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0)) { name = toPrettyChars(); namelen = strlen(name); } dtsize_t(&dt, namelen); dtabytes(&dt, TYnptr, 0, namelen + 1, name); // vtbl[] dtsize_t(&dt, vtbl.dim); dtxoff(&dt, vtblsym, 0, TYnptr); // interfaces[] dtsize_t(&dt, vtblInterfaces->dim); if (vtblInterfaces->dim) dtxoff(&dt, csym, offset, TYnptr); // (*) else dtsize_t(&dt, 0); // base if (baseClass) dtxoff(&dt, toSymbol(baseClass), 0, TYnptr); else dtsize_t(&dt, 0); // destructor if (dtor) dtxoff(&dt, toSymbol(dtor), 0, TYnptr); else dtsize_t(&dt, 0); // invariant if (inv) dtxoff(&dt, toSymbol(inv), 0, TYnptr); else dtsize_t(&dt, 0); // flags ClassFlags::Type flags = ClassFlags::hasOffTi; if (isCOMclass()) flags |= ClassFlags::isCOMclass; if (isCPPclass()) flags |= ClassFlags::isCPPclass; flags |= ClassFlags::hasGetMembers; flags |= ClassFlags::hasTypeInfo; if (ctor) flags |= ClassFlags::hasCtor; if (isabstract) flags |= ClassFlags::isAbstract; for (ClassDeclaration *cd = this; cd; cd = cd->baseClass) { if (cd->members) { for (size_t i = 0; i < cd->members->dim; i++) { Dsymbol *sm = (*cd->members)[i]; //printf("sm = %s %s\n", sm->kind(), sm->toChars()); if (sm->hasPointers()) goto L2; } } } flags |= ClassFlags::noPointers; L2: dtsize_t(&dt, flags); // deallocator if (aggDelete) dtxoff(&dt, toSymbol(aggDelete), 0, TYnptr); else dtsize_t(&dt, 0); // offTi[] dtsize_t(&dt, 0); dtsize_t(&dt, 0); // null for now, fix later // defaultConstructor if (defaultCtor) dtxoff(&dt, toSymbol(defaultCtor), 0, TYnptr); else dtsize_t(&dt, 0); // xgetRTInfo if (getRTInfo) getRTInfo->toDt(&dt); else if (flags & ClassFlags::noPointers) dtsize_t(&dt, 0); else dtsize_t(&dt, 1); //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; /* The layout is: * struct Interface * { * ClassInfo *interface; * void *[] vtbl; * size_t offset; * } */ // Fill in vtbl[] b->fillVtbl(this, &b->vtbl, 1); dtxoff(&dt, toSymbol(id), 0, TYnptr); // ClassInfo // vtbl[] dtsize_t(&dt, id->vtbl.dim); dtxoff(&dt, csym, offset, TYnptr); dtsize_t(&dt, b->offset); // this offset offset += id->vtbl.dim * Target::ptrsize; } // Put out the (*vtblInterfaces)[].vtbl[] // This must be mirrored with ClassDeclaration::baseVtblOffset() //printf("putting out %d interface vtbl[]s for '%s'\n", vtblInterfaces->dim, toChars()); for (size_t i = 0; i < vtblInterfaces->dim; i++) { BaseClass *b = (*vtblInterfaces)[i]; ClassDeclaration *id = b->base; //printf(" interface[%d] is '%s'\n", i, id->toChars()); size_t j = 0; if (id->vtblOffset()) { // First entry is ClassInfo reference //dtxoff(&dt, toSymbol(id), 0, TYnptr); // First entry is struct Interface reference dtxoff(&dt, csym, classinfo_size + i * (4 * Target::ptrsize), TYnptr); j = 1; } assert(id->vtbl.dim == b->vtbl.dim); for (; j < id->vtbl.dim; j++) { assert(j < b->vtbl.dim); #if 0 RootObject *o = b->vtbl[j]; if (o) { printf("o = %p\n", o); assert(o->dyncast() == DYNCAST_DSYMBOL); Dsymbol *s = (Dsymbol *)o; printf("s->kind() = '%s'\n", s->kind()); } #endif FuncDeclaration *fd = b->vtbl[j]; if (fd) dtxoff(&dt, fd->toThunkSymbol(b->offset), 0, TYnptr); else dtsize_t(&dt, 0); } } // Put out the overriding interface vtbl[]s. // This must be mirrored with ClassDeclaration::baseVtblOffset() //printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset); ClassDeclaration *cd; FuncDeclarations bvtbl; for (cd = this->baseClass; cd; cd = cd->baseClass) { for (size_t k = 0; k < cd->vtblInterfaces->dim; k++) { BaseClass *bs = (*cd->vtblInterfaces)[k]; if (bs->fillVtbl(this, &bvtbl, 0)) { //printf("\toverriding vtbl[] for %s\n", bs->base->toChars()); ClassDeclaration *id = bs->base; size_t j = 0; if (id->vtblOffset()) { // First entry is ClassInfo reference //dtxoff(&dt, toSymbol(id), 0, TYnptr); // First entry is struct Interface reference dtxoff(&dt, toSymbol(cd), classinfo_size + k * (4 * Target::ptrsize), TYnptr); j = 1; } for (; j < id->vtbl.dim; j++) { FuncDeclaration *fd; assert(j < bvtbl.dim); fd = bvtbl[j]; if (fd) dtxoff(&dt, fd->toThunkSymbol(bs->offset), 0, TYnptr); else dtsize_t(&dt, 0); } } } } csym->Sdt = dt; // ClassInfo cannot be const data, because we use the monitor on it outdata(csym); if (isExport()) objmod->export_symbol(csym,0); ////////////////////////////////////////////// // Put out the vtbl[] //printf("putting out %s.vtbl[]\n", toChars()); dt = NULL; if (vtblOffset()) dtxoff(&dt, csym, 0, TYnptr); // first entry is ClassInfo reference for (size_t i = vtblOffset(); i < vtbl.dim; i++) { FuncDeclaration *fd = vtbl[i]->isFuncDeclaration(); //printf("\tvtbl[%d] = %p\n", i, fd); if (fd && (fd->fbody || !isAbstract())) { // Ensure function has a return value (Bugzilla 4869) fd->functionSemantic(); Symbol *s = toSymbol(fd); if (isFuncHidden(fd)) { /* fd is hidden from the view of this class. * If fd overlaps with any function in the vtbl[], then * issue 'hidden' error. */ for (size_t j = 1; j < vtbl.dim; j++) { if (j == i) continue; FuncDeclaration *fd2 = vtbl[j]->isFuncDeclaration(); if (!fd2->ident->equals(fd->ident)) continue; if (fd->leastAsSpecialized(fd2) || fd2->leastAsSpecialized(fd)) { TypeFunction *tf = (TypeFunction *)fd->type; if (tf->ty == Tfunction) deprecation("use of %s%s hidden by %s is deprecated. Use 'alias %s.%s %s;' to introduce base class overload set.", fd->toPrettyChars(), Parameter::argsTypesToChars(tf->parameters, tf->varargs), toChars(), fd->parent->toChars(), fd->toChars(), fd->toChars()); else deprecation("use of %s hidden by %s is deprecated", fd->toPrettyChars(), toChars()); s = rtlsym[RTLSYM_DHIDDENFUNC]; break; } } } dtxoff(&dt, s, 0, TYnptr); } else dtsize_t(&dt, 0); } vtblsym->Sdt = dt; vtblsym->Sclass = scclass; vtblsym->Sfl = FLdata; out_readonly(vtblsym); outdata(vtblsym); if (isExport()) objmod->export_symbol(vtblsym,0); }