Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Expr.cpp

    r312029a rcf32116  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed May 15 17:00:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Created On       : Thr Jun 13 13:38:00 2019
    13 // Update Count     : 6
     11// Last Modified By : Andrew Beach
     12// Created On       : Thr Jun 26 12:12:00 2019
     13// Update Count     : 3
    1414//
    1515
     
    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 );
     
    7188}
    7289
     90bool UntypedExpr::get_lvalue() const {
     91        std::string fname = InitTweak::getFunctionName( this );
     92        return lvalueFunctionNames.count( fname );
     93}
     94
    7395UntypedExpr * UntypedExpr::createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs ) {
    7496        assert( lhs && rhs );
    7597
    76         UntypedExpr * ret = new UntypedExpr{
    77                 loc, new NameExpr{loc, "?=?"}, std::vector<ptr<Expr>>{ ptr<Expr>{ lhs }, ptr<Expr>{ rhs } }
    78         };
     98        UntypedExpr * ret = call( loc, "?=?", lhs, rhs );
    7999        if ( lhs->result && rhs->result ) {
    80100                // if both expressions are typed, assumes that this assignment is a C bitwise assignment,
     
    108128AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) : Expr( loc ), arg( a ) {
    109129        if ( arg->result ) {
    110                 if ( arg->result->is_lvalue() ) {
     130                if ( arg->get_lvalue() ) {
    111131                        // lvalue, retains all levels of reference, and gains a pointer inside the references
    112132                        Type * res = addrType( arg->result );
     
    139159: Expr( loc, new VoidType{} ), arg( a ), isGenerated( g ) {}
    140160
     161bool CastExpr::get_lvalue() const {
     162        // This is actually wrong by C, but it works with our current set-up.
     163        return arg->get_lvalue();
     164}
     165
    141166// --- KeywordCastExpr
    142167
    143 const char * KeywordCastExpr::targetString() const {
    144         return AggregateDecl::aggrString( target );
     168const std::string & KeywordCastExpr::targetString() const {
     169        static const std::string targetStrs[] = {
     170                "coroutine", "thread", "monitor"
     171        };
     172        static_assert(
     173                (sizeof(targetStrs) / sizeof(targetStrs[0])) == ((unsigned long)NUMBER_OF_TARGETS),
     174                "Each KeywordCastExpr::Target should have a corresponding string representation"
     175        );
     176        return targetStrs[(unsigned long)target];
     177}
     178
     179// --- UntypedMemberExpr
     180
     181bool UntypedMemberExpr::get_lvalue() const {
     182        return aggregate->get_lvalue();
    145183}
    146184
     
    153191        assert( aggregate->result );
    154192
    155         // take ownership of member type
    156         result = mem->get_type();
     193        // Deep copy on result type avoids mutation on transitively multiply referenced object.
     194        //
     195        // Example, adapted from parts of builtins and bootloader:
     196        //
     197        // forall(dtype T)
     198        // struct __Destructor {
     199        //   T * object;
     200        //   void (*dtor)(T *);
     201        // };
     202        //
     203        // forall(dtype S)
     204        // void foo(__Destructor(S) &d) {
     205        //   if (d.dtor) {  // here
     206        //   }
     207        // }
     208        //
     209        // Let e be the "d.dtor" guard espression, which is MemberExpr after resolve.  Let d be the
     210        // declaration of member __Destructor.dtor (an ObjectDecl), as accessed via the top-level
     211        // declaration of __Destructor.  Consider the types e.result and d.type.  In the old AST, one
     212        // is a clone of the other.  Ordinary new-AST use would set them up as a multiply-referenced
     213        // object.
     214        //
     215        // e.result: PointerType
     216        // .base: FunctionType
     217        // .params.front(): ObjectDecl, the anonymous parameter of type T*
     218        // .type: PointerType
     219        // .base: TypeInstType
     220        // let x = that
     221        // let y = similar, except start from d.type
     222        //
     223        // Consider two code lines down, genericSubstitution(...).apply(result).
     224        //
     225        // Applying this chosen-candidate's type substitution means modifying x, substituting
     226        // S for T.  This mutation should affect x and not y.
     227
     228        result = deepCopy(mem->get_type());
     229
    157230        // substitute aggregate generic parameters into member type
    158231        genericSubstitution( aggregate->result ).apply( result );
     
    161234}
    162235
     236MemberExpr::MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
     237    MemberExpr::NoOpConstruction overloadSelector )
     238: Expr( loc ), member( mem ), aggregate( agg ) {
     239        assert( member );
     240        assert( aggregate );
     241        assert( aggregate->result );
     242        (void) overloadSelector;
     243}
     244
     245bool MemberExpr::get_lvalue() const {
     246        // This is actually wrong by C, but it works with our current set-up.
     247        return true;
     248}
     249
    163250// --- VariableExpr
    164251
     
    170257        assert( var );
    171258        assert( var->get_type() );
    172         result = var->get_type();
    173         add_qualifiers( result, CV::Lvalue );
     259        auto r = shallowCopy( var->get_type() );
     260        r->qualifiers |= CV::Lvalue;
     261        result = r;
     262}
     263
     264bool VariableExpr::get_lvalue() const {
     265        // It isn't always an lvalue, but it is never an rvalue.
     266        return true;
    174267}
    175268
     
    258351: Expr( loc, new BasicType{ BasicType::SignedInt } ), arg1( a1 ), arg2( a2 ), isAnd( ia ) {}
    259352
     353// --- CommaExpr
     354bool CommaExpr::get_lvalue() const {
     355        // This is wrong by C, but the current implementation uses it.
     356        // (ex: Specialize, Lvalue and Box)
     357        return arg2->get_lvalue();
     358}
     359
    260360// --- ConstructorExpr
    261361
     
    279379}
    280380
     381bool CompoundLiteralExpr::get_lvalue() const {
     382        return true;
     383}
     384
    281385// --- TupleExpr
    282386
     
    294398        result = type->types[ index ];
    295399        add_qualifiers( result, CV::Lvalue );
     400}
     401
     402bool TupleIndexExpr::get_lvalue() const {
     403        return tuple->get_lvalue();
    296404}
    297405
Note: See TracChangeset for help on using the changeset viewer.