From 003f306cbaf33a2f5388eca6313d6f6b5f3f47eb Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Wed, 6 Jan 2010 15:18:23 -0300 Subject: [PATCH] Merge DMD r321: bugzilla 3575 CTFE: member structs not initialized correctly --- dmd/expression.c | 4 +--- dmd/interpret.c | 32 +++++++++----------------------- dmd/mtype.c | 48 +++++++++++++++++++++++++++++++++++++++++++----- dmd/mtype.h | 2 ++ 4 files changed, 55 insertions(+), 31 deletions(-) --- dmd/expression.c | 4 +--- dmd/interpret.c | 32 +++++++++----------------------- dmd/mtype.c | 48 +++++++++++++++++++++++++++++++++++++++++++----- dmd/mtype.h | 2 ++ 4 files changed, 55 insertions(+), 31 deletions(-) diff --git a/dmd/expression.c b/dmd/expression.c index 6648632e..0787dc02 100644 --- a/dmd/expression.c +++ b/dmd/expression.c @@ -3264,9 +3264,7 @@ Expression *StructLiteralExp::semantic(Scope *sc) } } else - { e = v->type->defaultInit(); - e->loc = loc; - } + e = v->type->defaultInitLiteral(loc); offset = v->offset + v->type->size(); } elements->push(e); diff --git a/dmd/interpret.c b/dmd/interpret.c index 79d0dc07..b7834d31 100644 --- a/dmd/interpret.c +++ b/dmd/interpret.c @@ -1515,24 +1515,6 @@ ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type, } -/******************************** - * Necessary because defaultInit() for a struct is a VarExp, not a StructLiteralExp. - */ -StructLiteralExp *createDefaultInitStructLiteral(Loc loc, StructDeclaration *sym) -{ - Expressions *structelems = new Expressions(); - structelems->setDim(sym->fields.dim); - for (size_t j = 0; j < structelems->dim; j++) - { - structelems->data[j] = ((VarDeclaration *)(sym->fields.data[j]))->type->defaultInit(); - } - StructLiteralExp *structinit = new StructLiteralExp(loc, sym, structelems); - // Why doesn't the StructLiteralExp constructor do this, when - // sym->type != NULL ? - structinit->type = sym->type; - return structinit; -} - /******************************** * Add v to the istate list, unless it already exists there. */ @@ -1592,7 +1574,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) } else if (v && v->value && (v->value->op==TOKindex || v->value->op == TOKdotvar)) { - // It is no longer be a TOKvar, eg when a[4] is passed by ref. + // It is no longer a TOKvar, eg when a[4] is passed by ref. e1 = v->value; } } @@ -1634,7 +1616,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) */ if (v->type->toBasetype()->ty == Tstruct && e2->op == TOKint64) { - e2 = v->type->defaultInit(); + e2 = v->type->defaultInitLiteral(); } e2 = Cast(v->type, v->type, e2); } @@ -1960,8 +1942,7 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post) if (telem->ty != Tstruct) { return EXP_CANT_INTERPRET; } // Create a default struct literal... - StructDeclaration *sym = ((TypeStruct *)telem)->sym; - StructLiteralExp *structinit = createDefaultInitStructLiteral(v->loc, sym); + Expression *structinit = telem->defaultInitLiteral(v->loc); // ... and use to create a blank array literal size_t dim = ((TypeSArray *)t)->dim->toInteger(); @@ -2642,10 +2623,15 @@ Expression *DotVarExp::interpret(InterState *istate) if (v) { e = se->getField(type, v->offset); if (!e) + { + error("couldn't find field %s in %s", v->toChars(), type->toChars()); e = EXP_CANT_INTERPRET; + } return e; } - } else error("%s.%s is not yet implemented at compile time", ex->toChars(), var->toChars()); + } + else + error("%s.%s is not yet implemented at compile time", ex->toChars(), var->toChars()); } #if LOG diff --git a/dmd/mtype.c b/dmd/mtype.c index de42e833..e3e6104b 100644 --- a/dmd/mtype.c +++ b/dmd/mtype.c @@ -569,12 +569,9 @@ int Type::checkBoolean() void Type::checkDeprecated(Loc loc, Scope *sc) { - Type *t; - Dsymbol *s; - - for (t = this; t; t = t->next) + for (Type *t = this; t; t = t->next) { - s = t->toDsymbol(sc); + Dsymbol *s = t->toDsymbol(sc); if (s) s->checkDeprecated(loc, sc); } @@ -589,6 +586,18 @@ Expression *Type::defaultInit(Loc loc) return NULL; } +/*************************************** + * Use when we prefer the default initializer to be a literal, + * rather than a global immutable variable. + */ +Expression *Type::defaultInitLiteral(Loc loc) +{ +#if LOGDEFAULTINIT + printf("Type::defaultInitLiteral() '%s'\n", toChars()); +#endif + return defaultInit(loc); +} + int Type::isZeroInit(Loc loc) { return 0; // assume not @@ -4707,6 +4716,35 @@ Expression *TypeStruct::defaultInit(Loc loc) return new VarExp(sym->loc, d); } +/*************************************** + * Use when we prefer the default initializer to be a literal, + * rather than a global immutable variable. + */ +Expression *TypeStruct::defaultInitLiteral(Loc loc) +{ +#if LOGDEFAULTINIT + printf("TypeStruct::defaultInitLiteral() '%s'\n", toChars()); +#endif + Expressions *structelems = new Expressions(); + structelems->setDim(sym->fields.dim); + for (size_t j = 0; j < structelems->dim; j++) + { + VarDeclaration *vd = (VarDeclaration *)(sym->fields.data[j]); + Expression *e; + if (vd->init) + e = vd->init->toExpression(); + else + e = vd->type->defaultInitLiteral(); + structelems->data[j] = e; + } + StructLiteralExp *structinit = new StructLiteralExp(loc, (StructDeclaration *)sym, structelems); + // Why doesn't the StructLiteralExp constructor do this, when + // sym->type != NULL ? + structinit->type = sym->type; + return structinit; +} + + int TypeStruct::isZeroInit(Loc loc) { return sym->zeroInit; diff --git a/dmd/mtype.h b/dmd/mtype.h index 2d5fe8bf..c510c045 100644 --- a/dmd/mtype.h +++ b/dmd/mtype.h @@ -250,6 +250,7 @@ struct Type : Object virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); virtual unsigned memalign(unsigned salign); virtual Expression *defaultInit(Loc loc = 0); + virtual Expression *defaultInitLiteral(Loc loc = 0); virtual int isZeroInit(Loc loc = 0); // if initializer is 0 #if IN_DMD virtual dt_t **toDt(dt_t **pdt); @@ -582,6 +583,7 @@ struct TypeStruct : Type Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); unsigned memalign(unsigned salign); Expression *defaultInit(Loc loc); + Expression *defaultInitLiteral(Loc loc); int isZeroInit(Loc loc); int checkBoolean(); #if IN_DMD