Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Expr.cpp

    r490fb92e r312029a  
    2020#include <vector>
    2121
    22 #include "Copy.hpp"                // for shallowCopy
    23 #include "Eval.hpp"                // for call
    2422#include "GenericSubstitution.hpp"
    25 #include "LinkageSpec.hpp"
    2623#include "Stmt.hpp"
    2724#include "Type.hpp"
     
    3027#include "Common/SemanticError.h"
    3128#include "GenPoly/Lvalue.h"        // for referencesPermissable
    32 #include "InitTweak/InitTweak.h"   // for getFunction, getPointerBase
     29#include "InitTweak/InitTweak.h"   // for getPointerBase
    3330#include "ResolvExpr/typeops.h"    // for extractResultType
    3431#include "Tuples/Tuples.h"         // for makeTupleType
    3532
    3633namespace ast {
    37 
    38 namespace {
    39         std::set<std::string> const lvalueFunctionNames = {"*?", "?[?]"};
    40 }
    41 
    42 // --- Expr
    43 bool Expr::get_lvalue() const {
    44         return false;
    45 }
    4634
    4735// --- ApplicationExpr
     
    5846}
    5947
    60 bool 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 
    6748// --- UntypedExpr
    6849
    69 UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, const Expr * arg ) {
     50UntypedExpr * UntypedExpr::createDeref( const CodeLocation & loc, Expr * arg ) {
    7051        assert( arg );
    7152
    72         UntypedExpr * ret = call( loc, "*?", arg );
     53        UntypedExpr * ret = new UntypedExpr{
     54                loc, new NameExpr{loc, "*?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ arg } }
     55        };
    7356        if ( const Type * ty = arg->result ) {
    7457                const Type * base = InitTweak::getPointerBase( ty );
     
    8265                        // base type
    8366                        ret->result = base;
     67                        add_qualifiers( ret->result, CV::Lvalue );
    8468                }
    8569        }
     
    8771}
    8872
    89 bool UntypedExpr::get_lvalue() const {
    90         std::string fname = InitTweak::getFunctionName( this );
    91         return lvalueFunctionNames.count( fname );
    92 }
    93 
    94 UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, const Expr * lhs, const Expr * rhs ) {
     73UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs ) {
    9574        assert( lhs && rhs );
    9675
    97         UntypedExpr * ret = call( loc, "?=?", lhs, rhs );
     76        UntypedExpr * ret = new UntypedExpr{
     77                loc, new NameExpr{loc, "?=?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ lhs }, ptr<Expr>{ rhs } }
     78        };
    9879        if ( lhs->result && rhs->result ) {
    9980                // if both expressions are typed, assumes that this assignment is a C bitwise assignment,
     
    127108AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) : Expr( loc ), arg( a ) {
    128109        if ( arg->result ) {
    129                 if ( arg->get_lvalue() ) {
     110                if ( arg->result->is_lvalue() ) {
    130111                        // lvalue, retains all levels of reference, and gains a pointer inside the references
    131112                        Type * res = addrType( arg->result );
     113                        res->set_lvalue( false ); // result of & is never an lvalue
    132114                        result = res;
    133115                } else {
     
    136118                                        dynamic_cast< const ReferenceType * >( arg->result.get() ) ) {
    137119                                Type * res = addrType( refType->base );
     120                                res->set_lvalue( false ); // result of & is never an lvalue
    138121                                result = res;
    139122                        } else {
     
    156139: Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}
    157140
    158 bool CastExpr::get_lvalue() const {
    159         // This is actually wrong by C, but it works with our current set-up.
    160         return arg->get_lvalue();
    161 }
    162 
    163141// --- KeywordCastExpr
    164142
    165143const char * KeywordCastExpr::targetString() const {
    166144        return AggregateDecl::aggrString( target );
    167 }
    168 
    169 // --- UntypedMemberExpr
    170 
    171 bool UntypedMemberExpr::get_lvalue() const {
    172         return aggregate->get_lvalue();
    173145}
    174146
     
    181153        assert( aggregate->result );
    182154
    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());
    219 
     155        // take ownership of member type
     156        result = mem->get_type();
    220157        // substitute aggregate generic parameters into member type
    221158        genericSubstitution( aggregate->result ).apply( result );
    222         // ensure appropriate restrictions from aggregate type
    223         add_qualifiers( result, aggregate->result->qualifiers );
    224 }
    225 
    226 MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
    227     MemberExpr::NoOpConstruction overloadSelector )
    228 : Expr( loc ), member( mem ), aggregate( agg ) {
    229         assert( member );
    230         assert( aggregate );
    231         assert( aggregate->result );
    232         (void) overloadSelector;
    233 }
    234 
    235 bool MemberExpr::get_lvalue() const {
    236         // This is actually wrong by C, but it works with our current set-up.
    237         return true;
     159        // ensure lvalue and appropriate restrictions from aggregate type
     160        add_qualifiers( result, aggregate->result->qualifiers | CV::Lvalue );
    238161}
    239162
     
    247170        assert( var );
    248171        assert( var->get_type() );
    249         result = shallowCopy( var->get_type() );
    250 }
    251 
    252 bool VariableExpr::get_lvalue() const {
    253         // It isn't always an lvalue, but it is never an rvalue.
    254         return true;
     172        result = var->get_type();
     173        add_qualifiers( result, CV::Lvalue );
    255174}
    256175
     
    338257        const CodeLocation & loc, const Expr * a1, const Expr * a2, LogicalFlag ia )
    339258: Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {}
    340 
    341 // --- CommaExpr
    342 bool 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 }
    347259
    348260// --- ConstructorExpr
     
    364276        assert( t && i );
    365277        result = t;
    366 }
    367 
    368 bool CompoundLiteralExpr::get_lvalue() const {
    369         return true;
     278        add_qualifiers( result, CV::Lvalue );
    370279}
    371280
     
    384293        // like MemberExpr, TupleIndexExpr is always an lvalue
    385294        result = type->types[ index ];
    386 }
    387 
    388 bool TupleIndexExpr::get_lvalue() const {
    389         return tuple->get_lvalue();
     295        add_qualifiers( result, CV::Lvalue );
    390296}
    391297
Note: See TracChangeset for help on using the changeset viewer.