Initializer *ArrayInitializer::semantic(Scope *sc, Type *t) { unsigned i; unsigned length; //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; default: //error(loc, "cannot use array to initialize %s", type->toChars()); return this; } length = 0; for (i = 0; i < index.dim; i++) { Expression *idx; Initializer *val; idx = (Expression *)index.data[i]; if (idx) { idx = idx->semantic(sc); idx = idx->optimize(WANTvalue | WANTinterpret); index.data[i] = (void *)idx; length = idx->toInteger(); } val = (Initializer *)value.data[i]; val = val->semantic(sc, t->nextOf()); value.data[i] = (void *)val; length++; /* if (length == 0) error(loc, "array dimension overflow"); */ if (length > dim) dim = length; } unsigned long amax = 0x80000000; /* if ((unsigned long) dim * t->nextOf()->size() >= amax) error(loc, "array dimension %u exceeds max of %ju", dim, amax / t->nextOf()->size()); */ return this; }
Initializer *ArrayInitializer::semantic(Scope *sc, Type *t, int 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; 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->optimize(WANTvalue | WANTinterpret); index[i] = idx; length = idx->toInteger(); } Initializer *val = value[i]; val = val->semantic(sc, t->nextOf(), needInterpret); 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()); }
Initializer *StructInitializer::semantic(Scope *sc, Type *t, int needInterpret) { int errors = 0; //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars()); vars.setDim(field.dim); t = t->toBasetype(); if (t->ty == Tstruct) { unsigned fieldi = 0; TypeStruct *ts = (TypeStruct *)t; ad = ts->sym; if (ad->ctor) error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead", ad->kind(), ad->toChars(), ad->toChars()); StructDeclaration *sd = ad->isStructDeclaration(); assert(sd); sd->size(loc); if (sd->sizeok != SIZEOKdone) { error(loc, "struct %s is forward referenced", sd->toChars()); errors = 1; goto Lerror; } size_t nfields = sd->fields.dim; if (sd->isnested) nfields--; for (size_t i = 0; i < field.dim; i++) { Identifier *id = field[i]; Initializer *val = value[i]; Dsymbol *s; VarDeclaration *v; if (id == NULL) { if (fieldi >= nfields) { error(loc, "too many initializers for %s", ad->toChars()); errors = 1; field.remove(i); i--; continue; } else { s = ad->fields[fieldi]; } } else { //s = ad->symtab->lookup(id); s = ad->search(loc, id, 0); if (!s) { s = ad->search_correct(id); if (s) error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?", id->toChars(), t->toChars(), s->kind(), s->toChars()); else error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars()); errors = 1; continue; } s = s->toAlias(); // Find out which field index it is for (fieldi = 0; 1; fieldi++) { if (fieldi >= nfields) { error(loc, "%s.%s is not a per-instance initializable field", t->toChars(), s->toChars()); errors = 1; break; } if (s == ad->fields[fieldi]) break; } } if (s && (v = s->isVarDeclaration()) != NULL) { val = val->semantic(sc, v->type, needInterpret); value[i] = val; vars[i] = v; } else { error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars()); errors = 1; } fieldi++; } } else if (t->ty == Tdelegate && value.dim == 0) { /* Rewrite as empty delegate literal { } */ Parameters *arguments = new Parameters; Type *tf = new TypeFunction(arguments, NULL, 0, LINKd); FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL); fd->fbody = new CompoundStatement(loc, new Statements()); fd->endloc = loc; Expression *e = new FuncExp(loc, fd); ExpInitializer *ie = new ExpInitializer(loc, e); return ie->semantic(sc, t, needInterpret); } else { error(loc, "a struct is not a valid initializer for a %s", t->toChars()); errors = 1; } Lerror: if (errors) { field.setDim(0); value.setDim(0); vars.setDim(0); } return this; }
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()); }
Initializer *StructInitializer::semantic(Scope *sc, Type *t) { TypeStruct *ts; int errors = 0; //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars()); vars.setDim(field.dim); t = t->toBasetype(); if (t->ty == Tstruct) { unsigned i; unsigned fieldi = 0; ts = (TypeStruct *)t; ad = ts->sym; for (i = 0; i < field.dim; i++) { Identifier *id = (Identifier *)field.data[i]; Initializer *val = (Initializer *)value.data[i]; Dsymbol *s; VarDeclaration *v; if (id == NULL) { if (fieldi >= ad->fields.dim) { //error(loc, "too many initializers for %s", ad->toChars()); field.remove(i); i--; continue; } else { s = (Dsymbol *)ad->fields.data[fieldi]; } } else { //s = ad->symtab->lookup(id); s = ad->search(loc, id, 0); if (!s) { // error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars()); continue; } // Find out which field index it is for (fieldi = 0; 1; fieldi++) { if (fieldi >= ad->fields.dim) { //s->error("is not a per-instance initializable field"); break; } if (s == (Dsymbol *)ad->fields.data[fieldi]) break; } } if (s && (v = s->isVarDeclaration()) != NULL) { val = val->semantic(sc, v->type); value.data[i] = (void *)val; vars.data[i] = (void *)v; } else { //error(loc, "%s is not a field of %s", id ? id->toChars() : s->toChars(), ad->toChars()); errors = 1; } fieldi++; } } else if (t->ty == Tdelegate && value.dim == 0) { /* Rewrite as empty delegate literal { } */ Arguments *arguments = new Arguments; Type *tf = new TypeFunction(arguments, NULL, 0, LINKd); FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, 0, tf, TOKdelegate, NULL); fd->fbody = new CompoundStatement(loc, new Statements()); fd->endloc = loc; Expression *e = new FuncExp(loc, fd); ExpInitializer *ie = new ExpInitializer(loc, e); return ie->semantic(sc, t); } else { //error(loc, "a struct is not a valid initializer for a %s", t->toChars()); errors = 1; } if (errors) { field.setDim(0); value.setDim(0); vars.setDim(0); } return this; }
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 *StructInitializer::semantic(Scope *sc, Type *t, NeedInterpret needInterpret) { //printf("StructInitializer::semantic(t = %s) %s\n", t->toChars(), toChars()); t = t->toBasetype(); if (t->ty == Tsarray && t->nextOf()->toBasetype()->ty == Tstruct) t = t->nextOf()->toBasetype(); if (t->ty == Tstruct) { StructDeclaration *sd = ((TypeStruct *)t)->sym; if (sd->ctor) { error(loc, "%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead", sd->kind(), sd->toChars(), sd->toChars()); return new ErrorInitializer(); } sd->size(loc); if (sd->sizeok != SIZEOKdone) return new ErrorInitializer(); size_t nfields = sd->fields.dim - sd->isNested(); //expandTuples for non-identity arguments? Expressions *elements = new Expressions(); elements->setDim(nfields); for (size_t i = 0; i < elements->dim; i++) (*elements)[i] = NULL; // Run semantic for explicitly given initializers // TODO: this part is slightly different from StructLiteralExp::semantic. bool errors = false; for (size_t fieldi = 0, i = 0; i < field.dim; i++) { if (Identifier *id = field[i]) { Dsymbol *s = sd->search(loc, id); if (!s) { s = sd->search_correct(id); if (s) error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?", id->toChars(), sd->toChars(), s->kind(), s->toChars()); else error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars()); return new ErrorInitializer(); } s = s->toAlias(); // Find out which field index it is for (fieldi = 0; 1; fieldi++) { if (fieldi >= nfields) { error(loc, "%s.%s is not a per-instance initializable field", sd->toChars(), s->toChars()); return new ErrorInitializer(); } if (s == sd->fields[fieldi]) break; } } else if (fieldi >= nfields) { error(loc, "too many initializers for %s", sd->toChars()); return new ErrorInitializer(); } VarDeclaration *vd = sd->fields[fieldi]; if ((*elements)[fieldi]) { error(loc, "duplicate initializer for field '%s'", vd->toChars()); errors = true; continue; } for (size_t j = 0; j < nfields; j++) { VarDeclaration *v2 = sd->fields[j]; bool overlap = (vd->offset < v2->offset + v2->type->size() && v2->offset < vd->offset + vd->type->size()); if (overlap && (*elements)[j]) { error(loc, "overlapping initialization for field %s and %s", v2->toChars(), vd->toChars()); errors = true; continue; } } assert(sc); Initializer *iz = value[i]; iz = iz->semantic(sc, vd->type->addMod(t->mod), needInterpret); Expression *ex = iz->toExpression(); if (ex->op == TOKerror) { errors = true; continue; } value[i] = iz; (*elements)[fieldi] = ex; ++fieldi; } if (errors) return new ErrorInitializer(); StructLiteralExp *sle = new StructLiteralExp(loc, sd, elements, t); if (!sd->fill(loc, elements, false)) return new ErrorInitializer(); sle->type = t; ExpInitializer *ie = new ExpInitializer(loc, sle); return ie->semantic(sc, t, needInterpret); } else if ((t->ty == Tdelegate || t->ty == Tpointer && t->nextOf()->ty == Tfunction) && value.dim == 0) { TOK tok = (t->ty == Tdelegate) ? TOKdelegate : TOKfunction; /* Rewrite as empty delegate literal { } */ Parameters *arguments = new Parameters; Type *tf = new TypeFunction(arguments, NULL, 0, LINKd); FuncLiteralDeclaration *fd = new FuncLiteralDeclaration(loc, Loc(), tf, tok, NULL); fd->fbody = new CompoundStatement(loc, new Statements()); fd->endloc = loc; Expression *e = new FuncExp(loc, fd); ExpInitializer *ie = new ExpInitializer(loc, e); return ie->semantic(sc, t, needInterpret); } error(loc, "a struct is not a valid initializer for a %s", t->toChars()); return new ErrorInitializer(); }
Expression *StructInitializer::fill(Scope *sc, Type *t, NeedInterpret needInterpret) { //printf("StructInitializer::fill(sc = %p, '%s')\n", sc, toChars()); assert(t->ty == Tstruct); StructDeclaration *sd = ((TypeStruct *)t)->sym; sd->size(loc); if (sd->sizeok != SIZEOKdone) return new ErrorExp(); size_t nfields = sd->fields.dim - sd->isNested(); Expressions *elements = new Expressions(); elements->setDim(nfields); for (size_t i = 0; i < elements->dim; i++) (*elements)[i] = NULL; // Run semantic for explicitly given initializers bool errors = false; for (size_t fieldi = 0, i = 0; i < field.dim; i++) { if (Identifier *id = field[i]) { Dsymbol *s = sd->search(loc, id, 0); if (!s) { s = sd->search_correct(id); if (s) error(loc, "'%s' is not a member of '%s', did you mean '%s %s'?", id->toChars(), sd->toChars(), s->kind(), s->toChars()); else error(loc, "'%s' is not a member of '%s'", id->toChars(), sd->toChars()); return new ErrorExp(); } s = s->toAlias(); // Find out which field index it is for (fieldi = 0; 1; fieldi++) { if (fieldi >= nfields) { error(loc, "%s.%s is not a per-instance initializable field", sd->toChars(), s->toChars()); return new ErrorExp(); } if (s == sd->fields[fieldi]) break; } } else if (fieldi >= nfields) { error(loc, "too many initializers for %s", sd->toChars()); return new ErrorExp(); } VarDeclaration *vd = sd->fields[fieldi]; if ((*elements)[fieldi]) { error(loc, "duplicate initializer for field '%s'", vd->toChars()); errors = true; continue; } for (size_t j = 0; j < nfields; j++) { VarDeclaration *v2 = sd->fields[j]; bool overlap = (vd->offset < v2->offset + v2->type->size() && v2->offset < vd->offset + vd->type->size()); if (overlap && (*elements)[j]) { error(loc, "overlapping initialization for field %s and %s", v2->toChars(), vd->toChars()); errors = true; continue; } } assert(sc); Initializer *iz = value[i]; iz = iz->semantic(sc, vd->type->addMod(t->mod), needInterpret); Expression *ex = iz->toExpression(); if (ex->op == TOKerror) { errors = true; continue; } value[i] = iz; (*elements)[fieldi] = ex; ++fieldi; } if (errors) return new ErrorExp(); // Fill in missing any elements with default initializers for (size_t i = 0; i < elements->dim; i++) { if ((*elements)[i]) continue; VarDeclaration *vd = sd->fields[i]; VarDeclaration *vx = vd; if (vd->init && vd->init->isVoidInitializer()) vx = NULL; // Find overlapped fields with the hole [vd->offset .. vd->offset->size()]. size_t fieldi = i; for (size_t j = 0; j < nfields; j++) { if (i == j) continue; VarDeclaration *v2 = sd->fields[j]; if (v2->init && v2->init->isVoidInitializer()) continue; bool overlap = (vd->offset < v2->offset + v2->type->size() && v2->offset < vd->offset + vd->type->size()); if (!overlap) continue; if ((*elements)[j]) { vx = NULL; break; } #if 1 /* Prefer first found non-void-initialized field * union U { int a; int b = 2; } * U u; // Error: overlapping initialization for field a and b */ if (!vx) vx = v2, fieldi = j; else if (v2->init) { error(loc, "overlapping initialization for field %s and %s", v2->toChars(), vd->toChars()); } #else // fix Bugzilla 1432 /* Prefer explicitly initialized field * union U { int a; int b = 2; } * U u; // OK (u.b == 2) */ if (!vx || !vx->init && v2->init) vx = v2, fieldi = j; else if (vx->init && v2->init) { error(loc, "overlapping default initialization for field %s and %s", v2->toChars(), vd->toChars()); } else assert(vx->init || !vx->init && !v2->init); #endif } if (vx) { if (vx->init) { assert(!vx->init->isVoidInitializer()); if (vx->scope) { // Do deferred semantic analysis Initializer *i2 = vx->init->syntaxCopy(); i2 = i2->semantic(vx->scope, vx->type, INITinterpret); (*elements)[fieldi] = i2->toExpression(); if (!global.gag) { vx->scope = NULL; vx->init = i2; // save result } } else (*elements)[fieldi] = vx->init->toExpression(); } else (*elements)[fieldi] = vx->type->defaultInit(); } } for (size_t i = 0; i < elements->dim; i++) { Expression *e = (*elements)[i]; if (e && e->op == TOKerror) return e; } Expression *e = new StructLiteralExp(loc, sd, elements, t); if (sc) e = e->semantic(sc); else e->type = sd->type; // from glue layer return e; }