Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ src/CodeGen/CodeGenerator.cc	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
@@ -21,8 +21,9 @@
 #include "Parser/ParseNode.h"
 
-#include "SynTree/Type.h"
+#include "SynTree/Declaration.h"
 #include "SynTree/Expression.h"
 #include "SynTree/Initializer.h"
 #include "SynTree/Statement.h"
+#include "SynTree/Type.h"
 
 #include "Common/utility.h"
Index: src/CodeGen/CodeGenerator.h
===================================================================
--- src/CodeGen/CodeGenerator.h	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ src/CodeGen/CodeGenerator.h	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
@@ -19,6 +19,8 @@
 #include <list>
 
+#include "SynTree/Declaration.h"
 #include "SynTree/SynTree.h"
 #include "SynTree/Visitor.h"
+
 #include "SymTab/Indexer.h"
 
Index: src/CodeGen/GenType.cc
===================================================================
--- src/CodeGen/GenType.cc	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ src/CodeGen/GenType.cc	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
@@ -19,7 +19,9 @@
 #include "GenType.h"
 #include "CodeGenerator.h"
+
+#include "SynTree/Declaration.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Type.h"
 #include "SynTree/Visitor.h"
-#include "SynTree/Type.h"
-#include "SynTree/Expression.h"
 
 namespace CodeGen {
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ src/GenPoly/Box.cc	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
@@ -14,15 +14,20 @@
 //
 
+#include <algorithm>
+#include <iterator>
+#include <list>
+#include <map>
 #include <set>
 #include <stack>
 #include <string>
-#include <iterator>
-#include <algorithm>
+#include <utility>
+#include <vector>
 #include <cassert>
 
 #include "Box.h"
-#include "InstantiateGeneric.h"
+#include "DeclMutator.h"
 #include "PolyMutator.h"
 #include "FindFunction.h"
+#include "ScopedMap.h"
 #include "ScrubTyVars.h"
 
@@ -30,9 +35,11 @@
 
 #include "SynTree/Constant.h"
-#include "SynTree/Type.h"
+#include "SynTree/Declaration.h"
 #include "SynTree/Expression.h"
 #include "SynTree/Initializer.h"
+#include "SynTree/Mutator.h"
 #include "SynTree/Statement.h"
-#include "SynTree/Mutator.h"
+#include "SynTree/Type.h"
+#include "SynTree/TypeSubstitution.h"
 
 #include "ResolvExpr/TypeEnvironment.h"
@@ -40,4 +47,5 @@
 #include "ResolvExpr/typeops.h"
 
+#include "SymTab/Indexer.h"
 #include "SymTab/Mangler.h"
 
@@ -54,4 +62,121 @@
 		FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars );
 
+		/// Key for a unique concrete type; generic base type paired with type parameter list
+		struct ConcreteType {
+			ConcreteType() : base(NULL), params() {}
+
+			ConcreteType(AggregateDecl *_base, const std::list< Type* >& _params) : base(_base), params() { cloneAll(_params, params); }
+
+			ConcreteType(const ConcreteType& that) : base(that.base), params() { cloneAll(that.params, params); }
+
+			/// Extracts types from a list of TypeExpr*
+			ConcreteType(AggregateDecl *_base, const std::list< TypeExpr* >& _params) : base(_base), params() {
+				for ( std::list< TypeExpr* >::const_iterator param = _params.begin(); param != _params.end(); ++param ) {
+					params.push_back( (*param)->get_type()->clone() );
+				}
+			}
+
+			ConcreteType& operator= (const ConcreteType& that) {
+				deleteAll( params );
+				params.clear();
+
+				base = that.base;
+				cloneAll( that.params, params );
+
+				return *this;
+			}
+
+			~ConcreteType() { deleteAll( params ); }
+
+			bool operator== (const ConcreteType& that) const {
+				if ( base != that.base ) return false;
+
+				SymTab::Indexer dummy;
+				if ( params.size() != that.params.size() ) return false;
+				for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) {
+					if ( ! ResolvExpr::typesCompatible( *it, *jt, dummy ) ) return false;
+				}
+				return true;
+			}
+
+			AggregateDecl *base;        ///< Base generic type
+			std::list< Type* > params;  ///< Instantiation parameters
+		};
+
+		/// Maps a concrete type to the some value, accounting for scope
+		template< typename Value >
+		class InstantiationMap {
+			/// Information about a specific instantiation of a generic type
+			struct Instantiation {
+				ConcreteType key;  ///< Instantiation parameters for this type
+				Value *value;      ///< Value for this instantiation
+
+				Instantiation() : key(), value(0) {}
+				Instantiation(const ConcreteType &_key, Value *_value) : key(_key), value(_value) {}
+			};
+			/// Map of generic types to instantiations of them
+			typedef std::map< AggregateDecl*, std::vector< Instantiation > > Scope;
+
+			std::vector< Scope > scopes;  ///< list of scopes, from outermost to innermost
+
+		public:
+			/// Starts a new scope
+			void beginScope() {
+				Scope scope;
+				scopes.push_back(scope);
+			}
+
+			/// Ends a scope
+			void endScope() {
+				scopes.pop_back();
+			}
+
+			/// Default constructor initializes with one scope
+			InstantiationMap() { beginScope(); }
+
+//		private:
+			/// Gets the value for the concrete instantiation of this type, assuming it has already been instantiated in the current scope.
+			/// Returns NULL on none such.
+			Value *lookup( AggregateDecl *generic, const std::list< TypeExpr* >& params ) {
+				ConcreteType key(generic, params);
+				// scan scopes from innermost out
+				for ( typename std::vector< Scope >::const_reverse_iterator scope = scopes.rbegin(); scope != scopes.rend(); ++scope ) {
+					// skip scope if no instantiations of this generic type
+					typename Scope::const_iterator insts = scope->find( generic );
+					if ( insts == scope->end() ) continue;
+					// look through instantiations for matches to concrete type
+					for ( typename std::vector< Instantiation >::const_iterator inst = insts->second.begin(); inst != insts->second.end(); ++inst ) {
+						if ( inst->key == key ) return inst->value;
+					}
+				}
+				// no matching instantiation found
+				return 0;
+			}
+		public:
+//			StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)lookup( inst->get_baseStruct(), typeSubs ); }
+//			UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)lookup( inst->get_baseUnion(), typeSubs ); }
+
+//		private:
+			/// Adds a value for a concrete type to the current scope
+			void insert( AggregateDecl *generic, const std::list< TypeExpr* > &params, Value *value ) {
+				ConcreteType key(generic, params);
+				scopes.back()[generic].push_back( Instantiation( key, value ) );
+			}
+//		public:
+//			void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { insert( inst->get_baseStruct(), typeSubs, decl ); }
+//			void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { insert( inst->get_baseUnion(), typeSubs, decl ); }
+		};
+
+		/// Adds layout-generation functions to polymorphic types
+		class LayoutFunctionBuilder : public DeclMutator {
+			unsigned int functionNesting;  // current level of nested functions
+		public:
+			LayoutFunctionBuilder() : functionNesting( 0 ) {}
+
+			virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );
+			virtual Declaration *mutate( StructDecl *structDecl );
+			virtual Declaration *mutate( UnionDecl *unionDecl );
+		};
+		
 		/// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call
 		class Pass1 : public PolyMutator {
@@ -100,8 +225,7 @@
 			ObjectDecl *makeTemporary( Type *type );
 
-			typedef std::map< std::string, DeclarationWithType *> AdapterMap;
 			std::map< std::string, DeclarationWithType *> assignOps;
 			ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps;
-			std::stack< AdapterMap > adapters;
+			ScopedMap< std::string, DeclarationWithType* > adapters;
 			DeclarationWithType *retval;
 			bool useRetval;
@@ -124,4 +248,32 @@
 
 			std::map< UniqueId, std::string > adapterName;
+		};
+
+		/// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
+		class GenericInstantiator : public DeclMutator {
+			/// Map of (generic type, parameter list) pairs to concrete type instantiations
+			InstantiationMap< AggregateDecl > instantiations;
+			/// Namer for concrete types
+			UniqueName typeNamer;
+
+		public:
+			GenericInstantiator() : DeclMutator(), instantiations(), typeNamer("_conc_") {}
+
+			virtual Type* mutate( StructInstType *inst );
+			virtual Type* mutate( UnionInstType *inst );
+
+	// 		virtual Expression* mutate( MemberExpr *memberExpr );
+
+			virtual void doBeginScope();
+			virtual void doEndScope();
+		private:
+			/// Wrap instantiation lookup for structs
+			StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)instantiations.lookup( inst->get_baseStruct(), typeSubs ); }
+			/// Wrap instantiation lookup for unions
+			UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)instantiations.lookup( inst->get_baseUnion(), typeSubs ); }
+			/// Wrap instantiation insertion for structs
+			void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { instantiations.insert( inst->get_baseStruct(), typeSubs, decl ); }
+			/// Wrap instantiation insertion for unions
+			void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { instantiations.insert( inst->get_baseUnion(), typeSubs, decl ); }
 		};
 
@@ -159,13 +311,4 @@
 	} // anonymous namespace
 
-	void printAllNotBuiltin( const std::list< Declaration *>& translationUnit, std::ostream &os ) {
-		for ( std::list< Declaration *>::const_iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
-			if ( ! LinkageSpec::isBuiltin( (*i)->get_linkage() ) ) {
-				(*i)->print( os );
-				os << std::endl;
-			} // if
-		} // for
-	}
-
 	/// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging
 	template< typename MutatorType >
@@ -195,15 +338,218 @@
 
 	void box( std::list< Declaration *>& translationUnit ) {
+		LayoutFunctionBuilder layoutBuilder;
 		Pass1 pass1;
 		Pass2 pass2;
+		GenericInstantiator instantiator;
 		MemberExprFixer memberFixer;
 		Pass3 pass3;
+		
+		layoutBuilder.mutateDeclarationList( translationUnit );
 		mutateTranslationUnit/*All*/( translationUnit, pass1 );
 		mutateTranslationUnit/*All*/( translationUnit, pass2 );
-		instantiateGeneric( translationUnit );
+//		instantiateGeneric( translationUnit );
+		instantiator.mutateDeclarationList( translationUnit );
 		mutateTranslationUnit/*All*/( translationUnit, memberFixer );
 		mutateTranslationUnit/*All*/( translationUnit, pass3 );
 	}
 
+	////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////
+
+	DeclarationWithType *LayoutFunctionBuilder::mutate( FunctionDecl *functionDecl ) {
+		functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
+		mutateAll( functionDecl->get_oldDecls(), *this );
+		++functionNesting;
+		functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
+		--functionNesting;
+		return functionDecl;
+	}
+	
+	/// Get a list of type declarations that will affect a layout function
+	std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) {
+		std::list< TypeDecl * > otypeDecls;
+
+		for ( std::list< TypeDecl* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
+			if ( (*decl)->get_kind() == TypeDecl::Any ) {
+				otypeDecls.push_back( *decl );
+			}
+		}
+		
+		return otypeDecls;
+	}
+
+	/// Adds parameters for otype layout to a function type
+	void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) {
+		BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt );
+		
+		for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
+			TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param );
+			layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( &paramType ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
+			layoutFnType->get_parameters().push_back( new ObjectDecl( alignofName( &paramType ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
+		}
+	}
+
+	/// Builds a layout function declaration
+	FunctionDecl *buildLayoutFunctionDecl( const std::string &typeName, unsigned int functionNesting, FunctionType *layoutFnType ) {
+		// 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.
+		FunctionDecl *layoutDecl = new FunctionDecl(
+			"__layoutof_" + typeName, functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false );
+		layoutDecl->fixUniqueId();
+		return layoutDecl;
+	}
+
+	/// Makes a unary operation
+	Expression *makeOp( const std::string &name, Expression *arg ) {
+		UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
+		expr->get_args().push_back( arg );
+		return expr;
+	}
+
+	/// Makes a binary operation
+	Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) {
+		UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
+		expr->get_args().push_back( lhs );
+		expr->get_args().push_back( rhs );
+		return expr;
+	}
+
+	/// Returns the dereference of a local pointer variable
+	Expression *derefVar( ObjectDecl *var ) {
+		return makeOp( "*?", new VariableExpr( var ) );
+	}
+
+	/// makes an if-statement with a single-expression if-block and no then block
+	Statement *makeCond( Expression *cond, Expression *ifPart ) {
+		return new IfStmt( noLabels, cond, new ExprStmt( noLabels, ifPart ), 0 );
+	}
+
+	/// makes a statement that assigns rhs to lhs if lhs < rhs
+	Statement *makeAssignMax( Expression *lhs, Expression *rhs ) {
+		return makeCond( makeOp( "?<?", lhs, rhs ), makeOp( "?=?", lhs->clone(), rhs->clone() ) );
+	}
+
+	/// makes a statement that aligns lhs to rhs (rhs should be an integer power of two)
+	Statement *makeAlignTo( Expression *lhs, Expression *rhs ) {
+		// check that the lhs is zeroed out to the level of rhs
+		Expression *ifCond = makeOp( "?&?", lhs, makeOp( "?-?", rhs, new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "1" ) ) ) );
+		// if not aligned, increment to alignment
+		Expression *ifExpr = makeOp( "?+=?", lhs->clone(), makeOp( "?-?", rhs->clone(), ifCond->clone() ) );
+		return makeCond( ifCond, ifExpr );
+	}
+	
+	/// adds an expression to a compound statement
+	void addExpr( CompoundStmt *stmts, Expression *expr ) {
+		stmts->get_kids().push_back( new ExprStmt( noLabels, expr ) );
+	}
+
+	/// adds a statement to a compound statement
+	void addStmt( CompoundStmt *stmts, Statement *stmt ) {
+		stmts->get_kids().push_back( stmt );
+	}
+	
+	Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {
+		// do not generate layout function for "empty" tag structs
+		if ( structDecl->get_members().empty() ) return structDecl;
+
+		// get parameters that can change layout, exiting early if none
+		std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() );
+		if ( otypeParams.empty() ) return structDecl;
+
+		// build layout function signature
+		FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
+		BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
+		PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
+		
+		ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
+		layoutFnType->get_parameters().push_back( sizeParam );
+		ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
+		layoutFnType->get_parameters().push_back( alignParam );
+		ObjectDecl *offsetParam = new ObjectDecl( "__offsetof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
+		layoutFnType->get_parameters().push_back( offsetParam );
+		addOtypeParams( layoutFnType, otypeParams );
+
+		// build function decl
+		FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl->get_name(), functionNesting, layoutFnType );
+
+		// calculate struct layout in function body
+
+		// initialize size and alignment to 0 and 1 (will have at least one member to re-edit size
+		addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "0" ) ) ) );
+		addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
+		unsigned long n_members = 0;
+		bool firstMember = true;
+		for ( std::list< Declaration* >::const_iterator member = structDecl->get_members().begin(); member != structDecl->get_members().end(); ++member ) {
+			DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
+			assert( dwt );
+			Type *memberType = dwt->get_type();
+
+			if ( firstMember ) {
+				firstMember = false;
+			} else {
+				// make sure all members after the first (automatically aligned at 0) are properly padded for alignment
+				addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) );
+			}
+			
+			// place current size in the current offset index
+			addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from( n_members ) ) ),
+			                                                      derefVar( sizeParam ) ) );
+			++n_members;
+
+			// add member size to current size
+			addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
+			
+			// take max of member alignment and global alignment
+			addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
+		}
+		// make sure the type is end-padded to a multiple of its alignment
+		addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
+
+		addDeclarationAfter( layoutDecl );
+		return structDecl;
+	}
+	
+	Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {
+		// do not generate layout function for "empty" tag unions
+		if ( unionDecl->get_members().empty() ) return unionDecl;
+		
+		// get parameters that can change layout, exiting early if none
+		std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );
+		if ( otypeParams.empty() ) return unionDecl;
+
+		// build layout function signature
+		FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
+		BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
+		PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
+		
+		ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
+		layoutFnType->get_parameters().push_back( sizeParam );
+		ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
+		layoutFnType->get_parameters().push_back( alignParam );
+		addOtypeParams( layoutFnType, otypeParams );
+
+		// build function decl
+		FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl->get_name(), functionNesting, layoutFnType );
+
+		// calculate union layout in function body
+		addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
+		addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
+		for ( std::list< Declaration* >::const_iterator member = unionDecl->get_members().begin(); member != unionDecl->get_members().end(); ++member ) {
+			DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
+			assert( dwt );
+			Type *memberType = dwt->get_type();
+			
+			// take max member size and global size
+			addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
+			
+			// take max of member alignment and global alignment
+			addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
+		}
+		// make sure the type is end-padded to a multiple of its alignment
+		addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
+
+		addDeclarationAfter( layoutDecl );
+		return unionDecl;
+	}
+	
 	////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////
 
@@ -245,7 +591,5 @@
 		}
 
-		Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {
-			adapters.push(AdapterMap());
-		}
+		Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {}
 
 		/// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
@@ -350,5 +694,4 @@
 				} // for
 
-				AdapterMap & adapters = Pass1::adapters.top();
 				for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
 					std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
@@ -772,10 +1115,11 @@
 					mangleName += makePolyMonoSuffix( originalFunction, exprTyVars );
 
-					AdapterMap & adapters = Pass1::adapters.top();
-					AdapterMap::iterator adapter = adapters.find( mangleName );
+					typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
+					AdapterIter adapter = adapters.find( mangleName );
 					if ( adapter == adapters.end() ) {
 						// adapter has not been created yet in the current scope, so define it
 						FunctionDecl *newAdapter = makeAdapter( *funType, realFunction, mangleName, exprTyVars );
-						adapter = adapters.insert( adapters.begin(), std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
+						std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
+						adapter = answer.first;
 						stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) );
 					} // if
@@ -1156,11 +1500,10 @@
 
 		void Pass1::doBeginScope() {
-			// push a copy of the current map
-			adapters.push(adapters.top());
+			adapters.beginScope();
 			scopedAssignOps.beginScope();
 		}
 
 		void Pass1::doEndScope() {
-			adapters.pop();
+			adapters.endScope();
 			scopedAssignOps.endScope();
 		}
@@ -1309,4 +1652,193 @@
 		}
 
+//////////////////////////////////////// GenericInstantiator //////////////////////////////////////////////////
+
+		/// Makes substitutions of params into baseParams; returns true if all parameters substituted for a concrete type
+		bool makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) {
+			bool allConcrete = true;  // will finish the substitution list even if they're not all concrete
+
+			// substitute concrete types for given parameters, and incomplete types for placeholders
+			std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
+			std::list< Expression* >::const_iterator param = params.begin();
+			for ( ; baseParam != baseParams.end() && param != params.end(); ++baseParam, ++param ) {
+	// 			switch ( (*baseParam)->get_kind() ) {
+	// 			case TypeDecl::Any: {   // any type is a valid substitution here; complete types can be used to instantiate generics
+					TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
+					assert(paramType && "Aggregate parameters should be type expressions");
+					out.push_back( paramType->clone() );
+					// check that the substituted type isn't a type variable itself
+					if ( dynamic_cast< TypeInstType* >( paramType->get_type() ) ) {
+						allConcrete = false;
+					}
+	// 				break;
+	// 			}
+	// 			case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
+	// 				out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
+	// 				break;
+	// 			case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
+	// 				out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
+	// 				break;
+	// 			}
+			}
+
+			// if any parameters left over, not done
+			if ( baseParam != baseParams.end() ) return false;
+	// 		// if not enough parameters given, substitute remaining incomplete types for placeholders
+	// 		for ( ; baseParam != baseParams.end(); ++baseParam ) {
+	// 			switch ( (*baseParam)->get_kind() ) {
+	// 			case TypeDecl::Any:    // no more substitutions here, fail early
+	// 				return false;
+	// 			case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
+	// 				out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
+	// 				break;
+	// 			case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
+	// 				out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
+	// 				break;
+	// 			}
+	// 		}
+
+			return allConcrete;
+		}
+
+		/// Substitutes types of members of in according to baseParams => typeSubs, appending the result to out
+		void substituteMembers( const std::list< Declaration* >& in, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs,
+								std::list< Declaration* >& out ) {
+			// substitute types into new members
+			TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
+			for ( std::list< Declaration* >::const_iterator member = in.begin(); member != in.end(); ++member ) {
+				Declaration *newMember = (*member)->clone();
+				subs.apply(newMember);
+				out.push_back( newMember );
+			}
+		}
+
+		Type* GenericInstantiator::mutate( StructInstType *inst ) {
+			// mutate subtypes
+			Type *mutated = Mutator::mutate( inst );
+			inst = dynamic_cast< StructInstType* >( mutated );
+			if ( ! inst ) return mutated;
+
+			// exit early if no need for further mutation
+			if ( inst->get_parameters().empty() ) return inst;
+			assert( inst->get_baseParameters() && "Base struct has parameters" );
+
+			// check if type can be concretely instantiated; put substitutions into typeSubs
+			std::list< TypeExpr* > typeSubs;
+			if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
+				deleteAll( typeSubs );
+				return inst;
+			}
+
+			// make concrete instantiation of generic type
+			StructDecl *concDecl = lookup( inst, typeSubs );
+			if ( ! concDecl ) {
+				// set concDecl to new type, insert type declaration into statements to add
+				concDecl = new StructDecl( typeNamer.newName( inst->get_name() ) );
+				substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs, 	concDecl->get_members() );
+				DeclMutator::addDeclaration( concDecl );
+				insert( inst, typeSubs, concDecl );
+			}
+			StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() );
+			newInst->set_baseStruct( concDecl );
+
+			deleteAll( typeSubs );
+			delete inst;
+			return newInst;
+		}
+
+		Type* GenericInstantiator::mutate( UnionInstType *inst ) {
+			// mutate subtypes
+			Type *mutated = Mutator::mutate( inst );
+			inst = dynamic_cast< UnionInstType* >( mutated );
+			if ( ! inst ) return mutated;
+
+			// exit early if no need for further mutation
+			if ( inst->get_parameters().empty() ) return inst;
+			assert( inst->get_baseParameters() && "Base union has parameters" );
+
+			// check if type can be concretely instantiated; put substitutions into typeSubs
+			std::list< TypeExpr* > typeSubs;
+			if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
+				deleteAll( typeSubs );
+				return inst;
+			}
+
+			// make concrete instantiation of generic type
+			UnionDecl *concDecl = lookup( inst, typeSubs );
+			if ( ! concDecl ) {
+				// set concDecl to new type, insert type declaration into statements to add
+				concDecl = new UnionDecl( typeNamer.newName( inst->get_name() ) );
+				substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
+				DeclMutator::addDeclaration( concDecl );
+				insert( inst, typeSubs, concDecl );
+			}
+			UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() );
+			newInst->set_baseUnion( concDecl );
+
+			deleteAll( typeSubs );
+			delete inst;
+			return newInst;
+		}
+
+	// 	/// Gets the base struct or union declaration for a member expression; NULL if not applicable
+	// 	AggregateDecl* getMemberBaseDecl( MemberExpr *memberExpr ) {
+	// 		// get variable for member aggregate
+	// 		VariableExpr *varExpr = dynamic_cast< VariableExpr* >( memberExpr->get_aggregate() );
+	// 		if ( ! varExpr ) return NULL;
+	//
+	// 		// get object for variable
+	// 		ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );
+	// 		if ( ! objectDecl ) return NULL;
+	//
+	// 		// get base declaration from object type
+	// 		Type *objectType = objectDecl->get_type();
+	// 		StructInstType *structType = dynamic_cast< StructInstType* >( objectType );
+	// 		if ( structType ) return structType->get_baseStruct();
+	// 		UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType );
+	// 		if ( unionType ) return unionType->get_baseUnion();
+	//
+	// 		return NULL;
+	// 	}
+	//
+	// 	/// Finds the declaration with the given name, returning decls.end() if none such
+	// 	std::list< Declaration* >::const_iterator findDeclNamed( const std::list< Declaration* > &decls, const std::string &name ) {
+	// 		for( std::list< Declaration* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
+	// 			if ( (*decl)->get_name() == name ) return decl;
+	// 		}
+	// 		return decls.end();
+	// 	}
+	//
+	// 	Expression* Instantiate::mutate( MemberExpr *memberExpr ) {
+	// 		// mutate, exiting early if no longer MemberExpr
+	// 		Expression *expr = Mutator::mutate( memberExpr );
+	// 		memberExpr = dynamic_cast< MemberExpr* >( expr );
+	// 		if ( ! memberExpr ) return expr;
+	//
+	// 		// get declaration of member and base declaration of member, exiting early if not found
+	// 		AggregateDecl *memberBase = getMemberBaseDecl( memberExpr );
+	// 		if ( ! memberBase ) return memberExpr;
+	// 		DeclarationWithType *memberDecl = memberExpr->get_member();
+	// 		std::list< Declaration* >::const_iterator baseIt = findDeclNamed( memberBase->get_members(), memberDecl->get_name() );
+	// 		if ( baseIt == memberBase->get_members().end() ) return memberExpr;
+	// 		DeclarationWithType *baseDecl = dynamic_cast< DeclarationWithType* >( *baseIt );
+	// 		if ( ! baseDecl ) return memberExpr;
+	//
+	// 		// check if stated type of the member is not the type of the member's declaration; if so, need a cast
+	// 		// this *SHOULD* be safe, I don't think anything but the void-replacements I put in for dtypes would make it past the typechecker
+	// 		SymTab::Indexer dummy;
+	// 		if ( ResolvExpr::typesCompatible( memberDecl->get_type(), baseDecl->get_type(), dummy ) ) return memberExpr;
+	// 		else return new CastExpr( memberExpr, memberDecl->get_type() );
+	// 	}
+
+		void GenericInstantiator::doBeginScope() {
+			DeclMutator::doBeginScope();
+			instantiations.beginScope();
+		}
+
+		void GenericInstantiator::doEndScope() {
+			DeclMutator::doEndScope();
+			instantiations.endScope();
+		}
+
 ////////////////////////////////////////// MemberExprFixer ////////////////////////////////////////////////////
 
Index: src/GenPoly/DeclMutator.cc
===================================================================
--- src/GenPoly/DeclMutator.cc	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ src/GenPoly/DeclMutator.cc	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
@@ -24,10 +24,15 @@
 	}
 
-	DeclMutator::DeclMutator() : Mutator(), declsToAdd(1) {}
+	DeclMutator::DeclMutator() : Mutator(), declsToAdd(1), declsToAddAfter(1) {}
 
 	DeclMutator::~DeclMutator() {}
 	
 	void DeclMutator::mutateDeclarationList( std::list< Declaration* > &decls ) {
-		for ( std::list< Declaration* >::iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
+		for ( std::list< Declaration* >::iterator decl = decls.begin(); ; ++decl ) {
+			// splice in new declarations after previous decl
+			decls.splice( decl, declsToAddAfter.back() );
+
+			if ( decl == decls.end() ) break;
+			
 			// run mutator on declaration
 			*decl = maybeMutate( *decl, *this );
@@ -39,6 +44,7 @@
 
 	void DeclMutator::doBeginScope() {
-		// add new decl list for inside of scope
+		// add new decl lists for inside of scope
 		declsToAdd.resize( declsToAdd.size()+1 );
+		declsToAddAfter.resize( declsToAddAfter.size()+1 );
 	}
 
@@ -49,4 +55,9 @@
 		newBack->splice( newBack->end(), *back );
 		declsToAdd.pop_back();
+		
+		back = declsToAddAfter.rbegin();
+		newBack = back + 1;
+		newBack->splice( newBack->end(), *back );
+		declsToAddAfter.pop_back();
 	}
 
@@ -61,5 +72,8 @@
 		stmt = maybeMutate( stmt, *this );
 		// return if no declarations to add
-		if ( declsToAdd.back().empty() ) return stmt;
+		if ( declsToAdd.back().empty() && declsToAddAfter.back().empty() ) {
+			doEndScope();
+			return stmt;
+		}
 
 		// otherwise add declarations to new compound statement
@@ -71,8 +85,15 @@
 		declsToAdd.back().clear();
 
+		// add mutated statement
+		compound->get_kids().push_back( stmt );
+
+		// add declarations after to new compound statement
+		for ( std::list< Declaration* >::iterator decl = declsToAddAfter.back().begin(); decl != declsToAddAfter.back().end(); ++decl ) {
+			DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
+			compound->get_kids().push_back( declStmt );
+		}
+		declsToAddAfter.back().clear();
+
 		doEndScope();
-
-		// add mutated statement and return
-		compound->get_kids().push_back( stmt );
 		return compound;
 	}
@@ -80,6 +101,16 @@
 	void DeclMutator::mutateStatementList( std::list< Statement* > &stmts ) {
 		doBeginScope();
+
 		
-		for ( std::list< Statement* >::iterator stmt = stmts.begin(); stmt != stmts.end(); ++stmt ) {
+		for ( std::list< Statement* >::iterator stmt = stmts.begin(); ; ++stmt ) {
+			// add any new declarations after the previous statement
+			for ( std::list< Declaration* >::iterator decl = declsToAddAfter.back().begin(); decl != declsToAddAfter.back().end(); ++decl ) {
+				DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
+				stmts.insert( stmt, declStmt );
+			}
+			declsToAddAfter.back().clear();
+
+			if ( stmt == stmts.end() ) break;
+			
 			// run mutator on statement
 			*stmt = maybeMutate( *stmt, *this );
@@ -92,5 +123,5 @@
 			declsToAdd.back().clear();
 		}
-
+		
 		doEndScope();
 	}
@@ -98,4 +129,8 @@
 	void DeclMutator::addDeclaration( Declaration *decl ) {
 		declsToAdd.back().push_back( decl );
+	}
+
+	void DeclMutator::addDeclarationAfter( Declaration *decl ) {
+		declsToAddAfter.back().push_back( decl );
 	}
 
Index: src/GenPoly/DeclMutator.h
===================================================================
--- src/GenPoly/DeclMutator.h	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ src/GenPoly/DeclMutator.h	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
@@ -55,7 +55,11 @@
 		/// Add a declaration to the list to be added before the current position
 		void addDeclaration( Declaration* decl );
+		/// Add a declaration to the list to be added after the current position
+		void addDeclarationAfter( Declaration* decl );
 	private:
 		/// A stack of declarations to add before the current declaration or statement
 		std::vector< std::list< Declaration* > > declsToAdd;
+		/// A stack of declarations to add after the current declaration or statement
+		std::vector< std::list< Declaration* > > declsToAddAfter;
 	};
 } // namespace
Index: c/GenPoly/InstantiateGeneric.cc
===================================================================
--- src/GenPoly/InstantiateGeneric.cc	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ 	(revision )
@@ -1,360 +1,0 @@
-//
-// 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.
-//
-// InstantiateGeneric.cc --
-//
-// Author           : Aaron B. Moss
-// Created On       : Wed Nov 11 14:55:01 2015
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Wed Nov 11 14:55:01 2015
-// Update Count     : 1
-//
-
-#include <list>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "InstantiateGeneric.h"
-#include "DeclMutator.h"
-
-#include "ResolvExpr/typeops.h"
-#include "SymTab/Indexer.h"
-#include "SynTree/Declaration.h"
-#include "SynTree/Mutator.h"
-#include "SynTree/Statement.h"
-#include "SynTree/Type.h"
-#include "SynTree/TypeSubstitution.h"
-
-#include "Common/UniqueName.h"
-#include "Common/utility.h"
-
-namespace GenPoly {
-
-	/// Key for a unique concrete type; generic base type paired with type parameter list
-	struct ConcreteType {
-		ConcreteType() : base(NULL), params() {}
-
-		ConcreteType(AggregateDecl *_base, const std::list< Type* >& _params) : base(_base), params() { cloneAll(_params, params); }
-
-		ConcreteType(const ConcreteType& that) : base(that.base), params() { cloneAll(that.params, params); }
-
-		/// Extracts types from a list of TypeExpr*
-		ConcreteType(AggregateDecl *_base, const std::list< TypeExpr* >& _params) : base(_base), params() {
-			for ( std::list< TypeExpr* >::const_iterator param = _params.begin(); param != _params.end(); ++param ) {
-				params.push_back( (*param)->get_type()->clone() );
-			}
-		}
-
-		ConcreteType& operator= (const ConcreteType& that) {
-			deleteAll( params );
-			params.clear();
-
-			base = that.base;
-			cloneAll( that.params, params );
-
-			return *this;
-		}
-
-		~ConcreteType() { deleteAll( params ); }
-
-		bool operator== (const ConcreteType& that) const {
-			if ( base != that.base ) return false;
-
-			SymTab::Indexer dummy;
-			if ( params.size() != that.params.size() ) return false;
-			for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) {
-				if ( ! ResolvExpr::typesCompatible( *it, *jt, dummy ) ) return false;
-			}
-			return true;
-		}
-
-		AggregateDecl *base;        ///< Base generic type
-		std::list< Type* > params;  ///< Instantiation parameters
-	};
-	
-	/// Maps a concrete type to the instantiated struct type, accounting for scope
-	class InstantiationMap {
-		/// Instantiation of a generic type, with key information to find it
-		struct Instantiation {
-			ConcreteType key;     ///< Instantiation parameters for this type
-			AggregateDecl *decl;  ///< Declaration of the instantiated generic type
-
-			Instantiation() : key(), decl(0) {}
-			Instantiation(const ConcreteType &_key, AggregateDecl *_decl) : key(_key), decl(_decl) {}
-		};
-		/// Map of generic types to instantiations of them
-		typedef std::map< AggregateDecl*, std::vector< Instantiation > > Scope;
-
-		std::vector< Scope > scopes;  ///< list of scopes, from outermost to innermost
-
-	public:
-		/// Starts a new scope
-		void beginScope() {
-			Scope scope;
-			scopes.push_back(scope);
-		}
-
-		/// Ends a scope
-		void endScope() {
-			scopes.pop_back();
-		}
-
-		/// Default constructor initializes with one scope
-		InstantiationMap() { beginScope(); }
-
-	private:
-		/// Gets the declaration for the concrete instantiation of this type, assuming it has already been instantiated in the current scope.
-		/// Returns NULL on none such.
-		AggregateDecl* lookup( AggregateDecl *generic, const std::list< TypeExpr* >& params ) {
-			ConcreteType key(generic, params);
-			// scan scopes from innermost out
-			for ( std::vector< Scope >::const_reverse_iterator scope = scopes.rbegin(); scope != scopes.rend(); ++scope ) {
-				// skip scope if no instantiations of this generic type
-				Scope::const_iterator insts = scope->find( generic );
-				if ( insts == scope->end() ) continue;
-				// look through instantiations for matches to concrete type
-				for ( std::vector< Instantiation >::const_iterator inst = insts->second.begin(); inst != insts->second.end(); ++inst ) {
-					if ( inst->key == key ) return inst->decl;
-				}
-			}
-			// no matching instantiation found
-			return NULL;
-		}
-	public:
-		StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)lookup( inst->get_baseStruct(), typeSubs ); }
-		UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)lookup( inst->get_baseUnion(), typeSubs ); }
-
-	private:
-		/// Adds a declaration for a concrete type to the current scope
-		void insert( AggregateDecl *generic, const std::list< TypeExpr* > &params, AggregateDecl *decl ) {
-			ConcreteType key(generic, params);
-			scopes.back()[generic].push_back( Instantiation( key, decl ) );
-		}
-	public:
-		void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { insert( inst->get_baseStruct(), typeSubs, decl ); }
-		void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { insert( inst->get_baseUnion(), typeSubs, decl ); }
-	};
-
-	/// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
-	class Instantiate : public DeclMutator {
-		/// Map of (generic type, parameter list) pairs to concrete type instantiations
-		InstantiationMap instantiations;
-		/// Namer for concrete types
-		UniqueName typeNamer;
-
-	public:
-		Instantiate() : DeclMutator(), instantiations(), typeNamer("_conc_") {}
-
-		virtual Type* mutate( StructInstType *inst );
-		virtual Type* mutate( UnionInstType *inst );
-
-// 		virtual Expression* mutate( MemberExpr *memberExpr );
-		
-		virtual void doBeginScope();
-		virtual void doEndScope();
-	};
-	
-	void instantiateGeneric( std::list< Declaration* >& translationUnit ) {
-		Instantiate instantiator;
-		instantiator.mutateDeclarationList( translationUnit );
-	}
-
-	/// Makes substitutions of params into baseParams; returns true if all parameters substituted for a concrete type
-	bool makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) {
- 		bool allConcrete = true;  // will finish the substitution list even if they're not all concrete
-
-		// substitute concrete types for given parameters, and incomplete types for placeholders
-		std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
-		std::list< Expression* >::const_iterator param = params.begin();
-		for ( ; baseParam != baseParams.end() && param != params.end(); ++baseParam, ++param ) {
-// 			switch ( (*baseParam)->get_kind() ) {
-// 			case TypeDecl::Any: {   // any type is a valid substitution here; complete types can be used to instantiate generics
-				TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
-				assert(paramType && "Aggregate parameters should be type expressions");
-				out.push_back( paramType->clone() );
-				// check that the substituted type isn't a type variable itself
-				if ( dynamic_cast< TypeInstType* >( paramType->get_type() ) ) {
- 					allConcrete = false;
-				}
-// 				break;
-// 			}
-// 			case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
-// 				out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
-// 				break;
-// 			case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
-// 				out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
-// 				break;
-// 			}
-		}
-
-		// if any parameters left over, not done
-		if ( baseParam != baseParams.end() ) return false;
-// 		// if not enough parameters given, substitute remaining incomplete types for placeholders
-// 		for ( ; baseParam != baseParams.end(); ++baseParam ) {
-// 			switch ( (*baseParam)->get_kind() ) {
-// 			case TypeDecl::Any:    // no more substitutions here, fail early
-// 				return false;
-// 			case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
-// 				out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
-// 				break;
-// 			case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
-// 				out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
-// 				break;
-// 			}
-// 		}
-
- 		return allConcrete;
-	}
-
-	/// Substitutes types of members of in according to baseParams => typeSubs, appending the result to out
-	void substituteMembers( const std::list< Declaration* >& in, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs, 
-						    std::list< Declaration* >& out ) {
-		// substitute types into new members
-		TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
-		for ( std::list< Declaration* >::const_iterator member = in.begin(); member != in.end(); ++member ) {
-			Declaration *newMember = (*member)->clone();
-			subs.apply(newMember);
-			out.push_back( newMember );
-		}
-	}
-
-	Type* Instantiate::mutate( StructInstType *inst ) {
-		// mutate subtypes
-		Type *mutated = Mutator::mutate( inst );
-		inst = dynamic_cast< StructInstType* >( mutated );
-		if ( ! inst ) return mutated;
-
-		// exit early if no need for further mutation
-		if ( inst->get_parameters().empty() ) return inst;
-		assert( inst->get_baseParameters() && "Base struct has parameters" );
-
-		// check if type can be concretely instantiated; put substitutions into typeSubs
-		std::list< TypeExpr* > typeSubs;
-		if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
-			deleteAll( typeSubs );
-			return inst;
-		}
-		
-		// make concrete instantiation of generic type
-		StructDecl *concDecl = instantiations.lookup( inst, typeSubs );
-		if ( ! concDecl ) {
-			// set concDecl to new type, insert type declaration into statements to add
-			concDecl = new StructDecl( typeNamer.newName( inst->get_name() ) );
-			substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs, 	concDecl->get_members() );
-			DeclMutator::addDeclaration( concDecl );
-			instantiations.insert( inst, typeSubs, concDecl );
-		}
-		StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() );
-		newInst->set_baseStruct( concDecl );
-
-		deleteAll( typeSubs );
-		delete inst;
-		return newInst;
-	}
-	
-	Type* Instantiate::mutate( UnionInstType *inst ) {
-		// mutate subtypes
-		Type *mutated = Mutator::mutate( inst );
-		inst = dynamic_cast< UnionInstType* >( mutated );
-		if ( ! inst ) return mutated;
-
-		// exit early if no need for further mutation
-		if ( inst->get_parameters().empty() ) return inst;
-		assert( inst->get_baseParameters() && "Base union has parameters" );
-
-		// check if type can be concretely instantiated; put substitutions into typeSubs
-		std::list< TypeExpr* > typeSubs;
-		if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
-			deleteAll( typeSubs );
-			return inst;
-		}
-		
-		// make concrete instantiation of generic type
-		UnionDecl *concDecl = instantiations.lookup( inst, typeSubs );
-		if ( ! concDecl ) {
-			// set concDecl to new type, insert type declaration into statements to add
-			concDecl = new UnionDecl( typeNamer.newName( inst->get_name() ) );
-			substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
-			DeclMutator::addDeclaration( concDecl );
-			instantiations.insert( inst, typeSubs, concDecl );
-		}
-		UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() );
-		newInst->set_baseUnion( concDecl );
-
-		deleteAll( typeSubs );
-		delete inst;
-		return newInst;
-	}
-
-// 	/// Gets the base struct or union declaration for a member expression; NULL if not applicable
-// 	AggregateDecl* getMemberBaseDecl( MemberExpr *memberExpr ) {
-// 		// get variable for member aggregate
-// 		VariableExpr *varExpr = dynamic_cast< VariableExpr* >( memberExpr->get_aggregate() );
-// 		if ( ! varExpr ) return NULL;
-// 
-// 		// get object for variable
-// 		ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );
-// 		if ( ! objectDecl ) return NULL;
-// 
-// 		// get base declaration from object type
-// 		Type *objectType = objectDecl->get_type();
-// 		StructInstType *structType = dynamic_cast< StructInstType* >( objectType );
-// 		if ( structType ) return structType->get_baseStruct();
-// 		UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType );
-// 		if ( unionType ) return unionType->get_baseUnion();
-// 
-// 		return NULL;
-// 	}
-// 
-// 	/// Finds the declaration with the given name, returning decls.end() if none such
-// 	std::list< Declaration* >::const_iterator findDeclNamed( const std::list< Declaration* > &decls, const std::string &name ) {
-// 		for( std::list< Declaration* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
-// 			if ( (*decl)->get_name() == name ) return decl;
-// 		}
-// 		return decls.end();
-// 	}
-// 	
-// 	Expression* Instantiate::mutate( MemberExpr *memberExpr ) {
-// 		// mutate, exiting early if no longer MemberExpr
-// 		Expression *expr = Mutator::mutate( memberExpr );
-// 		memberExpr = dynamic_cast< MemberExpr* >( expr );
-// 		if ( ! memberExpr ) return expr;
-// 
-// 		// get declaration of member and base declaration of member, exiting early if not found
-// 		AggregateDecl *memberBase = getMemberBaseDecl( memberExpr );
-// 		if ( ! memberBase ) return memberExpr;
-// 		DeclarationWithType *memberDecl = memberExpr->get_member();
-// 		std::list< Declaration* >::const_iterator baseIt = findDeclNamed( memberBase->get_members(), memberDecl->get_name() );
-// 		if ( baseIt == memberBase->get_members().end() ) return memberExpr;
-// 		DeclarationWithType *baseDecl = dynamic_cast< DeclarationWithType* >( *baseIt );
-// 		if ( ! baseDecl ) return memberExpr;
-// 
-// 		// check if stated type of the member is not the type of the member's declaration; if so, need a cast
-// 		// this *SHOULD* be safe, I don't think anything but the void-replacements I put in for dtypes would make it past the typechecker
-// 		SymTab::Indexer dummy;
-// 		if ( ResolvExpr::typesCompatible( memberDecl->get_type(), baseDecl->get_type(), dummy ) ) return memberExpr;
-// 		else return new CastExpr( memberExpr, memberDecl->get_type() );
-// 	}
-	
-	void Instantiate::doBeginScope() {
-		DeclMutator::doBeginScope();
-		instantiations.beginScope();
-	}
-
-	void Instantiate::doEndScope() {
-		DeclMutator::doEndScope();
-		instantiations.endScope();
-	}
-	
-}  // namespace GenPoly
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/GenPoly/InstantiateGeneric.h
===================================================================
--- src/GenPoly/InstantiateGeneric.h	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ 	(revision )
@@ -1,33 +1,0 @@
-//
-// 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.
-//
-// InstantiateGeneric.h --
-//
-// Author           : Aaron B. Moss
-// Created On       : Wed Nov 11 14:55:01 2015
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Wed Nov 11 14:55:01 2015
-// Update Count     : 1
-//
-
-#ifndef _INSTANTIATEGENERIC_H
-#define _INSTANTIATEGENERIC_H
-
-#include <list>
-#include "SynTree/SynTree.h"
-
-namespace GenPoly {
-	/// Replaces generic structs used outside polymorphic contexts with their concrete instantiations
-	void instantiateGeneric( std::list< Declaration* >& translationUnit );
-} // namespace GenPoly
-
-#endif // _INSTANTIATEGENERIC_H
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/GenPoly/module.mk
===================================================================
--- src/GenPoly/module.mk	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ src/GenPoly/module.mk	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
@@ -23,4 +23,3 @@
        GenPoly/CopyParams.cc \
        GenPoly/FindFunction.cc \
-       GenPoly/InstantiateGeneric.cc \
        GenPoly/DeclMutator.cc
Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ src/Makefile.in	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
@@ -122,5 +122,4 @@
 	GenPoly/driver_cfa_cpp-CopyParams.$(OBJEXT) \
 	GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT) \
-	GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT) \
 	GenPoly/driver_cfa_cpp-DeclMutator.$(OBJEXT) \
 	InitTweak/driver_cfa_cpp-RemoveInit.$(OBJEXT) \
@@ -154,5 +153,4 @@
 	ResolvExpr/driver_cfa_cpp-Occurs.$(OBJEXT) \
 	ResolvExpr/driver_cfa_cpp-TypeEnvironment.$(OBJEXT) \
-	SymTab/driver_cfa_cpp-IdTable.$(OBJEXT) \
 	SymTab/driver_cfa_cpp-Indexer.$(OBJEXT) \
 	SymTab/driver_cfa_cpp-Mangler.$(OBJEXT) \
@@ -347,11 +345,10 @@
 	GenPoly/ScrubTyVars.cc GenPoly/Lvalue.cc GenPoly/Specialize.cc \
 	GenPoly/CopyParams.cc GenPoly/FindFunction.cc \
-	GenPoly/InstantiateGeneric.cc GenPoly/DeclMutator.cc \
-	InitTweak/RemoveInit.cc Parser/parser.yy Parser/lex.ll \
-	Parser/TypedefTable.cc Parser/ParseNode.cc \
-	Parser/DeclarationNode.cc Parser/ExpressionNode.cc \
-	Parser/StatementNode.cc Parser/InitializerNode.cc \
-	Parser/TypeData.cc Parser/LinkageSpec.cc \
-	Parser/parseutility.cc Parser/Parser.cc \
+	GenPoly/DeclMutator.cc InitTweak/RemoveInit.cc \
+	Parser/parser.yy Parser/lex.ll Parser/TypedefTable.cc \
+	Parser/ParseNode.cc Parser/DeclarationNode.cc \
+	Parser/ExpressionNode.cc Parser/StatementNode.cc \
+	Parser/InitializerNode.cc Parser/TypeData.cc \
+	Parser/LinkageSpec.cc Parser/parseutility.cc Parser/Parser.cc \
 	ResolvExpr/AlternativeFinder.cc ResolvExpr/Alternative.cc \
 	ResolvExpr/Unify.cc ResolvExpr/PtrsAssignable.cc \
@@ -362,12 +359,11 @@
 	ResolvExpr/RenameVars.cc ResolvExpr/FindOpenVars.cc \
 	ResolvExpr/PolyCost.cc ResolvExpr/Occurs.cc \
-	ResolvExpr/TypeEnvironment.cc SymTab/IdTable.cc \
-	SymTab/Indexer.cc SymTab/Mangler.cc SymTab/Validate.cc \
-	SymTab/FixFunction.cc SymTab/ImplementationType.cc \
-	SymTab/TypeEquality.cc SynTree/Type.cc SynTree/VoidType.cc \
-	SynTree/BasicType.cc SynTree/PointerType.cc \
-	SynTree/ArrayType.cc SynTree/FunctionType.cc \
-	SynTree/ReferenceToType.cc SynTree/TupleType.cc \
-	SynTree/TypeofType.cc SynTree/AttrType.cc \
+	ResolvExpr/TypeEnvironment.cc SymTab/Indexer.cc \
+	SymTab/Mangler.cc SymTab/Validate.cc SymTab/FixFunction.cc \
+	SymTab/ImplementationType.cc SymTab/TypeEquality.cc \
+	SynTree/Type.cc SynTree/VoidType.cc SynTree/BasicType.cc \
+	SynTree/PointerType.cc SynTree/ArrayType.cc \
+	SynTree/FunctionType.cc SynTree/ReferenceToType.cc \
+	SynTree/TupleType.cc SynTree/TypeofType.cc SynTree/AttrType.cc \
 	SynTree/VarArgsType.cc SynTree/Constant.cc \
 	SynTree/Expression.cc SynTree/TupleExpr.cc \
@@ -556,6 +552,4 @@
 	GenPoly/$(DEPDIR)/$(am__dirstamp)
 GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT):  \
-	GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp)
-GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT):  \
 	GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp)
 GenPoly/driver_cfa_cpp-DeclMutator.$(OBJEXT): GenPoly/$(am__dirstamp) \
@@ -664,6 +658,4 @@
 	@$(MKDIR_P) SymTab/$(DEPDIR)
 	@: > SymTab/$(DEPDIR)/$(am__dirstamp)
-SymTab/driver_cfa_cpp-IdTable.$(OBJEXT): SymTab/$(am__dirstamp) \
-	SymTab/$(DEPDIR)/$(am__dirstamp)
 SymTab/driver_cfa_cpp-Indexer.$(OBJEXT): SymTab/$(am__dirstamp) \
 	SymTab/$(DEPDIR)/$(am__dirstamp)
@@ -796,5 +788,4 @@
 	-rm -f GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT)
 	-rm -f GenPoly/driver_cfa_cpp-GenPoly.$(OBJEXT)
-	-rm -f GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT)
 	-rm -f GenPoly/driver_cfa_cpp-Lvalue.$(OBJEXT)
 	-rm -f GenPoly/driver_cfa_cpp-PolyMutator.$(OBJEXT)
@@ -832,5 +823,4 @@
 	-rm -f ResolvExpr/driver_cfa_cpp-Unify.$(OBJEXT)
 	-rm -f SymTab/driver_cfa_cpp-FixFunction.$(OBJEXT)
-	-rm -f SymTab/driver_cfa_cpp-IdTable.$(OBJEXT)
 	-rm -f SymTab/driver_cfa_cpp-ImplementationType.$(OBJEXT)
 	-rm -f SymTab/driver_cfa_cpp-Indexer.$(OBJEXT)
@@ -903,5 +893,4 @@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-GenPoly.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Lvalue.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Po@am__quote@
@@ -939,5 +928,4 @@
 @AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Unify.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-FixFunction.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-ImplementationType.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Indexer.Po@am__quote@
@@ -1364,18 +1352,4 @@
 @am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-FindFunction.obj `if test -f 'GenPoly/FindFunction.cc'; then $(CYGPATH_W) 'GenPoly/FindFunction.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/FindFunction.cc'; fi`
 
-GenPoly/driver_cfa_cpp-InstantiateGeneric.o: GenPoly/InstantiateGeneric.cc
-@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-InstantiateGeneric.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo -c -o GenPoly/driver_cfa_cpp-InstantiateGeneric.o `test -f 'GenPoly/InstantiateGeneric.cc' || echo '$(srcdir)/'`GenPoly/InstantiateGeneric.cc
-@am__fastdepCXX_TRUE@	$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='GenPoly/InstantiateGeneric.cc' object='GenPoly/driver_cfa_cpp-InstantiateGeneric.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 GenPoly/driver_cfa_cpp-InstantiateGeneric.o `test -f 'GenPoly/InstantiateGeneric.cc' || echo '$(srcdir)/'`GenPoly/InstantiateGeneric.cc
-
-GenPoly/driver_cfa_cpp-InstantiateGeneric.obj: GenPoly/InstantiateGeneric.cc
-@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-InstantiateGeneric.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo -c -o GenPoly/driver_cfa_cpp-InstantiateGeneric.obj `if test -f 'GenPoly/InstantiateGeneric.cc'; then $(CYGPATH_W) 'GenPoly/InstantiateGeneric.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/InstantiateGeneric.cc'; fi`
-@am__fastdepCXX_TRUE@	$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='GenPoly/InstantiateGeneric.cc' object='GenPoly/driver_cfa_cpp-InstantiateGeneric.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 GenPoly/driver_cfa_cpp-InstantiateGeneric.obj `if test -f 'GenPoly/InstantiateGeneric.cc'; then $(CYGPATH_W) 'GenPoly/InstantiateGeneric.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/InstantiateGeneric.cc'; fi`
-
 GenPoly/driver_cfa_cpp-DeclMutator.o: GenPoly/DeclMutator.cc
 @am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-DeclMutator.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Tpo -c -o GenPoly/driver_cfa_cpp-DeclMutator.o `test -f 'GenPoly/DeclMutator.cc' || echo '$(srcdir)/'`GenPoly/DeclMutator.cc
@@ -1811,18 +1785,4 @@
 @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 ResolvExpr/driver_cfa_cpp-TypeEnvironment.obj `if test -f 'ResolvExpr/TypeEnvironment.cc'; then $(CYGPATH_W) 'ResolvExpr/TypeEnvironment.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/TypeEnvironment.cc'; fi`
-
-SymTab/driver_cfa_cpp-IdTable.o: SymTab/IdTable.cc
-@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-IdTable.o -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Tpo -c -o SymTab/driver_cfa_cpp-IdTable.o `test -f 'SymTab/IdTable.cc' || echo '$(srcdir)/'`SymTab/IdTable.cc
-@am__fastdepCXX_TRUE@	$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='SymTab/IdTable.cc' object='SymTab/driver_cfa_cpp-IdTable.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 SymTab/driver_cfa_cpp-IdTable.o `test -f 'SymTab/IdTable.cc' || echo '$(srcdir)/'`SymTab/IdTable.cc
-
-SymTab/driver_cfa_cpp-IdTable.obj: SymTab/IdTable.cc
-@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-IdTable.obj -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Tpo -c -o SymTab/driver_cfa_cpp-IdTable.obj `if test -f 'SymTab/IdTable.cc'; then $(CYGPATH_W) 'SymTab/IdTable.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/IdTable.cc'; fi`
-@am__fastdepCXX_TRUE@	$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='SymTab/IdTable.cc' object='SymTab/driver_cfa_cpp-IdTable.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 SymTab/driver_cfa_cpp-IdTable.obj `if test -f 'SymTab/IdTable.cc'; then $(CYGPATH_W) 'SymTab/IdTable.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/IdTable.cc'; fi`
 
 SymTab/driver_cfa_cpp-Indexer.o: SymTab/Indexer.cc
Index: c/SymTab/AggregateTable.h
===================================================================
--- src/SymTab/AggregateTable.h	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ 	(revision )
@@ -1,53 +1,0 @@
-//
-// 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.
-//
-// AggregateTable.h -- 
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 16:17:26 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar  2 17:31:00 2016
-// Update Count     : 5
-//
-
-#ifndef AGGREGATETABLE_H
-#define AGGREGATETABLE_H
-
-#include <map>
-#include <stack>
-#include <string>
-#include <functional>
-
-#include "StackTable.h"
-#include "SynTree/Declaration.h"
-
-namespace SymTab {
-	template< class AggregateDeclClass >
-	class AggregateTableConflictFunction : public std::binary_function< AggregateDeclClass *, AggregateDeclClass *, AggregateDeclClass *> {
-	  public:
-		AggregateDeclClass *operator()( AggregateDeclClass *existing, AggregateDeclClass *added ) {
-			if ( existing->get_members().empty() ) {
-				return added;
-			} else if ( ! added->get_members().empty() ) {
-				throw SemanticError( "redeclaration of ", added );
-			} // if
-			return existing;
-		}
-	};
-
-	typedef StackTable< StructDecl, AggregateTableConflictFunction< StructDecl > > StructTable;
-	typedef StackTable< EnumDecl, AggregateTableConflictFunction< EnumDecl > > EnumTable;
-	typedef StackTable< UnionDecl, AggregateTableConflictFunction< UnionDecl > > UnionTable;
-	typedef StackTable< TraitDecl, AggregateTableConflictFunction< TraitDecl > > TraitTable;
-} // namespace SymTab
-
-#endif // AGGREGATETABLE_H
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SymTab/IdTable.cc
===================================================================
--- src/SymTab/IdTable.cc	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ 	(revision )
@@ -1,189 +1,0 @@
-//
-// 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.
-//
-// IdTable.cc -- 
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 17:04:02 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jan  8 22:59:23 2016
-// Update Count     : 74
-//
-
-#include <cassert>
-
-#include "SynTree/Declaration.h"
-#include "ResolvExpr/typeops.h"
-#include "Indexer.h"
-#include "Mangler.h"
-#include "IdTable.h"
-#include "Common/SemanticError.h"
-
-using std::string;
-
-namespace SymTab {
-	IdTable::IdTable() : scopeLevel( 0 ) {
-	}
-
-	void IdTable::enterScope() {
-		scopeLevel++;
-	}
-
-	void IdTable::leaveScope() {
-		for ( OuterTableType::iterator outer = table.begin(); outer != table.end(); ++outer ) {
-			for ( InnerTableType::iterator inner = outer->second.begin(); inner != outer->second.end(); ++inner ) {
-				std::stack< DeclEntry >& entry = inner->second;
-				// xxx - should be while?
-				if ( ! entry.empty() && entry.top().second == scopeLevel ) {
-					entry.pop();
-				} // if
-			} // for
-		} // for
-
-		scopeLevel--;
-		assert( scopeLevel >= 0 );
-	}
-
-	void IdTable::addDecl( DeclarationWithType *decl ) {
-		const string &name = decl->get_name();
-		string manglename;
-		if ( decl->get_linkage() == LinkageSpec::C ) {
-			manglename = name;
-		} else if ( LinkageSpec::isOverridable( decl->get_linkage() ) ) {
-			// mangle the name without including the appropriate suffix, so overridable routines are placed into the
-			// same "bucket" as their user defined versions.
-			manglename = Mangler::mangle( decl, false );
-		} else {
-			manglename = Mangler::mangle( decl );
-		} // if
-
-		InnerTableType &declTable = table[ name ];
-		InnerTableType::iterator it = declTable.find( manglename );
-
-		if ( it == declTable.end() ) {
-			// first time this name mangling has been defined
-			declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) );
-		} else {
-			std::stack< DeclEntry >& entry = it->second;
-			if ( ! entry.empty() && entry.top().second == scopeLevel ) {
-				// if we're giving the same name mangling to things of different types then there is something wrong
-				Declaration *old = entry.top().first;
-				assert( (dynamic_cast<ObjectDecl*>( decl ) && dynamic_cast<ObjectDecl*>( old ) )
-				  || (dynamic_cast<FunctionDecl*>( decl ) && dynamic_cast<FunctionDecl*>( old ) ) );
-
-				if ( LinkageSpec::isOverridable( old->get_linkage() ) ) {
-					// new definition shadows the autogenerated one, even at the same scope
-					declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) );
-				} else if ( decl->get_linkage() != LinkageSpec::C || ResolvExpr::typesCompatible( decl->get_type(), entry.top().first->get_type(), Indexer() ) ) {
-					// typesCompatible doesn't really do the right thing here. When checking compatibility of function types,
-					// we should ignore outermost pointer qualifiers, except _Atomic?
-					FunctionDecl *newentry = dynamic_cast< FunctionDecl* >( decl );
-					FunctionDecl *oldentry = dynamic_cast< FunctionDecl* >( old );
-					if ( newentry && oldentry ) {
-						if ( newentry->get_statements() && oldentry->get_statements() ) {
-							throw SemanticError( "duplicate function definition for 1 ", decl );
-						} // if
-					} else {
-						// two objects with the same mangled name defined in the same scope.
-						// both objects must be marked extern or both must be intrinsic for this to be okay
-						// xxx - perhaps it's actually if either is intrinsic then this is okay?
-						//       might also need to be same storage class?
-						ObjectDecl *newobj = dynamic_cast< ObjectDecl* >( decl );
-						ObjectDecl *oldobj = dynamic_cast< ObjectDecl* >( old );
-						if (newobj->get_storageClass() != DeclarationNode::Extern && oldobj->get_storageClass() != DeclarationNode::Extern ) {
-							throw SemanticError( "duplicate definition for 3 ", decl );
-						} // if
-					} // if
-				} else {
-					throw SemanticError( "duplicate definition for ", decl );
-				} // if
-			} else {
-				// new scope level - shadow existing definition
-				declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) );
-			} // if
-		} // if
-		// this ensures that no two declarations with the same unmangled name both have C linkage
-		for ( InnerTableType::iterator i = declTable.begin(); i != declTable.end(); ++i ) {
-			if ( ! i->second.empty() && i->second.top().first->get_linkage() == LinkageSpec::C && declTable.size() > 1 ) {
-				InnerTableType::iterator j = i;
-				for ( j++; j != declTable.end(); ++j ) {
-					if ( ! j->second.empty() && j->second.top().first->get_linkage() == LinkageSpec::C ) {
-						throw SemanticError( "invalid overload of C function " );
-					} // if
-				} // for
-			} // if
-		} // for
-	}
-
-	void IdTable::lookupId( const std::string &id, std::list< DeclarationWithType* >& decls ) const {
-		OuterTableType::const_iterator outer = table.find( id );
-		if ( outer == table.end() ) return;
-		const InnerTableType &declTable = outer->second;
-		for ( InnerTableType::const_iterator it = declTable.begin(); it != declTable.end(); ++it ) {
-			const std::stack< DeclEntry >& entry = it->second;
-			if ( ! entry.empty() ) {
-				decls.push_back( entry.top().first );
-			} // if
-		} // for
-	}
-
-	DeclarationWithType * IdTable::lookupId( const std::string &id) const {
-		DeclarationWithType* result = 0;
-		int depth = -1;
-
-		OuterTableType::const_iterator outer = table.find( id );
-		if ( outer == table.end() ) return 0;
-		const InnerTableType &declTable = outer->second;
-		for ( InnerTableType::const_iterator it = declTable.begin(); it != declTable.end(); ++it ) {
-			const std::stack< DeclEntry >& entry = it->second;
-			if ( ! entry.empty() && entry.top().second > depth ) {
-				result = entry.top().first;
-				depth = entry.top().second;
-			} // if
-		} // for
-		return result;
-	}
-
-	void IdTable::dump( std::ostream &os ) const {
-		for ( OuterTableType::const_iterator outer = table.begin(); outer != table.end(); ++outer ) {
-			for ( InnerTableType::const_iterator inner = outer->second.begin(); inner != outer->second.end(); ++inner ) {
-#if 0
-				const std::stack< DeclEntry >& entry = inner->second;
-				if ( ! entry.empty() ) { // && entry.top().second == scopeLevel ) {
-					os << outer->first << " (" << inner->first << ") (" << entry.top().second << ")" << std::endl;
-				} else {
-					os << outer->first << " (" << inner->first << ") ( entry-empty)" << std::endl;
-				} // if
-#endif
-#if 0
-				std::stack<DeclEntry> stack = inner->second;
-				os << "dumping a stack" << std::endl;
-				while ( ! stack.empty()) {
-					DeclEntry d = stack.top();
-					os << outer->first << " (" << inner->first << ") (" << d.second << ") " << std::endl;
-					stack.pop();
-				} // while
-#endif
-			} // for
-		} // for
-#if 0
-		for ( OuterTableType::const_iterator outer = table.begin(); outer != table.end(); ++outer ) {
-			for ( InnerTableType::const_iterator inner = outer->second.begin(); inner != outer->second.end(); ++inner ) {
-				const std::stack< DeclEntry >& entry = inner->second;
-				if ( ! entry.empty() && entry.top().second == scopeLevel ) {
-					os << outer->first << " (" << inner->first << ") (" << scopeLevel << ")" << std::endl;
-				} // if
-			} // for
-		} // for
-#endif
-	}
-} // namespace SymTab
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SymTab/IdTable.h
===================================================================
--- src/SymTab/IdTable.h	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ 	(revision )
@@ -1,54 +1,0 @@
-//
-// 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.
-//
-// IdTable.h -- 
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 21:30:02 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue May 19 16:49:33 2015
-// Update Count     : 4
-//
-
-#ifndef IDTABLE_H
-#define IDTABLE_H
-
-#include <iostream>
-#include <map>
-#include <string>
-#include <stack>
-
-#include "SynTree/SynTree.h"
-
-namespace SymTab {
-	class IdTable {
-	  public:
-		IdTable();
-  
-		void enterScope();
-		void leaveScope();
-		void addDecl( DeclarationWithType *decl );
-		void lookupId( const std::string &id, std::list< DeclarationWithType* >& decls ) const;
-		DeclarationWithType* lookupId( const std::string &id) const;
-  
-		void dump( std::ostream &os ) const;			// debugging
-	  private:
-		typedef std::pair< DeclarationWithType*, int > DeclEntry;
-		typedef std::map< std::string, std::stack< DeclEntry > > InnerTableType;
-		typedef std::map< std::string, InnerTableType > OuterTableType;
-
-		OuterTableType table;
-		int scopeLevel;
-	};
-} // namespace SymTab
-
-#endif // IDTABLE_H
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ src/SymTab/Indexer.cc	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
@@ -14,4 +14,17 @@
 //
 
+#include "Indexer.h"
+
+#include <string>
+#include <typeinfo>
+#include <unordered_map>
+#include <utility>
+
+#include "Mangler.h"
+
+#include "Common/utility.h"
+
+#include "ResolvExpr/typeops.h"
+
 #include "SynTree/Declaration.h"
 #include "SynTree/Type.h"
@@ -19,7 +32,4 @@
 #include "SynTree/Initializer.h"
 #include "SynTree/Statement.h"
-#include "Indexer.h"
-#include <typeinfo>
-#include "Common/utility.h"
 
 #define debugPrint(x) if ( doDebug ) { std::cout << x; }
@@ -33,7 +43,104 @@
 	}
 
-	Indexer::Indexer( bool useDebug ) : doDebug( useDebug ) {}
-
-	Indexer::~Indexer() {}
+	typedef std::unordered_map< std::string, DeclarationWithType* > MangleTable;
+	typedef std::unordered_map< std::string, MangleTable > IdTable;
+	typedef std::unordered_map< std::string, NamedTypeDecl* > TypeTable;
+	typedef std::unordered_map< std::string, StructDecl* > StructTable;
+	typedef std::unordered_map< std::string, EnumDecl* > EnumTable;
+	typedef std::unordered_map< std::string, UnionDecl* > UnionTable;
+	typedef std::unordered_map< std::string, TraitDecl* > TraitTable;
+
+	void dump( const IdTable &table, std::ostream &os ) {
+		for ( IdTable::const_iterator id = table.begin(); id != table.end(); ++id ) {
+			for ( MangleTable::const_iterator mangle = id->second.begin(); mangle != id->second.end(); ++mangle ) {
+				os << mangle->second << std::endl;
+			}
+		}
+	}
+	
+	template< typename Decl >
+	void dump( const std::unordered_map< std::string, Decl* > &table, std::ostream &os ) {
+		for ( typename std::unordered_map< std::string, Decl* >::const_iterator it = table.begin(); it != table.end(); ++it ) {
+			os << it->second << std::endl;
+		} // for
+	}
+	
+	struct Indexer::Impl {
+		Impl( unsigned long _scope ) : refCount(1), scope( _scope ), size( 0 ), base(),
+				idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {}
+		Impl( unsigned long _scope, Indexer &&_base ) : refCount(1), scope( _scope ), size( 0 ), base( _base ),
+				idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {}
+		unsigned long refCount;   ///< Number of references to these tables
+		unsigned long scope;      ///< Scope these tables are associated with
+		unsigned long size;       ///< Number of elements stored in this table
+		const Indexer base;       ///< Base indexer this extends
+		
+		IdTable idTable;          ///< Identifier namespace
+		TypeTable typeTable;      ///< Type namespace
+		StructTable structTable;  ///< Struct namespace
+		EnumTable enumTable;      ///< Enum namespace
+		UnionTable unionTable;    ///< Union namespace
+		TraitTable traitTable;    ///< Trait namespace
+	};
+
+	Indexer::Impl *Indexer::newRef( Indexer::Impl *toClone ) {
+		if ( ! toClone ) return 0;
+
+		// shorten the search chain by skipping empty links
+		Indexer::Impl *ret = toClone->size == 0 ? toClone->base.tables : toClone;
+		if ( ret ) { ++ret->refCount; }
+
+		return ret;
+	}
+
+	void Indexer::deleteRef( Indexer::Impl *toFree ) {
+		if ( ! toFree ) return;
+
+		if ( --toFree->refCount == 0 ) delete toFree;
+	}
+
+	void Indexer::makeWritable() {
+		if ( ! tables ) {
+			// create indexer if not yet set
+			tables = new Indexer::Impl( scope );
+		} else if ( tables->refCount > 1 || tables->scope != scope ) {
+			// make this indexer the base of a fresh indexer at the current scope
+			tables = new Indexer::Impl( scope, std::move( *this ) );
+		}
+	}
+
+	Indexer::Indexer( bool _doDebug ) : tables( 0 ), scope( 0 ), doDebug( _doDebug ) {}
+
+	Indexer::Indexer( const Indexer &that ) : tables( newRef( that.tables ) ), scope( that.scope ), doDebug( that.doDebug ) {}
+
+	Indexer::Indexer( Indexer &&that ) : tables( that.tables ), scope( that.scope ), doDebug( that.doDebug ) {
+		that.tables = 0;
+	}
+
+	Indexer::~Indexer() {
+		deleteRef( tables );
+	}
+
+	Indexer& Indexer::operator= ( const Indexer &that ) {
+		deleteRef( tables );
+
+		tables = newRef( that.tables );
+		scope = that.scope;
+		doDebug = that.doDebug;
+
+		return *this;
+	}
+
+	Indexer& Indexer::operator= ( Indexer &&that ) {
+		deleteRef( tables );
+
+		tables = that.tables;
+		scope = that.scope;
+		doDebug = that.doDebug;
+
+		that.tables = 0;
+
+		return *this;
+	}
 
 	void Indexer::visit( ObjectDecl *objectDecl ) {
@@ -45,5 +152,5 @@
 		if ( objectDecl->get_name() != "" ) {
 			debugPrint( "Adding object " << objectDecl->get_name() << std::endl );
-			idTable.addDecl( objectDecl );
+			addId( objectDecl );
 		} // if
 	}
@@ -52,5 +159,5 @@
 		if ( functionDecl->get_name() == "" ) return;
 		debugPrint( "Adding function " << functionDecl->get_name() << std::endl );
-		idTable.addDecl( functionDecl );
+		addId( functionDecl );
 		enterScope();
 		maybeAccept( functionDecl->get_functionType(), *this );
@@ -90,5 +197,5 @@
 		leaveScope();
 		debugPrint( "Adding type " << typeDecl->get_name() << std::endl );
-		typeTable.add( typeDecl );
+		addType( typeDecl );
 		acceptAll( typeDecl->get_assertions(), *this );
 	}
@@ -100,5 +207,5 @@
 		leaveScope();
 		debugPrint( "Adding typedef " << typeDecl->get_name() << std::endl );
-		typeTable.add( typeDecl );
+		addType( typeDecl );
 	}
 
@@ -108,5 +215,5 @@
 		cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
 		debugPrint( "Adding fwd decl for struct " << fwdDecl.get_name() << std::endl );
-		structTable.add( &fwdDecl );
+		addStruct( &fwdDecl );
   
 		enterScope();
@@ -117,5 +224,5 @@
 		debugPrint( "Adding struct " << aggregateDecl->get_name() << std::endl );
 		// this addition replaces the forward declaration
-		structTable.add( aggregateDecl );
+		addStruct( aggregateDecl );
 	}
 
@@ -125,5 +232,5 @@
 		cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
 		debugPrint( "Adding fwd decl for union " << fwdDecl.get_name() << std::endl );
-		unionTable.add( &fwdDecl );
+		addUnion( &fwdDecl );
   
 		enterScope();
@@ -133,10 +240,10 @@
   
 		debugPrint( "Adding union " << aggregateDecl->get_name() << std::endl );
-		unionTable.add( aggregateDecl );
+		addUnion( aggregateDecl );
 	}
 
 	void Indexer::visit( EnumDecl *aggregateDecl ) {
 		debugPrint( "Adding enum " << aggregateDecl->get_name() << std::endl );
-		enumTable.add( aggregateDecl );
+		addEnum( aggregateDecl );
 		// unlike structs, contexts, and unions, enums inject their members into the global scope
 		acceptAll( aggregateDecl->get_members(), *this );
@@ -150,5 +257,5 @@
   
 		debugPrint( "Adding context " << aggregateDecl->get_name() << std::endl );
-		contextTable.add( aggregateDecl );
+		addTrait( aggregateDecl );
 	}
 
@@ -299,7 +406,7 @@
 
 	void Indexer::visit( StructInstType *structInst ) {
-		if ( ! structTable.lookup( structInst->get_name() ) ) {
+		if ( ! lookupStruct( structInst->get_name() ) ) {
 			debugPrint( "Adding struct " << structInst->get_name() << " from implicit forward declaration" << std::endl );
-			structTable.add( structInst->get_name() );
+			addStruct( structInst->get_name() );
 		}
 		enterScope();
@@ -309,7 +416,7 @@
 
 	void Indexer::visit( UnionInstType *unionInst ) {
-		if ( ! unionTable.lookup( unionInst->get_name() ) ) {
+		if ( ! lookupUnion( unionInst->get_name() ) ) {
 			debugPrint( "Adding union " << unionInst->get_name() << " from implicit forward declaration" << std::endl );
-			unionTable.add( unionInst->get_name() );
+			addUnion( unionInst->get_name() );
 		}
 		enterScope();
@@ -325,90 +432,350 @@
 	}
 
-
-	void Indexer::lookupId( const std::string &id, std::list< DeclarationWithType* > &list ) const {
-		idTable.lookupId( id, list );
-	}
-
-	DeclarationWithType* Indexer::lookupId( const std::string &id) const {
-		return idTable.lookupId(id);
+	
+
+	void Indexer::lookupId( const std::string &id, std::list< DeclarationWithType* > &out ) const {
+		if ( ! tables ) return;
+
+		IdTable::const_iterator decls = tables->idTable.find( id );
+		if ( decls != tables->idTable.end() ) {
+			const MangleTable &mangleTable = decls->second;
+			for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
+				out.push_back( decl->second );
+			}
+		}
+		
+		// get declarations from base indexers
+		tables->base.lookupId( id, out );
 	}
 
 	NamedTypeDecl *Indexer::lookupType( const std::string &id ) const {
-		return typeTable.lookup( id );
+		if ( ! tables ) return 0;
+
+		TypeTable::const_iterator ret = tables->typeTable.find( id );
+		return ret != tables->typeTable.end() ? ret->second : tables->base.lookupType( id );
 	}
 
 	StructDecl *Indexer::lookupStruct( const std::string &id ) const {
-		return structTable.lookup( id );
+		if ( ! tables ) return 0;
+
+		StructTable::const_iterator ret = tables->structTable.find( id );
+		return ret != tables->structTable.end() ? ret->second : tables->base.lookupStruct( id );
 	}
 
 	EnumDecl *Indexer::lookupEnum( const std::string &id ) const {
-		return enumTable.lookup( id );
+		if ( ! tables ) return 0;
+
+		EnumTable::const_iterator ret = tables->enumTable.find( id );
+		return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnum( id );
 	}
 
 	UnionDecl *Indexer::lookupUnion( const std::string &id ) const {
-		return unionTable.lookup( id );
-	}
-
-	TraitDecl  * Indexer::lookupTrait( const std::string &id ) const {
-		return contextTable.lookup( id );
+		if ( ! tables ) return 0;
+
+		UnionTable::const_iterator ret = tables->unionTable.find( id );
+		return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnion( id );
+	}
+
+	TraitDecl *Indexer::lookupTrait( const std::string &id ) const {
+		if ( ! tables ) return 0;
+
+		TraitTable::const_iterator ret = tables->traitTable.find( id );
+		return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTrait( id );
+	}
+
+	DeclarationWithType *Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const {
+		if ( ! tables ) return 0;
+		if ( tables->scope < scope ) return 0;
+
+		IdTable::const_iterator decls = tables->idTable.find( id );
+		if ( decls != tables->idTable.end() ) {
+			const MangleTable &mangleTable = decls->second;
+			MangleTable::const_iterator decl = mangleTable.find( mangleName );
+			if ( decl != mangleTable.end() ) return decl->second;
+		}
+
+		return tables->base.lookupIdAtScope( id, mangleName, scope );
+	}
+
+	bool Indexer::hasCDeclWithName( const std::string &id ) const {
+		if ( ! tables ) return false;
+
+		IdTable::const_iterator decls = tables->idTable.find( id );
+		if ( decls != tables->idTable.end() ) {
+			const MangleTable &mangleTable = decls->second;
+			for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
+				if ( decl->second->get_linkage() == LinkageSpec::C ) return true;
+			}
+		}
+
+		return tables->base.hasCDeclWithName( id );
+	}
+	
+	NamedTypeDecl *Indexer::lookupTypeAtScope( const std::string &id, unsigned long scope ) const {
+		if ( ! tables ) return 0;
+		if ( tables->scope < scope ) return 0;
+
+		TypeTable::const_iterator ret = tables->typeTable.find( id );
+		return ret != tables->typeTable.end() ? ret->second : tables->base.lookupTypeAtScope( id, scope );
+	}
+	
+	StructDecl *Indexer::lookupStructAtScope( const std::string &id, unsigned long scope ) const {
+		if ( ! tables ) return 0;
+		if ( tables->scope < scope ) return 0;
+
+		StructTable::const_iterator ret = tables->structTable.find( id );
+		return ret != tables->structTable.end() ? ret->second : tables->base.lookupStructAtScope( id, scope );
+	}
+	
+	EnumDecl *Indexer::lookupEnumAtScope( const std::string &id, unsigned long scope ) const {
+		if ( ! tables ) return 0;
+		if ( tables->scope < scope ) return 0;
+
+		EnumTable::const_iterator ret = tables->enumTable.find( id );
+		return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnumAtScope( id, scope );
+	}
+	
+	UnionDecl *Indexer::lookupUnionAtScope( const std::string &id, unsigned long scope ) const {
+		if ( ! tables ) return 0;
+		if ( tables->scope < scope ) return 0;
+
+		UnionTable::const_iterator ret = tables->unionTable.find( id );
+		return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnionAtScope( id, scope );
+	}
+	
+	TraitDecl *Indexer::lookupTraitAtScope( const std::string &id, unsigned long scope ) const {
+		if ( ! tables ) return 0;
+		if ( tables->scope < scope ) return 0;
+
+		TraitTable::const_iterator ret = tables->traitTable.find( id );
+		return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTraitAtScope( id, scope );
+	}
+
+	bool addedIdConflicts( DeclarationWithType *existing, DeclarationWithType *added ) {
+		// if we're giving the same name mangling to things of different types then there is something wrong
+		assert( (dynamic_cast<ObjectDecl*>( added ) && dynamic_cast<ObjectDecl*>( existing ) )
+			|| (dynamic_cast<FunctionDecl*>( added ) && dynamic_cast<FunctionDecl*>( existing ) ) );
+
+		if ( LinkageSpec::isOverridable( existing->get_linkage() ) ) {
+			// new definition shadows the autogenerated one, even at the same scope
+			return false;
+		} else if ( added->get_linkage() != LinkageSpec::C || ResolvExpr::typesCompatible( added->get_type(), existing->get_type(), Indexer() ) ) {
+			// typesCompatible doesn't really do the right thing here. When checking compatibility of function types,
+			// we should ignore outermost pointer qualifiers, except _Atomic?
+			FunctionDecl *newentry = dynamic_cast< FunctionDecl* >( added );
+			FunctionDecl *oldentry = dynamic_cast< FunctionDecl* >( existing );
+			if ( newentry && oldentry ) {
+				if ( newentry->get_statements() && oldentry->get_statements() ) {
+					throw SemanticError( "duplicate function definition for ", added );
+				} // if
+			} else {
+				// two objects with the same mangled name defined in the same scope.
+				// both objects must be marked extern or both must be intrinsic for this to be okay
+				// xxx - perhaps it's actually if either is intrinsic then this is okay?
+				//       might also need to be same storage class?
+				ObjectDecl *newobj = dynamic_cast< ObjectDecl* >( added );
+				ObjectDecl *oldobj = dynamic_cast< ObjectDecl* >( existing );
+				if ( newobj->get_storageClass() != DeclarationNode::Extern && oldobj->get_storageClass() != DeclarationNode::Extern ) {
+					throw SemanticError( "duplicate object definition for ", added );
+				} // if
+			} // if
+		} else {
+			throw SemanticError( "duplicate definition for ", added );
+		} // if
+
+		return true;
+	}
+	
+	void Indexer::addId( DeclarationWithType *decl ) {
+		makeWritable();
+
+		const std::string &name = decl->get_name();
+		std::string mangleName;
+		if ( decl->get_linkage() == LinkageSpec::C ) {
+			mangleName = name;
+		} else if ( LinkageSpec::isOverridable( decl->get_linkage() ) ) {
+			// mangle the name without including the appropriate suffix, so overridable routines are placed into the
+			// same "bucket" as their user defined versions.
+			mangleName = Mangler::mangle( decl, false );
+		} else {
+			mangleName = Mangler::mangle( decl );
+		} // if
+
+		DeclarationWithType *existing = lookupIdAtScope( name, mangleName, scope );
+		if ( ! existing || ! addedIdConflicts( existing, decl ) ) {
+			// this ensures that no two declarations with the same unmangled name both have C linkage
+			if ( decl->get_linkage() == LinkageSpec::C && hasCDeclWithName( name ) ) {
+				throw SemanticError( "invalid overload of C function ", decl );
+			}
+			
+			tables->idTable[ name ][ mangleName ] = decl;
+			++tables->size;
+		}
+	}
+
+	bool addedTypeConflicts( NamedTypeDecl *existing, NamedTypeDecl *added ) {
+		if ( existing->get_base() == 0 ) {
+			return false;
+		} else if ( added->get_base() == 0 ) {
+			return true;
+		} else {
+			throw SemanticError( "redeclaration of ", added );
+		}
+	}
+	
+	void Indexer::addType( NamedTypeDecl *decl ) {
+		makeWritable();
+
+		const std::string &id = decl->get_name();
+		TypeTable::iterator existing = tables->typeTable.find( id );
+		if ( existing == tables->typeTable.end() ) {
+			NamedTypeDecl *parent = tables->base.lookupTypeAtScope( id, scope );
+			if ( ! parent || ! addedTypeConflicts( parent, decl ) ) {
+				tables->typeTable.insert( existing, std::make_pair( id, decl ) );
+				++tables->size;
+			}
+		} else {
+			if ( ! addedTypeConflicts( existing->second, decl ) ) {
+				existing->second = decl;
+			}
+		}
+	}
+
+	bool addedDeclConflicts( AggregateDecl *existing, AggregateDecl *added ) {
+		if ( existing->get_members().empty() ) {
+			return false;
+		} else if ( ! added->get_members().empty() ) {
+			throw SemanticError( "redeclaration of ", added );
+		} // if
+		return true;
+	}
+
+	void Indexer::addStruct( const std::string &id ) {
+		addStruct( new StructDecl( id ) );
+	}
+	
+	void Indexer::addStruct( StructDecl *decl ) {
+		makeWritable();
+
+		const std::string &id = decl->get_name();
+		StructTable::iterator existing = tables->structTable.find( id );
+		if ( existing == tables->structTable.end() ) {
+			StructDecl *parent = tables->base.lookupStructAtScope( id, scope );
+			if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
+				tables->structTable.insert( existing, std::make_pair( id, decl ) );
+				++tables->size;
+			}
+		} else {
+			if ( ! addedDeclConflicts( existing->second, decl ) ) {
+				existing->second = decl;
+			}
+		}
+	}
+	
+	void Indexer::addEnum( EnumDecl *decl ) {
+		makeWritable();
+
+		const std::string &id = decl->get_name();
+		EnumTable::iterator existing = tables->enumTable.find( id );
+		if ( existing == tables->enumTable.end() ) {
+			EnumDecl *parent = tables->base.lookupEnumAtScope( id, scope );
+			if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
+				tables->enumTable.insert( existing, std::make_pair( id, decl ) );
+				++tables->size;
+			}
+		} else {
+			if ( ! addedDeclConflicts( existing->second, decl ) ) {
+				existing->second = decl;
+			}
+		}
+	}
+
+	void Indexer::addUnion( const std::string &id ) {
+		addUnion( new UnionDecl( id ) );
+	}
+	
+	void Indexer::addUnion( UnionDecl *decl ) {
+		makeWritable();
+
+		const std::string &id = decl->get_name();
+		UnionTable::iterator existing = tables->unionTable.find( id );
+		if ( existing == tables->unionTable.end() ) {
+			UnionDecl *parent = tables->base.lookupUnionAtScope( id, scope );
+			if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
+				tables->unionTable.insert( existing, std::make_pair( id, decl ) );
+				++tables->size;
+			}
+		} else {
+			if ( ! addedDeclConflicts( existing->second, decl ) ) {
+				existing->second = decl;
+			}
+		}
+	}
+	
+	void Indexer::addTrait( TraitDecl *decl ) {
+		makeWritable();
+
+		const std::string &id = decl->get_name();
+		TraitTable::iterator existing = tables->traitTable.find( id );
+		if ( existing == tables->traitTable.end() ) {
+			TraitDecl *parent = tables->base.lookupTraitAtScope( id, scope );
+			if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
+				tables->traitTable.insert( existing, std::make_pair( id, decl ) );
+				++tables->size;
+			}
+		} else {
+			if ( ! addedDeclConflicts( existing->second, decl ) ) {
+				existing->second = decl;
+			}
+		}
 	}
 
 	void Indexer::enterScope() {
+		++scope;
+		
 		if ( doDebug ) {
-			std::cout << "--- Entering scope" << std::endl;
-		}
-		idTable.enterScope();
-		typeTable.enterScope();
-		structTable.enterScope();
-		enumTable.enterScope();
-		unionTable.enterScope();
-		contextTable.enterScope();
+			std::cout << "--- Entering scope " << scope << std::endl;
+		}
 	}
 
 	void Indexer::leaveScope() {
 		using std::cout;
-		using std::endl;
-  
-		if ( doDebug ) {
-			cout << "--- Leaving scope containing" << endl;
-			idTable.dump( cout );
-			typeTable.dump( cout );
-			structTable.dump( cout );
-			enumTable.dump( cout );
-			unionTable.dump( cout );
-			contextTable.dump( cout );
-		}
-		idTable.leaveScope();
-		typeTable.leaveScope();
-		structTable.leaveScope();
-		enumTable.leaveScope();
-		unionTable.leaveScope();
-		contextTable.leaveScope();
+
+		assert( scope > 0 && "cannot leave initial scope" );
+		--scope;
+
+		while ( tables && tables->scope > scope ) {
+			if ( doDebug ) {
+				cout << "--- Leaving scope " << tables->scope << " containing" << std::endl;
+				dump( tables->idTable, cout );
+				dump( tables->typeTable, cout );
+				dump( tables->structTable, cout );
+				dump( tables->enumTable, cout );
+				dump( tables->unionTable, cout );
+				dump( tables->traitTable, cout );
+			}
+
+			// swap tables for base table until we find one at an appropriate scope
+			Indexer::Impl *base = newRef( tables->base.tables );
+			deleteRef( tables );
+			tables = base;
+		}
 	}
 
 	void Indexer::print( std::ostream &os, int indent ) const {
 	    using std::cerr;
-	    using std::endl;
-
-	    cerr << "===idTable===" << endl;
-	    idTable.dump( os );
-	    cerr << "===typeTable===" << endl;
-	    typeTable.dump( os );
-	    cerr << "===structTable===" << endl;
-	    structTable.dump( os );
-	    cerr << "===enumTable===" << endl;
-	    enumTable.dump( os );
-	    cerr << "===unionTable===" << endl;
-	    unionTable.dump( os );
-	    cerr << "===contextTable===" << endl;
-	    contextTable.dump( os );
-#if 0
-		idTable.dump( os );
-		typeTable.dump( os );
-		structTable.dump( os );
-		enumTable.dump( os );
-		unionTable.dump( os );
-		contextTable.dump( os );
-#endif
+
+	    cerr << "===idTable===" << std::endl;
+	    if ( tables ) dump( tables->idTable, os );
+	    cerr << "===typeTable===" << std::endl;
+	    if ( tables ) dump( tables->typeTable, os );
+	    cerr << "===structTable===" << std::endl;
+	    if ( tables ) dump( tables->structTable, os );
+	    cerr << "===enumTable===" << std::endl;
+	    if ( tables ) dump( tables->enumTable, os );
+	    cerr << "===unionTable===" << std::endl;
+	    if ( tables ) dump( tables->unionTable, os );
+	    cerr << "===contextTable===" << std::endl;
+	    if ( tables ) dump( tables->traitTable, os );
 	}
 } // namespace SymTab
Index: src/SymTab/Indexer.h
===================================================================
--- src/SymTab/Indexer.h	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ src/SymTab/Indexer.h	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
@@ -21,7 +21,4 @@
 
 #include "SynTree/Visitor.h"
-#include "IdTable.h"
-#include "AggregateTable.h"
-#include "TypeTable.h"
 
 namespace SymTab {
@@ -29,5 +26,10 @@
 	  public:
 		Indexer( bool useDebug = false );
+
+		Indexer( const Indexer &that );
+		Indexer( Indexer &&that );
 		virtual ~Indexer();
+		Indexer& operator= ( const Indexer &that );
+		Indexer& operator= ( Indexer &&that );
 
 		//using Visitor::visit;
@@ -78,22 +80,51 @@
 		void leaveScope();
 
-		void lookupId( const std::string &id, std::list< DeclarationWithType* >& ) const;
-		DeclarationWithType* lookupId( const std::string &id) const;
+		/// Gets all declarations with the given ID
+		void lookupId( const std::string &id, std::list< DeclarationWithType* > &out ) const;
+		/// Gets the top-most type declaration with the given ID
 		NamedTypeDecl *lookupType( const std::string &id ) const;
+		/// Gets the top-most struct declaration with the given ID
 		StructDecl *lookupStruct( const std::string &id ) const;
+		/// Gets the top-most enum declaration with the given ID
 		EnumDecl *lookupEnum( const std::string &id ) const;
+		/// Gets the top-most union declaration with the given ID
 		UnionDecl *lookupUnion( const std::string &id ) const;
+		/// Gets the top-most trait declaration with the given ID
 		TraitDecl *lookupTrait( const std::string &id ) const;
   
 		void print( std::ostream &os, int indent = 0 ) const;
 	  private:
-		IdTable idTable;
-		TypeTable typeTable;
-		StructTable structTable;
-		EnumTable enumTable;
-		UnionTable unionTable;
-		TraitTable contextTable;
-  
-		bool doDebug;					// display debugging trace
+		/// looks up a specific mangled ID at the given scope
+		DeclarationWithType *lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
+		/// returns true if there exists a declaration with C linkage and the given name
+		bool hasCDeclWithName( const std::string &id ) const;
+		// equivalents to lookup functions that only look at tables at scope `scope` (which should be >= tables->scope)
+		NamedTypeDecl *lookupTypeAtScope( const std::string &id, unsigned long scope ) const;
+		StructDecl *lookupStructAtScope( const std::string &id, unsigned long scope ) const;
+		EnumDecl *lookupEnumAtScope( const std::string &id, unsigned long scope ) const;
+		UnionDecl *lookupUnionAtScope( const std::string &id, unsigned long scope ) const;
+		TraitDecl *lookupTraitAtScope( const std::string &id, unsigned long scope ) const;
+		
+		void addId( DeclarationWithType *decl );
+		void addType( NamedTypeDecl *decl );
+		void addStruct( const std::string &id );
+		void addStruct( StructDecl *decl );
+		void addEnum( EnumDecl *decl );
+		void addUnion( const std::string &id );
+		void addUnion( UnionDecl *decl );
+		void addTrait( TraitDecl *decl );
+		
+		struct Impl;
+		Impl *tables;         ///< Copy-on-write instance of table data structure
+		unsigned long scope;  ///< Scope index of this pointer
+		bool doDebug;         ///< Display debugging trace?
+
+		/// Takes a new ref to a table (returns null if null)
+		static Impl *newRef( Impl *toClone );
+		/// Clears a ref to a table (does nothing if null)
+		static void deleteRef( Impl *toFree );
+
+		/// Ensures that tables variable is writable (i.e. allocated, uniquely owned by this Indexer, and at the current scope)
+		void makeWritable();
 	};
 } // namespace SymTab
Index: c/SymTab/StackTable.cc
===================================================================
--- src/SymTab/StackTable.cc	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ 	(revision )
@@ -1,84 +1,0 @@
-//
-// 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.
-//
-// StackTable.cc -- 
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 21:45:15 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue May 19 16:51:53 2015
-// Update Count     : 3
-//
-
-#include <cassert>
-
-#include "StackTable.h"
-
-namespace SymTab {
-	template< typename Element, typename ConflictFunction >
-	StackTable< Element, ConflictFunction >::StackTable() : scopeLevel( 0 ) {
-	}
-
-	template< typename Element, typename ConflictFunction >
-	void StackTable< Element, ConflictFunction >::enterScope() {
-		scopeLevel++;
-	}
-
-	template< typename Element, typename ConflictFunction >
-	void StackTable< Element, ConflictFunction >::leaveScope() {
-		for ( typename TableType::iterator it = table.begin(); it != table.end(); ++it ) {
-			std::stack< Entry >& entry = it->second;
-			if ( ! entry.empty() && entry.top().second == scopeLevel ) {
-				entry.pop();
-			} // if
-		} // for
-		scopeLevel--;
-		assert( scopeLevel >= 0 );
-	}
-
-	template< typename Element, typename ConflictFunction >
-	void StackTable< Element, ConflictFunction >::add( Element *type ) {
-		std::stack< Entry >& entry = table[ type->get_name() ];
-		if ( ! entry.empty() && entry.top().second == scopeLevel ) {
-			entry.top().first = conflictFunction( entry.top().first, type );
-		} else {
-			entry.push( Entry( type, scopeLevel ) );
-		} // if
-	}
-
-	template< typename Element, typename ConflictFunction >
-	void StackTable< Element, ConflictFunction >::add( std::string fwdDeclName ) {
-		add( new Element( fwdDeclName ) );
-	}
-
-	template< typename Element, typename ConflictFunction >
-	Element *StackTable< Element, ConflictFunction >::lookup( std::string id ) const {
-		typename TableType::const_iterator it = table.find( id );
-		if ( it == table.end() ) {
-			return 0;
-		} else if ( ! it->second.empty() ) {
-			return it->second.top().first;
-		} else {
-			return 0;
-		} // if
-	}
-
-	template< typename Element, typename ConflictFunction >
-	void StackTable< Element, ConflictFunction >::dump( std::ostream &os ) const {
-		for ( typename TableType::const_iterator it = table.begin(); it != table.end(); ++it ) {
-			const std::stack< Entry >& entry = it->second;
-			if ( ! entry.empty() && entry.top().second == scopeLevel ) {
-				os << it->first << std::endl;
-			} // if
-		} // for
-	}
-} // namespace SymTab
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SymTab/StackTable.h
===================================================================
--- src/SymTab/StackTable.h	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ 	(revision )
@@ -1,55 +1,0 @@
-//
-// 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.
-//
-// StackTable.h -- 
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 21:47:10 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue May 19 16:50:36 2015
-// Update Count     : 4
-//
-
-#ifndef STACKTABLE_H
-#define STACKTABLE_H
-
-#include <map>
-#include <stack>
-#include <string>
-#include <functional>
-
-namespace SymTab {
-	template< typename Element, typename ConflictFunction >
-	class StackTable {
-	  public:
-		StackTable();
-
-		void enterScope();
-		void leaveScope();
-		void add( Element *type );
-		void add( std::string fwdDeclName );
-		Element *lookup( std::string id ) const;
-
-		void dump( std::ostream &os ) const;			// debugging
-	  private:
-		typedef std::pair< Element*, int > Entry;
-		typedef std::map< std::string, std::stack< Entry > > TableType;
-  
-		ConflictFunction conflictFunction;
-		TableType table;
-		int scopeLevel;
-	};
-} // SymTab
-
-#include "StackTable.cc"
-
-#endif // STACKTABLE_H
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SymTab/TypeTable.h
===================================================================
--- src/SymTab/TypeTable.h	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ 	(revision )
@@ -1,53 +1,0 @@
-//
-// 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.
-//
-// TypeTable.h -- 
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 21:48:32 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue May 19 16:50:25 2015
-// Update Count     : 3
-//
-
-#ifndef TYPETABLE_H
-#define TYPETABLE_H
-
-#include <cassert>
-#include <map>
-#include <stack>
-#include <string>
-#include <functional>
-
-#include "StackTable.h"
-#include "SynTree/Declaration.h"
-
-namespace SymTab {
-	class TypeTableConflictFunction : public std::binary_function< NamedTypeDecl *, NamedTypeDecl *, NamedTypeDecl * > {
-	  public:
-		NamedTypeDecl *operator()( NamedTypeDecl *existing, NamedTypeDecl *added ) {
-			if ( existing->get_base() == 0 ) {
-				return added;
-			} else if ( added->get_base() == 0 ) {
-				return existing;
-			} else {
-				throw SemanticError( "redeclaration of ", added );
-			} // if
-			assert( false );
-			return 0;
-		}
-	};
-
-	typedef StackTable< NamedTypeDecl, TypeTableConflictFunction > TypeTable;
-} // namespace SymTab
-
-#endif // TYPETABLE_H
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SymTab/module.mk
===================================================================
--- src/SymTab/module.mk	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ src/SymTab/module.mk	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
@@ -15,6 +15,5 @@
 ###############################################################################
 
-SRC += SymTab/IdTable.cc \
-       SymTab/Indexer.cc \
+SRC += SymTab/Indexer.cc \
        SymTab/Mangler.cc \
        SymTab/Validate.cc \
Index: src/SynTree/Constant.cc
===================================================================
--- src/SynTree/Constant.cc	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ src/SynTree/Constant.cc	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
@@ -16,4 +16,5 @@
 #include <iostream>
 #include <list>
+#include <string>
 
 #include "Constant.h"
@@ -28,4 +29,16 @@
 
 Constant::~Constant() { delete type; }
+
+Constant Constant::from( int i ) {
+	return Constant( new BasicType( Type::Qualifiers(), BasicType::SignedInt ), std::to_string( i ) );
+}
+
+Constant Constant::from( unsigned long i ) {
+	return Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::to_string( i ) );
+}
+
+Constant Constant::from( double d ) {
+	return Constant( new BasicType( Type::Qualifiers(), BasicType::Double ), std::to_string( d ) );
+}
 
 Constant *Constant::clone() const { assert( false ); return 0; }
Index: src/SynTree/Constant.h
===================================================================
--- src/SynTree/Constant.h	(revision b63e3760197cb5f480cf1cdfd5886fdd0411d103)
+++ src/SynTree/Constant.h	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
@@ -32,4 +32,11 @@
 	void set_value( std::string newValue ) { value = newValue; }
 
+	/// generates an integer constant of the given int
+	static Constant from( int i );
+	/// generates an integer constant of the given unsigned long int
+	static Constant from( unsigned long i );
+	/// generates a floating point constant of the given double
+	static Constant from( double d );
+
 	virtual Constant *clone() const;
 	virtual void accept( Visitor &v ) { v.visit( this ); }
