Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/CodeGen/CodeGenerator.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,11 +5,11 @@
 // file "LICENCE" distributed with Cforall.
 //
-// CodeGenerator.cc -- 
+// CodeGenerator.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 17:32:16 2016
-// Update Count     : 243
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 06 16:01:00 2016
+// Update Count     : 255
 //
 
@@ -67,5 +67,6 @@
 	string mangleName( DeclarationWithType *decl ) {
 		if ( decl->get_mangleName() != "" ) {
-			return decl->get_mangleName();
+			// need to incorporate scope level in order to differentiate names for destructors
+			return decl->get_scopedMangleName();
 		} else {
 			return decl->get_name();
@@ -75,4 +76,24 @@
 	//*** Declarations
 	void CodeGenerator::visit( FunctionDecl *functionDecl ) {
+		// generalize this
+		FunctionDecl::Attribute attr = functionDecl->get_attribute();
+		switch ( attr.type ) {
+			case FunctionDecl::Attribute::Constructor:
+				output << "__attribute__ ((constructor";
+				if ( attr.priority != FunctionDecl::Attribute::Default ) {
+					output << "(" << attr.priority << ")";
+				}
+				output << ")) ";
+				break;
+			case FunctionDecl::Attribute::Destructor:
+				output << "__attribute__ ((destructor";
+				if ( attr.priority != FunctionDecl::Attribute::Default ) {
+					output << "(" << attr.priority << ")";
+				}
+				output << ")) ";
+				break;
+			default:
+				break;
+		}
 		handleStorageClass( functionDecl );
 		if ( functionDecl->get_isInline() ) {
@@ -99,5 +120,5 @@
 		handleStorageClass( objectDecl );
 		output << genType( objectDecl->get_type(), mangleName( objectDecl ) );
-	
+
 		if ( objectDecl->get_init() ) {
 			output << " = ";
@@ -113,5 +134,5 @@
 		if ( aggDecl->get_name() != "" )
 			output << aggDecl->get_name();
-	
+
 		std::list< Declaration * > &memb = aggDecl->get_members();
 
@@ -119,12 +140,12 @@
 			output << " {" << endl;
 
-			cur_indent += CodeGenerator::tabsize; 
+			cur_indent += CodeGenerator::tabsize;
 			for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end();  i++) {
-				output << indent; 
+				output << indent;
 				(*i)->accept( *this );
 				output << ";" << endl;
 			}
 
-			cur_indent -= CodeGenerator::tabsize; 
+			cur_indent -= CodeGenerator::tabsize;
 
 			output << indent << "}";
@@ -141,5 +162,5 @@
 		handleAggregate( aggregateDecl );
 	}
-  
+
 	void CodeGenerator::visit( EnumDecl *aggDecl ) {
 		output << "enum ";
@@ -147,5 +168,5 @@
 		if ( aggDecl->get_name() != "" )
 			output << aggDecl->get_name();
-	
+
 		std::list< Declaration* > &memb = aggDecl->get_members();
 
@@ -153,9 +174,9 @@
 			output << " {" << endl;
 
-			cur_indent += CodeGenerator::tabsize; 
+			cur_indent += CodeGenerator::tabsize;
 			for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end();  i++) {
 				ObjectDecl *obj = dynamic_cast< ObjectDecl* >( *i );
 				assert( obj );
-				output << indent << mangleName( obj ); 
+				output << indent << mangleName( obj );
 				if ( obj->get_init() ) {
 					output << " = ";
@@ -165,17 +186,17 @@
 			} // for
 
-			cur_indent -= CodeGenerator::tabsize; 
+			cur_indent -= CodeGenerator::tabsize;
 
 			output << indent << "}";
 		} // if
 	}
-  
+
 	void CodeGenerator::visit( TraitDecl *aggregateDecl ) {}
-  
+
 	void CodeGenerator::visit( TypedefDecl *typeDecl ) {
 		output << "typedef ";
 		output << genType( typeDecl->get_base(), typeDecl->get_name() );
 	}
-  
+
 	void CodeGenerator::visit( TypeDecl *typeDecl ) {
 		// really, we should mutate this into something that isn't a TypeDecl but that requires large-scale changes,
@@ -213,9 +234,15 @@
 		printDesignators( init->get_designators() );
 		output << "{ ";
-		genCommaList( init->begin_initializers(), init->end_initializers() );
+		if ( init->begin_initializers() == init->end_initializers() ) {
+			// illegal to leave initializer list empty for scalar initializers,
+			// but always legal to have 0
+			output << "0";
+		} else {
+			genCommaList( init->begin_initializers(), init->end_initializers() );
+		}
 		output << " }";
 	}
 
-	void CodeGenerator::visit( Constant *constant ) { 
+	void CodeGenerator::visit( Constant *constant ) {
 		output << constant->get_value() ;
 	}
@@ -231,10 +258,13 @@
 				  case OT_POSTFIXASSIGN:
 				  case OT_INFIXASSIGN:
+				  case OT_CTOR:
+				  case OT_DTOR:
 					{
 						assert( arg != applicationExpr->get_args().end() );
 						if ( AddressExpr *addrExpr = dynamic_cast< AddressExpr * >( *arg ) ) {
-	        
+							// remove & from first assignment/ctor argument
 							*arg = addrExpr->get_arg();
 						} else {
+							// no address-of operator, so must be a pointer - add dereference
 							UntypedExpr *newExpr = new UntypedExpr( new NameExpr( "*?" ) );
 							newExpr->get_args().push_back( *arg );
@@ -243,10 +273,10 @@
 						break;
 					}
-	      
+
 				  default:
 					// do nothing
 					;
 				}
-	    
+
 				switch ( opInfo.type ) {
 				  case OT_INDEX:
@@ -257,10 +287,31 @@
 					output << "]";
 					break;
-	      
+
 				  case OT_CALL:
 					// there are no intrinsic definitions of the function call operator
 					assert( false );
 					break;
-	      
+
+				  case OT_CTOR:
+				  case OT_DTOR:
+					if ( applicationExpr->get_args().size() == 1 ) {
+						// the expression fed into a single parameter constructor or destructor
+						// may contain side effects - output as a void expression
+						output << "((void)(";
+						(*arg++)->accept( *this );
+						output << ")) /* " << opInfo.inputName << " */";
+					} else if ( applicationExpr->get_args().size() == 2 ) {
+						// intrinsic two parameter constructors are essentially bitwise assignment
+						output << "(";
+						(*arg++)->accept( *this );
+						output << opInfo.symbol;
+						(*arg)->accept( *this );
+						output << ") /* " << opInfo.inputName << " */";
+					} else {
+						// no constructors with 0 or more than 2 parameters
+						assert( false );
+					}
+					break;
+
 				  case OT_PREFIX:
 				  case OT_PREFIXASSIGN:
@@ -271,5 +322,5 @@
 					output << ")";
 					break;
-	      
+
 				  case OT_POSTFIX:
 				  case OT_POSTFIXASSIGN:
@@ -278,4 +329,5 @@
 					output << opInfo.symbol;
 					break;
+
 
 				  case OT_INFIX:
@@ -288,5 +340,5 @@
 					output << ")";
 					break;
-	      
+
 				  case OT_CONSTANT:
 				  case OT_LABELADDRESS:
@@ -307,5 +359,5 @@
 		} // if
 	}
-  
+
 	void CodeGenerator::visit( UntypedExpr *untypedExpr ) {
 		if ( NameExpr *nameExpr = dynamic_cast< NameExpr* >( untypedExpr->get_function() ) ) {
@@ -321,9 +373,30 @@
 					output << "]";
 					break;
-	      
+
 				  case OT_CALL:
 					assert( false );
-					break;
-	      
+
+
+				  case OT_CTOR:
+				  case OT_DTOR:
+					if ( untypedExpr->get_args().size() == 1 ) {
+						// the expression fed into a single parameter constructor or destructor
+						// may contain side effects - output as a void expression
+						output << "((void)(";
+						(*arg++)->accept( *this );
+						output << ")) /* " << opInfo.inputName << " */";
+					} else if ( untypedExpr->get_args().size() == 2 ) {
+						// intrinsic two parameter constructors are essentially bitwise assignment
+						output << "(";
+						(*arg++)->accept( *this );
+						output << opInfo.symbol;
+						(*arg)->accept( *this );
+						output << ") /* " << opInfo.inputName << " */";
+					} else {
+						// no constructors with 0 or more than 2 parameters
+						assert( false );
+					}
+					break;
+
 				  case OT_PREFIX:
 				  case OT_PREFIXASSIGN:
@@ -335,5 +408,5 @@
 					output << ")";
 					break;
-	      
+
 				  case OT_POSTFIX:
 				  case OT_POSTFIXASSIGN:
@@ -342,5 +415,5 @@
 					output << opInfo.symbol;
 					break;
-  
+
 				  case OT_INFIX:
 				  case OT_INFIXASSIGN:
@@ -352,5 +425,5 @@
 					output << ")";
 					break;
-					
+
 				  case OT_CONSTANT:
 					// there are no intrinsic definitions of 0 or 1 as functions
@@ -370,5 +443,5 @@
 		} // if
 	}
-  
+
 	void CodeGenerator::visit( NameExpr *nameExpr ) {
 		OperatorInfo opInfo;
@@ -380,5 +453,5 @@
 		} // if
 	}
-  
+
 	void CodeGenerator::visit( AddressExpr *addressExpr ) {
 		output << "(&";
@@ -409,14 +482,14 @@
 		output << ")";
 	}
-  
+
 	void CodeGenerator::visit( UntypedMemberExpr *memberExpr ) {
 		assert( false );
 	}
-  
+
 	void CodeGenerator::visit( MemberExpr *memberExpr ) {
 		memberExpr->get_aggregate()->accept( *this );
 		output << "." << mangleName( memberExpr->get_member() );
 	}
-  
+
 	void CodeGenerator::visit( VariableExpr *variableExpr ) {
 		OperatorInfo opInfo;
@@ -427,10 +500,10 @@
 		} // if
 	}
-  
+
 	void CodeGenerator::visit( ConstantExpr *constantExpr ) {
 		assert( constantExpr->get_constant() );
 		constantExpr->get_constant()->accept( *this );
 	}
-  
+
 	void CodeGenerator::visit( SizeofExpr *sizeofExpr ) {
 		output << "sizeof(";
@@ -469,5 +542,5 @@
 		assert( false && "OffsetPackExpr should not reach code generation" );
 	}
-  
+
 	void CodeGenerator::visit( LogicalExpr *logicalExpr ) {
 		output << "(";
@@ -481,5 +554,5 @@
 		output << ")";
 	}
-  
+
 	void CodeGenerator::visit( ConditionalExpr *conditionalExpr ) {
 		output << "(";
@@ -491,5 +564,5 @@
 		output << ")";
 	}
-  
+
 	void CodeGenerator::visit( CommaExpr *commaExpr ) {
 		output << "(";
@@ -499,7 +572,7 @@
 		output << ")";
 	}
-  
+
 	void CodeGenerator::visit( TupleExpr *tupleExpr ) {}
-  
+
 	void CodeGenerator::visit( TypeExpr *typeExpr ) {}
 
@@ -532,5 +605,5 @@
 			}
 		}
-		cur_indent -= CodeGenerator::tabsize; 
+		cur_indent -= CodeGenerator::tabsize;
 
 		output << indent << "}";
@@ -538,6 +611,6 @@
 
 	void CodeGenerator::visit( ExprStmt *exprStmt ) {
-		// I don't see why this check is necessary. 
-		// If this starts to cause problems then put it back in, 
+		// I don't see why this check is necessary.
+		// If this starts to cause problems then put it back in,
 		// with an explanation
 		assert( exprStmt );
@@ -589,5 +662,5 @@
 		switchStmt->get_condition()->accept( *this );
 		output << " ) ";
-		
+
 		output << "{" << std::endl;
 		cur_indent += CodeGenerator::tabsize;
@@ -609,5 +682,5 @@
 		} // if
 		output << ":\n";
-		
+
 		std::list<Statement *> sts = caseStmt->get_statements();
 
@@ -626,5 +699,5 @@
 			if ( ! branchStmt->get_target().empty() )
 				output << "goto " << branchStmt->get_target();
-			else { 
+			else {
 				if ( branchStmt->get_computedTarget() != 0 ) {
 					output << "goto *";
@@ -677,6 +750,6 @@
 
 	void CodeGenerator::visit( ForStmt *forStmt ) {
-		// initialization is always hoisted, so don't 
-		// bother doing anything with that 
+		// initialization is always hoisted, so don't
+		// bother doing anything with that
 		output << "for (;";
 
@@ -702,5 +775,5 @@
 	void CodeGenerator::visit( DeclStmt *declStmt ) {
 		declStmt->get_decl()->accept( *this );
-	
+
 		if ( doSemicolon( declStmt->get_decl() ) ) {
 			output << ";";
Index: src/CodeGen/FixNames.cc
===================================================================
--- src/CodeGen/FixNames.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/CodeGen/FixNames.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// FixNames.cc -- 
+// FixNames.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon May 18 23:36:42 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Mon Apr 11 15:38:10 2016
 // Update Count     : 1
 //
@@ -26,4 +26,11 @@
 		virtual void visit( ObjectDecl *objectDecl );
 		virtual void visit( FunctionDecl *functionDecl );
+
+		virtual void visit( CompoundStmt *compoundStmt );
+
+	  private:
+		int scopeLevel = 1;
+
+		void fixDWT( DeclarationWithType *dwt );
 	};
 
@@ -33,8 +40,9 @@
 	}
 
-	void fixDWT( DeclarationWithType *dwt ) {
+	void FixNames::fixDWT( DeclarationWithType *dwt ) {
 		if ( dwt->get_name() != "" ) {
 			if ( LinkageSpec::isDecoratable( dwt->get_linkage() ) ) {
 				dwt->set_mangleName( SymTab::Mangler::mangle( dwt ) );
+				dwt->set_scopeLevel( scopeLevel );
 			} // if
 		} // if
@@ -50,4 +58,10 @@
 		fixDWT( functionDecl );
 	}
+
+	void FixNames::visit( CompoundStmt *compoundStmt ) {
+		scopeLevel++;
+		Visitor::visit( compoundStmt );
+		scopeLevel--;
+	}
 } // namespace CodeGen
 
Index: src/CodeGen/OperatorTable.cc
===================================================================
--- src/CodeGen/OperatorTable.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/CodeGen/OperatorTable.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,11 +5,11 @@
 // file "LICENCE" distributed with Cforall.
 //
-// OperatorTable.cc -- 
+// OperatorTable.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jun 23 17:41:14 2015
-// Update Count     : 5
+// Last Modified By : Rob Schluntz
+// Last Modified On : Thu Apr 14 16:48:27 2016
+// Update Count     : 9
 //
 
@@ -21,4 +21,6 @@
 		const OperatorInfo tableValues[] = {
 			{	"?[?]",		"",		"_operator_index",				OT_INDEX			},
+			{	"?{}",		"=",		"_constructor",					OT_CTOR				},
+			{	"^?{}",		"",		"_destructor",					OT_DTOR				},
 			{	"?()",		"",		"_operator_call",				OT_CALL				},
 			{	"?++",		"++",	"_operator_postincr",			OT_POSTFIXASSIGN	},
Index: src/CodeGen/OperatorTable.h
===================================================================
--- src/CodeGen/OperatorTable.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/CodeGen/OperatorTable.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jun 23 16:09:27 2015
-// Update Count     : 3
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Jun 24 16:17:57 2015
+// Update Count     : 5
 //
 
@@ -22,4 +22,6 @@
 	enum OperatorType {
 		OT_INDEX,
+		OT_CTOR,
+		OT_DTOR,
 		OT_CALL,
 		OT_PREFIX,
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/GenPoly/Box.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Feb  5 16:45:07 2016
-// Update Count     : 286
+// Last Modified By : Rob Schluntz
+// Last Modified On : Tue May 03 16:44:47 2016
+// Update Count     : 295
 //
 
@@ -133,5 +133,5 @@
 			Value *lookup( Key *key, const std::list< TypeExpr* >& params ) const {
  				TypeList typeList( params );
- 				
+
 				// scan scopes for matches to the key
 				for ( typename InnerMap::const_iterator insts = instantiations.find( key ); insts != instantiations.end(); insts = instantiations.findNext( insts, key ) ) {
@@ -160,5 +160,5 @@
 			virtual Declaration *mutate( UnionDecl *unionDecl );
 		};
-		
+
 		/// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call
 		class Pass1 : public PolyMutator {
@@ -208,5 +208,5 @@
 			ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps;  ///< Currently known assignment operators
 			ScopedMap< std::string, DeclarationWithType* > adapters;     ///< Set of adapter functions in the current scope
-			
+
 			DeclarationWithType *retval;
 			bool useRetval;
@@ -226,5 +226,5 @@
 			virtual Type *mutate( PointerType *pointerType );
 			virtual Type *mutate( FunctionType *funcType );
-			
+
 		  private:
 			void addAdapters( FunctionType *functionType );
@@ -297,5 +297,5 @@
 			/// Exits the type-variable scope
 			void endTypeScope();
-			
+
 			ScopedSet< std::string > knownLayouts;          ///< Set of generic type layouts known in the current scope, indexed by sizeofName
 			ScopedSet< std::string > knownOffsets;          ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName
@@ -351,5 +351,5 @@
 		PolyGenericCalculator polyCalculator;
 		Pass3 pass3;
-		
+
 		layoutBuilder.mutateDeclarationList( translationUnit );
 		mutateTranslationUnit/*All*/( translationUnit, pass1 );
@@ -370,5 +370,5 @@
 		return functionDecl;
 	}
-	
+
 	/// Get a list of type declarations that will affect a layout function
 	std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) {
@@ -380,5 +380,5 @@
 			}
 		}
-		
+
 		return otypeDecls;
 	}
@@ -387,5 +387,5 @@
 	void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) {
 		BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt );
-		
+
 		for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
 			TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param );
@@ -444,5 +444,5 @@
 		return makeCond( ifCond, ifExpr );
 	}
-	
+
 	/// adds an expression to a compound statement
 	void addExpr( CompoundStmt *stmts, Expression *expr ) {
@@ -454,5 +454,5 @@
 		stmts->get_kids().push_back( stmt );
 	}
-	
+
 	Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {
 		// do not generate layout function for "empty" tag structs
@@ -467,5 +467,5 @@
 		BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
 		PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
-		
+
 		ObjectDecl *sizeParam = new ObjectDecl( sizeofName( structDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
 		layoutFnType->get_parameters().push_back( sizeParam );
@@ -497,7 +497,7 @@
 				addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) );
 			}
-			
+
 			// place current size in the current offset index
-			addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from( n_members ) ) ),
+			addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from_ulong( n_members ) ) ),
 			                                                      derefVar( sizeParam ) ) );
 			++n_members;
@@ -505,5 +505,5 @@
 			// add member size to current size
 			addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
-			
+
 			// take max of member alignment and global alignment
 			addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
@@ -515,9 +515,9 @@
 		return structDecl;
 	}
-	
+
 	Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {
 		// do not generate layout function for "empty" tag unions
 		if ( unionDecl->get_members().empty() ) return unionDecl;
-		
+
 		// get parameters that can change layout, exiting early if none
 		std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );
@@ -528,5 +528,5 @@
 		BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
 		PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
-		
+
 		ObjectDecl *sizeParam = new ObjectDecl( sizeofName( unionDecl->get_name() ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
 		layoutFnType->get_parameters().push_back( sizeParam );
@@ -545,8 +545,8 @@
 			assert( dwt );
 			Type *memberType = dwt->get_type();
-			
+
 			// take max member size and global size
 			addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
-			
+
 			// take max of member alignment and global alignment
 			addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
@@ -558,5 +558,5 @@
 		return unionDecl;
 	}
-	
+
 	////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////
 
@@ -619,5 +619,5 @@
 			return 0;
 		}
-		
+
 		/// returns T if the given declaration is: (*?=?)(T *, T) for some type T (return not checked, but maybe should be), NULL otherwise
 		/// Only picks assignments where neither parameter is cv-qualified
@@ -631,5 +631,5 @@
 						Type *paramType2 = funType->get_parameters().back()->get_type();
 						if ( paramType2->get_qualifiers() != defaultQualifiers ) return 0;
-						
+
 						if ( PointerType *pointerType = dynamic_cast< PointerType* >( paramType1 ) ) {
 							Type *baseType1 = pointerType->get_base();
@@ -784,5 +784,6 @@
 						arg++;
 					} else {
-						throw SemanticError( "unbound type variable in application ", appExpr );
+						/// xxx - should this be an assertion?
+						throw SemanticError( "unbound type variable: " + tyParm->first + " in application ", appExpr );
 					} // if
 				} // if
@@ -803,5 +804,5 @@
 				passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes );
 			}
-			
+
 			// add type information args for presently unseen types in parameter list
 			for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
@@ -882,5 +883,5 @@
 			assert( env );
 			Type *concrete = replaceWithConcrete( appExpr, polyType );
-			// add out-parameter for return value	
+			// add out-parameter for return value
 			return addRetParam( appExpr, function, concrete, arg );
 		}
@@ -910,4 +911,5 @@
 				} else if ( arg->get_results().front()->get_isLvalue() ) {
 					// VariableExpr and MemberExpr are lvalues; need to check this isn't coming from the second arg of a comma expression though (not an lvalue)
+					// xxx - need to test that this code is still reachable
 					if ( CommaExpr *commaArg = dynamic_cast< CommaExpr* >( arg ) ) {
 						commaArg->set_arg2( new AddressExpr( commaArg->get_arg2() ) );
@@ -1291,8 +1293,6 @@
 			} else if ( needsAdapter( function, scopeTyVars ) ) {
 				// std::cerr << "needs adapter: ";
-				// for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
-				// 	std::cerr << i->first << " ";
-				// }
-				// std::cerr << "\n";
+				// printTyVarMap( std::cerr, scopeTyVars );
+				// std::cerr << *env << std::endl;
 				// change the application so it calls the adapter rather than the passed function
 				ret = applyAdapter( appExpr, function, arg, scopeTyVars );
@@ -1345,6 +1345,9 @@
 				} // if
 			} // if
+			// isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
+			// out of the if condition.
+			bool polytype = isPolyType( addrExpr->get_arg()->get_results().front(), scopeTyVars, env );
 			addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
-			if ( isPolyType( addrExpr->get_arg()->get_results().front(), scopeTyVars, env ) || needs ) {
+			if ( polytype || needs ) {
 				Expression *ret = addrExpr->get_arg();
 				delete ret->get_results().front();
@@ -1366,5 +1369,5 @@
 			return new VariableExpr( functionObj );
 		}
-		
+
 		Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
 			if ( retval && returnStmt->get_expr() ) {
@@ -1886,5 +1889,5 @@
 				}
 			}
-			
+
 			Type *ret = Mutator::mutate( funcType );
 
@@ -1905,5 +1908,5 @@
 
 					std::list<Expression*> designators;
-					objectDecl->set_init( new SingleInit( alloc, designators ) );
+					objectDecl->set_init( new SingleInit( alloc, designators, false ) ); // not constructed
 				}
 			}
@@ -1946,5 +1949,5 @@
 			return derefdVar;
 		}
-		
+
 		Expression *PolyGenericCalculator::mutate( MemberExpr *memberExpr ) {
 			// mutate, exiting early if no longer MemberExpr
@@ -2066,11 +2069,11 @@
 				if ( n_members == 0 ) {
 					// all empty structs have the same layout - size 1, align 1
-					makeVar( sizeofName( typeName ), layoutType, new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
-					makeVar( alignofName( typeName ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from( (unsigned long)1 ) ) ) );
+					makeVar( sizeofName( typeName ), layoutType, new SingleInit( new ConstantExpr( Constant::from_ulong( 1 ) ) ) );
+					makeVar( alignofName( typeName ), layoutType->clone(), new SingleInit( new ConstantExpr( Constant::from_ulong( 1 ) ) ) );
 					// NOTE zero-length arrays are forbidden in C, so empty structs have no offsetof array
 				} else {
 					ObjectDecl *sizeVar = makeVar( sizeofName( typeName ), layoutType );
 					ObjectDecl *alignVar = makeVar( alignofName( typeName ), layoutType->clone() );
-					ObjectDecl *offsetVar = makeVar( offsetofName( typeName ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from( n_members ) ), false, false ) );
+					ObjectDecl *offsetVar = makeVar( offsetofName( typeName ), new ArrayType( Type::Qualifiers(), layoutType->clone(), new ConstantExpr( Constant::from_int( n_members ) ), false, false ) );
 
 					// generate call to layout function
@@ -2144,5 +2147,5 @@
 			Type *ty = offsetofExpr->get_type();
 			if ( ! findGeneric( ty ) ) return offsetofExpr;
-			
+
 			if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
 				// replace offsetof expression by index into offset array
@@ -2191,5 +2194,5 @@
 
 					// build the offset array and replace the pack with a reference to it
-					ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from( baseMembers.size() ) ), false, false ),
+					ObjectDecl *offsetArray = makeVar( offsetName, new ArrayType( Type::Qualifiers(), offsetType, new ConstantExpr( Constant::from_ulong( baseMembers.size() ) ), false, false ),
 							new ListInit( inits ) );
 					ret = new VariableExpr( offsetArray );
Index: src/GenPoly/CopyParams.cc
===================================================================
--- src/GenPoly/CopyParams.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/GenPoly/CopyParams.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,9 +5,9 @@
 // file "LICENCE" distributed with Cforall.
 //
-// CopyParams.cc -- 
+// CopyParams.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
+// Last Modified By : Rob Schluntz
 // Last Modified On : Tue May 19 07:33:31 2015
 // Update Count     : 1
@@ -29,5 +29,5 @@
 	  public:
 		CopyParams();
-  
+
 		virtual void visit( FunctionDecl *funcDecl );
 		virtual void visit( AddressExpr *addrExpr );
@@ -50,5 +50,5 @@
 		if ( funcDecl->get_statements() ) {
 			funcDecl->get_statements()->accept( *this );
-	
+
 			if ( ! modVars.empty() ) {
 				std::map< std::string, DeclarationWithType* > assignOps;
@@ -57,4 +57,5 @@
 					if ( (*tyVar)->get_kind() == TypeDecl::Any ) {
 						assert( !(*tyVar)->get_assertions().empty() );
+						assert( (*tyVar)->get_assertions().front()->get_name() == "?=?" );
 						assignOps[ (*tyVar)->get_name() ] = (*tyVar)->get_assertions().front();
 					} // if
Index: src/GenPoly/GenPoly.cc
===================================================================
--- src/GenPoly/GenPoly.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/GenPoly/GenPoly.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// GenPoly.cc -- 
+// GenPoly.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Dec 15 16:11:18 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Mon May 02 14:53:33 2016
 // Update Count     : 13
 //
@@ -81,5 +81,5 @@
 		return 0;
 	}
-	
+
 	Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
 		if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
@@ -112,5 +112,5 @@
 		return 0;
 	}
-	
+
 	Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
 		if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
@@ -146,5 +146,5 @@
 		return isPolyType( type, env );
 	}
-	
+
 	Type * hasPolyBase( Type *type, const TyVarMap &tyVars, int *levels, const TypeSubstitution *env ) {
 		int dummy;
@@ -192,4 +192,8 @@
 				if ( ! fn || fn->get_name() != std::string("*?") ) return 0;
 				expr = *untypedExpr->begin_args();
+			} else if ( CommaExpr *commaExpr = dynamic_cast< CommaExpr* >( expr ) ) {
+				// copy constructors insert comma exprs, look at second argument which contains the variable
+				expr = commaExpr->get_arg2();
+				continue;
 			} else break;
 
@@ -209,5 +213,5 @@
 		}
 	}
-	
+
 	void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) {
 		for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) {
Index: src/GenPoly/PolyMutator.cc
===================================================================
--- src/GenPoly/PolyMutator.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/GenPoly/PolyMutator.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// PolyMutator.cc -- 
+// PolyMutator.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Fri Aug 14 15:28:50 2015
+// Last Modified On : Mon May 02 14:50:58 2016
 // Update Count     : 11
 //
@@ -63,4 +63,5 @@
 				env = expr->get_env();
 			}
+			// xxx - should env be cloned (or moved) onto the result of the mutate?
 			return expr->acceptMutator( *this );
 		} else {
@@ -144,6 +145,6 @@
 		return untypedExpr;
 	}
- 
- 
+
+
 	Initializer *PolyMutator::mutate( SingleInit *singleInit ) {
 		singleInit->set_value( mutateExpression( singleInit->get_value() ) );
Index: src/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/GenPoly/Specialize.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Wed Jan 20 12:40:33 2016
-// Update Count     : 18
+// Last Modified On : Thu Apr 28 15:17:45 2016
+// Update Count     : 24
 //
 
@@ -41,7 +41,7 @@
 		virtual Expression * mutate( AddressExpr *castExpr );
 		virtual Expression * mutate( CastExpr *castExpr );
-		virtual Expression * mutate( LogicalExpr *logicalExpr );
-		virtual Expression * mutate( ConditionalExpr *conditionalExpr );
-		virtual Expression * mutate( CommaExpr *commaExpr );
+		// virtual Expression * mutate( LogicalExpr *logicalExpr );
+		// virtual Expression * mutate( ConditionalExpr *conditionalExpr );
+		// virtual Expression * mutate( CommaExpr *commaExpr );
 
 	  private:
@@ -142,5 +142,5 @@
 
 	Expression * Specialize::doSpecialization( Type *formalType, Expression *actual, InferredParams *inferParams ) {
-		assert( ! actual->get_results().empty() );
+		assert( ! actual->get_results().empty() ); // using front, should have this assert
 		if ( needsSpecialization( formalType, actual->get_results().front(), env ) ) {
 			FunctionType *funType;
@@ -212,15 +212,19 @@
 	}
 
-	Expression * Specialize::mutate( LogicalExpr *logicalExpr ) {
-		return logicalExpr;
-	}
-
-	Expression * Specialize::mutate( ConditionalExpr *condExpr ) {
-		return condExpr;
-	}
-
-	Expression * Specialize::mutate( CommaExpr *commaExpr ) {
-		return commaExpr;
-	}
+	// Removing these for now. Richard put these in for some reason, but it's not clear why.
+	// In particular, copy constructors produce a comma expression, and with this code the parts
+	// of that comma expression are not specialized, which causes problems.
+
+	// Expression * Specialize::mutate( LogicalExpr *logicalExpr ) {
+	// 	return logicalExpr;
+	// }
+
+	// Expression * Specialize::mutate( ConditionalExpr *condExpr ) {
+	// 	return condExpr;
+	// }
+
+	// Expression * Specialize::mutate( CommaExpr *commaExpr ) {
+	// 	return commaExpr;
+	// }
 } // namespace GenPoly
 
Index: src/InitTweak/FixGlobalInit.cc
===================================================================
--- src/InitTweak/FixGlobalInit.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
+++ src/InitTweak/FixGlobalInit.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -0,0 +1,172 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// FixGlobalInit.cc --
+//
+// Author           : Rob Schluntz
+// Created On       : Mon May 04 15:14:56 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 13 11:37:30 2016
+// Update Count     : 2
+//
+
+#include "FixGlobalInit.h"
+#include "InitTweak.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Type.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Statement.h"
+#include "SynTree/Initializer.h"
+#include "SynTree/Visitor.h"
+#include <algorithm>
+
+namespace InitTweak {
+	namespace {
+		const std::list<Label> noLabels;
+	}
+
+	class GlobalFixer : public Visitor {
+	  public:
+		GlobalFixer( const std::string & name, bool inLibrary );
+
+		virtual void visit( ObjectDecl *objDecl );
+		virtual void visit( FunctionDecl *functionDecl );
+		virtual void visit( StructDecl *aggregateDecl );
+		virtual void visit( UnionDecl *aggregateDecl );
+		virtual void visit( EnumDecl *aggregateDecl );
+		virtual void visit( TraitDecl *aggregateDecl );
+		virtual void visit( TypeDecl *typeDecl );
+
+		UniqueName tempNamer;
+		FunctionDecl * initFunction;
+		FunctionDecl * destroyFunction;
+	};
+
+	class ConstExprChecker : public Visitor {
+	public:
+		ConstExprChecker() : isConstExpr( true ) {}
+
+		virtual void visit( ApplicationExpr *applicationExpr ) { isConstExpr = false; }
+		virtual void visit( UntypedExpr *untypedExpr ) { isConstExpr = false; }
+		virtual void visit( NameExpr *nameExpr ) { isConstExpr = false; }
+		virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
+		virtual void visit( LabelAddressExpr *labAddressExpr ) { isConstExpr = false; }
+		virtual void visit( UntypedMemberExpr *memberExpr ) { isConstExpr = false; }
+		virtual void visit( MemberExpr *memberExpr ) { isConstExpr = false; }
+		virtual void visit( VariableExpr *variableExpr ) { isConstExpr = false; }
+		virtual void visit( ConstantExpr *constantExpr ) { /* bottom out */ }
+		// these might be okay?
+		// virtual void visit( SizeofExpr *sizeofExpr );
+		// virtual void visit( AlignofExpr *alignofExpr );
+		// virtual void visit( UntypedOffsetofExpr *offsetofExpr );
+		// virtual void visit( OffsetofExpr *offsetofExpr );
+		// virtual void visit( OffsetPackExpr *offsetPackExpr );
+		// virtual void visit( AttrExpr *attrExpr );
+		// virtual void visit( CommaExpr *commaExpr );
+		// virtual void visit( LogicalExpr *logicalExpr );
+		// virtual void visit( ConditionalExpr *conditionalExpr );
+		virtual void visit( TupleExpr *tupleExpr ) { isConstExpr = false; }
+		virtual void visit( SolvedTupleExpr *tupleExpr ) { isConstExpr = false; }
+		virtual void visit( TypeExpr *typeExpr ) { isConstExpr = false; }
+		virtual void visit( AsmExpr *asmExpr ) { isConstExpr = false; }
+		virtual void visit( UntypedValofExpr *valofExpr ) { isConstExpr = false; }
+		virtual void visit( CompoundLiteralExpr *compLitExpr ) { isConstExpr = false; }
+
+		bool isConstExpr;
+	};
+
+	bool isConstExpr( Initializer * init ) {
+		if ( init ) {
+			ConstExprChecker checker;
+			init->accept( checker );
+			return checker.isConstExpr;
+		}
+		// for all intents and purposes, no initializer means const expr
+		return true;
+	}
+
+	void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ) {
+		GlobalFixer fixer( name, inLibrary );
+		acceptAll( translationUnit, fixer );
+		// don't need to include function if it's empty
+		if ( fixer.initFunction->get_statements()->get_kids().empty() ) {
+			delete fixer.initFunction;
+		} else {
+			translationUnit.push_back( fixer.initFunction );
+		}
+		if ( fixer.destroyFunction->get_statements()->get_kids().empty() ) {
+			delete fixer.destroyFunction;
+		} else {
+			translationUnit.push_back( fixer.destroyFunction );
+		}
+	}
+
+  std::string globalFunctionName( const std::string & name ) {
+  	// get basename
+  	std::string ret = name.substr( 0, name.find( '.' ) );
+  	// replace invalid characters with _
+		static std::string invalid = "/-";
+  	replace_if( ret.begin(), ret.end(), []( char c ) { return invalid.find(c) != std::string::npos; }, '_' );
+  	return ret;
+  }
+
+	GlobalFixer::GlobalFixer( const std::string & name, bool inLibrary ) : tempNamer( "_global_init" ) {
+		std::string fixedName = globalFunctionName( name );
+		initFunction = new FunctionDecl( "_init_" + fixedName, DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false, FunctionDecl::Attribute( FunctionDecl::Attribute::Constructor, inLibrary ? FunctionDecl::Attribute::High : FunctionDecl::Attribute::Default ) );
+
+		destroyFunction = new FunctionDecl( "_destroy_" + fixedName, DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false, FunctionDecl::Attribute( FunctionDecl::Attribute::Destructor, inLibrary ? FunctionDecl::Attribute::High : FunctionDecl::Attribute::Default ) );
+	}
+
+	void GlobalFixer::visit( ObjectDecl *objDecl ) {
+		std::list< Statement * > & initStatements = initFunction->get_statements()->get_kids();
+		std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
+
+		// if ( objDecl->get_init() == NULL ) return;
+		if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects
+		if ( objDecl->get_type()->get_isConst() ) return; // temporary: can't assign to a const variable
+		if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return;
+		// C allows you to initialize objects with constant expressions
+		// xxx - this is an optimization. Need to first resolve constructors before we decide
+		// to keep C-style initializer.
+		// if ( isConstExpr( objDecl->get_init() ) ) return;
+
+		if ( ArrayType * at = dynamic_cast< ArrayType * > ( objDecl->get_type() ) ) {
+			// xxx - initialize each element of the array
+		} else {
+			// steal initializer from object and attach it to a new temporary
+			ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, objDecl->get_type()->clone(), objDecl->get_init() );
+			objDecl->set_init( NULL );
+			initStatements.push_back( new DeclStmt( noLabels, newObj ) );
+
+			// copy construct objDecl using temporary
+			UntypedExpr * init = new UntypedExpr( new NameExpr( "?{}" ) );
+			init->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
+			init->get_args().push_back( new VariableExpr( newObj ) );
+			initStatements.push_back( new ExprStmt( noLabels, init ) );
+
+			// add destructor calls to global destroy function
+			UntypedExpr * destroy = new UntypedExpr( new NameExpr( "^?{}" ) );
+			destroy->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
+			destroyStatements.push_front( new ExprStmt( noLabels, destroy ) );
+		}
+	}
+
+	// only modify global variables
+	void GlobalFixer::visit( FunctionDecl *functionDecl ) {}
+	void GlobalFixer::visit( StructDecl *aggregateDecl ) {}
+	void GlobalFixer::visit( UnionDecl *aggregateDecl ) {}
+	void GlobalFixer::visit( EnumDecl *aggregateDecl ) {}
+	void GlobalFixer::visit( TraitDecl *aggregateDecl ) {}
+	void GlobalFixer::visit( TypeDecl *typeDecl ) {}
+
+} // namespace InitTweak
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
+
Index: src/InitTweak/FixGlobalInit.h
===================================================================
--- src/InitTweak/FixGlobalInit.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
+++ src/InitTweak/FixGlobalInit.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -0,0 +1,42 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// FixGlobalInit.h --
+//
+// Author           : Rob Schluntz
+// Created On       : Mon May 04 15:14:56 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 06 16:07:47 2016
+// Update Count     : 2
+//
+
+#ifndef FIX_GLOBAL_INIT_H
+#define FIX_GLOBAL_INIT_H
+
+#include <string>
+#include <list>
+
+#include "SynTree/SynTree.h"
+#include "SynTree/Declaration.h"
+
+namespace InitTweak {
+  /// Moves global initialization into an _init function that is unique to the translation unit.
+  /// Sets the priority of the initialization function depending on whether the initialization
+  /// function is for library code.
+  void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary );
+
+  /// Apply transformations to a file name to get a valid C identifier which will be used as
+  /// the name of the generated initializer function.
+  std::string globalFunctionName( const std::string & name );
+} // namespace
+
+#endif // GENPOLY_POLYMUTATOR_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
+++ src/InitTweak/FixInit.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -0,0 +1,467 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// FixInit.h --
+//
+// Author           : Rob Schluntz
+// Created On       : Wed Jan 13 16:29:30 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 13 11:44:26 2016
+// Update Count     : 30
+//
+
+#include <stack>
+#include <list>
+#include "FixInit.h"
+#include "InitTweak.h"
+#include "ResolvExpr/Resolver.h"
+#include "ResolvExpr/typeops.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Type.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Statement.h"
+#include "SynTree/Initializer.h"
+#include "SynTree/Mutator.h"
+#include "SymTab/Indexer.h"
+#include "GenPoly/PolyMutator.h"
+
+bool ctordtorp = false;
+#define PRINT( text ) if ( ctordtorp ) { text }
+
+namespace InitTweak {
+	namespace {
+		const std::list<Label> noLabels;
+		const std::list<Expression*> noDesignators;
+	}
+
+	class InsertImplicitCalls : public GenPoly::PolyMutator {
+	public:
+		/// wrap function application expressions as ImplicitCopyCtorExpr nodes
+		/// so that it is easy to identify which function calls need their parameters
+		/// to be copy constructed
+		static void insert( std::list< Declaration * > & translationUnit );
+
+		virtual Expression * mutate( ApplicationExpr * appExpr );
+	};
+
+	class ResolveCopyCtors : public SymTab::Indexer {
+	public:
+		/// generate temporary ObjectDecls for each argument and return value of each
+		/// ImplicitCopyCtorExpr, generate/resolve copy construction expressions for each,
+		/// and generate/resolve destructors for both arguments and return value temporaries
+		static void resolveImplicitCalls( std::list< Declaration * > & translationUnit );
+
+		virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr );
+
+		/// create and resolve ctor/dtor expression: fname(var, [cpArg])
+		ApplicationExpr * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL );
+		/// true if type does not need to be copy constructed to ensure correctness
+		bool skipCopyConstruct( Type * );
+	private:
+		TypeSubstitution * env;
+	};
+
+	class FixInit : public GenPoly::PolyMutator {
+	  public:
+		/// expand each object declaration to use its constructor after it is declared.
+		/// insert destructor calls at the appropriate places
+		static void fixInitializers( std::list< Declaration * > &translationUnit );
+
+		virtual DeclarationWithType * mutate( ObjectDecl *objDecl );
+
+		virtual CompoundStmt * mutate( CompoundStmt * compoundStmt );
+		virtual Statement * mutate( ReturnStmt * returnStmt );
+		virtual Statement * mutate( BranchStmt * branchStmt );
+
+	  private:
+		// stack of list of statements - used to differentiate scopes
+		std::list< std::list< Statement * > > dtorStmts;
+	};
+
+	class FixCopyCtors : public GenPoly::PolyMutator {
+	  public:
+		/// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors,
+		/// call expression, and destructors
+		static void fixCopyCtors( std::list< Declaration * > &translationUnit );
+
+		virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr );
+
+	  private:
+		// stack of list of statements - used to differentiate scopes
+		std::list< std::list< Statement * > > dtorStmts;
+	};
+
+	void fix( std::list< Declaration * > & translationUnit ) {
+		InsertImplicitCalls::insert( translationUnit );
+		ResolveCopyCtors::resolveImplicitCalls( translationUnit );
+		FixInit::fixInitializers( translationUnit );
+		// FixCopyCtors must happen after FixInit, so that destructors are placed correctly
+		FixCopyCtors::fixCopyCtors( translationUnit );
+	}
+
+	void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit ) {
+		InsertImplicitCalls inserter;
+		mutateAll( translationUnit, inserter );
+	}
+
+	void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit ) {
+		ResolveCopyCtors resolver;
+		acceptAll( translationUnit, resolver );
+	}
+
+	void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) {
+		FixInit fixer;
+		mutateAll( translationUnit, fixer );
+	}
+
+	void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit ) {
+		FixCopyCtors fixer;
+		mutateAll( translationUnit, fixer );
+	}
+
+	Expression * InsertImplicitCalls::mutate( ApplicationExpr * appExpr ) {
+		appExpr = dynamic_cast< ApplicationExpr * >( Mutator::mutate( appExpr ) );
+		assert( appExpr );
+
+		if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) {
+			if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) {
+				// optimization: don't need to copy construct in order to call intrinsic functions
+				return appExpr;
+			} else if ( FunctionDecl * funcDecl = dynamic_cast< FunctionDecl * > ( function->get_var() ) ) {
+				FunctionType * ftype = funcDecl->get_functionType();
+				if ( (funcDecl->get_name() == "?{}" || funcDecl->get_name() == "?=?") && ftype->get_parameters().size() == 2 ) {
+					Type * t1 = ftype->get_parameters().front()->get_type();
+					Type * t2 = ftype->get_parameters().back()->get_type();
+					PointerType * ptrType = dynamic_cast< PointerType * > ( t1 );
+					assert( ptrType );
+					if ( ResolvExpr::typesCompatible( ptrType->get_base(), t2, SymTab::Indexer() ) ) {
+						// optimization: don't need to copy construct in order to call a copy constructor or
+						// assignment operator
+						return appExpr;
+					}
+				} else if ( funcDecl->get_name() == "^?{}" ) {
+					// correctness: never copy construct arguments to a destructor
+					return appExpr;
+				}
+			}
+		}
+		PRINT( std::cerr << "InsertImplicitCalls: adding a wrapper " << appExpr << std::endl; )
+
+		// wrap each function call so that it is easy to identify nodes that have to be copy constructed
+		ImplicitCopyCtorExpr * expr = new ImplicitCopyCtorExpr( appExpr );
+		// save the type substitution onto the new node so that it is easy to find.
+		// Ensure it is not deleted with the ImplicitCopyCtorExpr by removing it before deletion.
+		// The substitution is needed to obtain the type of temporary variables so that copy constructor
+		// calls can be resolved. Normally this is what PolyMutator is for, but the pass that resolves
+		// copy constructor calls must be an Indexer. We could alternatively make a PolyIndexer which
+		// saves the environment, or compute the types of temporaries here, but it's much simpler to
+		// save the environment here, and more cohesive to compute temporary variables and resolve copy
+		// constructor calls together.
+		assert( env );
+		expr->set_env( env );
+		return expr;
+	}
+
+	bool ResolveCopyCtors::skipCopyConstruct( Type * type ) {
+		return dynamic_cast< VarArgsType * >( type ) || GenPoly::getFunctionType( type );
+	}
+
+	ApplicationExpr * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
+		assert( var );
+		UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) );
+		untyped->get_args().push_back( new AddressExpr( new VariableExpr( var ) ) );
+		if (cpArg) untyped->get_args().push_back( cpArg );
+
+		// resolve copy constructor
+		// should only be one alternative for copy ctor and dtor expressions, since
+		// all arguments are fixed (VariableExpr and already resolved expression)
+		PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )
+		ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) );
+		if ( resolved->get_env() ) {
+			env->add( *resolved->get_env() );
+		}
+
+		assert( resolved );
+		delete untyped;
+		return resolved;
+	}
+
+	void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
+		static UniqueName tempNamer("_tmp_cp");
+		static UniqueName retNamer("_tmp_cp_ret");
+
+		PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
+		Visitor::visit( impCpCtorExpr );
+		env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer...
+
+		ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr();
+
+		// take each argument and attempt to copy construct it.
+		for ( Expression * & arg : appExpr->get_args() ) {
+			PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; )
+			// xxx - need to handle tuple arguments
+			assert( ! arg->get_results().empty() );
+			Type * result = arg->get_results().front();
+			if ( skipCopyConstruct( result ) ) continue; // skip certain non-copyable types
+			// type may involve type variables, so apply type substitution to get temporary variable's actual type
+			result = result->clone();
+			impCpCtorExpr->get_env()->apply( result );
+			ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 );
+			tmp->get_type()->set_isConst( false );
+
+			// create and resolve copy constructor
+			PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; )
+			ApplicationExpr * cpCtor = makeCtorDtor( "?{}", tmp, arg );
+
+			// if the chosen constructor is intrinsic, the copy is unnecessary, so
+			// don't create the temporary and don't call the copy constructor
+			VariableExpr * function = dynamic_cast< VariableExpr * >( cpCtor->get_function() );
+			assert( function );
+			if ( function->get_var()->get_linkage() != LinkageSpec::Intrinsic ) {
+				// replace argument to function call with temporary
+				arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
+				impCpCtorExpr->get_tempDecls().push_back( tmp );
+				impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
+			}
+		}
+
+		// each return value from the call needs to be connected with an ObjectDecl
+		// at the call site, which is initialized with the return value and is destructed
+		// later
+		// xxx - handle multiple return values
+		ApplicationExpr * callExpr = impCpCtorExpr->get_callExpr();
+		// xxx - is this right? callExpr may not have the right environment, because it was attached
+		// at a higher level. Trying to pass that environment along.
+		callExpr->set_env( impCpCtorExpr->get_env()->clone() );
+		for ( Type * result : appExpr->get_results() ) {
+			result = result->clone();
+			impCpCtorExpr->get_env()->apply( result );
+			ObjectDecl * ret = new ObjectDecl( retNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 );
+			ret->get_type()->set_isConst( false );
+			impCpCtorExpr->get_returnDecls().push_back( ret );
+			PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
+			impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
+		}
+		PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; )
+	}
+
+
+	Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
+		PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; )
+
+		impCpCtorExpr = dynamic_cast< ImplicitCopyCtorExpr * >( Mutator::mutate( impCpCtorExpr ) );
+		assert( impCpCtorExpr );
+
+		std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls();
+		std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls();
+		std::list< Expression * > & dtors = impCpCtorExpr->get_dtors();
+
+		// add all temporary declarations and their constructors
+		for ( ObjectDecl * obj : tempDecls ) {
+			stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
+		}
+		for ( ObjectDecl * obj : returnDecls ) {
+			stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
+		}
+
+		// add destructors after current statement
+		for ( Expression * dtor : dtors ) {
+			stmtsToAddAfter.push_back( new ExprStmt( noLabels, dtor ) );
+		}
+
+		// xxx - update to work with multiple return values
+		ObjectDecl * returnDecl = returnDecls.empty() ? NULL : returnDecls.front();
+		Expression * callExpr = impCpCtorExpr->get_callExpr();
+
+		PRINT( std::cerr << "Coming out the back..." << impCpCtorExpr << std::endl; )
+
+		// xxx - some of these aren't necessary, and can be removed once this is stable
+		dtors.clear();
+		tempDecls.clear();
+		returnDecls.clear();
+		impCpCtorExpr->set_callExpr( NULL );
+		impCpCtorExpr->set_env( NULL );
+		delete impCpCtorExpr;
+
+		if ( returnDecl ) {
+			UntypedExpr * assign = new UntypedExpr( new NameExpr( "?=?" ) );
+			assign->get_args().push_back( new VariableExpr( returnDecl ) );
+			assign->get_args().push_back( callExpr );
+			// know the result type of the assignment is the type of the LHS (minus the pointer), so
+			// add that onto the assignment expression so that later steps have the necessary information
+			assign->add_result( returnDecl->get_type()->clone() );
+
+			Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
+			if ( callExpr->get_results().front()->get_isLvalue() ) {
+				// lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any
+				// lvalue returning non-intrinsic function. Add an AddressExpr to the call to negate
+				// the derefence and change the type of the return temporary from T to T* to properly
+				// capture the return value. Then dereference the result of the comma expression, since
+				// the lvalue returning call was originally wrapped with an AddressExpr.
+				// Effectively, this turns
+				//   lvalue T f();
+				//   &*f()
+				// into
+				//   T * tmp_cp_retN;
+				//   tmp_cp_ret_N = &*(tmp_cp_ret_N = &*f(), tmp_cp_ret);
+				// which work out in terms of types, but is pretty messy. It would be nice to find a better way.
+				assign->get_args().back() = new AddressExpr( assign->get_args().back() );
+
+				Type * resultType = returnDecl->get_type()->clone();
+				returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) );
+				UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
+				deref->get_args().push_back( retExpr );
+				deref->add_result( resultType );
+				retExpr = deref;
+			}
+			// xxx - might need to set env on retExpr...
+			// retExpr->set_env( env->clone() );
+			return retExpr;
+		} else {
+			return callExpr;
+		}
+	}
+
+	DeclarationWithType *FixInit::mutate( ObjectDecl *objDecl ) {
+		// first recursively handle pieces of ObjectDecl so that they aren't missed by other visitors
+		// when the init is removed from the ObjectDecl
+		objDecl = dynamic_cast< ObjectDecl * >( Mutator::mutate( objDecl ) );
+
+		if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
+			// a decision should have been made by the resolver, so ctor and init are not both non-NULL
+			assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
+			if ( Statement * ctor = ctorInit->get_ctor() ) {
+				if ( objDecl->get_storageClass() == DeclarationNode::Static ) {
+					// generate:
+					// static bool __objName_uninitialized = true;
+					// if (__objName_uninitialized) {
+					//   __ctor(__objName);
+					//   void dtor_atexit() {
+					//     __dtor(__objName);
+					//   }
+					//   on_exit(dtorOnExit, &__objName);
+					//   __objName_uninitialized = false;
+					// }
+
+					// generate first line
+					BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool );
+					SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators );
+					ObjectDecl * isUninitializedVar = new ObjectDecl( objDecl->get_mangleName() + "_uninitialized", DeclarationNode::Static, LinkageSpec::Cforall, 0, boolType, boolInitExpr );
+					isUninitializedVar->fixUniqueId();
+
+					// void dtor_atexit(...) {...}
+					FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + "_dtor_atexit", DeclarationNode::NoStorageClass, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
+					dtorCaller->fixUniqueId();
+					dtorCaller->get_statements()->get_kids().push_back( ctorInit->get_dtor() );
+
+					// on_exit(dtor_atexit);
+					UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
+					callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
+
+					// __objName_uninitialized = false;
+					UntypedExpr * setTrue = new UntypedExpr( new NameExpr( "?=?" ) );
+					setTrue->get_args().push_back( new VariableExpr( isUninitializedVar ) );
+					setTrue->get_args().push_back( new ConstantExpr( Constant( boolType->clone(), "0" ) ) );
+
+					// generate body of if
+					CompoundStmt * initStmts = new CompoundStmt( noLabels );
+					std::list< Statement * > & body = initStmts->get_kids();
+					body.push_back( ctor );
+					body.push_back( new DeclStmt( noLabels, dtorCaller ) );
+					body.push_back( new ExprStmt( noLabels, callAtexit ) );
+					body.push_back( new ExprStmt( noLabels, setTrue ) );
+
+					// put it all together
+					IfStmt * ifStmt = new IfStmt( noLabels, new VariableExpr( isUninitializedVar ), initStmts, 0 );
+					stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) );
+					stmtsToAddAfter.push_back( ifStmt );
+				} else {
+					stmtsToAddAfter.push_back( ctor );
+					dtorStmts.back().push_front( ctorInit->get_dtor() );
+				}
+				objDecl->set_init( NULL );
+				ctorInit->set_ctor( NULL );
+				ctorInit->set_dtor( NULL );  // xxx - only destruct when constructing? Probably not?
+			} else if ( Initializer * init = ctorInit->get_init() ) {
+				objDecl->set_init( init );
+				ctorInit->set_init( NULL );
+			} else {
+				// no constructor and no initializer, which is okay
+				objDecl->set_init( NULL );
+			}
+			delete ctorInit;
+		}
+		return objDecl;
+	}
+
+	namespace {
+		template<typename Iterator, typename OutputIterator>
+		void insertDtors( Iterator begin, Iterator end, OutputIterator out ) {
+			for ( Iterator it = begin ; it != end ; ++it ) {
+				// remove if instrinsic destructor statement. Note that this is only called
+				// on lists of implicit dtors, so if the user manually calls an intrinsic
+				// dtor then the call must (and will) still be generated since the argument
+				// may contain side effects.
+				if ( ! isInstrinsicSingleArgCallStmt( *it ) ) {
+					// don't need to call intrinsic dtor, because it does nothing, but
+					// non-intrinsic dtors must be called
+					*out++ = (*it)->clone();
+				}
+			}
+		}
+	}
+
+	CompoundStmt * FixInit::mutate( CompoundStmt * compoundStmt ) {
+		// mutate statements - this will also populate dtorStmts list.
+		// don't want to dump all destructors when block is left,
+		// just the destructors associated with variables defined in this block,
+		// so push a new list to the top of the stack so that we can differentiate scopes
+		dtorStmts.push_back( std::list<Statement *>() );
+
+		compoundStmt = PolyMutator::mutate( compoundStmt );
+		std::list< Statement * > & statements = compoundStmt->get_kids();
+
+		insertDtors( dtorStmts.back().begin(), dtorStmts.back().end(), back_inserter( statements ) );
+
+		deleteAll( dtorStmts.back() );
+		dtorStmts.pop_back();
+		return compoundStmt;
+	}
+
+	Statement * FixInit::mutate( ReturnStmt * returnStmt ) {
+		for ( std::list< std::list< Statement * > >::reverse_iterator list = dtorStmts.rbegin(); list != dtorStmts.rend(); ++list ) {
+			insertDtors( list->begin(), list->end(), back_inserter( stmtsToAdd ) );
+		}
+		return Mutator::mutate( returnStmt );
+	}
+
+	Statement * FixInit::mutate( BranchStmt * branchStmt ) {
+		// TODO: adding to the end of a block isn't sufficient, since
+		// return/break/goto should trigger destructor when block is left.
+		switch( branchStmt->get_type() ) {
+			case BranchStmt::Continue:
+			case BranchStmt::Break:
+				insertDtors( dtorStmts.back().begin(), dtorStmts.back().end(), back_inserter( stmtsToAdd ) );
+				break;
+			case BranchStmt::Goto:
+				// xxx
+				// if goto leaves a block, generate dtors for every block it leaves
+				// if goto is in same block but earlier statement, destruct every object that was defined after the statement
+				break;
+			default:
+				assert( false );
+		}
+		return Mutator::mutate( branchStmt );
+	}
+
+
+} // namespace InitTweak
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/InitTweak/FixInit.h
===================================================================
--- src/InitTweak/FixInit.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
+++ src/InitTweak/FixInit.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -0,0 +1,38 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// FixInit.h --
+//
+// Author           : Rob Schluntz
+// Created On       : Wed Jan 13 16:29:30 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 13 11:27:52 2016
+// Update Count     : 5
+//
+
+#ifndef FIX_INIT_H
+#define FIX_INIT_H
+
+#include <string>
+#include <list>
+
+#include "SynTree/SynTree.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Mutator.h"
+
+namespace InitTweak {
+  /// replace constructor initializers with expression statements
+  /// and unwrap basic C-style initializers
+	void fix( std::list< Declaration * > & translationUnit );
+} // namespace
+
+#endif // GENPOLY_POLYMUTATOR_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
+++ src/InitTweak/GenInit.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -0,0 +1,220 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// GenInit.cc --
+//
+// Author           : Rob Schluntz
+// Created On       : Mon May 18 07:44:20 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 13 11:37:48 2016
+// Update Count     : 166
+//
+
+#include <stack>
+#include <list>
+#include "GenInit.h"
+#include "InitTweak.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Type.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Statement.h"
+#include "SynTree/Initializer.h"
+#include "SynTree/Mutator.h"
+#include "SymTab/Autogen.h"
+#include "GenPoly/PolyMutator.h"
+
+namespace InitTweak {
+	namespace {
+		const std::list<Label> noLabels;
+		const std::list<Expression *> noDesignators;
+	}
+
+	class ReturnFixer : public GenPoly::PolyMutator {
+	  public:
+		/// consistently allocates a temporary variable for the return value
+		/// of a function so that anything which the resolver decides can be constructed
+		/// into the return type of a function can be returned.
+		static void makeReturnTemp( std::list< Declaration * > &translationUnit );
+
+		ReturnFixer();
+
+		virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
+
+		virtual Statement * mutate( ReturnStmt * returnStmt );
+
+	  protected:
+		std::list<DeclarationWithType*> returnVals;
+		UniqueName tempNamer;
+		std::string funcName;
+	};
+
+	class CtorDtor : public GenPoly::PolyMutator {
+	  public:
+		/// create constructor and destructor statements for object declarations.
+		/// Destructors are inserted directly into the code, whereas constructors
+		/// will be added in after the resolver has run so that the initializer expression
+		/// is only removed if a constructor is found
+		static void generateCtorDtor( std::list< Declaration * > &translationUnit );
+
+		CtorDtor() : inFunction( false ) {}
+
+		virtual DeclarationWithType * mutate( ObjectDecl * );
+		virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
+		virtual Declaration* mutate( StructDecl *aggregateDecl );
+		virtual Declaration* mutate( UnionDecl *aggregateDecl );
+		virtual Declaration* mutate( EnumDecl *aggregateDecl );
+		virtual Declaration* mutate( TraitDecl *aggregateDecl );
+		virtual TypeDecl* mutate( TypeDecl *typeDecl );
+		virtual Declaration* mutate( TypedefDecl *typeDecl );
+
+		virtual Type * mutate( FunctionType *funcType );
+
+	  protected:
+		bool inFunction;
+	};
+
+	void genInit( std::list< Declaration * > & translationUnit ) {
+		ReturnFixer::makeReturnTemp( translationUnit );
+		CtorDtor::generateCtorDtor( translationUnit );
+	}
+
+	void ReturnFixer::makeReturnTemp( std::list< Declaration * > & translationUnit ) {
+		ReturnFixer fixer;
+		mutateAll( translationUnit, fixer );
+	}
+
+	ReturnFixer::ReturnFixer() : tempNamer( "_retVal" ) {}
+
+	Statement *ReturnFixer::mutate( ReturnStmt *returnStmt ) {
+		// update for multiple return values
+		assert( returnVals.size() == 0 || returnVals.size() == 1 );
+		// hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
+		// is being returned
+		if ( returnStmt->get_expr() && returnVals.size() == 1 && funcName != "?=?" && ! returnVals.front()->get_type()->get_isLvalue() ) {
+			// ensure return value is not destructed by explicitly creating
+			// an empty SingleInit node wherein maybeConstruct is false
+			ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, returnVals.front()->get_type()->clone(), new ListInit( std::list<Initializer*>(), noDesignators, false ) );
+			stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
+
+			// and explicitly create the constructor expression separately
+			UntypedExpr *construct = new UntypedExpr( new NameExpr( "?{}" ) );
+			construct->get_args().push_back( new AddressExpr( new VariableExpr( newObj ) ) );
+			construct->get_args().push_back( returnStmt->get_expr() );
+			stmtsToAdd.push_back(new ExprStmt(noLabels, construct));
+
+			returnStmt->set_expr( new VariableExpr( newObj ) );
+		} // if
+		return returnStmt;
+	}
+
+	DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) {
+		std::list<DeclarationWithType*> oldReturnVals = returnVals;
+		std::string oldFuncName = funcName;
+
+		FunctionType * type = functionDecl->get_functionType();
+		returnVals = type->get_returnVals();
+		funcName = functionDecl->get_name();
+		DeclarationWithType * decl = Mutator::mutate( functionDecl );
+		returnVals = oldReturnVals;
+		funcName = oldFuncName;
+		return decl;
+	}
+
+
+	void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
+		CtorDtor ctordtor;
+		mutateAll( translationUnit, ctordtor );
+	}
+
+	namespace {
+		Expression * makeCtorDtorExpr( std::string name, ObjectDecl * objDecl, std::list< Expression * > args ) {
+			UntypedExpr * expr = new UntypedExpr( new NameExpr( name ) );
+			expr->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
+			expr->get_args().splice( expr->get_args().end(), args );
+			return expr;
+		}
+	}
+
+	DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) {
+		// hands off if designated or if @=
+		if ( tryConstruct( objDecl ) ) {
+			if ( inFunction ) {
+				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
+					// TODO: walk initializer and generate appropriate copy ctor if element has initializer
+					std::list< Expression * > args = makeInitList( objDecl->get_init() );
+					if ( args.empty() ) {
+						std::list< Statement * > ctor;
+						std::list< Statement * > dtor;
+
+						SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "?{}", back_inserter( ctor ) );
+						SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "^?{}", front_inserter( dtor ), false );
+
+						// Currently makeArrayFunction produces a single Statement - a CompoundStmt
+						// which  wraps everything that needs to happen. As such, it's technically
+						// possible to use a Statement ** in the above calls, but this is inherently
+						// unsafe, so instead we take the slightly less efficient route, but will be
+						// immediately informed if somehow the above assumption is broken. In this case,
+						// we could always wrap the list of statements at this point with a CompoundStmt,
+						// but it seems reasonable at the moment for this to be done by makeArrayFunction
+						// itself
+						assert( ctor.size() == 1 );
+						assert( dtor.size() == 1 );
+
+						objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
+					} else {
+						// array came with an initializer list: initialize each element
+						// may have more initializers than elements in the array - need to check at each index that
+						// we haven't exceeded size. This requires precomputing the size because it might be a side-effecting
+						// computation.
+						// may have fewer initializers than eleemnts in the array - need to default construct
+						// remaining elements.
+						// might be able to merge this with the case above.
+					}
+				} 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
+					ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor );
+					ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor );
+					objDecl->set_init( new ConstructorInit( ctorStmt, dtorStmt, objDecl->get_init() ) );
+				}
+			}
+		}
+		return Mutator::mutate( objDecl );
+	}
+
+	DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
+		// parameters should not be constructed and destructed, so don't mutate FunctionType
+		bool oldInFunc = inFunction;
+		mutateAll( functionDecl->get_oldDecls(), *this );
+		inFunction = true;
+		functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
+		inFunction = oldInFunc;
+		return functionDecl;
+	}
+
+	// should not traverse into any of these declarations to find objects
+	// that need to be constructed or destructed
+	Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
+	Declaration* CtorDtor::mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
+	Declaration* CtorDtor::mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
+	Declaration* CtorDtor::mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }
+	TypeDecl* CtorDtor::mutate( TypeDecl *typeDecl ) { return typeDecl; }
+	Declaration* CtorDtor::mutate( TypedefDecl *typeDecl ) { return typeDecl; }
+	Type* CtorDtor::mutate( FunctionType *funcType ) { return funcType; }
+
+} // namespace InitTweak
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/InitTweak/GenInit.h
===================================================================
--- src/InitTweak/GenInit.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
+++ src/InitTweak/GenInit.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -0,0 +1,37 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// RemoveInit.h --
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Mon May 18 07:44:20 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 13 11:27:19 2016
+// Update Count     : 3
+//
+
+#ifndef GEN_INIT_H
+#define GEN_INIT_H
+
+#include <string>
+#include <list>
+
+#include "SynTree/SynTree.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Mutator.h"
+
+namespace InitTweak {
+	/// Adds return value temporaries and wraps Initializers in ConstructorInit nodes
+	void genInit( std::list< Declaration * > & translationUnit );
+} // namespace
+
+#endif // INITTWEAK_GENINIT_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/InitTweak/InitModel.cc
===================================================================
--- src/InitTweak/InitModel.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/InitTweak/InitModel.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,11 +5,11 @@
 // file "LICENCE" distributed with Cforall.
 //
-// InitModel.cc -- 
+// InitModel.cc --
 //
 // Author           : Rodolfo G. Esteves
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue May 19 16:37:08 2015
-// Update Count     : 1
+// Last Modified By : Rob Schluntz
+// Last Modified On : Thu Jan 07 13:38:46 2016
+// Update Count     : 5
 //
 
@@ -198,5 +198,5 @@
 		assert(init == 0 && single != 0);
 		std::list< Expression * > empty;
-		init = new SingleInit( single->get_expr(), empty );
+		init = new SingleInit( single->get_expr(), empty, false ); // cannot be constructed
 		return;
 	}
@@ -214,5 +214,6 @@
 			} // if
 
-		init = new ListInit( contents );
+		std::list< Expression * > desig;
+		init = new ListInit( contents, desig, false ); // cannot be constructed
 		return;
 	}
Index: src/InitTweak/RemoveInit.cc
===================================================================
--- src/InitTweak/RemoveInit.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ 	(revision )
@@ -1,127 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// RemoveInit.cc -- 
-//
-// Author           : Rob Schluntz
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Dec 15 15:37:26 2015
-// Update Count     : 15
-//
-
-#include "RemoveInit.h"
-#include "SynTree/Declaration.h"
-#include "SynTree/Type.h"
-#include "SynTree/Expression.h"
-#include "SynTree/Statement.h"
-#include "SynTree/Initializer.h"
-#include "SynTree/Mutator.h"
-
-namespace InitTweak {
-	namespace {
-		const std::list<Label> noLabels;
-	}
-	
-	class RemoveInit : public Mutator {
-	  public:
-		RemoveInit();
-		virtual ObjectDecl * mutate(ObjectDecl *objDecl);
-		virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
-
-		virtual Statement * mutate( ReturnStmt * returnStmt );
-		
-		virtual CompoundStmt * mutate(CompoundStmt * compoundStmt);
-		
-	  protected:
-		std::list< Statement* > stmtsToAddBefore;
-		std::list< Statement* > stmtsToAddAfter;
-		void mutateStatementList( std::list< Statement* > &statements );
-
-		std::list<DeclarationWithType*> returnVals;
-		UniqueName tempNamer;
-		std::string funcName;
-	};
-
-	void tweak( std::list< Declaration * > translationUnit ) {
-		RemoveInit remover;
-		mutateAll( translationUnit, remover );
-	}
-
-	RemoveInit::RemoveInit() : tempNamer( "_retVal" ) {}
-	
-	void RemoveInit::mutateStatementList( std::list< Statement* > &statements ) {
-		for ( std::list< Statement* >::iterator i = statements.begin(); i != statements.end(); ++i ) {
-			if ( ! stmtsToAddAfter.empty() ) {
-				statements.splice( i, stmtsToAddAfter );
-			} // if
-			*i = (*i)->acceptMutator( *this );
-			if ( ! stmtsToAddBefore.empty() ) {
-				statements.splice( i, stmtsToAddBefore );
-			} // if
-		} // for
-		if ( ! stmtsToAddAfter.empty() ) {
-			statements.splice( statements.end(), stmtsToAddAfter );
-		} // if
-	}
-
-	CompoundStmt *RemoveInit::mutate(CompoundStmt *compoundStmt) {
-		mutateStatementList( compoundStmt->get_kids() );
-		return compoundStmt;
-	}
-
-	// in the case where an object has an initializer and a polymorphic type, insert an assignment immediately after the
-	// declaration. This will (seemingly) cause the later phases to do the right thing with the assignment
-	ObjectDecl *RemoveInit::mutate( ObjectDecl *objDecl ) {
-		if (objDecl->get_init() && dynamic_cast<TypeInstType*>(objDecl->get_type())) {
-			if (SingleInit * single = dynamic_cast<SingleInit*>(objDecl->get_init())) {
-				UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
-				assign->get_args().push_back( new AddressExpr (new NameExpr( objDecl->get_name() ) ) );
-				assign->get_args().push_back( single->get_value()->clone() );
-				stmtsToAddAfter.push_back(new ExprStmt(noLabels, assign));
-			} // if
-		} // if
-		return objDecl;
-	}
-
-	Statement *RemoveInit::mutate( ReturnStmt *returnStmt ) {
-		// update for multiple return values
-		assert( returnVals.size() == 0 || returnVals.size() == 1 );
-		// hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
-		// is being returned
-		if ( returnStmt->get_expr() && returnVals.size() == 1 && funcName != "?=?" && ! returnVals.front()->get_type()->get_isLvalue()  ) {
-			ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, returnVals.front()->get_type()->clone(), 0 );
-			stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) );
-			
-			UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
-			assign->get_args().push_back( new AddressExpr (new NameExpr( newObj->get_name() ) ) );
-			assign->get_args().push_back( returnStmt->get_expr() );
-			stmtsToAddBefore.push_back(new ExprStmt(noLabels, assign));
-
-			returnStmt->set_expr( new VariableExpr( newObj ) );
-		} // if
-		return returnStmt;
-	}
-
-	DeclarationWithType* RemoveInit::mutate( FunctionDecl *functionDecl ) {
-		std::list<DeclarationWithType*> oldReturnVals = returnVals;
-		std::string oldFuncName = funcName;
-		
-		FunctionType * type = functionDecl->get_functionType();
-		returnVals = type->get_returnVals();
-		funcName = functionDecl->get_name();
-		DeclarationWithType * decl = Mutator::mutate( functionDecl );
-		returnVals = oldReturnVals;
-		funcName = oldFuncName;
-		return decl;
-	}
-} // namespace InitTweak
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/InitTweak/RemoveInit.h
===================================================================
--- src/InitTweak/RemoveInit.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ 	(revision )
@@ -1,37 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// RemoveInit.h -- 
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Nov 27 17:00:47 2015
-// Update Count     : 2
-//
-
-#ifndef REMOVE_INIT_H
-#define REMOVE_INIT_H
-
-#include <string>
-#include <list>
-
-#include "SynTree/SynTree.h"
-#include "SynTree/Declaration.h"
-#include "SynTree/Mutator.h"
-
-namespace InitTweak {
-	/// Adds assignment statements for polymorphic type initializers
-	void tweak( std::list< Declaration * > translationUnit );
-} // namespace 
-
-#endif // GENPOLY_POLYMUTATOR_H
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/InitTweak/module.mk
===================================================================
--- src/InitTweak/module.mk	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/InitTweak/module.mk	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -11,8 +11,11 @@
 ## Created On       : Mon Jun  1 17:49:17 2015
 ## Last Modified By : Rob Schluntz
-## Last Modified On : Mon Jan 11 14:40:16 2016
-## Update Count     : 2
+## Last Modified On : Fri May 13 11:36:24 2016
+## Update Count     : 3
 ###############################################################################
 
-SRC += InitTweak/RemoveInit.cc
+SRC += InitTweak/GenInit.cc \
+	InitTweak/FixInit.cc \
+	InitTweak/FixGlobalInit.cc \
+	InitTweak/InitTweak.cc
 
Index: src/MakeLibCfa.cc
===================================================================
--- src/MakeLibCfa.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/MakeLibCfa.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,12 +5,12 @@
 // file "LICENCE" distributed with Cforall.
 //
-// MakeLibCfa.cc -- 
+// MakeLibCfa.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Sat May 16 10:33:33 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jun 26 16:52:59 2015
-// Update Count     : 14
-// 
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri Apr 22 13:54:15 2016
+// Update Count     : 40
+//
 
 #include "MakeLibCfa.h"
@@ -29,5 +29,5 @@
 		void visit( FunctionDecl* funcDecl );
 		void visit( ObjectDecl* objDecl );
-  
+
 		std::list< Declaration* > &get_newDecls() { return newDecls; }
 	  private:
@@ -43,5 +43,6 @@
 	void MakeLibCfa::visit( FunctionDecl* origFuncDecl ) {
 		if ( origFuncDecl->get_linkage() != LinkageSpec::Intrinsic ) return;
-  
+		if ( origFuncDecl->get_statements() ) return;
+
 		FunctionDecl *funcDecl = origFuncDecl->clone();
 		CodeGen::OperatorInfo opInfo;
@@ -54,8 +55,14 @@
 		assert( param != funcDecl->get_functionType()->get_parameters().end() );
 
-		if ( (*param)->get_name() == "" ) {
-			(*param)->set_name( paramNamer.newName() );
-			(*param)->set_linkage( LinkageSpec::C );
-		} // if
+		for ( ; param != funcDecl->get_functionType()->get_parameters().end(); ++param ) {
+			if ( (*param)->get_name() == "" ) {
+				(*param)->set_name( paramNamer.newName() );
+				(*param)->set_linkage( LinkageSpec::C );
+			}
+			newExpr->get_args().push_back( new VariableExpr( *param ) );
+		} // for
+
+		funcDecl->set_statements( new CompoundStmt( std::list< Label >() ) );
+		newDecls.push_back( funcDecl );
 
 		switch ( opInfo.type ) {
@@ -65,16 +72,28 @@
 		  case CodeGen::OT_POSTFIX:
 		  case CodeGen::OT_INFIX:
-			newExpr->get_args().push_back( new VariableExpr( *param ) );
-			break;
 		  case CodeGen::OT_PREFIXASSIGN:
 		  case CodeGen::OT_POSTFIXASSIGN:
 		  case CodeGen::OT_INFIXASSIGN:
-			{
-				newExpr->get_args().push_back( new VariableExpr( *param ) );
-				// UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) );
-				// deref->get_args().push_back( new VariableExpr( *param ) );
-				// newExpr->get_args().push_back( deref );
+				funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( std::list< Label >(), newExpr ) );
 				break;
-			}
+		  case CodeGen::OT_CTOR:
+		  	// ctors don't return a value
+		  	if ( funcDecl->get_functionType()->get_parameters().size() == 1 ) {
+		  		// intrinsic default constructors should do nothing
+		  		// delete newExpr;
+		  		break;
+		  	} else {
+		  		assert( funcDecl->get_functionType()->get_parameters().size() == 2 );
+		  		// anything else is a single parameter constructor that is effectively a C-style assignment
+		  		// delete newExpr->get_function();
+		  		assert(newExpr->get_args().size()==2);
+		  		newExpr->set_function( new NameExpr( "?=?" ) );
+			  	funcDecl->get_statements()->get_kids().push_back( new ExprStmt( std::list< Label >(), newExpr ) );
+		  	}
+		  	break;
+		  case CodeGen::OT_DTOR:
+		  	// intrinsic destructors should do nothing
+		  	// delete newExpr;
+		  	break;
 		  case CodeGen::OT_CONSTANT:
 		  case CodeGen::OT_LABELADDRESS:
@@ -82,31 +101,14 @@
 			assert( false );
 		} // switch
-
-		for ( param++; param != funcDecl->get_functionType()->get_parameters().end(); ++param ) {
-			if ( (*param)->get_name() == "" ) {
-				(*param)->set_name( paramNamer.newName() );
-				(*param)->set_linkage( LinkageSpec::C );
-			}
-			newExpr->get_args().push_back( new VariableExpr( *param ) );
-		} // for
-		funcDecl->set_statements( new CompoundStmt( std::list< Label >() ) );
-		funcDecl->get_statements()->get_kids().push_back( new ReturnStmt( std::list< Label >(), newExpr ) );
-		newDecls.push_back( funcDecl );
 	}
 
 	void MakeLibCfa::visit( ObjectDecl* origObjDecl ) {
 		if ( origObjDecl->get_linkage() != LinkageSpec::Intrinsic ) return;
-  
+
 		ObjectDecl *objDecl = origObjDecl->clone();
 		assert( ! objDecl->get_init() );
 		std::list< Expression* > noDesignators;
-		objDecl->set_init( new SingleInit( new NameExpr( objDecl->get_name() ), noDesignators ) );
+		objDecl->set_init( new SingleInit( new NameExpr( objDecl->get_name() ), noDesignators, false ) ); // cannot be constructed
 		newDecls.push_back( objDecl );
 	}
 } // namespace LibCfa
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/Makefile.in	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -123,5 +123,8 @@
 	GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT) \
 	GenPoly/driver_cfa_cpp-DeclMutator.$(OBJEXT) \
-	InitTweak/driver_cfa_cpp-RemoveInit.$(OBJEXT) \
+	InitTweak/driver_cfa_cpp-GenInit.$(OBJEXT) \
+	InitTweak/driver_cfa_cpp-FixInit.$(OBJEXT) \
+	InitTweak/driver_cfa_cpp-FixGlobalInit.$(OBJEXT) \
+	InitTweak/driver_cfa_cpp-InitTweak.$(OBJEXT) \
 	Parser/driver_cfa_cpp-parser.$(OBJEXT) \
 	Parser/driver_cfa_cpp-lex.$(OBJEXT) \
@@ -159,4 +162,5 @@
 	SymTab/driver_cfa_cpp-ImplementationType.$(OBJEXT) \
 	SymTab/driver_cfa_cpp-TypeEquality.$(OBJEXT) \
+	SymTab/driver_cfa_cpp-Autogen.$(OBJEXT) \
 	SynTree/driver_cfa_cpp-Type.$(OBJEXT) \
 	SynTree/driver_cfa_cpp-VoidType.$(OBJEXT) \
@@ -345,10 +349,12 @@
 	GenPoly/ScrubTyVars.cc GenPoly/Lvalue.cc GenPoly/Specialize.cc \
 	GenPoly/CopyParams.cc GenPoly/FindFunction.cc \
-	GenPoly/DeclMutator.cc InitTweak/RemoveInit.cc \
-	Parser/parser.yy Parser/lex.ll Parser/TypedefTable.cc \
-	Parser/ParseNode.cc Parser/DeclarationNode.cc \
-	Parser/ExpressionNode.cc Parser/StatementNode.cc \
-	Parser/InitializerNode.cc Parser/TypeData.cc \
-	Parser/LinkageSpec.cc Parser/parseutility.cc Parser/Parser.cc \
+	GenPoly/DeclMutator.cc InitTweak/GenInit.cc \
+	InitTweak/FixInit.cc InitTweak/FixGlobalInit.cc \
+	InitTweak/InitTweak.cc Parser/parser.yy Parser/lex.ll \
+	Parser/TypedefTable.cc Parser/ParseNode.cc \
+	Parser/DeclarationNode.cc Parser/ExpressionNode.cc \
+	Parser/StatementNode.cc Parser/InitializerNode.cc \
+	Parser/TypeData.cc Parser/LinkageSpec.cc \
+	Parser/parseutility.cc Parser/Parser.cc \
 	ResolvExpr/AlternativeFinder.cc ResolvExpr/Alternative.cc \
 	ResolvExpr/Unify.cc ResolvExpr/PtrsAssignable.cc \
@@ -362,8 +368,9 @@
 	SymTab/Mangler.cc SymTab/Validate.cc SymTab/FixFunction.cc \
 	SymTab/ImplementationType.cc SymTab/TypeEquality.cc \
-	SynTree/Type.cc SynTree/VoidType.cc SynTree/BasicType.cc \
-	SynTree/PointerType.cc SynTree/ArrayType.cc \
-	SynTree/FunctionType.cc SynTree/ReferenceToType.cc \
-	SynTree/TupleType.cc SynTree/TypeofType.cc SynTree/AttrType.cc \
+	SymTab/Autogen.cc SynTree/Type.cc SynTree/VoidType.cc \
+	SynTree/BasicType.cc SynTree/PointerType.cc \
+	SynTree/ArrayType.cc SynTree/FunctionType.cc \
+	SynTree/ReferenceToType.cc SynTree/TupleType.cc \
+	SynTree/TypeofType.cc SynTree/AttrType.cc \
 	SynTree/VarArgsType.cc SynTree/Constant.cc \
 	SynTree/Expression.cc SynTree/TupleExpr.cc \
@@ -561,5 +568,11 @@
 	@$(MKDIR_P) InitTweak/$(DEPDIR)
 	@: > InitTweak/$(DEPDIR)/$(am__dirstamp)
-InitTweak/driver_cfa_cpp-RemoveInit.$(OBJEXT):  \
+InitTweak/driver_cfa_cpp-GenInit.$(OBJEXT): InitTweak/$(am__dirstamp) \
+	InitTweak/$(DEPDIR)/$(am__dirstamp)
+InitTweak/driver_cfa_cpp-FixInit.$(OBJEXT): InitTweak/$(am__dirstamp) \
+	InitTweak/$(DEPDIR)/$(am__dirstamp)
+InitTweak/driver_cfa_cpp-FixGlobalInit.$(OBJEXT):  \
+	InitTweak/$(am__dirstamp) InitTweak/$(DEPDIR)/$(am__dirstamp)
+InitTweak/driver_cfa_cpp-InitTweak.$(OBJEXT):  \
 	InitTweak/$(am__dirstamp) InitTweak/$(DEPDIR)/$(am__dirstamp)
 Parser/parser.h: Parser/parser.cc
@@ -670,4 +683,6 @@
 SymTab/driver_cfa_cpp-TypeEquality.$(OBJEXT): SymTab/$(am__dirstamp) \
 	SymTab/$(DEPDIR)/$(am__dirstamp)
+SymTab/driver_cfa_cpp-Autogen.$(OBJEXT): SymTab/$(am__dirstamp) \
+	SymTab/$(DEPDIR)/$(am__dirstamp)
 SynTree/$(am__dirstamp):
 	@$(MKDIR_P) SynTree
@@ -792,5 +807,8 @@
 	-rm -f GenPoly/driver_cfa_cpp-ScrubTyVars.$(OBJEXT)
 	-rm -f GenPoly/driver_cfa_cpp-Specialize.$(OBJEXT)
-	-rm -f InitTweak/driver_cfa_cpp-RemoveInit.$(OBJEXT)
+	-rm -f InitTweak/driver_cfa_cpp-FixGlobalInit.$(OBJEXT)
+	-rm -f InitTweak/driver_cfa_cpp-FixInit.$(OBJEXT)
+	-rm -f InitTweak/driver_cfa_cpp-GenInit.$(OBJEXT)
+	-rm -f InitTweak/driver_cfa_cpp-InitTweak.$(OBJEXT)
 	-rm -f Parser/driver_cfa_cpp-DeclarationNode.$(OBJEXT)
 	-rm -f Parser/driver_cfa_cpp-ExpressionNode.$(OBJEXT)
@@ -822,4 +840,5 @@
 	-rm -f ResolvExpr/driver_cfa_cpp-TypeEnvironment.$(OBJEXT)
 	-rm -f ResolvExpr/driver_cfa_cpp-Unify.$(OBJEXT)
+	-rm -f SymTab/driver_cfa_cpp-Autogen.$(OBJEXT)
 	-rm -f SymTab/driver_cfa_cpp-FixFunction.$(OBJEXT)
 	-rm -f SymTab/driver_cfa_cpp-ImplementationType.$(OBJEXT)
@@ -897,5 +916,8 @@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Specialize.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-DeclarationNode.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@Parser/$(DEPDIR)/driver_cfa_cpp-ExpressionNode.Po@am__quote@
@@ -927,4 +949,5 @@
 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-TypeEnvironment.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Unify.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-FixFunction.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-ImplementationType.Po@am__quote@
@@ -1366,17 +1389,59 @@
 @am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-DeclMutator.obj `if test -f 'GenPoly/DeclMutator.cc'; then $(CYGPATH_W) 'GenPoly/DeclMutator.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/DeclMutator.cc'; fi`
 
-InitTweak/driver_cfa_cpp-RemoveInit.o: InitTweak/RemoveInit.cc
-@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-RemoveInit.o -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Tpo -c -o InitTweak/driver_cfa_cpp-RemoveInit.o `test -f 'InitTweak/RemoveInit.cc' || echo '$(srcdir)/'`InitTweak/RemoveInit.cc
-@am__fastdepCXX_TRUE@	$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='InitTweak/RemoveInit.cc' object='InitTweak/driver_cfa_cpp-RemoveInit.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-RemoveInit.o `test -f 'InitTweak/RemoveInit.cc' || echo '$(srcdir)/'`InitTweak/RemoveInit.cc
-
-InitTweak/driver_cfa_cpp-RemoveInit.obj: InitTweak/RemoveInit.cc
-@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-RemoveInit.obj -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Tpo -c -o InitTweak/driver_cfa_cpp-RemoveInit.obj `if test -f 'InitTweak/RemoveInit.cc'; then $(CYGPATH_W) 'InitTweak/RemoveInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/RemoveInit.cc'; fi`
-@am__fastdepCXX_TRUE@	$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-RemoveInit.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='InitTweak/RemoveInit.cc' object='InitTweak/driver_cfa_cpp-RemoveInit.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-RemoveInit.obj `if test -f 'InitTweak/RemoveInit.cc'; then $(CYGPATH_W) 'InitTweak/RemoveInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/RemoveInit.cc'; fi`
+InitTweak/driver_cfa_cpp-GenInit.o: InitTweak/GenInit.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-GenInit.o -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Tpo -c -o InitTweak/driver_cfa_cpp-GenInit.o `test -f 'InitTweak/GenInit.cc' || echo '$(srcdir)/'`InitTweak/GenInit.cc
+@am__fastdepCXX_TRUE@	$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='InitTweak/GenInit.cc' object='InitTweak/driver_cfa_cpp-GenInit.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-GenInit.o `test -f 'InitTweak/GenInit.cc' || echo '$(srcdir)/'`InitTweak/GenInit.cc
+
+InitTweak/driver_cfa_cpp-GenInit.obj: InitTweak/GenInit.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-GenInit.obj -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Tpo -c -o InitTweak/driver_cfa_cpp-GenInit.obj `if test -f 'InitTweak/GenInit.cc'; then $(CYGPATH_W) 'InitTweak/GenInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/GenInit.cc'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-GenInit.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='InitTweak/GenInit.cc' object='InitTweak/driver_cfa_cpp-GenInit.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-GenInit.obj `if test -f 'InitTweak/GenInit.cc'; then $(CYGPATH_W) 'InitTweak/GenInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/GenInit.cc'; fi`
+
+InitTweak/driver_cfa_cpp-FixInit.o: InitTweak/FixInit.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-FixInit.o -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Tpo -c -o InitTweak/driver_cfa_cpp-FixInit.o `test -f 'InitTweak/FixInit.cc' || echo '$(srcdir)/'`InitTweak/FixInit.cc
+@am__fastdepCXX_TRUE@	$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='InitTweak/FixInit.cc' object='InitTweak/driver_cfa_cpp-FixInit.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-FixInit.o `test -f 'InitTweak/FixInit.cc' || echo '$(srcdir)/'`InitTweak/FixInit.cc
+
+InitTweak/driver_cfa_cpp-FixInit.obj: InitTweak/FixInit.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-FixInit.obj -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Tpo -c -o InitTweak/driver_cfa_cpp-FixInit.obj `if test -f 'InitTweak/FixInit.cc'; then $(CYGPATH_W) 'InitTweak/FixInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/FixInit.cc'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-FixInit.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='InitTweak/FixInit.cc' object='InitTweak/driver_cfa_cpp-FixInit.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-FixInit.obj `if test -f 'InitTweak/FixInit.cc'; then $(CYGPATH_W) 'InitTweak/FixInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/FixInit.cc'; fi`
+
+InitTweak/driver_cfa_cpp-FixGlobalInit.o: InitTweak/FixGlobalInit.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-FixGlobalInit.o -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Tpo -c -o InitTweak/driver_cfa_cpp-FixGlobalInit.o `test -f 'InitTweak/FixGlobalInit.cc' || echo '$(srcdir)/'`InitTweak/FixGlobalInit.cc
+@am__fastdepCXX_TRUE@	$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='InitTweak/FixGlobalInit.cc' object='InitTweak/driver_cfa_cpp-FixGlobalInit.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-FixGlobalInit.o `test -f 'InitTweak/FixGlobalInit.cc' || echo '$(srcdir)/'`InitTweak/FixGlobalInit.cc
+
+InitTweak/driver_cfa_cpp-FixGlobalInit.obj: InitTweak/FixGlobalInit.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-FixGlobalInit.obj -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Tpo -c -o InitTweak/driver_cfa_cpp-FixGlobalInit.obj `if test -f 'InitTweak/FixGlobalInit.cc'; then $(CYGPATH_W) 'InitTweak/FixGlobalInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/FixGlobalInit.cc'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-FixGlobalInit.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='InitTweak/FixGlobalInit.cc' object='InitTweak/driver_cfa_cpp-FixGlobalInit.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-FixGlobalInit.obj `if test -f 'InitTweak/FixGlobalInit.cc'; then $(CYGPATH_W) 'InitTweak/FixGlobalInit.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/FixGlobalInit.cc'; fi`
+
+InitTweak/driver_cfa_cpp-InitTweak.o: InitTweak/InitTweak.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-InitTweak.o -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Tpo -c -o InitTweak/driver_cfa_cpp-InitTweak.o `test -f 'InitTweak/InitTweak.cc' || echo '$(srcdir)/'`InitTweak/InitTweak.cc
+@am__fastdepCXX_TRUE@	$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='InitTweak/InitTweak.cc' object='InitTweak/driver_cfa_cpp-InitTweak.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-InitTweak.o `test -f 'InitTweak/InitTweak.cc' || echo '$(srcdir)/'`InitTweak/InitTweak.cc
+
+InitTweak/driver_cfa_cpp-InitTweak.obj: InitTweak/InitTweak.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT InitTweak/driver_cfa_cpp-InitTweak.obj -MD -MP -MF InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Tpo -c -o InitTweak/driver_cfa_cpp-InitTweak.obj `if test -f 'InitTweak/InitTweak.cc'; then $(CYGPATH_W) 'InitTweak/InitTweak.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/InitTweak.cc'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Tpo InitTweak/$(DEPDIR)/driver_cfa_cpp-InitTweak.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='InitTweak/InitTweak.cc' object='InitTweak/driver_cfa_cpp-InitTweak.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o InitTweak/driver_cfa_cpp-InitTweak.obj `if test -f 'InitTweak/InitTweak.cc'; then $(CYGPATH_W) 'InitTweak/InitTweak.cc'; else $(CYGPATH_W) '$(srcdir)/InitTweak/InitTweak.cc'; fi`
 
 Parser/driver_cfa_cpp-parser.o: Parser/parser.cc
@@ -1869,4 +1934,18 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-TypeEquality.obj `if test -f 'SymTab/TypeEquality.cc'; then $(CYGPATH_W) 'SymTab/TypeEquality.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/TypeEquality.cc'; fi`
+
+SymTab/driver_cfa_cpp-Autogen.o: SymTab/Autogen.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Autogen.o -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Tpo -c -o SymTab/driver_cfa_cpp-Autogen.o `test -f 'SymTab/Autogen.cc' || echo '$(srcdir)/'`SymTab/Autogen.cc
+@am__fastdepCXX_TRUE@	$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='SymTab/Autogen.cc' object='SymTab/driver_cfa_cpp-Autogen.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-Autogen.o `test -f 'SymTab/Autogen.cc' || echo '$(srcdir)/'`SymTab/Autogen.cc
+
+SymTab/driver_cfa_cpp-Autogen.obj: SymTab/Autogen.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-Autogen.obj -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Tpo -c -o SymTab/driver_cfa_cpp-Autogen.obj `if test -f 'SymTab/Autogen.cc'; then $(CYGPATH_W) 'SymTab/Autogen.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/Autogen.cc'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='SymTab/Autogen.cc' object='SymTab/driver_cfa_cpp-Autogen.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-Autogen.obj `if test -f 'SymTab/Autogen.cc'; then $(CYGPATH_W) 'SymTab/Autogen.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/Autogen.cc'; fi`
 
 SynTree/driver_cfa_cpp-Type.o: SynTree/Type.cc
Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/Parser/DeclarationNode.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// DeclarationNode.cc -- 
+// DeclarationNode.cc --
 //
 // Author           : Rodolfo G. Esteves
 // Created On       : Sat May 16 12:34:05 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Apr 13 16:53:17 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Thu Apr 14 15:38:09 2016
 // Update Count     : 161
 //
@@ -97,4 +97,6 @@
 		os << endl << string( indent + 2, ' ' ) << "with initializer ";
 		initializer->printOneLine( os );
+		os << " maybe constructed? " << initializer->get_maybeConstructed();
+
 	} // if
 
@@ -353,5 +355,5 @@
 	} // if
 }
-	  
+
 DeclarationNode *DeclarationNode::addQualifiers( DeclarationNode *q ) {
 	if ( q ) {
@@ -504,5 +506,5 @@
 		assert( false );
 	} // switch
-	
+
 	return this;
 }
@@ -615,5 +617,5 @@
 		assert( a->type->kind == TypeData::Array );
 		TypeData *lastArray = findLast( a->type );
-		if ( type ) {  
+		if ( type ) {
 			switch ( type->kind ) {
 			  case TypeData::Aggregate:
@@ -659,5 +661,5 @@
 	} // if
 }
-	
+
 DeclarationNode *DeclarationNode::addIdList( DeclarationNode *ids ) {
 	type = addIdListToType( type, ids );
@@ -864,5 +866,5 @@
 Type *DeclarationNode::buildType() const {
 	assert( type );
-  
+
 	switch ( type->kind ) {
 	  case TypeData::Enum:
Index: src/Parser/InitializerNode.cc
===================================================================
--- src/Parser/InitializerNode.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/Parser/InitializerNode.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,12 +5,12 @@
 // file "LICENCE" distributed with Cforall.
 //
-// InitializerNode.cc -- 
-// 
+// InitializerNode.cc --
+//
 // Author           : Rodolfo G. Esteves
 // Created On       : Sat May 16 13:20:24 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Oct  8 17:18:55 2015
-// Update Count     : 4
-// 
+// Last Modified By : Rob Schluntz
+// Last Modified On : Thu Jan 07 13:32:57 2016
+// Update Count     : 13
+//
 
 #include <cassert>
@@ -23,5 +23,5 @@
 
 InitializerNode::InitializerNode( ExpressionNode *_expr, bool aggrp, ExpressionNode *des )
-	: expr( _expr ), aggregate( aggrp ), designator( des ), kids( 0 ) {
+	: expr( _expr ), aggregate( aggrp ), designator( des ), kids( 0 ), maybeConstructed( true ) {
 	if ( aggrp )
 		kids = dynamic_cast< InitializerNode *>( get_link() );
@@ -32,5 +32,5 @@
 
 InitializerNode::InitializerNode( InitializerNode *init, bool aggrp, ExpressionNode *des )
-	: expr( 0 ), aggregate( aggrp ), designator( des ), kids( 0 ) {
+	: expr( 0 ), aggregate( aggrp ), designator( des ), kids( 0 ), maybeConstructed( true ) {
 	if ( init != 0 )
 		set_link(init);
@@ -91,5 +91,5 @@
 		} // if
 
-		return new ListInit( initlist, designlist );
+		return new ListInit( initlist, designlist, maybeConstructed );
 	} else {
 		std::list< Expression *> designators;
@@ -99,5 +99,5 @@
 
 		if ( get_expression() != 0)
-			return new SingleInit( get_expression()->build(), designators );
+			return new SingleInit( get_expression()->build(), designators, maybeConstructed );
 	} // if
 
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/Parser/ParseNode.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,5 +10,5 @@
 // Created On       : Sat May 16 13:28:16 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Mon Apr 11 11:50:52 2016
+// Last Modified On : Thu Apr 14 15:37:52 2016
 // Update Count     : 205
 //
@@ -185,4 +185,5 @@
 				// monadic
 				UnPlus, UnMinus, AddressOf, PointTo, Neg, BitNeg, Incr, IncrPost, Decr, DecrPost, LabelAddress,
+				Ctor, Dtor,
 	};
 
@@ -525,4 +526,7 @@
 	ExpressionNode *get_designators() const { return designator; }
 
+	InitializerNode *set_maybeConstructed( bool value ) { maybeConstructed = value; return this; }
+	bool get_maybeConstructed() const { return maybeConstructed; }
+
 	InitializerNode *next_init() const { return kids; }
 
@@ -536,4 +540,5 @@
 	ExpressionNode *designator; // may be list
 	InitializerNode *kids;
+	bool maybeConstructed;
 };
 
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/Parser/TypeData.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// TypeData.cc -- 
+// TypeData.cc --
 //
 // Author           : Rodolfo G. Esteves
 // Created On       : Sat May 16 15:12:51 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 17:26:45 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Apr 06 16:57:53 2016
 // Update Count     : 49
 //
@@ -449,4 +449,22 @@
 	for ( std::list< TypeDecl* >::iterator i = outputList.begin(); i != outputList.end(); ++i ) {
 		if ( (*i)->get_kind() == TypeDecl::Any ) {
+			// add assertion parameters to `type' tyvars in reverse order
+			// 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 ) );
+			(*i)->get_assertions().push_front( new FunctionDecl( "^?{}", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, dtorType, 0, false, false ) );
+
+			// 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 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 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 ) );
@@ -902,5 +920,5 @@
 		if ( cur->get_enumeratorValue() != NULL ) {
 			ObjectDecl *member = dynamic_cast<ObjectDecl *>(*members);
-			member->set_init( new SingleInit( maybeBuild< Expression >( cur->get_enumeratorValue() ) ) );
+			member->set_init( new SingleInit( maybeBuild< Expression >( cur->get_enumeratorValue() ), std::list< Expression * >() ) );
 		} // if
 	} // for
Index: src/Parser/parser.cc
===================================================================
--- src/Parser/parser.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/Parser/parser.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -7468,5 +7468,5 @@
 /* Line 1806 of yacc.c  */
 #line 1704 "parser.yy"
-    { (yyval.in) = (yyvsp[(2) - (2)].in); }
+    { (yyval.in) = (yyvsp[(2) - (2)].in)->set_maybeConstructed( false ); }
     break;
 
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/Parser/parser.yy	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,6 +5,6 @@
 // file "LICENCE" distributed with Cforall.
 //
-// cfa.y -- 
-// 
+// cfa.y --
+//
 // Author           : Peter A. Buhr
 // Created On       : Sat Sep  1 20:22:55 2001
@@ -12,5 +12,5 @@
 // Last Modified On : Wed Apr 13 16:58:43 2016
 // Update Count     : 1519
-// 
+//
 
 // This grammar is based on the ANSI99/11 C grammar, specifically parts of EXPRESSION and STATEMENTS, and on the C
@@ -1702,5 +1702,5 @@
 		{ $$ = $2; }
 	| ATassign initializer
-		{ $$ = $2; }
+		{ $$ = $2->set_maybeConstructed( false ); }
 	;
 
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,5 +10,5 @@
 // Created On       : Sat May 16 23:52:08 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Wed Feb 10 17:00:04 2016
+// Last Modified On : Wed Apr 20 14:24:03 2016
 // Update Count     : 24
 //
@@ -982,4 +982,8 @@
 		} // for
 	}
+
+	void AlternativeFinder::visit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
+		alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
+	}
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/AlternativeFinder.h
===================================================================
--- src/ResolvExpr/AlternativeFinder.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/ResolvExpr/AlternativeFinder.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,12 +5,12 @@
 // file "LICENCE" distributed with Cforall.
 //
-// AlternativeFinder.h -- 
+// AlternativeFinder.h --
 //
 // Author           : Richard C. Bilson
 // Created On       : Sat May 16 23:56:12 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat May 16 23:58:43 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Tue Apr 19 11:44:53 2016
 // Update Count     : 2
-// 
+//
 
 #ifndef ALTERNATIVEFINDER_H
@@ -54,5 +54,5 @@
 		virtual void visit( NameExpr *variableExpr );
 		virtual void visit( VariableExpr *variableExpr );
-		virtual void visit( ConstantExpr *constantExpr ); 
+		virtual void visit( ConstantExpr *constantExpr );
 		virtual void visit( SizeofExpr *sizeofExpr );
 		virtual void visit( AlignofExpr *alignofExpr );
@@ -65,4 +65,5 @@
 		virtual void visit( CommaExpr *commaExpr );
 		virtual void visit( TupleExpr *tupleExpr );
+		virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr );
 	  public:  // xxx - temporary hack - should make Tuples::TupleAssignment a friend
 		template< typename InputIterator, typename OutputIterator >
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/ResolvExpr/Resolver.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,11 +5,11 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Resolver.cc -- 
+// Resolver.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 12:17:01 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 24 16:43:11 2016
-// Update Count     : 181
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 13 11:36:40 2016
+// Update Count     : 203
 //
 
@@ -25,4 +25,5 @@
 #include "SymTab/Indexer.h"
 #include "Common/utility.h"
+#include "InitTweak/InitTweak.h"
 
 #include <iostream>
@@ -33,5 +34,5 @@
 	  public:
 		Resolver() : SymTab::Indexer( false ), switchType( 0 ) {}
-  
+
 		virtual void visit( FunctionDecl *functionDecl );
 		virtual void visit( ObjectDecl *functionDecl );
@@ -54,4 +55,5 @@
 		virtual void visit( SingleInit *singleInit );
 		virtual void visit( ListInit *listInit );
+		virtual void visit( ConstructorInit *ctorInit );
 	  private:
   	typedef std::list< Initializer * >::iterator InitIterator;
@@ -59,5 +61,5 @@
 	  void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & );
 	  void resolveSingleAggrInit( Declaration *, InitIterator &, InitIterator & );
-
+	  void fallbackInit( ConstructorInit * ctorInit );
 		std::list< Type * > functionReturn;
 		Type *initContext;
@@ -82,4 +84,5 @@
 	}
 
+
 	namespace {
 		void finishExpr( Expression *expr, const TypeEnvironment &env ) {
@@ -87,13 +90,15 @@
 			env.makeSubstitution( *expr->get_env() );
 		}
-
-		Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
-			global_renamer.reset();
-			TypeEnvironment env;
-			Expression *newExpr = resolveInVoidContext( untyped, indexer, env );
-			finishExpr( newExpr, env );
-			return newExpr;
-		}
-  
+	} // namespace
+
+	Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
+		global_renamer.reset();
+		TypeEnvironment env;
+		Expression *newExpr = resolveInVoidContext( untyped, indexer, env );
+		finishExpr( newExpr, env );
+		return newExpr;
+	}
+
+	namespace {
 		Expression *findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
 			TypeEnvironment env;
@@ -126,5 +131,5 @@
 			} // if
 		}
-  
+
 		Expression *findIntegralExpression( Expression *untyped, const SymTab::Indexer &indexer ) {
 			TypeEnvironment env;
@@ -159,7 +164,7 @@
 			return newExpr;
 		}
-  
-	}
-  
+
+	}
+
 	void Resolver::visit( ObjectDecl *objectDecl ) {
 		Type *new_type = resolveTypeof( objectDecl->get_type(), *this );
@@ -258,5 +263,5 @@
 			forStmt->set_condition( newExpr );
 		} // if
-		
+
 		if ( forStmt->get_increment() ) {
 			Expression * newExpr = findVoidExpression( forStmt->get_increment(), *this );
@@ -272,5 +277,5 @@
 		delete switchStmt->get_condition();
 		switchStmt->set_condition( newExpr );
-  
+
 		visitor.Visitor::visit( switchStmt );
 	}
@@ -314,5 +319,5 @@
 	bool isCharType( T t ) {
 		if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) {
-			return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar || 
+			return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar ||
 				bt->get_kind() == BasicType::UnsignedChar;
 		}
@@ -326,5 +331,5 @@
 				string n = ne->get_name();
 				if (n == "0") {
-					initContext = new BasicType(Type::Qualifiers(), 
+					initContext = new BasicType(Type::Qualifiers(),
 												BasicType::SignedInt);
 				} else {
@@ -332,5 +337,5 @@
 					initContext = decl->get_type();
 				}
-			} else if (ConstantExpr * e = 
+			} else if (ConstantExpr * e =
 					   dynamic_cast<ConstantExpr*>(singleInit->get_value())) {
 				Constant *c = e->get_constant();
@@ -355,5 +360,5 @@
 							singleInit->set_value( ce->get_arg() );
 							ce->set_arg( NULL );
-							delete ce;									
+							delete ce;
 						}
 					}
@@ -471,4 +476,41 @@
 #endif
 	}
+
+	// ConstructorInit - fall back on C-style initializer
+	void Resolver::fallbackInit( ConstructorInit * ctorInit ) {
+		// could not find valid constructor, or found an intrinsic constructor
+		// fall back on C-style initializer
+		delete ctorInit->get_ctor();
+		ctorInit->set_ctor( NULL );
+		maybeAccept( ctorInit->get_init(), *this );
+	}
+
+	void Resolver::visit( ConstructorInit *ctorInit ) {
+		try {
+			maybeAccept( ctorInit->get_ctor(), *this );
+			maybeAccept( ctorInit->get_dtor(), *this );
+		} 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 );
+			return;
+		}
+
+		// found a constructor - can get rid of C-style initializer
+		delete ctorInit->get_init();
+		ctorInit->set_init( NULL );
+
+		// intrinsic single parameter constructors and destructors do nothing. Since this was
+		// implicitly generated, there's no way for it to have side effects, so get rid of it
+		// to clean up generated code.
+		if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
+			delete ctorInit->get_ctor();
+			ctorInit->set_ctor( NULL );
+		}
+		if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
+			delete ctorInit->get_dtor();
+			ctorInit->set_dtor( NULL );
+		}
+	}
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/Resolver.h
===================================================================
--- src/ResolvExpr/Resolver.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/ResolvExpr/Resolver.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Resolver.h -- 
+// Resolver.h --
 //
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 12:18:34 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sun May 17 12:19:32 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Thu Apr 14 15:06:53 2016
 // Update Count     : 2
 //
@@ -24,4 +24,5 @@
 	void resolve( std::list< Declaration * > translationUnit );
 	Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer );
+	Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer );
 } // namespace ResolvExpr
 
Index: src/SymTab/AddVisit.h
===================================================================
--- src/SymTab/AddVisit.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SymTab/AddVisit.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// AddVisit.h -- 
+// AddVisit.h --
 //
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 16:14:32 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Apr  7 14:42:21 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Thu Apr 14 15:52:42 2016
 // Update Count     : 5
 //
@@ -48,4 +48,19 @@
 	// 	maybeAccept( caseStmt->get_condition(), visitor );
 	// }
+
+	template< typename Visitor >
+	void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor, bool addBefore ) {
+		std::list< Declaration * >::iterator i = translationUnit.begin();
+		while ( i != translationUnit.end() ) {
+			(*i)->accept( visitor );
+			std::list< Declaration * >::iterator next = i;
+			next++;
+			if ( ! visitor.get_declsToAdd().empty() ) {
+				translationUnit.splice( addBefore ? i : next, visitor.get_declsToAdd() );
+			} // if
+			i = next;
+		} // while
+	}
+
 } // namespace SymTab
 
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
+++ src/SymTab/Autogen.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -0,0 +1,518 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Autogen.cc --
+//
+// Author           : Rob Schluntz
+// Created On       : Thu Mar 03 15:45:56 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed May 11 13:22:03 2016
+// Update Count     : 1
+//
+
+#include <list>
+#include <iterator>
+#include "SynTree/Visitor.h"
+#include "SynTree/Type.h"
+#include "SynTree/Statement.h"
+#include "SynTree/TypeSubstitution.h"
+#include "Common/utility.h"
+#include "AddVisit.h"
+#include "MakeLibCfa.h"
+#include "Autogen.h"
+
+namespace SymTab {
+	class AutogenerateRoutines : public Visitor {
+		public:
+		std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
+
+		virtual void visit( EnumDecl *enumDecl );
+		virtual void visit( StructDecl *structDecl );
+		virtual void visit( UnionDecl *structDecl );
+		virtual void visit( TypeDecl *typeDecl );
+		virtual void visit( TraitDecl *ctxDecl );
+		virtual void visit( FunctionDecl *functionDecl );
+
+		virtual void visit( FunctionType *ftype );
+		virtual void visit( PointerType *ftype );
+
+		virtual void visit( CompoundStmt *compoundStmt );
+		virtual void visit( SwitchStmt *switchStmt );
+		virtual void visit( ChooseStmt *chooseStmt );
+		// virtual void visit( CaseStmt *caseStmt );
+
+		AutogenerateRoutines() : functionNesting( 0 ) {}
+		private:
+		template< typename StmtClass > void visitStatement( StmtClass *stmt );
+
+		std::list< Declaration * > declsToAdd;
+		std::set< std::string > structsDone;
+		unsigned int functionNesting;     // current level of nested functions
+	};
+
+	void autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
+		AutogenerateRoutines visitor;
+		acceptAndAdd( translationUnit, visitor, false );
+	}
+
+	bool isUnnamedBitfield( ObjectDecl * obj ) {
+		return obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL;
+	}
+
+	template< typename OutputIterator >
+	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
+		if ( isUnnamedBitfield( obj ) ) return;
+
+		// 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( "*?" ) );
+		derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
+
+		// do something special for unnamed members
+		Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
+		fExpr->get_args().push_back( dstselect );
+
+		if ( src ) {
+			fExpr->get_args().push_back( src );
+		}
+
+		*out++ = new ExprStmt( noLabels, fExpr );
+	}
+
+	template< typename OutputIterator >
+	void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, UnionInstType *unionType, OutputIterator out ) {
+		UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
+		copy->get_args().push_back( new VariableExpr( dstParam ) );
+		copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
+		copy->get_args().push_back( new SizeofExpr( unionType ) );
+
+		*out++ = new ExprStmt( noLabels, copy );
+	}
+
+	//E ?=?(E volatile*, int),
+	//  ?=?(E _Atomic volatile*, int);
+	void makeEnumFunctions( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
+		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
+
+		ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
+		assignType->get_returnVals().push_back( returnVal );
+
+		// need two assignment operators with different types
+		FunctionType * assignType2 = assignType->clone();
+
+		// E ?=?(E volatile *, E)
+		Type *etype = refType->clone();
+		// etype->get_qualifiers() += Type::Qualifiers(false, true, false, false, false, false);
+
+		ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), etype ), 0 );
+		assignType->get_parameters().push_back( dstParam );
+
+		ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, etype->clone(), 0 );
+		assignType->get_parameters().push_back( srcParam );
+
+		// E ?=?(E volatile *, int)
+		assignType2->get_parameters().push_back( dstParam->clone() );
+		BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt);
+		ObjectDecl *srcParam2 = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, paramType, 0 );
+		assignType2->get_parameters().push_back( srcParam2 );
+
+		// 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.
+
+		// since there is no definition, these should not be inline
+		// make these intrinsic so that the code generator does not make use of them
+		FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, 0, false, false );
+		assignDecl->fixUniqueId();
+		FunctionDecl *assignDecl2 = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType2, 0, false, false );
+		assignDecl2->fixUniqueId();
+
+		// these should be built in the same way that the prelude
+		// functions are, so build a list containing the prototypes
+		// and allow MakeLibCfa to autogenerate the bodies.
+		std::list< Declaration * > assigns;
+		assigns.push_back( assignDecl );
+		assigns.push_back( assignDecl2 );
+
+		LibCfa::makeLibCfa( assigns );
+
+		// need to remove the prototypes, since this may be nested in a routine
+		for (int start = 0, end = assigns.size()/2; start < end; start++) {
+			delete assigns.front();
+			assigns.pop_front();
+		} // for
+
+		declsToAdd.insert( declsToAdd.begin(), assigns.begin(), assigns.end() );
+	}
+
+	/// Clones a reference type, replacing any parameters it may have with a clone of the provided list
+	template< typename GenericInstType >
+	GenericInstType *cloneWithParams( GenericInstType *refType, const std::list< Expression* >& params ) {
+		GenericInstType *clone = refType->clone();
+		clone->get_parameters().clear();
+		cloneAll( params, clone->get_parameters() );
+		return clone;
+	}
+
+	/// Creates a new type decl that's the same as src, but renamed and with only the ?=?, ?{} (default and copy), and ^?{} assertions (for complete types only)
+	TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) {
+		TypeDecl *dst = new TypeDecl( src->get_name(), src->get_storageClass(), 0, src->get_kind() );
+		cloneAll(src->get_assertions(), dst->get_assertions());
+		return dst;
+	}
+
+	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 );
+
+			if ( src ) {
+				genericSubs.apply( src );
+			}
+		}
+
+		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 *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 = field->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 ( field->get_name() == "" ) {
+					// don't assign to anonymous members
+					// xxx - this is a temporary fix. Anonymous members tie into
+					// our inheritance model. I think the correct way to handle this is to
+					// cast the structure to the type of the member and let the resolver
+					// figure out whether it's valid and have a pass afterwards that fixes
+					// the assignment to use pointer arithmetic with the offset of the
+					// member, much like how generic type members are handled.
+					continue;
+				}
+
+				assert( ! func->get_functionType()->get_parameters().empty() );
+				ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().front() );
+				ObjectDecl * srcParam = NULL;
+				if ( func->get_functionType()->get_parameters().size() == 2 ) {
+					srcParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().back() );
+				}
+				// srcParam may be NULL, in which case we have default ctor/dtor
+				assert( dstParam );
+
+				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
+					Expression *srcselect = new VariableExpr(*parameter);
+					makeStructMemberOp( dstParam, srcselect, field, func, genericSubs, isGeneric );
+					++parameter;
+				} else {
+					// 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 ) {
+		FunctionType *assignType = 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
+		TypeSubstitution genericSubs; // Substitutions to make to member types of struct
+		for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
+			isGeneric = true;
+			TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
+			assignType->get_forall().push_back( typeParam );
+			TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam );
+			genericSubs.add( (*param)->get_name(), newParamType );
+			structParams.push_back( new TypeExpr( newParamType ) );
+		}
+
+		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 );
+
+		// 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();
+		ctorDecl->fixUniqueId();
+		copyCtorDecl->fixUniqueId();
+		dtorDecl->fixUniqueId();
+
+		// create constructors which take each member type as a parameter.
+		// for example, for struct A { int x, y; }; generate
+		// void ?{}(A *, int) and void ?{}(A *, int, int)
+		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 );
+			if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( member ) ) ) {
+				// don't make a function whose parameter is an unnamed bitfield
+				continue;
+			} else if ( member->get_name() == "" ) {
+				// don't assign to anonymous members
+				// xxx - this is a temporary fix. Anonymous members tie into
+				// our inheritance model. I think the correct way to handle this is to
+				// cast the structure to the type of the member and let the resolver
+				// figure out whether it's valid and have a pass afterwards that fixes
+				// the assignment to use pointer arithmetic with the offset of the
+				// member, much like how generic type members are handled.
+				continue;
+			}
+			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 );
+		makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), ctorDecl, genericSubs, isGeneric );
+		makeStructFunctionBody( aggregateDecl->get_members().begin(), aggregateDecl->get_members().end(), copyCtorDecl, genericSubs, isGeneric );
+		// needs to do everything in reverse, so pass "forward" as false
+		makeStructFunctionBody( aggregateDecl->get_members().rbegin(), aggregateDecl->get_members().rend(), dtorDecl, genericSubs, isGeneric, false );
+
+		if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
+
+		declsToAdd.push_back( assignDecl );
+		declsToAdd.push_back( ctorDecl );
+		declsToAdd.push_back( copyCtorDecl );
+		declsToAdd.push_back( dtorDecl );
+		declsToAdd.splice( declsToAdd.end(), memCtors );
+	}
+
+	void makeUnionFunctions( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd ) {
+		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
+
+		// Make function polymorphic in same parameters as generic union, if applicable
+		bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
+		std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
+		std::list< Expression* > unionParams;  // 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 = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
+			assignType->get_forall().push_back( typeParam );
+			unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
+		}
+
+		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 );
+
+		// 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() ) );
+		if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
+
+		if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
+
+		// 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 );
+	}
+
+	void AutogenerateRoutines::visit( EnumDecl *enumDecl ) {
+		if ( ! enumDecl->get_members().empty() ) {
+			EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
+			// enumInst->set_baseEnum( enumDecl );
+			// declsToAdd.push_back(
+			makeEnumFunctions( enumDecl, enumInst, functionNesting, declsToAdd );
+		}
+	}
+
+	void AutogenerateRoutines::visit( StructDecl *structDecl ) {
+		if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
+			StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
+			structInst.set_baseStruct( structDecl );
+			makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd );
+			structsDone.insert( structDecl->get_name() );
+		} // if
+	}
+
+	void AutogenerateRoutines::visit( UnionDecl *unionDecl ) {
+		if ( ! unionDecl->get_members().empty() ) {
+			UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
+			unionInst.set_baseUnion( unionDecl );
+			makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAdd );
+		} // if
+	}
+
+	void AutogenerateRoutines::visit( TypeDecl *typeDecl ) {
+		CompoundStmt *stmts = 0;
+		TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false );
+		typeInst->set_baseType( typeDecl );
+		ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 );
+		ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 );
+		if ( typeDecl->get_base() ) {
+			stmts = new CompoundStmt( std::list< Label >() );
+			UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
+			assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) );
+			assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) );
+			stmts->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) );
+		} // if
+		FunctionType *type = new FunctionType( Type::Qualifiers(), false );
+		type->get_returnVals().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst, 0 ) );
+		type->get_parameters().push_back( dst );
+		type->get_parameters().push_back( src );
+		FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, false, false );
+		declsToAdd.push_back( func );
+	}
+
+	void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) {
+		for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) {
+			statements.insert( i, new DeclStmt( noLabels, *decl ) );
+		} // for
+		declsToAdd.clear();
+	}
+
+	void AutogenerateRoutines::visit( FunctionType *) {
+		// ensure that we don't add assignment ops for types defined as part of the function
+	}
+
+	void AutogenerateRoutines::visit( PointerType *) {
+		// ensure that we don't add assignment ops for types defined as part of the pointer
+	}
+
+	void AutogenerateRoutines::visit( TraitDecl *) {
+		// ensure that we don't add assignment ops for types defined as part of the trait
+	}
+
+	template< typename StmtClass >
+	inline void AutogenerateRoutines::visitStatement( StmtClass *stmt ) {
+		std::set< std::string > oldStructs = structsDone;
+		addVisit( stmt, *this );
+		structsDone = oldStructs;
+	}
+
+	void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) {
+		maybeAccept( functionDecl->get_functionType(), *this );
+		acceptAll( functionDecl->get_oldDecls(), *this );
+		functionNesting += 1;
+		maybeAccept( functionDecl->get_statements(), *this );
+		functionNesting -= 1;
+	}
+
+	void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) {
+		visitStatement( compoundStmt );
+	}
+
+	void AutogenerateRoutines::visit( SwitchStmt *switchStmt ) {
+		visitStatement( switchStmt );
+	}
+
+	void AutogenerateRoutines::visit( ChooseStmt *switchStmt ) {
+		visitStatement( switchStmt );
+	}
+
+	// void AutogenerateRoutines::visit( CaseStmt *caseStmt ) {
+	// 	visitStatement( caseStmt );
+	// }
+} // SymTab
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
+++ src/SymTab/Autogen.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -0,0 +1,99 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Autogen.h --
+//
+// Author           : Rob Schluntz
+// Created On       : Sun May 17 21:53:34 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Tue May 19 16:49:43 2015
+// Update Count     : 1
+//
+
+#ifndef AUTOGEN_H
+#define AUTOGEN_H
+
+#include <string>
+#include "SynTree/Statement.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Initializer.h"
+
+namespace SymTab {
+  static const std::list< std::string > noLabels;
+
+  /// Generates assignment operators, constructors, and destructor for aggregate types as required
+  void autogenerateRoutines( std::list< Declaration * > &translationUnit );
+
+  // originally makeArrayAssignment - changed to Function because it is now used for ctors and dtors as well
+  // admittedly not a great name change. This used to live in Validate.cc, but has been moved so it can be reused elsewhere
+
+  /// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
+  /// If forward is true, loop goes from 0 to N-1, else N-1 to 0
+  template< typename OutputIterator >
+  void makeArrayFunction( Expression *srcParam, Expression *dstParam, ArrayType *array, std::string fname, OutputIterator out, bool forward = true ) {
+    static UniqueName indexName( "_index" );
+
+    // for a flexible array member nothing is done -- user must define own assignment
+    if ( ! array->get_dimension() ) return;
+
+    Expression * begin, * end, * update, * cmp;
+    if ( forward ) {
+      // generate: for ( int i = 0; i < 0; ++i )
+      begin = new NameExpr( "0" );
+      end = array->get_dimension()->clone();
+      cmp = new NameExpr( "?<?" );
+      update = new NameExpr( "++?" );
+    } else {
+      // generate: for ( int i = N-1; i >= 0; --i )
+      begin = new UntypedExpr( new NameExpr( "?-?" ) );
+      ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
+      ((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) );
+      end = new NameExpr( "0" );
+      cmp = new NameExpr( "?>=?" );
+      update = new NameExpr( "--?" );
+    }
+
+    ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
+
+    UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
+    init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
+    init->get_args().push_back( begin );
+    index->set_init( new SingleInit( init, std::list<Expression*>() ) );
+
+    UntypedExpr *cond = new UntypedExpr( cmp );
+    cond->get_args().push_back( new VariableExpr( index ) );
+    cond->get_args().push_back( end );
+
+    UntypedExpr *inc = new UntypedExpr( update );
+    inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
+
+    // want to be able to generate assignment, ctor, and dtor generically,
+    // so fname is either ?=?, ?{}, or ^?{}
+    UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
+
+    UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) );
+    dstIndex->get_args().push_back( dstParam );
+    dstIndex->get_args().push_back( new VariableExpr( index ) );
+    fExpr->get_args().push_back( dstIndex );
+
+    // srcParam is NULL for default ctor/dtor
+    if ( srcParam ) {
+      UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
+      srcIndex->get_args().push_back( srcParam );
+      srcIndex->get_args().push_back( new VariableExpr( index ) );
+      fExpr->get_args().push_back( srcIndex );
+    }
+
+    std::list<Statement *> initList;
+    CompoundStmt * block = new CompoundStmt( noLabels );
+    block->get_kids().push_back( new DeclStmt( noLabels, index ) );
+    block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, fExpr ) ) );
+    *out++ = block;
+  }
+} // namespace SymTab
+#endif // AUTOGEN_H
+
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SymTab/Validate.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 21:50:04 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Apr 13 16:39:30 2016
-// Update Count     : 251
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed May 11 13:17:52 2016
+// Update Count     : 297
 //
 
@@ -56,4 +56,5 @@
 #include "MakeLibCfa.h"
 #include "TypeEquality.h"
+#include "Autogen.h"
 #include "ResolvExpr/typeops.h"
 
@@ -122,35 +123,4 @@
 
 		const Indexer *indexer;
-	};
-
-	class AutogenerateRoutines : public Visitor {
-	  public:
-		/// Generates assignment operators for aggregate types as required
-		static void autogenerateRoutines( std::list< Declaration * > &translationUnit );
-
-		std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
-
-		virtual void visit( EnumDecl *enumDecl );
-		virtual void visit( StructDecl *structDecl );
-		virtual void visit( UnionDecl *structDecl );
-		virtual void visit( TypeDecl *typeDecl );
-		virtual void visit( TraitDecl *ctxDecl );
-		virtual void visit( FunctionDecl *functionDecl );
-
-		virtual void visit( FunctionType *ftype );
-		virtual void visit( PointerType *ftype );
-
-		virtual void visit( CompoundStmt *compoundStmt );
-		virtual void visit( SwitchStmt *switchStmt );
-		virtual void visit( ChooseStmt *chooseStmt );
-		// virtual void visit( CaseStmt *caseStmt );
-
-		AutogenerateRoutines() : functionNesting( 0 ) {}
-	  private:
-		template< typename StmtClass > void visitStatement( StmtClass *stmt );
-
-		std::list< Declaration * > declsToAdd;
-		std::set< std::string > structsDone;
-		unsigned int functionNesting;			// current level of nested functions
 	};
 
@@ -192,9 +162,19 @@
 		template<typename AggDecl>
 		void addImplicitTypedef( AggDecl * aggDecl );
-		
+
 		typedef std::map< std::string, std::pair< TypedefDecl *, int > > TypedefMap;
 		TypedefMap typedefNames;
 		int scopeLevel;
 	};
+
+	class VerifyCtorDtor : public Visitor {
+	public:
+		/// ensure that constructors and destructors have at least one
+		/// parameter, the first of which must be a pointer, and no
+		/// return values.
+		static void verify( std::list< Declaration * > &translationUnit );
+
+		virtual void visit( FunctionDecl *funcDecl );
+};
 
 	class CompoundLiteral : public GenPoly::DeclMutator {
@@ -217,6 +197,7 @@
 		ReturnChecker::checkFunctionReturns( translationUnit );
 		mutateAll( translationUnit, compoundliteral );
-		AutogenerateRoutines::autogenerateRoutines( translationUnit );
+		autogenerateRoutines( translationUnit );
 		acceptAll( translationUnit, pass3 );
+		VerifyCtorDtor::verify( translationUnit );
 	}
 
@@ -228,18 +209,4 @@
 		type->accept( pass2 );
 		type->accept( pass3 );
-	}
-
-	template< typename Visitor >
-	void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor, bool addBefore ) {
-		std::list< Declaration * >::iterator i = translationUnit.begin();
-		while ( i != translationUnit.end() ) {
-			(*i)->accept( visitor );
-			std::list< Declaration * >::iterator next = i;
-			next++;
-			if ( ! visitor.get_declsToAdd().empty() ) {
-				translationUnit.splice( addBefore ? i : next, visitor.get_declsToAdd() );
-			} // if
-			i = next;
-		} // while
 	}
 
@@ -503,377 +470,4 @@
 	}
 
-	static const std::list< std::string > noLabels;
-
-	void AutogenerateRoutines::autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
-		AutogenerateRoutines visitor;
-		acceptAndAdd( translationUnit, visitor, false );
-	}
-
-	template< typename OutputIterator >
-	void makeScalarAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, 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( "?=?" ) );
-
-		UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
-		derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
-
-		// do something special for unnamed members
-		Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
-		assignExpr->get_args().push_back( dstselect );
-
-		Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
-		assignExpr->get_args().push_back( srcselect );
-
-		*out++ = new ExprStmt( noLabels, assignExpr );
-	}
-
-	template< typename OutputIterator >
-	void makeArrayAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, OutputIterator out ) {
-		static UniqueName indexName( "_index" );
-
-		// for a flexible array member nothing is done -- user must define own assignment
-		if ( ! array->get_dimension() ) return;
-
-		ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 0 );
-		*out++ = new DeclStmt( noLabels, index );
-
-		UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
-		init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
-		init->get_args().push_back( new NameExpr( "0" ) );
-		Statement *initStmt = new ExprStmt( noLabels, init );
-		std::list<Statement *> initList;
-		initList.push_back( initStmt );
-
-		UntypedExpr *cond = new UntypedExpr( new NameExpr( "?<?" ) );
-		cond->get_args().push_back( new VariableExpr( index ) );
-		cond->get_args().push_back( array->get_dimension()->clone() );
-
-		UntypedExpr *inc = new UntypedExpr( new NameExpr( "++?" ) );
-		inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
-
-		UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
-
-		UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
-		derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
-
-		Expression *dstselect = new MemberExpr( member, derefExpr );
-		UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) );
-		dstIndex->get_args().push_back( dstselect );
-		dstIndex->get_args().push_back( new VariableExpr( index ) );
-		assignExpr->get_args().push_back( dstIndex );
-
-		Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
-		UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
-		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 ) );
-	}
-
-	template< typename OutputIterator >
-	void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, UnionInstType *unionType, OutputIterator out ) {
-		UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
-		copy->get_args().push_back( new VariableExpr( dstParam ) );
-		copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
-		copy->get_args().push_back( new SizeofExpr( unionType ) );
-
-		*out++ = new ExprStmt( noLabels, copy );
-	}
-
-	//E ?=?(E volatile*, int),
-	//  ?=?(E _Atomic volatile*, int);
-	void makeEnumAssignment( EnumDecl *enumDecl, EnumInstType *refType, unsigned int functionNesting, std::list< Declaration * > &declsToAdd ) {
-		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
-
-		ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
-		assignType->get_returnVals().push_back( returnVal );
-
-		// need two assignment operators with different types
-		FunctionType * assignType2 = assignType->clone();
-
-		// E ?=?(E volatile *, E)
-		Type *etype = refType->clone();
-		// etype->get_qualifiers() += Type::Qualifiers(false, true, false, false, false, false);
-
-		ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), etype ), 0 );
-		assignType->get_parameters().push_back( dstParam );
-
-		ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, etype->clone(), 0 );
-		assignType->get_parameters().push_back( srcParam );
-
-		// E ?=?(E volatile *, int)
-		assignType2->get_parameters().push_back( dstParam->clone() );
-		BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt);
-		ObjectDecl *srcParam2 = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, paramType, 0 );
-		assignType2->get_parameters().push_back( srcParam2 );
-
-		// 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.
-
-		// since there is no definition, these should not be inline
-		// make these intrinsic so that the code generator does not make use of them
-		FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, 0, false, false );
-		assignDecl->fixUniqueId();
-		FunctionDecl *assignDecl2 = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType2, 0, false, false );
-		assignDecl2->fixUniqueId();
-
-		// these should be built in the same way that the prelude
-		// functions are, so build a list containing the prototypes
-		// and allow MakeLibCfa to autogenerate the bodies.
-		std::list< Declaration * > assigns;
-		assigns.push_back( assignDecl );
-		assigns.push_back( assignDecl2 );
-
-		LibCfa::makeLibCfa( assigns );
-
-		// need to remove the prototypes, since this may be nested in a routine
-		for (int start = 0, end = assigns.size()/2; start < end; start++) {
-			delete assigns.front();
-			assigns.pop_front();
-		} // for
-
-		declsToAdd.insert( declsToAdd.begin(), assigns.begin(), assigns.end() );
-	}
-
-	/// Clones a reference type, replacing any parameters it may have with a clone of the provided list
-	template< typename GenericInstType >
-	GenericInstType *cloneWithParams( GenericInstType *refType, const std::list< Expression* >& params ) {
-		GenericInstType *clone = refType->clone();
-		clone->get_parameters().clear();
-		cloneAll( params, clone->get_parameters() );
-		return clone;
-	}
-
-	/// Creates a new type decl that's the same as src, but renamed and with only the ?=? assertion (for complete types only)
-	TypeDecl *cloneAndRename( TypeDecl *src, const std::string &name ) {
-		TypeDecl *dst = new TypeDecl( name, src->get_storageClass(), 0, src->get_kind() );
-
-		if ( src->get_kind() == TypeDecl::Any ) {
-			// just include assignment operator assertion
-			TypeInstType *assignParamType = new TypeInstType( Type::Qualifiers(), name, dst );
-			FunctionType *assignFunctionType = new FunctionType( Type::Qualifiers(), false );
-			assignFunctionType->get_returnVals().push_back(
-				new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType->clone(), 0 ) );
-			assignFunctionType->get_parameters().push_back(
-				new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), assignParamType->clone() ), 0 ) );
-			assignFunctionType->get_parameters().push_back(
-				new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, assignParamType, 0 ) );
-			FunctionDecl *assignAssert = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, assignFunctionType, 0, false, false );
-			dst->get_assertions().push_back( assignAssert );
-		}
-
-		return dst;
-	}
-
-	Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
-		FunctionType *assignType = 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
-		TypeSubstitution genericSubs; // Substitutions to make to member types of struct
-		for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
-			isGeneric = true;
-			TypeDecl *typeParam = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
-			assignType->get_forall().push_back( typeParam );
-			TypeInstType *newParamType = new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam );
-			genericSubs.add( (*param)->get_name(), newParamType );
-			structParams.push_back( new TypeExpr( newParamType ) );
-		}
-
-		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 );
-		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() ) ) {
-						makeArrayAssignment( srcParam, dstParam, fixedMember, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
-						makeArrayAssignment( 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() ) );
-					} // 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() ) );
-					} else {
-						makeScalarAssignment( 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;
-	}
-
-	Declaration *makeUnionAssignment( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting ) {
-		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
-
-		// Make function polymorphic in same parameters as generic union, if applicable
-		bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
-		std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
-		std::list< Expression* > unionParams;  // 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 = cloneAndRename( *param, "_autoassign_" + aggregateDecl->get_name() + "_" + (*param)->get_name() );
-			assignType->get_forall().push_back( typeParam );
-			unionParams.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeParam->get_name(), typeParam ) ) );
-		}
-
-		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 );
-		assignDecl->fixUniqueId();
-
-		makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
-		if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
-		
-		if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
-
-		return assignDecl;
-	}
-
-	void AutogenerateRoutines::visit( EnumDecl *enumDecl ) {
-		if ( ! enumDecl->get_members().empty() ) {
-			EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
-			// enumInst->set_baseEnum( enumDecl );
-			// declsToAdd.push_back(
-			makeEnumAssignment( enumDecl, enumInst, functionNesting, declsToAdd );
-		}
-	}
-
-	void AutogenerateRoutines::visit( StructDecl *structDecl ) {
-		if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
-			StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
-			structInst.set_baseStruct( structDecl );
-			declsToAdd.push_back( makeStructAssignment( structDecl, &structInst, functionNesting ) );
-			structsDone.insert( structDecl->get_name() );
-		} // if
-	}
-
-	void AutogenerateRoutines::visit( UnionDecl *unionDecl ) {
-		if ( ! unionDecl->get_members().empty() ) {
-			UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
-			unionInst.set_baseUnion( unionDecl );
-			declsToAdd.push_back( makeUnionAssignment( unionDecl, &unionInst, functionNesting ) );
-		} // if
-	}
-
-	void AutogenerateRoutines::visit( TypeDecl *typeDecl ) {
-		CompoundStmt *stmts = 0;
-		TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false );
-		typeInst->set_baseType( typeDecl );
-		ObjectDecl *src = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 );
-		ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 );
-		if ( typeDecl->get_base() ) {
-			stmts = new CompoundStmt( std::list< Label >() );
-			UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
-			assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) );
-			assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) );
-			stmts->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) );
-		} // if
-		FunctionType *type = new FunctionType( Type::Qualifiers(), false );
-		type->get_returnVals().push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, typeInst, 0 ) );
-		type->get_parameters().push_back( dst );
-		type->get_parameters().push_back( src );
-		FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, false, false );
-		declsToAdd.push_back( func );
-	}
-
-	void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) {
-		for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) {
-			statements.insert( i, new DeclStmt( noLabels, *decl ) );
-		} // for
-		declsToAdd.clear();
-	}
-
-	void AutogenerateRoutines::visit( FunctionType *) {
-		// ensure that we don't add assignment ops for types defined as part of the function
-	}
-
-	void AutogenerateRoutines::visit( PointerType *) {
-		// ensure that we don't add assignment ops for types defined as part of the pointer
-	}
-
-	void AutogenerateRoutines::visit( TraitDecl *) {
-		// ensure that we don't add assignment ops for types defined as part of the context
-	}
-
-	template< typename StmtClass >
-	inline void AutogenerateRoutines::visitStatement( StmtClass *stmt ) {
-		std::set< std::string > oldStructs = structsDone;
-		addVisit( stmt, *this );
-		structsDone = oldStructs;
-	}
-
-	void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) {
-		maybeAccept( functionDecl->get_functionType(), *this );
-		acceptAll( functionDecl->get_oldDecls(), *this );
-		functionNesting += 1;
-		maybeAccept( functionDecl->get_statements(), *this );
-		functionNesting -= 1;
-	}
-
-	void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) {
-		visitStatement( compoundStmt );
-	}
-
-	void AutogenerateRoutines::visit( SwitchStmt *switchStmt ) {
-		visitStatement( switchStmt );
-	}
-
-	void AutogenerateRoutines::visit( ChooseStmt *switchStmt ) {
-		visitStatement( switchStmt );
-	}
-
-	// void AutogenerateRoutines::visit( CaseStmt *caseStmt ) {
-	// 	visitStatement( caseStmt );
-	// }
-
 	void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) {
 		ReturnChecker checker;
@@ -1033,5 +627,5 @@
 		return aggDecl;
 	}
-	
+
 	template<typename AggDecl>
 	void EliminateTypedef::addImplicitTypedef( AggDecl * aggDecl ) {
@@ -1072,4 +666,37 @@
 	}
 
+	void VerifyCtorDtor::verify( std::list< Declaration * > & translationUnit ) {
+		VerifyCtorDtor verifier;
+		acceptAll( translationUnit, verifier );
+	}
+
+	void VerifyCtorDtor::visit( FunctionDecl * funcDecl ) {
+		FunctionType * funcType = funcDecl->get_functionType();
+		std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals();
+		std::list< DeclarationWithType * > &params = funcType->get_parameters();
+
+		if ( funcDecl->get_name() == "?{}" || funcDecl->get_name() == "^?{}" ) {
+			if ( params.size() == 0 ) {
+				throw SemanticError( "Constructors and destructors require at least one parameter ", funcDecl );
+			}
+			if ( ! dynamic_cast< PointerType * >( params.front()->get_type() ) ) {
+				throw SemanticError( "First parameter of a constructor or destructor must be a pointer ", funcDecl );
+			}
+			if ( returnVals.size() != 0 ) {
+				throw SemanticError( "Constructors and destructors cannot have explicit return values ", funcDecl );
+			}
+		}
+
+		Visitor::visit( funcDecl );
+		// original idea: modify signature of ctor/dtors and insert appropriate return statements
+		// to cause desired behaviour
+		// new idea: add comma exprs to every ctor call to produce first parameter.
+		// this requires some memoization of the first parameter, because it can be a
+		// complicated expression with side effects (see: malloc). idea: add temporary variable
+		// that is assigned address of constructed object in ctor argument position and
+		// return the temporary. It should also be done after all implicit ctors are
+		// added, so not in this pass!
+	}
+
 	DeclarationWithType * CompoundLiteral::mutate( ObjectDecl *objectDecl ) {
 		storageclass = objectDecl->get_storageClass();
Index: src/SymTab/module.mk
===================================================================
--- src/SymTab/module.mk	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SymTab/module.mk	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -6,5 +6,5 @@
 ## file "LICENCE" distributed with Cforall.
 ##
-## module.mk -- 
+## module.mk --
 ##
 ## Author           : Richard C. Bilson
@@ -20,3 +20,4 @@
        SymTab/FixFunction.cc \
        SymTab/ImplementationType.cc \
-       SymTab/TypeEquality.cc
+       SymTab/TypeEquality.cc \
+       SymTab/Autogen.cc
Index: src/SynTree/CommaExpr.cc
===================================================================
--- src/SynTree/CommaExpr.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/CommaExpr.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,5 +10,5 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Mon May 02 15:11:29 2016
+// Last Modified On : Mon May 02 15:19:44 2016
 // Update Count     : 1
 //
Index: src/SynTree/CompoundStmt.cc
===================================================================
--- src/SynTree/CompoundStmt.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/CompoundStmt.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,5 +10,5 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Mon May 02 15:10:47 2016
+// Last Modified On : Mon May 02 15:19:17 2016
 // Update Count     : 3
 //
@@ -18,7 +18,26 @@
 #include <algorithm>
 #include <functional>
+#include "Expression.h"
+#include "Declaration.h"
 
 using std::string;
 using std::endl;
+
+class VarExprReplacer : public Visitor {
+public:
+  typedef std::map< DeclarationWithType *, DeclarationWithType * > DeclMap;
+private:
+  const DeclMap & declMap;
+public:
+  VarExprReplacer( const DeclMap & declMap ) : declMap( declMap ) {}
+
+  // replace variable with new node from decl map
+  virtual void visit( VariableExpr * varExpr ) {
+    if ( declMap.count( varExpr->get_var() ) ) {
+      varExpr->set_var( declMap.at( varExpr->get_var() ) );
+    }
+  }
+};
+
 
 CompoundStmt::CompoundStmt( std::list<Label> labels ) : Statement( labels ) {
@@ -27,4 +46,35 @@
 CompoundStmt::CompoundStmt( const CompoundStmt &other ) : Statement( other ) {
 	cloneAll( other.kids, kids );
+
+  // when cloning a compound statement, we may end up cloning declarations which
+  // are referred to by VariableExprs throughout the block. Cloning a VariableExpr
+  // does a shallow copy, so the VariableExpr will end up pointing to the original
+  // declaration. If the original declaration is deleted, e.g. because the original
+  // CompoundStmt is deleted, then we have a dangling pointer. To avoid this case,
+  // find all DeclarationWithType nodes (since a VariableExpr must point to a
+  // DeclarationWithType) in the original CompoundStmt and map them to the cloned
+  // node in the new CompoundStmt ('this'), then replace the Declarations referred to
+  // by each VariableExpr according to the constructed map. Note that only the declarations
+  // in the current level are collected into the map, because child CompoundStmts will
+  // recursively execute this routine. There may be more efficient ways of doing
+  // this.
+  VarExprReplacer::DeclMap declMap;
+  std::list< Statement * >::const_iterator origit = other.kids.begin();
+  for ( Statement * s : kids ) {
+    assert( origit != other.kids.end() );
+    if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( s ) ) {
+      DeclStmt * origDeclStmt = dynamic_cast< DeclStmt * >( *origit );
+      assert( origDeclStmt );
+      if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * > ( declStmt->get_decl() ) ) {
+        DeclarationWithType * origdwt = dynamic_cast< DeclarationWithType * > ( origDeclStmt->get_decl() );
+        assert( origdwt );
+        declMap[ origdwt ] = dwt;
+      }
+    }
+  }
+  if ( ! declMap.empty() ) {
+    VarExprReplacer replacer( declMap );
+    accept( replacer );
+  }
 }
 
Index: src/SynTree/Constant.cc
===================================================================
--- src/SynTree/Constant.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/Constant.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -30,13 +30,13 @@
 Constant::~Constant() { delete type; }
 
-Constant Constant::from( int i ) {
+Constant Constant::from_int( int i ) {
 	return Constant( new BasicType( Type::Qualifiers(), BasicType::SignedInt ), std::to_string( i ) );
 }
 
-Constant Constant::from( unsigned long i ) {
+Constant Constant::from_ulong( unsigned long i ) {
 	return Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::to_string( i ) );
 }
 
-Constant Constant::from( double d ) {
+Constant Constant::from_double( double d ) {
 	return Constant( new BasicType( Type::Qualifiers(), BasicType::Double ), std::to_string( d ) );
 }
Index: src/SynTree/Constant.h
===================================================================
--- src/SynTree/Constant.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/Constant.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -33,9 +33,9 @@
 
 	/// generates an integer constant of the given int
-	static Constant from( int i );
+	static Constant from_int( int i );
 	/// generates an integer constant of the given unsigned long int
-	static Constant from( unsigned long i );
+	static Constant from_ulong( unsigned long i );
 	/// generates a floating point constant of the given double
-	static Constant from( double d );
+	static Constant from_double( double d );
 
 	virtual Constant *clone() const;
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/Declaration.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Declaration.h -- 
+// Declaration.h --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 17:28:11 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 06 16:26:12 2016
 // Update Count     : 33
 //
@@ -22,4 +22,5 @@
 #include "Parser/LinkageSpec.h"
 #include "Parser/ParseNode.h"
+#include <string>
 
 class Declaration {
@@ -67,4 +68,9 @@
 	void set_mangleName( std::string newValue ) { mangleName = newValue; }
 
+	std::string get_scopedMangleName() const { return mangleName + "_" + std::to_string(scopeLevel); }
+
+	int get_scopeLevel() const { return scopeLevel; }
+	void set_scopeLevel( int newValue ) { scopeLevel = newValue; }
+
 	virtual DeclarationWithType *clone() const = 0;
 	virtual DeclarationWithType *acceptMutator( Mutator &m ) = 0;
@@ -75,4 +81,7 @@
 	// this represents the type with all types and typedefs expanded it is generated by SymTab::Validate::Pass2
 	std::string mangleName;
+	// need to remember the scope level at which the variable was declared, so that
+	// shadowed identifiers can be accessed
+	int scopeLevel = 0;
 };
 
@@ -106,5 +115,17 @@
 	typedef DeclarationWithType Parent;
   public:
-	FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn );
+	// temporary - merge this into general GCC attributes
+	struct Attribute {
+		enum Type {
+			NoAttribute, Constructor, Destructor,
+		} type;
+		enum Priority {
+			// priorities 0-100 are reserved by gcc, so it's okay to use 100 an exceptional case
+			Default = 100, High,
+		} priority;
+		Attribute(Type t = NoAttribute, Priority p = Default) : type(t), priority(p) {};
+	};
+
+	FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, Attribute attribute = Attribute() );
 	FunctionDecl( const FunctionDecl &other );
 	virtual ~FunctionDecl();
@@ -119,4 +140,6 @@
 	std::list< std::string >& get_oldIdents() { return oldIdents; }
 	std::list< Declaration* >& get_oldDecls() { return oldDecls; }
+	Attribute get_attribute() const { return attribute; }
+	void set_attribute( Attribute newValue ) { attribute = newValue; }
 
 	virtual FunctionDecl *clone() const { return new FunctionDecl( *this ); }
@@ -130,4 +153,5 @@
 	std::list< std::string > oldIdents;
 	std::list< Declaration* > oldDecls;
+	Attribute attribute;
 };
 
Index: src/SynTree/DeclarationWithType.cc
===================================================================
--- src/SynTree/DeclarationWithType.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/DeclarationWithType.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// DeclarationWithType.cc -- 
+// DeclarationWithType.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jun 13 08:08:07 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Mon Apr 11 15:35:27 2016
 // Update Count     : 3
 //
@@ -23,5 +23,5 @@
 
 DeclarationWithType::DeclarationWithType( const DeclarationWithType &other )
-		: Declaration( other ), mangleName( other.mangleName ) {
+		: Declaration( other ), mangleName( other.mangleName ), scopeLevel( other.scopeLevel ) {
 }
 
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/Expression.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,5 +10,5 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Fri May 13 13:19:09 2016
+// Last Modified On : Fri May 13 13:23:11 2016
 // Update Count     : 40
 //
@@ -78,4 +78,6 @@
 
 VariableExpr::VariableExpr( DeclarationWithType *_var, Expression *_aname ) : Expression( _aname ), var( _var ) {
+	assert( var );
+	assert( var->get_type() );
 	add_result( var->get_type()->clone() );
 	for ( std::list< Type* >::iterator i = get_results().begin(); i != get_results().end(); ++i ) {
@@ -464,4 +466,34 @@
 }
 
+
+ImplicitCopyCtorExpr::ImplicitCopyCtorExpr( ApplicationExpr * callExpr ) : callExpr( callExpr ) {
+	assert( callExpr );
+	cloneAll( callExpr->get_results(), results );
+}
+
+ImplicitCopyCtorExpr::ImplicitCopyCtorExpr( const ImplicitCopyCtorExpr & other ) : Expression( other ), callExpr( maybeClone( other.callExpr ) ) {
+	cloneAll( other.tempDecls, tempDecls );
+	cloneAll( other.returnDecls, returnDecls );
+	cloneAll( other.dtors, dtors );
+}
+
+ImplicitCopyCtorExpr::~ImplicitCopyCtorExpr() {
+	delete callExpr;
+	deleteAll( tempDecls );
+	deleteAll( returnDecls );
+	deleteAll( dtors );
+}
+
+void ImplicitCopyCtorExpr::print( std::ostream &os, int indent ) const {
+	os << std::string( indent, ' ' ) <<  "Implicit Copy Constructor Expression: " << std::endl;
+	assert( callExpr );
+	callExpr->print( os, indent + 2 );
+	os << std::endl << std::string( indent, ' ' ) << "with temporaries:" << std::endl;
+	printAll(tempDecls, os, indent+2);
+	os << std::endl << std::string( indent, ' ' ) << "with return temporaries:" << std::endl;
+	printAll(returnDecls, os, indent+2);
+	Expression::print( os, indent );
+}
+
 UntypedValofExpr::UntypedValofExpr( const UntypedValofExpr & other ) : Expression( other ), body ( maybeClone( other.body ) ) {}
 
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/Expression.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -9,6 +9,6 @@
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Apr  8 17:18:06 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Apr 27 17:06:49 2016
 // Update Count     : 21
 //
@@ -22,4 +22,5 @@
 #include "Mutator.h"
 #include "Constant.h"
+#include "Common/UniqueName.h"
 
 /// Expression is the root type for all expressions
@@ -559,4 +560,35 @@
 };
 
+/// ImplicitCopyCtorExpr represents the application of a function to a set of parameters,
+/// along with a set of copy constructor calls, one for each argument.
+class ImplicitCopyCtorExpr : public Expression {
+public:
+	ImplicitCopyCtorExpr( ApplicationExpr * callExpr );
+	ImplicitCopyCtorExpr( const ImplicitCopyCtorExpr & other );
+	virtual ~ImplicitCopyCtorExpr();
+
+	ApplicationExpr *get_callExpr() const { return callExpr; }
+	void set_callExpr( ApplicationExpr *newValue ) { callExpr = newValue; }
+
+	std::list< ObjectDecl * > & get_tempDecls() { return tempDecls; }
+	void set_tempDecls( std::list< ObjectDecl * > newValue ) { tempDecls = newValue; }
+
+	std::list< ObjectDecl * > & get_returnDecls() { return returnDecls; }
+	void set_returnDecls( std::list< ObjectDecl * > newValue ) { returnDecls = newValue; }
+
+	std::list< Expression * > & get_dtors() { return dtors; }
+	void set_dtors( std::list< Expression * > newValue ) { dtors = newValue; }
+
+	virtual ImplicitCopyCtorExpr *clone() const { return new ImplicitCopyCtorExpr( *this ); }
+	virtual void accept( Visitor &v ) { v.visit( this ); }
+	virtual Expression *acceptMutator( Mutator &m ) { return m.mutate( this ); }
+	virtual void print( std::ostream &os, int indent = 0 ) const;
+  private:
+	ApplicationExpr * callExpr;
+	std::list< ObjectDecl * > tempDecls;
+	std::list< ObjectDecl * > returnDecls;
+	std::list< Expression * > dtors;
+};
+
 /// ValofExpr represents a GCC 'lambda expression'
 class UntypedValofExpr : public Expression {
Index: src/SynTree/FunctionDecl.cc
===================================================================
--- src/SynTree/FunctionDecl.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/FunctionDecl.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,5 +10,5 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Tue May 03 15:37:43 2016
+// Last Modified On : Fri May 06 15:59:48 2016
 // Update Count     : 19
 //
@@ -21,6 +21,6 @@
 #include "Common/utility.h"
 
-FunctionDecl::FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn )
-		: Parent( name, sc, linkage ), type( type ), statements( statements ) {
+FunctionDecl::FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, Attribute attribute )
+		: Parent( name, sc, linkage ), type( type ), statements( statements ), attribute( attribute ) {
 	set_isInline( isInline );
 	set_isNoreturn( isNoreturn );
@@ -32,5 +32,5 @@
 
 FunctionDecl::FunctionDecl( const FunctionDecl &other )
-	: Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ) {
+	: Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ), attribute( other.attribute ) {
 }
 
@@ -65,4 +65,17 @@
 		os << "_Noreturn ";
 	} // if
+	switch ( attribute.type ) {
+		case Attribute::Constructor:
+			os << "Global Constructor ";
+			break;
+		case Attribute::Destructor:
+			os << "Global Destructor ";
+			break;
+		default:
+			break;
+	}
+	if ( attribute.priority != Attribute::Default ) {
+		os << "with priority " << attribute.priority << " ";
+	}
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
 		os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
@@ -105,4 +118,17 @@
 		os << "_Noreturn ";
 	} // if
+	switch ( attribute.type ) {
+		case Attribute::Constructor:
+			os << " Global Constructor ";
+			break;
+		case Attribute::Destructor:
+			os << " Global Destructor ";
+			break;
+		default:
+			break;
+	}
+	if ( attribute.priority != Attribute::Default ) {
+		os << "with priority " << attribute.priority << " ";
+	}
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
 		os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
Index: src/SynTree/Initializer.cc
===================================================================
--- src/SynTree/Initializer.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/Initializer.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,5 +10,5 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Fri May 13 13:19:30 2016
+// Last Modified On : Fri May 13 13:23:03 2016
 // Update Count     : 28
 //
@@ -16,7 +16,8 @@
 #include "Initializer.h"
 #include "Expression.h"
+#include "Statement.h"
 #include "Common/utility.h"
 
-Initializer::Initializer() {}
+Initializer::Initializer( bool maybeConstructed ) : maybeConstructed( maybeConstructed ) {}
 
 Initializer::~Initializer() {}
@@ -31,8 +32,8 @@
 void Initializer::print( std::ostream &os, int indent ) {}
 
-SingleInit::SingleInit( Expression *v, std::list< Expression *> &_designators ) : value ( v ), designators( _designators ) {
+SingleInit::SingleInit( Expression *v, const std::list< Expression *> &_designators, bool maybeConstructed ) : Initializer( maybeConstructed ), value ( v ), designators( _designators ) {
 }
 
-SingleInit::SingleInit( const SingleInit &other ) : value ( other.value ) {
+SingleInit::SingleInit( const SingleInit &other ) : Initializer(other), value ( maybeClone( other.value ) ) {
 	cloneAll(other.designators, designators );
 }
@@ -56,6 +57,6 @@
 }
 
-ListInit::ListInit( std::list<Initializer*> &_initializers, std::list<Expression *> &_designators )
-	: initializers( _initializers ), designators( _designators ) {
+ListInit::ListInit( const std::list<Initializer*> &_initializers, const std::list<Expression *> &_designators, bool maybeConstructed )
+	: Initializer( maybeConstructed), initializers( _initializers ), designators( _designators ) {
 }
 
@@ -81,4 +82,42 @@
 		(*i)->print( os, indent + 2 );
 }
+
+
+ConstructorInit::ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init ) : Initializer( true ), ctor( ctor ), dtor( dtor ), init( init ) {}
+ConstructorInit::~ConstructorInit() {
+	delete ctor;
+	delete init;
+}
+
+ConstructorInit *ConstructorInit::clone() const {
+	return new ConstructorInit( *this );
+}
+
+void ConstructorInit::print( std::ostream &os, int indent ) {
+	os << std::endl << std::string(indent, ' ') << "Constructor initializer: " << std::endl;
+	if ( ctor ) {
+		os << std::string(indent+2, ' ');
+		os << "initially constructed with ";
+		ctor->print( os, indent+4 );
+	} // if
+
+	if ( dtor ) {
+		os << std::string(indent+2, ' ');
+		os << "destructed with ";
+		dtor->print( os, indent+4 );
+	}
+
+	if ( init ) {
+		os << std::string(indent+2, ' ');
+		os << "with fallback C-style initializer: ";
+		init->print( os, indent+4 );
+	}
+}
+
+std::ostream & operator<<( std::ostream & out, Initializer * init ) {
+	init->print( out );
+	return out;
+}
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/SynTree/Initializer.h
===================================================================
--- src/SynTree/Initializer.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/Initializer.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,11 +5,11 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Initializer.h -- 
+// Initializer.h --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon May 18 09:03:48 2015
-// Update Count     : 1
+// Last Modified By : Rob Schluntz
+// Last Modified On : Tue Apr 12 13:49:13 2016
+// Update Count     : 19
 //
 
@@ -27,5 +27,5 @@
   public:
 	//	Initializer( std::string _name = std::string(""), int _pos = 0 );
-	Initializer( );
+	Initializer( bool maybeConstructed );
 	virtual ~Initializer();
 
@@ -43,4 +43,6 @@
 	}
 
+	bool get_maybeConstructed() { return maybeConstructed; }
+
 	virtual Initializer *clone() const = 0;
 	virtual void accept( Visitor &v ) = 0;
@@ -50,4 +52,5 @@
 	//	std::string name;
 	//	int pos;
+	bool maybeConstructed;
 };
 
@@ -55,8 +58,8 @@
 class SingleInit : public Initializer {
   public:
-	SingleInit( Expression *value, std::list< Expression *> &designators = *(new std::list<Expression *>()) );
+	SingleInit( Expression *value, const std::list< Expression *> &designators = std::list< Expression * >(), bool maybeConstructed = false );
 	SingleInit( const SingleInit &other );
 	virtual ~SingleInit();
-	
+
 	Expression *get_value() { return value; }
 	void set_value( Expression *newValue ) { value = newValue; }
@@ -79,6 +82,6 @@
 class ListInit : public Initializer {
   public:
-	ListInit( std::list<Initializer*> &, 
-			  std::list<Expression *> &designators = *(new std::list<Expression *>()) );
+	ListInit( const std::list<Initializer*> &initializers,
+			  const std::list<Expression *> &designators = std::list< Expression * >(), bool maybeConstructed = false );
 	virtual ~ListInit();
 
@@ -100,4 +103,33 @@
 };
 
+// ConstructorInit represents an initializer that is either a constructor expression or
+// a C-style initializer.
+class ConstructorInit : public Initializer {
+  public:
+	ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init );
+	virtual ~ConstructorInit();
+
+	void set_ctor( Statement * newValue ) { ctor = newValue; }
+	Statement * get_ctor() const { return ctor; }
+	void set_dtor( Statement * newValue ) { dtor = newValue; }
+	Statement * get_dtor() const { return dtor; }
+	void set_init( Initializer * newValue ) { init = newValue; }
+	Initializer * get_init() const { return init; }
+
+	virtual ConstructorInit *clone() const;
+	virtual void accept( Visitor &v ) { v.visit( this ); }
+	virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }
+	virtual void print( std::ostream &os, int indent = 0 );
+
+  private:
+	Statement * ctor;
+	Statement * dtor;
+	// C-style initializer made up of SingleInit and ListInit nodes to use as a fallback
+	// if an appropriate constructor definition is not found by the resolver
+	Initializer * init;
+};
+
+std::ostream & operator<<( std::ostream & out, Initializer * init );
+
 #endif // INITIALIZER_H
 
Index: src/SynTree/Mutator.cc
===================================================================
--- src/SynTree/Mutator.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/Mutator.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Mutator.cc -- 
+// Mutator.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Apr  1 18:05:16 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Apr 27 17:07:29 2016
 // Update Count     : 16
 //
@@ -337,4 +337,11 @@
 }
 
+Expression* Mutator::mutate( ImplicitCopyCtorExpr *impCpCtorExpr ) {
+	impCpCtorExpr->set_callExpr( maybeMutate( impCpCtorExpr->get_callExpr(), *this ) );
+	mutateAll( impCpCtorExpr->get_tempDecls(), *this );
+	mutateAll( impCpCtorExpr->get_returnDecls(), *this );
+	return impCpCtorExpr;
+}
+
 Expression *Mutator::mutate( UntypedValofExpr *valofExpr ) {
 	mutateAll( valofExpr->get_results(), *this );
@@ -450,4 +457,10 @@
 }
 
+Initializer *Mutator::mutate( ConstructorInit *ctorInit ) {
+	ctorInit->set_ctor( maybeMutate( ctorInit->get_ctor(), *this ) );
+	ctorInit->set_init( maybeMutate( ctorInit->get_init(), *this ) );
+	return ctorInit;
+}
+
 Subrange *Mutator::mutate( Subrange *subrange ) {
 	return subrange;
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/Mutator.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Mutator.h -- 
+// Mutator.h --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Apr  1 17:26:56 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Thu Apr 14 15:32:00 2016
 // Update Count     : 10
 //
@@ -62,5 +62,5 @@
 	virtual Expression* mutate( MemberExpr *memberExpr );
 	virtual Expression* mutate( VariableExpr *variableExpr );
-	virtual Expression* mutate( ConstantExpr *constantExpr ); 
+	virtual Expression* mutate( ConstantExpr *constantExpr );
 	virtual Expression* mutate( SizeofExpr *sizeofExpr );
 	virtual Expression* mutate( AlignofExpr *alignofExpr );
@@ -76,4 +76,5 @@
 	virtual Expression* mutate( TypeExpr *typeExpr );
 	virtual Expression* mutate( AsmExpr *asmExpr );
+	virtual Expression* mutate( ImplicitCopyCtorExpr *impCpCtorExpr );
 	virtual Expression* mutate( UntypedValofExpr *valofExpr );
 	virtual Expression* mutate( CompoundLiteralExpr *compLitExpr );
@@ -96,4 +97,5 @@
 	virtual Initializer* mutate( SingleInit *singleInit );
 	virtual Initializer* mutate( ListInit *listInit );
+	virtual Initializer* mutate( ConstructorInit *ctorInit );
 
 	virtual Subrange *mutate( Subrange *subrange );
Index: src/SynTree/ObjectDecl.cc
===================================================================
--- src/SynTree/ObjectDecl.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/ObjectDecl.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,5 +10,5 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Fri May 13 13:20:17 2016
+// Last Modified On : Fri May 13 13:23:32 2016
 // Update Count     : 30
 //
@@ -19,4 +19,5 @@
 #include "Expression.h"
 #include "Common/utility.h"
+#include "Statement.h"
 
 ObjectDecl::ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, bool isInline, bool isNoreturn )
@@ -58,4 +59,6 @@
 		os << " with initializer ";
 		init->print( os, indent );
+		os << std::endl << std::string(indent, ' ');
+		os << "maybeConstructed? " << init->get_maybeConstructed();
 	} // if
 
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/SynTree.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// SynTree.h -- 
+// SynTree.h --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Apr  1 16:47:44 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Thu Apr 14 15:31:36 2016
 // Update Count     : 5
 //
@@ -81,4 +81,5 @@
 class TypeExpr;
 class AsmExpr;
+class ImplicitCopyCtorExpr;
 class UntypedValofExpr;
 class CompoundLiteralExpr;
@@ -104,4 +105,5 @@
 class SingleInit;
 class ListInit;
+class ConstructorInit;
 
 class Subrange;
Index: src/SynTree/TypeSubstitution.cc
===================================================================
--- src/SynTree/TypeSubstitution.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/TypeSubstitution.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// TypeSubstitution.cc -- 
+// TypeSubstitution.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 17:29:15 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Tue Apr 26 11:15:29 2016
 // Update Count     : 3
 //
@@ -96,5 +96,5 @@
 	BoundVarsType::const_iterator bound = boundVars.find( inst->get_name() );
 	if ( bound != boundVars.end() ) return inst;
-	
+
 	TypeEnvType::const_iterator i = typeEnv.find( inst->get_name() );
 	if ( i == typeEnv.end() ) {
@@ -217,4 +217,10 @@
 }
 
+std::ostream & operator<<( std::ostream & out, const TypeSubstitution & sub ) {
+	sub.print( out );
+	return out;
+}
+
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/SynTree/TypeSubstitution.h
===================================================================
--- src/SynTree/TypeSubstitution.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/TypeSubstitution.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// TypeSubstitution.h -- 
+// TypeSubstitution.h --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 17:33:19 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri Apr 29 15:00:20 2016
 // Update Count     : 2
 //
@@ -33,10 +33,10 @@
 	TypeSubstitution( const TypeSubstitution &other );
 	virtual ~TypeSubstitution();
-	
+
 	TypeSubstitution &operator=( const TypeSubstitution &other );
-	
+
 	template< typename SynTreeClass > int apply( SynTreeClass *&input );
 	template< typename SynTreeClass > int applyFree( SynTreeClass *&input );
-	
+
 	void add( std::string formalType, Type *actualType );
 	void add( const TypeSubstitution &other );
@@ -44,11 +44,12 @@
 	Type *lookup( std::string formalType ) const;
 	bool empty() const;
-	
+
 	template< typename FormalIterator, typename ActualIterator >
 	void add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
-	
+
+	/// this function is unused...
 	template< typename TypeInstListIterator >
 	void extract( TypeInstListIterator begin, TypeInstListIterator end, TypeSubstitution &result );
-	
+
 	void normalize();
 
@@ -63,5 +64,5 @@
 	/// Records type variable bindings from forall-statements and instantiations of generic types
 	template< typename TypeClass > Type *handleAggregateType( TypeClass *type );
-	
+
 	virtual Type* mutate(VoidType *basicType);
 	virtual Type* mutate(BasicType *basicType);
@@ -75,7 +76,7 @@
 	virtual Type* mutate(TupleType *tupleType);
 	virtual Type* mutate(VarArgsType *varArgsType);
-	
+
 	// TODO: worry about traversing into a forall-qualified function type or type decl with assertions
-	
+
 	void initialize( const TypeSubstitution &src, TypeSubstitution &dest );
 
@@ -136,5 +137,5 @@
 	return subCount;
 }
-	
+
 template< typename SynTreeClass >
 int TypeSubstitution::applyFree( SynTreeClass *&input ) {
@@ -149,7 +150,8 @@
 	return subCount;
 }
-	
+
 template< typename TypeInstListIterator >
 void TypeSubstitution::extract( TypeInstListIterator begin, TypeInstListIterator end, TypeSubstitution &result ) {
+	// xxx - this function doesn't extract varEnv - is this intentional?
 	while ( begin != end ) {
 		TypeEnvType::iterator cur = typeEnv.find( (*begin++)->get_name() );
@@ -173,4 +175,6 @@
 }
 
+std::ostream & operator<<( std::ostream & out, const TypeSubstitution & sub );
+
 #endif // TYPESUBSTITUTION_H
 
Index: src/SynTree/Visitor.cc
===================================================================
--- src/SynTree/Visitor.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/Visitor.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Visitor.cc -- 
+// Visitor.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Apr  1 18:05:13 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Apr 27 17:07:40 2016
 // Update Count     : 18
 //
@@ -284,4 +284,10 @@
 }
 
+void Visitor::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
+	maybeAccept( impCpCtorExpr->get_callExpr(), *this );
+	acceptAll( impCpCtorExpr->get_tempDecls(), *this );
+	acceptAll( impCpCtorExpr->get_returnDecls(), *this );
+}
+
 void Visitor::visit( UntypedValofExpr *valofExpr ) {
 	acceptAll( valofExpr->get_results(), *this );
@@ -379,4 +385,9 @@
 }
 
+void Visitor::visit( ConstructorInit *ctorInit ) {
+	maybeAccept( ctorInit->get_ctor(), *this );
+	maybeAccept( ctorInit->get_init(), *this );
+}
+
 void Visitor::visit( Subrange *subrange ) {}
 
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/SynTree/Visitor.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Visitor.h -- 
+// Visitor.h --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Apr  1 17:26:55 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Thu Apr 14 15:30:58 2016
 // Update Count     : 7
 //
@@ -62,5 +62,5 @@
 	virtual void visit( MemberExpr *memberExpr );
 	virtual void visit( VariableExpr *variableExpr );
-	virtual void visit( ConstantExpr *constantExpr ); 
+	virtual void visit( ConstantExpr *constantExpr );
 	virtual void visit( SizeofExpr *sizeofExpr );
 	virtual void visit( AlignofExpr *alignofExpr );
@@ -76,4 +76,5 @@
 	virtual void visit( TypeExpr *typeExpr );
 	virtual void visit( AsmExpr *asmExpr );
+	virtual void visit( ImplicitCopyCtorExpr *impCpCtorExpr );
 	virtual void visit( UntypedValofExpr *valofExpr );
 	virtual void visit( CompoundLiteralExpr *compLitExpr );
@@ -96,4 +97,5 @@
 	virtual void visit( SingleInit *singleInit );
 	virtual void visit( ListInit *listInit );
+	virtual void visit( ConstructorInit *ctorInit );
 
 	virtual void visit( Subrange *subrange );
Index: src/driver/cc1.cc
===================================================================
--- src/driver/cc1.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/driver/cc1.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,6 +10,6 @@
 // Created On       : Fri Aug 26 14:23:51 2005
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Jan 25 16:05:15 2016
-// Update Count     : 56
+// Last Modified On : Thu May  5 16:04:30 2016
+// Update Count     : 77
 //
 
@@ -108,9 +108,13 @@
 	const char *args[argc + 100];						// leave space for 100 additional cpp command line values
 	int nargs = 1;										// number of arguments in args list; 0 => command name
-	const char *uargs[20];								// leave space for 20 additional cfa-cpp command line values
-	int nuargs = 1;										// 0 => command name
+	const char *cargs[20];								// leave space for 20 additional cfa-cpp command line values
+	int ncargs = 1;										// 0 => command name
 
 	signal( SIGINT,  sigTermHandler );
 	signal( SIGTERM, sigTermHandler );
+
+#ifdef __DEBUG_H__
+	cerr << "Stage1" << endl;
+#endif // __DEBUG_H__
 
 	// process all the arguments
@@ -153,9 +157,9 @@
 				CFA_flag = true;
 			} else if ( prefix( arg, D__CFA_FLAGPREFIX__ ) ) {
-				uargs[nuargs] = ( *new string( arg.substr( D__CFA_FLAGPREFIX__.size() ) ) ).c_str();
-				nuargs += 1;
+				cargs[ncargs] = ( *new string( arg.substr( D__CFA_FLAGPREFIX__.size() ) ) ).c_str();
+				ncargs += 1;
 			} else if ( arg == "-D" && prefix( argv[i + 1], D__CFA_FLAGPREFIX__.substr(2) ) ) {
-				uargs[nuargs] = ( *new string( string( argv[i + 1] ).substr( D__CFA_FLAGPREFIX__.size() - 2 ) ) ).c_str();
-				nuargs += 1;
+				cargs[ncargs] = ( *new string( string( argv[i + 1] ).substr( D__CFA_FLAGPREFIX__.size() - 2 ) ) ).c_str();
+				ncargs += 1;
 				i += 1;									// and the argument
 			} else if ( prefix( arg, D__GCC_BPREFIX__ ) ) {
@@ -317,26 +321,32 @@
 
 	if ( fork() == 0 ) {								// child runs CFA
-		uargs[0] = ( *new string( bprefix + "/cfa-cpp" ) ).c_str();
-
-		uargs[nuargs] = tmpname;
-		nuargs += 1;
+		cargs[0] = ( *new string( bprefix + "/cfa-cpp" ) ).c_str();
+
+		// Source file-name used to generate routine names containing global initializations for TU.
+		cargs[ncargs] = ( *new string( "-F" ) ).c_str();
+		ncargs += 1;
+		cargs[ncargs] = ( *new string( string( cpp_in ) ) ).c_str();
+		ncargs += 1;
+
+		cargs[ncargs] = tmpname;
+		ncargs += 1;
 		if ( o_name != NULL ) {
-			uargs[nuargs] = o_name;
-			nuargs += 1;
+			cargs[ncargs] = o_name;
+			ncargs += 1;
 		} else if ( ! CFA_flag ) {						// run cfa-cpp ?
-			uargs[nuargs] = cpp_out;
-			nuargs += 1;
+			cargs[ncargs] = cpp_out;
+			ncargs += 1;
 		} // if
-		uargs[nuargs] = NULL;							// terminate argument list
-
-#ifdef __DEBUG_H__
-		cerr << "cfa-cpp nuargs: " << o_name << " " << CFA_flag << " " << nuargs << endl;
-		for ( i = 0; uargs[i] != NULL; i += 1 ) {
-			cerr << uargs[i] << " ";
+		cargs[ncargs] = NULL;							// terminate argument list
+
+#ifdef __DEBUG_H__
+		cerr << "cfa-cpp ncargs: " << o_name << " " << CFA_flag << " " << ncargs << endl;
+		for ( i = 0; cargs[i] != NULL; i += 1 ) {
+			cerr << cargs[i] << " ";
 		} // for
 		cerr << endl;
 #endif // __DEBUG_H__
 
-		execvp( uargs[0], (char * const *)uargs );		// should not return
+		execvp( cargs[0], (char * const *)cargs );		// should not return
 		perror( "CFA Translator error: cpp level, execvp" );
 		exit( EXIT_FAILURE );
@@ -370,4 +380,8 @@
 	const char *args[argc + 100];						// leave space for 100 additional cfa command line values
 	int nargs = 1;										// number of arguments in args list; 0 => command name
+
+#ifdef __DEBUG_H__
+	cerr << "Stage2" << endl;
+#endif // __DEBUG_H__
 
 	// process all the arguments
@@ -467,12 +481,6 @@
 
 	if ( arg == "-E" ) {
-#ifdef __DEBUG_H__
-		cerr << "Stage1" << endl;
-#endif // __DEBUG_H__
 		Stage1( argc, argv );
 	} else if ( arg == "-fpreprocessed" ) {
-#ifdef __DEBUG_H__
-		cerr << "Stage2" << endl;
-#endif // __DEBUG_H__
 		Stage2( argc, argv );
 	} else {
Index: src/examples/abstype.c
===================================================================
--- src/examples/abstype.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/examples/abstype.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,9 +10,9 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed May 27 18:10:01 2015
-// Update Count     : 4
+// Last Modified On : Wed Apr  6 22:16:08 2016
+// Update Count     : 8
 //
 
-type T | { T x( T ); };
+otype T | { T x( T ); };
 
 T y( T t ) {
@@ -21,10 +21,10 @@
 }
 
-forall(type T) lvalue T	*?( T* );
-int ?++( int *);
-int ?=?( int*, int );
-forall(dtype DT) DT* ?=?( DT **, DT* );
+forall( otype T ) lvalue T *?( T* );
+int ?++( int * );
+int ?=?( int *, int );
+forall( dtype DT ) DT * ?=?( DT **, DT* );
 
-type U = int*;
+otype U = int *;
 
 U x( U u ) {
Index: src/examples/alloc.c
===================================================================
--- src/examples/alloc.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/examples/alloc.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -11,8 +11,12 @@
 // Created On       : Wed Feb  3 07:56:22 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb 17 11:43:23 2016
-// Update Count     : 40
+// Last Modified On : Fri Mar 11 17:42:08 2016
+// Update Count     : 59
 // 
 
+forall( otype T ) T * malloc( char fill );
+forall( dtype T ) T *?=?( T **, void * );
+void *malloc( unsigned long int );
+#if 0
 #include <fstream>
 #include <stdlib>
@@ -25,10 +29,14 @@
 int * bar( int * p, int c ) { return p; }
 int * baz( int * p, int c ) { return p; }
+#endif
 
 int main( void ) {
+#if 0
     size_t size = 10;
     int * p;
     struct S { int x; double y; } * s;
+#endif
 
+#if 0
     p = malloc( sizeof(*p) );							// C malloc, type unsafe
 	printf( "here1\n" );
@@ -37,5 +45,10 @@
 	printf( "here2\n" );
     free( p );
-    p = malloc( (char)'\0' );									// CFA malloc, type safe
+#endif
+//    int * p;
+//    p = malloc( (char)'\0' );									// CFA malloc, type safe
+    (int *)malloc( (char)'\0' );									// CFA malloc, type safe
+    (void *)malloc( (char)'\0' );									// CFA malloc, type safe
+#if 0
 	printf( "here3\n" );
     p = malloc( p, 1000 );								// CFA remalloc, type safe
@@ -60,5 +73,5 @@
 	printf( "here9\n" );
     free( p );
-#if 0
+
     float * fp = malloc() + 1;
     fprintf( stderr, "%p %p\n", fp, fp - 1 );
Index: src/examples/array.c
===================================================================
--- src/examples/array.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/examples/array.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// array.c -- 
+// array.c --
 //
 // Author           : Richard C. Bilson
 // Created On       : Wed May 27 17:56:53 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 18:13:52 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Apr 27 17:21:52 2016
 // Update Count     : 3
 //
@@ -26,5 +26,5 @@
 // The first element is always at index 0.
 forall( otype array_type, otype elt_type | bounded_array( array_type, elt_type ) )
-elt_type * begin( array_type array ) {
+elt_type * begin( array_type * array ) {
 	return &array[ 0 ];
 }
@@ -32,5 +32,5 @@
 // The end iterator should point one past the last element.
 forall( otype array_type, otype elt_type | bounded_array( array_type, elt_type ) )
-elt_type * end( array_type array ) {
+elt_type * end( array_type * array ) {
 	return &array[ last( array ) ] + 1;
 }
Index: src/examples/array.h
===================================================================
--- src/examples/array.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/examples/array.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// array.h -- 
+// array.h --
 //
 // Author           : Richard C. Bilson
 // Created On       : Wed May 27 17:56:53 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 18:13:35 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Apr 27 17:26:04 2016
 // Update Count     : 5
 //
@@ -26,6 +26,6 @@
 
 // A bounded array is an array that carries its maximum index with it.
-trait bounded_array( otype array_type, otype elt_type | array( array_type, elt_type ) ) {
-	int last( array_type );
+trait bounded_array( otype array_type, otype elt_type | array( array_type *, elt_type ) ) {
+	int last( array_type * );
 };
 
@@ -41,8 +41,9 @@
 // return iterators corresponding to the first element and the one-past-the-end element, STL-style.
 forall( otype array_type, otype elt_type | bounded_array( array_type, elt_type ) )
-elt_type *begin( array_type );
+elt_type * begin( array_type * array );
 
+// The end iterator should point one past the last element.
 forall( otype array_type, otype elt_type | bounded_array( array_type, elt_type ) )
-elt_type *end( array_type );
+elt_type * end( array_type * array );
 
 #endif // ARRAY_H
Index: src/examples/fstream_test.c
===================================================================
--- src/examples/fstream_test.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/examples/fstream_test.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Mar  6 20:58:29 2016
-// Update Count     : 54
+// Last Modified On : Mon May  2 15:25:54 2016
+// Update Count     : 61
 //
 
Index: src/examples/includes.c
===================================================================
--- src/examples/includes.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/examples/includes.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 23:28:02 2016
-// Update Count     : 328
+// Last Modified On : Wed Apr 13 22:30:02 2016
+// Update Count     : 370
 //
 
@@ -24,14 +24,15 @@
 #if 1
 #define _GNU_SOURCE
-#include <aio.h>
-#include <a.out.h>
-#include <aliases.h>
-#include <alloca.h>
-#include <ansidecl.h>
-#include <ar.h>
-#include <argp.h>
+//#include <aio.h>
+//#include <a.out.h>
+//#include <aliases.h>
+//#include <alloca.h>
+//#include <ansidecl.h>
+//#include <ar.h>
+//#include <argp.h>
 #include <argz.h>
-#include <assert.h>
+//#include <assert.h>
 #include <bfd.h>
+#if 0
 #include <bfdlink.h>
 #include <byteswap.h>
@@ -56,11 +57,10 @@
 #include <err.h>
 #include <errno.h>
-#if 0
 #include <error.h>
-#endif
 #include <eti.h>
 #include <evdns.h>
 #include <event.h>
 #include <evhttp.h>
+#endif
 #if 0
 #include <evrpc.h>
@@ -129,5 +129,6 @@
 
 //#define _GNU_SOURCE
-#include <error.h>
+#include <bfd.h>
+//#include <error.h>
 
 #endif // 0
Index: src/examples/io.c
===================================================================
--- src/examples/io.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/examples/io.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -11,6 +11,6 @@
 // Created On       : Wed Mar  2 16:56:02 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Apr 13 23:03:14 2016
-// Update Count     : 22
+// Last Modified On : Sat Apr 30 08:34:13 2016
+// Update Count     : 27
 // 
 
@@ -52,5 +52,5 @@
 		 | sepDisable | fc | dc | ldc | sepEnable | endl		// complex without separator
 		 | sepOn | s1 | sepOff | s2 | endl						// local separator removal
-		 | s1 | "" | s2 | endl;									// C string withou separator
+		 | s1 | "" | s2 | endl;									// C string without separator
 	sout | endl;
 
@@ -70,4 +70,5 @@
 		| "£" | 27
 		| "¥" | 27
+		| "¡" | 27
 		| "¿" | 27
 		| "«" | 27
Index: src/examples/rational.c
===================================================================
--- src/examples/rational.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/examples/rational.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -11,6 +11,6 @@
 // Created On       : Mon Mar 28 08:43:12 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Apr  8 11:27:48 2016
-// Update Count     : 21
+// Last Modified On : Wed May  4 14:19:36 2016
+// Update Count     : 24
 // 
 
@@ -20,23 +20,20 @@
 
 int main() {
-	Rational a, b, c;
 	sout | "constructor" | endl;
-	a = rational( 3 );
-	b = rational( 4 );
-	c = rational();
+	Rational a = { 3 }, b = { 4 }, c;
 	sout | a | b | c | endl;
-	a = rational( 4, 8 );
-	b = rational( 5, 7 );
+	a = (Rational){ 4, 8 };
+	b = (Rational){ 5, 7 };
 	sout | a | b | endl;
-	a = rational( -2, -3 );
-	b = rational( 3, -2 );
+	a = (Rational){ -2, -3 };
+	b = (Rational){ 3, -2 };
 	sout | a | b | endl;
-	a = rational( -2, 3 );
-	b = rational( 3, 2 );
+	a = (Rational){ -2, 3 };
+	b = (Rational){ 3, 2 };
 	sout | a | b | endl;
 
 	sout | "logical" | endl;
-	a = rational( -2 );
-	b = rational( -3, 2 );
+	a = (Rational){ -2 };
+	b = (Rational){ -3, 2 };
 	sout | a | b | endl;
 	sout | a == 1 | endl;
@@ -55,9 +52,9 @@
 
 	sout | "conversion" | endl;
-	a = rational( 3, 4 );
+	a = (Rational){ 3, 4 };
 	sout | widen( a ) | endl;
-	a = rational( 1, 7 );
+	a = (Rational){ 1, 7 };
 	sout | widen( a ) | endl;
-	a = rational( 355, 113 );
+	a = (Rational){ 355, 113 };
 	sout | widen( a ) | endl;
 	sout | narrow( 0.75, 4 ) | endl;
@@ -65,7 +62,5 @@
 	sout | narrow( 3.14159265358979, 256 ) | endl;
 
-	Rational x, y;
-	x = rational( 1, 2 );
-	y = rational( 2 );
+	Rational x = { 1, 2 }, y = { 2 };
 	sout | x - y | endl;
 	sout | x > y | endl;
@@ -73,13 +68,12 @@
 	sout | y | denominator( y, -2 ) | y | endl;
 
-	Rational z;
-	z = rational( 0, 5 );
+	Rational z = { 0, 5 };
 	sout | z | endl;
 
 	sout | x | numerator( x, 0 ) | x | endl;
 
-	x = rational( 1, MAX ) + rational( 1, MAX );
+	x = (Rational){ 1, MAX } + (Rational){ 1, MAX };
 	sout | x | endl;
-	x = rational( 3, MAX ) + rational( 2, MAX );
+	x = (Rational){ 3, MAX } + (Rational){ 2, MAX };
 	sout | x | endl;
 
Index: src/examples/sum.c
===================================================================
--- src/examples/sum.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/examples/sum.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Mar  4 15:06:47 2016
-// Update Count     : 196
+// Last Modified On : Mon May  2 15:07:57 2016
+// Update Count     : 198
 //
 
@@ -48,5 +48,5 @@
 	} // for
 	sout | "sum from" | low | "to" | High | "is"
-		 | (int)sum( size, a ) | "" | ", check" | (int)s | endl;
+		 | (int)sum( size, a ) | ", check" | (int)s | endl;
 
 	int s = 0, a[size], v = low;
@@ -56,5 +56,5 @@
 	} // for
 	sout | "sum from" | low | "to" | High | "is"
-		 | sum( size, (int *)a ) | "" | ", check" | (int)s | endl;
+		 | sum( size, (int *)a ) | ", check" | (int)s | endl;
 
 	float s = 0.0, a[size], v = low / 10.0;
@@ -64,5 +64,5 @@
 	} // for
 	sout | "sum from" | low / 10.0 | "to" | High / 10.0 | "is"
-		 | sum( size, (float *)a ) | "" | ", check" | (float)s | endl;
+		 | sum( size, (float *)a ) | ", check" | (float)s | endl;
 
 	double s = 0, a[size], v = low / 10.0;
@@ -72,5 +72,5 @@
 	} // for
 	sout | "sum from" | low / 10.0 | "to" | High / 10.0 | "is"
-		 | sum( size, (double *)a ) | "" | ", check" | (double)s | endl;
+		 | sum( size, (double *)a ) | ", check" | (double)s | endl;
 
 	struct S { int i, j; } 0 = { 0, 0 }, 1 = { 1, 1 };
@@ -87,5 +87,5 @@
 	} // for
 	sout | "sum from" | low | "to" | High | "is"
-		 | sum( size, (S *)a ) | "" | ", check" | (S)s | endl;
+		 | sum( size, (S *)a ) | ", check" | (S)s | endl;
 } // main
 
Index: src/examples/vector_int.c
===================================================================
--- src/examples/vector_int.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/examples/vector_int.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// vector_int.c -- 
+// vector_int.c --
 //
 // Author           : Richard C. Bilson
 // Created On       : Wed May 27 17:56:53 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed May 27 18:38:05 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Apr 27 17:27:12 2016
 // Update Count     : 3
 //
@@ -22,18 +22,25 @@
 #define DEFAULT_CAPACITY 20
 
-vector_int vector_int_allocate() {
-	return vector_int_allocate( DEFAULT_CAPACITY );
+void ?{}( vector_int * vec ) {
+	vec { DEFAULT_CAPACITY };
 }
 
-vector_int vector_int_allocate( int reserve ) {
-	vector_int new_vector;
-	new_vector.last = -1;
-	new_vector.capacity = reserve;
-	new_vector.data = malloc( sizeof( int ) * reserve );
-	return new_vector;
+void ?{}( vector_int * vec, int reserve ) {
+	vec->last = -1;
+	vec->capacity = reserve;
+	vec->data = malloc( sizeof( int ) * reserve );
 }
 
-void vector_int_deallocate( vector_int vec ) {
-	free( vec.data );
+void ?{}( vector_int * vec, vector_int other ) {
+	vec->last = other.last;
+	vec->capacity = other.capacity;
+	vec->data = malloc( sizeof( int ) * other.capacity );
+	for (int i = 0; i < vec->last; i++) {
+		vec->data[i] = other.data[i];
+	}
+}
+
+void ^?{}( vector_int * vec ) {
+	free( vec->data );
 }
 
@@ -56,10 +63,10 @@
 // implement bounded_array
 
-lvalue int ?[?]( vector_int vec, int index ) {
-	return vec.data[ index ];
+lvalue int ?[?]( vector_int * vec, int index ) {
+	return vec->data[ index ];
 }
 
-int last( vector_int vec ) {
-	return vec.last;
+int last( vector_int * vec ) {
+	return vec->last;
 }
 
Index: src/examples/vector_int.h
===================================================================
--- src/examples/vector_int.h	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/examples/vector_int.h	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// vector_int.h -- 
+// vector_int.h --
 //
 // Author           : Richard C. Bilson
 // Created On       : Wed May 27 17:56:53 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed May 27 18:39:05 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Apr 27 17:26:59 2016
 // Update Count     : 2
 //
@@ -25,7 +25,8 @@
 } vector_int;
 
-vector_int vector_int_allocate();						// allocate vector with default capacity
-vector_int vector_int_allocate( int reserve );			// allocate vector with specified capacity
-void vector_int_deallocate( vector_int );				// deallocate vector's storage
+void ?{}( vector_int * );								// allocate vector with default capacity
+void ?{}( vector_int *, int reserve );          // allocate vector with specified capacity
+void ?{}( vector_int * vec, vector_int other ); // copy constructor
+void ^?{}( vector_int * );								// deallocate vector's storage
 
 void reserve( vector_int *vec, int reserve );			// reserve more capacity
@@ -34,6 +35,6 @@
 // implement bounded_array
 
-lvalue int ?[?]( vector_int vec, int index );			// access to arbitrary element (does not resize)
-int last( vector_int vec );								// return last element
+lvalue int ?[?]( vector_int * vec, int index );			// access to arbitrary element (does not resize)
+int last( vector_int * vec );								// return last element
 
 #endif // VECTOR_INT_H
Index: src/examples/vector_test.c
===================================================================
--- src/examples/vector_test.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/examples/vector_test.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// vector_test.c -- 
+// vector_test.c --
 //
 // Author           : Richard C. Bilson
 // Created On       : Wed May 27 17:56:53 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb 17 12:23:55 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Apr 27 17:31:27 2016
 // Update Count     : 18
 //
@@ -20,5 +20,5 @@
 
 int main( void ) {
-	vector_int vec = vector_int_allocate();
+	vector_int vec;
 
 	// read in numbers until EOF or error
@@ -34,9 +34,9 @@
 
 	sout | "Array elements:" | endl;
-	write( begin( vec ), end( vec ), sout );
+	write( begin( &vec ), end( &vec ), sout );
 	sout | endl;
 
 	sout | "Array elements reversed:" | endl;
-	write_reverse( begin( vec ), end( vec ), sout );
+	write_reverse( begin( &vec ), end( &vec ), sout );
 	sout | endl;
 }
Index: src/initialization.txt
===================================================================
--- src/initialization.txt	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/initialization.txt	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -34,2 +34,38 @@
 sure that resolved initializers for all declarations are being
 generated.
+
+
+------
+
+More recent email: (I am quoted; Richard is the responder)
+> As far as I'm aware, the only way that I could currently get the correct
+> results from the unification engine is by feeding it an expression that
+> looks like "?=?( ((struct Y)x.y).a, 10 )", then picking out the pieces that
+> I need (namely the correct choice for a). Does this seem like a reasonable
+> approach to solve this problem?
+
+No, unfortunately. Initialization isn't being rewritten as assignment,
+so you shouldn't allow the particular selection of assignment
+operators that happen to be in scope (and which may include
+user-defined operators) to guide the type resolution.
+
+I don't think there is any way to rewrite an initializer as a single
+expression and have the resolver just do the right thing. I see the
+algorithm as:
+
+For each alternative interpretation of the designator:
+  Construct an expression that casts the initializer to the type of
+    the designator
+  Construct an AlternativeFinder and use it to find the lowest cost
+    interpretation of the expression
+  Add this interpretation to a list of possibilities
+Go through the list of possibilities and pick the lowest cost
+
+As with many things in the resolver, it's conceptually simple but the
+implementation may be a bit of a pain. It fits in with functions like
+findSingleExpression, findIntegralExpression in Resolver.cc, although
+it will be significantly more complicated than any of the existing
+ones.
+
+
+
Index: src/libcfa/Makefile.am
===================================================================
--- src/libcfa/Makefile.am	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/libcfa/Makefile.am	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -6,5 +6,5 @@
 ## file "LICENCE" distributed with Cforall.
 ##
-## Makefile.am -- 
+## Makefile.am --
 ##
 ## Author           : Peter A. Buhr
@@ -51,5 +51,5 @@
 
 CFLAGS = -g -Wall -Wno-unused-function -B${abs_top_srcdir}/src/driver -XCFA -t  # TEMPORARY: does not build with -O2
-CC = ${abs_top_srcdir}/src/driver/cfa 
+CC = ${abs_top_srcdir}/src/driver/cfa
 
 # extension-less header files are overridden by default make rules => explicitly override rule
@@ -67,3 +67,4 @@
 include_HEADERS = ${cheaders:=.h} ${libs} ${cfaheaders}
 
+CLEANFILES = libcfa-prelude.c
 MAINTAINERCLEANFILES += ${includedir}/*
Index: src/libcfa/Makefile.in
===================================================================
--- src/libcfa/Makefile.in	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/libcfa/Makefile.in	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -111,5 +111,5 @@
 AWK = @AWK@
 BACKEND_CC = @BACKEND_CC@
-CC = ${abs_top_srcdir}/src/driver/cfa 
+CC = ${abs_top_srcdir}/src/driver/cfa
 CCDEPMODE = @CCDEPMODE@
 CFA_BINDIR = @CFA_BINDIR@
@@ -219,4 +219,5 @@
 cfaheaders = # limits
 include_HEADERS = ${cheaders:=.h} ${libs} ${cfaheaders}
+CLEANFILES = libcfa-prelude.c
 all: all-am
 
@@ -457,4 +458,5 @@
 
 clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
 
 distclean-generic:
Index: src/libcfa/fstream
===================================================================
--- src/libcfa/fstream	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/libcfa/fstream	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Apr 19 20:44:10 2016
-// Update Count     : 84
+// Last Modified On : Thu Apr 28 08:08:04 2016
+// Update Count     : 88
 //
 
@@ -22,6 +22,6 @@
 struct ofstream {
 	void *file;
-	int sepDefault;
-	int sepOnOff;
+	_Bool sepDefault;
+	int sepOnOff;										// FIX ME: type should be _Bool
 	char separator[separateSize];
 }; // ofstream
Index: src/libcfa/fstream.c
===================================================================
--- src/libcfa/fstream.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/libcfa/fstream.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,11 +5,11 @@
 // file "LICENCE" distributed with Cforall.
 //
-// fstream.c -- 
+// fstream.c --
 //
 // Author           : Peter A. Buhr
 // Created On       : Wed May 27 17:56:53 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Apr  6 17:55:27 2016
-// Update Count     : 176
+// Last Modified By : Rob Schluntz
+// Last Modified On : Mon May 02 15:14:52 2016
+// Update Count     : 187
 //
 
@@ -75,5 +75,5 @@
 	if ( fclose( (FILE *)(os->file) ) == EOF ) {
 		perror( IO_MSG "close output" );
-	} // if 
+	} // if
 } // close
 
@@ -93,5 +93,4 @@
 int prtfmt( ofstream * os, const char fmt[], ... ) {
     va_list args;
-
     va_start( args, fmt );
     int len = vfprintf( (FILE *)(os->file), fmt, args );
@@ -103,4 +102,6 @@
 	} // if
     va_end( args );
+
+	sepReset( os );										// reset separator
 	return len;
 } // prtfmt
@@ -139,5 +140,5 @@
 	if ( fclose( (FILE *)(is->file) ) == EOF ) {
 		perror( IO_MSG "close input" );
-	} // if 
+	} // if
 } // close
 
@@ -154,5 +155,5 @@
 	return is;
 } // read
-  
+
 ifstream *ungetc( ifstream * is, char c ) {
 	if ( fail( is ) ) {
Index: src/libcfa/iostream.c
===================================================================
--- src/libcfa/iostream.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/libcfa/iostream.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,11 +5,11 @@
 // file "LICENCE" distributed with Cforall.
 //
-// iostream.c -- 
+// iostream.c --
 //
 // Author           : Peter A. Buhr
 // Created On       : Wed May 27 17:56:53 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Apr  6 16:13:29 2016
-// Update Count     : 278
+// Last Modified By : Rob Schluntz
+// Last Modified On : Mon May 02 15:13:55 2016
+// Update Count     : 302
 //
 
@@ -34,5 +34,4 @@
 ostype * ?|?( ostype *os, short int si ) {
 	if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) );
-	sepReset( os );
 	prtfmt( os, "%hd", si );
 	return os;
@@ -42,5 +41,4 @@
 ostype * ?|?( ostype *os, unsigned short int usi ) {
 	if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) );
-	sepReset( os );
 	prtfmt( os, "%hu", usi );
 	return os;
@@ -50,5 +48,4 @@
 ostype * ?|?( ostype *os, int i ) {
 	if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) );
-	sepReset( os );
 	prtfmt( os, "%d", i );
 	return os;
@@ -58,5 +55,4 @@
 ostype * ?|?( ostype *os, unsigned int ui ) {
 	if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) );
-	sepReset( os );
 	prtfmt( os, "%u", ui );
 	return os;
@@ -66,5 +62,4 @@
 ostype * ?|?( ostype *os, long int li ) {
 	if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) );
-	sepReset( os );
 	prtfmt( os, "%ld", li );
 	return os;
@@ -74,5 +69,4 @@
 ostype * ?|?( ostype *os, unsigned long int uli ) {
 	if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) );
-	sepReset( os );
 	prtfmt( os, "%lu", uli );
 	return os;
@@ -82,5 +76,4 @@
 ostype * ?|?( ostype *os, long long int lli ) {
 	if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) );
-	sepReset( os );
 	prtfmt( os, "%lld", lli );
 	return os;
@@ -90,5 +83,4 @@
 ostype * ?|?( ostype *os, unsigned long long int ulli ) {
 	if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) );
-	sepReset( os );
 	prtfmt( os, "%llu", ulli );
 	return os;
@@ -98,5 +90,4 @@
 ostype * ?|?( ostype *os, float f ) {
 	if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) );
-	sepReset( os );
 	prtfmt( os, "%g", f );
 	return os;
@@ -106,5 +97,4 @@
 ostype * ?|?( ostype *os, double d ) {
 	if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) );
-	sepReset( os );
 	prtfmt( os, "%.*lg", DBL_DIG, d );
 	return os;
@@ -114,5 +104,4 @@
 ostype * ?|?( ostype *os, long double ld ) {
 	if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) );
-	sepReset( os );
 	prtfmt( os, "%.*Lg", LDBL_DIG, ld );
 	return os;
@@ -155,5 +144,6 @@
 		// opening delimiters
 		['('] : Open, ['['] : Open, ['{'] : Open,
-		['$'] : Open, [(unsigned char)'£'] : Open, [(unsigned char)'¥'] : Open, [(unsigned char)'¿'] : Open, [(unsigned char)'«'] : Open,
+		['$'] : Open, [(unsigned char)'£'] : Open, [(unsigned char)'¥'] : Open,
+		[(unsigned char)'¡'] : Open, [(unsigned char)'¿'] : Open, [(unsigned char)'«'] : Open,
 		// closing delimiters
 		[','] : Close, ['.'] : Close, [':'] : Close, [';'] : Close, ['!'] : Close, ['?'] : Close,
@@ -162,10 +152,9 @@
 		// opening-closing delimiters
 		['\''] : OpenClose, ['`'] : OpenClose, ['"'] : OpenClose,
-		['\f'] : OpenClose, ['\n'] : OpenClose, ['\r'] : OpenClose, ['\t'] : OpenClose, ['\v'] : OpenClose, // isspace
+		[' '] : OpenClose, ['\f'] : OpenClose, ['\n'] : OpenClose, ['\r'] : OpenClose, ['\t'] : OpenClose, ['\v'] : OpenClose, // isspace
 	}; // mask
 
-	int len = strlen( cp );
-	// null string => no separator
-  if ( len == 0 ) { sepOff( os ); return os; }
+  if ( cp[0] == '\0' ) { sepOff( os ); return os; }		// null string => no separator
+
 	// first character IS NOT spacing or closing punctuation => add left separator
 	unsigned char ch = cp[0];							// must make unsigned
@@ -173,11 +162,15 @@
 		prtfmt( os, "%s", sepGet( os ) );
 	} // if
+
+	// if string starts line, must reset to determine open state because separator is off
+	sepReset( os );										// reset separator
+
 	// last character IS spacing or opening punctuation => turn off separator for next item
-	unsigned int posn = len - 1;
+	unsigned int len = strlen( cp ), posn = len - 1;
 	ch = cp[posn];										// must make unsigned
-	if ( mask[ ch ] == Open || mask[ ch ] == OpenClose ) {
+	if ( sepPrt( os ) && mask[ ch ] != Open && mask[ ch ] != OpenClose ) {
+		sepOn( os );
+	} else {
 		sepOff( os );
-	} else {
-		sepOn( os );
 	} // if
 	return write( os, cp, len );
@@ -187,5 +180,4 @@
 ostype * ?|?( ostype *os, const void *p ) {
 	if ( sepPrt( os ) ) prtfmt( os, "%s", sepGet( os ) );
-	sepReset( os );
 	prtfmt( os, "%p", p );
 	return os;
@@ -193,10 +185,10 @@
 
 
-forall( dtype ostype | ostream( ostype ) ) 
+forall( dtype ostype | ostream( ostype ) )
 ostype * ?|?( ostype *os, ostype * (* manip)( ostype * ) ) {
 	return manip( os );
 } // ?|?
 
-forall( dtype ostype | ostream( ostype ) ) 
+forall( dtype ostype | ostream( ostype ) )
 ostype * endl( ostype * os ) {
 	os | '\n';
@@ -206,5 +198,5 @@
 } // endl
 
-forall( dtype ostype | ostream( ostype ) ) 
+forall( dtype ostype | ostream( ostype ) )
 ostype * sepOn( ostype * os ) {
 	sepOn( os );
@@ -212,5 +204,5 @@
 } // sepOn
 
-forall( dtype ostype | ostream( ostype ) ) 
+forall( dtype ostype | ostream( ostype ) )
 ostype * sepOff( ostype * os ) {
 	sepOff( os );
@@ -218,5 +210,5 @@
 } // sepOff
 
-forall( dtype ostype | ostream( ostype ) ) 
+forall( dtype ostype | ostream( ostype ) )
 ostype * sepEnable( ostype * os ) {
 	sepEnable( os );
@@ -224,5 +216,5 @@
 } // sepEnable
 
-forall( dtype ostype | ostream( ostype ) ) 
+forall( dtype ostype | ostream( ostype ) )
 ostype * sepDisable( ostype * os ) {
 	sepDisable( os );
@@ -344,5 +336,5 @@
 } // ?|?
 
-_Istream_cstrUC cstr( char * s ) { _Istream_cstrUC s = { s }; return s; }
+_Istream_cstrUC cstr( char * str ) { _Istream_cstrUC s = { str }; return s; }
 forall( dtype istype | istream( istype ) )
 istype * ?|?( istype * is, _Istream_cstrUC cstr ) {
@@ -351,5 +343,5 @@
 } // cstr
 
-_Istream_cstrC cstr( char * s, int size ) { _Istream_cstrC s = { s, size }; return s; }
+_Istream_cstrC cstr( char * str, int size ) { _Istream_cstrC s = { str, size }; return s; }
 forall( dtype istype | istream( istype ) )
 istype * ?|?( istype * is, _Istream_cstrC cstr ) {
Index: src/libcfa/prelude.cf
===================================================================
--- src/libcfa/prelude.cf	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/libcfa/prelude.cf	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -1,9 +1,9 @@
 # 2 "prelude.cf"  // needed for error messages from this file
-//                               -*- Mode: C -*- 
-// 
+//                               -*- Mode: C -*-
+//
 // Copyright (C) Glen Ditchfield 1994, 1999
-// 
+//
 // prelude.cf -- Standard Cforall Preample for C99
-// 
+//
 // Author           : Glen Ditchfield
 // Created On       : Sat Nov 29 07:23:41 2014
@@ -117,11 +117,11 @@
 forall( ftype FT ) lvalue FT		 *?( FT * );
 
-_Bool			+?( _Bool ),			-?( _Bool ),			~?( _Bool );	     
-signed int		+?( signed int ),		-?( signed int ),		~?( signed int );	     
-unsigned int		+?( unsigned int ),		-?( unsigned int ),		~?( unsigned int );	     
-signed long int		+?( signed long int ),		-?( signed long int ),		~?( signed long int );	     
-unsigned long int	+?( unsigned long int ),	-?( unsigned long int ),	~?( unsigned long int );	     
-signed long long int	+?( signed long long int ),	-?( signed long long int ),	~?( signed long long int );    
-unsigned long long int	+?( unsigned long long int ),	-?( unsigned long long int ),	~?( unsigned long long int );  
+_Bool			+?( _Bool ),			-?( _Bool ),			~?( _Bool );
+signed int		+?( signed int ),		-?( signed int ),		~?( signed int );
+unsigned int		+?( unsigned int ),		-?( unsigned int ),		~?( unsigned int );
+signed long int		+?( signed long int ),		-?( signed long int ),		~?( signed long int );
+unsigned long int	+?( unsigned long int ),	-?( unsigned long int ),	~?( unsigned long int );
+signed long long int	+?( signed long long int ),	-?( signed long long int ),	~?( signed long long int );
+unsigned long long int	+?( unsigned long long int ),	-?( unsigned long long int ),	~?( unsigned long long int );
 float			+?( float ),			-?( float );
 double			+?( double ),			-?( double );
@@ -627,2 +627,229 @@
 			?+=?( long double _Complex *, long double _Complex ), ?+=?( volatile long double _Complex *, long double _Complex ),
 			?-=?( long double _Complex *, long double _Complex ), ?-=?( volatile long double _Complex *, long double _Complex );
+
+
+
+
+
+// ------------------------------------------------------------
+//
+// Section ??? Constructors and Destructors
+//
+// ------------------------------------------------------------
+
+// default ctor
+void	?{}( _Bool * ),				?{}( volatile _Bool * );
+void	?{}( char * ),	?{}( volatile char * );
+void	?{}( unsigned char * ),	?{}( volatile unsigned char * );
+void	?{}( char signed * ),			?{}( volatile char signed * );
+void	?{}( int short * ),				?{}( volatile int short * );
+void	?{}( int short unsigned * ),	?{}( volatile int short unsigned * );
+void	?{}( signed int * ),			?{}( volatile signed int * );
+void	?{}( unsigned int * ),			?{}( volatile unsigned int * );
+void	?{}( signed long int * ),		?{}( volatile signed long int * );
+void	?{}( unsigned long int * ),		?{}( volatile unsigned long int * );
+void	?{}( signed long long int * ),		?{}( volatile signed long long int * );
+void	?{}( unsigned long long int * ),	?{}( volatile unsigned long long int * );
+void	?{}( float * ),				?{}( volatile float * );
+void	?{}( double * ),			?{}( volatile double * );
+void	?{}( long double * ),			?{}( volatile long double * );
+void	?{}( float _Complex * ),		?{}( volatile float _Complex * );
+void	?{}( double _Complex * ),		?{}( volatile double _Complex * );
+void	?{}( long double _Complex * ),		?{}( volatile long double _Complex * );
+
+// copy ctor
+void	?{}( _Bool *, _Bool ),					?{}( volatile _Bool *, _Bool );
+void	?{}( char *, char ),	?{}( volatile char *, char );
+void	?{}( unsigned char *, unsigned char ),			?{}( volatile unsigned char *, unsigned char );
+void	?{}( char signed *, char signed ),			?{}( volatile char signed *, char signed );
+void	?{}( int short *, int short ),				?{}( volatile int short *, int short );
+void	?{}( int short unsigned *, int short unsigned ),	?{}( volatile int short unsigned *, int short unsigned );
+void	?{}( signed int *, signed int),				?{}( volatile signed int *, signed int );
+void	?{}( unsigned int *, unsigned int),			?{}( volatile unsigned int *, unsigned int );
+void	?{}( signed long int *, signed long int),		?{}( volatile signed long int *, signed long int );
+void	?{}( unsigned long int *, unsigned long int),		?{}( volatile unsigned long int *, unsigned long int );
+void	?{}( signed long long int *, signed long long int),	?{}( volatile signed long long int *, signed long long int );
+void	?{}( unsigned long long int *, unsigned long long int),	?{}( volatile unsigned long long int *, unsigned long long int );
+void	?{}( float *, float),					?{}( volatile float *, float );
+void	?{}( double *, double),					?{}( volatile double *, double );
+void	?{}( long double *, long double),			?{}( volatile long double *, long double );
+void	?{}( float _Complex *, float _Complex),			?{}( volatile float _Complex *, float _Complex );
+void	?{}( double _Complex *, double _Complex),		?{}( volatile double _Complex *, double _Complex );
+void	?{}( long double _Complex *, long double _Complex),	?{}( volatile long double _Complex *, long double _Complex );
+
+// dtor
+void	^?{}( _Bool * ),			^?{}( volatile _Bool * );
+void	^?{}( char * ),	^?{}( volatile char * );
+void	^?{}( char unsigned * ),			^?{}( volatile char unsigned * );
+void	^?{}( char signed * ),			^?{}( volatile char signed * );
+void	^?{}( int short * ),				^?{}( volatile int short * );
+void	^?{}( int short unsigned * ),	^?{}( volatile int short unsigned * );
+void	^?{}( signed int * ),			^?{}( volatile signed int * );
+void	^?{}( unsigned int * ),			^?{}( volatile unsigned int * );
+void	^?{}( signed long int * ),		^?{}( volatile signed long int * );
+void	^?{}( unsigned long int * ),		^?{}( volatile unsigned long int * );
+void	^?{}( signed long long int * ),		^?{}( volatile signed long long int * );
+void	^?{}( unsigned long long int * ),	^?{}( volatile unsigned long long int * );
+void	^?{}( float * ),			^?{}( volatile float * );
+void	^?{}( double * ),			^?{}( volatile double * );
+void	^?{}( long double * ),			^?{}( volatile long double * );
+void	^?{}( float _Complex * ),		^?{}( volatile float _Complex * );
+void	^?{}( double _Complex * ),		^?{}( volatile double _Complex * );
+void	^?{}( long double _Complex * ),		^?{}( volatile long double _Complex * );
+
+// // default ctor
+// forall( dtype DT ) void	 ?{}(		     DT ** );
+// forall( dtype DT ) void	 ?{}( const	     DT ** );
+// forall( dtype DT ) void	 ?{}(	    volatile DT ** );
+// forall( dtype DT ) void	 ?{}( const volatile DT ** );
+
+// // copy ctor
+// forall( dtype DT ) void	 ?{}(		     DT **, DT* );
+// forall( dtype DT ) void	 ?{}( const	     DT **, DT* );
+// forall( dtype DT ) void	 ?{}(	    volatile DT **, DT* );
+// forall( dtype DT ) void	 ?{}( const volatile DT **, DT* );
+
+// // dtor
+// forall( dtype DT ) void	^?{}(		     DT ** );
+// forall( dtype DT ) void	^?{}( const	     DT ** );
+// forall( dtype DT ) void	^?{}(	    volatile DT ** );
+// forall( dtype DT ) void	^?{}( const volatile DT ** );
+
+// copied from assignment section
+// copy constructors
+forall( ftype FT ) void ?{}( FT **, FT * );
+forall( ftype FT ) void ?{}( FT * volatile *, FT * );
+
+forall( dtype DT ) void ?{}(		     DT *	   *,			DT * );
+forall( dtype DT ) void ?{}(		     DT * volatile *,			DT * );
+forall( dtype DT ) void ?{}( const	     DT *	   *,			DT * );
+forall( dtype DT ) void ?{}( const	     DT * volatile *,			DT * );
+forall( dtype DT ) void ?{}( const	     DT *	   *, const		DT * );
+forall( dtype DT ) void ?{}( const	     DT * volatile *, const		DT * );
+forall( dtype DT ) void ?{}(	   volatile  DT *	   *,			DT * );
+forall( dtype DT ) void ?{}(	   volatile  DT * volatile *,			DT * );
+forall( dtype DT ) void ?{}(	   volatile  DT *	   *,	    volatile	DT * );
+forall( dtype DT ) void ?{}(	   volatile  DT * volatile *,	    volatile	DT * );
+
+forall( dtype DT ) void ?{}( const volatile  DT *	   *,			DT * );
+forall( dtype DT ) void ?{}( const volatile  DT * volatile *,			DT * );
+forall( dtype DT ) void ?{}( const volatile  DT *	   *, const		DT * );
+forall( dtype DT ) void ?{}( const volatile  DT * volatile *, const		DT * );
+forall( dtype DT ) void ?{}( const volatile  DT *	   *,	    volatile	DT * );
+forall( dtype DT ) void ?{}( const volatile  DT * volatile *,	    volatile	DT * );
+forall( dtype DT ) void ?{}( const volatile  DT *	   *, const volatile	DT * );
+forall( dtype DT ) void ?{}( const volatile  DT * volatile *, const volatile	DT * );
+
+forall( dtype DT ) void ?{}(		     DT *	   *,			void * );
+forall( dtype DT ) void ?{}(		     DT * volatile *,			void * );
+forall( dtype DT ) void ?{}( const	     DT *	   *,			void * );
+forall( dtype DT ) void ?{}( const	     DT * volatile *,			void * );
+forall( dtype DT ) void ?{}( const	     DT *	   *, const		void * );
+forall( dtype DT ) void ?{}( const	     DT * volatile *, const		void * );
+forall( dtype DT ) void ?{}(	   volatile  DT *	   *,			void * );
+forall( dtype DT ) void ?{}(	   volatile  DT * volatile *,			void * );
+forall( dtype DT ) void ?{}(	   volatile  DT *	   *,	    volatile	void * );
+forall( dtype DT ) void ?{}(	   volatile  DT * volatile *,	    volatile	void * );
+
+forall( dtype DT ) void ?{}( const volatile  DT *	   *,			void * );
+forall( dtype DT ) void ?{}( const volatile  DT * volatile *,			void * );
+forall( dtype DT ) void ?{}( const volatile  DT *	   *, const		void * );
+forall( dtype DT ) void ?{}( const volatile  DT * volatile *, const		void * );
+forall( dtype DT ) void ?{}( const volatile  DT *	   *,	    volatile	void * );
+forall( dtype DT ) void ?{}( const volatile  DT * volatile *,	    volatile	void * );
+forall( dtype DT ) void ?{}( const volatile  DT *	   *, const volatile	void * );
+forall( dtype DT ) void ?{}( const volatile  DT * volatile *, const volatile	void * );
+
+forall( dtype DT ) void ?{}(		     void *	     *,			DT * );
+forall( dtype DT ) void ?{}(		     void * volatile *,			DT * );
+forall( dtype DT ) void ?{}( const	     void *	     *,			DT * );
+forall( dtype DT ) void ?{}( const	     void * volatile *,			DT * );
+forall( dtype DT ) void ?{}( const	     void *	     *, const		DT * );
+forall( dtype DT ) void ?{}( const	     void * volatile *, const		DT * );
+forall( dtype DT ) void ?{}(	    volatile void *	     *,			DT * );
+forall( dtype DT ) void ?{}(	    volatile void * volatile *,			DT * );
+forall( dtype DT ) void ?{}(	    volatile void *	     *,	      volatile	DT * );
+forall( dtype DT ) void ?{}(	    volatile void * volatile *,	      volatile	DT * );
+forall( dtype DT ) void ?{}( const volatile void *	     *,			DT * );
+forall( dtype DT ) void ?{}( const volatile void * volatile *,			DT * );
+forall( dtype DT ) void ?{}( const volatile void *	     *, const		DT * );
+forall( dtype DT ) void ?{}( const volatile void * volatile *, const		DT * );
+forall( dtype DT ) void ?{}( const volatile void *	     *,	      volatile	DT * );
+forall( dtype DT ) void ?{}( const volatile void * volatile *,	      volatile	DT * );
+forall( dtype DT ) void ?{}( const volatile void *	     *, const volatile	DT * );
+forall( dtype DT ) void ?{}( const volatile void * volatile *, const volatile	DT * );
+
+void 	?{}(		    void *	    *,		      void * );
+void 	?{}(		    void * volatile *,		      void * );
+void 	?{}( const	    void *	    *,		      void * );
+void 	?{}( const	    void * volatile *,		      void * );
+void 	?{}( const	    void *	    *, const	      void * );
+void 	?{}( const	    void * volatile *, const	      void * );
+void 	?{}(	   volatile void *	    *,		      void * );
+void 	?{}(	   volatile void * volatile *,		      void * );
+void 	?{}(	   volatile void *	    *,	     volatile void * );
+void 	?{}(	   volatile void * volatile *,	     volatile void * );
+void 	?{}( const volatile void *	    *,		      void * );
+void 	?{}( const volatile void * volatile *,		      void * );
+void 	?{}( const volatile void *	    *, const	      void * );
+void 	?{}( const volatile void * volatile *, const	      void * );
+void 	?{}( const volatile void *	    *,	     volatile void * );
+void 	?{}( const volatile void * volatile *,	     volatile void * );
+void 	?{}( const volatile void *	    *, const volatile void * );
+void 	?{}( const volatile void * volatile *, const volatile void * );
+
+//forall( dtype DT ) void ?{}(		    DT *	  *, forall( dtype DT2 ) const DT2 * );
+//forall( dtype DT ) void ?{}(		    DT * volatile *, forall( dtype DT2 ) const DT2 * );
+forall( dtype DT ) void ?{}( const	    DT *	  *, forall( dtype DT2 ) const DT2 * );
+forall( dtype DT ) void ?{}( const	    DT * volatile *, forall( dtype DT2 ) const DT2 * );
+//forall( dtype DT ) void ?{}( volatile	    DT *	  *, forall( dtype DT2 ) const DT2 * );
+//forall( dtype DT ) void ?{}( volatile	    DT * volatile *, forall( dtype DT2 ) const DT2 * );
+forall( dtype DT ) void ?{}( const volatile DT *	  *, forall( dtype DT2 ) const DT2 * );
+forall( dtype DT ) void ?{}( const volatile DT * volatile *, forall( dtype DT2 ) const DT2 * );
+
+forall( ftype FT ) void	?{}( FT *	   *, forall( ftype FT2 ) FT2 * );
+forall( ftype FT ) void	?{}( FT * volatile *, forall( ftype FT2 ) FT2 * );
+
+// default ctors
+forall( ftype FT ) void	?{}( FT *	   * );
+forall( ftype FT ) void	?{}( FT * volatile * );
+
+forall( dtype DT ) void	?{}(		     DT *	   *);
+forall( dtype DT ) void	?{}(		     DT * volatile *);
+forall( dtype DT ) void	?{}( const	     DT *	   *);
+forall( dtype DT ) void	?{}( const	     DT * volatile *);
+forall( dtype DT ) void	?{}(	   volatile  DT *	   *);
+forall( dtype DT ) void	?{}(	   volatile  DT * volatile *);
+forall( dtype DT ) void ?{}( const volatile  DT *	   *);
+forall( dtype DT ) void ?{}( const volatile  DT * volatile *);
+
+void 	?{}(		    void *	    *);
+void 	?{}(		    void * volatile *);
+void 	?{}( const	    void *	    *);
+void 	?{}( const	    void * volatile *);
+void 	?{}(	   volatile void *	    *);
+void 	?{}(	   volatile void * volatile *);
+void 	?{}( const volatile void *	    *);
+void 	?{}( const volatile void * volatile *);
+
+// dtors
+forall( ftype FT ) void	^?{}( FT *	   * );
+forall( ftype FT ) void	^?{}( FT * volatile * );
+
+forall( dtype DT ) void	^?{}(		     DT *	   *);
+forall( dtype DT ) void	^?{}(		     DT * volatile *);
+forall( dtype DT ) void	^?{}( const	     DT *	   *);
+forall( dtype DT ) void	^?{}( const	     DT * volatile *);
+forall( dtype DT ) void	^?{}(	   volatile  DT *	   *);
+forall( dtype DT ) void	^?{}(	   volatile  DT * volatile *);
+forall( dtype DT ) void ^?{}( const volatile  DT *	   *);
+forall( dtype DT ) void ^?{}( const volatile  DT * volatile *);
+
+void 	^?{}(		    void *	    *);
+void 	^?{}(		    void * volatile *);
+void 	^?{}( const	    void *	    *);
+void 	^?{}( const	    void * volatile *);
+void 	^?{}(	   volatile void *	    *);
+void 	^?{}(	   volatile void * volatile *);
+void 	^?{}( const volatile void *	    *);
+void 	^?{}( const volatile void * volatile *);
Index: src/libcfa/rational
===================================================================
--- src/libcfa/rational	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/libcfa/rational	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -12,6 +12,6 @@
 // Created On       : Wed Apr  6 17:56:25 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Apr  8 11:38:27 2016
-// Update Count     : 15
+// Last Modified On : Wed May  4 14:11:45 2016
+// Update Count     : 16
 // 
 
@@ -28,7 +28,7 @@
 
 // constructors
-Rational rational();
-Rational rational( long int n );
-Rational rational( long int n, long int d );
+void ?{}( Rational * r );
+void ?{}( Rational * r, long int n );
+void ?{}( Rational * r, long int n, long int d );
 
 // getter/setter for numerator/denominator
Index: src/libcfa/rational.c
===================================================================
--- src/libcfa/rational.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/libcfa/rational.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -11,6 +11,6 @@
 // Created On       : Wed Apr  6 17:54:28 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Apr 21 07:33:03 2016
-// Update Count     : 22
+// Last Modified On : Wed May  4 14:16:14 2016
+// Update Count     : 25
 // 
 
@@ -53,15 +53,16 @@
 // constructors
 
-Rational rational() {
-    return (Rational){ 0, 1 };
+void ?{}( Rational * r ) {
+    r{ 0, 1 };
 } // rational
 
-Rational rational( long int n ) {
-    return (Rational){ n, 1 };
+void ?{}( Rational * r, long int n ) {
+    r{ n, 1 };
 } // rational
 
-Rational rational( long int n, long int d ) {
+void ?{}( Rational * r, long int n, long int d ) {
     long int t = simplify( &n, &d );					// simplify
-    return (Rational){ n / t, d / t };
+    r->numerator = n / t;
+	r->denominator = d / t;
 } // rational
 
@@ -172,6 +173,5 @@
 Rational narrow( double f, long int md ) {
 	if ( md <= 1 ) {									// maximum fractional digits too small?
-		Rational t = rational( f, 1 );					// truncate fraction
-		return t;
+		return (Rational){ f, 1};						// truncate fraction
 	} // if
 
@@ -199,6 +199,5 @@
 		k[2] = x * k[1] + k[0]; k[0] = k[1]; k[1] = k[2];
 	} // for
-	Rational t = rational( neg ? -h[1] : h[1], k[1] );
-	return t;
+	return (Rational){ neg ? -h[1] : h[1], k[1] };
 } // narrow
 
Index: src/libcfa/stdlib
===================================================================
--- src/libcfa/stdlib	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/libcfa/stdlib	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,6 +10,6 @@
 // Created On       : Thu Jan 28 17:12:35 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Apr 21 07:55:21 2016
-// Update Count     : 95
+// Last Modified On : Wed Apr 27 22:03:29 2016
+// Update Count     : 96
 //
 
@@ -45,5 +45,5 @@
 
 forall( otype T ) T * aligned_alloc( size_t alignment );
-forall( otype T ) T * memalign( size_t alignment );
+forall( otype T ) T * memalign( size_t alignment );		// deprecated
 forall( otype T ) int posix_memalign( T ** ptr, size_t alignment );
 
Index: src/libcfa/stdlib.c
===================================================================
--- src/libcfa/stdlib.c	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/libcfa/stdlib.c	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -10,6 +10,6 @@
 // Created On       : Thu Jan 28 17:10:29 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Apr 21 07:58:29 2016
-// Update Count     : 165
+// Last Modified On : Thu Apr 28 07:54:21 2016
+// Update Count     : 166
 //
 
@@ -213,6 +213,6 @@
 //---------------------------------------
 
-forall( otype T | { T ?/?( T, T ); T ?%?( T, T ); } )
-[ T, T ] div( T t1, T t2 ) { /* return [ t1 / t2, t1 % t2 ]; */ }
+// forall( otype T | { T ?/?( T, T ); T ?%?( T, T ); } )
+// [ T, T ] div( T t1, T t2 ) { return [ t1 / t2, t1 % t2 ]; }
 
 //---------------------------------------
Index: src/main.cc
===================================================================
--- src/main.cc	(revision bb8ea3011a8148746d8e28699f24b68eaa57a951)
+++ src/main.cc	(revision d6681823cf43689609e83bcc9077750fba1c262d)
@@ -5,11 +5,11 @@
 // file "LICENCE" distributed with Cforall.
 //
-// main.cc -- 
+// main.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Fri May 15 23:12:02 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Jan 27 22:20:20 2016
-// Update Count     : 199
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 06 15:59:09 2016
+// Update Count     : 203
 //
 
@@ -40,5 +40,7 @@
 #include "MakeLibCfa.h"
 #include "InitTweak/Mutate.h"
-#include "InitTweak/RemoveInit.h"
+#include "InitTweak/GenInit.h"
+#include "InitTweak/FixInit.h"
+#include "InitTweak/FixGlobalInit.h"
 //#include "Explain/GenProlog.h"
 //#include "Try/Visit.h"
@@ -55,9 +57,11 @@
 
 static void parse( FILE * input, LinkageSpec::Type t, bool shouldExit = false );
-static void dump( std::list< Declaration * > & translationUnit );
+static void dump( std::list< Declaration * > & translationUnit, std::ostream & out = std::cout );
 
 bool
 	astp = false,
 	bresolvep = false,
+	bboxp = false,
+	ctorinitp = false,
 	exprp = false,
 	expraltp = false,
@@ -74,9 +78,11 @@
 	codegenp = false;
 
-enum { Ast, Bresolver, Expr, ExprAlt, Grammar, LibCFA, Nopreamble, Parse, Prototypes, Resolver, Symbol, Tree, Validate, };
+enum { Ast, Bbox, Bresolver, CtorInitFix, Expr, ExprAlt, Grammar, LibCFA, Nopreamble, Parse, Prototypes, Resolver, Symbol, Tree, Validate, };
 
 static struct option long_opts[] = {
 	{ "ast", no_argument, 0, Ast },
+	{ "before-box", no_argument, 0, Bbox },
 	{ "before-resolver", no_argument, 0, Bresolver },
+	{ "ctorinitfix", no_argument, 0, CtorInitFix },
 	{ "expr", no_argument, 0, Expr },
 	{ "expralt", no_argument, 0, ExprAlt },
@@ -97,10 +103,11 @@
 	std::ostream *output = &std::cout;
 	int long_index;
-	std::list< Declaration* > translationUnit;
+	std::list< Declaration * > translationUnit;
+	const char *filename = NULL;
 
 	opterr = 0;											// prevent getopt from printing error messages
-	
+
 	int c;
-	while ( (c = getopt_long( argc, argv, "abefglnpqrstvyzD:", long_opts, &long_index )) != -1 ) {
+	while ( (c = getopt_long( argc, argv, "abBcefglnpqrstvyzD:F:", long_opts, &long_index )) != -1 ) {
 		switch ( c ) {
 		  case Ast:
@@ -112,4 +119,11 @@
 			bresolvep = true;
 			break;
+		  case 'B':										// print before resolver steps
+			bboxp = true;
+			break;
+		  case CtorInitFix:
+		  case 'c':
+			ctorinitp = true;
+			break;
 		  case Expr:
 		  case 'e':										// dump AST after expression analysis
@@ -162,4 +176,7 @@
 			break;
 		  case 'D':										// ignore -Dxxx
+			break;
+		  case 'F':										// source file-name without suffix
+			filename = optarg;
 			break;
 		  case '?':
@@ -176,7 +193,11 @@
 			input = fopen( argv[ optind ], "r" );
 			if ( ! input ) {
-				std::cout << "Error: can't open " << argv[optind] << std::endl;
+				std::cout << "Error: can't open " << argv[ optind ] << std::endl;
 				exit( 1 );
 			} // if
+			// if running cfa-cpp directly, might forget to pass -F option (and really shouldn't have to)
+			if ( filename == NULL ) filename = argv[ optind ];
+			// prelude filename comes in differently
+			if ( libcfap ) filename = "prelude.cf";
 			optind += 1;
 		} else {
@@ -187,5 +208,5 @@
 			output = new ofstream( argv[ optind ] );
 		} // if
-	
+
 		Parser::get_parser().set_debug( grammarp );
 
@@ -208,11 +229,11 @@
 					exit( 1 );
 				} // if
-		    
+
 				parse( prelude, LinkageSpec::Intrinsic );
 			} // if
 		} // if
 
-		parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, grammarp );	
-  
+		parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, grammarp );
+
 		if ( parsep ) {
 			Parser::get_parser().get_parseTree()->printList( std::cout );
@@ -249,8 +270,10 @@
 		OPTPRINT( "mutate" )
 		ControlStruct::mutate( translationUnit );
-		OPTPRINT( "fixNames" ) 
+		OPTPRINT( "fixNames" )
 		CodeGen::fixNames( translationUnit );
-		OPTPRINT( "tweak" )
-		InitTweak::tweak( translationUnit );
+		OPTPRINT( "fixGlobalInit" );
+		InitTweak::fixGlobalInit( translationUnit, filename, libcfap || treep );
+		OPTPRINT( "tweakInit" )
+		InitTweak::genInit( translationUnit );
 
 		if ( libcfap ) {
@@ -268,4 +291,13 @@
 		if ( exprp ) {
 			dump( translationUnit );
+			return 0;
+		}
+
+		OPTPRINT( "fixInit" )
+		// fix ObjectDecl - replaces ConstructorInit nodes
+		InitTweak::fix( translationUnit );
+		if ( ctorinitp ) {
+			dump ( translationUnit );
+			return 0;
 		}
 
@@ -276,7 +308,12 @@
 		OPTPRINT( "convertLvalue" )
 		GenPoly::convertLvalue( translationUnit );
+
+		if ( bboxp ) {
+			dump( translationUnit );
+			return 0;
+		}
 		OPTPRINT( "box" )
 		GenPoly::box( translationUnit );
-		
+
 		// print tree right before code generation
 		if ( codegenp ) {
@@ -292,5 +329,7 @@
 	} catch ( SemanticError &e ) {
 		if ( errorp ) {
-			dump( translationUnit );
+			std::cerr << "---AST at error:---" << std::endl;
+			dump( translationUnit, std::cerr );
+			std::cerr << std::endl << "---End of AST, begin error message:---\n" << std::endl;
 		}
 		e.print( std::cerr );
@@ -314,4 +353,5 @@
 	} // try
 
+	deleteAll( translationUnit );
 	return 0;
 } // main
@@ -331,8 +371,8 @@
 }
 
-static void dump( std::list< Declaration * > & translationUnit ) {
+static void dump( std::list< Declaration * > & translationUnit, std::ostream & out ) {
 	std::list< Declaration * > decls;
 	if ( noprotop ) {
-		filter( translationUnit.begin(), translationUnit.end(), 
+		filter( translationUnit.begin(), translationUnit.end(),
 				std::back_inserter( decls ), notPrelude );
 	} else {
@@ -340,5 +380,5 @@
 	}
 
-	printAll( decls, std::cout );
+	printAll( decls, out );
 	deleteAll( translationUnit );
 }
