Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision 5b40f300c07c8cd0b5d1720f42e535c1f4926bd5)
+++ src/SymTab/Autogen.cc	(revision dac0aa98c5f36cc84cb4a5902a16d8a34332dbf3)
@@ -64,5 +64,5 @@
 
 	template< typename OutputIterator >
-	void makeScalarFunction( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, std::string fname, OutputIterator out ) {
+	void makeScalarFunction( Expression *src, ObjectDecl *dstParam, DeclarationWithType *member, std::string fname, OutputIterator out ) {
 		ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member );
 		// unnamed bit fields are not copied as they cannot be accessed
@@ -80,7 +80,6 @@
 		fExpr->get_args().push_back( dstselect );
 
-		if ( srcParam ) {
-			Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
-			fExpr->get_args().push_back( srcselect );
+		if ( src ) {
+			fExpr->get_args().push_back( src );
 		}
 
@@ -183,11 +182,43 @@
 	}
 
+	void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, TypeSubstitution & genericSubs, bool isGeneric, bool forward = true ) {
+		if ( isGeneric ) {
+			// rewrite member type in terms of the type variables on this operator
+			field = field->clone();
+			genericSubs.apply( field );
+		}
+
+		ObjectDecl * returnVal = NULL;
+		if ( ! func->get_functionType()->get_returnVals().empty() ) {
+			returnVal = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_returnVals().front() );
+		}
+
+		// assign to destination (and return value if generic)
+		if ( ArrayType *array = dynamic_cast< ArrayType * >( field->get_type() ) ) {
+			UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
+			derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
+			Expression *dstselect = new MemberExpr( field, derefExpr );
+
+			makeArrayFunction( src, dstselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward );
+			if ( isGeneric && returnVal ) {
+				UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
+				derefRet->get_args().push_back( new VariableExpr( returnVal ) );
+				Expression *retselect = new MemberExpr( field, derefRet );
+
+				makeArrayFunction( src, retselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward );
+			}
+		} else {
+			makeScalarFunction( src, dstParam, field, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+			if ( isGeneric && returnVal ) makeScalarFunction( src, returnVal, field, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+		} // if
+	}
+
 	template<typename Iterator>
 	void makeStructFunctionBody( Iterator member, Iterator end, FunctionDecl * func, TypeSubstitution & genericSubs, bool isGeneric, bool forward = true ) {
 		for ( ; member != end; ++member ) {
-			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
+			if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate
 				// 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();
+				Type * type = field->get_type();
 				while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
 					type = at->get_base();
@@ -205,42 +236,41 @@
 					srcParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().back() );
 				}
-				ObjectDecl * returnVal = NULL;
-				if ( ! func->get_functionType()->get_returnVals().empty() ) {
-					returnVal = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_returnVals().front() );
-				}
 				// srcParam may be NULL, in which case we have default ctor/dtor
 				assert( dstParam );
 
-
-				DeclarationWithType * memType = dwt;
-				if ( isGeneric ) {
-					// rewrite member type in terms of the type variables on this operator
-					memType = memType->clone();
-					genericSubs.apply( memType );
-				}
-
-
-				// assign to destination (and return value if generic)
-				if ( ArrayType *array = dynamic_cast< ArrayType * >( memType->get_type() ) ) {
-					UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
-					derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
-					Expression *dstselect = new MemberExpr( memType, derefExpr );
-					Expression *srcselect = srcParam ? new MemberExpr( memType, new VariableExpr( srcParam ) ) : NULL;
-
-					makeArrayFunction( srcselect, dstselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward );
-					if ( isGeneric && returnVal ) {
-						UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
-						derefRet->get_args().push_back( new VariableExpr( returnVal ) );
-						Expression *retselect = new MemberExpr( memType, derefRet );
-
-						makeArrayFunction( srcselect, retselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward );
-					}
-				} else {
-					makeScalarFunction( srcParam, dstParam, memType, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
-					if ( isGeneric && returnVal ) makeScalarFunction( srcParam, returnVal, memType, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
-				} // if
+				Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL;
+				makeStructMemberOp( dstParam, srcselect, field, func, genericSubs, isGeneric, forward );
 			} // if
 		} // for
 	} // makeStructFunctionBody
+
+	/// generate the body of a constructor which takes parameters that match fields, e.g.
+	/// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
+	template<typename Iterator>
+	void makeStructFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func, TypeSubstitution & genericSubs, bool isGeneric ) {
+		FunctionType * ftype = func->get_functionType();
+		std::list<DeclarationWithType*> & params = ftype->get_parameters();
+		assert( params.size() >= 2 );  // should not call this function for default ctor, etc.
+
+		// skip 'this' parameter
+		ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( params.front() );
+		assert( dstParam );
+		std::list<DeclarationWithType*>::iterator parameter = params.begin()+1;
+		for ( ; member != end; ++member ) {
+			if ( DeclarationWithType * field = dynamic_cast<DeclarationWithType*>( *member ) ) {
+				if ( parameter != params.end() ) {
+					// matching parameter, initialize field with copy ctor
+					std::cerr << "matching parameter - copy ctor" << std::endl;
+					Expression *srcselect = new VariableExpr(*parameter);
+					makeStructMemberOp( dstParam, srcselect, field, func, genericSubs, isGeneric );
+					++parameter;
+				} else {
+					std::cerr << "no matching parameter - default ctor" << std::endl;
+					// no matching parameter, initialize field with default ctor
+					makeStructMemberOp( dstParam, NULL, field, func, genericSubs, isGeneric );
+				}
+			}
+		}
+	}
 
 	void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
@@ -289,4 +319,20 @@
 		dtorDecl->fixUniqueId();
 
+		// create constructors which take each member type as a parameter.
+		// we might be able to eventually collapse this into a single function
+		// which uses default parameters
+		std::list<Declaration *> memCtors;
+		FunctionType * memCtorType = ctorType->clone();
+		for ( std::list<Declaration *>::iterator i = aggregateDecl->get_members().begin(); i != aggregateDecl->get_members().end(); ++i ) {
+			DeclarationWithType * member = dynamic_cast<DeclarationWithType *>( *i );
+			assert( member );
+			memCtorType->get_parameters().push_back( new ObjectDecl( member->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, member->get_type()->clone(), 0 ) );
+			FunctionDecl * ctor = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, memCtorType->clone(), new CompoundStmt( noLabels ), true, false );
+			ctor->fixUniqueId();
+			makeStructFieldCtorBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctor, genericSubs, isGeneric );
+			memCtors.push_back( ctor );
+		}
+		delete memCtorType;
+
 		// generate appropriate calls to member ctor, assignment
 		makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), assignDecl, genericSubs, isGeneric );
@@ -302,4 +348,5 @@
 		declsToAdd.push_back( copyCtorDecl );
 		declsToAdd.push_back( dtorDecl );
+		declsToAdd.splice( declsToAdd.end(), memCtors );
 	}
 
