Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision d63eeb0d6eeb995b4c8c414f1d4989b0189ef8ca)
+++ src/SymTab/Validate.cc	(revision 7528ba10cd66aa6353fc8a1b816f5aca7fdde207)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 21:50:04 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Tue Feb 09 13:21:56 2016
-// Update Count     : 270
+// Last Modified On : Mon Feb 22 12:26:37 2016
+// Update Count     : 297
 //
 
@@ -729,4 +729,65 @@
 	}
 
+
+	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 *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, ctorType, 0, true, false );
+		ctorDecl->fixUniqueId();
+		dtorDecl->fixUniqueId();
+
+		// add definitions
+		// TODO: add in calls to default constructors and destructors for fields
+		ctorDecl->set_statements( new CompoundStmt( noLabels ) );
+		dtorDecl->set_statements( new CompoundStmt( noLabels ) );
+		declsToAdd.push_back( ctorDecl );
+		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
+		// 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 ) {
 		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
@@ -778,5 +839,7 @@
 			StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
 			structInst.set_baseStruct( structDecl );
+
 			declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) );
+			makeStructCtorDtor( structDecl, &structInst, functionNesting, declsToAdd );
 			structsDone.insert( structDecl->get_name() );
 		} // if
