Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 44f634105516d986619d99fb2c97409063553f7d)
+++ src/InitTweak/FixInit.cc	(revision 1ba88a0e455e57ec77fa646372ffd0c5ef7e999c)
@@ -787,5 +787,5 @@
 				// need to iterate through members in reverse in order for
 				// ctor/dtor statements to come out in the right order
-				for ( Declaration * member : ReverseIterate( structDecl->get_members() ) ) {
+				for ( Declaration * member : reverseIterate( structDecl->get_members() ) ) {
 					DeclarationWithType * field = dynamic_cast< DeclarationWithType * >( member );
 					// skip non-DWT members
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision 44f634105516d986619d99fb2c97409063553f7d)
+++ src/InitTweak/GenInit.cc	(revision 1ba88a0e455e57ec77fa646372ffd0c5ef7e999c)
@@ -25,6 +25,8 @@
 #include "SynTree/Mutator.h"
 #include "SymTab/Autogen.h"
+#include "SymTab/Mangler.h"
 #include "GenPoly/PolyMutator.h"
 #include "GenPoly/DeclMutator.h"
+#include "GenPoly/ScopedSet.h"
 
 namespace InitTweak {
@@ -55,4 +57,6 @@
 	class CtorDtor : public GenPoly::PolyMutator {
 	  public:
+		typedef GenPoly::PolyMutator Parent;
+		using Parent::mutate;
 		/// create constructor and destructor statements for object declarations.
 		/// the actual call statements will be added in after the resolver has run
@@ -65,5 +69,5 @@
 		// 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( StructDecl *aggregateDecl );
 		virtual Declaration* mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; }
 		virtual Declaration* mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; }
@@ -74,5 +78,15 @@
 		virtual Type * mutate( FunctionType *funcType ) { return funcType; }
 
-	  protected:
+		virtual CompoundStmt * mutate( CompoundStmt * compoundStmt );
+
+	  private:
+		// set of mangled type names for which a constructor or destructor exists in the current scope.
+		// these types require a ConstructorInit node to be generated, anything else is a POD type and thus
+		// should not have a ConstructorInit generated.
+
+		bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed
+		void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor
+		GenPoly::ScopedSet< std::string > managedTypes;
+		bool inFunction = false;
 	};
 
@@ -142,6 +156,6 @@
 
 	DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) {
-		std::list<DeclarationWithType*> oldReturnVals = returnVals;
-		std::string oldFuncName = funcName;
+		ValueGuard< std::list<DeclarationWithType*> > oldReturnVals( returnVals );
+		ValueGuard< std::string > oldFuncName( funcName );
 
 		FunctionType * type = functionDecl->get_functionType();
@@ -149,6 +163,4 @@
 		funcName = functionDecl->get_name();
 		DeclarationWithType * decl = Mutator::mutate( functionDecl );
-		returnVals = oldReturnVals;
-		funcName = oldFuncName;
 		return decl;
 	}
@@ -197,8 +209,7 @@
 
 	DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {
-		bool oldInFunc = inFunction;
+		ValueGuard< bool > oldInFunc( inFunction );
 		inFunction = true;
 		DeclarationWithType * decl = Parent::mutate( functionDecl );
-		inFunction = oldInFunc;
 		return decl;
 	}
@@ -209,7 +220,31 @@
 	}
 
+	bool CtorDtor::isManaged( ObjectDecl * objDecl ) const {
+		Type * type = objDecl->get_type();
+		while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
+			type = at->get_base();
+		}
+		return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();
+	}
+
+	void CtorDtor::handleDWT( DeclarationWithType * dwt ) {
+		// if this function is a user-defined constructor or destructor, mark down the type as "managed"
+		if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && isCtorDtor( dwt->get_name() ) ) {
+			std::list< DeclarationWithType * > & params = GenPoly::getFunctionType( dwt->get_type() )->get_parameters();
+			assert( ! params.empty() );
+			PointerType * type = safe_dynamic_cast< PointerType * >( params.front()->get_type() );
+			managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) );
+		}
+	}
+
 	DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) {
-		// hands off if designated, if @=, or if extern
-		if ( tryConstruct( objDecl ) ) {
+		handleDWT( objDecl );
+		// hands off if @=, extern, builtin, etc.
+		// if global but initializer is not constexpr, always try to construct, since this is not legal C
+		if ( ( tryConstruct( objDecl ) && isManaged( objDecl ) ) || (! inFunction && ! isConstExpr( objDecl->get_init() ) ) ) {
+			// constructed objects cannot be designated
+			if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.", objDecl );
+			// xxx - constructed objects should not have initializers nested too deeply
+
 			// call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
 			// for each constructable object
@@ -241,13 +276,49 @@
 			}
 		}
-		return Mutator::mutate( objDecl );
+		return Parent::mutate( objDecl );
 	}
 
 	DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
+		ValueGuard< bool > oldInFunc = inFunction;
+		inFunction = true;
+
+		handleDWT( functionDecl );
+
+		managedTypes.beginScope();
+		// go through assertions and recursively add seen ctor/dtors
+		for ( TypeDecl * tyDecl : functionDecl->get_functionType()->get_forall() ) {
+			for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) {
+				assertion = assertion->acceptMutator( *this );
+			}
+		}
 		// parameters should not be constructed and destructed, so don't mutate FunctionType
 		mutateAll( functionDecl->get_oldDecls(), *this );
 		functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
+
+		managedTypes.endScope();
 		return functionDecl;
 	}
+
+	Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) {
+		// don't construct members, but need to take note if there is a managed member,
+		// because that means that this type is also managed
+		for ( Declaration * member : aggregateDecl->get_members() ) {
+			if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
+				if ( isManaged( field ) ) {
+					managedTypes.insert( SymTab::Mangler::mangle( aggregateDecl ) );
+					break;
+				}
+			}
+		}
+		return aggregateDecl;
+	}
+
+	CompoundStmt * CtorDtor::mutate( CompoundStmt * compoundStmt ) {
+		managedTypes.beginScope();
+		CompoundStmt * stmt = Parent::mutate( compoundStmt );
+		managedTypes.endScope();
+		return stmt;
+	}
+
 } // namespace InitTweak
 
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 44f634105516d986619d99fb2c97409063553f7d)
+++ src/InitTweak/InitTweak.cc	(revision 1ba88a0e455e57ec77fa646372ffd0c5ef7e999c)
@@ -232,6 +232,5 @@
 		return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
 			(objDecl->get_init() == NULL ||
-				( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
-			! isDesignated( objDecl->get_init() )
+				( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() ))
 			&& objDecl->get_storageClass() != DeclarationNode::Extern;
 	}
@@ -391,11 +390,18 @@
 		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( NameExpr *nameExpr ) {
+			// xxx - temporary hack, because 0 and 1 really should be constexprs, even though they technically aren't in Cforall today
+			if ( nameExpr->get_name() != "0" && nameExpr->get_name() != "1" ) isConstExpr = false;
+		}
+		// virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
+		virtual void visit( AddressExpr *addressExpr ) {
+			// address of a variable or member expression is constexpr
+			Expression * arg = addressExpr->get_arg();
+			if ( ! dynamic_cast< NameExpr * >( arg) && ! dynamic_cast< VariableExpr * >( arg ) && ! dynamic_cast< MemberExpr * >( arg ) && ! dynamic_cast< UntypedMemberExpr * >( arg ) ) 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 );
