Index: src/InitTweak/FixGlobalInit.cc
===================================================================
--- src/InitTweak/FixGlobalInit.cc	(revision b81adcc465c4f2e9cfa5a06860250151ee01113e)
+++ src/InitTweak/FixGlobalInit.cc	(revision 6cf27a070551542d34340180263c714585975c85)
@@ -97,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
@@ -104,18 +102,27 @@
 		// if ( isConstExpr( objDecl->get_init() ) ) return;
 
-		if ( dynamic_cast< ArrayType * > ( objDecl->get_type() ) ) {
-			// xxx - initialize each element of the array
-		} else {
-			// insert constructor for objDecl into global init function
-			UntypedExpr * init = new UntypedExpr( new NameExpr( "?{}" ) );
-			init->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
-			init->get_args().splice( init->get_args().end(), makeInitList( objDecl->get_init() ) );
-			objDecl->set_init( NULL );
-			initStatements.push_back( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, init ) ) );
+		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() );
 
-			// 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 && ! isInstrinsicSingleArgCallStmt( 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 b81adcc465c4f2e9cfa5a06860250151ee01113e)
+++ src/InitTweak/FixInit.cc	(revision 6cf27a070551542d34340180263c714585975c85)
@@ -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"
@@ -83,4 +84,5 @@
 		};
 
+		// debug
 		struct printSet {
 			typedef ObjDeclCollector::ObjectSet ObjectSet;
@@ -171,5 +173,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 );
Index: src/InitTweak/FixInit.h
===================================================================
--- src/InitTweak/FixInit.h	(revision b81adcc465c4f2e9cfa5a06860250151ee01113e)
+++ src/InitTweak/FixInit.h	(revision 6cf27a070551542d34340180263c714585975c85)
@@ -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 b81adcc465c4f2e9cfa5a06860250151ee01113e)
+++ src/InitTweak/GenInit.cc	(revision 6cf27a070551542d34340180263c714585975c85)
@@ -61,6 +61,4 @@
 		static void generateCtorDtor( std::list< Declaration * > &translationUnit );
 
-		CtorDtor() : inFunction( false ) {}
-
 		virtual DeclarationWithType * mutate( ObjectDecl * );
 		virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
@@ -77,5 +75,4 @@
 
 	  protected:
-		bool inFunction;
 	};
 
@@ -216,53 +213,55 @@
 
 	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 initializers and generate appropriate ctor if element has initializer.
-					// Initializer could be nested (depends on the depth of the array type on the object)
-
-					std::list< Expression * > args = makeInitList( objDecl->get_init() );
-					if ( args.empty() ) {
-						std::list< Statement * > ctor;
-						std::list< Statement * > dtor;
-
-						SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
-						SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
-
-						// Currently genArrayCall 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 genArrayCall
-						// itself
-						assert( ctor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( ctor.front() ) );
-						assert( dtor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( dtor.front() ) );
+			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 initializers and generate appropriate ctor if element has initializer.
+				// Initializer could be nested (depends on the depth of the array type on the object)
+
+				std::list< Expression * > args = makeInitList( objDecl->get_init() );
+				if ( args.empty() ) {
+					std::list< Statement * > ctor;
+					std::list< Statement * > dtor;
+
+					SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
+					SymTab::genImplicitCall( NULL, 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 ) {
+						assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && 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 elements 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() ) );
+					// 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 elements 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() ) );
 			}
 		}
@@ -272,9 +271,6 @@
 	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;
 	}
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision b81adcc465c4f2e9cfa5a06860250151ee01113e)
+++ src/InitTweak/InitTweak.cc	(revision 6cf27a070551542d34340180263c714585975c85)
@@ -57,5 +57,6 @@
 			(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;
 	}
 
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision b81adcc465c4f2e9cfa5a06860250151ee01113e)
+++ src/SymTab/Autogen.h	(revision 6cf27a070551542d34340180263c714585975c85)
@@ -144,15 +144,17 @@
 		genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), forward );
 
-		// currently genCall should produce only 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 );
-		Statement * callStmt = stmts.front();
-		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;
+		// 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 ( (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;
+    }
 	}
 } // namespace SymTab
Index: src/main.cc
===================================================================
--- src/main.cc	(revision b81adcc465c4f2e9cfa5a06860250151ee01113e)
+++ src/main.cc	(revision 6cf27a070551542d34340180263c714585975c85)
@@ -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/extension.txt
===================================================================
--- src/tests/.expect/extension.txt	(revision b81adcc465c4f2e9cfa5a06860250151ee01113e)
+++ src/tests/.expect/extension.txt	(revision 6cf27a070551542d34340180263c714585975c85)
@@ -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)))) /* ^?{} */);
-}
