Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Tuples/TupleAssignment.cc

    r5fb6830 r03321e4  
    1414//
    1515
    16 #include "ResolvExpr/AlternativeFinder.h"
    17 #include "ResolvExpr/Alternative.h"
    18 #include "ResolvExpr/typeops.h"
    19 #include "SynTree/Expression.h"
    20 #include "SynTree/Initializer.h"
    21 #include "Tuples.h"
    22 #include "Explode.h"
    23 #include "Common/SemanticError.h"
    24 #include "CodeGen/OperatorTable.h"
    25 #include "InitTweak/InitTweak.h"
    26 #include "InitTweak/GenInit.h"
    27 
    28 #include <functional>
    29 #include <algorithm>
    30 #include <iterator>
    31 #include <iostream>
    32 #include <cassert>
    33 #include <set>
    34 #include <unordered_set>
     16#include <algorithm>                       // for transform
     17#include <cassert>                         // for assert
     18#include <iterator>                        // for back_insert_iterator, back...
     19#include <list>                            // for _List_const_iterator, _Lis...
     20#include <memory>                          // for unique_ptr, allocator_trai...
     21#include <string>                          // for string
     22
     23#include "Common/UniqueName.h"             // for UniqueName
     24#include "Common/utility.h"                // for zipWith
     25#include "Explode.h"                       // for explode
     26#include "InitTweak/GenInit.h"             // for genCtorInit
     27#include "InitTweak/InitTweak.h"           // for getPointerBase, isAssignment
     28#include "Parser/LinkageSpec.h"            // for Cforall
     29#include "ResolvExpr/Alternative.h"        // for AltList, Alternative
     30#include "ResolvExpr/AlternativeFinder.h"  // for AlternativeFinder, simpleC...
     31#include "ResolvExpr/Cost.h"               // for Cost
     32#include "ResolvExpr/Resolver.h"           // for resolveCtorInit
     33#include "ResolvExpr/TypeEnvironment.h"    // for TypeEnvironment
     34#include "SynTree/Declaration.h"           // for ObjectDecl
     35#include "SynTree/Expression.h"            // for Expression, CastExpr, Name...
     36#include "SynTree/Initializer.h"           // for ConstructorInit, SingleInit
     37#include "SynTree/Statement.h"             // for ExprStmt
     38#include "SynTree/Type.h"                  // for Type, Type::Qualifiers
     39#include "SynTree/TypeSubstitution.h"      // for TypeSubstitution
     40#include "SynTree/Visitor.h"               // for Visitor
    3541
    3642namespace Tuples {
     
    7884                if ( ! expr ) return false;
    7985                assert( expr->has_result() );
    80                 return dynamic_cast< TupleType * >( expr->get_result()->stripReferences() );
     86                return dynamic_cast< TupleType * >( expr->get_result() );
    8187        }
    8288
     
    9096        }
    9197
    92         bool refToTuple( Expression *expr ) {
    93                 assert( expr->get_result() );
     98        bool pointsToTuple( Expression *expr ) {
    9499                // also check for function returning tuple of reference types
    95100                if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    96                         return refToTuple( castExpr->get_arg() );
    97                 } else {
    98                         return isTuple( expr );
     101                        return pointsToTuple( castExpr->get_arg() );
     102                } else if ( AddressExpr *addr = dynamic_cast< AddressExpr * >( expr) ) {
     103                        return isTuple( addr->get_arg() );
    99104                }
    100105                return false;
     
    111116        void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) {
    112117                if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
    113                         if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) {
     118                        if ( InitTweak::isCtorDtorAssign( op->get_name() ) ) {
    114119                                fname = op->get_name();
    115120                                for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) {
    116121                                        if ( ali->size() == 0 ) continue; // AlternativeFinder will natrually handle this case, if it's legal
    117                                         if ( ali->size() <= 1 && CodeGen::isAssignment( op->get_name() ) ) {
     122                                        if ( ali->size() <= 1 && InitTweak::isAssignment( op->get_name() ) ) {
    118123                                                // what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it
    119124                                                continue;
     
    124129                                        const ResolvExpr::Alternative & alt1 = ali->front();
    125130                                        auto begin = std::next(ali->begin(), 1), end = ali->end();
    126                                         if ( refToTuple(alt1.expr) ) {
     131                                        if ( pointsToTuple(alt1.expr) ) {
    127132                                                if ( isMultAssign( begin, end ) ) {
    128133                                                        matcher.reset( new MultipleAssignMatcher( *this, *ali ) );
     
    182187
    183188                ResolvExpr::Alternative lhsAlt = alts.front();
    184                 // explode is aware of casts - ensure every LHS expression is sent into explode with a reference cast
    185                 if ( ! dynamic_cast< CastExpr * >( lhsAlt.expr ) ) {
    186                         lhsAlt.expr = new CastExpr( lhsAlt.expr, new ReferenceType( Type::Qualifiers(), lhsAlt.expr->get_result()->clone() ) );
     189                // peel off the cast that exists on ctor/dtor expressions
     190                bool isCast = false;
     191                if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( lhsAlt.expr ) ) {
     192                        lhsAlt.expr = castExpr->get_arg();
     193                        castExpr->set_arg( nullptr );
     194                        delete castExpr;
     195                        isCast = true;
    187196                }
    188197
     
    190199                explode( lhsAlt, spotter.currentFinder.get_indexer(), back_inserter(lhs), true );
    191200
    192                 for ( ResolvExpr::Alternative & alt : lhs ) {
    193                         // every LHS value must be a reference - some come in with a cast expression, if it doesn't just cast to reference here.
    194                         if ( ! dynamic_cast< ReferenceType * >( alt.expr->get_result() ) ) {
    195                                 alt.expr = new CastExpr( alt.expr, new ReferenceType( Type::Qualifiers(), alt.expr->get_result()->clone() ) );
     201                // and finally, re-add the cast to each lhs expr, so that qualified tuple fields can be constructed
     202                if ( isCast ) {
     203                        for ( ResolvExpr::Alternative & alt : lhs ) {
     204                                Expression *& expr = alt.expr;
     205                                Type * castType = expr->get_result()->clone();
     206                                Type * type = InitTweak::getPointerBase( castType );
     207                                assert( type );
     208                                type->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
     209                                type->set_lvalue( true ); // xxx - might not need this
     210                                expr = new CastExpr( expr, castType );
    196211                        }
    197212                }
     
    213228                assert( left );
    214229                std::list< Expression * > args;
    215                 args.push_back( new VariableExpr( left ) );
     230                args.push_back( new AddressExpr( UntypedExpr::createDeref( new VariableExpr( left ) ) ) );
    216231                // args.push_back( new AddressExpr( new VariableExpr( left ) ) );
    217232                if ( right ) args.push_back( new VariableExpr( right ) );
     
    233248                assert( expr->has_result() && ! expr->get_result()->isVoid() );
    234249                ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->get_result()->clone(), new SingleInit( expr->clone() ) );
    235                 // if expression type is a reference, don't need to construct anything, a simple initializer is sufficient.
    236                 if ( ! dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
    237                         ConstructorInit * ctorInit = InitTweak::genCtorInit( ret );
    238                         ret->set_init( ctorInit );
    239                         ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object
    240                         EnvRemover rm; // remove environments from subexpressions of StmtExprs
    241                         ctorInit->accept( rm );
    242                 }
     250                ConstructorInit * ctorInit = InitTweak::genCtorInit( ret );
     251                ret->set_init( ctorInit );
     252                ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object
     253                EnvRemover rm; // remove environments from subexpressions of StmtExprs
     254                ctorInit->accept( rm );
    243255                return ret;
    244256        }
Note: See TracChangeset for help on using the changeset viewer.