Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Expr.cpp

    r3e5dd913 r490fb92e  
    102102        }
    103103        return ret;
    104 }
    105 
    106 // --- VariableExpr
    107 
    108 VariableExpr::VariableExpr( const CodeLocation & loc )
    109 : Expr( loc ), var( nullptr ) {}
    110 
    111 VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
    112 : Expr( loc ), var( v ) {
    113         assert( var );
    114         assert( var->get_type() );
    115         result = shallowCopy( var->get_type() );
    116 }
    117 
    118 bool VariableExpr::get_lvalue() const {
    119         // It isn't always an lvalue, but it is never an rvalue.
    120         return true;
    121 }
    122 
    123 VariableExpr * VariableExpr::functionPointer(
    124                 const CodeLocation & loc, const FunctionDecl * decl ) {
    125         // wrap usually-determined result type in a pointer
    126         VariableExpr * funcExpr = new VariableExpr{ loc, decl };
    127         funcExpr->result = new PointerType{ funcExpr->result };
    128         return funcExpr;
    129104}
    130105
     
    206181        assert( aggregate->result );
    207182
    208         result = mem->get_type();
     183        // Deep copy on result type avoids mutation on transitively multiply referenced object.
     184        //
     185        // Example, adapted from parts of builtins and bootloader:
     186        //
     187        // forall(dtype T)
     188        // struct __Destructor {
     189        //   T * object;
     190        //   void (*dtor)(T *);
     191        // };
     192        //
     193        // forall(dtype S)
     194        // void foo(__Destructor(S) &d) {
     195        //   if (d.dtor) {  // here
     196        //   }
     197        // }
     198        //
     199        // Let e be the "d.dtor" guard espression, which is MemberExpr after resolve.  Let d be the
     200        // declaration of member __Destructor.dtor (an ObjectDecl), as accessed via the top-level
     201        // declaration of __Destructor.  Consider the types e.result and d.type.  In the old AST, one
     202        // is a clone of the other.  Ordinary new-AST use would set them up as a multiply-referenced
     203        // object.
     204        //
     205        // e.result: PointerType
     206        // .base: FunctionType
     207        // .params.front(): ObjectDecl, the anonymous parameter of type T*
     208        // .type: PointerType
     209        // .base: TypeInstType
     210        // let x = that
     211        // let y = similar, except start from d.type
     212        //
     213        // Consider two code lines down, genericSubstitution(...).apply(result).
     214        //
     215        // Applying this chosen-candidate's type substitution means modifying x, substituting
     216        // S for T.  This mutation should affect x and not y.
     217
     218        result = deepCopy(mem->get_type());
    209219
    210220        // substitute aggregate generic parameters into member type
     
    226236        // This is actually wrong by C, but it works with our current set-up.
    227237        return true;
     238}
     239
     240// --- VariableExpr
     241
     242VariableExpr::VariableExpr( const CodeLocation & loc )
     243: Expr( loc ), var( nullptr ) {}
     244
     245VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
     246: Expr( loc ), var( v ) {
     247        assert( var );
     248        assert( var->get_type() );
     249        result = shallowCopy( var->get_type() );
     250}
     251
     252bool VariableExpr::get_lvalue() const {
     253        // It isn't always an lvalue, but it is never an rvalue.
     254        return true;
     255}
     256
     257VariableExpr * VariableExpr::functionPointer(
     258                const CodeLocation & loc, const FunctionDecl * decl ) {
     259        // wrap usually-determined result type in a pointer
     260        VariableExpr * funcExpr = new VariableExpr{ loc, decl };
     261        funcExpr->result = new PointerType{ funcExpr->result };
     262        return funcExpr;
    228263}
    229264
Note: See TracChangeset for help on using the changeset viewer.