Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision fa463f18d6d521f0c6ade52d2a5106d42a026733)
+++ src/Common/utility.h	(revision c8dfcd3a4ea472775bb425585268096226f404ce)
@@ -246,4 +246,18 @@
 }
 
+// RAII object to regulate "save and restore" behaviour, e.g.
+// void Foo::bar() {
+//   ValueGuard<int> guard(var); // var is a member of type Foo
+//   var = ...;
+// } // var's original value is restored
+template< typename T >
+struct ValueGuard {
+	T old;
+	T& ref;
+
+	ValueGuard(T& inRef) : old(inRef), ref(inRef) {}
+	~ValueGuard() { ref = old; }
+};
+
 #endif // _UTILITY_H
 
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision fa463f18d6d521f0c6ade52d2a5106d42a026733)
+++ src/InitTweak/FixInit.cc	(revision c8dfcd3a4ea472775bb425585268096226f404ce)
@@ -31,4 +31,5 @@
 #include "SynTree/Mutator.h"
 #include "SymTab/Indexer.h"
+#include "SymTab/Autogen.h"
 #include "GenPoly/PolyMutator.h"
 #include "SynTree/AddStmtVisitor.h"
@@ -176,10 +177,11 @@
 		};
 
-		class WarnStructMembers : public Visitor {
+		class GenStructMemberCalls : public SymTab::Indexer {
 		  public:
-			typedef Visitor Parent;
-			/// warn if a user-defined constructor or destructor is missing calls for
-			/// a struct member or if a member is used before constructed
-			static void warnings( std::list< Declaration * > & translationUnit );
+			typedef Indexer Parent;
+			/// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors
+			/// for any member that is missing a corresponding ctor/dtor call.
+			/// error if a member is used before constructed
+			static void generate( std::list< Declaration * > & translationUnit );
 
 			virtual void visit( FunctionDecl * funcDecl );
@@ -195,6 +197,21 @@
 
 			FunctionDecl * function = 0;
-			std::set< DeclarationWithType * > unhandled;
+			std::set< DeclarationWithType * > unhandled, usedUninit;
 			ObjectDecl * thisParam = 0;
+			bool isCtor = false; // true if current function is a constructor
+		};
+
+		// very simple resolver-like mutator class - used to
+		// resolve UntypedExprs that are found within newly
+		// generated constructor/destructor calls
+		class MutatingResolver : public Mutator {
+		  public:
+			MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {}
+
+			virtual DeclarationWithType* mutate( ObjectDecl *objectDecl );
+
+			virtual Expression* mutate( UntypedExpr *untypedExpr );
+			private:
+			SymTab::Indexer & indexer;
 		};
 	} // namespace
@@ -212,5 +229,5 @@
 		FixCopyCtors::fixCopyCtors( translationUnit );
 
-		WarnStructMembers::warnings( translationUnit );
+		GenStructMemberCalls::generate( translationUnit );
 	}
 
@@ -257,13 +274,11 @@
 		}
 
-		void WarnStructMembers::warnings( std::list< Declaration * > & translationUnit ) {
-			if ( true ) { // fix this condition to skip this pass if warnings aren't enabled
-				WarnStructMembers warner;
-				acceptAll( translationUnit, warner );
-
-				// visitor doesn't throw so that it can collect all errors
-				if ( ! warner.errors.isEmpty() ) {
-					throw warner.errors;
-				}
+		void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) {
+			GenStructMemberCalls warner;
+			acceptAll( translationUnit, warner );
+
+			// visitor doesn't throw so that it can collect all errors
+			if ( ! warner.errors.isEmpty() ) {
+				throw warner.errors;
 			}
 		}
@@ -536,5 +551,5 @@
 							FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
 							dtorCaller->fixUniqueId();
-							dtorCaller->get_statements()->get_kids().push_back( dtorStmt );
+							dtorCaller->get_statements()->push_back( dtorStmt );
 
 							// atexit(dtor_atexit);
@@ -551,6 +566,12 @@
 							// at global scope and there could be multiple function-scoped
 							// static variables with the same name in different functions.
+							// Note: it isn't sufficient to modify only the mangleName, because
+							// then subsequent Indexer passes can choke on seeing the object's name
+							// if another object has the same name and type. An unfortunate side-effect
+							// of renaming the object is that subsequent NameExprs may fail to resolve,
+							// but there shouldn't be any remaining past this point.
 							static UniqueName staticNamer( "_static_var" );
-							objDecl->set_mangleName( objDecl->get_mangleName() + staticNamer.newName() );
+							objDecl->set_name( objDecl->get_name() + staticNamer.newName() );
+							objDecl->set_mangleName( SymTab::Mangler::mangle( objDecl ) );
 
 							objDecl->set_init( NULL );
@@ -717,11 +738,19 @@
 		}
 
-		void WarnStructMembers::visit( FunctionDecl * funcDecl ) {
-			WarnStructMembers old = *this;
-			*this = WarnStructMembers();
+		void GenStructMemberCalls::visit( FunctionDecl * funcDecl ) {
+			ValueGuard< FunctionDecl * > oldFunction( funcDecl );
+			ValueGuard< std::set< DeclarationWithType * > > oldUnhandled( unhandled );
+			ValueGuard< std::set< DeclarationWithType * > > oldUsedUninit( usedUninit );
+			ValueGuard< ObjectDecl * > oldThisParam( thisParam );
+			ValueGuard< bool > oldIsCtor( isCtor );
+
+			// need to start with fresh sets
+			unhandled.clear();
+			usedUninit.clear();
 
 			function = funcDecl;
-			if ( checkWarnings( funcDecl ) ) {
-				FunctionType * type = funcDecl->get_functionType();
+			isCtor = isConstructor( function->get_name() );
+			if ( checkWarnings( function ) ) {
+				FunctionType * type = function->get_functionType();
 				assert( ! type->get_parameters().empty() );
 				thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() );
@@ -739,17 +768,50 @@
 				}
 			}
-			Parent::visit( funcDecl );
-
-			for ( DeclarationWithType * member : unhandled ) {
-				// emit a warning for each unhandled member
-				emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", member->get_name(), " may not have been ", isConstructor( funcDecl->get_name() ) ? "constructed" : "destructed" );
+			Parent::visit( function );
+
+			// remove the unhandled objects from usedUninit, because a call is inserted
+			// to handle them - only objects that are later constructed are used uninitialized.
+			std::set< DeclarationWithType * > diff;
+			std::set_difference( usedUninit.begin(), usedUninit.end(), unhandled.begin(), unhandled.end(), std::inserter( diff, diff.begin() ) );
+			for ( DeclarationWithType * member : diff ) {
+				emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", member->get_name(), " used before being constructed" );
 			}
 
-			// need to steal the errors before they're lost
-			old.errors.append( errors );
-			*this = old;
-		}
-
-		void WarnStructMembers::visit( ApplicationExpr * appExpr ) {
+			if ( ! unhandled.empty() ) {
+				// need to explicitly re-add function parameters in order to resolve copy constructors
+				enterScope();
+				// maybeAccept( function->get_functionType(), *this );
+				for ( DeclarationWithType * member : unhandled ) {
+					// insert and resolve default/copy constructor call for each member that's unhandled
+					std::list< Statement * > stmt;
+					UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
+					deref->get_args().push_back( new VariableExpr( thisParam ) );
+					InitExpander srcParam( (Initializer *)NULL ); // xxx - if copy ctor, need to pass appropriate argument - second param of this function dot member
+					SymTab::genImplicitCall( srcParam, new MemberExpr( member, deref ), function->get_name(), back_inserter( stmt ), member, isCtor );
+
+					assert( stmt.size() <= 1 );
+					if ( stmt.size() == 1 ) {
+						Statement * callStmt = stmt.front();
+
+						MutatingResolver resolver( *this );
+						try {
+							// xxx - these should be in field declaration order
+							callStmt->acceptMutator( resolver );
+							if ( isCtor ) {
+								function->get_statements()->push_front( callStmt );
+							} else {
+								// destructor statements should be added at the end
+								function->get_statements()->push_back( callStmt );
+							}
+						} catch ( SemanticError & error ) {
+							emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", member->get_name(), " not explicitly ", isCtor ? "constructed" : "destructed",  " and no ", isCtor ? "default constructor" : "destructor", " found" );
+						}
+					}
+				}
+				leaveScope();
+			}
+		}
+
+		void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) {
 			if ( ! checkWarnings( function ) ) return;
 
@@ -780,5 +842,5 @@
 		}
 
-		void WarnStructMembers::handleFirstParam( Expression * firstParam ) {
+		void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) {
 			using namespace std;
 			if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) {
@@ -797,7 +859,7 @@
 		}
 
-		void WarnStructMembers::visit( MemberExpr * memberExpr ) {
+		void GenStructMemberCalls::visit( MemberExpr * memberExpr ) {
 			if ( ! checkWarnings( function ) ) return;
-			if ( ! isConstructor( function->get_name() ) ) return;
+			if ( ! isCtor ) return;
 
 			if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
@@ -807,5 +869,5 @@
 							if ( unhandled.count( memberExpr->get_member() ) ) {
 								// emit a warning because a member was used before it was constructed
-								emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", memberExpr->get_member()->get_name(), " used before being constructed" );
+								usedUninit.insert( memberExpr->get_member() );
 							}
 						}
@@ -822,8 +884,20 @@
 
 		template< typename... Params >
-		void WarnStructMembers::emit( const Params &... params ) {
+		void GenStructMemberCalls::emit( const Params &... params ) {
 			// toggle warnings vs. errors here.
 			// warn( params... );
 			error( *this, params... );
+		}
+
+		DeclarationWithType * MutatingResolver::mutate( ObjectDecl *objectDecl ) {
+			// add object to the indexer assumes that there will be no name collisions
+			// in generated code. If this changes, add mutate methods for entities with
+			// scope and call {enter,leave}Scope explicitly.
+			objectDecl->accept( indexer );
+			return objectDecl;
+		}
+
+		Expression* MutatingResolver::mutate( UntypedExpr *untypedExpr ) {
+			return safe_dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untypedExpr, indexer ) );
 		}
 	} // namespace
Index: src/Parser/ParseNode.cc
===================================================================
--- src/Parser/ParseNode.cc	(revision fa463f18d6d521f0c6ade52d2a5106d42a026733)
+++ src/Parser/ParseNode.cc	(revision c8dfcd3a4ea472775bb425585268096226f404ce)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// ParseNode.cc -- 
+// ParseNode.cc --
 //
 // Author           : Rodolfo G. Esteves
@@ -12,5 +12,5 @@
 // Last Modified On : Wed Aug 17 23:14:16 2016
 // Update Count     : 126
-// 
+//
 
 #include "ParseNode.h"
@@ -19,4 +19,9 @@
 int ParseNode::indent_by = 4;
 
+std::ostream & operator<<( std::ostream & out, const ParseNode * node ) {
+  node->print( out );
+  return out;
+}
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision fa463f18d6d521f0c6ade52d2a5106d42a026733)
+++ src/Parser/ParseNode.h	(revision c8dfcd3a4ea472775bb425585268096226f404ce)
@@ -409,4 +409,6 @@
 }
 
+// in ParseNode.cc
+std::ostream & operator<<( std::ostream & out, const ParseNode * node );
 
 #endif // PARSENODE_H
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision fa463f18d6d521f0c6ade52d2a5106d42a026733)
+++ src/SymTab/Autogen.h	(revision c8dfcd3a4ea472775bb425585268096226f404ce)
@@ -102,10 +102,5 @@
 		}
 
-		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*>() ) );
+		ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin, std::list<Expression*>() ) );
 
 		UntypedExpr *cond = new UntypedExpr( cmp );
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision fa463f18d6d521f0c6ade52d2a5106d42a026733)
+++ src/SynTree/Expression.cc	(revision c8dfcd3a4ea472775bb425585268096226f404ce)
@@ -358,5 +358,4 @@
 	assert( member );
 	os << std::string( indent + 2, ' ' );
-	os << (void*)member << " ";
 	member->print( os, indent + 2 );
 	os << std::endl;
Index: src/SynTree/Statement.h
===================================================================
--- src/SynTree/Statement.h	(revision fa463f18d6d521f0c6ade52d2a5106d42a026733)
+++ src/SynTree/Statement.h	(revision c8dfcd3a4ea472775bb425585268096226f404ce)
@@ -47,4 +47,6 @@
 
 	std::list<Statement*>& get_kids() { return kids; }
+	void push_back( Statement * stmt ) { kids.push_back( stmt ); }
+	void push_front( Statement * stmt ) { kids.push_front( stmt ); }
 
 	virtual CompoundStmt *clone() const { return new CompoundStmt( *this ); }
