Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision 711eee5ec8d25e9626c493d8242244335aa1f547)
+++ src/CodeGen/CodeGenerator.cc	(revision 4e2461096b7c7d12f2ee84f0cef534e05aa25d48)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// CodeGenerator.cc -- 
+// CodeGenerator.cc --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 17:32:16 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 06 11:39:01 2016
 // Update Count     : 243
 //
@@ -84,4 +84,16 @@
 		output << genType( functionDecl->get_functionType(), mangleName( functionDecl ) );
 
+		// generalize this
+		switch ( functionDecl->get_attribute() ) {
+			case FunctionDecl::Constructor:
+				output << " __attribute__ ((constructor))";
+				break;
+			case FunctionDecl::Destructor:
+				output << " __attribute__ ((destructor))";
+				break;
+			default:
+				break;
+		}
+
 		// how to get this to the Functype?
 		std::list< Declaration * > olds = functionDecl->get_oldDecls();
@@ -99,5 +111,5 @@
 		handleStorageClass( objectDecl );
 		output << genType( objectDecl->get_type(), mangleName( objectDecl ) );
-	
+
 		if ( objectDecl->get_init() ) {
 			output << " = ";
@@ -113,5 +125,5 @@
 		if ( aggDecl->get_name() != "" )
 			output << aggDecl->get_name();
-	
+
 		std::list< Declaration * > &memb = aggDecl->get_members();
 
@@ -119,12 +131,12 @@
 			output << " {" << endl;
 
-			cur_indent += CodeGenerator::tabsize; 
+			cur_indent += CodeGenerator::tabsize;
 			for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end();  i++) {
-				output << indent; 
+				output << indent;
 				(*i)->accept( *this );
 				output << ";" << endl;
 			}
 
-			cur_indent -= CodeGenerator::tabsize; 
+			cur_indent -= CodeGenerator::tabsize;
 
 			output << indent << "}";
@@ -141,5 +153,5 @@
 		handleAggregate( aggregateDecl );
 	}
-  
+
 	void CodeGenerator::visit( EnumDecl *aggDecl ) {
 		output << "enum ";
@@ -147,5 +159,5 @@
 		if ( aggDecl->get_name() != "" )
 			output << aggDecl->get_name();
-	
+
 		std::list< Declaration* > &memb = aggDecl->get_members();
 
@@ -153,9 +165,9 @@
 			output << " {" << endl;
 
-			cur_indent += CodeGenerator::tabsize; 
+			cur_indent += CodeGenerator::tabsize;
 			for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end();  i++) {
 				ObjectDecl *obj = dynamic_cast< ObjectDecl* >( *i );
 				assert( obj );
-				output << indent << mangleName( obj ); 
+				output << indent << mangleName( obj );
 				if ( obj->get_init() ) {
 					output << " = ";
@@ -165,17 +177,17 @@
 			} // for
 
-			cur_indent -= CodeGenerator::tabsize; 
+			cur_indent -= CodeGenerator::tabsize;
 
 			output << indent << "}";
 		} // if
 	}
-  
+
 	void CodeGenerator::visit( TraitDecl *aggregateDecl ) {}
-  
+
 	void CodeGenerator::visit( TypedefDecl *typeDecl ) {
 		output << "typedef ";
 		output << genType( typeDecl->get_base(), typeDecl->get_name() );
 	}
-  
+
 	void CodeGenerator::visit( TypeDecl *typeDecl ) {
 		// really, we should mutate this into something that isn't a TypeDecl but that requires large-scale changes,
@@ -217,5 +229,5 @@
 	}
 
-	void CodeGenerator::visit( Constant *constant ) { 
+	void CodeGenerator::visit( Constant *constant ) {
 		output << constant->get_value() ;
 	}
@@ -234,5 +246,5 @@
 						assert( arg != applicationExpr->get_args().end() );
 						if ( AddressExpr *addrExpr = dynamic_cast< AddressExpr * >( *arg ) ) {
-	        
+
 							*arg = addrExpr->get_arg();
 						} else {
@@ -243,10 +255,10 @@
 						break;
 					}
-	      
+
 				  default:
 					// do nothing
 					;
 				}
-	    
+
 				switch ( opInfo.type ) {
 				  case OT_INDEX:
@@ -257,10 +269,10 @@
 					output << "]";
 					break;
-	      
+
 				  case OT_CALL:
 					// there are no intrinsic definitions of the function call operator
 					assert( false );
 					break;
-	      
+
 				  case OT_PREFIX:
 				  case OT_PREFIXASSIGN:
@@ -271,5 +283,5 @@
 					output << ")";
 					break;
-	      
+
 				  case OT_POSTFIX:
 				  case OT_POSTFIXASSIGN:
@@ -288,5 +300,5 @@
 					output << ")";
 					break;
-	      
+
 				  case OT_CONSTANT:
 				  case OT_LABELADDRESS:
@@ -307,5 +319,5 @@
 		} // if
 	}
-  
+
 	void CodeGenerator::visit( UntypedExpr *untypedExpr ) {
 		if ( NameExpr *nameExpr = dynamic_cast< NameExpr* >( untypedExpr->get_function() ) ) {
@@ -321,9 +333,9 @@
 					output << "]";
 					break;
-	      
+
 				  case OT_CALL:
 					assert( false );
 					break;
-	      
+
 				  case OT_PREFIX:
 				  case OT_PREFIXASSIGN:
@@ -335,5 +347,5 @@
 					output << ")";
 					break;
-	      
+
 				  case OT_POSTFIX:
 				  case OT_POSTFIXASSIGN:
@@ -342,5 +354,5 @@
 					output << opInfo.symbol;
 					break;
-  
+
 				  case OT_INFIX:
 				  case OT_INFIXASSIGN:
@@ -352,5 +364,5 @@
 					output << ")";
 					break;
-					
+
 				  case OT_CONSTANT:
 					// there are no intrinsic definitions of 0 or 1 as functions
@@ -370,5 +382,5 @@
 		} // if
 	}
-  
+
 	void CodeGenerator::visit( NameExpr *nameExpr ) {
 		OperatorInfo opInfo;
@@ -380,5 +392,5 @@
 		} // if
 	}
-  
+
 	void CodeGenerator::visit( AddressExpr *addressExpr ) {
 		output << "(&";
@@ -409,14 +421,14 @@
 		output << ")";
 	}
-  
+
 	void CodeGenerator::visit( UntypedMemberExpr *memberExpr ) {
 		assert( false );
 	}
-  
+
 	void CodeGenerator::visit( MemberExpr *memberExpr ) {
 		memberExpr->get_aggregate()->accept( *this );
 		output << "." << mangleName( memberExpr->get_member() );
 	}
-  
+
 	void CodeGenerator::visit( VariableExpr *variableExpr ) {
 		OperatorInfo opInfo;
@@ -427,10 +439,10 @@
 		} // if
 	}
-  
+
 	void CodeGenerator::visit( ConstantExpr *constantExpr ) {
 		assert( constantExpr->get_constant() );
 		constantExpr->get_constant()->accept( *this );
 	}
-  
+
 	void CodeGenerator::visit( SizeofExpr *sizeofExpr ) {
 		output << "sizeof(";
@@ -469,5 +481,5 @@
 		assert( false && "OffsetPackExpr should not reach code generation" );
 	}
-  
+
 	void CodeGenerator::visit( LogicalExpr *logicalExpr ) {
 		output << "(";
@@ -481,5 +493,5 @@
 		output << ")";
 	}
-  
+
 	void CodeGenerator::visit( ConditionalExpr *conditionalExpr ) {
 		output << "(";
@@ -491,5 +503,5 @@
 		output << ")";
 	}
-  
+
 	void CodeGenerator::visit( CommaExpr *commaExpr ) {
 		output << "(";
@@ -499,7 +511,7 @@
 		output << ")";
 	}
-  
+
 	void CodeGenerator::visit( TupleExpr *tupleExpr ) {}
-  
+
 	void CodeGenerator::visit( TypeExpr *typeExpr ) {}
 
@@ -532,5 +544,5 @@
 			}
 		}
-		cur_indent -= CodeGenerator::tabsize; 
+		cur_indent -= CodeGenerator::tabsize;
 
 		output << indent << "}";
@@ -538,6 +550,6 @@
 
 	void CodeGenerator::visit( ExprStmt *exprStmt ) {
-		// I don't see why this check is necessary. 
-		// If this starts to cause problems then put it back in, 
+		// I don't see why this check is necessary.
+		// If this starts to cause problems then put it back in,
 		// with an explanation
 		assert( exprStmt );
@@ -589,5 +601,5 @@
 		switchStmt->get_condition()->accept( *this );
 		output << " ) ";
-		
+
 		output << "{" << std::endl;
 		cur_indent += CodeGenerator::tabsize;
@@ -609,5 +621,5 @@
 		} // if
 		output << ":\n";
-		
+
 		std::list<Statement *> sts = caseStmt->get_statements();
 
@@ -626,5 +638,5 @@
 			if ( ! branchStmt->get_target().empty() )
 				output << "goto " << branchStmt->get_target();
-			else { 
+			else {
 				if ( branchStmt->get_computedTarget() != 0 ) {
 					output << "goto *";
@@ -677,6 +689,6 @@
 
 	void CodeGenerator::visit( ForStmt *forStmt ) {
-		// initialization is always hoisted, so don't 
-		// bother doing anything with that 
+		// initialization is always hoisted, so don't
+		// bother doing anything with that
 		output << "for (;";
 
@@ -702,5 +714,5 @@
 	void CodeGenerator::visit( DeclStmt *declStmt ) {
 		declStmt->get_decl()->accept( *this );
-	
+
 		if ( doSemicolon( declStmt->get_decl() ) ) {
 			output << ";";
Index: src/InitTweak/FixGlobalInit.cc
===================================================================
--- src/InitTweak/FixGlobalInit.cc	(revision 711eee5ec8d25e9626c493d8242244335aa1f547)
+++ src/InitTweak/FixGlobalInit.cc	(revision 4e2461096b7c7d12f2ee84f0cef534e05aa25d48)
@@ -10,5 +10,5 @@
 // Created On       : Mon May 04 15:14:56 2016
 // Last Modified By : Rob Schluntz
-// Last Modified On : Wed May 04 16:53:12 2016
+// Last Modified On : Fri May 06 13:51:00 2016
 // Update Count     : 2
 //
@@ -30,11 +30,16 @@
 	class GlobalFixer : public Visitor {
 	  public:
-		GlobalFixer( const std::string & fileName );
+		GlobalFixer();
 
 		virtual void visit( ObjectDecl *objDecl );
 		virtual void visit( FunctionDecl *functionDecl );
+		virtual void visit( StructDecl *aggregateDecl );
+		virtual void visit( UnionDecl *aggregateDecl );
+		virtual void visit( EnumDecl *aggregateDecl );
+		virtual void visit( TraitDecl *aggregateDecl );
+		virtual void visit( TypeDecl *typeDecl );
 
 		UniqueName tempNamer;
-		FunctionDecl * initFunction;
+		CompoundStmt * block;
 	};
 
@@ -83,7 +88,14 @@
 
 	void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name ) {
-		GlobalFixer fixer( name );
+		GlobalFixer fixer;
 		acceptAll( translationUnit, fixer );
-		translationUnit.push_back( fixer.initFunction );
+		// attribute only appears on the forward declaration, so need to make two function decls:
+		// one with the body, one with the attribute.
+		FunctionDecl * initFunction = new FunctionDecl( initName( name ), DeclarationNode::NoStorageClass, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), 0, false, false );
+		FunctionDecl * forward = initFunction->clone();
+		forward->set_attribute( FunctionDecl::Constructor );
+		initFunction->set_statements( fixer.block );
+		translationUnit.push_back( forward );
+		translationUnit.push_back( initFunction );
 	}
 
@@ -97,13 +109,16 @@
   }
 
-	GlobalFixer::GlobalFixer( const std::string & fileName ) : tempNamer( "_global_init" ) {
-		initFunction = new FunctionDecl( initName( fileName ), DeclarationNode::NoStorageClass, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
+	GlobalFixer::GlobalFixer() : tempNamer( "_global_init" ), block( new CompoundStmt( noLabels ) ) {
 	}
 
 	void GlobalFixer::visit( ObjectDecl *objDecl ) {
-		std::list< Statement * > & statements = initFunction->get_statements()->get_kids();
+		std::list< Statement * > & statements = block->get_kids();
 
+		if ( objDecl->get_init() == NULL ) return;
+		if ( objDecl->get_type()->get_isConst() ) return; // temporary: can't assign to a const variable
 		// C allows you to initialize objects with constant expressions
-		if ( isConstExpr( objDecl->get_init() ) ) return;
+		// xxx - this is an optimization. Need to first resolve constructors before we decide
+		// to keep C-style initializer.
+		// if ( isConstExpr( objDecl->get_init() ) ) return;
 
 		// steal initializer from object and attach it to a new temporary
@@ -121,7 +136,12 @@
 	}
 
-	void GlobalFixer::visit( FunctionDecl *functionDecl ) {
-		// only modify global variables
-	}
+	// only modify global variables
+	void GlobalFixer::visit( FunctionDecl *functionDecl ) {}
+	void GlobalFixer::visit( StructDecl *aggregateDecl ) {}
+	void GlobalFixer::visit( UnionDecl *aggregateDecl ) {}
+	void GlobalFixer::visit( EnumDecl *aggregateDecl ) {}
+	void GlobalFixer::visit( TraitDecl *aggregateDecl ) {}
+	void GlobalFixer::visit( TypeDecl *typeDecl ) {}
+
 } // namespace InitTweak
 
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision 711eee5ec8d25e9626c493d8242244335aa1f547)
+++ src/SynTree/Declaration.h	(revision 4e2461096b7c7d12f2ee84f0cef534e05aa25d48)
@@ -5,10 +5,10 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Declaration.h -- 
+// Declaration.h --
 //
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 17:28:11 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 06 11:16:45 2016
 // Update Count     : 33
 //
@@ -106,5 +106,10 @@
 	typedef DeclarationWithType Parent;
   public:
-	FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn );
+	// temporary - merge this into general GCC attributes
+	enum Attribute {
+		NoAttribute, Constructor, Destructor,
+	};
+
+	FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, Attribute attribute = NoAttribute );
 	FunctionDecl( const FunctionDecl &other );
 	virtual ~FunctionDecl();
@@ -119,4 +124,6 @@
 	std::list< std::string >& get_oldIdents() { return oldIdents; }
 	std::list< Declaration* >& get_oldDecls() { return oldDecls; }
+	Attribute get_attribute() const { return attribute; }
+	void set_attribute( Attribute newValue ) { attribute = newValue; }
 
 	virtual FunctionDecl *clone() const { return new FunctionDecl( *this ); }
@@ -130,4 +137,5 @@
 	std::list< std::string > oldIdents;
 	std::list< Declaration* > oldDecls;
+	Attribute attribute;
 };
 
Index: src/SynTree/FunctionDecl.cc
===================================================================
--- src/SynTree/FunctionDecl.cc	(revision 711eee5ec8d25e9626c493d8242244335aa1f547)
+++ src/SynTree/FunctionDecl.cc	(revision 4e2461096b7c7d12f2ee84f0cef534e05aa25d48)
@@ -10,5 +10,5 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Fri Apr 01 11:40:07 2016
+// Last Modified On : Fri May 06 11:35:09 2016
 // Update Count     : 19
 //
@@ -21,12 +21,16 @@
 #include "Common/utility.h"
 
-FunctionDecl::FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn )
-		: Parent( name, sc, linkage ), type( type ), statements( statements ) {
+FunctionDecl::FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, Attribute attribute )
+		: Parent( name, sc, linkage ), type( type ), statements( statements ), attribute( attribute ) {
 	set_isInline( isInline );
 	set_isNoreturn( isNoreturn );
+	// this is a brazen hack to force the function "main" to have C linkage
+	if ( name == "main" ) {
+		set_linkage( LinkageSpec::C );
+	} // if
 }
 
 FunctionDecl::FunctionDecl( const FunctionDecl &other )
-	: Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ) {
+	: Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ), attribute( other.attribute ) {
 }
 
@@ -61,4 +65,14 @@
 		os << "_Noreturn ";
 	} // if
+	switch ( attribute ) {
+		case Constructor:
+			os << "Global Constructor ";
+			break;
+		case Destructor:
+			os << "Global Destructor ";
+			break;
+		default:
+			break;
+	}
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
 		os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
@@ -100,4 +114,14 @@
 		os << "_Noreturn ";
 	} // if
+	switch ( attribute ) {
+		case Constructor:
+			os << " Global Constructor ";
+			break;
+		case Destructor:
+			os << " Global Destructor ";
+			break;
+		default:
+			break;
+	}
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
 		os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
