Expression *expandVar(int result, VarDeclaration *v) { //printf("expandVar(result = %d, v = %p, %s)\n", result, v, v ? v->toChars() : "null"); Expression *e = NULL; if (!v) return e; if (!v->originalType && v->scope) // semantic() not yet run v->semantic (v->scope); if (v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) { if (!v->type) { //error("ICE"); return e; } Type *tb = v->type->toBasetype(); if (result & WANTinterpret || v->storage_class & STCmanifest || v->type->toBasetype()->isscalar() || ((result & WANTexpand) && (tb->ty != Tsarray && tb->ty != Tstruct)) ) { if (v->init) { if (v->inuse) { if (v->storage_class & STCmanifest) v->error("recursive initialization of constant"); goto L1; } Expression *ei = v->init->toExpression(); if (!ei) { if (v->storage_class & STCmanifest) v->error("enum cannot be initialized with %s", v->init->toChars()); goto L1; } if (ei->op == TOKconstruct || ei->op == TOKblit) { AssignExp *ae = (AssignExp *)ei; ei = ae->e2; if (result & WANTinterpret) { v->inuse++; ei = ei->optimize(result); v->inuse--; } else if (ei->isConst() != 1 && ei->op != TOKstring) goto L1; if (ei->type == v->type) { // const variable initialized with const expression } else if (ei->implicitConvTo(v->type) >= MATCHconst) { // const var initialized with non-const expression ei = ei->implicitCastTo(0, v->type); ei = ei->semantic(0); } else goto L1; } if (v->scope) { v->inuse++; e = ei->syntaxCopy(); e = e->semantic(v->scope); e = e->implicitCastTo(v->scope, v->type); // enabling this line causes test22 in test suite to fail //ei->type = e->type; v->scope = NULL; v->inuse--; } else if (!ei->type) { goto L1; } else // Should remove the copy() operation by // making all mods to expressions copy-on-write e = ei->copy(); } else { #if 1 goto L1; #else // BUG: what if const is initialized in constructor? e = v->type->defaultInit(); e->loc = e1->loc; #endif } if (e->type != v->type) { e = e->castTo(NULL, v->type); } v->inuse++; e = e->optimize(result); v->inuse--; } } L1: //if (e) printf("\te = %p, %s, e->type = %d, %s\n", e, e->toChars(), e->type->ty, e->type->toChars()); return e; }
Expression *AddrExp::optimize(int result) { Expression *e; //printf("AddrExp::optimize(result = %d) %s\n", result, toChars()); /* Rewrite &(a,b) as (a,&b) */ if (e1->op == TOKcomma) { CommaExp *ce = (CommaExp *)e1; AddrExp *ae = new AddrExp(loc, ce->e2); ae->type = type; e = new CommaExp(ce->loc, ce->e1, ae); e->type = type; return e->optimize(result); } if (e1->op == TOKvar) { VarExp *ve = (VarExp *)e1; if (ve->var->storage_class & STCmanifest) e1 = e1->optimize(result); } else e1 = e1->optimize(result); // Convert &*ex to ex if (e1->op == TOKstar) { Expression *ex; ex = ((PtrExp *)e1)->e1; if (type->equals(ex->type)) e = ex; else { e = ex->copy(); e->type = type; } return e; } if (e1->op == TOKvar) { VarExp *ve = (VarExp *)e1; if (!ve->var->isOut() && !ve->var->isRef() && !ve->var->isImportedSymbol()) { SymOffExp *se = new SymOffExp(loc, ve->var, 0, ve->hasOverloads); se->type = type; return se; } } if (e1->op == TOKindex) { // Convert &array[n] to &array+n IndexExp *ae = (IndexExp *)e1; if (ae->e2->op == TOKint64 && ae->e1->op == TOKvar) { dinteger_t index = ae->e2->toInteger(); VarExp *ve = (VarExp *)ae->e1; if (ve->type->ty == Tsarray && !ve->var->isImportedSymbol()) { TypeSArray *ts = (TypeSArray *)ve->type; dinteger_t dim = ts->dim->toInteger(); if (index < 0 || index >= dim) error("array index %jd is out of bounds [0..%jd]", index, dim); e = new SymOffExp(loc, ve->var, index * ts->nextOf()->size()); e->type = type; return e; } } } return this; }