Index: src/GenPoly/DeclMutator.h
===================================================================
--- src/GenPoly/DeclMutator.h	(revision 2be10237217d3203f88d37d1da72d6ec3736ab71)
+++ src/GenPoly/DeclMutator.h	(revision 5f98ce5c7a2f9f7f1b2877251c37b8b1f6bec9a7)
@@ -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/InitTweak/FixGlobalInit.cc
===================================================================
--- src/InitTweak/FixGlobalInit.cc	(revision 2be10237217d3203f88d37d1da72d6ec3736ab71)
+++ src/InitTweak/FixGlobalInit.cc	(revision 5f98ce5c7a2f9f7f1b2877251c37b8b1f6bec9a7)
@@ -79,4 +79,13 @@
 		bool isConstExpr;
 	};
+
+	bool isConstExpr( Expression * expr ) {
+		if ( expr ) {
+			ConstExprChecker checker;
+			expr->accept( checker );
+			return checker.isConstExpr;
+		}
+		return true;
+	}
 
 	bool isConstExpr( Initializer * init ) {
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision 2be10237217d3203f88d37d1da72d6ec3736ab71)
+++ src/InitTweak/GenInit.cc	(revision 5f98ce5c7a2f9f7f1b2877251c37b8b1f6bec9a7)
@@ -26,4 +26,5 @@
 #include "SymTab/Autogen.h"
 #include "GenPoly/PolyMutator.h"
+#include "GenPoly/DeclMutator.h"
 
 namespace InitTweak {
@@ -55,7 +56,7 @@
 	  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 );
 
@@ -64,12 +65,14 @@
 		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:
@@ -77,6 +80,34 @@
 	};
 
+	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:
+		DeclarationWithType * mutate( ObjectDecl * objectDecl );
+		// 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;
+	};
+
 	void genInit( std::list< Declaration * > & translationUnit ) {
 		ReturnFixer::makeReturnTemp( translationUnit );
+		HoistArrayDimension::hoistArrayDimension( translationUnit );
 		CtorDtor::generateCtorDtor( translationUnit );
 	}
@@ -124,4 +155,36 @@
 	}
 
+	void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
+		HoistArrayDimension hoister;
+		mutateAll( translationUnit, hoister );
+	}
+
+	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 ) {
+		static UniqueName dimensionName( "_array_dim" );
+		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;
+		}
+	}
 
 	void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
@@ -203,15 +266,4 @@
 		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.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 2be10237217d3203f88d37d1da72d6ec3736ab71)
+++ src/InitTweak/InitTweak.h	(revision 5f98ce5c7a2f9f7f1b2877251c37b8b1f6bec9a7)
@@ -54,4 +54,8 @@
   /// 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 );
 } // namespace
 
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 2be10237217d3203f88d37d1da72d6ec3736ab71)
+++ src/ResolvExpr/Resolver.cc	(revision 5f98ce5c7a2f9f7f1b2877251c37b8b1f6bec9a7)
@@ -24,4 +24,5 @@
 #include "SynTree/Initializer.h"
 #include "SymTab/Indexer.h"
+#include "SymTab/Autogen.h"
 #include "Common/utility.h"
 #include "InitTweak/InitTweak.h"
@@ -194,6 +195,5 @@
 	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() );
+			CastExpr *castExpr = new CastExpr( at->get_dimension(), SymTab::SizeType->clone() );
 			Expression *newExpr = findSingleExpression( castExpr, *this );
 			delete at->get_dimension();
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision 2be10237217d3203f88d37d1da72d6ec3736ab71)
+++ src/SymTab/Autogen.cc	(revision 5f98ce5c7a2f9f7f1b2877251c37b8b1f6bec9a7)
@@ -26,4 +26,6 @@
 
 namespace SymTab {
+	Type * SizeType = 0;
+
 	class AutogenerateRoutines : public Visitor {
 		public:
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision 2be10237217d3203f88d37d1da72d6ec3736ab71)
+++ src/SymTab/Autogen.h	(revision 5f98ce5c7a2f9f7f1b2877251c37b8b1f6bec9a7)
@@ -29,4 +29,8 @@
 	/// returns true if obj's name is the empty string and it has a bitfield width
 	bool isUnnamedBitfield( ObjectDecl * obj );
+
+	/// 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;
 
 	/// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 2be10237217d3203f88d37d1da72d6ec3736ab71)
+++ src/SymTab/Validate.cc	(revision 5f98ce5c7a2f9f7f1b2877251c37b8b1f6bec9a7)
@@ -174,5 +174,5 @@
 
 		virtual void visit( FunctionDecl *funcDecl );
-};
+	};
 
 	class CompoundLiteral : public GenPoly::DeclMutator {
@@ -490,5 +490,12 @@
 		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 {
+			assert( false && "missing global typedef for size_t" );
+		}
 		filter( translationUnit, isTypedef, true );
+
 	}
 
@@ -518,4 +525,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
