void StructDeclaration::toDt(dt_t **pdt) { if (zeroInit) { dtnzeros(pdt, structsize); return; } unsigned offset; dt_t *dt; dt_t *sdt = NULL; //printf("StructDeclaration::toDt(), this='%s'\n", toChars()); offset = 0; // Note equivalence of this loop to class's for (size_t i = 0; i < fields.dim; i++) { VarDeclaration *v = (VarDeclaration *)fields.data[i]; Initializer *init; //printf("\tfield '%s' voffset %d, offset = %d\n", v->toChars(), v->offset, offset); dt = NULL; init = v->init; if (init) { //printf("\t\thas initializer %s\n", init->toChars()); ExpInitializer *ei = init->isExpInitializer(); Type *tb = v->type->toBasetype(); if (ei && tb->ty == Tsarray) ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); else dt = init->toDt(); } else if (v->offset >= offset) v->type->toDt(&dt); if (dt) { if (v->offset < offset) error("overlapping initialization for struct %s.%s", toChars(), v->toChars()); else { if (offset < v->offset) dtnzeros(&sdt, v->offset - offset); dtcat(&sdt, dt); offset = v->offset + v->type->size(); } } } if (offset < structsize) dtnzeros(&sdt, structsize - offset); #ifdef IN_GCC dtcontainer(pdt, type, sdt); #else dtcat(pdt, sdt); #endif dt_optimize(*pdt); }
void StructDeclaration::toDt(dt_t **pdt) { unsigned offset; unsigned i; dt_t *dt; //printf("StructDeclaration::toDt(), this='%s'\n", toChars()); offset = 0; // Note equivalence of this loop to class's for (i = 0; i < fields.dim; i++) { VarDeclaration *v = (VarDeclaration *)fields.data[i]; //printf("\tfield '%s' voffset %d, offset = %d\n", v->toChars(), v->offset, offset); dt = NULL; int sz; if (v->storage_class & STCref) { sz = PTRSIZE; if (v->offset >= offset) dtnzeros(&dt, sz); } else { sz = v->type->size(); Initializer *init = v->init; if (init) { //printf("\t\thas initializer %s\n", init->toChars()); ExpInitializer *ei = init->isExpInitializer(); Type *tb = v->type->toBasetype(); if (ei && tb->ty == Tsarray) ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); else dt = init->toDt(); } else if (v->offset >= offset) v->type->toDt(&dt); } if (dt) { if (v->offset < offset) error("overlapping initialization for struct %s.%s", toChars(), v->toChars()); else { if (offset < v->offset) dtnzeros(pdt, v->offset - offset); dtcat(pdt, dt); offset = v->offset + sz; } } } if (offset < structsize) dtnzeros(pdt, structsize - offset); dt_optimize(*pdt); }
bool isImplicit(Initializer& init) { if (ExpInitializer* expInit = init.isExpInitializer()) { if (expInit->exp) { return expInit->exp->op == TOKblit; } } return false; }
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) { unsigned i; unsigned length; const unsigned amax = 0x80000000; //printf("ArrayInitializer::semantic(%s)\n", t->toChars()); if (sem) // if semantic() already run return this; sem = 1; type = t; t = t->toBasetype(); switch (t->ty) { case Tpointer: case Tsarray: case Tarray: break; case Tvector: t = ((TypeVector *)t)->basetype; break; default: error(loc, "cannot use array to initialize %s", type->toChars()); goto Lerr; } length = 0; for (i = 0; i < index.dim; i++) { Expression *idx = index[i]; if (idx) { idx = idx->semantic(sc); idx = idx->ctfeInterpret(); index[i] = idx; length = idx->toInteger(); } Initializer *val = value[i]; ExpInitializer *ei = val->isExpInitializer(); if (ei && !idx) ei->expandTuples = 1; val = val->semantic(sc, t->nextOf(), needInterpret); ei = val->isExpInitializer(); // found a tuple, expand it if (ei && ei->exp->op == TOKtuple) { TupleExp *te = (TupleExp *)ei->exp; index.remove(i); value.remove(i); for (size_t j = 0; j < te->exps->dim; ++j) { Expression *e = (*te->exps)[j]; index.insert(i + j, (Expression *)NULL); value.insert(i + j, new ExpInitializer(e->loc, e)); } i--; continue; } else { value[i] = val; } length++; if (length == 0) { error(loc, "array dimension overflow"); goto Lerr; } if (length > dim) dim = length; } if (t->ty == Tsarray) { dinteger_t edim = ((TypeSArray *)t)->dim->toInteger(); if (dim > edim) { error(loc, "array initializer has %u elements, but array length is %lld", dim, edim); goto Lerr; } } if ((unsigned long) dim * t->nextOf()->size() >= amax) { error(loc, "array dimension %u exceeds max of %u", dim, amax / t->nextOf()->size()); goto Lerr; } return this; Lerr: return new ExpInitializer(loc, new ErrorExp()); }
void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd) { unsigned offset; dt_t *dt; unsigned csymoffset; #define LOG 0 #if LOG printf("ClassDeclaration::toDt2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); #endif if (baseClass) { baseClass->toDt2(pdt, cd); offset = baseClass->structsize; } else { offset = PTRSIZE * 2; } // Note equivalence of this loop to struct's for (size_t i = 0; i < fields.dim; i++) { VarDeclaration *v = (VarDeclaration *)fields.data[i]; Initializer *init; //printf("\t\tv = '%s' v->offset = %2d, offset = %2d\n", v->toChars(), v->offset, offset); dt = NULL; init = v->init; if (init) { //printf("\t\t%s has initializer %s\n", v->toChars(), init->toChars()); ExpInitializer *ei = init->isExpInitializer(); Type *tb = v->type->toBasetype(); if (ei && tb->ty == Tsarray) ((TypeSArray *)tb)->toDtElem(&dt, ei->exp); else dt = init->toDt(); } else if (v->offset >= offset) { //printf("\t\tdefault initializer\n"); v->type->toDt(&dt); } if (dt) { if (v->offset < offset) error("duplicated union initialization for %s", v->toChars()); else { if (offset < v->offset) dtnzeros(pdt, v->offset - offset); dtcat(pdt, dt); offset = v->offset + v->type->size(); } } } // Interface vptr initializations toSymbol(); // define csym for (size_t i = 0; i < vtblInterfaces->dim; i++) { BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; #if 1 || INTERFACE_VIRTUAL for (ClassDeclaration *cd2 = cd; 1; cd2 = cd2->baseClass) { assert(cd2); csymoffset = cd2->baseVtblOffset(b); if (csymoffset != ~0) { if (offset < b->offset) dtnzeros(pdt, b->offset - offset); dtxoff(pdt, cd2->toSymbol(), csymoffset, TYnptr); break; } } #else csymoffset = baseVtblOffset(b); assert(csymoffset != ~0); dtxoff(pdt, csym, csymoffset, TYnptr); #endif offset = b->offset + PTRSIZE; } if (offset < structsize) dtnzeros(pdt, structsize - offset); #undef LOG }
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) { size_t length; const unsigned amax = 0x80000000; bool errors = false; //printf("ArrayInitializer::semantic(%s)\n", t->toChars()); if (sem) // if semantic() already run return this; sem = true; t = t->toBasetype(); switch (t->ty) { case Tsarray: case Tarray: break; case Tvector: t = ((TypeVector *)t)->basetype; break; case Taarray: case Tstruct: // consider implicit constructor call { Expression *e; if (t->ty == Taarray || isAssociativeArray()) e = toAssocArrayLiteral(); else e = toExpression(); ExpInitializer *ei = new ExpInitializer(e->loc, e); return ei->semantic(sc, t, needInterpret); } case Tpointer: if (t->nextOf()->ty != Tfunction) break; default: error(loc, "cannot use array to initialize %s", t->toChars()); goto Lerr; } type = t; length = 0; for (size_t i = 0; i < index.dim; i++) { Expression *idx = index[i]; if (idx) { sc = sc->startCTFE(); idx = idx->semantic(sc); sc = sc->endCTFE(); idx = idx->ctfeInterpret(); index[i] = idx; length = (size_t)idx->toInteger(); if (idx->op == TOKerror) errors = true; } Initializer *val = value[i]; ExpInitializer *ei = val->isExpInitializer(); if (ei && !idx) ei->expandTuples = true; val = val->semantic(sc, t->nextOf(), needInterpret); if (val->isErrorInitializer()) errors = true; ei = val->isExpInitializer(); // found a tuple, expand it if (ei && ei->exp->op == TOKtuple) { TupleExp *te = (TupleExp *)ei->exp; index.remove(i); value.remove(i); for (size_t j = 0; j < te->exps->dim; ++j) { Expression *e = (*te->exps)[j]; index.insert(i + j, (Expression *)NULL); value.insert(i + j, new ExpInitializer(e->loc, e)); } i--; continue; } else { value[i] = val; } length++; if (length == 0) { error(loc, "array dimension overflow"); goto Lerr; } if (length > dim) dim = length; } if (t->ty == Tsarray) { dinteger_t edim = ((TypeSArray *)t)->dim->toInteger(); if (dim > edim) { error(loc, "array initializer has %u elements, but array length is %lld", dim, edim); goto Lerr; } } if (errors) goto Lerr; if ((uinteger_t) dim * t->nextOf()->size() >= amax) { error(loc, "array dimension %u exceeds max of %u", (unsigned) dim, (unsigned)(amax / t->nextOf()->size())); goto Lerr; } return this; Lerr: return new ErrorInitializer(); }
Initializer *ArrayInitializer::inferType(Scope *sc) { //printf("ArrayInitializer::inferType() %s\n", toChars()); Expressions *keys = NULL; Expressions *values; if (isAssociativeArray()) { keys = new Expressions(); keys->setDim(value.dim); values = new Expressions(); values->setDim(value.dim); for (size_t i = 0; i < value.dim; i++) { Expression *e = index[i]; if (!e) goto Lno; (*keys)[i] = e; Initializer *iz = value[i]; if (!iz) goto Lno; iz = iz->inferType(sc); if (iz->isErrorInitializer()) return iz; assert(iz->isExpInitializer()); (*values)[i] = ((ExpInitializer *)iz)->exp; assert((*values)[i]->op != TOKerror); } Expression *e = new AssocArrayLiteralExp(loc, keys, values); ExpInitializer *ei = new ExpInitializer(loc, e); return ei->inferType(sc); } else { Expressions *elements = new Expressions(); elements->setDim(value.dim); elements->zero(); for (size_t i = 0; i < value.dim; i++) { assert(!index[i]); // already asserted by isAssociativeArray() Initializer *iz = value[i]; if (!iz) goto Lno; iz = iz->inferType(sc); if (iz->isErrorInitializer()) return iz; assert(iz->isExpInitializer()); (*elements)[i] = ((ExpInitializer *)iz)->exp; assert((*elements)[i]->op != TOKerror); } Expression *e = new ArrayLiteralExp(loc, elements); ExpInitializer *ei = new ExpInitializer(loc, e); return ei->inferType(sc); } Lno: if (keys) { delete keys; delete values; error(loc, "not an associative array initializer"); } else { error(loc, "cannot infer type from array initializer"); } return new ErrorInitializer(); }
Initializer *ArrayInitializer::inferType(Scope *sc, Type *tx) { //printf("ArrayInitializer::inferType() %s\n", toChars()); Expressions *keys = NULL; Expressions *values; if (tx ? (tx->ty == Taarray || tx->ty != Tarray && tx->ty != Tsarray && isAssociativeArray()) : isAssociativeArray()) { Type *tidx = NULL; Type *tval = NULL; if (tx && tx->ty == Taarray) { tidx = ((TypeAArray *)tx)->index; tval = ((TypeAArray *)tx)->next; } keys = new Expressions(); keys->setDim(value.dim); values = new Expressions(); values->setDim(value.dim); for (size_t i = 0; i < value.dim; i++) { Expression *e = index[i]; if (!e) goto Lno; if (tidx) { e = ::inferType(e, tidx); e = e->semantic(sc); e = resolveProperties(sc, e); if (tidx->deco) // tidx may be partial type e = e->implicitCastTo(sc, tidx); } (*keys)[i] = e; Initializer *iz = value[i]; if (!iz) goto Lno; iz = iz->inferType(sc, tval); if (iz->isErrorInitializer()) return iz; assert(iz->isExpInitializer()); (*values)[i] = ((ExpInitializer *)iz)->exp; assert((*values)[i]->op != TOKerror); } Expression *e = new AssocArrayLiteralExp(loc, keys, values); ExpInitializer *ei = new ExpInitializer(loc, e); return ei->inferType(sc, tx); } else { Type *tn = NULL; if (tx && (tx->ty == Tarray || tx->ty == Tsarray)) tn = ((TypeNext *)tx)->next; Expressions *elements = new Expressions(); elements->setDim(value.dim); elements->zero(); for (size_t i = 0; i < value.dim; i++) { assert(!index[i]); // already asserted by isAssociativeArray() Initializer *iz = value[i]; if (!iz) goto Lno; iz = iz->inferType(sc, tn); if (iz->isErrorInitializer()) return iz; assert(iz->isExpInitializer()); (*elements)[i] = ((ExpInitializer *)iz)->exp; assert((*elements)[i]->op != TOKerror); } Expression *e = new ArrayLiteralExp(loc, elements); ExpInitializer *ei = new ExpInitializer(loc, e); return ei->inferType(sc, tx); } Lno: if (keys) { delete keys; delete values; error(loc, "not an associative array initializer"); } else { error(loc, "cannot infer type from array initializer"); } return new ErrorInitializer(); }