Index: Jenkinsfile
===================================================================
--- Jenkinsfile	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ Jenkinsfile	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -36,8 +36,22 @@
 
 def push_build() {
-	build_stage 'Push'
-
-		sh 'git remote add DoLang git@gitlab.do-lang.org:internal/cfa-cc.git'
-		sh 'git push DoLang master'
+	//Don't use the build_stage function which outputs the compiler
+	stage 'Push'
+
+		status_prefix = 'Push'
+
+		def out_dir = pwd tmp: true
+		sh "mkdir -p ${out_dir}"
+
+		//parse git logs to find what changed
+		sh "git remote > ${out_dir}/GIT_REMOTE"
+		git_remote = readFile("${out_dir}/GIT_REMOTE")
+		remoteDoLangExists = git_remote.contains("DoLang")
+
+		if( !remoteDoLangExists ) {
+			sh 'git remote add DoLang git@gitlab.do-lang.org:internal/cfa-cc.git'
+		}
+
+		sh "git push DoLang ${gitRefNewValue}:master"
 }
 
@@ -74,5 +88,9 @@
 def collect_git_info() {
 
+	//create the temporary output directory in case it doesn't already exist
 	def out_dir = pwd tmp: true
+	sh "mkdir -p ${out_dir}"
+
+	//parse git logs to find what changed
 	gitRefName = env.BRANCH_NAME
 	dir("../${gitRefName}@script") {
@@ -89,4 +107,5 @@
 node ('master'){
 
+	boolean doPromoteBuild2DoLang
 	def err = null
 	def log_needed = false
@@ -113,5 +132,7 @@
 					]])
 
-				echo "FULL BUILD = ${promoteBuild2DoLang}"
+				doPromoteBuild2DoLang = promoteBuild2DoLang == 'true'
+
+				echo "FULL BUILD = ${doPromoteBuild2DoLang}"
 
 				//Compile using gcc-4.9
@@ -127,5 +148,5 @@
 				cfa_build()
 
-				if(promote_build) {
+				if( doPromoteBuild2DoLang ) {
 					push_build()
 				}
@@ -149,5 +170,5 @@
 	finally {
 		//Send email with final results
-		notify_result(promote_build, err != null, currentBuild.result, log_needed)
+		notify_result(doPromoteBuild2DoLang, err, currentBuild.result, log_needed)
 
 		/* Must re-throw exception to propagate error */
@@ -161,7 +182,7 @@
 //Routine responsible of sending the email notification once the build is completed
 //===========================================================================================================
-def promote_email(boolean promote, boolean success, String status, boolean log) {
+def notify_result(boolean promote, Exception err, String status, boolean log) {
 	if(promote)	{
-		if( !success ) {
+		if( err ) {
 			promote_email(status)
 		}
Index: doc/bibliography/cfa.bib
===================================================================
--- doc/bibliography/cfa.bib	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ doc/bibliography/cfa.bib	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -356,5 +356,5 @@
 }
 
-@article{Cor:overload,
+@article{Cormack81,
     keywords	= {},
     contributer	= {gjditchfield@plg},
@@ -2922,4 +2922,12 @@
     }
 }
+
+@unpublished{Bilson,
+	keywords = {generic programming, generics, polymorphism},
+	contributor  {a3moss@plg},
+	author = {Richard C. Bilson and Glen Ditchfield and Peter A. Buhr},
+	title = {Generic Programming with Inferred Models},
+}
+
 
 @article{Haskell,
@@ -5455,4 +5463,25 @@
 % Q
 
+@article{Grossman06,
+ keywords = {Cyclone, existential types, polymorphism, type variables},
+ contributer = {a3moss@plg},
+ author = {Grossman, Dan},
+ title = {Quantified Types in an Imperative Language},
+ journal = toplas,
+ issue_date = {May 2006},
+ volume = {28},
+ number = {3},
+ month = may,
+ year = {2006},
+ issn = {0164-0925},
+ pages = {429--475},
+ numpages = {47},
+ url = {http://doi.acm.org.proxy.lib.uwaterloo.ca/10.1145/1133651.1133653},
+ doi = {10.1145/1133651.1133653},
+ acmid = {1133653},
+ publisher = {ACM},
+ address = {New York, NY, USA},
+}
+
 @article{Hoare61,
     keywords	= {quick sort},
Index: doc/working/resolver_design.md
===================================================================
--- doc/working/resolver_design.md	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ doc/working/resolver_design.md	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -81,9 +81,10 @@
 
 ## Conversion Costs ##
-Each possible resolution of an expression has a _cost_ consisting of four 
-integer components: _unsafe_ conversion cost, _polymorphic_ specialization 
-cost, _safe_ conversion cost, and a _count_ of conversions. 
-These components form a lexically-ordered tuple which can be summed 
-element-wise; summation starts at `(0, 0, 0, 0)`.
+Each possible resolution of an expression has a _cost_ tuple consisting of 
+the following components: _unsafe_ conversion cost, _polymorphic_ 
+specialization cost, _safe_ conversion cost, a count of _explicit_ 
+conversions, and _qualifier_ conversion cost. 
+These components are lexically-ordered and can be summed element-wise; 
+summation starts at `(0, 0, 0, 0, 0)`.
 
 ### Lvalue and Qualifier Conversions ###
@@ -1224,4 +1225,193 @@
 programmers.
 
+## Resolver Architecture ##
+
+### Function Application Resolution ###
+Our resolution algorithm for function application expressions is based on 
+Baker's[3] single-pass bottom-up algorithm, with Cormack's[4] single-pass 
+top-down algorithm applied where appropriate as an optimization. 
+Broadly speaking, the cost of this resolution per expression will be 
+proportional to `i^d`, where `i` is the number of interpretations of each 
+program symbol, and `d` is the maximum depth of the expression DAG. 
+Since `d` is determined by the user programmer (in general, bounded by a small 
+constant), opportunities for resolver optimization primarily revolve around 
+minimizing `i`, the number of interpretations of each symbol that are 
+considered.
+
+[3] Baker, Theodore P. A one-pass algorithm for overload resolution in Ada. 
+ACM Transactions on Programming Languages and Systems (1982) 4:4 p.601-614
+
+[4] Cormack, Gordon V. An algorithm for the selection of overloaded functions 
+in Ada. SIGPLAN Notices (1981) 16:2 p.48-52
+
+Unlike Baker, our system allows implicit type conversions for function 
+arguments and return types; the problem then becomes to find the valid 
+interpretation for an expression that has the unique minimal conversion cost, 
+if such exists. 
+Interpretations can be produced both by overloaded names and implicit 
+conversions applied to existing interpretations; we have proposals to reduce 
+the number of interpretations considered from both sources. 
+To simplify the problem for this discussion, we will consider application 
+resolution restricted to a domain of functions applied to variables, possibly 
+in a nested manner (e.g. `f( g( x ), y )`, where `x` and `y` are variables and 
+`f` and `g` are functions), and possibly in a typed context such as a variable 
+initialization (e.g. `int i = f( x );`); the other aspects of Cforall type 
+resolution should be able to be straightforwardly mapped into this model. 
+The types of the symbol tables used for variable and function declarations 
+look somewhat like the following:
+
+	variable_table = name_map( variable_name, variable_map )
+	
+	function_table = name_map( function_name, function_map )
+	
+	variable_map = multi_index( by_type( variable_type ), 
+	                            variable_decl_set )
+
+	function_map = multi_index( by_int( n_params ),
+								by_type( return_type ),
+								function_decl_set )
+
+`variable_name` and `function_name` are likely simple strings, with `name_map` 
+a hash table (or perhaps trie) mapping string keys to values. 
+`variable_decl_set` and `function_decl_set` can be thought of for the moment 
+as simple bags of typed declarations, where the declaration types are linked 
+to the graph of available conversions for that type. 
+In a typed context both the `variable_decl_set` and the `function_decl_set` 
+should be able to be selected upon by type; this is accomplished by the 
+`by_type` index of both `variable_map` and `function_map`. 
+The `by_int` index of `function_map` also provides a way to select functions 
+by their number of parameters; this index may be used to swiftly discard any 
+function declaration which does not have the appropriate number of parameters 
+for the argument interpretations being passed to it; given the likely small 
+number of entries in this map, it is possible that a binary search of a sorted 
+vector or even a linear search of an unsorted vector would be more efficient 
+than the usual hash-based index.
+
+Given these data structures, the general outline of our algorithm follows 
+Baker, with Cormack's algorithm used as a heuristic filter in typed contexts. 
+
+In an untyped context, we use a variant of Baker's bottom-up algorithm. 
+The leaves of the interpretation DAG are drawn from the variable symbol table, 
+with entries in the table each producing zero-cost interpretations, and each 
+implicit conversion available to be applied to the type of an existing entry 
+producing a further interpretation with the same cost as the conversion. 
+As in Baker, if two or more interpretations have the same type, only the 
+minimum cost interpretation with that type is produced; if there is no unique 
+minimum cost interpretation than resolution with that type is ambiguous, and 
+not permitted. 
+It should be relatively simple to produce the list of interpretations sorted 
+by cost by producing the interpretations via a breadth-first search of the 
+conversion graph from the initial interpretations provided in the variable 
+symbol table.
+
+To match a function at one of the internal nodes of the DAG, we first look up 
+the function's name in the function symbol table, the appropriate number of 
+parameters for the arguments that are provided through the `by_int` index of 
+the returned `function_map`, then go through the resulting `function_decl_set` 
+searching for functions where the parameter types can unify with the provided 
+argument lists; any such matching function produces an interpretation with a 
+cost that is the sum of its argument costs. 
+Though this is not included in our simplified model, this unification step may 
+include binding of polymorphic variables, which introduces a cost for the 
+function binding itself which must be added to the argument costs. 
+Also, checking of function assertions would likely be done at this step as 
+well, possibly eliminating some possible matching functions (if no suitable 
+assertions can be satisfied), or adding further conversion costs for the 
+assertion satisfaction. 
+Once the set of valid function interpretations is produced, these may also be 
+expanded by the graph of implicit conversions on their return types, as the 
+variable interpretations were. 
+
+This implicit conversion-based expansion of interpretations should be skipped 
+for the top-level expression if used in an untyped (void) context, e.g. for 
+`f` in `f( g ( x ) );` or `x` in `x;`. 
+On the other hand, if the top-level expression specifies a type, e.g. in 
+`int i = f( x );`, only top level expressions that return that type are 
+relevant to the search, so the candidates for `f` can be filtered first by 
+those that return `int` (or a type convertable to it); this can be 
+accomplished by performing a top-down filter of the interpretations of `f` by 
+the `by_type` index of the `function_map` in a manner similar to Cormack's[4] 
+algorithm. 
+
+In a typed context, such as an initialization expression 
+`T x = f( g( y ), z );`, only interpretations of `f( g( y ), z )` which have 
+type `T` are valid; since there are likely to be valid interpretations of 
+`f( g( y ), z )` which cannot be used to initialize a variable of type `T`, we 
+can use this information to reduce the number of interpretations considered. 
+Drawing from Cormack[4], we first search for interpretations of `f` where the 
+return type is `T`; by breadth-first-search of the conversion graph, it should 
+be straightforward to order the interpretations of `f` by the cost to convert 
+their return type to `T`. 
+We can also filter out interpretations of `f` with less than two parameters, 
+since both `g( y )` and `z` must produce at least one parameter; we may not, 
+however, rule out interpretations of `f` with more than two parameters, as 
+there may be a valid interpretation of `g( y )` as a function returning more 
+than one parameter (if the expression was `f( y, z )` instead, we could use an 
+exact parameter count, assuming that variables of tuple type don't exist). 
+For each compatible interpretation of `f`, we can add the type of the first 
+parameter of that interpretation of `f` to a set `S`, and recursively search 
+for interpretations of `g( y )` that return some type `Si` in `S`, and 
+similarly for interpretations of `z` that match the type of any of the second 
+parameters of some `f`. 
+Naturally, if no matching interpretation of `g( y )` can be found for the 
+first parameter of some `f`, the type of the second parameter of that `f` will 
+not be added to the set of valid types for `z`. 
+Each node in this interpretation DAG is given a cost the same way it would be 
+in the bottom-up approach, with the exception that when going top-down there 
+must be a final bottom-up pass to sum the interpretation costs and sort them 
+as appropriate. 
+
+If a parameter type for some `f` is a polymorphic type variable that is left 
+unbound by the return type (e.g. `forall(otype S) int f(S x, int y)`), the 
+matching arguments should be found using the bottom-up algorithm above for 
+untyped contexts, because the polymorphic type variable does not sufficiently 
+constrain the available interpretations of the argument expression. 
+Similarly, it would likely be an advantage to use top-down resolution for 
+cast expressions (e.g. `(int)x`), even when those cast expressions are 
+subexpressions of an otherwise untyped expression. 
+It may also be fruitful to switch between the bottom-up and top-down 
+algorithms if the number of valid interpretations for a subexpression or valid 
+types for an argument exceeds some heuristic threshold, but finding such 
+a threshold (if any exists) will require experimental data. 
+This hybrid top-down/bottom-up search provides more opportunities for pruning 
+interpretations than either a bottom-up or top-down approach alone, and thus 
+may be more efficient than either. 
+A top-down-only approach, however, devolves to linear search through every 
+possible interpretation in the solution space in an untyped context, and is 
+thus likely to be inferior to a strictly bottom-up approach, though this 
+hypothesis needs to be empirically validated.
+
+Both Baker and Cormack explicitly generate all possible interpretations of a 
+given expression; thinking of the set of interpretations of an expression as a 
+list sorted by cost, this is an eager evaluation of the list. 
+However, since we generally expect that user programmers will not often use 
+high-cost implicit conversions, one potentially effective way to prune the 
+search space would be to first find the minimal-cost interpretations of any 
+given subexpression, then to save the resolution progress of the 
+subexpressions and attempt to resolve the superexpression using only those 
+subexpression interpretations.
+If no valid interpretation of the superexpression can be found, the resolver 
+would then repeatedly find the next-most-minimal cost interpretations of the 
+subexpressions and attempt to produce the minimal cost interpretation of the 
+superexpression. 
+This process would proceed until all possible subexpression interpretations 
+have been found and considered. 
+
+A middle ground between the eager and lazy approaches can be taken by 
+considering the lexical order on the cost tuple; essentially, every 
+interpretation in each of the classes below will be strictly cheaper than any 
+interpretation in the class after it, so if a min-cost valid interpretation 
+can be found while only generating interpretations in a given class, that 
+interpretation is guaranteed to be the best possible one:
+
+1. Interpretations without polymorphic functions or implicit conversions
+2. Interpretations without polymorphic functions using only safe conversions
+3. Interpretations using polymorphic functions without unsafe conversions
+4. Interpretations using unsafe conversions
+
+In this lazy-eager approach, all the interpretations in one class would be 
+eagerly generated, while the interpretations in the next class would only be 
+considered if no match was found in the previous class.
+
 ## Appendix A: Partial and Total Orders ##
 The `<=` relation on integers is a commonly known _total order_, and 
Index: src/ArgTweak/FunctionFixer.cc
===================================================================
--- src/ArgTweak/FunctionFixer.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/ArgTweak/FunctionFixer.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// FunctionFixer.cc -- 
+// FunctionFixer.cc --
 //
 // Author           : Rodolfo G. Esteves
@@ -42,18 +42,15 @@
 	Expression *FunctionFixer::mutate( UntypedExpr *untypedExpr ) throw ( SemanticError ) {
 		assert( untypedExpr != 0 );
-		NameExpr *function;
 
-		if ( ( function = dynamic_cast< NameExpr *>(untypedExpr->get_function()) ) != 0 ) {
+		if ( NameExpr * function = dynamic_cast< NameExpr *>(untypedExpr->get_function() ) ) {
 			std::list < DeclarationWithType * > options;
 			index->lookupId ( function->get_name(), options );
 			for ( std::list < DeclarationWithType * >::iterator i = options.begin(); i != options.end(); i++ ) {
-				FunctionType *f;
-				if ( ( f = dynamic_cast< FunctionType * > ( (*i)->get_type() ) ) != 0 )	{
+				if ( FunctionType * f = dynamic_cast< FunctionType * > ( (*i)->get_type() ) )	{
 					std::list < DeclarationWithType * > &pars = f->get_parameters();
-
 					bool candidateExists ;
-					for ( std::list < DeclarationWithType * >::iterator p = pars.begin(); p != pars.end(); p++ )
+					for ( std::list < DeclarationWithType * >::iterator p = pars.begin(); p != pars.end(); p++ ) {
 						if ( ( candidateExists = align( f->get_parameters(), untypedExpr->get_args(), Matcher() ) ) ) break;
-
+					}
 					if ( ! candidateExists ) throw SemanticError("Error in function call");
 				} // if
Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/CodeGen/CodeGenerator.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -26,4 +26,5 @@
 #include "SynTree/Statement.h"
 #include "SynTree/Type.h"
+#include "SynTree/Attribute.h"
 
 #include "Common/utility.h"
@@ -33,4 +34,6 @@
 #include "OperatorTable.h"
 #include "GenType.h"
+
+#include "InitTweak/InitTweak.h"
 
 using namespace std;
@@ -74,26 +77,24 @@
 	}
 
+	void CodeGenerator::genAttributes( std::list< Attribute * > & attributes ) {
+		if ( ! attributes.empty() ) {
+			output << "__attribute__ ((";
+			for ( Attribute *& attr : attributes ) {
+				if ( ! attr->empty() ) {
+					output << attr->get_name() << "(";
+					genCommaList( attr->get_parameters().begin(), attr->get_parameters().end() );
+					output << ")";
+				}
+				output << ",";
+			}
+			output << ")) ";
+		}
+	}
+
+
 	//*** Declarations
 	void CodeGenerator::visit( FunctionDecl *functionDecl ) {
-		// generalize this
-		FunctionDecl::Attribute attr = functionDecl->get_attribute();
-		switch ( attr.type ) {
-			case FunctionDecl::Attribute::Constructor:
-				output << "__attribute__ ((constructor";
-				if ( attr.priority != FunctionDecl::Attribute::Default ) {
-					output << "(" << attr.priority << ")";
-				}
-				output << ")) ";
-				break;
-			case FunctionDecl::Attribute::Destructor:
-				output << "__attribute__ ((destructor";
-				if ( attr.priority != FunctionDecl::Attribute::Default ) {
-					output << "(" << attr.priority << ")";
-				}
-				output << ")) ";
-				break;
-			default:
-				break;
-		}
+		genAttributes( functionDecl->get_attributes() );
+
 		handleStorageClass( functionDecl );
 		if ( functionDecl->get_isInline() ) {
@@ -270,4 +271,8 @@
 							UntypedExpr *newExpr = new UntypedExpr( new NameExpr( "*?" ) );
 							newExpr->get_args().push_back( *arg );
+							assert( (*arg)->get_results().size() == 1 );
+							Type * type = InitTweak::getPointerBase( (*arg)->get_results().front() );
+							assert( type );
+							newExpr->get_results().push_back( type );
 							*arg = newExpr;
 						} // if
@@ -298,8 +303,8 @@
 					if ( applicationExpr->get_args().size() == 1 ) {
 						// the expression fed into a single parameter constructor or destructor
-						// may contain side effects - output as a void expression
-						output << "((void)(";
+						// may contain side effects, so must still output this expression
+						output << "(";
 						(*arg++)->accept( *this );
-						output << ")) /* " << opInfo.inputName << " */";
+						output << ") /* " << opInfo.inputName << " */";
 					} else if ( applicationExpr->get_args().size() == 2 ) {
 						// intrinsic two parameter constructors are essentially bitwise assignment
@@ -384,8 +389,8 @@
 					if ( untypedExpr->get_args().size() == 1 ) {
 						// the expression fed into a single parameter constructor or destructor
-						// may contain side effects - output as a void expression
-						output << "((void)(";
+						// may contain side effects, so must still output this expression
+						output << "(";
 						(*arg++)->accept( *this );
-						output << ")) /* " << opInfo.inputName << " */";
+						output << ") /* " << opInfo.inputName << " */";
 					} else if ( untypedExpr->get_args().size() == 2 ) {
 						// intrinsic two parameter constructors are essentially bitwise assignment
@@ -626,13 +631,9 @@
 
 	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,
-		// with an explanation
 		assert( exprStmt );
-
-		// if ( exprStmt != 0 ) {
-		exprStmt->get_expr()->accept( *this );
-		output << ";" ;
-		// } // if
+		// cast the top-level expression to void to reduce gcc warnings.
+		Expression * expr = new CastExpr( exprStmt->get_expr() );
+		expr->accept( *this );
+		output << ";";
 	}
 
@@ -743,7 +744,7 @@
 
 	void CodeGenerator::visit( WhileStmt *whileStmt ) {
-		if ( whileStmt->get_isDoWhile() )
+		if ( whileStmt->get_isDoWhile() ) {
 			output << "do" ;
-		else {
+		} else {
 			output << "while (" ;
 			whileStmt->get_condition()->accept( *this );
@@ -769,10 +770,14 @@
 		output << "for (;";
 
-		if ( forStmt->get_condition() != 0 )
+		if ( forStmt->get_condition() != 0 ) {
 			forStmt->get_condition()->accept( *this );
+		}
 		output << ";";
 
-		if ( forStmt->get_increment() != 0 )
-			forStmt->get_increment()->accept( *this );
+		if ( forStmt->get_increment() != 0 ) {
+			// cast the top-level expression to void to reduce gcc warnings.
+			Expression * expr = new CastExpr( forStmt->get_increment() );
+			expr->accept( *this );
+		}
 		output << ") ";
 
Index: src/CodeGen/CodeGenerator.h
===================================================================
--- src/CodeGen/CodeGenerator.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/CodeGen/CodeGenerator.h	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// CodeGenerator.h -- 
+// CodeGenerator.h --
 //
 // Author           : Richard C. Bilson
@@ -60,5 +60,5 @@
 		virtual void visit( MemberExpr *memberExpr );
 		virtual void visit( VariableExpr *variableExpr );
-		virtual void visit( ConstantExpr *constantExpr ); 
+		virtual void visit( ConstantExpr *constantExpr );
 		virtual void visit( SizeofExpr *sizeofExpr );
 		virtual void visit( AlignofExpr *alignofExpr );
@@ -85,5 +85,7 @@
 		virtual void visit( ForStmt * );
 		virtual void visit( NullStmt * );
-		virtual void visit( DeclStmt * ); 
+		virtual void visit( DeclStmt * );
+
+		void genAttributes( std::list< Attribute * > & attributes );
 
 		template< class Iterator > void genCommaList( Iterator begin, Iterator end );
@@ -114,5 +116,5 @@
 
 	};
-	
+
 	template< class Iterator >
 	void CodeGenerator::genCommaList( Iterator begin, Iterator end ) {
@@ -125,5 +127,5 @@
 		} // for
 	}
-  
+
 	inline bool doSemicolon( Declaration* decl ) {
 		if ( FunctionDecl* func = dynamic_cast< FunctionDecl* >( decl ) ) {
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/GenPoly/Box.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -1947,4 +1947,5 @@
 				UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
 				derefExpr->get_args().push_back( derefdVar );
+				// xxx - should set results on derefExpr
 				derefdVar = derefExpr;
 			}
Index: src/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/GenPoly/Specialize.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -25,4 +25,5 @@
 #include "SynTree/Statement.h"
 #include "SynTree/Type.h"
+#include "SynTree/Attribute.h"
 #include "SynTree/TypeSubstitution.h"
 #include "SynTree/Mutator.h"
@@ -101,4 +102,7 @@
 		thunkFunc->fixUniqueId();
 
+		// thunks may be generated and not used - silence warning with attribute
+		thunkFunc->get_attributes().push_back( new Attribute( "unused" ) );
+
 		// thread thunk parameters into call to actual function, naming thunk parameters as we go
 		UniqueName paramNamer( paramPrefix );
Index: src/InitTweak/FixGlobalInit.cc
===================================================================
--- src/InitTweak/FixGlobalInit.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/InitTweak/FixGlobalInit.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -22,4 +22,5 @@
 #include "SynTree/Initializer.h"
 #include "SynTree/Visitor.h"
+#include "SynTree/Attribute.h"
 #include <algorithm>
 
@@ -116,7 +117,20 @@
 	GlobalFixer::GlobalFixer( const std::string & name, bool inLibrary ) : tempNamer( "_global_init" ) {
 		std::string fixedName = globalFunctionName( name );
-		initFunction = new FunctionDecl( "_init_" + fixedName, DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false, FunctionDecl::Attribute( FunctionDecl::Attribute::Constructor, inLibrary ? FunctionDecl::Attribute::High : FunctionDecl::Attribute::Default ) );
-
-		destroyFunction = new FunctionDecl( "_destroy_" + fixedName, DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false, FunctionDecl::Attribute( FunctionDecl::Attribute::Destructor, inLibrary ? FunctionDecl::Attribute::High : FunctionDecl::Attribute::Default ) );
+		std::list< Expression * > ctorParameters;
+		std::list< Expression * > dtorParameters;
+		if ( inLibrary ) {
+			// Constructor/destructor attributes take a single parameter which
+			// is the priority, with lower numbers meaning higher priority.
+			// Functions specified with priority are guaranteed to run before
+			// functions without a priority. To ensure that constructors and destructors
+			// for library code are run before constructors and destructors for user code,
+			// specify a priority when building the library. Priorities 0-100 are reserved by gcc.
+			ctorParameters.push_back( new ConstantExpr( Constant::from_int( 101 ) ) );
+			dtorParameters.push_back( new ConstantExpr( Constant::from_int( 101 ) ) );
+		}
+		initFunction = new FunctionDecl( "_init_" + fixedName, DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
+		initFunction->get_attributes().push_back( new Attribute( "constructor", ctorParameters ) );
+		destroyFunction = new FunctionDecl( "_destroy_" + fixedName, DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
+		destroyFunction->get_attributes().push_back( new Attribute( "destructor", dtorParameters ) );
 	}
 
@@ -125,7 +139,5 @@
 		std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
 
-		// if ( objDecl->get_init() == NULL ) return;
 		if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects
-		if ( objDecl->get_type()->get_isConst() ) return; // temporary: can't assign to a const variable
 		if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return;
 		// C allows you to initialize objects with constant expressions
@@ -146,10 +158,10 @@
 			init->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );
 			init->get_args().push_back( new VariableExpr( newObj ) );
-			initStatements.push_back( new ExprStmt( noLabels, init ) );
+			initStatements.push_back( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, 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 ExprStmt( noLabels, destroy ) );
+			destroyStatements.push_front( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, destroy ) ) );
 		}
 	}
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/InitTweak/FixInit.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -132,5 +132,4 @@
 				return appExpr;
 			} else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) {
-				// FunctionType * ftype = funcDecl->get_functionType();
 				FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
 				assert( ftype );
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/InitTweak/GenInit.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -164,6 +164,5 @@
 						assert( ctor.size() == 1 );
 						assert( dtor.size() == 1 );
-
-						objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
+						objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctor.front() ), new ImplicitCtorDtorStmt( dtor.front() ), objDecl->get_init() ) );
 					} else {
 						// array came with an initializer list: initialize each element
@@ -185,5 +184,5 @@
 					ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor );
 					ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor );
-					objDecl->set_init( new ConstructorInit( ctorStmt, dtorStmt, objDecl->get_init() ) );
+					objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) );
 				}
 			}
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/InitTweak/InitTweak.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -7,79 +7,148 @@
 
 namespace InitTweak {
-  namespace {
-    class HasDesignations : public Visitor {
-    public:
-      bool hasDesignations = false;
-      template<typename Init>
-      void handleInit( Init * init ) {
-        if ( ! init->get_designators().empty() ) hasDesignations = true;
-        else Visitor::visit( init );
-      }
-      virtual void visit( SingleInit * singleInit ) { handleInit( singleInit); }
-      virtual void visit( ListInit * listInit ) { handleInit( listInit); }
-    };
+	namespace {
+		class HasDesignations : public Visitor {
+		public:
+			bool hasDesignations = false;
+			template<typename Init>
+			void handleInit( Init * init ) {
+				if ( ! init->get_designators().empty() ) hasDesignations = true;
+				else Visitor::visit( init );
+			}
+			virtual void visit( SingleInit * singleInit ) { handleInit( singleInit); }
+			virtual void visit( ListInit * listInit ) { handleInit( listInit); }
+		};
 
-    class InitExpander : public Visitor {
-      public:
-      InitExpander() {}
-      virtual void visit( SingleInit * singleInit );
-      virtual void visit( ListInit * listInit );
-      std::list< Expression * > argList;
-    };
+		class InitExpander : public Visitor {
+			public:
+			InitExpander() {}
+			virtual void visit( SingleInit * singleInit );
+			virtual void visit( ListInit * listInit );
+			std::list< Expression * > argList;
+		};
 
-    void InitExpander::visit( SingleInit * singleInit ) {
-      argList.push_back( singleInit->get_value()->clone() );
-    }
+		void InitExpander::visit( SingleInit * singleInit ) {
+			argList.push_back( singleInit->get_value()->clone() );
+		}
 
-    void InitExpander::visit( ListInit * listInit ) {
-      // xxx - for now, assume no nested list inits
-      std::list<Initializer*>::iterator it = listInit->begin_initializers();
-      for ( ; it != listInit->end_initializers(); ++it ) {
-        (*it)->accept( *this );
-      }
-    }
-  }
+		void InitExpander::visit( ListInit * listInit ) {
+			// xxx - for now, assume no nested list inits
+			std::list<Initializer*>::iterator it = listInit->begin_initializers();
+			for ( ; it != listInit->end_initializers(); ++it ) {
+				(*it)->accept( *this );
+			}
+		}
+	}
 
-  std::list< Expression * > makeInitList( Initializer * init ) {
-    InitExpander expander;
-    maybeAccept( init, expander );
-    return expander.argList;
-  }
+	std::list< Expression * > makeInitList( Initializer * init ) {
+		InitExpander expander;
+		maybeAccept( init, expander );
+		return expander.argList;
+	}
 
-  bool isDesignated( Initializer * init ) {
-    HasDesignations finder;
-    maybeAccept( init, finder );
-    return finder.hasDesignations;
-  }
+	bool isDesignated( Initializer * init ) {
+		HasDesignations finder;
+		maybeAccept( init, finder );
+		return finder.hasDesignations;
+	}
 
-  bool tryConstruct( ObjectDecl * objDecl ) {
-    return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
-      (objDecl->get_init() == NULL ||
-        ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
-      ! isDesignated( objDecl->get_init() );
-  }
+	bool tryConstruct( ObjectDecl * objDecl ) {
+		return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
+			(objDecl->get_init() == NULL ||
+				( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) &&
+			! isDesignated( objDecl->get_init() );
+	}
 
-  bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
-    if ( stmt == NULL ) return false;
-    if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
-      ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( exprStmt->get_expr() );
-      assert( appExpr );
-      VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
-      assert( function );
-      // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
-      // will call all member dtors, and some members may have a user defined dtor.
-      FunctionType * funcType = GenPoly::getFunctionType( function->get_var()->get_type() );
-      assert( funcType );
-      return function->get_var()->get_linkage() == LinkageSpec::Intrinsic && funcType->get_parameters().size() == 1;
-    } else if ( CompoundStmt * compoundStmt = dynamic_cast< CompoundStmt * >( stmt ) ) {
-      // could also be a compound statement with a loop, in the case of an array
-      assert( compoundStmt->get_kids().size() == 2 ); // loop variable and loop
-      ForStmt * forStmt = dynamic_cast< ForStmt * >( compoundStmt->get_kids().back() );
-      assert( forStmt && forStmt->get_body() );
-      return isInstrinsicSingleArgCallStmt( forStmt->get_body() );
-    } else {
-      // should never get here
-      assert( false && "encountered unknown call statement" );
-    }
-  }
+	Expression * getCtorDtorCall( Statement * stmt ) {
+		if ( stmt == NULL ) return NULL;
+		if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
+			return exprStmt->get_expr();
+		} else if ( CompoundStmt * compoundStmt = dynamic_cast< CompoundStmt * >( stmt ) ) {
+			// could also be a compound statement with a loop, in the case of an array
+			assert( compoundStmt->get_kids().size() == 2 ); // loop variable and loop
+			ForStmt * forStmt = dynamic_cast< ForStmt * >( compoundStmt->get_kids().back() );
+			assert( forStmt && forStmt->get_body() );
+			return getCtorDtorCall( forStmt->get_body() );
+		} if ( ImplicitCtorDtorStmt * impCtorDtorStmt = dynamic_cast< ImplicitCtorDtorStmt * > ( stmt ) ) {
+			return getCtorDtorCall( impCtorDtorStmt->get_callStmt() );
+		} else {
+			// should never get here
+			assert( false && "encountered unknown call statement" );
+		}
+	}
+
+	bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
+		Expression * callExpr = getCtorDtorCall( stmt );
+		if ( ! callExpr ) return false;
+		ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr );
+		assert( appExpr );
+		VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
+		assert( function );
+		// check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
+		// will call all member dtors, and some members may have a user defined dtor.
+		FunctionType * funcType = GenPoly::getFunctionType( function->get_var()->get_type() );
+		assert( funcType );
+		return function->get_var()->get_linkage() == LinkageSpec::Intrinsic && funcType->get_parameters().size() == 1;
+	}
+
+	namespace {
+		template<typename CallExpr>
+		Expression *& callArg( CallExpr * callExpr, unsigned int pos ) {
+			if ( pos >= callExpr->get_args().size() ) assert( false && "asking for argument that doesn't exist. Return NULL/throw exception?" );
+			for ( Expression *& arg : callExpr->get_args() ) {
+				if ( pos == 0 ) return arg;
+				pos--;
+			}
+			assert( false );
+		}
+	}
+
+	Expression *& getCallArg( Expression * callExpr, unsigned int pos ) {
+		if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr ) ) {
+			return callArg( appExpr, pos );
+		} else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( callExpr ) ) {
+			return callArg( untypedExpr, pos );
+		} else {
+			assert( false && "Unexpected expression type passed to getCallArg" );
+		}
+	}
+
+	namespace {
+		template<typename CallExpr>
+		std::string funcName( CallExpr * expr ) {
+			Expression * func = expr->get_function();
+			if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( func ) ) {
+				return nameExpr->get_name();
+			} else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( func ) ) {
+				return varExpr->get_var()->get_name();
+			} else {
+				assert( false && "Unexpected expression type being called as a function in call expression" );
+			}
+		}
+	}
+
+	std::string getFunctionName( Expression * expr ) {
+		if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ) ) {
+			return funcName( appExpr );
+		} else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * > ( expr ) ) {
+			return funcName( untypedExpr );
+		} else {
+			assert( false && "Unexpected expression type passed to getFunctionName" );
+		}
+	}
+
+	Type * getPointerBase( Type * type ) {
+		if ( PointerType * ptrType = dynamic_cast< PointerType * >( type ) ) {
+			return ptrType->get_base();
+		} else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
+			return arrayType->get_base();
+		} else {
+			return NULL;
+		}
+	}
+
+	Type * isPointerType( Type * type ) {
+		if ( getPointerBase( type ) ) return type;
+		else return NULL;
+	}
 }
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/InitTweak/InitTweak.h	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -39,4 +39,19 @@
   /// Currently has assertions that make it less than fully general.
   bool isInstrinsicSingleArgCallStmt( Statement * expr );
+
+  /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
+  Expression * getCtorDtorCall( Statement * stmt );
+
+  /// returns the name of the function being called
+  std::string getFunctionName( Expression * expr );
+
+  /// returns the argument to a call expression in position N indexed from 0
+  Expression *& getCallArg( Expression * callExpr, unsigned int pos );
+
+  /// returns the base type of a PointerType or ArrayType, else returns NULL
+  Type * getPointerBase( Type * );
+
+  /// returns the argument if it is a PointerType or ArrayType, else returns NULL
+  Type * isPointerType( Type * );
 } // namespace
 
Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/Makefile.in	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -195,4 +195,5 @@
 	SynTree/driver_cfa_cpp-Mutator.$(OBJEXT) \
 	SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT) \
+	SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) \
 	Tuples/driver_cfa_cpp-Mutate.$(OBJEXT) \
 	Tuples/driver_cfa_cpp-AssignExpand.$(OBJEXT) \
@@ -411,8 +412,8 @@
 	SynTree/NamedTypeDecl.cc SynTree/TypeDecl.cc \
 	SynTree/Initializer.cc SynTree/Visitor.cc SynTree/Mutator.cc \
-	SynTree/TypeSubstitution.cc Tuples/Mutate.cc \
-	Tuples/AssignExpand.cc Tuples/FunctionFixer.cc \
-	Tuples/TupleAssignment.cc Tuples/FunctionChecker.cc \
-	Tuples/NameMatcher.cc
+	SynTree/TypeSubstitution.cc SynTree/Attribute.cc \
+	Tuples/Mutate.cc Tuples/AssignExpand.cc \
+	Tuples/FunctionFixer.cc Tuples/TupleAssignment.cc \
+	Tuples/FunctionChecker.cc Tuples/NameMatcher.cc
 MAINTAINERCLEANFILES = Parser/parser.output ${libdir}/${notdir \
 	${cfa_cpplib_PROGRAMS}}
@@ -783,4 +784,6 @@
 SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT):  \
 	SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
+SynTree/driver_cfa_cpp-Attribute.$(OBJEXT): SynTree/$(am__dirstamp) \
+	SynTree/$(DEPDIR)/$(am__dirstamp)
 Tuples/$(am__dirstamp):
 	@$(MKDIR_P) Tuples
@@ -880,4 +883,5 @@
 	-rm -f SynTree/driver_cfa_cpp-ArrayType.$(OBJEXT)
 	-rm -f SynTree/driver_cfa_cpp-AttrType.$(OBJEXT)
+	-rm -f SynTree/driver_cfa_cpp-Attribute.$(OBJEXT)
 	-rm -f SynTree/driver_cfa_cpp-BasicType.$(OBJEXT)
 	-rm -f SynTree/driver_cfa_cpp-CommaExpr.$(OBJEXT)
@@ -989,4 +993,5 @@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-ArrayType.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AttrType.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-BasicType.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-CommaExpr.Po@am__quote@
@@ -2424,4 +2429,18 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-TypeSubstitution.obj `if test -f 'SynTree/TypeSubstitution.cc'; then $(CYGPATH_W) 'SynTree/TypeSubstitution.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/TypeSubstitution.cc'; fi`
+
+SynTree/driver_cfa_cpp-Attribute.o: SynTree/Attribute.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Attribute.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Tpo -c -o SynTree/driver_cfa_cpp-Attribute.o `test -f 'SynTree/Attribute.cc' || echo '$(srcdir)/'`SynTree/Attribute.cc
+@am__fastdepCXX_TRUE@	$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='SynTree/Attribute.cc' object='SynTree/driver_cfa_cpp-Attribute.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Attribute.o `test -f 'SynTree/Attribute.cc' || echo '$(srcdir)/'`SynTree/Attribute.cc
+
+SynTree/driver_cfa_cpp-Attribute.obj: SynTree/Attribute.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-Attribute.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Tpo -c -o SynTree/driver_cfa_cpp-Attribute.obj `if test -f 'SynTree/Attribute.cc'; then $(CYGPATH_W) 'SynTree/Attribute.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Attribute.cc'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-Attribute.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='SynTree/Attribute.cc' object='SynTree/driver_cfa_cpp-Attribute.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Attribute.obj `if test -f 'SynTree/Attribute.cc'; then $(CYGPATH_W) 'SynTree/Attribute.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Attribute.cc'; fi`
 
 Tuples/driver_cfa_cpp-Mutate.o: Tuples/Mutate.cc
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -39,4 +39,5 @@
 #include "Tuples/NameMatcher.h"
 #include "Common/utility.h"
+#include "InitTweak/InitTweak.h"
 
 extern bool resolvep;
@@ -546,7 +547,6 @@
 
 		{
-			NameExpr *fname = 0;;
-			if ( ( fname = dynamic_cast<NameExpr *>( untypedExpr->get_function()))
-				 && ( fname->get_name() == std::string("&&")) ) {
+			std::string fname = InitTweak::getFunctionName( untypedExpr );
+			if ( fname == "&&" ) {
 				VoidType v = Type::Qualifiers();		// resolve to type void *
 				PointerType pt( Type::Qualifiers(), v.clone() );
Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/ResolvExpr/CommonType.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// CommonType.cc -- 
+// CommonType.cc --
 //
 // Author           : Richard C. Bilson
@@ -134,4 +134,10 @@
 				result = new BasicType( basicType->get_qualifiers() + otherBasic->get_qualifiers(), newType );
 			} // if
+		} else if ( EnumInstType *enumInstType = dynamic_cast< EnumInstType * > ( type2 ) ) {
+			// use signed int in lieu of the enum type
+			BasicType::Kind newType = combinedType[ basicType->get_kind() ][ BasicType::SignedInt ];
+			if ( ( ( newType == basicType->get_kind() && basicType->get_qualifiers() >= enumInstType->get_qualifiers() ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->get_qualifiers() <= enumInstType->get_qualifiers() ) || widenSecond ) ) {
+				result = new BasicType( basicType->get_qualifiers() + enumInstType->get_qualifiers(), newType );
+			} // if
 		} // if
 	}
@@ -183,5 +189,12 @@
 	}
 
-	void CommonType::visit( EnumInstType *aggregateUseType ) {
+	void CommonType::visit( EnumInstType *enumInstType ) {
+		if ( dynamic_cast< BasicType * >( type2 ) ) {
+			// reuse BasicType, EnumInstType code by swapping type2 with enumInstType
+			Type * temp = type2;
+			type2 = enumInstType;
+			temp->accept( *this );
+			type2 = temp;
+		} // if
 	}
 
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/ResolvExpr/ConversionCost.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// ConversionCost.cc -- 
+// ConversionCost.cc --
 //
 // Author           : Richard C. Bilson
@@ -157,5 +157,8 @@
 				cost = Cost( 0, 0, tableResult );
 			} // if
-		} // if
+		} else if ( dynamic_cast< EnumInstType *>( dest ) ) {
+			// xxx - not positive this is correct, but appears to allow casting int => enum
+			cost = Cost( 1, 0, 0 );
+    } // if
 	}
 
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/ResolvExpr/Resolver.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -38,4 +38,5 @@
 		virtual void visit( ObjectDecl *functionDecl );
 		virtual void visit( TypeDecl *typeDecl );
+		virtual void visit( EnumDecl * enumDecl );
 
 		virtual void visit( ArrayType * at );
@@ -52,4 +53,5 @@
 		virtual void visit( BranchStmt *branchStmt );
 		virtual void visit( ReturnStmt *returnStmt );
+		virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt );
 
 		virtual void visit( SingleInit *singleInit );
@@ -65,4 +67,5 @@
 		Type *initContext;
 		Type *switchType;
+		bool inEnumDecl = false;
 	};
 
@@ -177,5 +180,14 @@
 		Type *temp = initContext;
 		initContext = new_type;
+		if ( inEnumDecl && dynamic_cast< EnumInstType * >( initContext ) ) {
+			// enumerator initializers should not use the enum type to initialize, since
+			// the enum type is still incomplete at this point. Use signed int instead.
+			initContext = new BasicType( Type::Qualifiers(), BasicType::SignedInt );
+		}
 		SymTab::Indexer::visit( objectDecl );
+		if ( inEnumDecl && dynamic_cast< EnumInstType * >( initContext ) ) {
+			// delete newly created signed int type
+			delete initContext;
+		}
 		initContext = temp;
 	}
@@ -215,4 +227,12 @@
 		SymTab::Indexer::visit( functionDecl );
 		functionReturn = oldFunctionReturn;
+	}
+
+	void Resolver::visit( EnumDecl * enumDecl ) {
+		// in case we decide to allow nested enums
+		bool oldInEnumDecl = inEnumDecl;
+		inEnumDecl = true;
+		SymTab::Indexer::visit( enumDecl );
+		inEnumDecl = oldInEnumDecl;
 	}
 
@@ -492,5 +512,5 @@
 		} catch ( SemanticError ) {
 			// no alternatives for the constructor initializer - fallback on C-style initializer
-			// xxx- not sure if this makes a ton of sense - should maybe never be able to have this situation?
+			// xxx - not sure if this makes a ton of sense - should maybe never be able to have this situation?
 			fallbackInit( ctorInit );
 			return;
@@ -513,4 +533,46 @@
 		}
 	}
+
+	void Resolver::visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) {
+		// before resolving ctor/dtor, need to remove type qualifiers from the first argument (the object being constructed).
+		// Do this through a cast expression to greatly simplify the code.
+		Expression * callExpr = InitTweak::getCtorDtorCall( impCtorDtorStmt );
+		assert( callExpr );
+		Expression *& constructee = InitTweak::getCallArg( callExpr, 0 );
+		Type * type = 0;
+
+		// need to find the type of the first argument, which is unfortunately not uniform since array construction
+		// includes an untyped '+' expression.
+		if ( UntypedExpr * plusExpr = dynamic_cast< UntypedExpr * >( constructee ) ) {
+			// constructee is <array>+<index>
+			// get Variable <array>, then get the base type of the VariableExpr - this is the type that needs to be fixed
+			Expression * arr = InitTweak::getCallArg( plusExpr, 0 );
+			assert( dynamic_cast< VariableExpr * >( arr ) );
+			assert( arr && arr->get_results().size() == 1 );
+			type = arr->get_results().front()->clone();
+		} else {
+			// otherwise, constructing a plain object, which means the object's address is being taken.
+			// Need to get the type of the VariableExpr object, because the AddressExpr is rebuilt and uses the
+			// type of the VariableExpr to do so.
+			assert( constructee->get_results().size() == 1 );
+			AddressExpr * addrExpr = dynamic_cast< AddressExpr * > ( constructee );
+			assert( addrExpr && addrExpr->get_results().size() == 1);
+			type = addrExpr->get_results().front()->clone();
+		}
+		// cast to T* with qualifiers removed.
+		// unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
+		// must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
+		// remove lvalue as a qualifier, this can change to
+		//   type->get_qualifiers() = Type::Qualifiers();
+		Type * base = InitTweak::getPointerBase( type );
+		assert( base );
+		base->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
+		// if pointer has lvalue qualifier, cast won't appear in output
+		type->set_isLvalue( false );
+		constructee = new CastExpr( constructee, type );
+
+		// finally, resolve the ctor/dtor
+		impCtorDtorStmt->get_callStmt()->accept( *this );
+	}
 } // namespace ResolvExpr
 
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SymTab/Autogen.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -102,52 +102,56 @@
 		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
 
+		ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), refType ), 0 );
+		assignType->get_parameters().push_back( dstParam );
+
+		// void ?{}(E *); void ^?{}(E *);
+		FunctionType * ctorType = assignType->clone();
+		FunctionType * dtorType = assignType->clone();
+
+		ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
+		assignType->get_parameters().push_back( srcParam );
+		// void ?{}(E *, E);
+		FunctionType *copyCtorType = assignType->clone();
+
+		// T ?=?(E *, E);
 		ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
 		assignType->get_returnVals().push_back( returnVal );
 
-		// need two assignment operators with different types
-		FunctionType * assignType2 = assignType->clone();
-
-		// E ?=?(E volatile *, E)
-		Type *etype = refType->clone();
-		// etype->get_qualifiers() += Type::Qualifiers(false, true, false, false, false, false);
-
-		ObjectDecl *dstParam = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), etype ), 0 );
-		assignType->get_parameters().push_back( dstParam );
-
-		ObjectDecl *srcParam = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, etype->clone(), 0 );
-		assignType->get_parameters().push_back( srcParam );
-
-		// E ?=?(E volatile *, int)
-		assignType2->get_parameters().push_back( dstParam->clone() );
-		BasicType * paramType = new BasicType(Type::Qualifiers(), BasicType::SignedInt);
-		ObjectDecl *srcParam2 = new ObjectDecl( "_src", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, paramType, 0 );
-		assignType2->get_parameters().push_back( srcParam2 );
+		// xxx - should we also generate void ?{}(E *, int) and E ?{}(E *, E)?
+		// right now these cases work, but that might change.
 
 		// Routines at global scope marked "static" to prevent multiple definitions is separate translation units
 		// because each unit generates copies of the default routines for each aggregate.
-
-		// since there is no definition, these should not be inline
-		// make these intrinsic so that the code generator does not make use of them
-		FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, 0, false, false );
+		// xxx - Temporary: make these functions intrinsic so they codegen as C assignment.
+		// Really they're something of a cross between instrinsic and autogen, so should
+		// probably make a new linkage type
+		FunctionDecl *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType, new CompoundStmt( noLabels ), true, false );
+		FunctionDecl *ctorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, ctorType, new CompoundStmt( noLabels ), true, false );
+		FunctionDecl *copyCtorDecl = new FunctionDecl( "?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, copyCtorType, new CompoundStmt( noLabels ), true, false );
+		FunctionDecl *dtorDecl = new FunctionDecl( "^?{}", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, dtorType, new CompoundStmt( noLabels ), true, false );
 		assignDecl->fixUniqueId();
-		FunctionDecl *assignDecl2 = new FunctionDecl( "?=?", functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::Intrinsic, assignType2, 0, false, false );
-		assignDecl2->fixUniqueId();
-
-		// these should be built in the same way that the prelude
-		// functions are, so build a list containing the prototypes
-		// and allow MakeLibCfa to autogenerate the bodies.
-		std::list< Declaration * > assigns;
-		assigns.push_back( assignDecl );
-		assigns.push_back( assignDecl2 );
-
-		LibCfa::makeLibCfa( assigns );
-
-		// need to remove the prototypes, since this may be nested in a routine
-		for (int start = 0, end = assigns.size()/2; start < end; start++) {
-			delete assigns.front();
-			assigns.pop_front();
-		} // for
-
-		declsToAdd.insert( declsToAdd.begin(), assigns.begin(), assigns.end() );
+		ctorDecl->fixUniqueId();
+		copyCtorDecl->fixUniqueId();
+		dtorDecl->fixUniqueId();
+
+		// enum copy construct and assignment is just C-style assignment.
+		// this looks like a bad recursive call, but code gen will turn it into
+		// a C-style assignment.
+		// This happens before function pointer type conversion, so need to do it manually here
+		VariableExpr * assignVarExpr = new VariableExpr( assignDecl );
+		Type *& assignVarExprType = assignVarExpr->get_results().front();
+		assignVarExprType = new PointerType( Type::Qualifiers(), assignVarExprType );
+		ApplicationExpr * assignExpr = new ApplicationExpr( assignVarExpr );
+		assignExpr->get_args().push_back( new VariableExpr( dstParam ) );
+		assignExpr->get_args().push_back( new VariableExpr( srcParam ) );
+
+		// body is either return stmt or expr stmt
+		assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, assignExpr ) );
+		copyCtorDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, assignExpr->clone() ) );
+
+		declsToAdd.push_back( assignDecl );
+		declsToAdd.push_back( ctorDecl );
+		declsToAdd.push_back( copyCtorDecl );
+		declsToAdd.push_back( dtorDecl );
 	}
 
@@ -488,5 +492,5 @@
 		type->get_parameters().push_back( dst );
 		type->get_parameters().push_back( src );
-		FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, false, false );
+		FunctionDecl *func = new FunctionDecl( "?=?", DeclarationNode::NoStorageClass, LinkageSpec::AutoGen, type, stmts, true, false );
 		declsToAdd.push_back( func );
 	}
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SymTab/Validate.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -279,11 +279,8 @@
 	void Pass1::visit( EnumDecl *enumDecl ) {
 		// Set the type of each member of the enumeration to be EnumConstant
-
 		for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) {
 			ObjectDecl * obj = dynamic_cast< ObjectDecl * >( *i );
 			assert( obj );
-			// obj->set_type( new EnumInstType( Type::Qualifiers( true, false, false, false, false, false ), enumDecl->get_name() ) );
-			BasicType * enumType = new BasicType( Type::Qualifiers(), BasicType::SignedInt );
-			obj->set_type( enumType ) ;
+			obj->set_type( new EnumInstType( Type::Qualifiers( true, false, false, false, false, false ), enumDecl->get_name() ) );
 		} // for
 		Parent::visit( enumDecl );
Index: src/SynTree/Attribute.cc
===================================================================
--- src/SynTree/Attribute.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
+++ src/SynTree/Attribute.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -0,0 +1,47 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Attribute.cc --
+//
+// Author           : Rob Schluntz
+// Created On       : Mon June 06 14:51:16 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Mon June 06 14:54:48 2016
+// Update Count     : 1
+//
+
+#include <cassert>
+
+#include "Common/utility.h"
+#include "Attribute.h"
+#include "Expression.h"
+
+Attribute::Attribute( const Attribute &other ) : name( other.name ) {
+  cloneAll( other.parameters, parameters );
+}
+
+Attribute::~Attribute() {
+  deleteAll( parameters );
+}
+
+void Attribute::print( std::ostream &os, int indent ) const {
+  using std::endl;
+  using std::string;
+
+  if ( ! empty() ) {
+    os << "Attribute with name: " << name;
+    if ( ! parameters.empty() ) {
+      os << " with parameters: " << endl;
+      printAll( parameters, os, indent );
+    }
+  }
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SynTree/Attribute.h
===================================================================
--- src/SynTree/Attribute.h	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
+++ src/SynTree/Attribute.h	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -0,0 +1,43 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Declaration.h --
+//
+// Author           : Richard C. Bilson
+// Created On       : Mon May 18 07:44:20 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 06 16:26:12 2016
+// Update Count     : 33
+//
+
+#ifndef GCC_ATTRIBUTE_H
+#define GCC_ATTRIBUTE_H
+
+#include "SynTree.h"
+
+// GCC attribute
+// https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Attribute-Syntax.html#Attribute-Syntax
+class Attribute {
+  public:
+  Attribute( std::string name = "", const std::list< Expression * > & parameters = std::list< Expression * >() ) : name( name ), parameters( parameters ) {}
+  Attribute( const Attribute &other );
+  virtual ~Attribute();
+
+  std::string get_name() const { return name; }
+  void set_name( const std::string & newValue ) { name = newValue; }
+  std::list< Expression * > & get_parameters() { return parameters; }
+  bool empty() const { return name == ""; }
+
+  Attribute * clone() const { return new Attribute( *this ); }
+  void print( std:: ostream &os, int indent = 0 ) const;
+
+  private:
+  std::string name;
+  // to keep things nice and tight, use NameExpr for special identifier parameters
+  std::list< Expression * > parameters;
+};
+
+#endif
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Declaration.h	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -115,17 +115,5 @@
 	typedef DeclarationWithType Parent;
   public:
-	// temporary - merge this into general GCC attributes
-	struct Attribute {
-		enum Type {
-			NoAttribute, Constructor, Destructor,
-		} type;
-		enum Priority {
-			// priorities 0-100 are reserved by gcc, so it's okay to use 100 an exceptional case
-			Default = 100, High,
-		} priority;
-		Attribute(Type t = NoAttribute, Priority p = Default) : type(t), priority(p) {};
-	};
-
-	FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, Attribute attribute = Attribute() );
+	FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, const std::list< Attribute * > attributes = std::list< Attribute * >() );
 	FunctionDecl( const FunctionDecl &other );
 	virtual ~FunctionDecl();
@@ -140,6 +128,5 @@
 	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; }
+	std::list< Attribute * >& get_attributes() { return attributes; }
 
 	virtual FunctionDecl *clone() const { return new FunctionDecl( *this ); }
@@ -153,5 +140,5 @@
 	std::list< std::string > oldIdents;
 	std::list< Declaration* > oldDecls;
-	Attribute attribute;
+	std::list< Attribute * > attributes;
 };
 
Index: src/SynTree/FunctionDecl.cc
===================================================================
--- src/SynTree/FunctionDecl.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/FunctionDecl.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -19,8 +19,9 @@
 #include "Statement.h"
 #include "Type.h"
+#include "Attribute.h"
 #include "Common/utility.h"
 
-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 ) {
+FunctionDecl::FunctionDecl( const std::string &name, DeclarationNode::StorageClass sc, LinkageSpec::Type linkage, FunctionType *type, CompoundStmt *statements, bool isInline, bool isNoreturn, std::list< Attribute * > attributes )
+		: Parent( name, sc, linkage ), type( type ), statements( statements ), attributes( attributes ) {
 	set_isInline( isInline );
 	set_isNoreturn( isNoreturn );
@@ -32,5 +33,6 @@
 
 FunctionDecl::FunctionDecl( const FunctionDecl &other )
-	: Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ), attribute( other.attribute ) {
+	: Parent( other ), type( maybeClone( other.type ) ), statements( maybeClone( other.statements ) ) {
+		cloneAll( other.attributes, attributes );
 }
 
@@ -38,4 +40,5 @@
 	delete type;
 	delete statements;
+	deleteAll( attributes );
 }
 
@@ -65,17 +68,7 @@
 		os << "_Noreturn ";
 	} // if
-	switch ( attribute.type ) {
-		case Attribute::Constructor:
-			os << "Global Constructor ";
-			break;
-		case Attribute::Destructor:
-			os << "Global Destructor ";
-			break;
-		default:
-			break;
-	}
-	if ( attribute.priority != Attribute::Default ) {
-		os << "with priority " << attribute.priority << " ";
-	}
+
+	printAll( attributes, os, indent );
+
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
 		os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
@@ -118,17 +111,7 @@
 		os << "_Noreturn ";
 	} // if
-	switch ( attribute.type ) {
-		case Attribute::Constructor:
-			os << " Global Constructor ";
-			break;
-		case Attribute::Destructor:
-			os << " Global Destructor ";
-			break;
-		default:
-			break;
-	}
-	if ( attribute.priority != Attribute::Default ) {
-		os << "with priority " << attribute.priority << " ";
-	}
+
+	// xxx - should printShort print attributes?
+
 	if ( get_storageClass() != DeclarationNode::NoStorageClass ) {
 		os << DeclarationNode::storageName[ get_storageClass() ] << ' ';
Index: src/SynTree/Initializer.cc
===================================================================
--- src/SynTree/Initializer.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Initializer.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -20,4 +20,7 @@
 
 Initializer::Initializer( bool maybeConstructed ) : maybeConstructed( maybeConstructed ) {}
+Initializer::Initializer( const Initializer & other ) : maybeConstructed( other.maybeConstructed ) {
+}
+
 
 Initializer::~Initializer() {}
@@ -39,7 +42,7 @@
 }
 
-SingleInit::~SingleInit() {}
-
-SingleInit *SingleInit::clone() const { return new SingleInit( *this); }
+SingleInit::~SingleInit() {
+	deleteAll(designators);
+}
 
 void SingleInit::print( std::ostream &os, int indent ) {
@@ -58,11 +61,10 @@
 
 ListInit::ListInit( const std::list<Initializer*> &_initializers, const std::list<Expression *> &_designators, bool maybeConstructed )
-	: Initializer( maybeConstructed), initializers( _initializers ), designators( _designators ) {
+	: Initializer( maybeConstructed ), initializers( _initializers ), designators( _designators ) {
 }
 
-ListInit::~ListInit() {}
-
-ListInit *ListInit::clone() const {
-	return new ListInit( *this );
+ListInit::~ListInit() {
+	deleteAll( initializers );
+	deleteAll( designators );
 }
 
@@ -85,11 +87,11 @@
 
 ConstructorInit::ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init ) : Initializer( true ), ctor( ctor ), dtor( dtor ), init( init ) {}
+ConstructorInit::ConstructorInit( const ConstructorInit &other ) : Initializer( other ), ctor( maybeClone( other.ctor ) ), dtor( maybeClone( other.dtor ) ), init( maybeClone( other.init ) ) {
+}
+
 ConstructorInit::~ConstructorInit() {
 	delete ctor;
+	delete dtor;
 	delete init;
-}
-
-ConstructorInit *ConstructorInit::clone() const {
-	return new ConstructorInit( *this );
 }
 
Index: src/SynTree/Initializer.h
===================================================================
--- src/SynTree/Initializer.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Initializer.h	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -20,4 +20,5 @@
 #include "Visitor.h"
 #include "Mutator.h"
+#include "Type.h"
 
 #include <cassert>
@@ -28,4 +29,5 @@
 	//	Initializer( std::string _name = std::string(""), int _pos = 0 );
 	Initializer( bool maybeConstructed );
+	Initializer( const Initializer & other );
 	virtual ~Initializer();
 
@@ -68,5 +70,5 @@
 	std::list<Expression *> &get_designators() { return designators; }
 
-	virtual SingleInit *clone() const;
+	virtual SingleInit *clone() const { return new SingleInit( *this); }
 	virtual void accept( Visitor &v ) { v.visit( this ); }
 	virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }
@@ -94,5 +96,5 @@
 	std::list<Initializer*>::iterator end_initializers() { return initializers.end(); }
 
-	virtual ListInit *clone() const;
+	virtual ListInit *clone() const { return new ListInit( *this ); }
 	virtual void accept( Visitor &v ) { v.visit( this ); }
 	virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }
@@ -108,4 +110,5 @@
   public:
 	ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init );
+	ConstructorInit( const ConstructorInit &other );
 	virtual ~ConstructorInit();
 
@@ -117,5 +120,5 @@
 	Initializer * get_init() const { return init; }
 
-	virtual ConstructorInit *clone() const;
+	ConstructorInit *clone() const { return new ConstructorInit( *this ); }
 	virtual void accept( Visitor &v ) { v.visit( this ); }
 	virtual Initializer *acceptMutator( Mutator &m ) { return m.mutate( this ); }
Index: src/SynTree/Mutator.cc
===================================================================
--- src/SynTree/Mutator.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Mutator.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -182,4 +182,9 @@
 }
 
+Statement *Mutator::mutate( ImplicitCtorDtorStmt *impCtorDtorStmt ) {
+	impCtorDtorStmt->set_callStmt( maybeMutate( impCtorDtorStmt->get_callStmt(), *this ) );
+	return impCtorDtorStmt;
+}
+
 Expression *Mutator::mutate( ApplicationExpr *applicationExpr ) {
 	mutateAll( applicationExpr->get_results(), *this );
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Mutator.h	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -52,4 +52,5 @@
 	virtual NullStmt* mutate( NullStmt *nullStmt );
 	virtual Statement* mutate( DeclStmt *declStmt );
+	virtual Statement* mutate( ImplicitCtorDtorStmt *impCtorDtorStmt );
 
 	virtual Expression* mutate( ApplicationExpr *applicationExpr );
Index: src/SynTree/Statement.cc
===================================================================
--- src/SynTree/Statement.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Statement.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -358,5 +358,5 @@
 
 void CatchStmt::print( std::ostream &os, int indent ) const {
-	os << string( indent, ' ' ) << "Catch Statement" << endl;
+	os << "Catch Statement" << endl;
 
 	os << string( indent, ' ' ) << "... catching" << endl;
@@ -383,5 +383,5 @@
 
 void FinallyStmt::print( std::ostream &os, int indent ) const {
-	os << string( indent, ' ' ) << "Finally Statement" << endl;
+	os << "Finally Statement" << endl;
 	os << string( indent + 2, ' ' ) << "with block: " << endl;
 	block->print( os, indent + 4 );
@@ -393,4 +393,21 @@
 void NullStmt::print( std::ostream &os, int indent ) const {
 	os << "Null Statement" << endl ;
+}
+
+ImplicitCtorDtorStmt::ImplicitCtorDtorStmt( Statement * callStmt ) : Statement( std::list<Label>() ), callStmt( callStmt ) {
+	assert( callStmt );
+}
+
+ImplicitCtorDtorStmt::ImplicitCtorDtorStmt( const ImplicitCtorDtorStmt & other ) : Statement( other ), callStmt( other.callStmt ) {
+}
+
+ImplicitCtorDtorStmt::~ImplicitCtorDtorStmt() {
+}
+
+void ImplicitCtorDtorStmt::print( std::ostream &os, int indent ) const {
+	os << "Implicit Ctor Dtor Statement" << endl;
+	os << string( indent + 2, ' ' ) << "with Ctor/Dtor: ";
+	callStmt->print( os, indent + 2);
+	os << endl;
 }
 
Index: src/SynTree/Statement.h
===================================================================
--- src/SynTree/Statement.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Statement.h	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -21,4 +21,5 @@
 #include "Mutator.h"
 #include "Common/SemanticError.h"
+#include "Type.h"
 
 class Statement {
@@ -394,5 +395,5 @@
 	virtual ~DeclStmt();
 
-	Declaration *get_decl() { return decl; }
+	Declaration *get_decl() const { return decl; }
 	void set_decl( Declaration *newValue ) { decl = newValue; }
 
@@ -404,4 +405,28 @@
 	Declaration *decl;
 };
+
+
+/// represents an implicit application of a constructor or destructor. Qualifiers are replaced
+/// immediately before and after the call so that qualified objects can be constructed
+/// with the same functions as unqualified objects.
+class ImplicitCtorDtorStmt : public Statement {
+  public:
+	ImplicitCtorDtorStmt( Statement * callStmt );
+	ImplicitCtorDtorStmt( const ImplicitCtorDtorStmt & other );
+	virtual ~ImplicitCtorDtorStmt();
+
+	Statement *get_callStmt() const { return callStmt; }
+	void set_callStmt( Statement * newValue ) { callStmt = newValue; }
+
+	virtual ImplicitCtorDtorStmt *clone() const { return new ImplicitCtorDtorStmt( *this ); }
+	virtual void accept( Visitor &v ) { v.visit( this ); }
+	virtual Statement *acceptMutator( Mutator &m ) { return m.mutate( this ); }
+	virtual void print( std::ostream &os, int indent = 0 ) const;
+
+  private:
+	// Non-owned pointer to the constructor/destructor statement
+	Statement * callStmt;
+};
+
 
 std::ostream & operator<<( std::ostream & out, Statement * statement );
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/SynTree.h	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -56,4 +56,5 @@
 class DeclStmt;
 class NullStmt;
+class ImplicitCtorDtorStmt;
 
 class Expression;
@@ -117,4 +118,7 @@
 class TypeSubstitution;
 
+// gcc attribute
+class Attribute;
+
 #endif // SYNTREE_H
 
Index: src/SynTree/Type.cc
===================================================================
--- src/SynTree/Type.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Type.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Type.cc -- 
+// Type.cc --
 //
 // Author           : Richard C. Bilson
@@ -54,4 +54,25 @@
 }
 
+void Type::Qualifiers::print( std::ostream &os, int indent ) const {
+	if ( isConst ) {
+		os << "const ";
+	} // if
+	if ( isVolatile ) {
+		os << "volatile ";
+	} // if
+	if ( isRestrict ) {
+		os << "restrict ";
+	} // if
+	if ( isLvalue ) {
+		os << "lvalue ";
+	} // if
+	if ( isAtomic ) {
+		os << "_Atomic ";
+	} // if
+	if ( isAttribute ) {
+		os << "__attribute(( )) ";
+	} // if
+}
+
 void Type::print( std::ostream &os, int indent ) const {
 	if ( ! forall.empty() ) {
@@ -60,22 +81,5 @@
 		os << std::string( indent+2, ' ' );
 	} // if
-	if ( tq.isConst ) {
-		os << "const ";
-	} // if
-	if ( tq.isVolatile ) {
-		os << "volatile ";
-	} // if
-	if ( tq.isRestrict ) {
-		os << "restrict ";
-	} // if
-	if ( tq.isLvalue ) {
-		os << "lvalue ";
-	} // if
-	if ( tq.isAtomic ) {
-		os << "_Atomic ";
-	} // if
-	if ( tq.isAttribute ) {
-		os << "__attribute(( )) ";
-	} // if
+	tq.print( os, indent );
 }
 
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Type.h	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -36,4 +36,5 @@
 		bool operator<( const Qualifiers &other );
 		bool operator>( const Qualifiers &other );
+		void print( std::ostream &os, int indent = 0 ) const;
 
 		bool isConst;
Index: src/SynTree/Visitor.cc
===================================================================
--- src/SynTree/Visitor.cc	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Visitor.cc	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -152,4 +152,8 @@
 }
 
+void Visitor::visit( ImplicitCtorDtorStmt *impCtorDtorStmt ) {
+	maybeAccept( impCtorDtorStmt->get_callStmt(), *this );
+}
+
 void Visitor::visit( ApplicationExpr *applicationExpr ) {
 	acceptAll( applicationExpr->get_results(), *this );
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/Visitor.h	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -52,4 +52,5 @@
 	virtual void visit( NullStmt *nullStmt );
 	virtual void visit( DeclStmt *declStmt );
+	virtual void visit( ImplicitCtorDtorStmt *impCtorDtorStmt );
 
 	virtual void visit( ApplicationExpr *applicationExpr );
Index: src/SynTree/module.mk
===================================================================
--- src/SynTree/module.mk	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/SynTree/module.mk	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -6,5 +6,5 @@
 ## file "LICENCE" distributed with Cforall.
 ##
-## module.mk -- 
+## module.mk --
 ##
 ## Author           : Richard C. Bilson
@@ -46,4 +46,5 @@
        SynTree/Visitor.cc \
        SynTree/Mutator.cc \
-       SynTree/TypeSubstitution.cc
+       SynTree/TypeSubstitution.cc \
+       SynTree/Attribute.cc
 
Index: src/examples/avltree/avl-private.h
===================================================================
--- src/examples/avltree/avl-private.h	(revision e04ef3a33b7695190c509b61da6fe0cfcf46b265)
+++ src/examples/avltree/avl-private.h	(revision c8c03683ab886c6aabc128b60ed569f8abadd1c6)
@@ -1,2 +1,3 @@
+#ifndef AVL_PRIVATE_H
 #include "avl.h"
 
@@ -13,2 +14,4 @@
 forall(otype K | Comparable(K), otype V)
 int height(tree(K, V) * t);
+
+#endif
