Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision ae42f2a7f234c8e9567c98613f8f967c7fabd3df)
+++ src/CodeGen/CodeGenerator.cc	(revision a9a259cff14b8d1aebb4436ded3476b2d261f8c7)
@@ -263,6 +263,13 @@
 
 				  case OT_CTOR:
+				  // it's just an optimization to disallow this, so for now let it through
+				  // since it makes autogenerating constructors a lot easier
+  				varExpr->accept( *this );
+					output << "(";
+					genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
+					output << ")";
+
 				  // intrinsic constructors should never be called directly - they should be transformed back into Initializer nodes
-				  assert(false);
+				  // assert(false);
 				  break;
 
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision ae42f2a7f234c8e9567c98613f8f967c7fabd3df)
+++ src/Parser/TypeData.cc	(revision a9a259cff14b8d1aebb4436ded3476b2d261f8c7)
@@ -437,5 +437,5 @@
 		if ( (*i)->get_kind() == TypeDecl::Any ) {
 			// add assertion parameters to `type' tyvars
-			// add:  T * ?=?(T *, T)
+			// add assignment operator:  T * ?=?(T *, T)
 			FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
 			assignType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) );
@@ -444,10 +444,16 @@
 			(*i)->get_assertions().push_front( new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignType, 0, false, false ) );
 
-			// add:  void ?{}(T *)
+			// add default ctor:  void ?{}(T *)
 			FunctionType *ctorType = new FunctionType( Type::Qualifiers(), false );
 			ctorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) );
 			(*i)->get_assertions().push_front( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, ctorType, 0, false, false ) );
 
-			// add:  void ^?{}(T *)
+			// add copy ctor:  void ?{}(T *, T)
+			FunctionType *copyCtorType = new FunctionType( Type::Qualifiers(), false );
+			copyCtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) );
+			copyCtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ), 0 ) );
+			(*i)->get_assertions().push_front( new FunctionDecl( "?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, copyCtorType, 0, false, false ) );
+
+			// add dtor:  void ^?{}(T *)
 			FunctionType *dtorType = new FunctionType( Type::Qualifiers(), false );
 			dtorType->get_parameters().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), (*i)->get_name(), *i ) ), 0 ) );
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision ae42f2a7f234c8e9567c98613f8f967c7fabd3df)
+++ src/ResolvExpr/Resolver.cc	(revision a9a259cff14b8d1aebb4436ded3476b2d261f8c7)
@@ -487,6 +487,6 @@
 			if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( choice.expr ) ) {
 				if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) {
-					if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) {
-						// if the constructor that was found is intrinsic, reset to C-style
+					if ( LinkageSpec::isOverridable( function->get_var()->get_linkage() ) ) {
+						// if the constructor that was found is intrinsic or autogenerated, reset to C-style
 						// initializer so that code generation is easy to handle
 						fallbackInit( ctorInit );
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision ae42f2a7f234c8e9567c98613f8f967c7fabd3df)
+++ src/SymTab/Validate.cc	(revision a9a259cff14b8d1aebb4436ded3476b2d261f8c7)
@@ -535,10 +535,12 @@
 
 	template< typename OutputIterator >
-	void makeScalarAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, OutputIterator out ) {
+	void makeScalarFunction( ObjectDecl *srcParam, 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
 		if ( obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL ) return;
 
-		UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
+		// want to be able to generate assignment, ctor, and dtor generically,
+		// so fname is either ?=?, ?{}, or ^?{}
+		UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
 
 		UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
@@ -547,14 +549,14 @@
 		// do something special for unnamed members
 		Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
-		assignExpr->get_args().push_back( dstselect );
+		fExpr->get_args().push_back( dstselect );
 
 		Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
-		assignExpr->get_args().push_back( srcselect );
-
-		*out++ = new ExprStmt( noLabels, assignExpr );
+		fExpr->get_args().push_back( srcselect );
+
+		*out++ = new ExprStmt( noLabels, fExpr );
 	}
 
 	template< typename OutputIterator >
-	void makeArrayAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, OutputIterator out ) {
+	void makeArrayFunction( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, std::string fname, OutputIterator out ) {
 		static UniqueName indexName( "_index" );
 
@@ -579,5 +581,7 @@
 		inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
 
-		UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
+		// want to be able to generate assignment, ctor, and dtor generically,
+		// so fname is either ?=?, ?{}, or ^?{}
+		UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
 
 		UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
@@ -588,5 +592,5 @@
 		dstIndex->get_args().push_back( dstselect );
 		dstIndex->get_args().push_back( new VariableExpr( index ) );
-		assignExpr->get_args().push_back( dstIndex );
+		fExpr->get_args().push_back( dstIndex );
 
 		Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
@@ -594,7 +598,7 @@
 		srcIndex->get_args().push_back( srcselect );
 		srcIndex->get_args().push_back( new VariableExpr( index ) );
-		assignExpr->get_args().push_back( srcIndex );
-
-		*out++ = new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, assignExpr ) );
+		fExpr->get_args().push_back( srcIndex );
+
+		*out++ = new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, fExpr ) );
 	}
 
@@ -746,16 +750,16 @@
 					// assign to both destination and return value
 					if ( ArrayType *array = dynamic_cast< ArrayType * >( fixedMember->get_type() ) ) {
-						makeArrayAssignment( srcParam, dstParam, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
-						makeArrayAssignment( srcParam, returnVal, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
+						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 {
-						makeScalarAssignment( srcParam, dstParam, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
-						makeScalarAssignment( srcParam, returnVal, fixedMember, back_inserter( assignDecl->get_statements()->get_kids() ) );
+						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() ) ) {
-						makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
+						makeArrayFunction( srcParam, dstParam, dwt, array, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
 					} else {
-						makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
+						makeScalarFunction( srcParam, dstParam, dwt, "?=?", back_inserter( assignDecl->get_statements()->get_kids() ) );
 					} // if
 				} // if
@@ -766,5 +770,4 @@
 		return assignDecl;
 	}
-
 
 	void makeStructCtorDtor( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
@@ -788,6 +791,8 @@
 		// 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 *dtorDecl = 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();
 
@@ -795,38 +800,39 @@
 		// 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 ) );
 		declsToAdd.push_back( ctorDecl );
+		declsToAdd.push_back( copyCtorDecl );
 		declsToAdd.push_back( dtorDecl );
 
-
-		// 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() ) ) {
-		// 			makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
-		// 			if ( isGeneric ) makeArrayAssignment( srcParam, returnVal, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
-		// 		} else {
-		// 			makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
-		// 			if ( isGeneric ) makeScalarAssignment( srcParam, returnVal, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
-		// 		} // if
-		// 	} // if
-		// } // for
+		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 ) ) );
-
-		// return assignDecl;
-	}
-
-	Declaration *makeUnionAssignment( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting ) {
+	}
+
+	void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
 		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
 
@@ -842,17 +848,32 @@
 		}
 
+		ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 );
+		assignType->get_parameters().push_back( dstParam );
+
+		// default ctor/dtor need only first parameter
+		FunctionType * ctorType = assignType->clone();
+		FunctionType * dtorType = assignType->clone();
+
+		ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
+		assignType->get_parameters().push_back( srcParam );
+
+		// copy ctor needs both parameters
+		FunctionType * copyCtorType = assignType->clone();
+
+		// assignment needs both and return value
 		ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
 		assignType->get_returnVals().push_back( returnVal );
-
-		ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), cloneWithParams( refType, unionParams ) ), 0 );
-		assignType->get_parameters().push_back( dstParam );
-
-		ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 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, NULL, true, false );
+		FunctionDecl *dtorDecl = new FunctionDecl( "^?{}",  functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, dtorType, new CompoundStmt( noLabels ), true, false );
+
 		assignDecl->fixUniqueId();
+		ctorDecl->fixUniqueId();
+		copyCtorDecl->fixUniqueId();
+		dtorDecl->fixUniqueId();
 
 		makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
@@ -861,5 +882,11 @@
 		if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
 
-		return assignDecl;
+		// body of assignment and copy ctor is the same
+		copyCtorDecl->set_statements( assignDecl->get_statements()->clone() );
+
+		declsToAdd.push_back( assignDecl );
+		declsToAdd.push_back( ctorDecl );
+		declsToAdd.push_back( copyCtorDecl );
+		declsToAdd.push_back( dtorDecl );
 	}
 
@@ -888,5 +915,5 @@
 			UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
 			unionInst.set_baseUnion( unionDecl );
-			declsToAdd.push_back( makeUnionAssignment( unionDecl, &unionInst, functionNesting ) );
+			makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAdd );
 		} // if
 	}
