Index: src/SymTab/AddVisit.h
===================================================================
--- src/SymTab/AddVisit.h	(revision dbe8f244d5ddc4656e04f6da8db1d7f072f437bf)
+++ src/SymTab/AddVisit.h	(revision 35b1bf4a3c6817f25d0e553e86d13309a28c2b42)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 16:14:32 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Aug  4 11:22:01 2016
-// Update Count     : 9
+// Last Modified On : Thu Feb  2 16:36:02 2017
+// Update Count     : 14
 //
 
@@ -18,10 +18,25 @@
 
 	template< typename Visitor >
-	inline void addVisitStatementList( std::list< Statement* > &statements, Visitor &visitor ) {
-		for ( std::list< Statement* >::iterator i = statements.begin(); i != statements.end(); ++i ) {
-			addDecls( visitor.get_declsToAdd(), statements, i );
-			(*i)->accept( visitor );
-		} // for
-		addDecls( visitor.get_declsToAdd(), statements, statements.end() );
+	inline void addVisitStatementList( std::list< Statement* > &stmts, Visitor &visitor ) {
+		for ( std::list< Statement* >::iterator stmt = stmts.begin(); ; ++stmt ) {
+			// add any new declarations after the previous statement
+			for ( std::list< Declaration* >::iterator decl = visitor.declsToAddAfter.begin(); decl != visitor.declsToAddAfter.end(); ++decl ) {
+				DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
+				stmts.insert( stmt, declStmt );
+			}
+			visitor.declsToAddAfter.clear();
+
+			if ( stmt == stmts.end() ) break;
+			
+			// run mutator on statement
+			maybeAccept( *stmt, visitor );
+
+			// add any new declarations before the statement
+			for ( std::list< Declaration* >::iterator decl = visitor.declsToAdd.begin(); decl != visitor.declsToAdd.end(); ++decl ) {
+				DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
+				stmts.insert( stmt, declStmt );
+			}
+			visitor.declsToAdd.clear();
+		}
 	}
 
@@ -38,15 +53,17 @@
 
 	template< typename Visitor >
-	void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor, bool addBefore ) {
-		std::list< Declaration * >::iterator i = translationUnit.begin();
-		while ( i != translationUnit.end() ) {
-			(*i)->accept( visitor );
-			std::list< Declaration * >::iterator next = i;
-			next++;
-			if ( ! visitor.get_declsToAdd().empty() ) {
-				translationUnit.splice( addBefore ? i : next, visitor.get_declsToAdd() );
-			} // if
-			i = next;
-		} // while
+	void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor ) {
+		for ( std::list< Declaration* >::iterator decl = translationUnit.begin(); ; ++decl ) {
+			// splice in new declarations after previous decl
+			translationUnit.splice( decl, visitor.declsToAddAfter );
+
+			if ( decl == translationUnit.end() ) break;
+			
+			// run mutator on declaration
+			maybeAccept( *decl, visitor );
+
+			// splice in new declarations before current decl
+			translationUnit.splice( decl, visitor.declsToAdd );
+		}
 	}
 
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision dbe8f244d5ddc4656e04f6da8db1d7f072f437bf)
+++ src/SymTab/Autogen.cc	(revision 35b1bf4a3c6817f25d0e553e86d13309a28c2b42)
@@ -10,6 +10,6 @@
 // Created On       : Thu Mar 03 15:45:56 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jul 12 17:47:17 2016
-// Update Count     : 2
+// Last Modified On : Thu Feb  2 18:04:40 2017
+// Update Count     : 11
 //
 
@@ -43,4 +43,8 @@
 
 	class AutogenerateRoutines final : public Visitor {
+	    template< typename Visitor >
+	    friend void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor );
+	    template< typename Visitor >
+	    friend void addVisitStatementList( std::list< Statement* > &stmts, Visitor &visitor );
 	  public:
 		std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
@@ -67,5 +71,5 @@
 		template< typename StmtClass > void visitStatement( StmtClass *stmt );
 
-		std::list< Declaration * > declsToAdd;
+		std::list< Declaration * > declsToAdd, declsToAddAfter;
 		std::set< std::string > structsDone;
 		unsigned int functionNesting = 0;     // current level of nested functions
@@ -98,5 +102,5 @@
 	void autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
 		AutogenerateRoutines generator;
-		acceptAndAdd( translationUnit, generator, false );
+		acceptAndAdd( translationUnit, generator );
 
 		// needs to be done separately because AutogenerateRoutines skips types that appear as function arguments, etc.
@@ -567,6 +571,5 @@
 			EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
 			// enumInst->set_baseEnum( enumDecl );
-			// declsToAdd.push_back(
-			makeEnumFunctions( enumDecl, enumInst, functionNesting, declsToAdd );
+			makeEnumFunctions( enumDecl, enumInst, functionNesting, declsToAddAfter );
 		}
 	}
@@ -581,5 +584,5 @@
 			}
 			structInst.set_baseStruct( structDecl );
-			makeStructFunctions( structDecl, &structInst, functionNesting, declsToAdd, data );
+			makeStructFunctions( structDecl, &structInst, functionNesting, declsToAddAfter, data );
 			structsDone.insert( structDecl->get_name() );
 		} // if
@@ -593,5 +596,5 @@
 				unionInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );
 			}
-			makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAdd );
+			makeUnionFunctions( unionDecl, &unionInst, functionNesting, declsToAddAfter );
 		} // if
 	}
@@ -618,5 +621,5 @@
 		FunctionDecl *func = genFunc( "?=?", type, functionNesting );
 		func->get_statements()->get_kids() = stmts;
-		declsToAdd.push_back( func );
+		declsToAddAfter.push_back( func );
 	}
 
@@ -763,2 +766,8 @@
 	}
 } // SymTab
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision dbe8f244d5ddc4656e04f6da8db1d7f072f437bf)
+++ src/SymTab/Autogen.h	(revision 35b1bf4a3c6817f25d0e553e86d13309a28c2b42)
@@ -9,7 +9,7 @@
 // Author           : Rob Schluntz
 // Created On       : Sun May 17 21:53:34 2015
-// Last Modified By : Rob Schluntz
-// Last Modified On : Tue May 19 16:49:43 2015
-// Update Count     : 1
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Wed Feb  1 16:31:00 2017
+// Update Count     : 2
 //
 
@@ -58,5 +58,5 @@
 			assert( type );
 			Type * castType = type->clone();
-			castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
+			castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true);
 			castType->set_isLvalue( true ); // xxx - might not need this
 			dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision dbe8f244d5ddc4656e04f6da8db1d7f072f437bf)
+++ src/SymTab/Validate.cc	(revision 35b1bf4a3c6817f25d0e553e86d13309a28c2b42)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 21:50:04 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jul 12 17:49:21 2016
-// Update Count     : 298
+// Last Modified On : Thu Feb  2 17:47:54 2017
+// Update Count     : 312
 //
 
@@ -67,4 +67,8 @@
 namespace SymTab {
 	class HoistStruct final : public Visitor {
+		template< typename Visitor >
+		friend void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor );
+	    template< typename Visitor >
+	    friend void addVisitStatementList( std::list< Statement* > &stmts, Visitor &visitor );
 	  public:
 		/// Flattens nested struct types
@@ -73,4 +77,7 @@
 		std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
 
+		virtual void visit( EnumInstType *enumInstType );
+		virtual void visit( StructInstType *structInstType );
+		virtual void visit( UnionInstType *unionInstType );
 		virtual void visit( StructDecl *aggregateDecl );
 		virtual void visit( UnionDecl *aggregateDecl );
@@ -83,5 +90,5 @@
 		template< typename AggDecl > void handleAggregate( AggDecl *aggregateDecl );
 
-		std::list< Declaration * > declsToAdd;
+		std::list< Declaration * > declsToAdd, declsToAddAfter;
 		bool inStruct;
 	};
@@ -115,7 +122,9 @@
 	  private:
   		using Parent::visit;
+		void visit( EnumInstType *enumInst ) final;
 		void visit( StructInstType *structInst ) final;
 		void visit( UnionInstType *unionInst ) final;
 		void visit( TraitInstType *contextInst ) final;
+		void visit( EnumDecl *enumDecl ) final;
 		void visit( StructDecl *structDecl ) final;
 		void visit( UnionDecl *unionDecl ) final;
@@ -124,6 +133,8 @@
 		const Indexer *indexer;
 
+		typedef std::map< std::string, std::list< EnumInstType * > > ForwardEnumsType;
 		typedef std::map< std::string, std::list< StructInstType * > > ForwardStructsType;
 		typedef std::map< std::string, std::list< UnionInstType * > > ForwardUnionsType;
+		ForwardEnumsType forwardEnums;
 		ForwardStructsType forwardStructs;
 		ForwardUnionsType forwardUnions;
@@ -236,5 +247,5 @@
 	void HoistStruct::hoistStruct( std::list< Declaration * > &translationUnit ) {
 		HoistStruct hoister;
-		acceptAndAdd( translationUnit, hoister, true );
+		acceptAndAdd( translationUnit, hoister );
 	}
 
@@ -260,5 +271,5 @@
 		return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl );
 	}
-	// xxx - shouldn't this be declsToAddBefore?
+
 	template< typename AggDecl >
 	void HoistStruct::handleAggregate( AggDecl *aggregateDecl ) {
@@ -276,4 +287,22 @@
 	}
 
+	void HoistStruct::visit( EnumInstType *structInstType ) {
+		if ( structInstType->get_baseEnum() ) {
+			declsToAdd.push_front( structInstType->get_baseEnum() );
+		}
+	}
+
+	void HoistStruct::visit( StructInstType *structInstType ) {
+		if ( structInstType->get_baseStruct() ) {
+			declsToAdd.push_front( structInstType->get_baseStruct() );
+		}
+	}
+
+	void HoistStruct::visit( UnionInstType *structInstType ) {
+		if ( structInstType->get_baseUnion() ) {
+			declsToAdd.push_front( structInstType->get_baseUnion() );
+		}
+	}
+
 	void HoistStruct::visit( StructDecl *aggregateDecl ) {
 		handleAggregate( aggregateDecl );
@@ -297,5 +326,5 @@
 			ObjectDecl * obj = dynamic_cast< ObjectDecl * >( *i );
 			assert( obj );
-			obj->set_type( new EnumInstType( Type::Qualifiers( true, false, false, false, false, false ), enumDecl->get_name() ) );
+			obj->set_type( new EnumInstType( Type::Qualifiers( true, false, false, false, false ), enumDecl->get_name() ) );
 		} // for
 		Parent::visit( enumDecl );
@@ -349,4 +378,18 @@
 	}
 
+	void LinkReferenceToTypes::visit( EnumInstType *enumInst ) {
+		Parent::visit( enumInst );
+		EnumDecl *st = indexer->lookupEnum( enumInst->get_name() );
+		// it's not a semantic error if the enum is not found, just an implicit forward declaration
+		if ( st ) {
+			//assert( ! enumInst->get_baseEnum() || enumInst->get_baseEnum()->get_members().empty() || ! st->get_members().empty() );
+			enumInst->set_baseEnum( st );
+		} // if
+		if ( ! st || st->get_members().empty() ) {
+			// use of forward declaration
+			forwardEnums[ enumInst->get_name() ].push_back( enumInst );
+		} // if
+	}
+
 	void LinkReferenceToTypes::visit( StructInstType *structInst ) {
 		Parent::visit( structInst );
@@ -419,4 +462,18 @@
 			}
 		}
+	}
+
+	void LinkReferenceToTypes::visit( EnumDecl *enumDecl ) {
+		// visit enum members first so that the types of self-referencing members are updated properly
+		Parent::visit( enumDecl );
+		if ( ! enumDecl->get_members().empty() ) {
+			ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl->get_name() );
+			if ( fwds != forwardEnums.end() ) {
+				for ( std::list< EnumInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
+					(*inst )->set_baseEnum( enumDecl );
+				} // for
+				forwardEnums.erase( fwds );
+			} // if
+		} // if
 	}
 
