Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/TupleAssignment.cc

    r615a096 r7d49b72  
    2222#include "Explode.h"
    2323#include "Common/SemanticError.h"
     24#include "CodeGen/OperatorTable.h"
    2425#include "InitTweak/InitTweak.h"
    2526#include "InitTweak/GenInit.h"
     
    7778                if ( ! expr ) return false;
    7879                assert( expr->has_result() );
    79                 return dynamic_cast< TupleType * >( expr->get_result() );
     80                return dynamic_cast< TupleType * >( expr->get_result()->stripReferences() );
    8081        }
    8182
     
    8990        }
    9091
    91         bool pointsToTuple( Expression *expr ) {
     92        bool refToTuple( Expression *expr ) {
     93                assert( expr->get_result() );
    9294                // also check for function returning tuple of reference types
    9395                if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    94                         return pointsToTuple( castExpr->get_arg() );
    95                 } else if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ) {
    96                         return isTuple( addr->get_arg() );
     96                        return refToTuple( castExpr->get_arg() );
     97                } else {
     98                        return isTuple( expr );
    9799                }
    98100                return false;
     
    109111        void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) {
    110112                if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
    111                         if ( InitTweak::isCtorDtorAssign( op->get_name() ) ) {
     113                        if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) {
    112114                                fname = op->get_name();
    113115                                for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
    114116                                        if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal
    115                                         if ( ali->size() <= 1 && InitTweak::isAssignment( op->get_name() ) ) {
     117                                        if ( ali->size() <= 1 && CodeGen::isAssignment( op->get_name() ) ) {
    116118                                                // what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it
    117119                                                continue;
     
    122124                                        const ResolvExpr::Alternative & alt1 = ali->front();
    123125                                        auto begin = std::next(ali->begin(), 1), end = ali->end();
    124                                         if ( pointsToTuple(alt1.expr) ) {
     126                                        if ( refToTuple(alt1.expr) ) {
    125127                                                if ( isMultAssign( begin, end ) ) {
    126128                                                        matcher.reset( new MultipleAssignMatcher( *this, *ali ) );
     
    196198                        for ( ResolvExpr::Alternative & alt : lhs ) {
    197199                                Expression *& expr = alt.expr;
    198                                 Type * castType = expr->get_result()->clone();
    199                                 Type * type = InitTweak::getPointerBase( castType );
    200                                 assert( type );
     200                                Type * type = expr->get_result()->clone();
    201201                                type->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
    202                                 type->set_lvalue( true ); // xxx - might not need this
    203                                 expr = new CastExpr( expr, castType );
     202                                expr = new CastExpr( expr, new ReferenceType( Type::Qualifiers(), type ) );
     203                        }
     204                }
     205
     206                for ( ResolvExpr::Alternative & alt : lhs ) {
     207                        // every LHS value must be a reference - some come in with a cast expression, if it doesn't just cast to reference here.
     208                        // TODO: can this somehow be merge with the cast code directly above?
     209                        if ( ! dynamic_cast< ReferenceType * >( alt.expr->get_result() ) ) {
     210                                alt.expr = new CastExpr( alt.expr, new ReferenceType( Type::Qualifiers(), alt.expr->get_result()->clone() ) );
    204211                        }
    205212                }
     
    221228                assert( left );
    222229                std::list< Expression * > args;
    223                 args.push_back( new AddressExpr( UntypedExpr::createDeref( new VariableExpr( left ) ) ) );
     230                args.push_back( new VariableExpr( left ) );
    224231                // args.push_back( new AddressExpr( new VariableExpr( left ) ) );
    225232                if ( right ) args.push_back( new VariableExpr( right ) );
     
    241248                assert( expr->has_result() && ! expr->get_result()->isVoid() );
    242249                ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) );
    243                 ConstructorInit * ctorInit = InitTweak::genCtorInit( ret );
    244                 ret->set_init( ctorInit );
    245                 ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object
    246                 EnvRemover rm; // remove environments from subexpressions of StmtExprs
    247                 ctorInit->accept( rm );
     250                // if expression type is a reference, don't need to construct anything, a simple initializer is sufficient.
     251                if ( ! dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
     252                        ConstructorInit * ctorInit = InitTweak::genCtorInit( ret );
     253                        ret->set_init( ctorInit );
     254                        ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object
     255                        EnvRemover rm; // remove environments from subexpressions of StmtExprs
     256                        ctorInit->accept( rm );
     257                }
    248258                return ret;
    249259        }
Note: See TracChangeset for help on using the changeset viewer.