Changes in src/Tuples/TupleAssignment.cc [5fb6830:03321e4]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Tuples/TupleAssignment.cc
r5fb6830 r03321e4 14 14 // 15 15 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 35 41 36 42 namespace Tuples { … … 78 84 if ( ! expr ) return false; 79 85 assert( expr->has_result() ); 80 return dynamic_cast< TupleType * >( expr->get_result() ->stripReferences());86 return dynamic_cast< TupleType * >( expr->get_result() ); 81 87 } 82 88 … … 90 96 } 91 97 92 bool refToTuple( Expression *expr ) { 93 assert( expr->get_result() ); 98 bool pointsToTuple( Expression *expr ) { 94 99 // also check for function returning tuple of reference types 95 100 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() ); 99 104 } 100 105 return false; … … 111 116 void TupleAssignSpotter::spot( UntypedExpr * expr, const std::list<ResolvExpr::AltList> &possibilities ) { 112 117 if ( NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) { 113 if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) {118 if ( InitTweak::isCtorDtorAssign( op->get_name() ) ) { 114 119 fname = op->get_name(); 115 120 for ( std::list<ResolvExpr::AltList>::const_iterator ali = possibilities.begin(); ali != possibilities.end(); ++ali ) { 116 121 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() ) ) { 118 123 // what does it mean if an assignment takes 1 argument? maybe someone defined such a function, in which case AlternativeFinder will naturally handle it 119 124 continue; … … 124 129 const ResolvExpr::Alternative & alt1 = ali->front(); 125 130 auto begin = std::next(ali->begin(), 1), end = ali->end(); 126 if ( refToTuple(alt1.expr) ) {131 if ( pointsToTuple(alt1.expr) ) { 127 132 if ( isMultAssign( begin, end ) ) { 128 133 matcher.reset( new MultipleAssignMatcher( *this, *ali ) ); … … 182 187 183 188 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; 187 196 } 188 197 … … 190 199 explode( lhsAlt, spotter.currentFinder.get_indexer(), back_inserter(lhs), true ); 191 200 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 ); 196 211 } 197 212 } … … 213 228 assert( left ); 214 229 std::list< Expression * > args; 215 args.push_back( new VariableExpr( left) );230 args.push_back( new AddressExpr( UntypedExpr::createDeref( new VariableExpr( left ) ) ) ); 216 231 // args.push_back( new AddressExpr( new VariableExpr( left ) ) ); 217 232 if ( right ) args.push_back( new VariableExpr( right ) ); … … 233 248 assert( expr->has_result() && ! expr->get_result()->isVoid() ); 234 249 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 ); 243 255 return ret; 244 256 }
Note:
See TracChangeset
for help on using the changeset viewer.