Changeset 5802a4f for src/GenPoly
- Timestamp:
- Dec 15, 2016, 4:16:52 PM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 66f8528
- Parents:
- 9facf3b
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified src/GenPoly/Box.cc ¶
r9facf3b r5802a4f 54 54 #include "Common/UniqueName.h" 55 55 #include "Common/utility.h" 56 57 #include "InitTweak/InitTweak.h" 56 58 57 59 #include <ext/functional> // temporary … … 113 115 void addInferredParams( ApplicationExpr *appExpr, FunctionType *functionType, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ); 114 116 /// Stores assignment operators from assertion list in local map of assignment operations 115 void findTypeOps( const Type::ForallList &forall );116 117 void passAdapters( ApplicationExpr *appExpr, FunctionType *functionType, const TyVarMap &exprTyVars ); 117 118 FunctionDecl *makeAdapter( FunctionType *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ); … … 121 122 ObjectDecl *makeTemporary( Type *type ); 122 123 123 ScopedMap< std::string, DeclarationWithType* > assignOps; ///< Currently known type variable assignment operators124 ScopedMap< std::string, DeclarationWithType* > ctorOps; ///< Currently known type variable constructors125 ScopedMap< std::string, DeclarationWithType* > copyOps; ///< Currently known type variable copy constructors126 ScopedMap< std::string, DeclarationWithType* > dtorOps; ///< Currently known type variable destructors127 ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps; ///< Currently known assignment operators128 ResolvExpr::TypeMap< DeclarationWithType > scopedCtorOps; ///< Currently known assignment operators129 ResolvExpr::TypeMap< DeclarationWithType > scopedCopyOps; ///< Currently known assignment operators130 ResolvExpr::TypeMap< DeclarationWithType > scopedDtorOps; ///< Currently known assignment operators131 124 ScopedMap< std::string, DeclarationWithType* > adapters; ///< Set of adapter functions in the current scope 132 125 … … 500 493 Pass1::Pass1() : tempNamer( "_temp" ) {} 501 494 502 /// Returns T if the given declaration is a function with parameter (T*) for some TypeInstType T, NULL otherwise503 TypeInstType *isTypeInstPtrFn( DeclarationWithType *decl ) {504 if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {505 if ( funType->get_parameters().size() == 1 ) {506 if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {507 if ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {508 return refType;509 } // if510 } // if511 } // if512 } // if513 return 0;514 }515 516 /// Returns T if the given declaration is a function with parameters (T*, T) for some TypeInstType T, NULL otherwise517 TypeInstType *isTypeInstPtrValFn( DeclarationWithType *decl ) {518 if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {519 if ( funType->get_parameters().size() == 2 ) {520 if ( PointerType *pointer = dynamic_cast< PointerType *>( funType->get_parameters().front()->get_type() ) ) {521 if ( TypeInstType *refType = dynamic_cast< TypeInstType *>( pointer->get_base() ) ) {522 if ( TypeInstType *refType2 = dynamic_cast< TypeInstType *>( funType->get_parameters().back()->get_type() ) ) {523 if ( refType->get_name() == refType2->get_name() ) {524 return refType;525 } // if526 } // if527 } // if528 } // if529 } // if530 } // if531 return 0;532 }533 534 /// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise535 TypeInstType *isTypeInstAssignment( DeclarationWithType *decl ) {536 return decl->get_name() == "?=?" ? isTypeInstPtrValFn( decl ) : 0;537 }538 539 /// Returns T if the given declaration is (*?{})(T *) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise540 TypeInstType *isTypeInstCtor( DeclarationWithType *decl ) {541 return decl->get_name() == "?{}" ? isTypeInstPtrFn( decl ) : 0;542 }543 544 /// Returns T if the given declaration is (*?{})(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise545 TypeInstType *isTypeInstCopy( DeclarationWithType *decl ) {546 return decl->get_name() == "?{}" ? isTypeInstPtrValFn( decl ) : 0;547 }548 549 /// Returns T if the given declaration is (*^?{})(T *) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise550 TypeInstType *isTypeInstDtor( DeclarationWithType *decl ) {551 return decl->get_name() == "^?{}" ? isTypeInstPtrFn( decl ) : 0;552 }553 554 /// Returns T if the given declaration is a function with parameters (T*, T) for some type T, where neither parameter is cv-qualified,555 /// NULL otherwise556 Type *isNoCvPtrFn( DeclarationWithType *decl ) {557 if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {558 if ( funType->get_parameters().size() == 1 ) {559 Type::Qualifiers defaultQualifiers;560 Type *paramType = funType->get_parameters().front()->get_type();561 if ( paramType->get_qualifiers() != defaultQualifiers ) return 0;562 563 if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType ) ) {564 Type *baseType = pointerType->get_base();565 if ( baseType->get_qualifiers() == defaultQualifiers ) {566 return baseType;567 } // if568 } // if569 } // if570 } // if571 return 0;572 }573 574 /// Returns T if the given declaration is a function with parameters (T*, T) for some type T, where neither parameter is cv-qualified,575 /// NULL otherwise576 Type *isNoCvPtrValFn( DeclarationWithType *decl ) {577 if ( FunctionType *funType = getFunctionType( decl->get_type() ) ) {578 if ( funType->get_parameters().size() == 2 ) {579 Type::Qualifiers defaultQualifiers;580 Type *paramType1 = funType->get_parameters().front()->get_type();581 if ( paramType1->get_qualifiers() != defaultQualifiers ) return 0;582 Type *paramType2 = funType->get_parameters().back()->get_type();583 if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0;584 585 if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) {586 Type *baseType1 = pointerType->get_base();587 if ( baseType1->get_qualifiers() != defaultQualifiers ) return 0;588 SymTab::Indexer dummy;589 if ( ResolvExpr::typesCompatible( baseType1, paramType2, dummy ) ) {590 return baseType1;591 } // if592 } // if593 } // if594 } // if595 return 0;596 }597 598 /// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise599 /// Only picks assignments where neither parameter is cv-qualified600 Type *isAssignment( DeclarationWithType *decl ) {601 return decl->get_name() == "?=?" ? isNoCvPtrValFn( decl ) : 0;602 }603 604 /// returns T if the given declaration is: (*?{})(T *) for some type T, NULL otherwise605 /// Only picks ctors where the parameter is not cv-qualified606 Type *isCtor( DeclarationWithType *decl ) {607 return decl->get_name() == "?{}" ? isNoCvPtrFn( decl ) : 0;608 }609 610 /// returns T if the given declaration is: (*?{})(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise611 /// Only picks copy constructors where neither parameter is cv-qualified612 Type *isCopy( DeclarationWithType *decl ) {613 return decl->get_name() == "?{}" ? isNoCvPtrValFn( decl ) : 0;614 }615 616 /// returns T if the given declaration is: (*?{})(T *) for some type T, NULL otherwise617 /// Only picks ctors where the parameter is not cv-qualified618 Type *isDtor( DeclarationWithType *decl ) {619 return decl->get_name() == "^?{}" ? isNoCvPtrFn( decl ) : 0;620 }621 622 void Pass1::findTypeOps( const Type::ForallList &forall ) {623 // what if a nested function uses an assignment operator?624 // assignOps.clear();625 for ( Type::ForallList::const_iterator i = forall.begin(); i != forall.end(); ++i ) {626 for ( std::list< DeclarationWithType *>::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {627 std::string typeName;628 if ( TypeInstType *typeInst = isTypeInstAssignment( *assert ) ) {629 assignOps[ typeInst->get_name() ] = *assert;630 } else if ( TypeInstType *typeInst = isTypeInstCtor( *assert ) ) {631 ctorOps[ typeInst->get_name() ] = *assert;632 } else if ( TypeInstType *typeInst = isTypeInstCopy( *assert ) ) {633 copyOps[ typeInst->get_name() ] = *assert;634 } else if ( TypeInstType *typeInst = isTypeInstDtor( *assert ) ) {635 dtorOps[ typeInst->get_name() ] = *assert;636 } // if637 } // for638 } // for639 }640 641 495 DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) { 642 // if this is a assignment function, put it in the map for this scope643 if ( Type *paramType = isAssignment( functionDecl ) ) {644 if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {645 scopedAssignOps.insert( paramType, functionDecl );646 }647 } else if ( Type *paramType = isCtor( functionDecl ) ) {648 if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {649 scopedCtorOps.insert( paramType, functionDecl );650 }651 } else if ( Type *paramType = isCopy( functionDecl ) ) {652 if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {653 scopedCopyOps.insert( paramType, functionDecl );654 }655 } else if ( Type *paramType = isDtor( functionDecl ) ) {656 if ( ! dynamic_cast< TypeInstType* >( paramType ) ) {657 scopedDtorOps.insert( paramType, functionDecl );658 }659 }660 661 496 if ( functionDecl->get_statements() ) { // empty routine body ? 662 497 doBeginScope(); 663 498 scopeTyVars.beginScope(); 664 assignOps.beginScope();665 ctorOps.beginScope();666 copyOps.beginScope();667 dtorOps.beginScope();668 499 669 500 DeclarationWithType *oldRetval = retval; … … 683 514 FunctionType *functionType = functionDecl->get_functionType(); 684 515 makeTyVarMap( functionDecl->get_functionType(), scopeTyVars ); 685 findTypeOps( functionDecl->get_functionType()->get_forall() );686 516 687 517 std::list< DeclarationWithType *> ¶mList = functionType->get_parameters(); … … 707 537 708 538 scopeTyVars.endScope(); 709 assignOps.endScope();710 ctorOps.endScope();711 copyOps.endScope();712 dtorOps.endScope();713 539 retval = oldRetval; 714 540 doEndScope(); … … 811 637 Type *concRetType = replaceWithConcrete( appExpr, polyRetType ); 812 638 passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes ); 639 ++fnArg; // skip the return parameter in the argument list 813 640 } 814 641 815 642 // add type information args for presently unseen types in parameter list 816 643 for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) { 817 VariableExpr *fnArgBase = getBaseVar( *fnArg );818 if ( ! fnArgBase ) continue; // xxx - previously had check for non-empty fnArgBase results819 passArgTypeVars( appExpr, (*fnParm)->get_type(), fnArgBase->get_result(), arg, exprTyVars, seenTypes );644 if ( ! (*fnArg)->get_result() ) continue; 645 Type * argType = (*fnArg)->get_result(); 646 passArgTypeVars( appExpr, (*fnParm)->get_type(), argType, arg, exprTyVars, seenTypes ); 820 647 } 821 648 } … … 967 794 for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) { 968 795 InferredParams::const_iterator inferParam = appExpr->get_inferParams().find( (*assert)->get_uniqueId() ); 969 assert( inferParam != appExpr->get_inferParams().end() && "NOTE: Explicit casts of polymorphic functions to compatible monomorphic functions are currently unsupported" ); 796 if ( inferParam == appExpr->get_inferParams().end() ) { 797 std::cerr << "looking for assertion: " << (*assert) << std::endl << appExpr << std::endl; 798 } 799 assertf( inferParam != appExpr->get_inferParams().end(), "NOTE: Explicit casts of polymorphic functions to compatible monomorphic functions are currently unsupported" ); 970 800 Expression *newExpr = inferParam->second.expr->clone(); 971 801 addCast( newExpr, (*assert)->get_type(), tyVars ); … … 1295 1125 1296 1126 TyVarMap exprTyVars( TypeDecl::Data{} ); 1297 makeTyVarMap( function, exprTyVars ); 1127 makeTyVarMap( function, exprTyVars ); // xxx - should this take into account the variables already bound in scopeTyVars (i.e. remove them from exprTyVars?) 1298 1128 ReferenceToType *dynRetType = isDynRet( function, exprTyVars ); 1299 Type *concRetType = appExpr->get_result() ;// ?: dynRetType; // xxx - is concRetType a good name?1129 Type *concRetType = appExpr->get_result()->isVoid() ? nullptr : appExpr->get_result();// ?: dynRetType; // xxx - is concRetType a good name? 1300 1130 1301 1131 if ( dynRetType ) { 1302 1132 ret = addDynRetParam( appExpr, function, concRetType, arg ); // xxx - used to use dynRetType instead of concRetType 1303 } else if ( needsAdapter( function, scopeTyVars ) ) { 1133 } else if ( needsAdapter( function, scopeTyVars ) && ! needsAdapter( function, exprTyVars) ) { // xxx - exprTyVars is used above...? 1134 // xxx - the ! needsAdapter check may be incorrect. It seems there is some situation where an adapter is applied where it shouldn't be, and this fixes it for some cases. More investigation is needed. 1135 1304 1136 // std::cerr << "needs adapter: "; 1305 1137 // printTyVarMap( std::cerr, scopeTyVars ); … … 1310 1142 arg = appExpr->get_args().begin(); 1311 1143 1312 passTypeVars( appExpr, concRetType, arg, exprTyVars ); // xxx - used to use dynRetType instead of concRetType 1144 passTypeVars( appExpr, concRetType, arg, exprTyVars ); // xxx - used to use dynRetType instead of concRetType; this changed so that the correct type paramaters are passed for return types (it should be the concrete type's parameters, not the formal type's) 1313 1145 addInferredParams( appExpr, function, arg, exprTyVars ); 1314 1146 … … 1369 1201 } 1370 1202 1371 /// Wraps a function declaration in a new pointer-to-function variable expression1372 VariableExpr *wrapFunctionDecl( DeclarationWithType *functionDecl ) {1373 // line below cloned from FixFunction.cc1374 // xxx - functionObj is never added to a list of declarations...1375 // alternatively, this function could return a new VariableExpr( functionDecl ) and change the result type of the new expression1376 ObjectDecl *functionObj = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,1377 new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );1378 functionObj->set_mangleName( functionDecl->get_mangleName() );1379 functionObj->set_scopeLevel( functionDecl->get_scopeLevel() );1380 return new VariableExpr( functionObj );1381 }1382 1383 /// Finds the operation declaration for a given type in one of the two maps1384 DeclarationWithType* findOpForType( Type *formalType, const ScopedMap< std::string, DeclarationWithType* >& ops, ResolvExpr::TypeMap< DeclarationWithType >& scopedOps ) {1385 if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) {1386 ScopedMap< std::string, DeclarationWithType *>::const_iterator opIt = ops.find( formalTypeInstType->get_name() );1387 return opIt == ops.end() ? 0 : opIt->second;1388 } else {1389 return scopedOps.find( formalType );1390 }1391 }1392 1393 /// Adds an assertion parameter to the application expression for the actual assertion declaration valued with the assert op1394 void addAssertionFor( ApplicationExpr *appExpr, DeclarationWithType *actualDecl, DeclarationWithType *assertOp ) {1395 appExpr->get_inferParams()[ actualDecl->get_uniqueId() ]1396 = ParamEntry( assertOp->get_uniqueId(), assertOp->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertOp ) );1397 }1398 1399 1203 Statement * Pass1::mutate( ReturnStmt *returnStmt ) { 1204 // maybe need access to the env when mutating the expr 1205 if ( Expression * expr = returnStmt->get_expr() ) { 1206 if ( expr->get_env() ) { 1207 env = expr->get_env(); 1208 } 1209 } 1210 1400 1211 if ( retval && returnStmt->get_expr() ) { 1401 1212 assert( returnStmt->get_expr()->has_result() && ! returnStmt->get_expr()->get_result()->isVoid() ); 1402 // ***** Code Removal ***** After introducing a temporary variable for all return expressions, the following code appears superfluous. 1403 // if ( returnStmt->get_expr()->get_results().front()->get_isLvalue() ) { 1404 // by this point, a cast expr on a polymorphic return value is redundant 1405 while ( CastExpr *castExpr = dynamic_cast< CastExpr *>( returnStmt->get_expr() ) ) { 1406 returnStmt->set_expr( castExpr->get_arg() ); 1407 returnStmt->get_expr()->set_env( castExpr->get_env() ); 1408 castExpr->set_env( 0 ); 1409 castExpr->set_arg( 0 ); 1410 delete castExpr; 1411 } //while 1412 1413 // find assignment operator for (polymorphic) return type 1414 ApplicationExpr *assignExpr = 0; 1415 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) { 1416 // find assignment operator for type variable 1417 ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() ); 1418 if ( assignIter == assignOps.end() ) { 1419 throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() ); 1420 } // if 1421 assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) ); 1422 } else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) { 1423 // find assignment operator for generic type 1424 DeclarationWithType *functionDecl = scopedAssignOps.find( refType ); 1425 if ( ! functionDecl ) { 1426 throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() ); 1427 } 1428 1429 // wrap it up in an application expression 1430 assignExpr = new ApplicationExpr( wrapFunctionDecl( functionDecl ) ); 1431 assignExpr->set_env( env->clone() ); 1432 1433 // find each of its needed secondary assignment operators 1434 std::list< Expression* > &tyParams = refType->get_parameters(); 1435 Type::ForallList &forallParams = functionDecl->get_type()->get_forall(); 1436 std::list< Expression* >::const_iterator tyIt = tyParams.begin(); 1437 Type::ForallList::const_iterator forallIt = forallParams.begin(); 1438 for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) { 1439 // Add appropriate mapping to assignment expression environment 1440 TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt ); 1441 assert( formalTypeExpr && "type parameters must be type expressions" ); 1442 Type *formalType = formalTypeExpr->get_type(); 1443 assignExpr->get_env()->add( (*forallIt)->get_name(), formalType ); 1444 1445 // skip non-otype parameters (ftype/dtype) 1446 // xxx - should this check whether the type is complete instead? 1447 if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; 1448 1449 // find otype operators for formal type 1450 DeclarationWithType *assertAssign = findOpForType( formalType, assignOps, scopedAssignOps ); 1451 if ( ! assertAssign ) throw SemanticError( "No assignment operation found for ", formalType ); 1452 1453 DeclarationWithType *assertCtor = findOpForType( formalType, ctorOps, scopedCtorOps ); 1454 if ( ! assertCtor ) throw SemanticError( "No default constructor found for ", formalType ); 1455 1456 DeclarationWithType *assertCopy = findOpForType( formalType, copyOps, scopedCopyOps ); 1457 if ( ! assertCopy ) throw SemanticError( "No copy constructor found for ", formalType ); 1458 1459 DeclarationWithType *assertDtor = findOpForType( formalType, dtorOps, scopedDtorOps ); 1460 if ( ! assertDtor ) throw SemanticError( "No destructor found for ", formalType ); 1461 1462 // add inferred parameters for otype operators to assignment expression 1463 // NOTE: Code here assumes that first four assertions are assign op, ctor, copy ctor, dtor, in that order 1464 std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions(); 1465 assert( asserts.size() >= 4 && "Type param needs otype operator assertions" ); 1466 1467 std::list< DeclarationWithType* >::iterator actualIt = asserts.begin(); 1468 addAssertionFor( assignExpr, *actualIt, assertAssign ); 1469 ++actualIt; 1470 addAssertionFor( assignExpr, *actualIt, assertCtor ); 1471 ++actualIt; 1472 addAssertionFor( assignExpr, *actualIt, assertCopy ); 1473 ++actualIt; 1474 addAssertionFor( assignExpr, *actualIt, assertDtor ); 1475 1476 } 1477 } 1478 assert( assignExpr ); 1479 1480 // replace return statement with appropriate assignment to out parameter 1481 Expression *retParm = new NameExpr( retval->get_name() ); 1482 retParm->set_result( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) ); 1483 assignExpr->get_args().push_back( retParm ); 1484 assignExpr->get_args().push_back( returnStmt->get_expr() ); 1485 stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( assignExpr ) ) ); 1486 // } else { 1487 // useRetval = true; 1488 // stmtsToAdd.push_back( new ExprStmt( noLabels, mutateExpression( returnStmt->get_expr() ) ) ); 1489 // useRetval = false; 1490 // } // if 1213 delete returnStmt->get_expr(); 1491 1214 returnStmt->set_expr( 0 ); 1492 1215 } else { … … 1518 1241 void Pass1::doBeginScope() { 1519 1242 adapters.beginScope(); 1520 scopedAssignOps.beginScope();1521 scopedCtorOps.beginScope();1522 scopedCopyOps.beginScope();1523 scopedDtorOps.beginScope();1524 1243 } 1525 1244 1526 1245 void Pass1::doEndScope() { 1527 1246 adapters.endScope(); 1528 scopedAssignOps.endScope();1529 scopedCtorOps.endScope();1530 scopedCopyOps.endScope();1531 scopedDtorOps.endScope();1532 1247 } 1533 1248 … … 1569 1284 1570 1285 DeclarationWithType * Pass2::mutate( FunctionDecl *functionDecl ) { 1571 if ( ! LinkageSpec::isBuiltin( functionDecl->get_linkage() ) ) {1572 // std::cerr << "mutating function: " << functionDecl->get_name() << std::endl;1573 }1574 1286 functionDecl = safe_dynamic_cast< FunctionDecl * > ( handleDecl( functionDecl, functionDecl->get_functionType() ) ); 1575 1287 FunctionType * ftype = functionDecl->get_functionType(); … … 1861 1573 // replace member expression with pointer to base plus offset 1862 1574 UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) ); 1863 fieldLoc->get_args().push_back( makeDerefdVar( varExpr->clone(), varDepth ) ); 1575 Expression * aggr = memberExpr->get_aggregate()->clone(); 1576 delete aggr->get_env(); // xxx - there's a problem with keeping the env for some reason, so for now just get rid of it 1577 aggr->set_env( nullptr ); 1578 fieldLoc->get_args().push_back( aggr ); 1864 1579 fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) ); 1865 1580 newMemberExpr = fieldLoc;
Note: See TracChangeset
for help on using the changeset viewer.