Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/CodeGen/CodeGenerator.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -148,4 +148,6 @@
 	void CodeGenerator::visit( ObjectDecl * objectDecl ) {
 		extension( objectDecl );
+		genAttributes( objectDecl->get_attributes() );
+
 		handleStorageClass( objectDecl );
 		output << genType( objectDecl->get_type(), mangleName( objectDecl ) );
@@ -271,9 +273,9 @@
 		printDesignators( init->get_designators() );
 		output << "{ ";
-		if ( init->begin_initializers() == init->end_initializers() ) {
+		if ( init->begin() == init->end() ) {
 			// 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() );
+			genCommaList( init->begin(), init->end() );
 		} // if
 		output << " }";
Index: src/GenPoly/DeclMutator.h
===================================================================
--- src/GenPoly/DeclMutator.h	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/GenPoly/DeclMutator.h	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -28,7 +28,10 @@
 	class DeclMutator : public Mutator {
 	public:
+		typedef Mutator Parent;
+
 		DeclMutator();
 		virtual ~DeclMutator();
-		
+
+		using Parent::mutate;
 		virtual CompoundStmt* mutate(CompoundStmt *compoundStmt);
 		virtual Statement* mutate(IfStmt *ifStmt);
@@ -42,5 +45,5 @@
 		/// Mutates a list of declarations with this visitor
 		void mutateDeclarationList(std::list< Declaration* >& decls);
-		
+
 		/// Called on entry to a new scope; overriders should call this as a super-class call
 		virtual void doBeginScope();
Index: src/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/GenPoly/Specialize.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -31,4 +31,5 @@
 #include "Common/UniqueName.h"
 #include "Common/utility.h"
+#include "InitTweak/InitTweak.h"
 
 namespace GenPoly {
@@ -184,10 +185,13 @@
 		mutateAll( appExpr->get_args(), *this );
 
-		// create thunks for the inferred parameters
-		for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
-			inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() );
-		}
-
-		handleExplicitParams( appExpr );
+		if ( ! InitTweak::isIntrinsicCallExpr( appExpr ) ) {
+			// create thunks for the inferred parameters
+			// don't need to do this for intrinsic calls, because they aren't actually passed
+			for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
+				inferParam->second.expr = doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() );
+			}
+
+			handleExplicitParams( appExpr );
+		}
 
 		return appExpr;
Index: src/InitTweak/FixGlobalInit.cc
===================================================================
--- src/InitTweak/FixGlobalInit.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/InitTweak/FixGlobalInit.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -46,47 +46,4 @@
 		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;
-		} // if
-		// for all intents and purposes, no initializer means const expr
-		return true;
-	}
 
 	void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ) {
@@ -140,6 +97,4 @@
 		std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
 
-		if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects
-		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
@@ -147,22 +102,27 @@
 		// if ( isConstExpr( objDecl->get_init() ) ) return;
 
-		if ( 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 ) );
+		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() );
 
-			// 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 ImplicitCtorDtorStmt( 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 ImplicitCtorDtorStmt( new ExprStmt( noLabels, destroy ) ) );
+			Statement * dtor = ctorInit->get_dtor();
+			if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
+				// don't need to call intrinsic dtor, because it does nothing, but
+				// non-intrinsic dtors must be called
+				destroyStatements.push_front( dtor );
+				ctorInit->set_dtor( NULL );
+			} // if
+			if ( Statement * ctor = ctorInit->get_ctor() ) {
+				initStatements.push_back( ctor );
+				objDecl->set_init( NULL );
+				ctorInit->set_ctor( NULL );
+			} 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 );
+			} // if
+			delete ctorInit;
 		} // if
 	}
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/InitTweak/FixInit.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -18,6 +18,7 @@
 #include <iterator>
 #include <algorithm>
+#include "InitTweak.h"
 #include "FixInit.h"
-#include "InitTweak.h"
+#include "FixGlobalInit.h"
 #include "ResolvExpr/Resolver.h"
 #include "ResolvExpr/typeops.h"
@@ -25,4 +26,5 @@
 #include "SynTree/Type.h"
 #include "SynTree/Expression.h"
+#include "SynTree/Attribute.h"
 #include "SynTree/Statement.h"
 #include "SynTree/Initializer.h"
@@ -83,4 +85,5 @@
 		};
 
+		// debug
 		struct printSet {
 			typedef ObjDeclCollector::ObjectSet ObjectSet;
@@ -159,4 +162,6 @@
 
 			virtual DeclarationWithType * mutate( ObjectDecl *objDecl );
+
+			std::list< Declaration * > staticDtorDecls;
 		};
 
@@ -171,5 +176,8 @@
 	} // namespace
 
-	void fix( std::list< Declaration * > & translationUnit ) {
+	void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) {
+		// fixes ConstructorInit for global variables. should happen before fixInitializers.
+		InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
+
 		InsertImplicitCalls::insert( translationUnit );
 		ResolveCopyCtors::resolveImplicitCalls( translationUnit );
@@ -194,5 +202,19 @@
 		void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) {
 			FixInit fixer;
-			mutateAll( translationUnit, fixer );
+
+			// can't use mutateAll, because need to insert declarations at top-level
+			// can't use DeclMutator, because sometimes need to insert IfStmt, etc.
+			SemanticError errors;
+			for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
+				try {
+					*i = maybeMutate( *i, fixer );
+					translationUnit.splice( i, fixer.staticDtorDecls );
+				} catch( SemanticError &e ) {
+					errors.append( e );
+				} // try
+			} // for
+			if ( ! errors.isEmpty() ) {
+				throw errors;
+			} // if
 		}
 
@@ -422,16 +444,27 @@
 				if ( Statement * ctor = ctorInit->get_ctor() ) {
 					if ( objDecl->get_storageClass() == DeclarationNode::Static ) {
+						// originally wanted to take advantage of gcc nested functions, but
+						// we get memory errors with this approach. To remedy this, the static
+						// variable is hoisted when the destructor needs to be called.
+						//
 						// generate:
-						// static bool __objName_uninitialized = true;
-						// if (__objName_uninitialized) {
-						//   __ctor(__objName);
-						//   void dtor_atexit() {
-						//     __dtor(__objName);
+						// static T __objName_static_varN;
+						// void __objName_dtor_atexitN() {
+						//   __dtor__...;
+						// }
+						// int f(...) {
+						//   ...
+						//   static bool __objName_uninitialized = true;
+						//   if (__objName_uninitialized) {
+						//     __ctor(__objName);
+						//     __objName_uninitialized = false;
+						//     atexit(__objName_dtor_atexitN);
 						//   }
-						//   on_exit(dtorOnExit, &__objName);
-						//   __objName_uninitialized = false;
+						//   ...
 						// }
 
-						// generate first line
+						static UniqueName dtorCallerNamer( "_dtor_atexit" );
+
+						// static bool __objName_uninitialized = true
 						BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool );
 						SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators );
@@ -439,13 +472,4 @@
 						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()->clone() );
-
-						// 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( "?=?" ) );
@@ -457,6 +481,4 @@
 						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 ) );
 
@@ -465,4 +487,43 @@
 						stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) );
 						stmtsToAddAfter.push_back( ifStmt );
+
+						if ( ctorInit->get_dtor() ) {
+							// if the object has a non-trivial destructor, have to
+							// hoist it and the object into the global space and
+							// call the destructor function with atexit.
+
+							Statement * dtorStmt = ctorInit->get_dtor()->clone();
+
+							// void __objName_dtor_atexitN(...) {...}
+							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 );
+
+							// atexit(dtor_atexit);
+							UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );
+							callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
+
+							body.push_back( new ExprStmt( noLabels, callAtexit ) );
+
+							// hoist variable and dtor caller decls to list of decls that will be added into global scope
+							staticDtorDecls.push_back( objDecl );
+							staticDtorDecls.push_back( dtorCaller );
+
+							// need to rename object uniquely since it now appears
+							// at global scope and there could be multiple function-scoped
+							// static variables with the same name in different functions.
+							static UniqueName staticNamer( "_static_var" );
+							objDecl->set_mangleName( objDecl->get_mangleName() + staticNamer.newName() );
+
+							objDecl->set_init( NULL );
+							ctorInit->set_ctor( NULL );
+							delete ctorInit;
+
+							// xxx - temporary hack: need to return a declaration, but want to hoist the current object out of this scope
+							// create a new object which is never used
+							static UniqueName dummyNamer( "_dummy" );
+							ObjectDecl * dummy = new ObjectDecl( dummyNamer.newName(), DeclarationNode::Static, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), 0, std::list< Attribute * >{ new Attribute("unused") } );
+							return dummy;
+						}
 					} else {
 						stmtsToAddAfter.push_back( ctor );
@@ -524,5 +585,5 @@
 					assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
 					Statement * dtor = ctorInit->get_dtor();
-					if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) {
+					if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
 						// don't need to call intrinsic dtor, because it does nothing, but
 						// non-intrinsic dtors must be called
Index: src/InitTweak/FixInit.h
===================================================================
--- src/InitTweak/FixInit.h	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/InitTweak/FixInit.h	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -27,5 +27,5 @@
   /// replace constructor initializers with expression statements
   /// and unwrap basic C-style initializers
-	void fix( std::list< Declaration * > & translationUnit );
+	void fix( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary );
 } // namespace
 
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/InitTweak/GenInit.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -26,4 +26,5 @@
 #include "SymTab/Autogen.h"
 #include "GenPoly/PolyMutator.h"
+#include "GenPoly/DeclMutator.h"
 
 namespace InitTweak {
@@ -55,28 +56,57 @@
 	  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
+		/// the actual call statements will be added in after the resolver has run
+		/// so that the initializer expression is only removed if a constructor is found
+		/// and the same destructor call is inserted in all of the appropriate locations.
 		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 );
+		// should not traverse into any of these declarations to find objects
+		// that need to be constructed or destructed
+		virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
+		virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
+		virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
+		virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }
+		virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; }
+		virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; }
+
+		virtual Type * mutate( FunctionType *funcType ) { return funcType; }
 
 	  protected:
-		bool inFunction;
+	};
+
+	class HoistArrayDimension : public GenPoly::DeclMutator {
+	  public:
+		typedef GenPoly::DeclMutator Parent;
+
+		/// hoist dimension from array types in object declaration so that it uses a single
+		/// const variable of type size_t, so that side effecting array dimensions are only
+		/// computed once.
+		static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
+
+	  private:
+		virtual DeclarationWithType * mutate( ObjectDecl * objectDecl );
+		virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
+		// should not traverse into any of these declarations to find objects
+		// that need to be constructed or destructed
+		virtual Declaration* mutate( StructDecl *aggregateDecl ) { return aggregateDecl; }
+		virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
+		virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
+		virtual Declaration* mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; }
+		virtual TypeDecl* mutate( TypeDecl *typeDecl ) { return typeDecl; }
+		virtual Declaration* mutate( TypedefDecl *typeDecl ) { return typeDecl; }
+
+		virtual Type* mutate( FunctionType *funcType ) { return funcType; }
+
+		void hoist( Type * type );
+
+		DeclarationNode::StorageClass storageclass = DeclarationNode::NoStorageClass;
+		bool inFunction = false;
 	};
 
 	void genInit( std::list< Declaration * > & translationUnit ) {
 		ReturnFixer::makeReturnTemp( translationUnit );
+		HoistArrayDimension::hoistArrayDimension( translationUnit );
 		CtorDtor::generateCtorDtor( translationUnit );
 	}
@@ -124,4 +154,53 @@
 	}
 
+	// precompute array dimension expression, because constructor generation may duplicate it,
+	// which would be incorrect if it is a side-effecting computation.
+	void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
+		HoistArrayDimension hoister;
+		hoister.mutateDeclarationList( translationUnit );
+	}
+
+	DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) {
+		storageclass = objectDecl->get_storageClass();
+		DeclarationWithType * temp = Parent::mutate( objectDecl );
+		hoist( objectDecl->get_type() );
+		storageclass = DeclarationNode::NoStorageClass;
+		return temp;
+	}
+
+	void HoistArrayDimension::hoist( Type * type ) {
+		// if in function, generate const size_t var
+		static UniqueName dimensionName( "_array_dim" );
+
+		// C doesn't allow variable sized arrays at global scope or for static variables,
+		// so don't hoist dimension.
+		if ( ! inFunction ) return;
+		if ( storageclass == DeclarationNode::Static ) return;
+
+		if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
+			if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
+
+			// don't need to hoist dimension if it's a constexpr - only need to if there's potential
+			// for side effects.
+			if ( isConstExpr( arrayType->get_dimension() ) ) return;
+
+			ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageclass, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
+			arrayDimension->get_type()->set_isConst( true );
+
+			arrayType->set_dimension( new VariableExpr( arrayDimension ) );
+			addDeclaration( arrayDimension );
+
+			hoist( arrayType->get_base() );
+			return;
+		}
+	}
+
+	DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {
+		bool oldInFunc = inFunction;
+		inFunction = true;
+		DeclarationWithType * decl = Parent::mutate( functionDecl );
+		inFunction = oldInFunc;
+		return decl;
+	}
 
 	void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
@@ -130,60 +209,34 @@
 	}
 
-	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 @=
+		// hands off if designated, if @=, or if extern
 		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 && dynamic_cast< ImplicitCtorDtorStmt * >( ctor.front() ) );
-						assert( dtor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( dtor.front() ) );
-						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( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) );
-				}
+			// call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
+			// for each constructable object
+			std::list< Statement * > ctor;
+			std::list< Statement * > dtor;
+
+			InitExpander srcParam( objDecl->get_init() );
+			InitExpander nullParam( (Initializer *)NULL );
+			SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
+			SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
+
+			// Currently genImplicitCall 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 genImplicitCall
+			// itself. It is possible that genImplicitCall produces no statements (e.g. if
+			// an array type does not have a dimension). In this case, it's fine to ignore
+			// the object for the purposes of construction.
+			assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
+			if ( ctor.size() == 1 ) {
+				// 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
+				assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
+				objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
 			}
 		}
@@ -193,22 +246,8 @@
 	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
 
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/InitTweak/InitTweak.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -1,2 +1,3 @@
+#include <algorithm>
 #include "InitTweak.h"
 #include "SynTree/Visitor.h"
@@ -4,4 +5,5 @@
 #include "SynTree/Initializer.h"
 #include "SynTree/Expression.h"
+#include "SynTree/Attribute.h"
 #include "GenPoly/GenPoly.h"
 
@@ -20,7 +22,6 @@
 		};
 
-		class InitExpander : public Visitor {
+		class InitFlattener : public Visitor {
 			public:
-			InitExpander() {}
 			virtual void visit( SingleInit * singleInit );
 			virtual void visit( ListInit * listInit );
@@ -28,12 +29,12 @@
 		};
 
-		void InitExpander::visit( SingleInit * singleInit ) {
+		void InitFlattener::visit( SingleInit * singleInit ) {
 			argList.push_back( singleInit->get_value()->clone() );
 		}
 
-		void InitExpander::visit( ListInit * listInit ) {
-			// xxx - for now, assume no nested list inits
-			std::list<Initializer*>::iterator it = listInit->begin_initializers();
-			for ( ; it != listInit->end_initializers(); ++it ) {
+		void InitFlattener::visit( ListInit * listInit ) {
+			// flatten nested list inits
+			std::list<Initializer*>::iterator it = listInit->begin();
+			for ( ; it != listInit->end(); ++it ) {
 				(*it)->accept( *this );
 			}
@@ -42,7 +43,7 @@
 
 	std::list< Expression * > makeInitList( Initializer * init ) {
-		InitExpander expander;
-		maybeAccept( init, expander );
-		return expander.argList;
+		InitFlattener flattener;
+		maybeAccept( init, flattener );
+		return flattener.argList;
 	}
 
@@ -53,48 +54,254 @@
 	}
 
+	class InitExpander::ExpanderImpl {
+	public:
+		virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0;
+		virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0;
+	};
+
+	class InitImpl : public InitExpander::ExpanderImpl {
+	public:
+		InitImpl( Initializer * init ) : init( init ) {}
+
+		virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
+			// this is wrong, but just a placeholder for now
+			// if ( ! flattened ) flatten( indices );
+			// return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >();
+			return makeInitList( init );
+		}
+
+		virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
+	private:
+		Initializer * init;
+	};
+
+	class ExprImpl : public InitExpander::ExpanderImpl {
+	public:
+		ExprImpl( Expression * expr ) : arg( expr ) {}
+
+		virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
+			std::list< Expression * > ret;
+			Expression * expr = maybeClone( arg );
+			if ( expr ) {
+				for ( std::list< Expression * >::reverse_iterator it = indices.rbegin(); it != indices.rend(); ++it ) {
+					// go through indices and layer on subscript exprs ?[?]
+					++it;
+					UntypedExpr * subscriptExpr = new UntypedExpr( new NameExpr( "?[?]") );
+					subscriptExpr->get_args().push_back( expr );
+					subscriptExpr->get_args().push_back( (*it)->clone() );
+					expr = subscriptExpr;
+				}
+				ret.push_back( expr );
+			}
+			return ret;
+		}
+
+		virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
+	private:
+		Expression * arg;
+	};
+
+	InitExpander::InitExpander( Initializer * init ) : expander( new InitImpl( init ) ) {}
+
+	InitExpander::InitExpander( Expression * expr ) : expander( new ExprImpl( expr ) ) {}
+
+	std::list< Expression * > InitExpander::operator*() {
+		return cur;
+	}
+
+	InitExpander & InitExpander::operator++() {
+		cur = expander->next( indices );
+		return *this;
+	}
+
+	// use array indices list to build switch statement
+	void InitExpander::addArrayIndex( Expression * index, Expression * dimension ) {
+		indices.push_back( index );
+		indices.push_back( dimension );
+	}
+
+	void InitExpander::clearArrayIndices() {
+		indices.clear();
+	}
+
+	namespace {
+		/// given index i, dimension d, initializer init, and callExpr f, generates
+		///   if (i < d) f(..., init)
+		///   ++i;
+		/// so that only elements within the range of the array are constructed
+		template< typename OutIterator >
+		void buildCallExpr( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {
+			UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
+			cond->get_args().push_back( index->clone() );
+			cond->get_args().push_back( dimension->clone() );
+
+			std::list< Expression * > args = makeInitList( init );
+			callExpr->get_args().splice( callExpr->get_args().end(), args );
+
+			*out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL );
+
+			UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
+			increment->get_args().push_back( new AddressExpr( index->clone() ) );
+			*out++ = new ExprStmt( noLabels, increment );
+		}
+
+		template< typename OutIterator >
+		void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
+			if ( idx == idxEnd ) return;
+			Expression * index = *idx++;
+			assert( idx != idxEnd );
+			Expression * dimension = *idx++;
+
+			// xxx - may want to eventually issue a warning here if we can detect
+			// that the number of elements exceeds to dimension of the array
+			if ( idx == idxEnd ) {
+				if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) {
+					for ( Initializer * init : *listInit ) {
+						buildCallExpr( callExpr->clone(), index, dimension, init, out );
+					}
+				} else {
+					buildCallExpr( callExpr->clone(), index, dimension, init, out );
+				}
+			} else {
+				std::list< Statement * > branches;
+
+				unsigned long cond = 0;
+				ListInit * listInit = dynamic_cast< ListInit * >( init );
+				if ( ! listInit ) {
+					// xxx - this shouldn't be an error, but need a way to
+					// terminate without creating output, so should catch this error
+					throw SemanticError( "unbalanced list initializers" );
+				}
+
+				static UniqueName targetLabel( "L__autogen__" );
+				Label switchLabel( targetLabel.newName(), 0, std::list< Attribute * >{ new Attribute("unused") } );
+				for ( Initializer * init : *listInit ) {
+					Expression * condition;
+					// check for designations
+					// if ( init-> ) {
+						condition = new ConstantExpr( Constant::from_ulong( cond ) );
+						++cond;
+					// } else {
+					// 	condition = // ... take designation
+					// 	cond = // ... take designation+1
+					// }
+					std::list< Statement * > stmts;
+					build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
+					stmts.push_back( new BranchStmt( noLabels, switchLabel, BranchStmt::Break ) );
+					CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
+					branches.push_back( caseStmt );
+				}
+				*out++ = new SwitchStmt( noLabels, index->clone(), branches );
+				*out++ = new NullStmt( std::list<Label>{ switchLabel } );
+			}
+		}
+	}
+
+	// if 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.
+	// may have fewer initializers than elements in the array - need to default construct
+	// remaining elements.
+	// To accomplish this, generate switch statement, consuming all of expander's elements
+	Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
+		if ( ! init ) return NULL;
+		CompoundStmt * block = new CompoundStmt( noLabels );
+		build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
+		if ( block->get_kids().empty() ) {
+			delete block;
+			return NULL;
+		} else {
+			init = NULL; // init was consumed in creating the list init
+			return block;
+		}
+	}
+
+	Statement * ExprImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
+		return NULL;
+	}
+
+	Statement * InitExpander::buildListInit( UntypedExpr * dst ) {
+		return expander->buildListInit( dst, indices );
+	}
+
 	bool tryConstruct( ObjectDecl * objDecl ) {
 		return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
 			(objDecl->get_init() == NULL ||
 				( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
-			! isDesignated( objDecl->get_init() );
+			! isDesignated( objDecl->get_init() )
+			&& objDecl->get_storageClass() != DeclarationNode::Extern;
+	}
+
+	class CallFinder : public Visitor {
+	public:
+		typedef Visitor Parent;
+		CallFinder( const std::list< std::string > & names ) : names( names ) {}
+
+		virtual void visit( ApplicationExpr * appExpr ) {
+			handleCallExpr( appExpr );
+		}
+
+		virtual void visit( UntypedExpr * untypedExpr ) {
+			handleCallExpr( untypedExpr );
+		}
+
+		std::list< Expression * > * matches;
+	private:
+		const std::list< std::string > names;
+
+		template< typename CallExpr >
+		void handleCallExpr( CallExpr * expr ) {
+			Parent::visit( expr );
+			std::string fname = getFunctionName( expr );
+			if ( std::find( names.begin(), names.end(), fname ) != names.end() ) {
+				matches->push_back( expr );
+			}
+		}
+	};
+
+	void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
+		static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } );
+		finder.matches = &matches;
+		maybeAccept( stmt, finder );
 	}
 
 	Expression * getCtorDtorCall( Statement * stmt ) {
-		if ( stmt == NULL ) return NULL;
-		if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
-			return exprStmt->get_expr();
-		} else if ( CompoundStmt * compoundStmt = dynamic_cast< CompoundStmt * >( stmt ) ) {
-			// could also be a compound statement with a loop, in the case of an array
-			if( compoundStmt->get_kids().size() == 2 ) {
-				// loop variable and loop
-				ForStmt * forStmt = dynamic_cast< ForStmt * >( compoundStmt->get_kids().back() );
-				assert( forStmt && forStmt->get_body() );
-				return getCtorDtorCall( forStmt->get_body() );
-			} else if ( compoundStmt->get_kids().size() == 1 ) {
-				// should be the call statement, but in any case there's only one option
-				return getCtorDtorCall( compoundStmt->get_kids().front() );
-			} else {
-				assert( false && "too many statements in compoundStmt for getCtorDtorCall" );
-			}
-		} if ( ImplicitCtorDtorStmt * impCtorDtorStmt = dynamic_cast< ImplicitCtorDtorStmt * > ( stmt ) ) {
-			return getCtorDtorCall( impCtorDtorStmt->get_callStmt() );
-		} else {
-			// should never get here
-			assert( false && "encountered unknown call statement" );
-		}
-	}
-
-	bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
-		Expression * callExpr = getCtorDtorCall( stmt );
-		if ( ! callExpr ) return false;
-		ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr );
-		assert( appExpr );
-		VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
+		std::list< Expression * > matches;
+		collectCtorDtorCalls( stmt, matches );
+		assert( matches.size() <= 1 );
+		return matches.size() == 1 ? matches.front() : NULL;
+	}
+
+	namespace {
+		VariableExpr * getCalledFunction( ApplicationExpr * appExpr ) {
+			assert( appExpr );
+			// xxx - it's possible this can be other things, e.g. MemberExpr, so this is insufficient
+			return dynamic_cast< VariableExpr * >( appExpr->get_function() );
+		}
+	}
+
+	ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
+		ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
+		if ( ! appExpr ) return NULL;
+		VariableExpr * function = getCalledFunction( appExpr );
 		assert( function );
 		// check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
 		// will call all member dtors, and some members may have a user defined dtor.
-		FunctionType * funcType = GenPoly::getFunctionType( function->get_var()->get_type() );
-		assert( funcType );
-		return function->get_var()->get_linkage() == LinkageSpec::Intrinsic && funcType->get_parameters().size() == 1;
+		return function->get_var()->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL;
+	}
+
+	bool isIntrinsicSingleArgCallStmt( Statement * stmt ) {
+		std::list< Expression * > callExprs;
+		collectCtorDtorCalls( stmt, callExprs );
+		// if ( callExprs.empty() ) return false; // xxx - do I still need this check?
+		return std::all_of( callExprs.begin(), callExprs.end(), []( Expression * callExpr ){
+			if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
+				assert( ! appExpr->get_function()->get_results().empty() );
+				FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() );
+				assert( funcType );
+				return funcType->get_parameters().size() == 1;
+			}
+			return false;
+		});
 	}
 
@@ -160,3 +367,56 @@
 		else return NULL;
 	}
+
+	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( Expression * expr ) {
+		if ( expr ) {
+			ConstExprChecker checker;
+			expr->accept( checker );
+			return checker.isConstExpr;
+		}
+		return true;
+	}
+
+	bool isConstExpr( Initializer * init ) {
+		if ( init ) {
+			ConstExprChecker checker;
+			init->accept( checker );
+			return checker.isConstExpr;
+		} // if
+		// for all intents and purposes, no initializer means const expr
+		return true;
+	}
+
 }
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/InitTweak/InitTweak.h	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -26,32 +26,70 @@
 // helper functions for initialization
 namespace InitTweak {
-  /// transform Initializer into an argument list that can be passed to a call expression
-  std::list< Expression * > makeInitList( Initializer * init );
+	/// transform Initializer into an argument list that can be passed to a call expression
+	std::list< Expression * > makeInitList( Initializer * init );
 
-  /// True if the resolver should try to construct objDecl
-  bool tryConstruct( ObjectDecl * objDecl );
+	/// True if the resolver should try to construct objDecl
+	bool tryConstruct( ObjectDecl * objDecl );
 
-  /// True if the Initializer contains designations
-  bool isDesignated( Initializer * init );
+	/// True if the Initializer contains designations
+	bool isDesignated( Initializer * init );
 
-  /// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
-  /// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
-  /// Currently has assertions that make it less than fully general.
-  bool isInstrinsicSingleArgCallStmt( Statement * expr );
+  /// Non-Null if expr is a call expression whose target function is intrinsic
+  ApplicationExpr * isIntrinsicCallExpr( Expression * expr );
 
-  /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
-  Expression * getCtorDtorCall( Statement * stmt );
+	/// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
+	/// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
+	/// Currently has assertions that make it less than fully general.
+	bool isIntrinsicSingleArgCallStmt( Statement * expr );
 
-  /// returns the name of the function being called
-  std::string getFunctionName( Expression * expr );
+	/// get all Ctor/Dtor call expressions from a Statement
+	void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
 
-  /// returns the argument to a call expression in position N indexed from 0
-  Expression *& getCallArg( Expression * callExpr, unsigned int pos );
+	/// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
+	Expression * getCtorDtorCall( Statement * stmt );
 
-  /// returns the base type of a PointerType or ArrayType, else returns NULL
-  Type * getPointerBase( Type * );
+	/// returns the name of the function being called
+	std::string getFunctionName( Expression * expr );
 
-  /// returns the argument if it is a PointerType or ArrayType, else returns NULL
-  Type * isPointerType( Type * );
+	/// returns the argument to a call expression in position N indexed from 0
+	Expression *& getCallArg( Expression * callExpr, unsigned int pos );
+
+	/// returns the base type of a PointerType or ArrayType, else returns NULL
+	Type * getPointerBase( Type * );
+
+	/// returns the argument if it is a PointerType or ArrayType, else returns NULL
+	Type * isPointerType( Type * );
+
+	/// returns true if expr is trivially a compile-time constant
+	bool isConstExpr( Expression * expr );
+	bool isConstExpr( Initializer * init );
+
+	class InitExpander {
+	public:
+		// expand by stepping through init to get each list of arguments
+		InitExpander( Initializer * init );
+
+		// always expand to expr
+		InitExpander( Expression * expr );
+
+		// iterator-like interface
+		std::list< Expression * > operator*();
+		InitExpander & operator++();
+
+		// builds statement which has the same semantics as a C-style list initializer
+		// (for array initializers) using callExpr as the base expression to perform initialization
+		Statement * buildListInit( UntypedExpr * callExpr );
+		void addArrayIndex( Expression * index, Expression * dimension );
+		void clearArrayIndices();
+
+		class ExpanderImpl;
+	private:
+		std::shared_ptr< ExpanderImpl > expander;
+		std::list< Expression * > cur;
+
+		// invariant: list of size 2N (elements come in pairs [index, dimension])
+		typedef std::list< Expression * > IndexList;
+		IndexList indices;
+	};
 } // namespace
 
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/Parser/TypeData.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -510,5 +510,5 @@
 		return buildVariable();
 	} else {
-		return new ObjectDecl( name, sc, linkage, bitfieldWidth, build(), init, isInline, isNoreturn );
+		return new ObjectDecl( name, sc, linkage, bitfieldWidth, build(), init, std::list< Attribute * >(),  isInline, isNoreturn );
 	} // if
 	return 0;
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/ResolvExpr/Resolver.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -24,4 +24,5 @@
 #include "SynTree/Initializer.h"
 #include "SymTab/Indexer.h"
+#include "SymTab/Autogen.h"
 #include "Common/utility.h"
 #include "InitTweak/InitTweak.h"
@@ -41,4 +42,5 @@
 
 		virtual void visit( ArrayType * at );
+		virtual void visit( PointerType * at );
 
 		virtual void visit( ExprStmt *exprStmt );
@@ -52,5 +54,4 @@
 		virtual void visit( BranchStmt *branchStmt );
 		virtual void visit( ReturnStmt *returnStmt );
-		virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt );
 
 		virtual void visit( SingleInit *singleInit );
@@ -59,4 +60,7 @@
 	  private:
   	typedef std::list< Initializer * >::iterator InitIterator;
+
+		template< typename PtrType >
+		void handlePtrType( PtrType * type );
 
 	  void resolveAggrInit( AggregateDecl *, InitIterator &, InitIterator & );
@@ -192,13 +196,22 @@
 	}
 
+	template< typename PtrType >
+	void Resolver::handlePtrType( PtrType * type ) {
+		if ( type->get_dimension() ) {
+			CastExpr *castExpr = new CastExpr( type->get_dimension(), SymTab::SizeType->clone() );
+			Expression *newExpr = findSingleExpression( castExpr, *this );
+			delete type->get_dimension();
+			type->set_dimension( newExpr );
+		}
+	}
+
 	void Resolver::visit( ArrayType * at ) {
-		if ( at->get_dimension() ) {
-			BasicType arrayLenType = BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
-			CastExpr *castExpr = new CastExpr( at->get_dimension(), arrayLenType.clone() );
-			Expression *newExpr = findSingleExpression( castExpr, *this );
-			delete at->get_dimension();
-			at->set_dimension( newExpr );
-		}
+		handlePtrType( at );
 		Visitor::visit( at );
+	}
+
+	void Resolver::visit( PointerType * pt ) {
+		handlePtrType( pt );
+		Visitor::visit( pt );
 	}
 
@@ -422,6 +435,6 @@
 
 	void Resolver::visit( ListInit * listInit ) {
-		InitIterator iter = listInit->begin_initializers();
-		InitIterator end = listInit->end_initializers();
+		InitIterator iter = listInit->begin();
+		InitIterator end = listInit->end();
 
 		if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) {
@@ -521,54 +534,19 @@
 		// 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() ) ) {
+		if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
 			delete ctorInit->get_ctor();
 			ctorInit->set_ctor( NULL );
 		}
-		if ( InitTweak::isInstrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
+
+		// xxx - todo
+		// if ( InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
+		// 	// can reduce the constructor down to a SingleInit using the
+		// 	// second argument from the ctor call
+		// }
+
+		if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->get_dtor() ) ) {
 			delete ctorInit->get_dtor();
 			ctorInit->set_dtor( NULL );
 		}
-	}
-
-	void Resolver::visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) {
-		// before resolving ctor/dtor, need to remove type qualifiers from the first argument (the object being constructed).
-		// Do this through a cast expression to greatly simplify the code.
-		Expression * callExpr = InitTweak::getCtorDtorCall( impCtorDtorStmt );
-		assert( callExpr );
-		Expression *& constructee = InitTweak::getCallArg( callExpr, 0 );
-		Type * type = 0;
-
-		// need to find the type of the first argument, which is unfortunately not uniform since array construction
-		// includes an untyped '+' expression.
-		if ( UntypedExpr * plusExpr = dynamic_cast< UntypedExpr * >( constructee ) ) {
-			// constructee is <array>+<index>
-			// get Variable <array>, then get the base type of the VariableExpr - this is the type that needs to be fixed
-			Expression * arr = InitTweak::getCallArg( plusExpr, 0 );
-			assert( dynamic_cast< VariableExpr * >( arr ) || dynamic_cast< MemberExpr *>( arr ) );
-			assert( arr && arr->get_results().size() == 1 );
-			type = arr->get_results().front()->clone();
-		} else {
-			// otherwise, constructing a plain object, which means the object's address is being taken.
-			// Need to get the type of the VariableExpr object, because the AddressExpr is rebuilt and uses the
-			// type of the VariableExpr to do so.
-			assert( constructee->get_results().size() == 1 );
-			AddressExpr * addrExpr = dynamic_cast< AddressExpr * > ( constructee );
-			assert( addrExpr && addrExpr->get_results().size() == 1 );
-			type = addrExpr->get_results().front()->clone();
-		}
-		// cast to T* with qualifiers removed.
-		// unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
-		// must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
-		// remove lvalue as a qualifier, this can change to
-		//   type->get_qualifiers() = Type::Qualifiers();
-		Type * base = InitTweak::getPointerBase( type );
-		assert( base );
-		base->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
-		// if pointer has lvalue qualifier, cast won't appear in output
-		type->set_isLvalue( false );
-		constructee = new CastExpr( constructee, type );
-
-		// finally, resolve the ctor/dtor
-		impCtorDtorStmt->get_callStmt()->accept( *this );
 	}
 } // namespace ResolvExpr
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/SymTab/Autogen.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -26,4 +26,6 @@
 
 namespace SymTab {
+	Type * SizeType = 0;
+
 	class AutogenerateRoutines : public Visitor {
 		public:
@@ -59,36 +61,4 @@
 	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 );
-		}
-
-		Statement * callStmt = new ExprStmt( noLabels, fExpr );
-		if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ) ) {
-			// implicitly generated ctor/dtor calls should be wrapped
-			// so that later passes are aware they were generated.
-			// xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
-			// because this causes the address to be taken at codegen, which is illegal in C.
-			callStmt = new ImplicitCtorDtorStmt( callStmt );
-		}
-		*out++ = callStmt;
 	}
 
@@ -219,21 +189,17 @@
 		}
 
+		InitTweak::InitExpander srcParam( src );
+
 		// 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() ) );
+		UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
+		derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
+		Expression *dstselect = new MemberExpr( field, derefExpr );
+		genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
+
+		if ( isGeneric && returnVal ) {
+			UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
+			derefRet->get_args().push_back( new VariableExpr( returnVal ) );
+			Expression *retselect = new MemberExpr( field, derefRet );
+			genImplicitCall( srcParam, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
 		} // if
 	}
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/SymTab/Autogen.h	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -22,82 +22,160 @@
 #include "SynTree/Declaration.h"
 #include "SynTree/Initializer.h"
+#include "InitTweak/InitTweak.h"
 
 namespace SymTab {
-  /// Generates assignment operators, constructors, and destructor for aggregate types as required
-  void autogenerateRoutines( std::list< Declaration * > &translationUnit );
+	/// 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
+	/// returns true if obj's name is the empty string and it has a bitfield width
+	bool isUnnamedBitfield( ObjectDecl * obj );
 
-  /// 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" );
+	/// size_t type - set when size_t typedef is seen. Useful in a few places,
+	/// such as in determining array dimension type
+	extern Type * SizeType;
 
-    // for a flexible array member nothing is done -- user must define own assignment
-    if ( ! array->get_dimension() ) return;
+	/// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
+	template< typename OutputIterator >
+	Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false, bool forward = true );
 
-    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( "--?" );
-    }
+	/// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
+	/// optionally returns a statement which must be inserted prior to the containing loop, if there is one
+	template< typename OutputIterator >
+	Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
+		// want to be able to generate assignment, ctor, and dtor generically,
+		// so fname is either ?=?, ?{}, or ^?{}
+		UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
 
-    ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
+		// do something special for unnamed members
+		dstParam = new AddressExpr( dstParam );
+		if ( addCast ) {
+			// cast to T* with qualifiers removed, so that qualified objects can be constructed
+			// and destructed with the same functions as non-qualified objects.
+			// unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
+			// must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
+			// remove lvalue as a qualifier, this can change to
+			//   type->get_qualifiers() = Type::Qualifiers();
+			assert( type );
+			Type * castType = type->clone();
+			castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
+			castType->set_isLvalue( true ); // xxx - might not need this
+			dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
+		}
+		fExpr->get_args().push_back( dstParam );
 
-    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*>() ) );
+		Statement * listInit = srcParam.buildListInit( fExpr );
 
-    UntypedExpr *cond = new UntypedExpr( cmp );
-    cond->get_args().push_back( new VariableExpr( index ) );
-    cond->get_args().push_back( end );
+		std::list< Expression * > args = *++srcParam;
+		fExpr->get_args().splice( fExpr->get_args().end(), args );
 
-    UntypedExpr *inc = new UntypedExpr( update );
-    inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
+		*out++ = new ExprStmt( noLabels, fExpr );
 
-    // want to be able to generate assignment, ctor, and dtor generically,
-    // so fname is either ?=?, ?{}, or ^?{}
-    UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
+		srcParam.clearArrayIndices();
 
-    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 );
+		return listInit;
+	}
 
-    // 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 );
-    }
+	/// 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 genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, bool addCast = false, bool forward = true ) {
+		static UniqueName indexName( "_index" );
 
-    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 ) ) );
+		// for a flexible array member nothing is done -- user must define own assignment
+		if ( ! array->get_dimension() ) return ;
 
-    Statement * stmt = block;
-    if ( fname == "?{}" || fname == "^?{}" ) {
-      // implicitly generated ctor/dtor calls should be wrapped
-      // so that later passes are aware they were generated
-      stmt = new ImplicitCtorDtorStmt( stmt );
-    }
-    *out++ = stmt;
-  }
+		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 ) ) );
+
+		UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
+		dstIndex->get_args().push_back( dstParam );
+		dstIndex->get_args().push_back( new VariableExpr( index ) );
+		dstParam = dstIndex;
+
+		// srcParam must keep track of the array indices to build the
+		// source parameter and/or array list initializer
+		srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() );
+
+		// for stmt's body, eventually containing call
+		CompoundStmt * body = new CompoundStmt( noLabels );
+		Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
+
+		// block containing for stmt and index variable
+		std::list<Statement *> initList;
+		CompoundStmt * block = new CompoundStmt( noLabels );
+		block->get_kids().push_back( new DeclStmt( noLabels, index ) );
+		if ( listInit ) block->get_kids().push_back( listInit );
+		block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
+
+		*out++ = block;
+	}
+
+	template< typename OutputIterator >
+	Statement * genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
+		if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
+			genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
+			return 0;
+		} else {
+			return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
+		}
+	}
+
+	/// inserts into out a generated call expression to function fname with arguments dstParam
+	/// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
+	/// object being constructed. The function wraps constructor and destructor calls in an
+	/// ImplicitCtorDtorStmt node.
+	template< typename OutputIterator >
+	void genImplicitCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
+		ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
+		assert( obj );
+		// unnamed bit fields are not copied as they cannot be accessed
+		if ( isUnnamedBitfield( obj ) ) return;
+
+		bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) );
+		std::list< Statement * > stmts;
+		genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
+
+		// currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call
+		assert( stmts.size() <= 1 );
+		if ( stmts.size() == 1 ) {
+			Statement * callStmt = stmts.front();
+			if ( addCast ) {
+				// implicitly generated ctor/dtor calls should be wrapped
+				// so that later passes are aware they were generated.
+				// xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
+				// because this causes the address to be taken at codegen, which is illegal in C.
+				callStmt = new ImplicitCtorDtorStmt( callStmt );
+			}
+			*out++ = callStmt;
+		}
+	}
 } // namespace SymTab
 #endif // AUTOGEN_H
Index: src/SymTab/FixFunction.cc
===================================================================
--- src/SymTab/FixFunction.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/SymTab/FixFunction.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// FixFunction.cc -- 
+// FixFunction.cc --
 //
 // Author           : Richard C. Bilson
@@ -44,5 +44,6 @@
 
 	Type * FixFunction::mutate(ArrayType *arrayType) {
-		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), maybeClone( arrayType->get_base()->clone() ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
+		// need to recursively mutate the base type in order for multi-dimensional arrays to work.
+		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone()->acceptMutator( *this ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
 		delete arrayType;
 		return pointerType;
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/SymTab/Validate.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -174,5 +174,5 @@
 
 		virtual void visit( FunctionDecl *funcDecl );
-};
+	};
 
 	class CompoundLiteral : public GenPoly::DeclMutator {
@@ -191,9 +191,9 @@
 		EliminateTypedef::eliminateTypedef( translationUnit );
 		HoistStruct::hoistStruct( translationUnit );
+		autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs Pass1
 		acceptAll( translationUnit, pass1 );
 		acceptAll( translationUnit, pass2 );
 		ReturnChecker::checkFunctionReturns( translationUnit );
-		mutateAll( translationUnit, compoundliteral );
-		autogenerateRoutines( translationUnit );
+		compoundliteral.mutateDeclarationList( translationUnit );
 		acceptAll( translationUnit, pass3 );
 		VerifyCtorDtor::verify( translationUnit );
@@ -490,5 +490,14 @@
 		EliminateTypedef eliminator;
 		mutateAll( translationUnit, eliminator );
+		if ( eliminator.typedefNames.count( "size_t" ) ) {
+			// grab and remember declaration of size_t
+			SizeType = eliminator.typedefNames["size_t"].first->get_base()->clone();
+		} else {
+			// xxx - missing global typedef for size_t - default to long unsigned int, even though that may be wrong
+			// eventually should have a warning for this case.
+			SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
+		}
 		filter( translationUnit, isTypedef, true );
+
 	}
 
@@ -518,4 +527,5 @@
 	Declaration *EliminateTypedef::mutate( TypedefDecl * tyDecl ) {
 		Declaration *ret = Mutator::mutate( tyDecl );
+
 		if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
 			// typedef to the same name from the same scope
Index: src/SynTree/Declaration.cc
===================================================================
--- src/SynTree/Declaration.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/SynTree/Declaration.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Declaration.cc -- 
+// Declaration.cc --
 //
 // Author           : Richard C. Bilson
@@ -20,4 +20,5 @@
 #include "Initializer.h"
 #include "Type.h"
+#include "Attribute.h"
 #include "Common/utility.h"
 
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/SynTree/Declaration.h	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -64,5 +64,5 @@
 class DeclarationWithType : public Declaration {
   public:
-	DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage );
+	DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, const std::list< Attribute * > & attributes );
 	DeclarationWithType( const DeclarationWithType &other );
 	virtual ~DeclarationWithType();
@@ -75,4 +75,7 @@
 	int get_scopeLevel() const { return scopeLevel; }
 	void set_scopeLevel( int newValue ) { scopeLevel = newValue; }
+
+	std::list< Attribute * >& get_attributes() { return attributes; }
+	const std::list< Attribute * >& get_attributes() const { return attributes; }
 
 	virtual DeclarationWithType *clone() const = 0;
@@ -87,4 +90,6 @@
 	// shadowed identifiers can be accessed
 	int scopeLevel = 0;
+
+	std::list< Attribute * > attributes;
 };
 
@@ -92,5 +97,5 @@
 	typedef DeclarationWithType Parent;
   public:
-	ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, bool isInline = false, bool isNoreturn = false );
+	ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, const std::list< Attribute * > attributes = std::list< Attribute * >(), bool isInline = false, bool isNoreturn = false );
 	ObjectDecl( const ObjectDecl &other );
 	virtual ~ObjectDecl();
@@ -131,5 +136,4 @@
 	std::list< std::string >& get_oldIdents() { return oldIdents; }
 	std::list< Declaration* >& get_oldDecls() { return oldDecls; }
-	std::list< Attribute * >& get_attributes() { return attributes; }
 
 	virtual FunctionDecl *clone() const { return new FunctionDecl( *this ); }
@@ -143,5 +147,4 @@
 	std::list< std::string > oldIdents;
 	std::list< Declaration* > oldDecls;
-	std::list< Attribute * > attributes;
 };
 
Index: src/SynTree/DeclarationWithType.cc
===================================================================
--- src/SynTree/DeclarationWithType.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/SynTree/DeclarationWithType.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -16,15 +16,18 @@
 #include "Declaration.h"
 #include "Type.h"
+#include "Attribute.h"
 #include "Common/utility.h"
 
-DeclarationWithType::DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage )
-		: Declaration( name, sc, linkage ) {
+DeclarationWithType::DeclarationWithType( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, const std::list< Attribute * > & attributes )
+		: Declaration( name, sc, linkage ), attributes( attributes ) {
 }
 
 DeclarationWithType::DeclarationWithType( const DeclarationWithType &other )
 		: Declaration( other ), mangleName( other.mangleName ), scopeLevel( other.scopeLevel ) {
+	cloneAll( other.attributes, attributes );
 }
 
 DeclarationWithType::~DeclarationWithType() {
+	deleteAll( attributes );
 }
 
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/SynTree/Expression.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -344,10 +344,11 @@
 }
 
+//// is this right? It's cloning the member, but the member is a declaration so probably shouldn't be cloned...
 MemberExpr::MemberExpr( const MemberExpr &other ) :
-		Expression( other ), member( maybeClone( other.member ) ), aggregate( maybeClone( other.aggregate ) ) {
+		Expression( other ), member( other.member ), aggregate( maybeClone( other.aggregate ) ) {
 }
 
 MemberExpr::~MemberExpr() {
-	delete member;
+	// delete member;
 	delete aggregate;
 }
Index: src/SynTree/FunctionDecl.cc
===================================================================
--- src/SynTree/FunctionDecl.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/SynTree/FunctionDecl.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -23,5 +23,5 @@
 
 FunctionDecl::FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, std::list< Attribute * > attributes )
-		: Parent( name, sc, linkage ), type( type ), statements( statements ), attributes( attributes ) {
+		: Parent( name, sc, linkage, attributes ), type( type ), statements( statements ) {
 	set_isInline( isInline );
 	set_isNoreturn( isNoreturn );
@@ -34,5 +34,4 @@
 FunctionDecl::FunctionDecl( const FunctionDecl &other )
 	: Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ) {
-		cloneAll( other.attributes, attributes );
 }
 
@@ -40,5 +39,4 @@
 	delete type;
 	delete statements;
-	deleteAll( attributes );
 }
 
@@ -69,5 +67,5 @@
 	} // if
 
-	printAll( attributes, os, indent );
+	printAll( get_attributes(), os, indent );
 
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
Index: src/SynTree/Initializer.h
===================================================================
--- src/SynTree/Initializer.h	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/SynTree/Initializer.h	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -93,6 +93,7 @@
 	std::list<Initializer*> &get_initializers() { return initializers; }
 
-	std::list<Initializer*>::iterator begin_initializers() { return initializers.begin(); }
-	std::list<Initializer*>::iterator end_initializers() { return initializers.end(); }
+	typedef std::list<Initializer*>::iterator iterator;
+	iterator begin() { return initializers.begin(); }
+	iterator end() { return initializers.end(); }
 
 	virtual ListInit *clone() const { return new ListInit( *this ); }
Index: src/SynTree/Label.h
===================================================================
--- src/SynTree/Label.h	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/SynTree/Label.h	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -24,5 +24,5 @@
 class Label {
   public:
-	Label( const std::string & name = "", Statement * labelled = 0 ) : name( name ), labelled( labelled ) {}
+	Label( const std::string & name = "", Statement * labelled = 0, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : name( name ), labelled( labelled ), attributes( attributes ) {}
 	Label( const char * name, Statement * labelled = 0 ) : name( name ), labelled( labelled ) {}
 
Index: src/SynTree/ObjectDecl.cc
===================================================================
--- src/SynTree/ObjectDecl.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/SynTree/ObjectDecl.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -18,9 +18,10 @@
 #include "Initializer.h"
 #include "Expression.h"
+#include "Attribute.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 )
-	: Parent( name, sc, linkage ), type( type ), init( init ), bitfieldWidth( bitfieldWidth ) {
+ObjectDecl::ObjectDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, Expression *bitfieldWidth, Type *type, Initializer *init, const std::list< Attribute * > attributes, bool isInline, bool isNoreturn )
+	: Parent( name, sc, linkage, attributes ), type( type ), init( init ), bitfieldWidth( bitfieldWidth ) {
 	set_isInline( isInline );
 	set_isNoreturn( isNoreturn );
@@ -45,4 +46,6 @@
 		os << LinkageSpec::toString( get_linkage() ) << " ";
 	} // if
+
+	printAll( get_attributes(), os, indent );
 
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
@@ -80,4 +83,6 @@
 	} // if
 
+	// xxx - should printShort print attributes?
+
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
 		os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
Index: src/main.cc
===================================================================
--- src/main.cc	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/main.cc	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -42,5 +42,4 @@
 #include "InitTweak/GenInit.h"
 #include "InitTweak/FixInit.h"
-#include "InitTweak/FixGlobalInit.h"
 //#include "Explain/GenProlog.h"
 //#include "Try/Visit.h"
@@ -282,6 +281,4 @@
 		OPTPRINT( "fixNames" )
 		CodeGen::fixNames( translationUnit );
-		OPTPRINT( "fixGlobalInit" );
-		InitTweak::fixGlobalInit( translationUnit, filename, libcfap || treep );
 		OPTPRINT( "tweakInit" )
 		InitTweak::genInit( translationUnit );
@@ -304,7 +301,7 @@
 		}
 
+		// fix ObjectDecl - replaces ConstructorInit nodes
 		OPTPRINT( "fixInit" )
-		// fix ObjectDecl - replaces ConstructorInit nodes
-		InitTweak::fix( translationUnit );
+		InitTweak::fix( translationUnit, filename, libcfap || treep );
 		if ( ctorinitp ) {
 			dump ( translationUnit );
Index: src/tests/.expect/64/extension.txt
===================================================================
--- src/tests/.expect/64/extension.txt	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/tests/.expect/64/extension.txt	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -100,15 +100,2 @@
     ((void)((__extension__ __a__i_2 , __extension__ __b__i_2) , __extension__ __c__i_2));
 }
-__attribute__ ((constructor(),)) static void _init_extension(void){
-    int _global_init0;
-    ((void)((*((int *)(&__a__i_1)))=_global_init0) /* ?{} */);
-    int _global_init1;
-    ((void)((*((int *)(&__b__i_1)))=_global_init1) /* ?{} */);
-    int _global_init2;
-    ((void)((*((int *)(&__c__i_1)))=_global_init2) /* ?{} */);
-}
-__attribute__ ((destructor(),)) static void _destroy_extension(void){
-    ((void)((*((int *)(&__c__i_1)))) /* ^?{} */);
-    ((void)((*((int *)(&__b__i_1)))) /* ^?{} */);
-    ((void)((*((int *)(&__a__i_1)))) /* ^?{} */);
-}
Index: src/tests/.expect/multiDimension.txt
===================================================================
--- src/tests/.expect/multiDimension.txt	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
+++ src/tests/.expect/multiDimension.txt	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -0,0 +1,304 @@
+constructing with 1
+constructing with 2
+constructing with 3
+constructing with 4
+constructing with 5
+constructing with 6
+constructing with 7
+constructing with 8
+constructing with 9
+constructing with 10
+constructing with 1
+constructing with 2
+constructing with 3
+constructing with 4
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+constructing with 1234567
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+constructing with 1
+constructing with 2
+constructing with 3
+constructing with 4
+constructing with 5
+constructing with 6
+constructing with 7
+constructing with 8
+constructing with 9
+constructing with 0
+constructing with 0
+constructing with 0
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+default constructing
+constructing with 999
+constructing with 1111
+default constructing
+default constructing
+constructing with 1
+constructing with 2
+constructing with 3
+constructing with 4
+default constructing
+default constructing
+default constructing
+default constructing
+constructing with 0
+default constructing
+default constructing
+default constructing
+constructing with 11
+constructing with 22
+constructing with 33
+constructing with 55
+constructing with 66
+default constructing
+constructing with 77
+default constructing
+default constructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
+destructing
Index: src/tests/init_once.c
===================================================================
--- src/tests/init_once.c	(revision dae881f61dcc6f8cfd54c3e290f737e7bbd9212f)
+++ src/tests/init_once.c	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -92,4 +92,8 @@
 init_once y = x;
 
+void static_variable() {
+	static init_once x;
+}
+
 int main() {
 	// local variables
@@ -179,4 +183,9 @@
 		}
 	}
+
+	// function-scoped static variable
+	for (int i = 0; i < 10; i++) {
+		static_variable();
+	}
 }
 
Index: src/tests/multiDimension.c
===================================================================
--- src/tests/multiDimension.c	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
+++ src/tests/multiDimension.c	(revision 1b0020a936c9eda0e3b3c47045c62fc5c51b82ce)
@@ -0,0 +1,72 @@
+struct X {
+  int a;
+  int * ptr;
+};
+
+void ?{}(X * this) {
+  printf("default constructing\n");
+  (&this->a){ 123 };
+  this->ptr = malloc(sizeof(int));
+}
+
+void ?{}(X * this, X other) {
+  printf("copy constructing\n");
+  (&this->a){ other.a };
+  this->ptr = malloc(sizeof(int));
+}
+
+void ?{}(X * this, int a) {
+  printf("constructing with %d\n", a);
+  (&this->a){ a };
+  this->ptr = malloc(sizeof(int));
+}
+
+void ^?{}(X * this) {
+  printf("destructing\n");
+  free(this->ptr);
+}
+
+X ?=?(X * this, X other) {
+  this->a = other.a;
+  return *this;
+}
+
+X global[10][10] = {
+  { 1, { 2 }, { 3 }, { 4 }, 5, 6, 7, 8, 9, 10, 11, 12 },
+  { 1, 2, 3, 4 },
+  { { 1234567 } }
+};
+
+X global2[3][3][3] = {
+  {
+    { 1, 2, 3 },
+    { 4, 5, 6 },
+    { 7, 8, 9 },
+    { 10, 11, 12 }
+  },
+  {
+    { 0, 0, 0 }
+  }
+};
+
+int foo() {
+  static X abc[3][3] = {
+    { 11, 22, 33, 44 },
+    { 55, 66 },
+    { 77 },
+    { 88, 99, 1010 }
+  };
+}
+
+int main() {
+  X abc[4][4] = {
+    { 999, 1111 },
+    { 1, 2, 3, 4, 5 },
+    {},
+    { 0 },
+    { 88 }
+  };
+
+  foo();
+  foo();
+}
