Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision b10c9959109272e0304123be8aaefa37571499cf)
+++ src/GenPoly/Box.cc	(revision b4cd03b740cf2cfe5905750f3587883e5a51a654)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Fri Dec 18 14:53:08 2015
-// Update Count     : 217
+// Last Modified On : Fri Feb 05 12:23:10 2016
+// Update Count     : 280
 //
 
@@ -123,6 +123,5 @@
 		};
 
-		/// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference;
-		/// also fixes offsetof expressions.
+		/// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference
 		class MemberExprFixer : public PolyMutator {
 		  public:
@@ -137,7 +136,6 @@
 			virtual Type *mutate( FunctionType *funcType );
 			virtual Expression *mutate( MemberExpr *memberExpr );
-			virtual Expression *mutate( OffsetofExpr *offsetofExpr );
 		};
-		
+
 		/// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, and sizeof expressions of polymorphic types with the proper variable
 		class Pass3 : public PolyMutator {
@@ -178,5 +176,5 @@
 						seenIntrinsic = false; // break on this line when debugging for end of prelude
 					}
-					
+
 					*i = dynamic_cast< Declaration* >( (*i)->acceptMutator( mutator ) );
 					assert( *i );
@@ -286,5 +284,5 @@
 				}
 			}
-			
+
 			if ( functionDecl->get_statements() ) {		// empty routine body ?
 				doBeginScope();
@@ -320,5 +318,5 @@
 					findFunction( (*arg)->get_type(), functions, scopeTyVars, needsAdapter );
 				} // for
-				
+
 				AdapterMap & adapters = Pass1::adapters.top();
 				for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
@@ -373,5 +371,5 @@
 		Expression *Pass1::makeOffsetArray( StructInstType *ty ) {
 			std::list< Declaration* > &baseMembers = ty->get_baseStruct()->get_members();
-			
+
 			// make a new temporary array
 			Type *offsetType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
@@ -397,5 +395,5 @@
 			return new VariableExpr( arrayTemp );
 		}
-		
+
 		void Pass1::passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
 			// pass size/align for type variables
@@ -493,5 +491,5 @@
 			}
 		}
-		
+
 		Type *Pass1::replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone ) {
 			if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
@@ -531,5 +529,7 @@
 			std::string adapterName = makeAdapterName( mangleName );
 
-			appExpr->get_args().push_front( appExpr->get_function() );
+			// cast adaptee to void (*)(), since it may have any type inside a polymorphic function
+			Type * adapteeType = new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
+			appExpr->get_args().push_front( new CastExpr( appExpr->get_function(), adapteeType ) );
 			appExpr->set_function( new NameExpr( adapterName ) );
 
@@ -559,14 +559,12 @@
 		}
 
+		/// cast parameters to polymorphic functions so that types are replaced with
+		/// void * if they are type parameters in the formal type.
+		/// this gets rid of warnings from gcc.
 		void addCast( Expression *&actual, Type *formal, const TyVarMap &tyVars ) {
-			Type *newType = formal->clone();
-			std::list< FunctionType *> functions;
-			// instead of functions needing adapters, this really ought to look for
-			// any function mentioning a polymorphic type
-			findAndReplaceFunction( newType, functions, tyVars, needsAdapter );
-			if ( ! functions.empty() ) {
+			Type * newType = formal->clone();
+			if ( getFunctionType( newType ) ) {
+				newType = ScrubTyVars::scrub( newType, tyVars );
 				actual = new CastExpr( actual, newType );
-			} else {
-				delete newType;
 			} // if
 		}
@@ -989,13 +987,4 @@
 		}
 
-		/// Wraps a function declaration in a new pointer-to-function variable expression
-		VariableExpr *wrapFunctionDecl( DeclarationWithType *functionDecl ) {
-			// line below cloned from FixFunction.cc
-			ObjectDecl *functionObj = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,
-			                                          new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
-			functionObj->set_mangleName( functionDecl->get_mangleName() );
-			return new VariableExpr( functionObj );
-		}
-		
 		Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
 			if ( retval && returnStmt->get_expr() ) {
@@ -1013,66 +1002,26 @@
 
 				// find assignment operator for (polymorphic) return type
-				ApplicationExpr *assignExpr = 0;
+				DeclarationWithType *assignDecl = 0;
 				if ( TypeInstType *typeInst = dynamic_cast< TypeInstType *>( retval->get_type() ) ) {
-					// find assignment operator for type variable
 					std::map< std::string, DeclarationWithType *>::const_iterator assignIter = assignOps.find( typeInst->get_name() );
 					if ( assignIter == assignOps.end() ) {
 						throw SemanticError( "Attempt to return dtype or ftype object in ", returnStmt->get_expr() );
 					} // if
-					assignExpr = new ApplicationExpr( new VariableExpr( assignIter->second ) );
+					assignDecl = assignIter->second;
 				} else if ( ReferenceToType *refType = dynamic_cast< ReferenceToType *>( retval->get_type() ) ) {
-					// find assignment operator for generic type
 					ScopedMap< std::string, DeclarationWithType *>::const_iterator assignIter = scopedAssignOps.find( refType->get_name() );
 					if ( assignIter == scopedAssignOps.end() ) {
 						throw SemanticError( "Attempt to return dtype or ftype generic object in ", returnStmt->get_expr() );
 					}
-
-					// wrap it up in an application expression
 					DeclarationWithType *functionDecl = assignIter->second;
-					assignExpr = new ApplicationExpr( wrapFunctionDecl( functionDecl ) );
-					assignExpr->set_env( env->clone() );
-
-					// find each of its needed secondary assignment operators
-					std::list< Expression* > &tyParams = refType->get_parameters();
-					std::list< TypeDecl* > &forallParams = functionDecl->get_type()->get_forall();
-					std::list< Expression* >::const_iterator tyIt = tyParams.begin();
-					std::list< TypeDecl* >::const_iterator forallIt = forallParams.begin();
-					for ( ; tyIt != tyParams.end() && forallIt != forallParams.end(); ++tyIt, ++forallIt ) {
-						if ( (*forallIt)->get_kind() != TypeDecl::Any ) continue; // skip types with no assign op (ftype/dtype)
-
-						std::list< DeclarationWithType* > &asserts = (*forallIt)->get_assertions();
-						assert( ! asserts.empty() && "Type param needs assignment operator assertion" );
-						DeclarationWithType *actualDecl = asserts.front();
-						ReferenceToType *actualType = isAssignment( actualDecl );
-						assert( actualType && "First assertion of type with assertions should be assignment operator" );
-						TypeExpr *formalTypeExpr = dynamic_cast< TypeExpr* >( *tyIt );
-						assert( formalTypeExpr && "type parameters must be type expressions" );
-						Type *formalType = formalTypeExpr->get_type();
-						assignExpr->get_env()->add( actualType->get_name(), formalType );
-						
-						DeclarationWithType *assertAssign = 0;
-						if ( TypeInstType *formalTypeInstType = dynamic_cast< TypeInstType* >( formalType ) ) {
-							std::map< std::string, DeclarationWithType *>::const_iterator assertAssignIt = assignOps.find( formalTypeInstType->get_name() );
-							if ( assertAssignIt == assignOps.end() ) {
-								throw SemanticError( "No assignment operation found for ", formalTypeInstType );
-							}
-							assertAssign = assertAssignIt->second;
-							//assignExpr->get_env()->add( formalTypeInstType->get_name(), actualType );
-						} else if ( ReferenceToType *formalReferenceType = dynamic_cast< ReferenceToType* >( formalType ) )  {
-							ScopedMap< std::string, DeclarationWithType *>::const_iterator assertAssignIt = scopedAssignOps.find( formalReferenceType->get_name() );
-							if ( assertAssignIt == scopedAssignOps.end() ) {
-								throw SemanticError( "No assignment operation found for ", formalReferenceType );
-							}
-							assertAssign = assertAssignIt->second;
-						} else assert( false && "returning polymorphic types with non struct/polymorphic parameters not yet supported" );
-						
-
-						assignExpr->get_inferParams()[ actualDecl->get_uniqueId() ]
-							= ParamEntry( assertAssign->get_uniqueId(), assertAssign->get_type()->clone(), actualDecl->get_type()->clone(), wrapFunctionDecl( assertAssign ) );
-					}
+					// line below cloned from FixFunction.cc
+					assignDecl = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0,
+					                             new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
+					assignDecl->set_mangleName( functionDecl->get_mangleName() );
 				}
-				assert( assignExpr );
+				assert( assignDecl );
 
 				// replace return statement with appropriate assignment to out parameter
+				ApplicationExpr *assignExpr = new ApplicationExpr( new VariableExpr( assignDecl ) );
 				Expression *retParm = new NameExpr( retval->get_name() );
 				retParm->get_results().push_back( new PointerType( Type::Qualifiers(), retval->get_type()->clone() ) );
@@ -1334,20 +1283,47 @@
 		}
 
-		/// Finds the member in the base list that matches the given declaration; returns its index, or -1 if not present
-		long findMember( DeclarationWithType *memberDecl, std::list< Declaration* > &baseDecls ) {
-			long i = 0;
-			for(std::list< Declaration* >::const_iterator decl = baseDecls.begin(); decl != baseDecls.end(); ++decl, ++i ) {
+		Expression *MemberExprFixer::mutate( MemberExpr *memberExpr ) {
+			// mutate, exiting early if no longer MemberExpr
+			Expression *expr = Mutator::mutate( memberExpr );
+			memberExpr = dynamic_cast< MemberExpr* >( expr );
+			if ( ! memberExpr ) return expr;
+
+			// get declaration for base struct, exiting early if not found
+			int varDepth;
+			VariableExpr *varExpr = getBaseVar( memberExpr->get_aggregate(), &varDepth );
+			if ( ! varExpr ) return memberExpr;
+			ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );
+			if ( ! objectDecl ) return memberExpr;
+
+			// only mutate member expressions for polymorphic types
+			int tyDepth;
+			Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth );
+			if ( ! objectType ) return memberExpr;
+
+			// get base aggregate for type so members can be looked up
+			AggregateDecl *memberBase = 0;
+			if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
+				memberBase = structType->get_baseStruct();
+			} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType ) ) {
+				memberBase = unionType->get_baseUnion();
+			} else return memberExpr;
+
+			// look up numeric index of member in base aggregate
+			DeclarationWithType *memberDecl = memberExpr->get_member();
+			std::list< Declaration* > &baseDecls = memberBase->get_members();
+			std::list< Declaration* >::const_iterator decl = baseDecls.begin();
+			unsigned long i = 0;
+			for( ; decl != baseDecls.end(); ++decl, ++i ) {
 				if ( memberDecl->get_name() != (*decl)->get_name() ) continue;
 
 				if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) {
-					if ( memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i;
+					if ( memberDecl->get_mangleName() == declWithType->get_mangleName() ) break;
 					else continue;
-				} else return i;
+				} else break;
 			}
-			return -1;
-		}
-
-		/// Returns an index expression into the offset array for a type
-		Expression *makeOffsetIndex( Type *objectType, long i ) {
+			if ( decl == baseDecls.end() ) return memberExpr;
+
+			// replace member expression with pointer to base plus offset
+			// get offset for field
 			std::stringstream offset_namer;
 			offset_namer << i;
@@ -1356,78 +1332,18 @@
 			fieldOffset->get_args().push_back( new NameExpr( offsetofName( objectType ) ) );
 			fieldOffset->get_args().push_back( fieldIndex );
-			return fieldOffset;
-		}
-
-		/// Returns an expression dereferenced n times
-		Expression *makeDerefdVar( Expression *derefdVar, long n ) {
-			for ( int i = 1; i < n; ++i ) {
+			// build appropriately-dereferenced variable
+			Expression *derefdVar = varExpr->clone();
+			for ( int i = 1; i < varDepth; ++i ) {
 				UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
 				derefExpr->get_args().push_back( derefdVar );
 				derefdVar = derefExpr;
 			}
-			return derefdVar;
-		}
-		
-		Expression *MemberExprFixer::mutate( MemberExpr *memberExpr ) {
-			// mutate, exiting early if no longer MemberExpr
-			Expression *expr = Mutator::mutate( memberExpr );
-			memberExpr = dynamic_cast< MemberExpr* >( expr );
-			if ( ! memberExpr ) return expr;
-
-			// get declaration for base struct, exiting early if not found
-			int varDepth;
-			VariableExpr *varExpr = getBaseVar( memberExpr->get_aggregate(), &varDepth );
-			if ( ! varExpr ) return memberExpr;
-			ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );
-			if ( ! objectDecl ) return memberExpr;
-
-			// only mutate member expressions for polymorphic types
-			int tyDepth;
-			Type *objectType = hasPolyBase( objectDecl->get_type(), scopeTyVars, &tyDepth );
-			if ( ! objectType ) return memberExpr;
-
-			if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
-				// look up offset index
-				long i = findMember( memberExpr->get_member(), structType->get_baseStruct()->get_members() );
-				if ( i == -1 ) return memberExpr;
-
-				// replace member expression with pointer to base plus offset
-				UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
-				fieldLoc->get_args().push_back( makeDerefdVar( varExpr->clone(), varDepth ) );
-				fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) );
-
-				delete memberExpr;
-				return fieldLoc;
-			} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType ) ) {
-				// union members are all at offset zero, so build appropriately-dereferenced variable
-				Expression *derefdVar = makeDerefdVar( varExpr->clone(), varDepth );
-				delete memberExpr;
-				return derefdVar;
-			} else return memberExpr;
-		}
-
-		Expression *MemberExprFixer::mutate( OffsetofExpr *offsetofExpr ) {
-			// mutate, exiting early if no longer OffsetofExpr
-			Expression *expr = Mutator::mutate( offsetofExpr );
-			offsetofExpr = dynamic_cast< OffsetofExpr* >( expr );
-			if ( ! offsetofExpr ) return expr;
-
-			// only mutate expressions for polymorphic structs/unions
-			Type *ty = isPolyType( offsetofExpr->get_type(), scopeTyVars );
-			if ( ! ty ) return offsetofExpr;
-
-			if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
-				// replace offsetof expression by index into offset array
-				long i = findMember( offsetofExpr->get_member(), structType->get_baseStruct()->get_members() );
-				if ( i == -1 ) return offsetofExpr;
-
-				Expression *offsetInd = makeOffsetIndex( ty, i );
-				delete offsetofExpr;
-				return offsetInd;
-			} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( ty ) ) {
-				// all union members are at offset zero
-				delete offsetofExpr;
-				return new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::string("0") ) );
-			} else return offsetofExpr;
+			// add offset to deref'd variable
+			UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
+			fieldLoc->get_args().push_back( derefdVar );
+			fieldLoc->get_args().push_back( fieldOffset );
+
+			delete memberExpr;
+			return fieldLoc;
 		}
 
