Index: src/InitTweak/RemoveInit.cc
===================================================================
--- src/InitTweak/RemoveInit.cc	(revision c14cff1813318f9616a9e814d9a8528eb9ddcbf9)
+++ src/InitTweak/RemoveInit.cc	(revision 071a31a897b52a4c1abdb6c4c2536e3bfe6257fb)
@@ -192,16 +192,24 @@
 		if ( tryConstruct( objDecl ) ) {
 			if ( inFunction ) {
-				Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );
-				Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );
-
-				// need to remember init expression, in case no ctors exist
-				// if ctor does exist, want to use ctor expression instead of init
-				// push this decision to the resolver
-				objDecl->set_init( new ConstructorInit( ctor, objDecl->get_init() ) );
-				destructorStmts.push_front( new ExprStmt( noLabels, dtor ) );
+				if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
+					// call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array
+				} else {
+					// it's sufficient to attempt to call the ctor/dtor for the given object and its initializer
+					Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );
+					Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );
+
+					// need to remember init expression, in case no ctors exist
+					// if ctor does exist, want to use ctor expression instead of init
+					// push this decision to the resolver
+					objDecl->set_init( new ConstructorInit( ctor, objDecl->get_init() ) );
+					destructorStmts.push_front( new ExprStmt( noLabels, dtor ) );
+				}
 			} else {
 				// xxx - find a way to construct/destruct globals
 				// hack: implicit "static" initialization routine for each struct type? or something similar?
 				// --ties into module system
+				// this can be done by mangling main and replacing it with our own main which calls each
+				// module initialization routine in some decided order (order given in link command?)
+				// and finally calls mangled main
 			}
 		}
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision c14cff1813318f9616a9e814d9a8528eb9ddcbf9)
+++ src/ResolvExpr/Resolver.cc	(revision 071a31a897b52a4c1abdb6c4c2536e3bfe6257fb)
@@ -479,9 +479,16 @@
 		TypeEnvironment env;
 		AlternativeFinder finder( *this, env );
-		finder.find( ctorInit->get_ctor() );
-
-		if ( finder.get_alternatives().size() == 0 ) {
+		try {
+			finder.find( ctorInit->get_ctor() );
+		} catch ( SemanticError ) {
+			// no alternatives for the constructor initializer - fallback on C-style initializer
+			// xxx- not sure if this makes a ton of sense - should maybe never be able to have this situation?
 			fallbackInit( ctorInit );
-		} else if ( finder.get_alternatives().size() == 1 ) {
+			return;
+		}
+
+		assert( ! finder.get_alternatives().empty() );
+
+		if ( finder.get_alternatives().size() == 1 ) {
 			Alternative &choice = finder.get_alternatives().front();
 			if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( choice.expr ) ) {
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision c14cff1813318f9616a9e814d9a8528eb9ddcbf9)
+++ src/SymTab/Validate.cc	(revision 071a31a897b52a4c1abdb6c4c2536e3bfe6257fb)
@@ -698,5 +698,55 @@
 	}
 
-	Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
+	void makeStructFunctionBody( StructDecl *aggregateDecl, FunctionDecl * func, TypeSubstitution & genericSubs, bool isGeneric ) {
+		for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
+			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
+				// query the type qualifiers of this field and skip assigning it if it is marked const.
+				// If it is an array type, we need to strip off the array layers to find its qualifiers.
+				Type * type = dwt->get_type();
+				while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
+					type = at->get_base();
+				}
+
+				if ( type->get_qualifiers().isConst ) {
+					// don't assign const members
+					continue;
+				}
+
+				// temporary hack: for now only works for 2 parameters
+				assert( func->get_functionType()->get_parameters().size() == 2 );
+
+				ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().front() );
+				ObjectDecl * srcParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().back() );
+				ObjectDecl * returnVal;
+				if ( ! func->get_functionType()->get_returnVals().empty() ) {
+					returnVal = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_returnVals().front() );
+				}
+
+				if ( isGeneric ) {
+					// rewrite member type in terms of the type variables on this operator
+					DeclarationWithType *fixedMember = dwt->clone();
+					genericSubs.apply( fixedMember );
+
+					// assign to both destination and return value
+					if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) {
+						makeArrayFunction( srcParam, dstParam, fixedMember, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+						if ( returnVal ) makeArrayFunction( srcParam, returnVal, fixedMember, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+					} else {
+						makeScalarFunction( srcParam, dstParam, fixedMember, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+						if ( returnVal ) makeScalarFunction( srcParam, returnVal, fixedMember, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+					} // if
+				} else {
+					// assign to destination
+					if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
+						makeArrayFunction( srcParam, dstParam, dwt, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+					} else {
+						makeScalarFunction( srcParam, dstParam, dwt, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+					} // if
+				} // if
+			} // if
+		} // for
+	} // makeStructFunctionBody
+
+	void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
 		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
 
@@ -715,121 +765,41 @@
 		}
 
+		ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
+		assignType->get_parameters().push_back( dstParam );
+
+		// void ?{}(T *); void ^?{}(T *);
+		FunctionType *ctorType = assignType->clone();
+		FunctionType *dtorType = assignType->clone();
+
+		ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
+		assignType->get_parameters().push_back( srcParam );
+
+		// void ?{}(T *, T);
+		FunctionType *copyCtorType = assignType->clone();
+
+		// T ?=?(T *, T);
 		ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
 		assignType->get_returnVals().push_back( returnVal );
-
-		ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
-		assignType->get_parameters().push_back( dstParam );
-
-		ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
-		assignType->get_parameters().push_back( srcParam );
 
 		// Routines at global scope marked "static" to prevent multiple definitions is separate translation units
 		// because each unit generates copies of the default routines for each aggregate.
 		FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true, false );
+		FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, new CompoundStmt( noLabels ), true, false );
+		FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, copyCtorType, new CompoundStmt( noLabels ), true, false );
+		FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false );
 		assignDecl->fixUniqueId();
-
-		for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
-			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
-				// query the type qualifiers of this field and skip assigning it if it is marked const.
-				// If it is an array type, we need to strip off the array layers to find its qualifiers.
-				Type * type = dwt->get_type();
-				while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
-					type = at->get_base();
-				}
-
-				if ( type->get_qualifiers().isConst ) {
-					// don't assign const members
-					continue;
-				}
-
-				if ( isGeneric ) {
-					// rewrite member type in terms of the type variables on this operator
-					DeclarationWithType *fixedMember = dwt->clone();
-					genericSubs.apply( fixedMember );
-
-					// assign to both destination and return value
-					if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) {
-						makeArrayFunction( srcParam, dstParam, fixedMember, array, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
-						makeArrayFunction( srcParam, returnVal, fixedMember, array, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
-					} else {
-						makeScalarFunction( srcParam, dstParam, fixedMember, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
-						makeScalarFunction( srcParam, returnVal, fixedMember, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
-					} // if
-				} else {
-					// assign to destination
-					if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
-						makeArrayFunction( srcParam, dstParam, dwt, array, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
-					} else {
-						makeScalarFunction( srcParam, dstParam, dwt, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
-					} // if
-				} // if
-			} // if
-		} // for
-		if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
-
-		return assignDecl;
-	}
-
-	void makeStructCtorDtor( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
-		FunctionType *ctorType = new FunctionType( Type::Qualifiers(), false );
-
-		// Make function polymorphic in same parameters as generic struct, if applicable
-		bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
-		std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
-		std::list< Expression* > structParams;  // List of matching parameters to put on types
-		for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
-			isGeneric = true;
-			TypeDecl *typeParam = (*param)->clone();
-			ctorType->get_forall().push_back( typeParam );
-			structParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
-		}
-
-		ObjectDecl *thisParam = new ObjectDecl( "_this", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, structParams ) ), 0 );
-		ctorType->get_parameters().push_back( thisParam );
-
-		// Routines at global scope marked "static" to prevent multiple definitions is separate translation units
-		// because each unit generates copies of the default routines for each aggregate.
-		FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, 0, true, false );
-		FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType->clone(), 0, true, false );
-		FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType->clone(), 0, true, false );
 		ctorDecl->fixUniqueId();
 		copyCtorDecl->fixUniqueId();
 		dtorDecl->fixUniqueId();
 
-		// add definitions
-		// TODO: add in calls to default constructors and destructors for fields
-		ctorDecl->set_statements( new CompoundStmt( noLabels ) );
-		copyCtorDecl->set_statements( new CompoundStmt( noLabels ) );
-		dtorDecl->set_statements( new CompoundStmt( noLabels ) );
+		if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
+
+		makeStructFunctionBody( aggregateDecl, assignDecl, genericSubs, isGeneric );
+		makeStructFunctionBody( aggregateDecl, copyCtorDecl, genericSubs, isGeneric );
+
+		declsToAdd.push_back( assignDecl );
 		declsToAdd.push_back( ctorDecl );
 		declsToAdd.push_back( copyCtorDecl );
 		declsToAdd.push_back( dtorDecl );
-
-		ObjectDecl * srcParam = new ObjectDecl( "_other", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
-		copyCtorDecl->get_functionType()->get_parameters().push_back( srcParam );
-		for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
-			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
-				// query the type qualifiers of this field and skip assigning it if it is marked const.
-				// If it is an array type, we need to strip off the array layers to find its qualifiers.
-				Type * type = dwt->get_type();
-				while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
-					type = at->get_base();
-				}
-
-				if ( type->get_qualifiers().isConst ) {
-					// don't assign const members
-					continue;
-				}
-
-				if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
-					makeArrayFunction( srcParam, thisParam, dwt, array, "?{}", back_inserter( copyCtorDecl->get_statements()->get_kids() ) );
-					// if ( isGeneric ) makeArrayFunction( srcParam, returnVal, dwt, array, back_inserter( copyCtorDecl->get_statements()->get_kids() ) );
-				} else {
-					makeScalarFunction( srcParam, thisParam, dwt, "?{}", back_inserter( copyCtorDecl->get_statements()->get_kids() ) );
-					// if ( isGeneric ) makeScalarCtor( srcParam, returnVal, dwt, back_inserter( copyCtorDecl->get_statements()->get_kids() ) );
-				} // if
-			} // if
-		} // for
-		// if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
 	}
 
@@ -904,7 +874,5 @@
 			StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
 			structInst.set_baseStruct( structDecl );
-
-			declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) );
-			makeStructCtorDtor( structDecl, &structInst, functionNesting, declsToAdd );
+			makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd );
 			structsDone.insert( structDecl->get_name() );
 		} // if
Index: src/libcfa/prelude.cf
===================================================================
--- src/libcfa/prelude.cf	(revision c14cff1813318f9616a9e814d9a8528eb9ddcbf9)
+++ src/libcfa/prelude.cf	(revision 071a31a897b52a4c1abdb6c4c2536e3bfe6257fb)
@@ -810,9 +810,4 @@
 forall( dtype DT ) void ?{}( const volatile  DT * volatile *);
 
-forall( dtype DT ) void ?{}(          DT (*)[] ); // xxx - probably incomplete
-forall( dtype DT ) void ?{}( const    DT (*)[] );
-forall( dtype DT ) void ?{}( volatile DT (*)[] );
-forall( dtype DT ) void ?{}( const volatile DT (*)[] );
-
 void 	?{}(		    void *	    *);
 void 	?{}(		    void * volatile *);
@@ -837,10 +832,4 @@
 forall( dtype DT ) void ^?{}( const volatile  DT * volatile *);
 
-forall( dtype DT ) void ^?{}(        DT (*) [] ); // xxx - probably incomplete
-forall( dtype DT ) void ^?{}( const    DT (*)[] );
-forall( dtype DT ) void ^?{}( volatile DT (*)[] );
-forall( dtype DT ) void ^?{}( const volatile DT (*)[] );
-
-
 void 	^?{}(		    void *	    *);
 void 	^?{}(		    void * volatile *);
