int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) { int result = 0; if (names.dim == 0) return Dsymbol::addMember(sc, sd, memnum); if (aliasId) result = Dsymbol::addMember(sc, sd, memnum); /* Instead of adding the import to sd's symbol table, * add each of the alias=name pairs */ for (size_t i = 0; i < names.dim; i++) { Identifier *name = names[i]; Identifier *alias = aliases[i]; if (!alias) alias = name; TypeIdentifier *tname = new TypeIdentifier(loc, name); AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname); result |= ad->addMember(sc, sd, memnum); aliasdecls.push(ad); } return result; }
int Import::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) { int result = 0; if (names.dim == 0) return Dsymbol::addMember(sc, sd, memnum); if (aliasId) result = Dsymbol::addMember(sc, sd, memnum); for (size_t i = 0; i < names.dim; i++) { Identifier *name = (Identifier *)names.data[i]; Identifier *alias = (Identifier *)aliases.data[i]; if (!alias) alias = name; #if 1 TypeIdentifier *tname = new TypeIdentifier(loc, name); #else TypeIdentifier *tname = new TypeIdentifier(loc, NULL); if (packages) { for (size_t j = 0; j < packages->dim; j++) { Identifier *pid = (Identifier *)packages->data[j]; if (!tname->ident) tname->ident = pid; else tname->addIdent(pid); } } if (!tname->ident) tname->ident = id; else tname->addIdent(id); tname->addIdent(name); #endif AliasDeclaration *ad = new AliasDeclaration(loc, alias, tname); result |= ad->addMember(sc, sd, memnum); aliasdecls.push(ad); } return result; }
/***************************************** * Create inclusive destructor for struct/class by aggregating * all the destructors in dtors[] with the destructors for * all the members. * Note the close similarity with StructDeclaration::buildPostBlit(), * and the ordering changes (runs backward instead of forwards). */ FuncDeclaration *buildDtor(AggregateDeclaration *ad, Scope *sc) { //printf("AggregateDeclaration::buildDtor() %s\n", ad->toChars()); StorageClass stc = STCsafe | STCnothrow | STCpure | STCnogc; Loc declLoc = ad->dtors.dim ? ad->dtors[0]->loc : ad->loc; Loc loc = Loc(); // internal code should have no loc to prevent coverage Expression *e = NULL; for (size_t i = 0; i < ad->fields.dim; i++) { VarDeclaration *v = ad->fields[i]; if (v->storage_class & STCref) continue; Type *tv = v->type->baseElemOf(); if (tv->ty != Tstruct || !v->type->size()) continue; StructDeclaration *sdv = ((TypeStruct *)tv)->sym; if (!sdv->dtor) continue; sdv->dtor->functionSemantic(); stc = mergeFuncAttrs(stc, sdv->dtor); if (stc & STCdisable) { e = NULL; break; } Expression *ex = new ThisExp(loc); ex = new DotVarExp(loc, ex, v, 0); if (v->type->toBasetype()->ty == Tstruct) { // this.v.__xdtor() // This is a hack so we can call destructors on const/immutable objects. ex = new AddrExp(loc, ex); ex = new CastExp(loc, ex, v->type->mutableOf()->pointerTo()); ex = new PtrExp(loc, ex); if (stc & STCsafe) stc = (stc & ~STCsafe) | STCtrusted; ex = new DotVarExp(loc, ex, sdv->dtor, 0); ex = new CallExp(loc, ex); } else { // _ArrayDtor((cast(S*)this.v.ptr)[0 .. n]) // This is a hack so we can call destructors on const/immutable objects. ex = new DotIdExp(loc, ex, Id::ptr); ex = new CastExp(loc, ex, sdv->type->pointerTo()); if (stc & STCsafe) stc = (stc & ~STCsafe) | STCtrusted; uinteger_t n = v->type->size() / sdv->type->size(); ex = new SliceExp(loc, ex, new IntegerExp(loc, 0, Type::tsize_t), new IntegerExp(loc, n, Type::tsize_t)); // Prevent redundant bounds check ((SliceExp *)ex)->upperIsInBounds = true; ((SliceExp *)ex)->lowerIsLessThanUpper = true; ex = new CallExp(loc, new IdentifierExp(loc, Id::_ArrayDtor), ex); } e = Expression::combine(ex, e); // combine in reverse order } /* Build our own "destructor" which executes e */ if (e || (stc & STCdisable)) { //printf("Building __fieldDtor()\n"); DtorDeclaration *dd = new DtorDeclaration(declLoc, Loc(), stc, Id::__fieldDtor); dd->storage_class |= STCinference; dd->fbody = new ExpStatement(loc, e); ad->dtors.shift(dd); ad->members->push(dd); dd->semantic(sc); } FuncDeclaration *xdtor = NULL; switch (ad->dtors.dim) { case 0: break; case 1: xdtor = ad->dtors[0]; break; default: e = NULL; stc = STCsafe | STCnothrow | STCpure | STCnogc; for (size_t i = 0; i < ad->dtors.dim; i++) { FuncDeclaration *fd = ad->dtors[i]; stc = mergeFuncAttrs(stc, fd); if (stc & STCdisable) { e = NULL; break; } Expression *ex = new ThisExp(loc); ex = new DotVarExp(loc, ex, fd, 0); ex = new CallExp(loc, ex); e = Expression::combine(ex, e); } DtorDeclaration *dd = new DtorDeclaration(declLoc, Loc(), stc, Id::__aggrDtor); dd->storage_class |= STCinference; dd->fbody = new ExpStatement(loc, e); ad->members->push(dd); dd->semantic(sc); xdtor = dd; break; } // Add an __xdtor alias to make the inclusive dtor accessible if (xdtor) { AliasDeclaration *alias = new AliasDeclaration(Loc(), Id::__xdtor, xdtor); alias->semantic(sc); ad->members->push(alias); alias->addMember(sc, ad); // add to symbol table } return xdtor; }
/***************************************** * Create inclusive postblit for struct by aggregating * all the postblits in postblits[] with the postblits for * all the members. * Note the close similarity with AggregateDeclaration::buildDtor(), * and the ordering changes (runs forward instead of backwards). */ FuncDeclaration *buildPostBlit(StructDeclaration *sd, Scope *sc) { //printf("StructDeclaration::buildPostBlit() %s\n", sd->toChars()); StorageClass stc = STCsafe | STCnothrow | STCpure | STCnogc; Loc declLoc = sd->postblits.dim ? sd->postblits[0]->loc : sd->loc; Loc loc = Loc(); // internal code should have no loc to prevent coverage for (size_t i = 0; i < sd->postblits.dim; i++) { stc |= sd->postblits[i]->storage_class & STCdisable; } Statements *a = NULL; for (size_t i = 0; i < sd->fields.dim && !(stc & STCdisable); i++) { VarDeclaration *v = sd->fields[i]; if (v->storage_class & STCref) continue; Type *tv = v->type->baseElemOf(); if (tv->ty != Tstruct || !v->type->size()) continue; StructDeclaration *sdv = ((TypeStruct *)tv)->sym; if (!sdv->postblit) continue; sdv->postblit->functionSemantic(); stc = mergeFuncAttrs(stc, sdv->postblit); stc = mergeFuncAttrs(stc, sdv->dtor); if (stc & STCdisable) { a = NULL; break; } if (!a) a = new Statements(); Expression *ex = new ThisExp(loc); ex = new DotVarExp(loc, ex, v, 0); if (v->type->toBasetype()->ty == Tstruct) { // this.v.__xpostblit() // This is a hack so we can call postblits on const/immutable objects. ex = new AddrExp(loc, ex); ex = new CastExp(loc, ex, v->type->mutableOf()->pointerTo()); ex = new PtrExp(loc, ex); if (stc & STCsafe) stc = (stc & ~STCsafe) | STCtrusted; ex = new DotVarExp(loc, ex, sdv->postblit, 0); ex = new CallExp(loc, ex); } else { // _ArrayPostblit((cast(S*)this.v.ptr)[0 .. n]) // This is a hack so we can call postblits on const/immutable objects. ex = new DotIdExp(loc, ex, Id::ptr); ex = new CastExp(loc, ex, sdv->type->pointerTo()); if (stc & STCsafe) stc = (stc & ~STCsafe) | STCtrusted; uinteger_t n = v->type->size() / sdv->type->size(); ex = new SliceExp(loc, ex, new IntegerExp(loc, 0, Type::tsize_t), new IntegerExp(loc, n, Type::tsize_t)); // Prevent redundant bounds check ((SliceExp *)ex)->upperIsInBounds = true; ((SliceExp *)ex)->lowerIsLessThanUpper = true; ex = new CallExp(loc, new IdentifierExp(loc, Id::_ArrayPostblit), ex); } a->push(new ExpStatement(loc, ex)); // combine in forward order /* Bugzilla 10972: When the following field postblit calls fail, * this field should be destructed for Exception Safety. */ if (!sdv->dtor) continue; sdv->dtor->functionSemantic(); ex = new ThisExp(loc); ex = new DotVarExp(loc, ex, v, 0); if (v->type->toBasetype()->ty == Tstruct) { // this.v.__xdtor() // This is a hack so we can call destructors on const/immutable objects. ex = new AddrExp(loc, ex); ex = new CastExp(loc, ex, v->type->mutableOf()->pointerTo()); ex = new PtrExp(loc, ex); if (stc & STCsafe) stc = (stc & ~STCsafe) | STCtrusted; ex = new DotVarExp(loc, ex, sdv->dtor, 0); ex = new CallExp(loc, ex); } else { // _ArrayDtor((cast(S*)this.v.ptr)[0 .. n]) // This is a hack so we can call destructors on const/immutable objects. ex = new DotIdExp(loc, ex, Id::ptr); ex = new CastExp(loc, ex, sdv->type->pointerTo()); if (stc & STCsafe) stc = (stc & ~STCsafe) | STCtrusted; uinteger_t n = v->type->size() / sdv->type->size(); ex = new SliceExp(loc, ex, new IntegerExp(loc, 0, Type::tsize_t), new IntegerExp(loc, n, Type::tsize_t)); // Prevent redundant bounds check ((SliceExp *)ex)->upperIsInBounds = true; ((SliceExp *)ex)->lowerIsLessThanUpper = true; ex = new CallExp(loc, new IdentifierExp(loc, Id::_ArrayDtor), ex); } a->push(new OnScopeStatement(loc, TOKon_scope_failure, new ExpStatement(loc, ex))); } /* Build our own "postblit" which executes a */ if (a || (stc & STCdisable)) { //printf("Building __fieldPostBlit()\n"); PostBlitDeclaration *dd = new PostBlitDeclaration(declLoc, Loc(), stc, Id::__fieldPostblit); dd->storage_class |= STCinference; dd->fbody = a ? new CompoundStatement(loc, a) : NULL; sd->postblits.shift(dd); sd->members->push(dd); dd->semantic(sc); } FuncDeclaration *xpostblit = NULL; switch (sd->postblits.dim) { case 0: break; case 1: xpostblit = sd->postblits[0]; break; default: Expression *e = NULL; stc = STCsafe | STCnothrow | STCpure | STCnogc; for (size_t i = 0; i < sd->postblits.dim; i++) { FuncDeclaration *fd = sd->postblits[i]; stc = mergeFuncAttrs(stc, fd); if (stc & STCdisable) { e = NULL; break; } Expression *ex = new ThisExp(loc); ex = new DotVarExp(loc, ex, fd, 0); ex = new CallExp(loc, ex); e = Expression::combine(e, ex); } PostBlitDeclaration *dd = new PostBlitDeclaration(declLoc, Loc(), stc, Id::__aggrPostblit); dd->storage_class |= STCinference; dd->fbody = new ExpStatement(loc, e); sd->members->push(dd); dd->semantic(sc); xpostblit = dd; break; } // Add an __xpostblit alias to make the inclusive postblit accessible if (xpostblit) { AliasDeclaration *alias = new AliasDeclaration(Loc(), Id::__xpostblit, xpostblit); alias->semantic(sc); sd->members->push(alias); alias->addMember(sc, sd); // add to symbol table } return xpostblit; }