Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

Changeset 1499:df11cdec45a2

Show
Ignore:
Timestamp:
06/14/09 13:49:58 (3 years ago)
Author:
Christian Kamm <kamm incasoftware de>
branch:
default
Message:

Another shot at fixing the issues with (constant) struct literals and their addresses. See DMD2682, #218, #324.

The idea is to separate the notion of const from 'this variable can always be
replaced with its initializer' in the frontend. To do that, I introduced
Declaration::isSameAsInitializer, which is overridden in VarDeclaration? to
return false for constants that have a struct literal initializer.

So

const S s = S(5);
void foo() { auto ps = &s; }
// is no longer replaced by
void foo() { auto ps = &(S(5)); }

To make taking the address of a struct constant with a struct-initializer
outside of function scope possible, I made sure that AddrExp::optimize doesn't
try to run the argument's optimization with WANTinterpret - that'd again
replace the constant with a struct literal temporary.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • dmd/declaration.c

    r1482 r1499  
    12141214} 
    12151215 
     1216int VarDeclaration::isSameAsInitializer() 
     1217{ 
     1218    if (init && init->isExpInitializer() &&  
     1219        init->isExpInitializer()->exp->op == TOKstructliteral) 
     1220        return 0; 
     1221    return isConst(); 
     1222} 
     1223 
    12161224/****************************************** 
    12171225 * If a variable has an auto destructor call, return call for it. 
  • dmd/declaration.h

    r1482 r1499  
    136136    int isDeprecated()   { return storage_class & STCdeprecated; } 
    137137    int isOverride()     { return storage_class & STCoverride; } 
     138     
     139    virtual int isSameAsInitializer() { return isConst(); }; 
    138140 
    139141    int isIn()    { return storage_class & STCin; } 
     
    283285    void checkNestedReference(Scope *sc, Loc loc); 
    284286    Dsymbol *toAlias(); 
     287     
     288    virtual int isSameAsInitializer(); 
    285289 
    286290#if IN_DMD 
  • dmd/expression.c

    r1372 r1499  
    21142114        } 
    21152115    } 
    2116     if (v->isConst() && type->toBasetype()->ty != Tsarray) 
     2116    if (v->isSameAsInitializer() && type->toBasetype()->ty != Tsarray) 
    21172117    { 
    21182118        if (v->init) 
     
    32433243#endif 
    32443244 
    3245 /* 
    3246 Removed in LDC. See declaration. 
    32473245Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e) 
    32483246{ 
    32493247    return this; 
    32503248} 
    3251 */ 
    32523249 
    32533250 
     
    39503947    if (v) 
    39513948    { 
    3952     if (v->isConst() && type->toBasetype()->ty != Tsarray && v->init) 
     3949    if (v->isSameAsInitializer() && type->toBasetype()->ty != Tsarray && v->init) 
    39533950    { 
    39543951        ExpInitializer *ei = v->init->isExpInitializer(); 
     
    53565353        } 
    53575354        type = v->type; 
    5358         if (v->isConst()) 
     5355        if (v->isSameAsInitializer()) 
    53595356        { 
    53605357            if (v->init) 
     
    56155612 
    56165613        VarDeclaration *v = var->isVarDeclaration(); 
    5617         if (v && v->isConst()) 
     5614        if (v && v->isSameAsInitializer()) 
    56185615        {   ExpInitializer *ei = v->getExpInitializer(); 
    56195616        if (ei) 
  • dmd/expression.h

    r1372 r1499  
    510510    Expression *optimize(int result); 
    511511    Expression *interpret(InterState *istate); 
    512     // LDC: struct literals aren't lvalues! Taking their address can lead to  
    513     //      incorrect behavior, see LDC#218, DMD#2682 
    514     // Expression *toLvalue(Scope *sc, Expression *e); 
     512    Expression *toLvalue(Scope *sc, Expression *e); 
    515513 
    516514    int inlineCost(InlineCostState *ics); 
  • dmd/mtype.c

    r1393 r1499  
    34103410        if (v && id == Id::length) 
    34113411        { 
    3412             if (v->isConst() && v->getExpInitializer()) 
     3412            if (v->isSameAsInitializer() && v->getExpInitializer()) 
    34133413            {   e = v->getExpInitializer()->exp; 
    34143414            } 
     
    34573457    { 
    34583458        // It's not a type, it's an expression 
    3459         if (v->isConst() && v->getExpInitializer()) 
     3459        if (v->isSameAsInitializer() && v->getExpInitializer()) 
    34603460        { 
    34613461        ExpInitializer *ei = v->getExpInitializer(); 
     
    45214521 
    45224522    v = s->isVarDeclaration(); 
    4523     if (v && v->isConst() && v->type->toBasetype()->ty != Tsarray) 
     4523    if (v && v->isSameAsInitializer() && v->type->toBasetype()->ty != Tsarray) 
    45244524    {   ExpInitializer *ei = v->getExpInitializer(); 
    45254525 
     
    49334933    s = s->toAlias(); 
    49344934    v = s->isVarDeclaration(); 
    4935     if (v && v->isConst() && v->type->toBasetype()->ty != Tsarray) 
     4935    if (v && v->isSameAsInitializer() && v->type->toBasetype()->ty != Tsarray) 
    49364936    {   ExpInitializer *ei = v->getExpInitializer(); 
    49374937 
  • dmd/optimize.c

    r1367 r1499  
    195195 
    196196    //printf("AddrExp::optimize(result = %d) %s\n", result, toChars()); 
    197     e1 = e1->optimize(result); 
     197    // never try to interpret: it could change the semantics by turning 
     198    // const p = &s; into an something like const p = &(Struct()); 
     199    e1 = e1->optimize(result & ~WANTinterpret); 
    198200    // Convert &*ex to ex 
    199201    if (e1->op == TOKstar) 
Copyright © 2008, LDC Development Team.