void ConditionalDeclaration::addComment(unsigned char *comment) { /* Because addComment is called by the parser, if we called * include() it would define a version before it was used. * But it's no problem to drill down to both decl and elsedecl, * so that's the workaround. */ if (comment) { Dsymbols *d = decl; for (int j = 0; j < 2; j++) { if (d) { for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s; s = d->tdata()[i]; //printf("ConditionalDeclaration::addComment %s\n", s->toChars()); s->addComment(comment); } } d = elsedecl; } } }
FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) { //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars()); ClassDeclaration *cd = this; Dsymbols *vtbl = &cd->vtbl; while (1) { for (size_t i = 0; i < vtbl->dim; i++) { FuncDeclaration *fd = vtbl->tdata()[i]->isFuncDeclaration(); if (!fd) continue; // the first entry might be a ClassInfo //printf("\t[%d] = %s\n", i, fd->toChars()); if (ident == fd->ident && //tf->equals(fd->type) fd->type->covariant(tf) == 1 ) { //printf("\t\tfound\n"); return fd; } //else printf("\t\t%d\n", fd->type->covariant(tf)); } if (!cd) break; vtbl = &cd->vtblFinal; cd = cd->baseClass; } return NULL; }
void AttribDeclaration::toObjFile(int multiobj) { Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; s->toObjFile(multiobj); } } }
void AttribDeclaration::checkCtorConstInit() { Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; s->checkCtorConstInit(); } } }
void AttribDeclaration::semantic3(Scope *sc) { Dsymbols *d = include(sc, NULL); if (d) { for (size_t i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; s->semantic3(sc); } } }
void AttribDeclaration::addLocalClass(ClassDeclarations *aclasses) { Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; s->addLocalClass(aclasses); } } }
void AttribDeclaration::inlineScan() { Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; //printf("AttribDeclaration::inlineScan %s\n", s->toChars()); s->inlineScan(); } } }
void AttribDeclaration::semantic(Scope *sc) { Dsymbols *d = include(sc, NULL); //printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d); if (d) { for (size_t i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; s->semantic(sc); } } }
int AttribDeclaration::addMember(Scope *sc, ScopeDsymbol *sd, int memnum) { int m = 0; Dsymbols *d = include(sc, sd); if (d) { for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; //printf("\taddMember %s to %s\n", s->toChars(), sd->toChars()); m |= s->addMember(sc, sd, m | memnum); } } return m; }
int AttribDeclaration::hasPointers() { Dsymbols *d = include(NULL, NULL); if (d) { for (size_t i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; if (s->hasPointers()) return 1; } } return 0; }
void ConditionalDeclaration::importAll(Scope *sc) { Dsymbols *d = include(sc, NULL); //printf("\tConditionalDeclaration::importAll '%s', d = %p\n",toChars(), d); if (d) { for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; s->importAll(sc); } } }
void AttribDeclaration::addComment(unsigned char *comment) { //printf("AttribDeclaration::addComment %s\n", comment); if (comment) { Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; //printf("AttribDeclaration::addComment %s\n", s->toChars()); s->addComment(comment); } } } }
int AttribDeclaration::cvMember(unsigned char *p) { int nwritten = 0; int n; Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; n = s->cvMember(p); if (p) p += n; nwritten += n; } } return nwritten; }
void ConditionalDeclaration::emitComment(Scope *sc) { //printf("ConditionalDeclaration::emitComment(sc = %p)\n", sc); if (condition->inc) { AttribDeclaration::emitComment(sc); } else if (sc->docbuf) { /* If generating doc comment, be careful because if we're inside * a template, then include(NULL, NULL) will fail. */ Dsymbols *d = decl ? decl : elsedecl; for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; s->emitComment(sc); } } }
void StaticIfDeclaration::semantic(Scope *sc) { Dsymbols *d = include(sc, sd); //printf("\tStaticIfDeclaration::semantic '%s', d = %p\n",toChars(), d); if (d) { if (!addisdone) { AttribDeclaration::addMember(sc, sd, 1); addisdone = 1; } for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; s->semantic(sc); } } }
void AttribDeclaration::emitComment(Scope *sc) { //printf("AttribDeclaration::emitComment(sc = %p)\n", sc); /* A general problem with this, illustrated by BUGZILLA 2516, * is that attributes are not transmitted through to the underlying * member declarations for template bodies, because semantic analysis * is not done for template declaration bodies * (only template instantiations). * Hence, Ddoc omits attributes from template members. */ Dsymbols *d = include(NULL, NULL); if (d) { for (unsigned i = 0; i < d->dim; i++) { Dsymbol *s = d->tdata()[i]; //printf("AttribDeclaration::emitComment %s\n", s->toChars()); s->emitComment(sc); } } }
void obj_append(Dsymbol *s) { obj_symbols_towrite.push(s); }
FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc) { if (FuncDeclaration *f = hasIdentityOpAssign(sc)) { hasIdentityAssign = 1; return f; } // Even if non-identity opAssign is defined, built-in identity opAssign // will be defined. if (!needOpAssign()) return NULL; //printf("StructDeclaration::buildOpAssign() %s\n", toChars()); StorageClass stc = STCsafe | STCnothrow | STCpure; Loc declLoc = this->loc; Loc loc = Loc(); // internal code should have no loc to prevent coverage if (dtor || postblit) { if (dtor) stc = mergeFuncAttrs(stc, dtor->storage_class); } else { for (size_t i = 0; i < fields.dim; i++) { Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v && v->isField()); if (v->storage_class & STCref) continue; Type *tv = v->type->toBasetype(); while (tv->ty == Tsarray) { TypeSArray *ta = (TypeSArray *)tv; tv = tv->nextOf()->toBasetype(); } if (tv->ty == Tstruct) { TypeStruct *ts = (TypeStruct *)tv; StructDeclaration *sd = ts->sym; if (FuncDeclaration *f = sd->hasIdentityOpAssign(sc)) stc = mergeFuncAttrs(stc, f->storage_class); } } } Parameters *fparams = new Parameters; fparams->push(new Parameter(STCnodtor, type, Id::p, NULL)); Type *tf = new TypeFunction(fparams, handle, 0, LINKd, stc | STCref); FuncDeclaration *fop = new FuncDeclaration(declLoc, Loc(), Id::assign, stc, tf); Expression *e = NULL; if (stc & STCdisable) { } else if (dtor || postblit) { /* Do swap this and rhs * tmp = this; this = s; tmp.dtor(); */ //printf("\tswap copy\n"); Identifier *idtmp = Lexer::uniqueId("__tmp"); VarDeclaration *tmp; AssignExp *ec = NULL; if (dtor) { tmp = new VarDeclaration(loc, type, idtmp, new VoidInitializer(loc)); tmp->noscope = 1; tmp->storage_class |= STCctfe; e = new DeclarationExp(loc, tmp); ec = new AssignExp(loc, new VarExp(loc, tmp), new ThisExp(loc) ); ec->op = TOKblit; e = Expression::combine(e, ec); } ec = new AssignExp(loc, new ThisExp(loc), new IdentifierExp(loc, Id::p)); ec->op = TOKblit; e = Expression::combine(e, ec); if (dtor) { /* Instead of running the destructor on s, run it * on tmp. This avoids needing to copy tmp back in to s. */ Expression *ec2 = new DotVarExp(loc, new VarExp(loc, tmp), dtor, 0); ec2 = new CallExp(loc, ec2); e = Expression::combine(e, ec2); } } else { /* Do memberwise copy */ //printf("\tmemberwise copy\n"); for (size_t i = 0; i < fields.dim; i++) { Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v && v->isField()); // this.v = s.v; AssignExp *ec = new AssignExp(loc, new DotVarExp(loc, new ThisExp(loc), v, 0), new DotVarExp(loc, new IdentifierExp(loc, Id::p), v, 0)); e = Expression::combine(e, ec); } } if (e) { Statement *s1 = new ExpStatement(loc, e); /* Add: * return this; */ e = new ThisExp(loc); Statement *s2 = new ReturnStatement(loc, e); fop->fbody = new CompoundStatement(loc, s1, s2); } Dsymbol *s = fop; #if 1 // workaround until fixing issue 1528 Dsymbol *assign = search_function(this, Id::assign); if (assign && assign->isTemplateDeclaration()) { // Wrap a template around the function declaration TemplateParameters *tpl = new TemplateParameters(); Dsymbols *decldefs = new Dsymbols(); decldefs->push(s); TemplateDeclaration *tempdecl = new TemplateDeclaration(assign->loc, fop->ident, tpl, NULL, decldefs, 0); s = tempdecl; } #endif members->push(s); s->addMember(sc, this, 1); this->hasIdentityAssign = 1; // temporary mark identity assignable unsigned errors = global.startGagging(); // Do not report errors, even if the unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. global.speculativeGag = global.gag; Scope *sc2 = sc->push(); sc2->stc = 0; sc2->linkage = LINKd; sc2->speculative = true; s->semantic(sc2); s->semantic2(sc2); s->semantic3(sc2); sc2->pop(); global.speculativeGag = oldspec; if (global.endGagging(errors)) // if errors happened { // Disable generated opAssign, because some members forbid identity assignment. fop->storage_class |= STCdisable; fop->fbody = NULL; // remove fbody which contains the error } //printf("-StructDeclaration::buildOpAssign() %s %s, errors = %d\n", toChars(), s->kind(), (fop->storage_class & STCdisable) != 0); return fop; }
void obj_write_deferred(Library *library) { for (size_t i = 0; i < obj_symbols_towrite.dim; i++) { Dsymbol *s = obj_symbols_towrite.tdata()[i]; Module *m = s->getModule(); char *mname; if (m) { mname = m->srcfile->toChars(); lastmname = mname; } else { //mname = s->ident->toChars(); mname = lastmname; assert(mname); } obj_start(mname); static int count; count++; // sequence for generating names /* Create a module that's a doppelganger of m, with just * enough to be able to create the moduleinfo. */ OutBuffer idbuf; idbuf.printf("%s.%d", m ? m->ident->toChars() : mname, count); char *idstr = idbuf.toChars(); idbuf.data = NULL; Identifier *id = new Identifier(idstr, TOKidentifier); Module *md = new Module(mname, id, 0, 0); md->members = new Dsymbols(); md->members->push(s); // its only 'member' is s if (m) { md->doppelganger = 1; // identify this module as doppelganger md->md = m->md; md->aimports.push(m); // it only 'imports' m md->massert = m->massert; md->munittest = m->munittest; md->marray = m->marray; } md->genobjfile(0); /* Set object file name to be source name with sequence number, * as mangled symbol names get way too long. */ char *fname = FileName::removeExt(mname); OutBuffer namebuf; unsigned hash = 0; for (char *p = s->toChars(); *p; p++) hash += *p; namebuf.printf("%s_%x_%x.%s", fname, count, hash, global.obj_ext); namebuf.writeByte(0); mem.free(fname); fname = (char *)namebuf.extractData(); //printf("writing '%s'\n", fname); File *objfile = new File(fname); obj_end(library, objfile); } obj_symbols_towrite.dim = 0; }
void obj_append(Dsymbol *s) { //printf("deferred: %s\n", s->toChars()); obj_symbols_towrite.push(s); }
FuncDeclaration *StructDeclaration::buildOpAssign(Scope *sc) { Dsymbol *assign = search_function(this, Id::assign); if (assign) { if (FuncDeclaration *f = hasIdentityOpAssign(sc, assign)) return f; // Even if non-identity opAssign is defined, built-in identity opAssign // will be defined. (Is this an exception of operator overloading rule?) } if (!needOpAssign()) return NULL; //printf("StructDeclaration::buildOpAssign() %s\n", toChars()); Parameters *fparams = new Parameters; fparams->push(new Parameter(STCnodtor, type, Id::p, NULL)); Type *ftype = new TypeFunction(fparams, handle, FALSE, LINKd); ((TypeFunction *)ftype)->isref = 1; FuncDeclaration *fop = new FuncDeclaration(loc, 0, Id::assign, STCundefined, ftype); Expression *e = NULL; if (postblit) { /* Swap: * tmp = *this; *this = s; tmp.dtor(); */ //printf("\tswap copy\n"); Identifier *idtmp = Lexer::uniqueId("__tmp"); VarDeclaration *tmp; AssignExp *ec = NULL; if (dtor) { tmp = new VarDeclaration(0, type, idtmp, new VoidInitializer(0)); tmp->noscope = 1; tmp->storage_class |= STCctfe; e = new DeclarationExp(0, tmp); ec = new AssignExp(0, new VarExp(0, tmp), new ThisExp(0) ); ec->op = TOKblit; e = Expression::combine(e, ec); } ec = new AssignExp(0, new ThisExp(0), new IdentifierExp(0, Id::p)); ec->op = TOKblit; e = Expression::combine(e, ec); if (dtor) { /* Instead of running the destructor on s, run it * on tmp. This avoids needing to copy tmp back in to s. */ Expression *ec2 = new DotVarExp(0, new VarExp(0, tmp), dtor, 0); ec2 = new CallExp(0, ec2); e = Expression::combine(e, ec2); } } else { /* Do memberwise copy */ //printf("\tmemberwise copy\n"); for (size_t i = 0; i < fields.dim; i++) { Dsymbol *s = fields[i]; VarDeclaration *v = s->isVarDeclaration(); assert(v && v->isField()); // this.v = s.v; AssignExp *ec = new AssignExp(0, new DotVarExp(0, new ThisExp(0), v, 0), new DotVarExp(0, new IdentifierExp(0, Id::p), v, 0)); e = Expression::combine(e, ec); } } Statement *s1 = new ExpStatement(0, e); /* Add: * return this; */ e = new ThisExp(0); Statement *s2 = new ReturnStatement(0, e); fop->fbody = new CompoundStatement(0, s1, s2); Dsymbol *s = fop; if (assign && assign->isTemplateDeclaration()) { // Wrap a template around the function declaration TemplateParameters *tpl = new TemplateParameters(); Dsymbols *decldefs = new Dsymbols(); decldefs->push(s); TemplateDeclaration *tempdecl = new TemplateDeclaration(assign->loc, fop->ident, tpl, NULL, decldefs, 0); s = tempdecl; } members->push(s); s->addMember(sc, this, 1); this->hasIdentityAssign = 1; // temporary mark identity assignable unsigned errors = global.startGagging(); // Do not report errors, even if the unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. global.speculativeGag = global.gag; Scope *sc2 = sc->push(); sc2->stc = 0; sc2->linkage = LINKd; sc2->speculative = true; s->semantic(sc2); s->semantic2(sc2); s->semantic3(sc2); sc2->pop(); global.speculativeGag = oldspec; if (global.endGagging(errors)) // if errors happened { // Disable generated opAssign, because some members forbid identity assignment. fop->storage_class |= STCdisable; fop->fbody = NULL; // remove fbody which contains the error } //printf("-StructDeclaration::buildOpAssign() %s %s, errors = %d\n", toChars(), s->kind(), (fop->storage_class & STCdisable) != 0); return fop; }
FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) { //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars()); FuncDeclaration *fdmatch = NULL; FuncDeclaration *fdambig = NULL; ClassDeclaration *cd = this; Dsymbols *vtbl = &cd->vtbl; while (1) { for (size_t i = 0; i < vtbl->dim; i++) { FuncDeclaration *fd = vtbl->tdata()[i]->isFuncDeclaration(); if (!fd) continue; // the first entry might be a ClassInfo //printf("\t[%d] = %s\n", i, fd->toChars()); if (ident == fd->ident && fd->type->covariant(tf) == 1) { //printf("fd->parent->isClassDeclaration() = %p", fd->parent->isClassDeclaration()); if (!fdmatch) goto Lfd; { // Function type matcing: exact > covariant int m1 = tf->equals(fd ->type) ? MATCHexact : MATCHnomatch; int m2 = tf->equals(fdmatch->type) ? MATCHexact : MATCHnomatch; if (m1 > m2) goto Lfd; else if (m1 < m2) goto Lfdmatch; } { // The way of definition: non-mixin > mixin int m1 = fd ->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch; int m2 = fdmatch->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch; if (m1 > m2) goto Lfd; else if (m1 < m2) goto Lfdmatch; } Lambig: fdambig = fd; //printf("Lambig fdambig = %s %s [%s]\n", fdambig->toChars(), fdambig->type->toChars(), fdambig->loc.toChars()); continue; Lfd: fdmatch = fd, fdambig = NULL; //printf("Lfd fdmatch = %s %s [%s]\n", fdmatch->toChars(), fdmatch->type->toChars(), fdmatch->loc.toChars()); continue; Lfdmatch: continue; } //else printf("\t\t%d\n", fd->type->covariant(tf)); } if (!cd) break; vtbl = &cd->vtblFinal; cd = cd->baseClass; } if (fdambig) error("ambiguous virtual function %s", fdambig->toChars()); return fdmatch; }