Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Expr.cpp

    r312029a rd5631b3  
    2020#include <vector>
    2121
     22#include "Copy.hpp"                // for shallowCopy
     23#include "Eval.hpp"                // for call
    2224#include "GenericSubstitution.hpp"
     25#include "LinkageSpec.hpp"
    2326#include "Stmt.hpp"
    2427#include "Type.hpp"
     
    2730#include "Common/SemanticError.h"
    2831#include "GenPoly/Lvalue.h"        // for referencesPermissable
    29 #include "InitTweak/InitTweak.h"   // for getPointerBase
     32#include "InitTweak/InitTweak.h"   // for getFunction, getPointerBase
    3033#include "ResolvExpr/typeops.h"    // for extractResultType
    3134#include "Tuples/Tuples.h"         // for makeTupleType
    3235
    3336namespace ast {
     37
     38namespace {
     39        std::set<std::string> const lvalueFunctionNames = {"*?", "?[?]"};
     40}
     41
     42// --- Expr
     43bool Expr::get_lvalue() const {
     44        return false;
     45}
    3446
    3547// --- ApplicationExpr
     
    4658}
    4759
     60bool ApplicationExpr::get_lvalue() const {
     61        if ( const DeclWithType * func = InitTweak::getFunction( this ) ) {
     62                return func->linkage == Linkage::Intrinsic && lvalueFunctionNames.count( func->name );
     63        }
     64        return false;
     65}
     66
    4867// --- UntypedExpr
    4968
     
    5170        assert( arg );
    5271
    53         UntypedExpr * ret = new UntypedExpr{
    54                 loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } }
    55         };
     72        UntypedExpr * ret = call( loc, "*?", arg );
    5673        if ( const Type * ty = arg->result ) {
    5774                const Type * base = InitTweak::getPointerBase( ty );
     
    6582                        // base type
    6683                        ret->result = base;
    67                         add_qualifiers( ret->result, CV::Lvalue );
    6884                }
    6985        }
    7086        return ret;
     87}
     88
     89bool UntypedExpr::get_lvalue() const {
     90        std::string fname = InitTweak::getFunctionName( this );
     91        return lvalueFunctionNames.count( fname );
    7192}
    7293
     
    7495        assert( lhs && rhs );
    7596
    76         UntypedExpr * ret = new UntypedExpr{
    77                 loc, new NameExpr{loc, "?=?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ lhs }, ptr<Expr>{ rhs } }
    78         };
     97        UntypedExpr * ret = call( loc, "?=?", lhs, rhs );
    7998        if ( lhs->result && rhs->result ) {
    8099                // if both expressions are typed, assumes that this assignment is a C bitwise assignment,
     
    83102        }
    84103        return ret;
     104}
     105
     106// --- VariableExpr
     107
     108VariableExpr::VariableExpr( const CodeLocation & loc )
     109: Expr( loc ), var( nullptr ) {}
     110
     111VariableExpr::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
     118bool VariableExpr::get_lvalue() const {
     119        // It isn't always an lvalue, but it is never an rvalue.
     120        return true;
     121}
     122
     123VariableExpr * 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;
    85129}
    86130
     
    108152AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) : Expr( loc ), arg( a ) {
    109153        if ( arg->result ) {
    110                 if ( arg->result->is_lvalue() ) {
     154                if ( arg->get_lvalue() ) {
    111155                        // lvalue, retains all levels of reference, and gains a pointer inside the references
    112156                        Type * res = addrType( arg->result );
    113                         res->set_lvalue( false ); // result of & is never an lvalue
    114157                        result = res;
    115158                } else {
     
    118161                                        dynamic_cast< const ReferenceType * >( arg->result.get() ) ) {
    119162                                Type * res = addrType( refType->base );
    120                                 res->set_lvalue( false ); // result of & is never an lvalue
    121163                                result = res;
    122164                        } else {
     
    139181: Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}
    140182
     183bool CastExpr::get_lvalue() const {
     184        // This is actually wrong by C, but it works with our current set-up.
     185        return arg->get_lvalue();
     186}
     187
    141188// --- KeywordCastExpr
    142189
    143190const char * KeywordCastExpr::targetString() const {
    144191        return AggregateDecl::aggrString( target );
     192}
     193
     194// --- UntypedMemberExpr
     195
     196bool UntypedMemberExpr::get_lvalue() const {
     197        return aggregate->get_lvalue();
    145198}
    146199
     
    153206        assert( aggregate->result );
    154207
    155         // take ownership of member type
    156         result = mem->get_type();
     208        // Deep copy on result type avoids mutation on transitively multiply referenced object.
     209        //
     210        // Example, adapted from parts of builtins and bootloader:
     211        //
     212        // forall(dtype T)
     213        // struct __Destructor {
     214        //   T * object;
     215        //   void (*dtor)(T *);
     216        // };
     217        //
     218        // forall(dtype S)
     219        // void foo(__Destructor(S) &d) {
     220        //   if (d.dtor) {  // here
     221        //   }
     222        // }
     223        //
     224        // Let e be the "d.dtor" guard espression, which is MemberExpr after resolve.  Let d be the
     225        // declaration of member __Destructor.dtor (an ObjectDecl), as accessed via the top-level
     226        // declaration of __Destructor.  Consider the types e.result and d.type.  In the old AST, one
     227        // is a clone of the other.  Ordinary new-AST use would set them up as a multiply-referenced
     228        // object.
     229        //
     230        // e.result: PointerType
     231        // .base: FunctionType
     232        // .params.front(): ObjectDecl, the anonymous parameter of type T*
     233        // .type: PointerType
     234        // .base: TypeInstType
     235        // let x = that
     236        // let y = similar, except start from d.type
     237        //
     238        // Consider two code lines down, genericSubstitution(...).apply(result).
     239        //
     240        // Applying this chosen-candidate's type substitution means modifying x, substituting
     241        // S for T.  This mutation should affect x and not y.
     242
     243        result = deepCopy(mem->get_type());
     244
    157245        // substitute aggregate generic parameters into member type
    158246        genericSubstitution( aggregate->result ).apply( result );
    159         // ensure lvalue and appropriate restrictions from aggregate type
    160         add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue );
    161 }
    162 
    163 // --- VariableExpr
    164 
    165 VariableExpr::VariableExpr( const CodeLocation & loc )
    166 : Expr( loc ), var( nullptr ) {}
    167 
    168 VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
    169 : Expr( loc ), var( v ) {
    170         assert( var );
    171         assert( var->get_type() );
    172         result = var->get_type();
    173         add_qualifiers( result, CV::Lvalue );
    174 }
    175 
    176 VariableExpr * VariableExpr::functionPointer(
    177                 const CodeLocation & loc, const FunctionDecl * decl ) {
    178         // wrap usually-determined result type in a pointer
    179         VariableExpr * funcExpr = new VariableExpr{ loc, decl };
    180         funcExpr->result = new PointerType{ funcExpr->result };
    181         return funcExpr;
     247        // ensure appropriate restrictions from aggregate type
     248        add_qualifiers( result, aggregate->result->qualifiers );
     249}
     250
     251MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
     252    MemberExpr::NoOpConstruction overloadSelector )
     253: Expr( loc ), member( mem ), aggregate( agg ) {
     254        assert( member );
     255        assert( aggregate );
     256        assert( aggregate->result );
     257        (void) overloadSelector;
     258}
     259
     260bool MemberExpr::get_lvalue() const {
     261        // This is actually wrong by C, but it works with our current set-up.
     262        return true;
    182263}
    183264
     
    258339: Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {}
    259340
     341// --- CommaExpr
     342bool CommaExpr::get_lvalue() const {
     343        // This is wrong by C, but the current implementation uses it.
     344        // (ex: Specialize, Lvalue and Box)
     345        return arg2->get_lvalue();
     346}
     347
    260348// --- ConstructorExpr
    261349
     
    276364        assert( t && i );
    277365        result = t;
    278         add_qualifiers( result, CV::Lvalue );
     366}
     367
     368bool CompoundLiteralExpr::get_lvalue() const {
     369        return true;
    279370}
    280371
     
    293384        // like MemberExpr, TupleIndexExpr is always an lvalue
    294385        result = type->types[ index ];
    295         add_qualifiers( result, CV::Lvalue );
     386}
     387
     388bool TupleIndexExpr::get_lvalue() const {
     389        return tuple->get_lvalue();
    296390}
    297391
Note: See TracChangeset for help on using the changeset viewer.