Index: src/SymTab/AddVisit.h
===================================================================
--- src/SymTab/AddVisit.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/AddVisit.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,93 @@
+//
+// 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.
+//
+// AddVisit.h -- 
+//
+// Author           : Richard C. Bilson
+// Created On       : Sun May 17 16:14:32 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sun May 17 16:16:38 2015
+// Update Count     : 3
+//
+
+namespace SymTab {
+	void addDecls( std::list< Declaration* > &declsToAdd, std::list< Statement* > &statements, std::list< Statement* >::iterator i );
+
+	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() );
+	}
+
+	template< typename Visitor >
+	inline void addVisitStatement( Statement *stmt, Visitor &visitor ) {
+		maybeAccept( stmt, visitor );
+///   if ( ! declsToAdd.empty() ) {
+///     CompoundStmt *compound = new CompoundStmt( noLabels );
+///     compound->get_kids().push_back( stmt );
+///     addDecls( declsToAdd, compound->get_kids(), compound->get_kids().end() );
+///   }
+	}
+
+	template< typename Visitor >
+	inline void addVisit(CompoundStmt *compoundStmt, Visitor &visitor) {
+		addVisitStatementList( compoundStmt->get_kids(), visitor );
+	}
+
+	template< typename Visitor >
+	inline void addVisit(IfStmt *ifStmt, Visitor &visitor) {
+		addVisitStatement( ifStmt->get_thenPart(), visitor );
+		addVisitStatement( ifStmt->get_elsePart(), visitor );
+		maybeAccept( ifStmt->get_condition(), visitor );
+	}
+
+	template< typename Visitor >
+	inline void addVisit(WhileStmt *whileStmt, Visitor &visitor) {
+		addVisitStatement( whileStmt->get_body(), visitor );
+		maybeAccept( whileStmt->get_condition(), visitor );
+	}
+
+	template< typename Visitor >
+	inline void addVisit(ForStmt *forStmt, Visitor &visitor) {
+		addVisitStatement( forStmt->get_body(), visitor );
+		maybeAccept( forStmt->get_initialization(), visitor );
+		maybeAccept( forStmt->get_condition(), visitor );
+		maybeAccept( forStmt->get_increment(), visitor );
+	}
+
+	template< typename Visitor >
+	inline void addVisit(SwitchStmt *switchStmt, Visitor &visitor) {
+		addVisitStatementList( switchStmt->get_branches(), visitor );
+		maybeAccept( switchStmt->get_condition(), visitor );
+	}
+
+	template< typename Visitor >
+	inline void addVisit(ChooseStmt *switchStmt, Visitor &visitor) {
+		addVisitStatementList( switchStmt->get_branches(), visitor );
+		maybeAccept( switchStmt->get_condition(), visitor );
+	}
+
+	template< typename Visitor >
+	inline void addVisit(CaseStmt *caseStmt, Visitor &visitor) {
+		addVisitStatementList( caseStmt->get_statements(), visitor );
+		maybeAccept( caseStmt->get_condition(), visitor );
+	}
+
+	template< typename Visitor >
+	inline void addVisit(CatchStmt *cathStmt, Visitor &visitor) {
+		addVisitStatement( cathStmt->get_body(), visitor );
+		maybeAccept( cathStmt->get_decl(), visitor );
+	}
+} // namespace SymTab
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/AggregateTable.h
===================================================================
--- src/SymTab/AggregateTable.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/AggregateTable.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,53 @@
+//
+// 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 : Sun May 17 16:19:29 2015
+// Update Count     : 4
+//
+
+#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< ContextDecl, AggregateTableConflictFunction< ContextDecl > > ContextTable;
+} // namespace SymTab
+
+#endif // AGGREGATETABLE_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/FixFunction.cc
===================================================================
--- src/SymTab/FixFunction.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/FixFunction.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,80 @@
+//
+// 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.
+//
+// FixFunction.cc -- 
+//
+// Author           : Richard C. Bilson
+// Created On       : Sun May 17 16:19:49 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sun May 17 16:22:54 2015
+// Update Count     : 2
+//
+
+#include "FixFunction.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Type.h"
+#include "SynTree/Expression.h"
+#include "utility.h"
+
+namespace SymTab {
+	FixFunction::FixFunction() : isVoid( false ) {
+	}
+
+	DeclarationWithType * FixFunction::mutate(FunctionDecl *functionDecl) {
+		ObjectDecl *pointer = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClass(), functionDecl->get_linkage(), 0, new PointerType( Type::Qualifiers(), functionDecl->get_type()->clone() ), 0 );
+		delete functionDecl;
+		return pointer;
+	}
+
+	Type * FixFunction::mutate(VoidType *voidType) {
+		isVoid = true;
+		return voidType;
+	}
+
+	Type * FixFunction::mutate(BasicType *basicType) {
+		return basicType;
+	}
+
+	Type * FixFunction::mutate(PointerType *pointerType) {
+		return pointerType;
+	}
+
+	Type * FixFunction::mutate(ArrayType *arrayType) {
+		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), maybeClone( arrayType->get_base()->clone() ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
+		delete arrayType;
+		return pointerType;
+	}
+
+	Type * FixFunction::mutate(StructInstType *aggregateUseType) {
+		return aggregateUseType;
+	}
+
+	Type * FixFunction::mutate(UnionInstType *aggregateUseType) {
+		return aggregateUseType;
+	}
+
+	Type * FixFunction::mutate(EnumInstType *aggregateUseType) {
+		return aggregateUseType;
+	}
+
+	Type * FixFunction::mutate(ContextInstType *aggregateUseType) {
+		return aggregateUseType;
+	}
+
+	Type * FixFunction::mutate(TypeInstType *aggregateUseType) {
+		return aggregateUseType;
+	}
+
+	Type * FixFunction::mutate(TupleType *tupleType) {
+		return tupleType;
+	}
+} // namespace SymTab
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/FixFunction.h
===================================================================
--- src/SymTab/FixFunction.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/FixFunction.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,53 @@
+//
+// 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.
+//
+// FixFunction.h -- 
+//
+// Author           : Richard C. Bilson
+// Created On       : Sun May 17 17:02:08 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sun May 17 17:03:43 2015
+// Update Count     : 2
+//
+
+#ifndef FIXFUNCTION_H
+#define FIXFUNCTION_H
+
+#include "SynTree/Mutator.h"
+
+namespace SymTab {
+	class FixFunction : public Mutator {
+		typedef Mutator Parent;
+	  public:
+		FixFunction();
+
+		bool get_isVoid() const { return isVoid; }
+		void set_isVoid( bool newValue ) { isVoid = newValue; }
+	  private:
+		virtual DeclarationWithType* mutate(FunctionDecl *functionDecl);
+
+		virtual Type* mutate(VoidType *voidType);
+		virtual Type* mutate(BasicType *basicType);
+		virtual Type* mutate(PointerType *pointerType);
+		virtual Type* mutate(ArrayType *arrayType);
+		virtual Type* mutate(StructInstType *aggregateUseType);
+		virtual Type* mutate(UnionInstType *aggregateUseType);
+		virtual Type* mutate(EnumInstType *aggregateUseType);
+		virtual Type* mutate(ContextInstType *aggregateUseType);
+		virtual Type* mutate(TypeInstType *aggregateUseType);
+		virtual Type* mutate(TupleType *tupleType);
+  
+		bool isVoid;
+	};
+} // namespace SymTab
+
+#endif // FIXFUNCTION_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/IdTable.cc
===================================================================
--- src/SymTab/IdTable.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/IdTable.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,166 @@
+//
+// 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 : Sun May 17 17:07:43 2015
+// Update Count     : 3
+//
+
+#include <cassert>
+
+#include "SynTree/Declaration.h"
+#include "ResolvExpr/typeops.h"
+#include "Indexer.h"
+#include "Mangler.h"
+#include "IdTable.h"
+#include "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;
+				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 {
+			manglename = Mangler::mangle( decl );
+		} // if
+
+		InnerTableType &declTable = table[ name ];
+		InnerTableType::iterator it = declTable.find( manglename );
+
+		if ( it == declTable.end() ) {
+			declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) );
+		} else {
+			std::stack< DeclEntry >& entry = it->second;
+			if ( ! entry.empty() && entry.top().second == scopeLevel ) {
+				if ( decl->get_linkage() != LinkageSpec::C || ResolvExpr::typesCompatible( decl->get_type(), entry.top().first->get_type(), Indexer() ) ) {
+					FunctionDecl *newentry = dynamic_cast< FunctionDecl* >( decl );
+					FunctionDecl *old = dynamic_cast< FunctionDecl* >( entry.top().first );
+					if ( newentry && old && newentry->get_statements() && old->get_statements() ) {
+						throw SemanticError( "duplicate function definition for ", decl );
+					} else {
+						ObjectDecl *newobj = dynamic_cast< ObjectDecl* >( decl );
+						ObjectDecl *oldobj = dynamic_cast< ObjectDecl* >( entry.top().first );
+						if ( newobj && oldobj && newobj->get_init() && oldobj->get_init() ) {
+							throw SemanticError( "duplicate definition for ", decl );
+						} // if
+					} // if
+				} else {
+					throw SemanticError( "duplicate definition for ", decl );
+				} // if
+			} else {
+				declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) );
+			} // if
+		} // if
+		// ensure the set of routines with C linkage cannot be overloaded
+		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: src/SymTab/IdTable.h
===================================================================
--- src/SymTab/IdTable.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/IdTable.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,54 @@
+//
+// 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/ImplementationType.cc
===================================================================
--- src/SymTab/ImplementationType.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/ImplementationType.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,124 @@
+//
+// 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.
+//
+// ImplementationType.cc -- 
+//
+// Author           : Richard C. Bilson
+// Created On       : Sun May 17 21:32:01 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sun May 17 21:34:40 2015
+// Update Count     : 2
+//
+
+#include "ImplementationType.h"
+#include "SynTree/Type.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Visitor.h"
+#include "SymTab/Indexer.h"
+#include "utility.h"
+
+
+namespace SymTab {
+	class ImplementationType : public Visitor {
+	  public:
+		ImplementationType( const SymTab::Indexer &indexer );
+
+		Type *get_result() { return result; }
+	  private:
+		virtual void visit(VoidType *voidType);
+		virtual void visit(BasicType *basicType);
+		virtual void visit(PointerType *pointerType);
+		virtual void visit(ArrayType *arrayType);
+		virtual void visit(FunctionType *functionType);
+		virtual void visit(StructInstType *aggregateUseType);
+		virtual void visit(UnionInstType *aggregateUseType);
+		virtual void visit(EnumInstType *aggregateUseType);
+		virtual void visit(ContextInstType *aggregateUseType);
+		virtual void visit(TypeInstType *aggregateUseType);
+		virtual void visit(TupleType *tupleType);
+
+		Type *result;			// synthesized
+		const SymTab::Indexer &indexer;
+	};
+
+	Type * implementationType( Type *type, const SymTab::Indexer& indexer ) {
+		ImplementationType implementor( indexer );
+		type->accept( implementor );
+		if ( implementor.get_result() == 0 ) {
+			return type->clone();
+		} else {
+			return implementor.get_result();
+		} // if
+	}
+
+	ImplementationType::ImplementationType( const SymTab::Indexer &indexer ) : result( 0 ), indexer( indexer ) {
+	}
+
+	void ImplementationType::visit(VoidType *voidType) {
+	}
+
+	void ImplementationType::visit(BasicType *basicType) {
+	}
+
+	void ImplementationType::visit(PointerType *pointerType) {
+		PointerType *newType = pointerType->clone();
+		newType->set_base( implementationType( pointerType->get_base(), indexer ) );
+		result = newType;
+	}
+
+	void ImplementationType::visit(ArrayType *arrayType) {
+		ArrayType *newType = arrayType->clone();
+		newType->set_base( implementationType( arrayType->get_base(), indexer ) );
+		result = newType;
+	}
+
+	void ImplementationType::visit(FunctionType *functionType) {
+///   FunctionType *newType = functionType->clone();
+///   for ( std::list< DeclarationWithType* >::iterator i = newType->get_parameters().begin(); i != newType->get_parameters().end(); ++i ) {
+///     i->set_type( implementationType( i->get_type(), indexer ) );
+///   }
+///   for ( std::list< DeclarationWithType* >::iterator i = newType->get_parameters().begin(); i != newType->get_parameters().end(); ++i ) {
+///     i->set_type( implementationType( i->get_type(), indexer ) );
+///   }
+	}
+
+	void ImplementationType::visit(StructInstType *aggregateUseType) {
+	}
+
+	void ImplementationType::visit(UnionInstType *aggregateUseType) {
+	}
+
+	void ImplementationType::visit(EnumInstType *aggregateUseType) {
+	}
+
+	void ImplementationType::visit(ContextInstType *aggregateUseType) {
+	}
+
+	void ImplementationType::visit(TypeInstType *inst) {
+		NamedTypeDecl *typeDecl = indexer.lookupType( inst->get_name() );
+		if ( typeDecl && typeDecl->get_base() ) {
+			Type *base = implementationType( typeDecl->get_base(), indexer );
+			base->get_qualifiers() += inst->get_qualifiers();
+			result = base;
+		} // if
+	}
+
+	void ImplementationType::visit(TupleType *tupleType) {
+		TupleType *newType = new TupleType( Type::Qualifiers() );
+		for ( std::list< Type* >::iterator i = tupleType->get_types().begin(); i != tupleType->get_types().end(); ++i ) {
+			Type *implType = implementationType( *i, indexer );
+			implType->get_qualifiers() += tupleType->get_qualifiers();
+			newType->get_types().push_back( implType );
+		} // for
+		result = newType;
+	}
+} // namespace SymTab
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/ImplementationType.h
===================================================================
--- src/SymTab/ImplementationType.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/ImplementationType.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,39 @@
+//
+// 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.
+//
+// ImplementationType.h -- 
+//
+// Author           : Richard C. Bilson
+// Created On       : Sun May 17 21:35:41 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sun May 17 21:37:15 2015
+// Update Count     : 2
+//
+
+#ifndef IMPLEMENTATIONTYPE_H
+#define IMPLEMENTATIONTYPE_H
+
+#include "SynTree/SynTree.h"
+#include "SymTab/Indexer.h"
+
+namespace SymTab {
+	Type *implementationType( Type *, const SymTab::Indexer &indexer );
+
+	template< typename InputIterator, typename OutputIterator >
+	void implementationTypeList( InputIterator begin, InputIterator end, OutputIterator out, const SymTab::Indexer &indexer ) {
+		while ( begin != end ) {
+			*out++ = implementationType( *begin++, indexer );
+		} // while
+	}
+} // namespace SymTab
+
+#endif // IMPLEMENTATIONTYPE_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/Indexer.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,275 @@
+//
+// 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.
+//
+// Indexer.cc -- 
+//
+// Author           : Richard C. Bilson
+// Created On       : Sun May 17 21:37:33 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue May 19 16:49:55 2015
+// Update Count     : 3
+//
+
+#include "SynTree/Declaration.h"
+#include "SynTree/Type.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Initializer.h"
+#include "SynTree/Statement.h"
+#include "Indexer.h"
+#include <typeinfo>
+#include "utility.h"
+
+#define debugPrint(x) if ( doDebug ) { std::cout << x; }
+
+namespace SymTab {
+	Indexer::Indexer( bool useDebug ) : doDebug( useDebug ) {}
+
+	Indexer::~Indexer() {}
+
+	void Indexer::visit( ObjectDecl *objectDecl ) {
+		maybeAccept( objectDecl->get_type(), *this );
+		maybeAccept( objectDecl->get_init(), *this );
+		maybeAccept( objectDecl->get_bitfieldWidth(), *this );
+		if ( objectDecl->get_name() != "" ) {
+			debugPrint( "Adding object " << objectDecl->get_name() << std::endl );
+			idTable.addDecl( objectDecl );
+		} // if
+	}
+
+	void Indexer::visit( FunctionDecl *functionDecl ) {
+		if ( functionDecl->get_name() == "" ) return;
+		debugPrint( "Adding function " << functionDecl->get_name() << std::endl );
+		idTable.addDecl( functionDecl );
+		enterScope();
+		maybeAccept( functionDecl->get_functionType(), *this );
+		acceptAll( functionDecl->get_oldDecls(), *this );
+		maybeAccept( functionDecl->get_statements(), *this );
+		leaveScope();
+	}
+
+/********
+ * A NOTE ON THE ORDER OF TRAVERSAL
+ *
+ * Types and typedefs have their base types visited before they are added to the type table.
+ * This is ok, since there is no such thing as a recursive type or typedef.
+ *             typedef struct { T *x; } T; // never allowed
+ *
+ * for structs/unions, it is possible to have recursion, so the decl should be added as if it's
+ * incomplete to begin, the members are traversed, and then the complete type should be added
+ * (assuming the type is completed by this particular declaration).
+ *             struct T { struct T *x; }; // allowed
+ *
+ * It's important to add the complete type to the symbol table *after* the members/base has been
+ * traversed, since that traversal may modify the definition of the type and these modifications
+ * should be visible when the symbol table is queried later in this pass.
+ *
+ * TODO: figure out whether recursive contexts are sensible/possible/reasonable.
+ */
+
+	void Indexer::visit( TypeDecl *typeDecl ) {
+		// see A NOTE ON THE ORDER OF TRAVERSAL, above
+		// note that assertions come after the type is added to the symtab, since they aren't part
+		// of the type proper and may depend on the type itself
+		enterScope();
+		acceptAll( typeDecl->get_parameters(), *this );
+		maybeAccept( typeDecl->get_base(), *this );
+		leaveScope();
+		debugPrint( "Adding type " << typeDecl->get_name() << std::endl );
+		typeTable.add( typeDecl );
+		acceptAll( typeDecl->get_assertions(), *this );
+	}
+
+	void Indexer::visit( TypedefDecl *typeDecl ) {
+		enterScope();
+		acceptAll( typeDecl->get_parameters(), *this );
+		maybeAccept( typeDecl->get_base(), *this );
+		leaveScope();
+		debugPrint( "Adding typedef " << typeDecl->get_name() << std::endl );
+		typeTable.add( typeDecl );
+	}
+
+	void Indexer::visit( StructDecl *aggregateDecl ) {
+		// make up a forward declaration and add it before processing the members
+		StructDecl fwdDecl( aggregateDecl->get_name() );
+		cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
+		debugPrint( "Adding fwd decl for struct " << fwdDecl.get_name() << std::endl );
+		structTable.add( &fwdDecl );
+  
+		enterScope();
+		acceptAll( aggregateDecl->get_parameters(), *this );
+		acceptAll( aggregateDecl->get_members(), *this );
+		leaveScope();
+  
+		debugPrint( "Adding struct " << aggregateDecl->get_name() << std::endl );
+		// this addition replaces the forward declaration
+		structTable.add( aggregateDecl );
+	}
+
+	void Indexer::visit( UnionDecl *aggregateDecl ) {
+		// make up a forward declaration and add it before processing the members
+		UnionDecl fwdDecl( aggregateDecl->get_name() );
+		cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
+		debugPrint( "Adding fwd decl for union " << fwdDecl.get_name() << std::endl );
+		unionTable.add( &fwdDecl );
+  
+		enterScope();
+		acceptAll( aggregateDecl->get_parameters(), *this );
+		acceptAll( aggregateDecl->get_members(), *this );
+		leaveScope();
+  
+		debugPrint( "Adding union " << aggregateDecl->get_name() << std::endl );
+		unionTable.add( aggregateDecl );
+	}
+
+	void Indexer::visit( EnumDecl *aggregateDecl ) {
+		debugPrint( "Adding enum " << aggregateDecl->get_name() << std::endl );
+		enumTable.add( aggregateDecl );
+		// unlike structs, contexts, and unions, enums inject their members into the global scope
+		acceptAll( aggregateDecl->get_members(), *this );
+	}
+
+	void Indexer::visit( ContextDecl *aggregateDecl ) {
+		enterScope();
+		acceptAll( aggregateDecl->get_parameters(), *this );
+		acceptAll( aggregateDecl->get_members(), *this );
+		leaveScope();
+  
+		debugPrint( "Adding context " << aggregateDecl->get_name() << std::endl );
+		contextTable.add( aggregateDecl );
+	}
+
+	void Indexer::visit( CompoundStmt *compoundStmt ) {
+		enterScope();
+		acceptAll( compoundStmt->get_kids(), *this );
+		leaveScope();
+	}
+
+	void Indexer::visit( ContextInstType *contextInst ) {
+		acceptAll( contextInst->get_parameters(), *this );
+		acceptAll( contextInst->get_members(), *this );
+	}
+
+	void Indexer::visit( StructInstType *structInst ) {
+		if ( ! structTable.lookup( structInst->get_name() ) ) {
+			debugPrint( "Adding struct " << structInst->get_name() << " from implicit forward declaration" << std::endl );
+			structTable.add( structInst->get_name() );
+		}
+		enterScope();
+		acceptAll( structInst->get_parameters(), *this );
+		leaveScope();
+	}
+
+	void Indexer::visit( UnionInstType *unionInst ) {
+		if ( ! unionTable.lookup( unionInst->get_name() ) ) {
+			debugPrint( "Adding union " << unionInst->get_name() << " from implicit forward declaration" << std::endl );
+			unionTable.add( unionInst->get_name() );
+		}
+		enterScope();
+		acceptAll( unionInst->get_parameters(), *this );
+		leaveScope();
+	}
+
+	void Indexer::visit( ForStmt *forStmt ) {
+	    // for statements introduce a level of scope
+	    enterScope();
+	    Visitor::visit( forStmt );
+	    leaveScope();
+	}
+
+
+	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);
+	}
+
+	NamedTypeDecl *Indexer::lookupType( const std::string &id ) const {
+		return typeTable.lookup( id );
+	}
+
+	StructDecl *Indexer::lookupStruct( const std::string &id ) const {
+		return structTable.lookup( id );
+	}
+
+	EnumDecl *Indexer::lookupEnum( const std::string &id ) const {
+		return enumTable.lookup( id );
+	}
+
+	UnionDecl *Indexer::lookupUnion( const std::string &id ) const {
+		return unionTable.lookup( id );
+	}
+
+	ContextDecl  * Indexer::lookupContext( const std::string &id ) const {
+		return contextTable.lookup( id );
+	}
+
+	void Indexer::enterScope() {
+		if ( doDebug ) {
+			std::cout << "--- Entering scope" << std::endl;
+		}
+		idTable.enterScope();
+		typeTable.enterScope();
+		structTable.enterScope();
+		enumTable.enterScope();
+		unionTable.enterScope();
+		contextTable.enterScope();
+	}
+
+	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();
+	}
+
+	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
+	}
+} // namespace SymTab
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/Indexer.h
===================================================================
--- src/SymTab/Indexer.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/Indexer.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,84 @@
+//
+// 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.
+//
+// Indexer.h -- 
+//
+// Author           : Richard C. Bilson
+// Created On       : Sun May 17 21:38:55 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue May 19 16:51:21 2015
+// Update Count     : 3
+//
+
+#ifndef INDEXER_H
+#define INDEXER_H
+
+#include <list>
+#include <string>
+#include <map>
+
+#include "SynTree/Visitor.h"
+#include "IdTable.h"
+#include "AggregateTable.h"
+#include "TypeTable.h"
+
+namespace SymTab {
+	class Indexer : public Visitor {
+	  public:
+		Indexer( bool useDebug = false );
+		virtual ~Indexer();
+
+		//using Visitor::visit;
+		virtual void visit( ObjectDecl *objectDecl );
+		virtual void visit( FunctionDecl *functionDecl );
+		virtual void visit( TypeDecl *typeDecl );
+		virtual void visit( TypedefDecl *typeDecl );
+		virtual void visit( StructDecl *aggregateDecl );
+		virtual void visit( UnionDecl *aggregateDecl );
+		virtual void visit( EnumDecl *aggregateDecl );
+		virtual void visit( ContextDecl *aggregateDecl );
+
+		virtual void visit( CompoundStmt *compoundStmt );
+
+		virtual void visit( ContextInstType *contextInst );
+		virtual void visit( StructInstType *contextInst );
+		virtual void visit( UnionInstType *contextInst );
+
+		virtual void visit( ForStmt *forStmt );
+
+		// when using an indexer manually (e.g., within a mutator traversal), it is necessary to tell the indexer
+		// explicitly when scopes begin and end
+		void enterScope();
+		void leaveScope();
+
+		void lookupId( const std::string &id, std::list< DeclarationWithType* >& ) const;
+		DeclarationWithType* lookupId( const std::string &id) const;
+		NamedTypeDecl *lookupType( const std::string &id ) const;
+		StructDecl *lookupStruct( const std::string &id ) const;
+		EnumDecl *lookupEnum( const std::string &id ) const;
+		UnionDecl *lookupUnion( const std::string &id ) const;
+		ContextDecl *lookupContext( 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;
+		ContextTable contextTable;
+  
+		bool doDebug;					// display debugging trace
+	};
+} // namespace SymTab
+
+#endif // INDEXER_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/Mangler.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,251 @@
+//
+// 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.
+//
+// Mangler.cc -- 
+//
+// Author           : Richard C. Bilson
+// Created On       : Sun May 17 21:40:29 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue May 19 16:50:47 2015
+// Update Count     : 3
+//
+
+#include <cassert>
+#include <string>
+#include <algorithm>
+#include <iterator>
+#include <functional>
+#include <set>
+
+#include "SynTree/Declaration.h"
+#include "SynTree/Type.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Initializer.h"
+#include "SynTree/Statement.h"
+#include "Mangler.h"
+#include "CodeGen/OperatorTable.h"
+
+namespace SymTab {
+	Mangler::Mangler() : nextVarNum( 0 ), isTopLevel( true ) {
+	}
+
+//Mangler::Mangler( const Mangler & )
+//  : mangleName(), varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( isTopLevel )
+//{
+//}
+	Mangler::Mangler( const Mangler &rhs ) : mangleName() {
+		varNums = rhs.varNums;
+		nextVarNum = rhs.nextVarNum;
+		isTopLevel = rhs.isTopLevel;
+	}
+
+	void Mangler::mangleDecl( DeclarationWithType *declaration ) {
+		bool wasTopLevel = isTopLevel;
+		if ( isTopLevel ) {
+			varNums.clear();
+			nextVarNum = 0;
+			isTopLevel = false;
+		} // if
+		mangleName << "__";
+		CodeGen::OperatorInfo opInfo;
+		if ( operatorLookup( declaration->get_name(), opInfo ) ) {
+			mangleName << opInfo.outputName;
+		} else {
+			mangleName << declaration->get_name();
+		} // if
+		mangleName << "__";
+		maybeAccept( declaration->get_type(), *this );
+		isTopLevel = wasTopLevel;
+	}
+
+	void Mangler::visit( ObjectDecl *declaration ) {
+		mangleDecl( declaration );
+	}
+
+	void Mangler::visit( FunctionDecl *declaration ) {
+		mangleDecl( declaration );
+	}
+
+	void Mangler::visit( VoidType *voidType ) {
+		printQualifiers( voidType );
+		mangleName << "v";
+	}
+
+	void Mangler::visit( BasicType *basicType ) {
+		static const char *btLetter[] = {
+			"b",	// Bool
+			"c",	// Char
+			"Sc",	// SignedChar
+			"Uc",	// UnsignedChar
+			"s",	// ShortSignedInt
+			"Us",	// ShortUnsignedInt
+			"i",	// SignedInt
+			"Ui",	// UnsignedInt
+			"l",	// LongSignedInt
+			"Ul",	// LongUnsignedInt
+			"q",	// LongLongSignedInt
+			"Uq",	// LongLongUnsignedInt
+			"f",	// Float
+			"d",	// Double
+			"r",	// LongDouble
+			"Xf",	// FloatComplex
+			"Xd",	// DoubleComplex
+			"Xr",	// LongDoubleComplex
+			"If",	// FloatImaginary
+			"Id",	// DoubleImaginary
+			"Ir",	// LongDoubleImaginary
+		};
+  
+		printQualifiers( basicType );
+		mangleName << btLetter[ basicType->get_kind() ];
+	}
+
+	void Mangler::visit( PointerType *pointerType ) {
+		printQualifiers( pointerType );
+		mangleName << "P";
+		maybeAccept( pointerType->get_base(), *this );
+	}
+
+	void Mangler::visit( ArrayType *arrayType ) {
+		// TODO: encode dimension
+		printQualifiers( arrayType );
+		mangleName << "A0";
+		maybeAccept( arrayType->get_base(), *this );
+	}
+
+	namespace {
+		inline std::list< Type* > getTypes( const std::list< DeclarationWithType* > decls ) {
+			std::list< Type* > ret;
+			std::transform( decls.begin(), decls.end(), std::back_inserter( ret ),
+							std::mem_fun( &DeclarationWithType::get_type ) );
+			return ret;
+		}
+	}
+
+	void Mangler::visit( FunctionType *functionType ) {
+		printQualifiers( functionType );
+		mangleName << "F";
+		std::list< Type* > returnTypes = getTypes( functionType->get_returnVals() );
+		acceptAll( returnTypes, *this );
+		mangleName << "_";
+		std::list< Type* > paramTypes = getTypes( functionType->get_parameters() );
+		acceptAll( paramTypes, *this );
+		mangleName << "_";
+	}
+
+	void Mangler::mangleRef( ReferenceToType *refType, std::string prefix ) {
+		printQualifiers( refType );
+		mangleName << ( refType->get_name().length() + prefix.length() ) << prefix << refType->get_name();
+	}
+
+	void Mangler::visit( StructInstType *aggregateUseType ) {
+		mangleRef( aggregateUseType, "s" );
+	}
+
+	void Mangler::visit( UnionInstType *aggregateUseType ) {
+		mangleRef( aggregateUseType, "u" );
+	}
+
+	void Mangler::visit( EnumInstType *aggregateUseType ) {
+		mangleRef( aggregateUseType, "e" );
+	}
+
+	void Mangler::visit( TypeInstType *typeInst ) {
+		VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
+		if ( varNum == varNums.end() ) {
+			mangleRef( typeInst, "t" );
+		} else {
+			printQualifiers( typeInst );
+			std::ostrstream numStream;
+			numStream << varNum->second.first;
+			mangleName << (numStream.pcount() + 1);
+			switch ( (TypeDecl::Kind )varNum->second.second ) {
+			  case TypeDecl::Any:
+				mangleName << "t";
+				break;
+			  case TypeDecl::Dtype:
+				mangleName << "d";
+				break;
+			  case TypeDecl::Ftype:
+				mangleName << "f";
+				break;
+			} // switch
+			mangleName << std::string( numStream.str(), numStream.pcount() );
+		} // if
+	}
+
+	void Mangler::visit( TupleType *tupleType ) {
+		printQualifiers( tupleType );
+		mangleName << "T";
+		acceptAll( tupleType->get_types(), *this );
+		mangleName << "_";
+	}
+
+	void Mangler::visit( TypeDecl *decl ) {
+		static const char *typePrefix[] = { "BT", "BD", "BF" };
+		mangleName << typePrefix[ decl->get_kind() ] << ( decl->get_name().length() + 1 ) << decl->get_name();
+	}
+
+	void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) {
+		for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) {
+			os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl;
+		} // for
+	}
+
+	void Mangler::printQualifiers( Type *type ) {
+		if ( ! type->get_forall().empty() ) {
+			std::list< std::string > assertionNames;
+			int tcount = 0, dcount = 0, fcount = 0;
+			mangleName << "A";
+			for ( std::list< TypeDecl* >::iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
+				switch ( (*i)->get_kind() ) {
+				  case TypeDecl::Any:
+					tcount++;
+					break;
+				  case TypeDecl::Dtype:
+					dcount++;
+					break;
+				  case TypeDecl::Ftype:
+					fcount++;
+					break;
+				} // switch
+				varNums[ (*i )->get_name() ] = std::pair< int, int >( nextVarNum++, (int )(*i )->get_kind() );
+				for ( std::list< DeclarationWithType* >::iterator assert = (*i )->get_assertions().begin(); assert != (*i )->get_assertions().end(); ++assert ) {
+					Mangler sub_mangler;
+					sub_mangler.nextVarNum = nextVarNum;
+					sub_mangler.isTopLevel = false;
+					sub_mangler.varNums = varNums;
+					(*assert)->accept( sub_mangler );
+					assertionNames.push_back( std::string( sub_mangler.mangleName.str(), sub_mangler.mangleName.pcount() ) );
+				} // for
+			} // for
+			mangleName << tcount << "_" << dcount << "_" << fcount << "_";
+			std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
+			mangleName << "_";
+		} // if
+		if ( type->get_isConst() ) {
+			mangleName << "C";
+		} // if
+		if ( type->get_isVolatile() ) {
+			mangleName << "V";
+		} // if
+		if ( type->get_isRestrict() ) {
+			mangleName << "R";
+		} // if
+		if ( type->get_isLvalue() ) {
+			mangleName << "L";
+		} // if
+		if ( type->get_isAtomic() ) {
+			mangleName << "A";
+		} // if
+	}
+} // namespace SymTab
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/Mangler.h
===================================================================
--- src/SymTab/Mangler.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/Mangler.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,76 @@
+//
+// 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.
+//
+// Mangler.h -- 
+//
+// Author           : Richard C. Bilson
+// Created On       : Sun May 17 21:44:03 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue May 19 16:49:21 2015
+// Update Count     : 3
+//
+
+#ifndef MANGLER_H
+#define MANGLER_H
+
+#include <strstream>
+#include "SynTree/SynTree.h"
+#include "SynTree/Visitor.h"
+
+namespace SymTab {
+	class Mangler : public Visitor {
+	  public:
+		template< typename SynTreeClass >
+	    static std::string mangle( SynTreeClass *decl ); // interface to clients
+
+///   using Visitor::visit;
+		virtual void visit( ObjectDecl *declaration );
+		virtual void visit( FunctionDecl *declaration );
+		virtual void visit( TypeDecl *declaration );
+
+		virtual void visit( VoidType *voidType );
+		virtual void visit( BasicType *basicType );
+		virtual void visit( PointerType *pointerType );
+		virtual void visit( ArrayType *arrayType );
+		virtual void visit( FunctionType *functionType );
+		virtual void visit( StructInstType *aggregateUseType );
+		virtual void visit( UnionInstType *aggregateUseType );
+		virtual void visit( EnumInstType *aggregateUseType );
+		virtual void visit( TypeInstType *aggregateUseType );
+		virtual void visit( TupleType *tupleType );
+  
+		std::string get_mangleName() { return std::string( mangleName.str(), mangleName.pcount() ); }
+	  private:
+		std::ostrstream mangleName;
+		typedef std::map< std::string, std::pair< int, int > > VarMapType;
+		VarMapType varNums;
+		int nextVarNum;
+		bool isTopLevel;
+  
+		Mangler();
+		Mangler( const Mangler & );
+  
+		void mangleDecl( DeclarationWithType *declaration );
+		void mangleRef( ReferenceToType *refType, std::string prefix );
+  
+		void printQualifiers( Type *type );
+	}; // Mangler
+
+	template< typename SynTreeClass >
+	std::string Mangler::mangle( SynTreeClass *decl ) {
+		Mangler mangler;
+		maybeAccept( decl, mangler );
+		return mangler.get_mangleName();
+	}
+} // SymTab
+
+#endif // MANGLER_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/StackTable.cc
===================================================================
--- src/SymTab/StackTable.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/StackTable.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,84 @@
+//
+// 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: src/SymTab/StackTable.h
===================================================================
--- src/SymTab/StackTable.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/StackTable.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,55 @@
+//
+// 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: src/SymTab/TypeTable.h
===================================================================
--- src/SymTab/TypeTable.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/TypeTable.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,53 @@
+//
+// 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/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/Validate.cc	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,802 @@
+//
+// 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.
+//
+// Validate.cc -- 
+//
+// Author           : Richard C. Bilson
+// Created On       : Sun May 17 21:50:04 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue May 19 16:50:09 2015
+// Update Count     : 3
+//
+
+// The "validate" phase of translation is used to take a syntax tree and convert it into a standard form that aims to be
+// as regular in structure as possible.  Some assumptions can be made regarding the state of the tree after this pass is
+// complete, including:
+//
+// - No nested structure or union definitions; any in the input are "hoisted" to the level of the containing struct or
+//   union.
+//
+// - All enumeration constants have type EnumInstType.
+//
+// - The type "void" never occurs in lists of function parameter or return types; neither do tuple types.  A function
+//   taking no arguments has no argument types, and tuples are flattened.
+//
+// - No context instances exist; they are all replaced by the set of declarations signified by the context, instantiated
+//   by the particular set of type arguments.
+//
+// - Every declaration is assigned a unique id.
+//
+// - No typedef declarations or instances exist; the actual type is substituted for each instance.
+//
+// - Each type, struct, and union definition is followed by an appropriate assignment operator.
+//
+// - Each use of a struct or union is connected to a complete definition of that struct or union, even if that
+//   definition occurs later in the input.
+
+#include <list>
+#include <iterator>
+#include "Validate.h"
+#include "SynTree/Visitor.h"
+#include "SynTree/Mutator.h"
+#include "SynTree/Type.h"
+#include "SynTree/Statement.h"
+#include "Indexer.h"
+#include "SynTree/TypeSubstitution.h"
+#include "FixFunction.h"
+#include "ImplementationType.h"
+#include "utility.h"
+#include "UniqueName.h"
+#include "AddVisit.h"
+
+
+#define debugPrint( x ) if ( doDebug ) { std::cout << x; }
+
+namespace SymTab {
+	class HoistStruct : public Visitor {
+	  public:
+		static void hoistStruct( std::list< Declaration * > &translationUnit );
+  
+		std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
+  
+		virtual void visit( StructDecl *aggregateDecl );
+		virtual void visit( UnionDecl *aggregateDecl );
+
+		virtual void visit( CompoundStmt *compoundStmt );
+		virtual void visit( IfStmt *ifStmt );
+		virtual void visit( WhileStmt *whileStmt );
+		virtual void visit( ForStmt *forStmt );
+		virtual void visit( SwitchStmt *switchStmt );
+		virtual void visit( ChooseStmt *chooseStmt );
+		virtual void visit( CaseStmt *caseStmt );
+		virtual void visit( CatchStmt *catchStmt );
+	  private:
+		HoistStruct();
+
+		template< typename AggDecl > void handleAggregate( AggDecl *aggregateDecl );
+
+		std::list< Declaration * > declsToAdd;
+		bool inStruct;
+	};
+
+	class Pass1 : public Visitor {
+		typedef Visitor Parent;
+		virtual void visit( EnumDecl *aggregateDecl );
+		virtual void visit( FunctionType *func );
+	};
+  
+	class Pass2 : public Indexer {
+		typedef Indexer Parent;
+	  public:
+		Pass2( bool doDebug, const Indexer *indexer );
+	  private:
+		virtual void visit( StructInstType *structInst );
+		virtual void visit( UnionInstType *unionInst );
+		virtual void visit( ContextInstType *contextInst );
+		virtual void visit( StructDecl *structDecl );
+		virtual void visit( UnionDecl *unionDecl );
+		virtual void visit( TypeInstType *typeInst );
+
+		const Indexer *indexer;
+  
+		typedef std::map< std::string, std::list< StructInstType * > > ForwardStructsType;
+		typedef std::map< std::string, std::list< UnionInstType * > > ForwardUnionsType;
+		ForwardStructsType forwardStructs;
+		ForwardUnionsType forwardUnions;
+	};
+
+	class Pass3 : public Indexer {
+		typedef Indexer Parent;
+	  public:
+		Pass3( const Indexer *indexer );
+	  private:
+		virtual void visit( ObjectDecl *object );
+		virtual void visit( FunctionDecl *func );
+
+		const Indexer *indexer;
+	};
+
+	class AddStructAssignment : public Visitor {
+	  public:
+		static void addStructAssignment( std::list< Declaration * > &translationUnit );
+
+		std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
+  
+		virtual void visit( StructDecl *structDecl );
+		virtual void visit( UnionDecl *structDecl );
+		virtual void visit( TypeDecl *typeDecl );
+		virtual void visit( ContextDecl *ctxDecl );
+		virtual void visit( FunctionDecl *functionDecl );
+
+		virtual void visit( FunctionType *ftype );
+		virtual void visit( PointerType *ftype );
+  
+		virtual void visit( CompoundStmt *compoundStmt );
+		virtual void visit( IfStmt *ifStmt );
+		virtual void visit( WhileStmt *whileStmt );
+		virtual void visit( ForStmt *forStmt );
+		virtual void visit( SwitchStmt *switchStmt );
+		virtual void visit( ChooseStmt *chooseStmt );
+		virtual void visit( CaseStmt *caseStmt );
+		virtual void visit( CatchStmt *catchStmt );
+
+		AddStructAssignment() : functionNesting( 0 ) {}
+	  private:
+		template< typename StmtClass > void visitStatement( StmtClass *stmt );
+  
+		std::list< Declaration * > declsToAdd;
+		std::set< std::string > structsDone;
+		unsigned int functionNesting;			// current level of nested functions
+	};
+
+	class EliminateTypedef : public Mutator {
+	  public:
+		static void eliminateTypedef( std::list< Declaration * > &translationUnit );
+	  private:
+		virtual Declaration *mutate( TypedefDecl *typeDecl );
+		virtual TypeDecl *mutate( TypeDecl *typeDecl );
+		virtual DeclarationWithType *mutate( FunctionDecl *funcDecl );
+		virtual ObjectDecl *mutate( ObjectDecl *objDecl );
+		virtual CompoundStmt *mutate( CompoundStmt *compoundStmt );
+		virtual Type *mutate( TypeInstType *aggregateUseType );
+		virtual Expression *mutate( CastExpr *castExpr );
+  
+		std::map< std::string, TypedefDecl * > typedefNames;
+	};
+
+	void validate( std::list< Declaration * > &translationUnit, bool doDebug ) {
+		Pass1 pass1;
+		Pass2 pass2( doDebug, 0 );
+		Pass3 pass3( 0 );
+		EliminateTypedef::eliminateTypedef( translationUnit );
+		HoistStruct::hoistStruct( translationUnit );
+		acceptAll( translationUnit, pass1 );
+		acceptAll( translationUnit, pass2 );
+		AddStructAssignment::addStructAssignment( translationUnit );
+		acceptAll( translationUnit, pass3 );
+	}
+	
+	void validateType( Type *type, const Indexer *indexer ) {
+		Pass1 pass1;
+		Pass2 pass2( false, indexer );
+		Pass3 pass3( indexer );
+		type->accept( pass1 );
+		type->accept( pass2 );
+		type->accept( pass3 );
+	}
+
+	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 HoistStruct::hoistStruct( std::list< Declaration * > &translationUnit ) {
+		HoistStruct hoister;
+		acceptAndAdd( translationUnit, hoister, true );
+	}
+
+	HoistStruct::HoistStruct() : inStruct( false ) {
+	}
+
+	void filter( std::list< Declaration * > &declList, bool (*pred)( Declaration * ), bool doDelete ) {
+		std::list< Declaration * >::iterator i = declList.begin();
+		while ( i != declList.end() ) {
+			std::list< Declaration * >::iterator next = i;
+			++next;
+			if ( pred( *i ) ) {
+				if ( doDelete ) {
+					delete *i;
+				} // if
+				declList.erase( i );
+			} // if
+			i = next;
+		} // while
+	}
+
+	bool isStructOrUnion( Declaration *decl ) {
+		return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl );
+	}
+
+	template< typename AggDecl >
+	void HoistStruct::handleAggregate( AggDecl *aggregateDecl ) {
+		if ( inStruct ) {
+			// Add elements in stack order corresponding to nesting structure.
+			declsToAdd.push_front( aggregateDecl );
+			Visitor::visit( aggregateDecl );
+		} else {
+			inStruct = true;
+			Visitor::visit( aggregateDecl );
+			inStruct = false;
+		} // if
+		// Always remove the hoisted aggregate from the inner structure.
+		filter( aggregateDecl->get_members(), isStructOrUnion, false );
+	}
+
+	void HoistStruct::visit( StructDecl *aggregateDecl ) {
+		handleAggregate( aggregateDecl );
+	}
+
+	void HoistStruct::visit( UnionDecl *aggregateDecl ) {
+		handleAggregate( aggregateDecl );
+	}
+
+	void HoistStruct::visit( CompoundStmt *compoundStmt ) {
+		addVisit( compoundStmt, *this );
+	}
+
+	void HoistStruct::visit( IfStmt *ifStmt ) {
+		addVisit( ifStmt, *this );
+	}
+
+	void HoistStruct::visit( WhileStmt *whileStmt ) {
+		addVisit( whileStmt, *this );
+	}
+
+	void HoistStruct::visit( ForStmt *forStmt ) {
+		addVisit( forStmt, *this );
+	}
+
+	void HoistStruct::visit( SwitchStmt *switchStmt ) {
+		addVisit( switchStmt, *this );
+	}
+
+	void HoistStruct::visit( ChooseStmt *switchStmt ) {
+		addVisit( switchStmt, *this );
+	}
+
+	void HoistStruct::visit( CaseStmt *caseStmt ) {
+		addVisit( caseStmt, *this );
+	}
+
+	void HoistStruct::visit( CatchStmt *cathStmt ) {
+		addVisit( cathStmt, *this );
+	}
+
+	void Pass1::visit( EnumDecl *enumDecl ) {
+		// Set the type of each member of the enumeration to be EnumConstant
+  
+		for ( std::list< Declaration * >::iterator i = enumDecl->get_members().begin(); i != enumDecl->get_members().end(); ++i ) {
+			ObjectDecl *obj = dynamic_cast< ObjectDecl * >( *i );
+			assert( obj );
+			obj->set_type( new EnumInstType( Type::Qualifiers( true, false, false, false, false, false ), enumDecl->get_name() ) );
+		} // for
+		Parent::visit( enumDecl );
+	}
+
+	namespace {
+		template< typename DWTIterator >
+		void fixFunctionList( DWTIterator begin, DWTIterator end, FunctionType *func ) {
+			// the only case in which "void" is valid is where it is the only one in the list; then it should be removed
+			// entirely other fix ups are handled by the FixFunction class
+			if ( begin == end ) return;
+			FixFunction fixer;
+			DWTIterator i = begin;
+			*i = (*i )->acceptMutator( fixer );
+			if ( fixer.get_isVoid() ) {
+				DWTIterator j = i;
+				++i;
+				func->get_parameters().erase( j );
+				if ( i != end ) { 
+					throw SemanticError( "invalid type void in function type ", func );
+				} // if
+			} else {
+				++i;
+				for ( ; i != end; ++i ) {
+					FixFunction fixer;
+					*i = (*i )->acceptMutator( fixer );
+					if ( fixer.get_isVoid() ) {
+						throw SemanticError( "invalid type void in function type ", func );
+					} // if
+				} // for
+			} // if
+		}
+	}
+
+	void Pass1::visit( FunctionType *func ) {
+		// Fix up parameters and return types
+		fixFunctionList( func->get_parameters().begin(), func->get_parameters().end(), func );
+		fixFunctionList( func->get_returnVals().begin(), func->get_returnVals().end(), func );
+		Visitor::visit( func );
+	}
+
+	Pass2::Pass2( bool doDebug, const Indexer *other_indexer ) : Indexer( doDebug ) {
+		if ( other_indexer ) {
+			indexer = other_indexer;
+		} else {
+			indexer = this;
+		} // if
+	}
+
+	void Pass2::visit( StructInstType *structInst ) {
+		Parent::visit( structInst );
+		StructDecl *st = indexer->lookupStruct( structInst->get_name() );
+		// it's not a semantic error if the struct is not found, just an implicit forward declaration
+		if ( st ) {
+			assert( ! structInst->get_baseStruct() || structInst->get_baseStruct()->get_members().empty() || ! st->get_members().empty() );
+			structInst->set_baseStruct( st );
+		} // if
+		if ( ! st || st->get_members().empty() ) {
+			// use of forward declaration
+			forwardStructs[ structInst->get_name() ].push_back( structInst );
+		} // if
+	}
+
+	void Pass2::visit( UnionInstType *unionInst ) {
+		Parent::visit( unionInst );
+		UnionDecl *un = indexer->lookupUnion( unionInst->get_name() );
+		// it's not a semantic error if the union is not found, just an implicit forward declaration
+		if ( un ) {
+			unionInst->set_baseUnion( un );
+		} // if
+		if ( ! un || un->get_members().empty() ) {
+			// use of forward declaration
+			forwardUnions[ unionInst->get_name() ].push_back( unionInst );
+		} // if
+	}
+
+	void Pass2::visit( ContextInstType *contextInst ) {
+		Parent::visit( contextInst );
+		ContextDecl *ctx = indexer->lookupContext( contextInst->get_name() );
+		if ( ! ctx ) {
+			throw SemanticError( "use of undeclared context " + contextInst->get_name() );
+		} // if
+		for ( std::list< TypeDecl * >::const_iterator i = ctx->get_parameters().begin(); i != ctx->get_parameters().end(); ++i ) {
+			for ( std::list< DeclarationWithType * >::const_iterator assert = (*i )->get_assertions().begin(); assert != (*i )->get_assertions().end(); ++assert ) {
+				if ( ContextInstType *otherCtx = dynamic_cast< ContextInstType * >(*assert ) ) {
+					cloneAll( otherCtx->get_members(), contextInst->get_members() );
+				} else {
+					contextInst->get_members().push_back( (*assert )->clone() );
+				} // if
+			} // for
+		} // for
+		applySubstitution( ctx->get_parameters().begin(), ctx->get_parameters().end(), contextInst->get_parameters().begin(), ctx->get_members().begin(), ctx->get_members().end(), back_inserter( contextInst->get_members() ) );
+	}
+
+	void Pass2::visit( StructDecl *structDecl ) {
+		if ( ! structDecl->get_members().empty() ) {
+			ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->get_name() );
+			if ( fwds != forwardStructs.end() ) {
+				for ( std::list< StructInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
+					(*inst )->set_baseStruct( structDecl );
+				} // for
+				forwardStructs.erase( fwds );
+			} // if
+		} // if
+		Indexer::visit( structDecl );
+	}
+
+	void Pass2::visit( UnionDecl *unionDecl ) {
+		if ( ! unionDecl->get_members().empty() ) {
+			ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->get_name() );
+			if ( fwds != forwardUnions.end() ) {
+				for ( std::list< UnionInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
+					(*inst )->set_baseUnion( unionDecl );
+				} // for
+				forwardUnions.erase( fwds );
+			} // if
+		} // if
+		Indexer::visit( unionDecl );
+	}
+
+	void Pass2::visit( TypeInstType *typeInst ) {
+		if ( NamedTypeDecl *namedTypeDecl = lookupType( typeInst->get_name() ) ) {
+			if ( TypeDecl *typeDecl = dynamic_cast< TypeDecl * >( namedTypeDecl ) ) {
+				typeInst->set_isFtype( typeDecl->get_kind() == TypeDecl::Ftype );
+			} // if
+		} // if
+	}
+
+	Pass3::Pass3( const Indexer *other_indexer ) :  Indexer( false ) {
+		if ( other_indexer ) {
+			indexer = other_indexer;
+		} else {
+			indexer = this;
+		} // if
+	}
+
+	void forallFixer( Type *func ) {
+		// Fix up assertions
+		for ( std::list< TypeDecl * >::iterator type = func->get_forall().begin(); type != func->get_forall().end(); ++type ) {
+			std::list< DeclarationWithType * > toBeDone, nextRound;
+			toBeDone.splice( toBeDone.end(), (*type )->get_assertions() );
+			while ( ! toBeDone.empty() ) {
+				for ( std::list< DeclarationWithType * >::iterator assertion = toBeDone.begin(); assertion != toBeDone.end(); ++assertion ) {
+					if ( ContextInstType *ctx = dynamic_cast< ContextInstType * >( (*assertion )->get_type() ) ) {
+						for ( std::list< Declaration * >::const_iterator i = ctx->get_members().begin(); i != ctx->get_members().end(); ++i ) {
+							DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *i );
+							assert( dwt );
+							nextRound.push_back( dwt->clone() );
+						}
+						delete ctx;
+					} else {
+						FixFunction fixer;
+						*assertion = (*assertion )->acceptMutator( fixer );
+						if ( fixer.get_isVoid() ) {
+							throw SemanticError( "invalid type void in assertion of function ", func );
+						}
+						(*type )->get_assertions().push_back( *assertion );
+					} // if
+				} // for
+				toBeDone.clear();
+				toBeDone.splice( toBeDone.end(), nextRound );
+			} // while
+		} // for
+	}
+
+	void Pass3::visit( ObjectDecl *object ) {
+		forallFixer( object->get_type() );
+		if ( PointerType *pointer = dynamic_cast< PointerType * >( object->get_type() ) ) {
+			forallFixer( pointer->get_base() );
+		} // if
+		Parent::visit( object );
+		object->fixUniqueId();
+	}
+
+	void Pass3::visit( FunctionDecl *func ) {
+		forallFixer( func->get_type() );
+		Parent::visit( func );
+		func->fixUniqueId();
+	}
+
+	static const std::list< std::string > noLabels;
+
+	void AddStructAssignment::addStructAssignment( std::list< Declaration * > &translationUnit ) {
+		AddStructAssignment visitor;
+		acceptAndAdd( translationUnit, visitor, false );
+	}
+
+	template< typename OutputIterator >
+	void makeScalarAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, OutputIterator out ) {
+		ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member );
+		// unnamed bit fields are not copied as they cannot be accessed
+		if ( obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL ) return;
+
+		UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
+  
+		UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
+		derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
+  
+		// do something special for unnamed members
+		Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
+		assignExpr->get_args().push_back( dstselect );
+  
+		Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
+		assignExpr->get_args().push_back( srcselect );
+  
+		*out++ = new ExprStmt( noLabels, assignExpr );
+	}
+
+	template< typename OutputIterator >
+	void makeArrayAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, DeclarationWithType *member, ArrayType *array, OutputIterator out ) {
+		static UniqueName indexName( "_index" );
+  
+		// for a flexible array member nothing is done -- user must define own assignment
+		if ( ! array->get_dimension() ) return;
+  
+		ObjectDecl *index = new ObjectDecl( indexName.newName(), Declaration::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 0 );
+		*out++ = new DeclStmt( noLabels, index );
+  
+		UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
+		init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
+		init->get_args().push_back( new NameExpr( "0" ) );
+		Statement *initStmt = new ExprStmt( noLabels, init );
+  
+		UntypedExpr *cond = new UntypedExpr( new NameExpr( "?<?" ) );
+		cond->get_args().push_back( new VariableExpr( index ) );
+		cond->get_args().push_back( array->get_dimension()->clone() );
+  
+		UntypedExpr *inc = new UntypedExpr( new NameExpr( "++?" ) );
+		inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
+  
+		UntypedExpr *assignExpr = new UntypedExpr( new NameExpr( "?=?" ) );
+  
+		UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
+		derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
+  
+		Expression *dstselect = new MemberExpr( member, derefExpr );
+		UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) );
+		dstIndex->get_args().push_back( dstselect );
+		dstIndex->get_args().push_back( new VariableExpr( index ) );
+		assignExpr->get_args().push_back( dstIndex );
+  
+		Expression *srcselect = new MemberExpr( member, new VariableExpr( srcParam ) );
+		UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
+		srcIndex->get_args().push_back( srcselect );
+		srcIndex->get_args().push_back( new VariableExpr( index ) );
+		assignExpr->get_args().push_back( srcIndex );
+  
+		*out++ = new ForStmt( noLabels, initStmt, cond, inc, new ExprStmt( noLabels, assignExpr ) );
+	}
+
+	Declaration *makeStructAssignment( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting ) {
+		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
+  
+		ObjectDecl *returnVal = new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
+		assignType->get_returnVals().push_back( returnVal );
+  
+		ObjectDecl *dstParam = new ObjectDecl( "_dst", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), refType->clone() ), 0 );
+		assignType->get_parameters().push_back( dstParam );
+  
+		ObjectDecl *srcParam = new ObjectDecl( "_src", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, refType, 0 );
+		assignType->get_parameters().push_back( srcParam );
+
+		// 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 *assignDecl = new FunctionDecl( "?=?", functionNesting > 0 ? Declaration::NoStorageClass : Declaration::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true );
+		assignDecl->fixUniqueId();
+  
+		for ( std::list< Declaration * >::const_iterator member = aggregateDecl->get_members().begin(); member != aggregateDecl->get_members().end(); ++member ) {
+			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member ) ) {
+				if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
+					makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
+				} else {
+					makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
+				} // if
+			} // if
+		} // for
+		assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
+  
+		return assignDecl;
+	}
+
+	Declaration *makeUnionAssignment( UnionDecl *aggregateDecl, UnionInstType *refType, unsigned int functionNesting ) {
+		FunctionType *assignType = new FunctionType( Type::Qualifiers(), false );
+  
+		ObjectDecl *returnVal = new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, refType->clone(), 0 );
+		assignType->get_returnVals().push_back( returnVal );
+  
+		ObjectDecl *dstParam = new ObjectDecl( "_dst", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), refType->clone() ), 0 );
+		assignType->get_parameters().push_back( dstParam );
+  
+		ObjectDecl *srcParam = new ObjectDecl( "_src", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, refType, 0 );
+		assignType->get_parameters().push_back( srcParam );
+  
+		// 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 *assignDecl = new FunctionDecl( "?=?",  functionNesting > 0 ? Declaration::NoStorageClass : Declaration::Static, LinkageSpec::AutoGen, assignType, new CompoundStmt( noLabels ), true );
+		assignDecl->fixUniqueId();
+  
+		UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
+		copy->get_args().push_back( new VariableExpr( dstParam ) );
+		copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
+		copy->get_args().push_back( new SizeofExpr( refType->clone() ) );
+
+		assignDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, copy ) );
+		assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
+  
+		return assignDecl;
+	}
+
+	void AddStructAssignment::visit( StructDecl *structDecl ) {
+		if ( ! structDecl->get_members().empty() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
+			StructInstType *structInst = new StructInstType( Type::Qualifiers(), structDecl->get_name() );
+			structInst->set_baseStruct( structDecl );
+			declsToAdd.push_back( makeStructAssignment( structDecl, structInst, functionNesting ) );
+			structsDone.insert( structDecl->get_name() );
+		} // if
+	}
+
+	void AddStructAssignment::visit( UnionDecl *unionDecl ) {
+		if ( ! unionDecl->get_members().empty() ) {
+			UnionInstType *unionInst = new UnionInstType( Type::Qualifiers(), unionDecl->get_name() );
+			unionInst->set_baseUnion( unionDecl );
+			declsToAdd.push_back( makeUnionAssignment( unionDecl, unionInst, functionNesting ) );
+		} // if
+	}
+
+	void AddStructAssignment::visit( TypeDecl *typeDecl ) {
+		CompoundStmt *stmts = 0;
+		TypeInstType *typeInst = new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), false );
+		typeInst->set_baseType( typeDecl );
+		ObjectDecl *src = new ObjectDecl( "_src", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, typeInst->clone(), 0 );
+		ObjectDecl *dst = new ObjectDecl( "_dst", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 );
+		if ( typeDecl->get_base() ) {
+			stmts = new CompoundStmt( std::list< Label >() );
+			UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) );
+			assign->get_args().push_back( new CastExpr( new VariableExpr( dst ), new PointerType( Type::Qualifiers(), typeDecl->get_base()->clone() ) ) );
+			assign->get_args().push_back( new CastExpr( new VariableExpr( src ), typeDecl->get_base()->clone() ) );
+			stmts->get_kids().push_back( new ReturnStmt( std::list< Label >(), assign ) );
+		} // if
+		FunctionType *type = new FunctionType( Type::Qualifiers(), false );
+		type->get_returnVals().push_back( new ObjectDecl( "", Declaration::NoStorageClass, LinkageSpec::Cforall, 0, typeInst, 0 ) );
+		type->get_parameters().push_back( dst );
+		type->get_parameters().push_back( src );
+		FunctionDecl *func = new FunctionDecl( "?=?", Declaration::NoStorageClass, LinkageSpec::AutoGen, type, stmts, false );
+		declsToAdd.push_back( func );
+	}
+
+	void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) {
+		if ( ! declsToAdd.empty() ) {
+			for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) {
+				statements.insert( i, new DeclStmt( noLabels, *decl ) );
+			} // for
+			declsToAdd.clear();
+		} // if
+	}
+
+	void AddStructAssignment::visit( FunctionType *) {
+		// ensure that we don't add assignment ops for types defined as part of the function
+	}
+
+	void AddStructAssignment::visit( PointerType *) {
+		// ensure that we don't add assignment ops for types defined as part of the pointer
+	}
+
+	void AddStructAssignment::visit( ContextDecl *) {
+		// ensure that we don't add assignment ops for types defined as part of the context
+	}
+
+	template< typename StmtClass >
+	inline void AddStructAssignment::visitStatement( StmtClass *stmt ) {
+		std::set< std::string > oldStructs = structsDone;
+		addVisit( stmt, *this );
+		structsDone = oldStructs;
+	}
+
+	void AddStructAssignment::visit( FunctionDecl *functionDecl ) {
+		maybeAccept( functionDecl->get_functionType(), *this );
+		acceptAll( functionDecl->get_oldDecls(), *this );
+		functionNesting += 1;
+		maybeAccept( functionDecl->get_statements(), *this );
+		functionNesting -= 1;
+	}
+
+	void AddStructAssignment::visit( CompoundStmt *compoundStmt ) {
+		visitStatement( compoundStmt );
+	}
+
+	void AddStructAssignment::visit( IfStmt *ifStmt ) {
+		visitStatement( ifStmt );
+	}
+
+	void AddStructAssignment::visit( WhileStmt *whileStmt ) {
+		visitStatement( whileStmt );
+	}
+
+	void AddStructAssignment::visit( ForStmt *forStmt ) {
+		visitStatement( forStmt );
+	}
+
+	void AddStructAssignment::visit( SwitchStmt *switchStmt ) {
+		visitStatement( switchStmt );
+	}
+
+	void AddStructAssignment::visit( ChooseStmt *switchStmt ) {
+		visitStatement( switchStmt );
+	}
+
+	void AddStructAssignment::visit( CaseStmt *caseStmt ) {
+		visitStatement( caseStmt );
+	}
+
+	void AddStructAssignment::visit( CatchStmt *cathStmt ) {
+		visitStatement( cathStmt );
+	}
+
+	bool isTypedef( Declaration *decl ) {
+		return dynamic_cast< TypedefDecl * >( decl );
+	}
+
+	void EliminateTypedef::eliminateTypedef( std::list< Declaration * > &translationUnit ) {
+		EliminateTypedef eliminator;
+		mutateAll( translationUnit, eliminator );
+		filter( translationUnit, isTypedef, true );
+	}
+
+	Type *EliminateTypedef::mutate( TypeInstType *typeInst ) {
+		std::map< std::string, TypedefDecl * >::const_iterator def = typedefNames.find( typeInst->get_name() );
+		if ( def != typedefNames.end() ) {
+			Type *ret = def->second->get_base()->clone();
+			ret->get_qualifiers() += typeInst->get_qualifiers();
+			delete typeInst;
+			return ret;
+		} // if
+		return typeInst;
+	}
+
+	Declaration *EliminateTypedef::mutate( TypedefDecl *tyDecl ) {
+		Declaration *ret = Mutator::mutate( tyDecl );
+		typedefNames[ tyDecl->get_name() ] = tyDecl;
+		// When a typedef is a forward declaration:
+		//    typedef struct screen SCREEN;
+		// the declaration portion must be retained:
+		//    struct screen;
+		// because the expansion of the typedef is:
+		//    void rtn( SCREEN *p ) => void rtn( struct screen *p )
+		// hence the type-name "screen" must be defined.
+		// Note, qualifiers on the typedef are superfluous for the forward declaration.
+		if ( StructInstType *aggDecl = dynamic_cast< StructInstType * >( tyDecl->get_base() ) ) {
+			return new StructDecl( aggDecl->get_name() );
+		} else if ( UnionInstType *aggDecl = dynamic_cast< UnionInstType * >( tyDecl->get_base() ) ) {
+			return new UnionDecl( aggDecl->get_name() );
+		} else {
+			return ret;
+		} // if
+	}
+
+	TypeDecl *EliminateTypedef::mutate( TypeDecl *typeDecl ) {
+		std::map< std::string, TypedefDecl * >::iterator i = typedefNames.find( typeDecl->get_name() );
+		if ( i != typedefNames.end() ) {
+			typedefNames.erase( i ) ;
+		} // if
+		return typeDecl;
+	}
+
+	DeclarationWithType *EliminateTypedef::mutate( FunctionDecl *funcDecl ) {
+		std::map< std::string, TypedefDecl * > oldNames = typedefNames;
+		DeclarationWithType *ret = Mutator::mutate( funcDecl );
+		typedefNames = oldNames;
+		return ret;
+	}
+
+	ObjectDecl *EliminateTypedef::mutate( ObjectDecl *objDecl ) {
+		std::map< std::string, TypedefDecl * > oldNames = typedefNames;
+		ObjectDecl *ret = Mutator::mutate( objDecl );
+		typedefNames = oldNames;
+		return ret;
+	}
+
+	Expression *EliminateTypedef::mutate( CastExpr *castExpr ) {
+		std::map< std::string, TypedefDecl * > oldNames = typedefNames;
+		Expression *ret = Mutator::mutate( castExpr );
+		typedefNames = oldNames;
+		return ret;
+	}
+
+	CompoundStmt *EliminateTypedef::mutate( CompoundStmt *compoundStmt ) {
+		std::map< std::string, TypedefDecl * > oldNames = typedefNames;
+		CompoundStmt *ret = Mutator::mutate( compoundStmt );
+		std::list< Statement * >::iterator i = compoundStmt->get_kids().begin();
+		while ( i != compoundStmt->get_kids().end() ) {
+			std::list< Statement * >::iterator next = i;
+			++next;
+			if ( DeclStmt *declStmt = dynamic_cast< DeclStmt * >( *i ) ) {
+				if ( dynamic_cast< TypedefDecl * >( declStmt->get_decl() ) ) {
+					delete *i;
+					compoundStmt->get_kids().erase( i );
+				} // if
+			} // if
+			i = next;
+		} // while
+		typedefNames = oldNames;
+		return ret;
+	}
+} // namespace SymTab
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/Validate.h
===================================================================
--- src/SymTab/Validate.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/Validate.h	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,35 @@
+//
+// 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.
+//
+// Validate.h -- This class is intended to perform pre-processing of declarations, validating their correctness and
+//               computing some auxilliary data that is necessary for the indexer.
+//
+// Author           : Richard C. Bilson
+// Created On       : Sun May 17 21:53:34 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue May 19 16:49:43 2015
+// Update Count     : 3
+//
+
+#ifndef VALIDATE_H
+#define VALIDATE_H
+
+#include "SynTree/SynTree.h"
+
+namespace SymTab {
+	class Indexer;
+
+	void validate( std::list< Declaration * > &translationUnit, bool doDebug = false );
+	void validateType( Type *type, const Indexer *indexer );
+} // namespace SymTab
+
+#endif // VALIDATE_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SymTab/module.mk
===================================================================
--- src/SymTab/module.mk	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
+++ src/SymTab/module.mk	(revision 843054c23fcb725d2486e5e42e91b3741bc523b8)
@@ -0,0 +1,7 @@
+SRC += SymTab/IdTable.cc \
+       SymTab/Indexer.cc \
+       SymTab/Mangler.cc \
+       SymTab/Validate.cc \
+       SymTab/FixFunction.cc \
+       SymTab/ImplementationType.cc
+
