Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 72e9222a9026d1f801ca6ee36c7a5b77604f5304)
+++ src/InitTweak/FixInit.cc	(revision 926af747ff7dac04cacef082cdd822ede9e85c2d)
@@ -26,4 +26,5 @@
 #include "SynTree/Type.h"
 #include "SynTree/Expression.h"
+#include "SynTree/Attribute.h"
 #include "SynTree/Statement.h"
 #include "SynTree/Initializer.h"
@@ -208,7 +209,5 @@
 				try {
 					*i = maybeMutate( *i, fixer );
-					// if (! fixer.staticDtorDecls.empty() ) {
-						translationUnit.splice( i, fixer.staticDtorDecls );
-					// }
+					translationUnit.splice( i, fixer.staticDtorDecls );
 				} catch( SemanticError &e ) {
 					errors.append( e );
@@ -446,44 +445,24 @@
 					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, create a
-						// global static pointer that is set to refer to the object and make
-						// the dtor-caller function global so that.
+						// we get memory errors with this approach. To remedy this, the static
+						// variable is hoisted when the destructor needs to be called.
 						//
 						// generate:
-						// T * __objName_static_ptrN;
+						// static T __objName_static_varN;
 						// void __objName_dtor_atexitN() {
-						//   __dtor(__objName_static_ptrN);
+						//   __dtor__...;
 						// }
 						// int f(...) {
 						//   ...
-						//   static T __objName;
 						//   static bool __objName_uninitialized = true;
 						//   if (__objName_uninitialized) {
-						//     __objName_ptr = &__objName;
 						//     __ctor(__objName);
-						//     on_exit(__objName_dtor_atexitN, &__objName);
 						//     __objName_uninitialized = false;
+						//     atexit(__objName_dtor_atexitN);
 						//   }
 						//   ...
 						// }
 
-						static UniqueName ptrNamer( "_static_ptr" );
 						static UniqueName dtorCallerNamer( "_dtor_atexit" );
-
-						// T * __objName_ptrN
-						ObjectDecl * objPtr = new ObjectDecl( objDecl->get_mangleName() + ptrNamer.newName(), DeclarationNode::Static, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), objDecl->get_type()->clone() ), 0 );
-						objPtr->fixUniqueId();
-
-						// void __objName_dtor_atexitN(...) {...}
-						// need to modify dtor call so that it refers to objPtr, since function will be global
-						Statement * dtorStmt = ctorInit->get_dtor()->clone();
-						ApplicationExpr * dtor = dynamic_cast< ApplicationExpr * >( InitTweak::getCtorDtorCall( dtorStmt ) );
-						assert( dtor );
-						delete dtor->get_args().front();
-						dtor->get_args().front() = new VariableExpr( objPtr );
-
-						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 );
 
 						// static bool __objName_uninitialized = true
@@ -493,13 +472,4 @@
 						isUninitializedVar->fixUniqueId();
 
-						// __objName_static_ptrN = &__objName;
-						UntypedExpr * ptrAssign = new UntypedExpr( new NameExpr( "?=?" ) );
-						ptrAssign->get_args().push_back( new VariableExpr( objPtr ) );
-						ptrAssign->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
-
-						// atexit(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( "?=?" ) );
@@ -511,6 +481,4 @@
 						std::list< Statement * > & body = initStmts->get_kids();
 						body.push_back( ctor );
-						body.push_back( new ExprStmt( noLabels, ptrAssign ) );
-						body.push_back( new ExprStmt( noLabels, callAtexit ) );
 						body.push_back( new ExprStmt( noLabels, setTrue ) );
 
@@ -520,7 +488,42 @@
 						stmtsToAddAfter.push_back( ifStmt );
 
-						// add pointer and dtor caller decls to list of decls that will be added into global scope
-						staticDtorDecls.push_back( objPtr );
-						staticDtorDecls.push_back( dtorCaller );
+						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 );
@@ -582,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
