Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 314

Show
Ignore:
Timestamp:
12/29/09 00:15:03 (15 years ago)
Author:
walter
Message:

bugzilla 2029 Typesafe variadic functions don't work in CTFE

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/dmd-1.x/src/constfold.c

    r199 r314  
    838838    } 
    839839#endif 
    840840    } 
    841841    else if (e1->type->iscomplex()) 
    842842    { 
    843843    cmp = e1->toComplex() == e2->toComplex(); 
    844844    } 
    845845    else if (e1->type->isintegral() || e1->type->toBasetype()->ty == Tpointer) 
    846846    { 
    847847    cmp = (e1->toInteger() == e2->toInteger()); 
    848848    } 
    849849    else 
    850850    return EXP_CANT_INTERPRET; 
    851851    if (op == TOKnotequal) 
    852852    cmp ^= 1; 
    853853    e = new IntegerExp(loc, cmp, type); 
    854854    return e; 
    855855} 
    856856 
    857857Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2) 
    858 {   Expression *e; 
     858{ 
    859859    Loc loc = e1->loc; 
    860860    int cmp; 
    861861 
    862862    if (e1->op == TOKnull) 
    863863    { 
    864864    cmp = (e2->op == TOKnull); 
    865865    } 
    866866    else if (e2->op == TOKnull) 
    867867    { 
    868868    cmp = 0; 
    869869    } 
    870870    else if (e1->op == TOKsymoff && e2->op == TOKsymoff) 
    871871    { 
    872872    SymOffExp *es1 = (SymOffExp *)e1; 
    873873    SymOffExp *es2 = (SymOffExp *)e2; 
    874874 
    875875    cmp = (es1->var == es2->var && es1->offset == es2->offset); 
    876876    } 
    877877    else if (e1->isConst() == 1 && e2->isConst() == 1) 
    878878    return Equal((op == TOKidentity) ? TOKequal : TOKnotequal, 
     
    10421042    Loc loc = e1->loc; 
    10431043 
    10441044    //printf("Cast(type = %s, to = %s, e1 = %s)\n", type->toChars(), to->toChars(), e1->toChars()); 
    10451045    //printf("e1->type = %s\n", e1->type->toChars()); 
    10461046    if (type->equals(e1->type) && to->equals(type)) 
    10471047    return e1; 
    10481048 
    10491049    Type *tb = to->toBasetype(); 
    10501050 
    10511051    /* Allow casting from one string type to another 
    10521052     */ 
    10531053    if (e1->op == TOKstring) 
    10541054    { 
    10551055    Type *typeb = type->toBasetype(); 
    10561056    if (tb->ty == Tarray && typeb->ty == Tarray && 
    10571057        tb->nextOf()->size() == typeb->nextOf()->size()) 
    10581058    { 
    10591059        return expType(to, e1); 
    10601060    } 
    10611061    } 
     1062 
     1063    if (e1->op == TOKarrayliteral && e1->type->toBasetype() == tb) 
     1064        return e1; 
    10621065 
    10631066    if (e1->isConst() != 1) 
    10641067    return EXP_CANT_INTERPRET; 
    10651068 
    10661069    if (tb->ty == Tbool) 
    10671070    e = new IntegerExp(loc, e1->toInteger() != 0, type); 
    10681071    else if (type->isintegral()) 
    10691072    { 
    10701073    if (e1->type->isfloating()) 
    10711074    {   dinteger_t result; 
    10721075        real_t r = e1->toReal(); 
    10731076 
    10741077        switch (type->toBasetype()->ty) 
    10751078        { 
    10761079        case Tint8: result = (d_int8)r; break; 
    10771080        case Tchar: 
    10781081        case Tuns8: result = (d_uns8)r; break; 
    10791082        case Tint16:    result = (d_int16)r;    break; 
    10801083        case Twchar: 
    10811084        case Tuns16:    result = (d_uns16)r;    break; 
  • branches/dmd-1.x/src/declaration.c

    r304 r314  
    290290        st->htype = htype->syntaxCopy(); 
    291291    if (!hbasetype) 
    292292    {   if (basetype) 
    293293    {   hbasetype = basetype->syntaxCopy(); 
    294294        st->hbasetype = basetype->syntaxCopy(); 
    295295    } 
    296296    } 
    297297    else 
    298298        st->hbasetype = hbasetype->syntaxCopy(); 
    299299#endif 
    300300    return st; 
    301301} 
    302302 
    303303void TypedefDeclaration::semantic(Scope *sc) 
    304304{ 
    305305    //printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem); 
    306306    if (sem == 0) 
    307307    {   sem = 1; 
    308308    basetype = basetype->semantic(loc, sc); 
    309309    sem = 2; 
     310#if DMDV2 
     311    type = type->addStorageClass(storage_class); 
     312#endif 
    310313    type = type->semantic(loc, sc); 
    311314    if (sc->parent->isFuncDeclaration() && init) 
    312315        semantic2(sc); 
    313316    storage_class |= sc->stc & STCdeprecated; 
    314317    } 
    315318    else if (sem == 1) 
    316319    { 
    317320    error("circular definition"); 
    318321    } 
    319322} 
    320323 
    321324void TypedefDeclaration::semantic2(Scope *sc) 
    322325{ 
    323326    //printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem); 
    324327    if (sem == 2) 
    325328    {   sem = 3; 
    326329    if (init) 
    327330    { 
    328331        init = init->semantic(sc, basetype); 
    329332 
     
    421424        sa->haliassym = aliassym->syntaxCopy(s); 
    422425    } 
    423426    } 
    424427    else 
    425428    sa->haliassym = haliassym->syntaxCopy(s); 
    426429#endif 
    427430    return sa; 
    428431} 
    429432 
    430433void AliasDeclaration::semantic(Scope *sc) 
    431434{ 
    432435    //printf("AliasDeclaration::semantic() %s\n", toChars()); 
    433436    if (aliassym) 
    434437    { 
    435438    if (aliassym->isTemplateInstance()) 
    436439        aliassym->semantic(sc); 
    437440    return; 
    438441    } 
    439442    this->inSemantic = 1; 
    440443 
     444#if DMDV1   // don't really know why this is here 
    441445    if (storage_class & STCconst) 
    442446    error("cannot be const"); 
     447#endif 
    443448 
    444449    storage_class |= sc->stc & STCdeprecated; 
    445450 
    446451    // Given: 
    447452    //  alias foo.bar.abc def; 
    448453    // it is not knowable from the syntax whether this is an alias 
    449454    // for a type or an alias for a symbol. It is up to the semantic() 
    450455    // pass to distinguish. 
    451456    // If it is a type, then type is set and getType() will return that 
    452457    // type. If it is a symbol, then aliassym is set and type is NULL - 
    453458    // toAlias() will return aliasssym. 
    454459 
    455460    Dsymbol *s; 
    456461    Type *t; 
    457462    Expression *e; 
    458463 
    459464    /* This section is needed because resolve() will: 
    460465     *   const x = 3; 
    461466     *   alias x y; 
    462467     * try to alias y to 3. 
    463468     */ 
    464469    s = type->toDsymbol(sc); 
    465470    if (s 
    466471#if DMDV2 
    467472`   && ((s->getType() && type->equals(s->getType())) || s->isEnumMember()) 
    468473#endif 
    469474    ) 
    470475    goto L2;            // it's a symbolic alias 
    471476 
    472477#if DMDV2 
     478    type = type->addStorageClass(storage_class); 
    473479    if (storage_class & (STCref | STCnothrow | STCpure)) 
    474480    {   // For 'ref' to be attached to function types, and picked 
    475481    // up by Type::resolve(), it has to go into sc. 
    476482    sc = sc->push(); 
    477     sc->stc |= storage_class & (STCref | STCnothrow | STCpure); 
     483    sc->stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared); 
    478484    type->resolve(loc, sc, &e, &t, &s); 
    479485    sc = sc->pop(); 
    480486    } 
    481487    else 
    482488#endif 
    483489    type->resolve(loc, sc, &e, &t, &s); 
    484490    if (s) 
    485491    { 
    486492    goto L2; 
    487493    } 
    488494    else if (e) 
    489495    { 
    490496    // Try to convert Expression to Dsymbol 
    491497        if (e->op == TOKvar) 
    492498    {   s = ((VarExp *)e)->var; 
    493499        goto L2; 
    494500    } 
    495501        else if (e->op == TOKfunction) 
    496502    {   s = ((FuncExp *)e)->fd; 
    497503        goto L2; 
     
    13111317    Dsymbol *parent = this->toParent(); 
    13121318    if (!parent && !(storage_class & (STCstatic | STCconst))) 
    13131319    {   error("forward referenced"); 
    13141320    type = Type::terror; 
    13151321    return 0; 
    13161322    } 
    13171323    return (storage_class & (STCstatic | STCconst) || 
    13181324       parent->isModule() || 
    13191325       parent->isTemplateInstance()); 
    13201326} 
    13211327 
    13221328/************************************ 
    13231329 * Does symbol go into thread local storage? 
    13241330 */ 
    13251331 
    13261332int VarDeclaration::isThreadlocal() 
    13271333{ 
    13281334    return 0; 
    13291335} 
    13301336 
     1337/******************************************** 
     1338 * Can variable be read and written by CTFE? 
     1339 */ 
     1340 
     1341int VarDeclaration::isCTFE() 
     1342{ 
     1343    return (storage_class & STCctfe) || !isDataseg(); 
     1344} 
     1345 
    13311346int VarDeclaration::hasPointers() 
    13321347{ 
    13331348    //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty); 
    13341349    return (!isDataseg() && type->hasPointers()); 
    13351350} 
    13361351 
    13371352/****************************************** 
    13381353 * If a variable has an auto destructor call, return call for it. 
    13391354 * Otherwise, return NULL. 
    13401355 */ 
    13411356 
    13421357Expression *VarDeclaration::callAutoDtor(Scope *sc) 
    13431358{   Expression *e = NULL; 
    13441359 
    13451360    //printf("VarDeclaration::callAutoDtor() %s\n", toChars()); 
    13461361    if (storage_class & (STCauto | STCscope) && !noauto) 
    13471362    { 
    13481363    for (ClassDeclaration *cd = type->isClassHandle(); 
    13491364         cd; 
    13501365         cd = cd->baseClass) 
  • branches/dmd-1.x/src/declaration.h

    r304 r314  
    5656    STCout          = 0x1000,       // out parameter 
    5757    STClazy     = 0x2000,       // lazy parameter 
    5858    STCforeach      = 0x4000,       // variable for foreach loop 
    5959    STCcomdat       = 0x8000,       // should go into COMDAT record 
    6060    STCvariadic     = 0x10000,      // variadic function argument 
    6161    STCctorinit     = 0x20000,      // can only be set inside constructor 
    6262    STCtemplateparameter = 0x40000, // template parameter 
    6363    STCscope        = 0x80000,      // template parameter 
    6464    STCimmutable    = 0x100000, 
    6565    STCref      = 0x200000, 
    6666    STCinit     = 0x400000,     // has explicit initializer 
    6767    STCmanifest     = 0x800000,     // manifest constant 
    6868    STCnodtor       = 0x1000000,    // don't run destructor 
    6969    STCnothrow      = 0x2000000,    // never throws exceptions 
    7070    STCpure     = 0x4000000,    // pure function 
    7171    STCtls      = 0x8000000,    // thread local 
    7272    STCalias        = 0x10000000,   // alias parameter 
    7373    STCshared       = 0x20000000,   // accessible from multiple threads 
    7474    STCgshared      = 0x40000000,   // accessible from multiple threads 
    7575                    // but not typed as "shared" 
    76     STC_TYPECTOR    = (STCconst | STCimmutable | STCshared), 
    77 }; 
     76    STCwild         = 0x80000000,   // for "wild" type constructor 
     77    STC_TYPECTOR    = (STCconst | STCimmutable | STCshared | STCwild), 
     78}; 
     79 
     80#define STCproperty 0x100000000LL 
     81#define STCsafe     0x200000000LL 
     82#define STCtrusted  0x400000000LL 
     83#define STCsystem   0x800000000LL 
     84#define STCctfe     0x1000000000LL  // can be used in CTFE, even if it is static 
    7885 
    7986struct Match 
    8087{ 
    8188    int count;          // number of matches found 
    8289    MATCH last;         // match level of lastf 
    8390    FuncDeclaration *lastf; // last matching function we found 
    8491    FuncDeclaration *nextf; // current matching function 
    8592    FuncDeclaration *anyf;  // pick a func, any func, to use for error recovery 
    8693}; 
    8794 
    8895void overloadResolveX(Match *m, FuncDeclaration *f, 
    8996    Expression *ethis, Expressions *arguments); 
    9097int overloadApply(FuncDeclaration *fstart, 
    9198    int (*fp)(void *, FuncDeclaration *), 
    9299    void *param); 
    93100 
    94101/**************************************************************/ 
    95102 
    96103struct Declaration : Dsymbol 
    97104{ 
     
    245252#if DMDV2 
    246253    VarDeclaration *rundtor;    // if !NULL, rundtor is tested at runtime to see 
    247254                // if the destructor should be run. Used to prevent 
    248255                // dtor calls on postblitted vars 
    249256#endif 
    250257 
    251258    VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); 
    252259    Dsymbol *syntaxCopy(Dsymbol *); 
    253260    void semantic(Scope *sc); 
    254261    void semantic2(Scope *sc); 
    255262    const char *kind(); 
    256263    void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 
    257264#ifdef _DH 
    258265    Type *htype; 
    259266    Initializer *hinit; 
    260267#endif 
    261268    int needThis(); 
    262269    int isImportedSymbol(); 
    263270    int isDataseg(); 
    264271    int isThreadlocal(); 
     272    int isCTFE(); 
    265273    int hasPointers(); 
    266274#if DMDV2 
    267275    int canTakeAddressOf(); 
    268276    int needsAutoDtor(); 
    269277#endif 
    270278    Expression *callAutoDtor(Scope *sc); 
    271279    ExpInitializer *getExpInitializer(); 
    272280    Expression *getConstInitializer(); 
    273281    void checkCtorConstInit(); 
    274282    void checkNestedReference(Scope *sc, Loc loc); 
    275283    Dsymbol *toAlias(); 
    276284 
    277285    Symbol *toSymbol(); 
    278286    void toObjFile(int multiobj);           // compile to .obj file 
    279287    int cvMember(unsigned char *p); 
    280288 
    281289    // Eliminate need for dynamic_cast 
    282290    VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; } 
    283291}; 
    284292 
  • branches/dmd-1.x/src/expression.c

    r304 r314  
    680680        Type *tret = p->isLazyArray(); 
    681681        switch (tb->ty) 
    682682        { 
    683683            case Tsarray: 
    684684            case Tarray: 
    685685            {   // Create a static array variable v of type arg->type 
    686686#ifdef IN_GCC 
    687687            /* GCC 4.0 does not like zero length arrays used like 
    688688               this; pass a null array value instead. Could also 
    689689               just make a one-element array. */ 
    690690            if (nargs - i == 0) 
    691691            { 
    692692                arg = new NullExp(loc); 
    693693                break; 
    694694            } 
    695695#endif 
    696696            Identifier *id = Lexer::uniqueId("__arrayArg"); 
    697697            Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i)); 
    698698            t = t->semantic(loc, sc); 
    699699            VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc)); 
     700            v->storage_class |= STCctfe; 
    700701            v->semantic(sc); 
    701702            v->parent = sc->parent; 
    702703            //sc->insert(v); 
    703704 
    704705            Expression *c = new DeclarationExp(0, v); 
    705706            c->type = v->type; 
    706707 
    707708            for (size_t u = i; u < nargs; u++) 
    708709            {   Expression *a = (Expression *)arguments->data[u]; 
    709710                if (tret && !((TypeArray *)tb)->next->equals(a->type)) 
    710711                a = a->toDelegate(sc, tret); 
    711712 
    712713                Expression *e = new VarExp(loc, v); 
    713714                e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams)); 
    714715                AssignExp *ae = new AssignExp(loc, e, a); 
    715716#if DMDV2 
    716717                ae->op = TOKconstruct; 
    717718#endif 
    718719                if (c) 
    719720                c = new CommaExp(loc, c, ae); 
  • branches/dmd-1.x/src/interpret.c

    r310 r314  
    3131{ 
    3232    InterState *caller;     // calling function's InterState 
    3333    FuncDeclaration *fd;    // function being interpreted 
    3434    Dsymbols vars;      // variables used in this function 
    3535    Statement *start;       // if !=NULL, start execution at this statement 
    3636    Statement *gotoTarget;  // target of EXP_GOTO_INTERPRET result 
    3737    Expression *localThis;  // value of 'this', or NULL if none 
    3838 
    3939    InterState(); 
    4040}; 
    4141 
    4242InterState::InterState() 
    4343{ 
    4444    memset(this, 0, sizeof(InterState)); 
    4545} 
    4646 
    4747Expression *interpret_aaLen(InterState *istate, Expressions *arguments); 
    4848Expression *interpret_aaKeys(InterState *istate, Expressions *arguments); 
    4949Expression *interpret_aaValues(InterState *istate, Expressions *arguments); 
    5050 
     51Expression *interpret_length(InterState *istate, Expression *earg); 
     52Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd); 
     53Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd); 
     54 
    5155/************************************* 
    5256 * Attempt to interpret a function given the arguments. 
    5357 * Input: 
    5458 *  istate     state for calling function (NULL if none) 
    5559 *      arguments  function arguments 
    5660 *      thisarg    'this', if a needThis() function, NULL if not.    
    5761 * 
    5862 * Return result expression if successful, NULL if not. 
    5963 */ 
    6064 
    6165Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg) 
    6266{ 
    6367#if LOG 
    6468    printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars()); 
    6569    printf("cantInterpret = %d, semanticRun = %d\n", cantInterpret, semanticRun); 
    6670#endif 
    6771    if (global.errors) 
    6872    return NULL; 
     73 
     74#if DMDV1 
    6975    if (ident == Id::aaLen) 
    7076    return interpret_aaLen(istate, arguments); 
    7177    else if (ident == Id::aaKeys) 
    7278    return interpret_aaKeys(istate, arguments); 
    7379    else if (ident == Id::aaValues) 
    7480    return interpret_aaValues(istate, arguments); 
     81#endif 
     82#if DMDV2 
     83    if (thisarg && 
     84    (!arguments || arguments->dim == 0)) 
     85    { 
     86    if (ident == Id::length) 
     87        return interpret_length(istate, thisarg); 
     88    else if (ident == Id::keys) 
     89        return interpret_keys(istate, thisarg, this); 
     90    else if (ident == Id::values) 
     91        return interpret_values(istate, thisarg, this); 
     92    } 
     93#endif 
    7594 
    7695    if (cantInterpret || semanticRun == 3) 
    7796    return NULL; 
    7897 
    7998    if (!fbody) 
    8099    {   cantInterpret = 1; 
    81100    return NULL; 
    82101    } 
    83102 
    84103    if (semanticRun < 3 && scope) 
    85104    { 
    86105    semantic3(scope); 
    87106    if (global.errors)  // if errors compiling this function 
    88107        return NULL; 
    89108    } 
    90109    if (semanticRun < 4) 
    91110    return NULL; 
    92111 
    93112    Type *tb = type->toBasetype(); 
    94113    assert(tb->ty == Tfunction); 
    95114    TypeFunction *tf = (TypeFunction *)tb; 
    96115    Type *tret = tf->next->toBasetype(); 
    97     if (tf->varargs
     116    if (tf->varargs && arguments && parameters && arguments->dim != parameters->dim
    98117    {   cantInterpret = 1; 
    99     error("Variadic functions are not yet implemented in CTFE"); 
     118    error("C-style variadic functions are not yet implemented in CTFE"); 
    100119    return NULL; 
    101120    } 
    102121     
    103122    // Ensure there are no lazy parameters 
    104123    if (tf->parameters) 
    105124    {   size_t dim = Parameter::dim(tf->parameters); 
    106125    for (size_t i = 0; i < dim; i++) 
    107126    {   Parameter *arg = Parameter::getNth(tf->parameters, i); 
    108127        if (arg->storageClass & STClazy) 
    109128        {   cantInterpret = 1; 
    110129        return NULL; 
    111130        } 
    112131    } 
    113132    } 
    114133 
    115134    InterState istatex; 
    116135    istatex.caller = istate; 
    117136    istatex.fd = this; 
    118137    istatex.localThis = thisarg; 
    119138 
     
    9871006} 
    9881007 
    9891008Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) 
    9901009{ 
    9911010    Expression *e = EXP_CANT_INTERPRET; 
    9921011    VarDeclaration *v = d->isVarDeclaration(); 
    9931012    SymbolDeclaration *s = d->isSymbolDeclaration(); 
    9941013    if (v) 
    9951014    { 
    9961015#if DMDV2 
    9971016    if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->value) 
    9981017#else 
    9991018    if (v->isConst() && v->init) 
    10001019#endif 
    10011020    {   e = v->init->toExpression(); 
    10021021        if (e && !e->type) 
    10031022        e->type = v->type; 
    10041023    } 
    10051024    else 
    10061025    {   e = v->value; 
    1007         if (v->isDataseg()) 
     1026        if (!v->isCTFE()) 
    10081027        {   error(loc, "static variable %s cannot be read at compile time", v->toChars()); 
    10091028        e = EXP_CANT_INTERPRET; 
    10101029        } 
    10111030        else if (!e) 
    10121031        error(loc, "variable %s is used before initialization", v->toChars()); 
    10131032        else if (e != EXP_CANT_INTERPRET) 
    10141033        e = e->interpret(istate); 
    10151034    } 
    10161035    if (!e) 
    10171036        e = EXP_CANT_INTERPRET; 
    10181037    } 
    10191038    else if (s) 
    10201039    { 
    10211040    if (s->dsym->toInitializer() == s->sym) 
    10221041    {   Expressions *exps = new Expressions(); 
    10231042        e = new StructLiteralExp(0, s->dsym, exps); 
    10241043        e = e->semantic(NULL); 
    10251044    } 
    10261045    } 
    10271046    return e; 
     
    15791598    } 
    15801599 
    15811600    // To reduce code complexity of handling dotvar expressions, 
    15821601    // extract the aggregate now. 
    15831602    Expression *aggregate; 
    15841603    if (e1->op == TOKdotvar) { 
    15851604        aggregate = ((DotVarExp *)e1)->e1; 
    15861605    // Get rid of 'this'. 
    15871606        if (aggregate->op == TOKthis && istate->localThis) 
    15881607            aggregate = istate->localThis;   
    15891608    } 
    15901609     
    15911610    /* Assignment to variable of the form: 
    15921611     *  v = e2 
    15931612     */ 
    15941613    if (e1->op == TOKvar) 
    15951614    { 
    15961615    VarExp *ve = (VarExp *)e1; 
    15971616    VarDeclaration *v = ve->var->isVarDeclaration(); 
    15981617    assert(v); 
    1599     if (v && v->isDataseg()) 
     1618    if (v && !v->isCTFE()) 
    16001619    {   // Can't modify global or static data 
    16011620        error("%s cannot be modified at compile time", v->toChars()); 
    16021621        return EXP_CANT_INTERPRET; 
    16031622    } 
    1604     if (v && !v->isDataseg()) 
     1623    if (v && v->isCTFE()) 
    16051624    { 
    16061625        Expression *ev = v->value; 
    16071626        if (fp && !ev) 
    16081627        {   error("variable %s is used before initialization", v->toChars()); 
    16091628        return e; 
    16101629        } 
    16111630        if (fp) 
    16121631        e2 = (*fp)(v->type, ev, e2); 
    16131632        else 
    16141633        {   /* Look for special case of struct being initialized with 0. 
    16151634         */ 
    16161635        if (v->type->toBasetype()->ty == Tstruct && e2->op == TOKint64) 
    16171636        { 
    16181637            e2 = v->type->defaultInit(); 
    16191638        } 
    16201639        e2 = Cast(v->type, v->type, e2); 
    16211640        } 
    16221641        if (e2 == EXP_CANT_INTERPRET) 
    16231642        return e2; 
    16241643 
    16251644        addVarToInterstate(istate, v); 
    16261645        v->value = e2; 
    16271646        e = Cast(type, type, post ? ev : e2); 
    16281647    } 
    16291648    } 
    16301649    else if (e1->op == TOKdotvar && aggregate->op == TOKdotvar) 
    16311650    {   // eg  v.u.var = e2,  v[3].u.var = e2, etc. 
    16321651    error("Nested struct assignment %s is not yet supported in CTFE", toChars()); 
    16331652    } 
    16341653    /* Assignment to struct member of the form: 
    16351654     *   v.var = e2 
    16361655     */ 
    16371656    else if (e1->op == TOKdotvar && aggregate->op == TOKvar) 
    16381657    {   VarDeclaration *v = ((VarExp *)aggregate)->var->isVarDeclaration(); 
    16391658 
    1640     if (v->isDataseg()) 
     1659    if (!v->isCTFE()) 
    16411660    {   // Can't modify global or static data 
    16421661        error("%s cannot be modified at compile time", v->toChars()); 
    16431662        return EXP_CANT_INTERPRET; 
    16441663    } else { 
    16451664        // Chase down rebinding of out and ref 
    16461665        if (v->value && v->value->op == TOKvar) 
    16471666        { 
    16481667        VarExp *ve2 = (VarExp *)v->value; 
    16491668        if (ve2->var->isSymbolDeclaration()) 
    16501669        {   // This can happen if v is a struct initialized to 
    16511670            // 0 using an __initZ SymbolDeclaration from 
    16521671            // TypeStruct::defaultInit() 
    16531672        } 
    16541673        else 
    16551674            v = ve2->var->isVarDeclaration(); 
    16561675        assert(v); 
    16571676        } 
    16581677    } 
    16591678    if (fp && !v->value) 
    16601679    {   error("variable %s is used before initialization", v->toChars()); 
     
    16921711    if (e2 == EXP_CANT_INTERPRET) 
    16931712        return e2; 
    16941713 
    16951714    addVarToInterstate(istate, v); 
    16961715 
    16971716    /* Create new struct literal reflecting updated fieldi 
    16981717     */ 
    16991718    Expressions *expsx = changeOneElement(se->elements, fieldi, e2); 
    17001719    v->value = new StructLiteralExp(se->loc, se->sd, expsx); 
    17011720    v->value->type = se->type; 
    17021721 
    17031722    e = Cast(type, type, post ? ev : e2); 
    17041723    } 
    17051724    /* Assignment to struct member of the form: 
    17061725     *   *(symoffexp) = e2 
    17071726     */ 
    17081727    else if (e1->op == TOKstar && ((PtrExp *)e1)->e1->op == TOKsymoff) 
    17091728    {   SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1; 
    17101729    VarDeclaration *v = soe->var->isVarDeclaration(); 
    17111730 
    1712     if (v->isDataseg()) 
     1731    if (!v->isCTFE()) 
    17131732    { 
    17141733        error("%s cannot be modified at compile time", v->toChars()); 
    17151734        return EXP_CANT_INTERPRET; 
    17161735    } 
    17171736    if (fp && !v->value) 
    17181737    {   error("variable %s is used before initialization", v->toChars()); 
    17191738        return e; 
    17201739    } 
    17211740    Expression *vie = v->value; 
    17221741    if (vie->op == TOKvar) 
    17231742    { 
    17241743        Declaration *d = ((VarExp *)vie)->var; 
    17251744        vie = getVarExp(e1->loc, istate, d); 
    17261745    } 
    17271746    if (vie->op != TOKstructliteral) 
    17281747        return EXP_CANT_INTERPRET; 
    17291748    StructLiteralExp *se = (StructLiteralExp *)vie; 
    17301749    int fieldi = se->getFieldIndex(type, soe->offset); 
    17311750    if (fieldi == -1) 
    17321751        return EXP_CANT_INTERPRET; 
     
    17381757    if (e2 == EXP_CANT_INTERPRET) 
    17391758        return e2; 
    17401759 
    17411760    addVarToInterstate(istate, v); 
    17421761 
    17431762    /* Create new struct literal reflecting updated fieldi 
    17441763     */ 
    17451764    Expressions *expsx = changeOneElement(se->elements, fieldi, e2); 
    17461765    v->value = new StructLiteralExp(se->loc, se->sd, expsx); 
    17471766    v->value->type = se->type; 
    17481767 
    17491768    e = Cast(type, type, post ? ev : e2); 
    17501769    } 
    17511770    /* Assignment to array element of the form: 
    17521771     *   a[i] = e2 
    17531772     */ 
    17541773    else if (e1->op == TOKindex && ((IndexExp *)e1)->e1->op == TOKvar) 
    17551774    {   IndexExp *ie = (IndexExp *)e1; 
    17561775    VarExp *ve = (VarExp *)ie->e1; 
    17571776    VarDeclaration *v = ve->var->isVarDeclaration(); 
    1758     if (!v || v->isDataseg()) 
     1777    if (!v || !v->isCTFE()) 
    17591778    { 
    17601779        error("%s cannot be modified at compile time", v ? v->toChars(): "void"); 
    17611780        return EXP_CANT_INTERPRET; 
    17621781    } 
    17631782        if (v->value && v->value->op == TOKvar) 
    17641783        { 
    17651784        VarExp *ve2 = (VarExp *)v->value; 
    17661785        if (ve2->var->isSymbolDeclaration()) 
    17671786        {   // This can happen if v is a struct initialized to 
    17681787            // 0 using an __initZ SymbolDeclaration from 
    17691788            // TypeStruct::defaultInit() 
    17701789        } 
    17711790        else 
    17721791            v = ve2->var->isVarDeclaration(); 
    17731792        assert(v); 
    17741793        } 
    17751794    if (!v->value) 
    17761795    { 
    17771796        if (fp) 
    17781797        {   error("variable %s is used before initialization", v->toChars()); 
     
    19011920        se2->committed = se->committed; 
    19021921        se2->postfix = se->postfix; 
    19031922        se2->type = se->type; 
    19041923        v->value = se2; 
    19051924    } 
    19061925    else 
    19071926        assert(0); 
    19081927 
    19091928    e = Cast(type, type, post ? ev : e2); 
    19101929    } 
    19111930     
    19121931    /* Assignment to struct element in array, of the form: 
    19131932     *  a[i].var = e2 
    19141933     */ 
    19151934    else if (e1->op == TOKdotvar && aggregate->op == TOKindex && 
    19161935         ((IndexExp *)aggregate)->e1->op == TOKvar) 
    19171936    { 
    19181937        IndexExp * ie = (IndexExp *)aggregate; 
    19191938    VarExp *ve = (VarExp *)(ie->e1); 
    19201939    VarDeclaration *v = ve->var->isVarDeclaration(); 
    1921     if (!v || v->isDataseg()) 
     1940    if (!v || !v->isCTFE()) 
    19221941    { 
    19231942        error("%s cannot be modified at compile time", v ? v->toChars(): "void"); 
    19241943        return EXP_CANT_INTERPRET; 
    19251944    } 
    19261945    Type *t = ve->type->toBasetype(); 
    19271946    ArrayLiteralExp *ae = (ArrayLiteralExp *)v->value; 
    19281947    if (!ae) 
    19291948    { 
    19301949        // assignment to one element in an uninitialized (static) array. 
    19311950        // This is quite difficult, because defaultInit() for a struct is a VarExp, 
    19321951        // not a StructLiteralExp. 
    19331952        Type *t = v->type->toBasetype(); 
    19341953        if (t->ty != Tsarray) 
    19351954        { 
    19361955        error("Cannot index an uninitialized variable"); 
    19371956        return EXP_CANT_INTERPRET; 
    19381957        } 
    19391958 
    19401959        Type *telem = ((TypeSArray *)t)->nextOf()->toBasetype(); 
    19411960        if (telem->ty != Tstruct) { return EXP_CANT_INTERPRET; } 
     
    19932012        e2 = Cast(type, type, e2); 
    19942013    if (e2 == EXP_CANT_INTERPRET) 
    19952014        return e2; 
    19962015 
    19972016    // Create new struct literal reflecting updated field 
    19982017    Expressions *expsx = changeOneElement(se->elements, fieldi, e2); 
    19992018    Expression * newstruct = new StructLiteralExp(se->loc, se->sd, expsx); 
    20002019 
    20012020    // Create new array literal reflecting updated struct elem 
    20022021    ae->elements = changeOneElement(ae->elements, elemi, newstruct); 
    20032022    return ae; 
    20042023    } 
    20052024    /* Slice assignment, initialization of static arrays 
    20062025     *   a[] = e 
    20072026     */ 
    20082027    else if (e1->op == TOKslice && ((SliceExp *)e1)->e1->op==TOKvar) 
    20092028    { 
    20102029        SliceExp * sexp = (SliceExp *)e1; 
    20112030    VarExp *ve = (VarExp *)(sexp->e1); 
    20122031    VarDeclaration *v = ve->var->isVarDeclaration(); 
    2013     if (!v || v->isDataseg()) 
     2032    if (!v || !v->isCTFE()) 
    20142033    { 
    20152034        error("%s cannot be modified at compile time", v->toChars()); 
    20162035        return EXP_CANT_INTERPRET; 
    20172036    } 
    20182037        // Chase down rebinding of out and ref 
    20192038        if (v->value && v->value->op == TOKvar) 
    20202039        { 
    20212040        VarExp *ve2 = (VarExp *)v->value; 
    20222041        if (ve2->var->isSymbolDeclaration()) 
    20232042        {   // This can happen if v is a struct initialized to 
    20242043            // 0 using an __initZ SymbolDeclaration from 
    20252044            // TypeStruct::defaultInit() 
    20262045        } 
    20272046        else 
    20282047            v = ve2->var->isVarDeclaration(); 
    20292048        assert(v); 
    20302049        } 
    20312050    /* Set the $ variable 
    20322051     */ 
    20332052    Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value) 
     
    26212640    {   StructLiteralExp *se = (StructLiteralExp *)ex; 
    26222641        VarDeclaration *v = var->isVarDeclaration(); 
    26232642        if (v) 
    26242643        {   e = se->getField(type, v->offset); 
    26252644        if (!e) 
    26262645            e = EXP_CANT_INTERPRET; 
    26272646        return e; 
    26282647        } 
    26292648    } else error("%s.%s is not yet implemented at compile time", ex->toChars(), var->toChars()); 
    26302649    } 
    26312650 
    26322651#if LOG 
    26332652    if (e == EXP_CANT_INTERPRET) 
    26342653    printf("DotVarExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars()); 
    26352654#endif 
    26362655    return e; 
    26372656} 
    26382657 
    26392658/******************************* Special Functions ***************************/ 
    26402659 
     2660#if DMDV1 
     2661 
    26412662Expression *interpret_aaLen(InterState *istate, Expressions *arguments) 
    26422663{ 
    26432664    if (!arguments || arguments->dim != 1) 
    26442665    return NULL; 
    26452666    Expression *earg = (Expression *)arguments->data[0]; 
    26462667    earg = earg->interpret(istate); 
    26472668    if (earg == EXP_CANT_INTERPRET) 
    26482669    return NULL; 
    26492670    if (earg->op != TOKassocarrayliteral) 
    26502671    return NULL; 
    26512672    AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 
    26522673    Expression *e = new IntegerExp(aae->loc, aae->keys->dim, Type::tsize_t); 
    26532674    return e; 
    26542675} 
    26552676 
    26562677Expression *interpret_aaKeys(InterState *istate, Expressions *arguments) 
    26572678{ 
    26582679#if LOG 
    26592680    printf("interpret_aaKeys()\n"); 
    26602681#endif 
     
    26752696 
    26762697Expression *interpret_aaValues(InterState *istate, Expressions *arguments) 
    26772698{ 
    26782699    //printf("interpret_aaValues()\n"); 
    26792700    if (!arguments || arguments->dim != 3) 
    26802701    return NULL; 
    26812702    Expression *earg = (Expression *)arguments->data[0]; 
    26822703    earg = earg->interpret(istate); 
    26832704    if (earg == EXP_CANT_INTERPRET) 
    26842705    return NULL; 
    26852706    if (earg->op != TOKassocarrayliteral) 
    26862707    return NULL; 
    26872708    AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 
    26882709    Expression *e = new ArrayLiteralExp(aae->loc, aae->values); 
    26892710    Type *elemType = ((TypeAArray *)aae->type)->next; 
    26902711    e->type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments->dim : 0)); 
    26912712    //printf("result is %s\n", e->toChars()); 
    26922713    return e; 
    26932714} 
    26942715 
     2716#endif 
     2717 
     2718#if DMDV2 
     2719 
     2720Expression *interpret_length(InterState *istate, Expression *earg) 
     2721{ 
     2722    //printf("interpret_length()\n"); 
     2723    earg = earg->interpret(istate); 
     2724    if (earg == EXP_CANT_INTERPRET) 
     2725    return NULL; 
     2726    if (earg->op != TOKassocarrayliteral) 
     2727    return NULL; 
     2728    AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 
     2729    Expression *e = new IntegerExp(aae->loc, aae->keys->dim, Type::tsize_t); 
     2730    return e; 
     2731} 
     2732 
     2733Expression *interpret_keys(InterState *istate, Expression *earg, FuncDeclaration *fd) 
     2734{ 
     2735#if LOG 
     2736    printf("interpret_keys()\n"); 
     2737#endif 
     2738    earg = earg->interpret(istate); 
     2739    if (earg == EXP_CANT_INTERPRET) 
     2740    return NULL; 
     2741    if (earg->op != TOKassocarrayliteral) 
     2742    return NULL; 
     2743    AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 
     2744    Expression *e = new ArrayLiteralExp(aae->loc, aae->keys); 
     2745    assert(fd->type->ty == Tfunction); 
     2746    assert(fd->type->nextOf()->ty == Tarray); 
     2747    Type *elemType = ((TypeFunction *)fd->type)->nextOf()->nextOf(); 
     2748    e->type = new TypeSArray(elemType, new IntegerExp(aae->keys->dim)); 
     2749    return e; 
     2750} 
     2751 
     2752Expression *interpret_values(InterState *istate, Expression *earg, FuncDeclaration *fd) 
     2753{ 
     2754    //printf("interpret_values()\n"); 
     2755    earg = earg->interpret(istate); 
     2756    if (earg == EXP_CANT_INTERPRET) 
     2757    return NULL; 
     2758    if (earg->op != TOKassocarrayliteral) 
     2759    return NULL; 
     2760    AssocArrayLiteralExp *aae = (AssocArrayLiteralExp *)earg; 
     2761    Expression *e = new ArrayLiteralExp(aae->loc, aae->values); 
     2762    assert(fd->type->ty == Tfunction); 
     2763    assert(fd->type->nextOf()->ty == Tarray); 
     2764    Type *elemType = ((TypeFunction *)fd->type)->nextOf()->nextOf(); 
     2765    e->type = new TypeSArray(elemType, new IntegerExp(aae->values->dim)); 
     2766    //printf("result is %s\n", e->toChars()); 
     2767    return e; 
     2768} 
     2769 
     2770#endif 
     2771 
  • trunk/src/constfold.c

    r199 r314  
    10751075    if (e1->type->equals(type) && type->equals(to)) 
    10761076    return e1; 
    10771077    if (e1->type->implicitConvTo(to) >= MATCHconst || 
    10781078    to->implicitConvTo(e1->type) >= MATCHconst) 
    10791079    return expType(to, e1); 
    10801080 
    10811081    Type *tb = to->toBasetype(); 
    10821082    Type *typeb = type->toBasetype(); 
    10831083 
    10841084    /* Allow casting from one string type to another 
    10851085     */ 
    10861086    if (e1->op == TOKstring) 
    10871087    { 
    10881088    if (tb->ty == Tarray && typeb->ty == Tarray && 
    10891089        tb->nextOf()->size() == typeb->nextOf()->size()) 
    10901090    { 
    10911091        return expType(to, e1); 
    10921092    } 
    10931093    } 
    10941094 
     1095    if (e1->op == TOKarrayliteral && typeb == tb) 
     1096        return e1; 
     1097 
    10951098    if (e1->isConst() != 1) 
    10961099    return EXP_CANT_INTERPRET; 
    10971100 
    10981101    if (tb->ty == Tbool) 
    10991102    e = new IntegerExp(loc, e1->toInteger() != 0, type); 
    11001103    else if (type->isintegral()) 
    11011104    { 
    11021105    if (e1->type->isfloating()) 
    11031106    {   dinteger_t result; 
    11041107        real_t r = e1->toReal(); 
    11051108 
    11061109        switch (typeb->ty) 
    11071110        { 
    11081111        case Tint8: result = (d_int8)r; break; 
    11091112        case Tchar: 
    11101113        case Tuns8: result = (d_uns8)r; break; 
    11111114        case Tint16:    result = (d_int16)r;    break; 
    11121115        case Twchar: 
    11131116        case Tuns16:    result = (d_uns16)r;    break; 
    11141117        case Tint32:    result = (d_int32)r;    break; 
  • trunk/src/declaration.c

    r307 r314  
    14271427       ) 
    14281428    { 
    14291429    return 0; 
    14301430    } 
    14311431#else 
    14321432    if (storage_class & STCmanifest) 
    14331433    return 0; 
    14341434#endif 
    14351435    return 1; 
    14361436} 
    14371437 
    14381438/******************************* 
    14391439 * Does symbol go into data segment? 
    14401440 * Includes extern variables. 
    14411441 */ 
    14421442 
    14431443int VarDeclaration::isDataseg() 
    14441444{ 
    14451445#if 0 
    14461446    printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars()); 
    1447     printf("%x, %p, %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance()); 
     1447    printf("%llx, isModule: %p, isTemplateInstance: %p\n", storage_class & (STCstatic | STCconst), parent->isModule(), parent->isTemplateInstance()); 
    14481448    printf("parent = '%s'\n", parent->toChars()); 
    14491449#endif 
    14501450    if (storage_class & STCmanifest) 
    14511451    return 0; 
    14521452    Dsymbol *parent = this->toParent(); 
    14531453    if (!parent && !(storage_class & STCstatic)) 
    14541454    {   error("forward referenced"); 
    14551455    type = Type::terror; 
    14561456    return 0; 
    14571457    } 
    14581458    return canTakeAddressOf() && 
    14591459    (storage_class & (STCstatic | STCextern | STCtls | STCgshared) || 
    14601460     toParent()->isModule() || 
    14611461     toParent()->isTemplateInstance()); 
    14621462} 
    14631463 
    14641464/************************************ 
    14651465 * Does symbol go into thread local storage? 
    14661466 */ 
    14671467 
    14681468int VarDeclaration::isThreadlocal() 
    14691469{ 
    14701470    //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars()); 
    14711471#if 0 || TARGET_OSX 
    14721472    /* To be thread-local, must use the __thread storage class. 
    14731473     * BUG: OSX doesn't support thread local yet. 
    14741474     */ 
    14751475    return isDataseg() && 
    14761476    (storage_class & (STCtls | STCconst | STCimmutable | STCshared | STCgshared)) == STCtls; 
    14771477#else 
    14781478    /* Data defaults to being thread-local. It is not thread-local 
    14791479     * if it is immutable, const or shared. 
    14801480     */ 
    14811481    int i = isDataseg() && 
    14821482    !(storage_class & (STCimmutable | STCconst | STCshared | STCgshared)); 
    14831483    //printf("\treturn %d\n", i); 
    14841484    return i; 
    14851485#endif 
    14861486} 
    14871487 
     1488/******************************************** 
     1489 * Can variable be read and written by CTFE? 
     1490 */ 
     1491 
     1492int VarDeclaration::isCTFE() 
     1493{ 
     1494    return (storage_class & STCctfe) || !isDataseg(); 
     1495} 
     1496 
    14881497int VarDeclaration::hasPointers() 
    14891498{ 
    14901499    //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type->ty); 
    14911500    return (!isDataseg() && type->hasPointers()); 
    14921501} 
    14931502 
    14941503/****************************************** 
    14951504 * Return TRUE if variable needs to call the destructor. 
    14961505 */ 
    14971506 
    14981507int VarDeclaration::needsAutoDtor() 
    14991508{ 
    15001509    //printf("VarDeclaration::needsAutoDtor() %s\n", toChars()); 
    15011510 
    15021511    if (noauto || storage_class & STCnodtor) 
    15031512    return FALSE; 
    15041513 
    15051514    // Destructors for structs and arrays of structs 
    15061515    Type *tv = type->toBasetype(); 
    15071516    while (tv->ty == Tsarray) 
  • trunk/src/declaration.h

    r305 r314  
    6464    STCimmutable    = 0x100000, 
    6565    STCref      = 0x200000, 
    6666    STCinit     = 0x400000,     // has explicit initializer 
    6767    STCmanifest     = 0x800000,     // manifest constant 
    6868    STCnodtor       = 0x1000000,    // don't run destructor 
    6969    STCnothrow      = 0x2000000,    // never throws exceptions 
    7070    STCpure     = 0x4000000,    // pure function 
    7171    STCtls      = 0x8000000,    // thread local 
    7272    STCalias        = 0x10000000,   // alias parameter 
    7373    STCshared       = 0x20000000,   // accessible from multiple threads 
    7474    STCgshared      = 0x40000000,   // accessible from multiple threads 
    7575                    // but not typed as "shared" 
    7676    STCwild         = 0x80000000,   // for "wild" type constructor 
    7777    STC_TYPECTOR    = (STCconst | STCimmutable | STCshared | STCwild), 
    7878}; 
    7979 
    8080#define STCproperty 0x100000000LL 
    8181#define STCsafe     0x200000000LL 
    8282#define STCtrusted  0x400000000LL 
    8383#define STCsystem   0x800000000LL 
     84#define STCctfe     0x1000000000LL  // can be used in CTFE, even if it is static 
    8485 
    8586struct Match 
    8687{ 
    8788    int count;          // number of matches found 
    8889    MATCH last;         // match level of lastf 
    8990    FuncDeclaration *lastf; // last matching function we found 
    9091    FuncDeclaration *nextf; // current matching function 
    9192    FuncDeclaration *anyf;  // pick a func, any func, to use for error recovery 
    9293}; 
    9394 
    9495void overloadResolveX(Match *m, FuncDeclaration *f, 
    9596    Expression *ethis, Expressions *arguments); 
    9697int overloadApply(FuncDeclaration *fstart, 
    9798    int (*fp)(void *, FuncDeclaration *), 
    9899    void *param); 
    99100 
    100101/**************************************************************/ 
    101102 
    102103struct Declaration : Dsymbol 
    103104{ 
     
    251252#if DMDV2 
    252253    VarDeclaration *rundtor;    // if !NULL, rundtor is tested at runtime to see 
    253254                // if the destructor should be run. Used to prevent 
    254255                // dtor calls on postblitted vars 
    255256#endif 
    256257 
    257258    VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init); 
    258259    Dsymbol *syntaxCopy(Dsymbol *); 
    259260    void semantic(Scope *sc); 
    260261    void semantic2(Scope *sc); 
    261262    const char *kind(); 
    262263    void toCBuffer(OutBuffer *buf, HdrGenState *hgs); 
    263264#ifdef _DH 
    264265    Type *htype; 
    265266    Initializer *hinit; 
    266267#endif 
    267268    int needThis(); 
    268269    int isImportedSymbol(); 
    269270    int isDataseg(); 
    270271    int isThreadlocal(); 
     272    int isCTFE(); 
    271273    int hasPointers(); 
    272274#if DMDV2 
    273275    int canTakeAddressOf(); 
    274276    int needsAutoDtor(); 
    275277#endif 
    276278    Expression *callAutoDtor(Scope *sc); 
    277279    ExpInitializer *getExpInitializer(); 
    278280    Expression *getConstInitializer(); 
    279281    void checkCtorConstInit(); 
    280282    void checkNestedReference(Scope *sc, Loc loc); 
    281283    Dsymbol *toAlias(); 
    282284 
    283285    Symbol *toSymbol(); 
    284286    void toObjFile(int multiobj);           // compile to .obj file 
    285287    int cvMember(unsigned char *p); 
    286288 
    287289    // Eliminate need for dynamic_cast 
    288290    VarDeclaration *isVarDeclaration() { return (VarDeclaration *)this; } 
    289291}; 
    290292 
  • trunk/src/expression.c

    r313 r314  
    696696        Type *tret = p->isLazyArray(); 
    697697        switch (tb->ty) 
    698698        { 
    699699            case Tsarray: 
    700700            case Tarray: 
    701701            {   // Create a static array variable v of type arg->type 
    702702#ifdef IN_GCC 
    703703            /* GCC 4.0 does not like zero length arrays used like 
    704704               this; pass a null array value instead. Could also 
    705705               just make a one-element array. */ 
    706706            if (nargs - i == 0) 
    707707            { 
    708708                arg = new NullExp(loc); 
    709709                break; 
    710710            } 
    711711#endif 
    712712            Identifier *id = Lexer::uniqueId("__arrayArg"); 
    713713            Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i)); 
    714714            t = t->semantic(loc, sc); 
    715715            VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc)); 
     716            v->storage_class |= STCctfe; 
    716717            v->semantic(sc); 
    717718            v->parent = sc->parent; 
    718719            //sc->insert(v); 
    719720 
    720721            Expression *c = new DeclarationExp(0, v); 
    721722            c->type = v->type; 
    722723 
    723724            for (size_t u = i; u < nargs; u++) 
    724725            {   Expression *a = (Expression *)arguments->data[u]; 
    725726                if (tret && !((TypeArray *)tb)->next->equals(a->type)) 
    726727                a = a->toDelegate(sc, tret); 
    727728 
    728729                Expression *e = new VarExp(loc, v); 
    729730                e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams)); 
    730731                AssignExp *ae = new AssignExp(loc, e, a); 
    731732#if DMDV2 
    732733                ae->op = TOKconstruct; 
    733734#endif 
    734735                if (c) 
    735736                c = new CommaExp(loc, c, ae); 
  • trunk/src/interpret.c

    r310 r314  
    9696    return NULL; 
    9797 
    9898    if (!fbody) 
    9999    {   cantInterpret = 1; 
    100100    return NULL; 
    101101    } 
    102102 
    103103    if (semanticRun < 3 && scope) 
    104104    { 
    105105    semantic3(scope); 
    106106    if (global.errors)  // if errors compiling this function 
    107107        return NULL; 
    108108    } 
    109109    if (semanticRun < 4) 
    110110    return NULL; 
    111111 
    112112    Type *tb = type->toBasetype(); 
    113113    assert(tb->ty == Tfunction); 
    114114    TypeFunction *tf = (TypeFunction *)tb; 
    115115    Type *tret = tf->next->toBasetype(); 
    116     if (tf->varargs
     116    if (tf->varargs && arguments && parameters && arguments->dim != parameters->dim
    117117    {   cantInterpret = 1; 
    118     error("Variadic functions are not yet implemented in CTFE"); 
     118    error("C-style variadic functions are not yet implemented in CTFE"); 
    119119    return NULL; 
    120120    } 
    121121     
    122122    // Ensure there are no lazy parameters 
    123123    if (tf->parameters) 
    124124    {   size_t dim = Parameter::dim(tf->parameters); 
    125125    for (size_t i = 0; i < dim; i++) 
    126126    {   Parameter *arg = Parameter::getNth(tf->parameters, i); 
    127127        if (arg->storageClass & STClazy) 
    128128        {   cantInterpret = 1; 
    129129        return NULL; 
    130130        } 
    131131    } 
    132132    } 
    133133 
    134134    InterState istatex; 
    135135    istatex.caller = istate; 
    136136    istatex.fd = this; 
    137137    istatex.localThis = thisarg; 
    138138 
     
    10061006} 
    10071007 
    10081008Expression *getVarExp(Loc loc, InterState *istate, Declaration *d) 
    10091009{ 
    10101010    Expression *e = EXP_CANT_INTERPRET; 
    10111011    VarDeclaration *v = d->isVarDeclaration(); 
    10121012    SymbolDeclaration *s = d->isSymbolDeclaration(); 
    10131013    if (v) 
    10141014    { 
    10151015#if DMDV2 
    10161016    if ((v->isConst() || v->isImmutable() || v->storage_class & STCmanifest) && v->init && !v->value) 
    10171017#else 
    10181018    if (v->isConst() && v->init) 
    10191019#endif 
    10201020    {   e = v->init->toExpression(); 
    10211021        if (e && !e->type) 
    10221022        e->type = v->type; 
    10231023    } 
    10241024    else 
    10251025    {   e = v->value; 
    1026         if (v->isDataseg()) 
     1026        if (!v->isCTFE()) 
    10271027        {   error(loc, "static variable %s cannot be read at compile time", v->toChars()); 
    10281028        e = EXP_CANT_INTERPRET; 
    10291029        } 
    10301030        else if (!e) 
    10311031        error(loc, "variable %s is used before initialization", v->toChars()); 
    10321032        else if (e != EXP_CANT_INTERPRET) 
    10331033        e = e->interpret(istate); 
    10341034    } 
    10351035    if (!e) 
    10361036        e = EXP_CANT_INTERPRET; 
    10371037    } 
    10381038    else if (s) 
    10391039    { 
    10401040    if (s->dsym->toInitializer() == s->sym) 
    10411041    {   Expressions *exps = new Expressions(); 
    10421042        e = new StructLiteralExp(0, s->dsym, exps); 
    10431043        e = e->semantic(NULL); 
    10441044    } 
    10451045    } 
    10461046    return e; 
     
    15981598    } 
    15991599 
    16001600    // To reduce code complexity of handling dotvar expressions, 
    16011601    // extract the aggregate now. 
    16021602    Expression *aggregate; 
    16031603    if (e1->op == TOKdotvar) { 
    16041604        aggregate = ((DotVarExp *)e1)->e1; 
    16051605    // Get rid of 'this'. 
    16061606        if (aggregate->op == TOKthis && istate->localThis) 
    16071607            aggregate = istate->localThis;   
    16081608    } 
    16091609     
    16101610    /* Assignment to variable of the form: 
    16111611     *  v = e2 
    16121612     */ 
    16131613    if (e1->op == TOKvar) 
    16141614    { 
    16151615    VarExp *ve = (VarExp *)e1; 
    16161616    VarDeclaration *v = ve->var->isVarDeclaration(); 
    16171617    assert(v); 
    1618     if (v && v->isDataseg()) 
     1618    if (v && !v->isCTFE()) 
    16191619    {   // Can't modify global or static data 
    16201620        error("%s cannot be modified at compile time", v->toChars()); 
    16211621        return EXP_CANT_INTERPRET; 
    16221622    } 
    1623     if (v && !v->isDataseg()) 
     1623    if (v && v->isCTFE()) 
    16241624    { 
    16251625        Expression *ev = v->value; 
    16261626        if (fp && !ev) 
    16271627        {   error("variable %s is used before initialization", v->toChars()); 
    16281628        return e; 
    16291629        } 
    16301630        if (fp) 
    16311631        e2 = (*fp)(v->type, ev, e2); 
    16321632        else 
    16331633        {   /* Look for special case of struct being initialized with 0. 
    16341634         */ 
    16351635        if (v->type->toBasetype()->ty == Tstruct && e2->op == TOKint64) 
    16361636        { 
    16371637            e2 = v->type->defaultInit(); 
    16381638        } 
    16391639        e2 = Cast(v->type, v->type, e2); 
    16401640        } 
    16411641        if (e2 == EXP_CANT_INTERPRET) 
    16421642        return e2; 
    16431643 
    16441644        addVarToInterstate(istate, v); 
    16451645        v->value = e2; 
    16461646        e = Cast(type, type, post ? ev : e2); 
    16471647    } 
    16481648    } 
    16491649    else if (e1->op == TOKdotvar && aggregate->op == TOKdotvar) 
    16501650    {   // eg  v.u.var = e2,  v[3].u.var = e2, etc. 
    16511651    error("Nested struct assignment %s is not yet supported in CTFE", toChars()); 
    16521652    } 
    16531653    /* Assignment to struct member of the form: 
    16541654     *   v.var = e2 
    16551655     */ 
    16561656    else if (e1->op == TOKdotvar && aggregate->op == TOKvar) 
    16571657    {   VarDeclaration *v = ((VarExp *)aggregate)->var->isVarDeclaration(); 
    16581658 
    1659     if (v->isDataseg()) 
     1659    if (!v->isCTFE()) 
    16601660    {   // Can't modify global or static data 
    16611661        error("%s cannot be modified at compile time", v->toChars()); 
    16621662        return EXP_CANT_INTERPRET; 
    16631663    } else { 
    16641664        // Chase down rebinding of out and ref 
    16651665        if (v->value && v->value->op == TOKvar) 
    16661666        { 
    16671667        VarExp *ve2 = (VarExp *)v->value; 
    16681668        if (ve2->var->isSymbolDeclaration()) 
    16691669        {   // This can happen if v is a struct initialized to 
    16701670            // 0 using an __initZ SymbolDeclaration from 
    16711671            // TypeStruct::defaultInit() 
    16721672        } 
    16731673        else 
    16741674            v = ve2->var->isVarDeclaration(); 
    16751675        assert(v); 
    16761676        } 
    16771677    } 
    16781678    if (fp && !v->value) 
    16791679    {   error("variable %s is used before initialization", v->toChars()); 
     
    17111711    if (e2 == EXP_CANT_INTERPRET) 
    17121712        return e2; 
    17131713 
    17141714    addVarToInterstate(istate, v); 
    17151715 
    17161716    /* Create new struct literal reflecting updated fieldi 
    17171717     */ 
    17181718    Expressions *expsx = changeOneElement(se->elements, fieldi, e2); 
    17191719    v->value = new StructLiteralExp(se->loc, se->sd, expsx); 
    17201720    v->value->type = se->type; 
    17211721 
    17221722    e = Cast(type, type, post ? ev : e2); 
    17231723    } 
    17241724    /* Assignment to struct member of the form: 
    17251725     *   *(symoffexp) = e2 
    17261726     */ 
    17271727    else if (e1->op == TOKstar && ((PtrExp *)e1)->e1->op == TOKsymoff) 
    17281728    {   SymOffExp *soe = (SymOffExp *)((PtrExp *)e1)->e1; 
    17291729    VarDeclaration *v = soe->var->isVarDeclaration(); 
    17301730 
    1731     if (v->isDataseg()) 
     1731    if (!v->isCTFE()) 
    17321732    { 
    17331733        error("%s cannot be modified at compile time", v->toChars()); 
    17341734        return EXP_CANT_INTERPRET; 
    17351735    } 
    17361736    if (fp && !v->value) 
    17371737    {   error("variable %s is used before initialization", v->toChars()); 
    17381738        return e; 
    17391739    } 
    17401740    Expression *vie = v->value; 
    17411741    if (vie->op == TOKvar) 
    17421742    { 
    17431743        Declaration *d = ((VarExp *)vie)->var; 
    17441744        vie = getVarExp(e1->loc, istate, d); 
    17451745    } 
    17461746    if (vie->op != TOKstructliteral) 
    17471747        return EXP_CANT_INTERPRET; 
    17481748    StructLiteralExp *se = (StructLiteralExp *)vie; 
    17491749    int fieldi = se->getFieldIndex(type, soe->offset); 
    17501750    if (fieldi == -1) 
    17511751        return EXP_CANT_INTERPRET; 
     
    17571757    if (e2 == EXP_CANT_INTERPRET) 
    17581758        return e2; 
    17591759 
    17601760    addVarToInterstate(istate, v); 
    17611761 
    17621762    /* Create new struct literal reflecting updated fieldi 
    17631763     */ 
    17641764    Expressions *expsx = changeOneElement(se->elements, fieldi, e2); 
    17651765    v->value = new StructLiteralExp(se->loc, se->sd, expsx); 
    17661766    v->value->type = se->type; 
    17671767 
    17681768    e = Cast(type, type, post ? ev : e2); 
    17691769    } 
    17701770    /* Assignment to array element of the form: 
    17711771     *   a[i] = e2 
    17721772     */ 
    17731773    else if (e1->op == TOKindex && ((IndexExp *)e1)->e1->op == TOKvar) 
    17741774    {   IndexExp *ie = (IndexExp *)e1; 
    17751775    VarExp *ve = (VarExp *)ie->e1; 
    17761776    VarDeclaration *v = ve->var->isVarDeclaration(); 
    1777     if (!v || v->isDataseg()) 
     1777    if (!v || !v->isCTFE()) 
    17781778    { 
    17791779        error("%s cannot be modified at compile time", v ? v->toChars(): "void"); 
    17801780        return EXP_CANT_INTERPRET; 
    17811781    } 
    17821782        if (v->value && v->value->op == TOKvar) 
    17831783        { 
    17841784        VarExp *ve2 = (VarExp *)v->value; 
    17851785        if (ve2->var->isSymbolDeclaration()) 
    17861786        {   // This can happen if v is a struct initialized to 
    17871787            // 0 using an __initZ SymbolDeclaration from 
    17881788            // TypeStruct::defaultInit() 
    17891789        } 
    17901790        else 
    17911791            v = ve2->var->isVarDeclaration(); 
    17921792        assert(v); 
    17931793        } 
    17941794    if (!v->value) 
    17951795    { 
    17961796        if (fp) 
    17971797        {   error("variable %s is used before initialization", v->toChars()); 
     
    19201920        se2->committed = se->committed; 
    19211921        se2->postfix = se->postfix; 
    19221922        se2->type = se->type; 
    19231923        v->value = se2; 
    19241924    } 
    19251925    else 
    19261926        assert(0); 
    19271927 
    19281928    e = Cast(type, type, post ? ev : e2); 
    19291929    } 
    19301930     
    19311931    /* Assignment to struct element in array, of the form: 
    19321932     *  a[i].var = e2 
    19331933     */ 
    19341934    else if (e1->op == TOKdotvar && aggregate->op == TOKindex && 
    19351935         ((IndexExp *)aggregate)->e1->op == TOKvar) 
    19361936    { 
    19371937        IndexExp * ie = (IndexExp *)aggregate; 
    19381938    VarExp *ve = (VarExp *)(ie->e1); 
    19391939    VarDeclaration *v = ve->var->isVarDeclaration(); 
    1940     if (!v || v->isDataseg()) 
     1940    if (!v || !v->isCTFE()) 
    19411941    { 
    19421942        error("%s cannot be modified at compile time", v ? v->toChars(): "void"); 
    19431943        return EXP_CANT_INTERPRET; 
    19441944    } 
    19451945    Type *t = ve->type->toBasetype(); 
    19461946    ArrayLiteralExp *ae = (ArrayLiteralExp *)v->value; 
    19471947    if (!ae) 
    19481948    { 
    19491949        // assignment to one element in an uninitialized (static) array. 
    19501950        // This is quite difficult, because defaultInit() for a struct is a VarExp, 
    19511951        // not a StructLiteralExp. 
    19521952        Type *t = v->type->toBasetype(); 
    19531953        if (t->ty != Tsarray) 
    19541954        { 
    19551955        error("Cannot index an uninitialized variable"); 
    19561956        return EXP_CANT_INTERPRET; 
    19571957        } 
    19581958 
    19591959        Type *telem = ((TypeSArray *)t)->nextOf()->toBasetype(); 
    19601960        if (telem->ty != Tstruct) { return EXP_CANT_INTERPRET; } 
     
    20122012        e2 = Cast(type, type, e2); 
    20132013    if (e2 == EXP_CANT_INTERPRET) 
    20142014        return e2; 
    20152015 
    20162016    // Create new struct literal reflecting updated field 
    20172017    Expressions *expsx = changeOneElement(se->elements, fieldi, e2); 
    20182018    Expression * newstruct = new StructLiteralExp(se->loc, se->sd, expsx); 
    20192019 
    20202020    // Create new array literal reflecting updated struct elem 
    20212021    ae->elements = changeOneElement(ae->elements, elemi, newstruct); 
    20222022    return ae; 
    20232023    } 
    20242024    /* Slice assignment, initialization of static arrays 
    20252025     *   a[] = e 
    20262026     */ 
    20272027    else if (e1->op == TOKslice && ((SliceExp *)e1)->e1->op==TOKvar) 
    20282028    { 
    20292029        SliceExp * sexp = (SliceExp *)e1; 
    20302030    VarExp *ve = (VarExp *)(sexp->e1); 
    20312031    VarDeclaration *v = ve->var->isVarDeclaration(); 
    2032     if (!v || v->isDataseg()) 
     2032    if (!v || !v->isCTFE()) 
    20332033    { 
    20342034        error("%s cannot be modified at compile time", v->toChars()); 
    20352035        return EXP_CANT_INTERPRET; 
    20362036    } 
    20372037        // Chase down rebinding of out and ref 
    20382038        if (v->value && v->value->op == TOKvar) 
    20392039        { 
    20402040        VarExp *ve2 = (VarExp *)v->value; 
    20412041        if (ve2->var->isSymbolDeclaration()) 
    20422042        {   // This can happen if v is a struct initialized to 
    20432043            // 0 using an __initZ SymbolDeclaration from 
    20442044            // TypeStruct::defaultInit() 
    20452045        } 
    20462046        else 
    20472047            v = ve2->var->isVarDeclaration(); 
    20482048        assert(v); 
    20492049        } 
    20502050    /* Set the $ variable 
    20512051     */ 
    20522052    Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value)