Index: src/SymTab/TypeEquality.cc
===================================================================
--- src/SymTab/TypeEquality.cc	(revision cff1143e2baa13d1597cb90a47cb8f47aa3cc8db)
+++ src/SymTab/TypeEquality.cc	(revision cff1143e2baa13d1597cb90a47cb8f47aa3cc8db)
@@ -0,0 +1,193 @@
+//
+// 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.
+//
+// TypeEquality.cc -- 
+//
+// Author           : Rob Schluntz
+// Created On       : Tue Jul 07 16:28:29 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Thu Jul 09 11:18:46 2015
+// Update Count     : 36
+//
+
+#include <list>
+#include <iterator>
+#include "Validate.h"
+#include "SynTree/Visitor.h"
+#include "SynTree/Type.h"
+#include "SynTree/Statement.h"
+#include "SynTree/TypeSubstitution.h"
+#include "Indexer.h"
+#include "TypeEquality.h"
+
+namespace SymTab {
+	class TypeEquality : public Visitor {
+  public:
+		TypeEquality( Type * other, bool vlaErr ) : result( true ), other( other ), 
+			vlaErr( vlaErr ) {}
+		bool result;
+
+  private:
+		virtual void visit( FunctionType *funcType );
+		virtual void visit( VoidType *voidType );
+		virtual void visit( BasicType *basicType );
+		virtual void visit( PointerType *pointerType );
+		virtual void visit( ArrayType *arrayType );
+		virtual void visit( StructInstType *structInst );
+		virtual void visit( UnionInstType *unionInst );
+		virtual void visit( EnumInstType *enumInst );
+		virtual void visit( TypeInstType *typeInst );
+
+		void handleQualifiers( Type * t );
+
+		Type * other;
+		bool vlaErr;
+	};
+
+	bool typeEquals( Type * t1, Type * t2, bool vlaErr ) {
+		TypeEquality teq( t2, vlaErr );
+		t1->accept( teq );
+		return teq.result;
+	}
+
+	void TypeEquality::handleQualifiers( Type * t ) {
+		result = result && t->get_qualifiers() == other->get_qualifiers();
+	}
+
+	void TypeEquality::visit( VoidType *voidType ) {
+		handleQualifiers( voidType );
+		if ( ! dynamic_cast< VoidType * >( other ) ) {
+			result = false;
+		}
+	}
+
+	void TypeEquality::visit( BasicType *basicType ) {
+		handleQualifiers( basicType );
+		if ( BasicType * bt = dynamic_cast< BasicType * >( other ) ) {
+			result = result && basicType->get_kind() == bt->get_kind(); 
+		} else {
+			result = false;
+		}
+	}
+
+	void TypeEquality::visit( PointerType *pointerType ) {
+		handleQualifiers( pointerType );
+		if ( PointerType * pt = dynamic_cast< PointerType * >( other ) ) {
+			other = pt->get_base();
+			pointerType->get_base()->accept( *this );
+		} else {
+			result = false;
+		}
+	}
+
+	void TypeEquality::visit( ArrayType *arrayType ) {
+		handleQualifiers( arrayType );
+
+		if ( ArrayType * at = dynamic_cast< ArrayType * >( other ) ) {
+			// to be equal, array types must both be VLA or both not VLA
+			// and must both have a dimension expression or not have a dimension
+			result = result	&& arrayType->get_isVarLen() == at->get_isVarLen()
+				&& (arrayType->get_dimension() != 0 && at->get_dimension() != 0
+					|| arrayType->get_dimension() == 0 && at->get_dimension() == 0);
+
+			if ( vlaErr ) {
+				// useful for comparing typedef types - in this case, we 
+				// want types to appear distinct if either is a VLA type
+				if ( arrayType->get_isVarLen() || at->get_isVarLen() ) {
+					result = false;
+				}
+			}
+
+			if ( ! arrayType->get_isVarLen() && ! at->get_isVarLen() &&
+				arrayType->get_dimension() != 0 && at->get_dimension() != 0 ) {
+				ConstantExpr * ce1 = dynamic_cast< ConstantExpr * >( arrayType->get_dimension() );
+				ConstantExpr * ce2 = dynamic_cast< ConstantExpr * >( at->get_dimension() );
+				assert(ce1 && ce2);
+
+				Constant * c1 = ce1->get_constant();
+				Constant * c2 = ce2->get_constant();
+
+				result = result && c1->get_value() == c2->get_value();
+			}
+
+			other = at->get_base();
+			arrayType->get_base()->accept( *this );
+		} else {
+			result = false;
+		}
+	}
+
+	void TypeEquality::visit( FunctionType *funcType ) {
+		handleQualifiers( funcType );
+
+		if ( FunctionType * ft = dynamic_cast< FunctionType * >( other ) ) {
+			// function types must have the same number of return types
+			// and parameters to be equivalent
+			result = result && funcType->get_returnVals().size() == ft->get_returnVals().size()
+				&& funcType->get_parameters().size() == ft->get_parameters().size()
+				&& funcType->get_isVarArgs() == ft->get_isVarArgs();
+
+			std::list< DeclarationWithType * >::iterator it1, it2;
+
+			// return types must be equivalent
+			it1 = funcType->get_returnVals().begin();
+			it2 = ft->get_returnVals().begin();
+			for ( ; it1 != funcType->get_returnVals().end(); ++it1, ++it2 ) {
+				if ( ! result ) return;
+				other = (*it2)->get_type();
+				(*it1)->get_type()->accept( *this );
+			}
+
+			// parameter types must be equivalent
+			it1 = funcType->get_parameters().begin(); 
+			it2 = ft->get_parameters().begin();
+			for ( ; it1 != funcType->get_parameters().end(); ++it1, ++it2 ) {
+				if ( ! result ) return;
+				other = (*it2)->get_type();
+				(*it1)->get_type()->accept( *this );
+			}
+		} else {
+			result = false;
+		}
+	}
+
+	// aggregate types only need to have the same name
+	void TypeEquality::visit( StructInstType *structInst )  {
+		handleQualifiers( structInst );
+		if ( StructInstType * st = dynamic_cast< StructInstType * >( other ) ) {
+			result = result && structInst->get_name() == st->get_name();
+		} else {
+			result = false;
+		}
+	}
+
+	void TypeEquality::visit( UnionInstType *unionInst ) {
+		handleQualifiers( unionInst );
+		if ( UnionInstType * ut = dynamic_cast< UnionInstType * >( other ) ) {
+			result = result && unionInst->get_name() == ut->get_name();
+		} else {
+			result = false;
+		}
+	}
+
+	void TypeEquality::visit( EnumInstType *enumInst ) {
+		handleQualifiers( enumInst );
+		if ( EnumInstType * et = dynamic_cast< EnumInstType * >( other ) ) {
+			result = result && enumInst->get_name() == et->get_name();
+		} else {
+			result = false;
+		}
+	}
+
+	void TypeEquality::visit( TypeInstType *typeInst ) {
+		handleQualifiers( typeInst );
+		if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( other ) ) {
+			result = result && typeInst->get_name() == tt->get_name();
+		} else {
+			result = false;
+		}
+	}
+} // namespace SymTab
Index: src/SymTab/TypeEquality.h
===================================================================
--- src/SymTab/TypeEquality.h	(revision cff1143e2baa13d1597cb90a47cb8f47aa3cc8db)
+++ src/SymTab/TypeEquality.h	(revision cff1143e2baa13d1597cb90a47cb8f47aa3cc8db)
@@ -0,0 +1,21 @@
+//
+// 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.
+//
+// TypeEquality.h -- 
+//
+// Author           : Rob Schluntz
+// Created On       : Tue Jul 07 16:30:07 2015
+// Last Modified By : Rob Schluntz
+// Last Modified On : Wed Jul 08 12:41:15 2015
+// Update Count     : 6
+//
+
+namespace SymTab {
+  // compare types t1 and t2 for equality
+  // if vlaErr is true, then if at least one of the types is a 
+  // variable-length array type, then the result will be false 
+  bool typeEquals( Type * t1, Type * t2, bool vlaErr = false );
+} // namespace SymTab
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 82dd287be3d478bfc671d7f0679e11c94f8b8500)
+++ src/SymTab/Validate.cc	(revision cff1143e2baa13d1597cb90a47cb8f47aa3cc8db)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 21:50:04 2015
 // Last Modified By : Rob Schluntz
-// Last Modified On : Tue Jul 07 10:41:23 2015
-// Update Count     : 136
+// Last Modified On : Wed Jul 08 12:49:36 2015
+// Update Count     : 166
 //
 
@@ -48,10 +48,10 @@
 #include "Indexer.h"
 #include "FixFunction.h"
-#include "ImplementationType.h"
+// #include "ImplementationType.h"
 #include "utility.h"
 #include "UniqueName.h"
 #include "AddVisit.h"
 #include "MakeLibCfa.h"
-
+#include "TypeEquality.h"
 
 #define debugPrint( x ) if ( doDebug ) { std::cout << x; }
@@ -162,4 +162,5 @@
 	class EliminateTypedef : public Mutator {
 	  public:
+	  EliminateTypedef() : scopeLevel( 0 ) {}
 		static void eliminateTypedef( std::list< Declaration * > &translationUnit );
 	  private:
@@ -171,6 +172,8 @@
 		virtual Type *mutate( TypeInstType *aggregateUseType );
 		virtual Expression *mutate( CastExpr *castExpr );
-  
-		std::map< std::string, TypedefDecl * > typedefNames;
+
+		typedef std::map< std::string, std::pair< TypedefDecl *, int > > TypedefMap;
+		TypedefMap typedefNames;
+		int scopeLevel;
 	};
 
@@ -589,4 +592,7 @@
 		assignDecl2->fixUniqueId();
 
+		// these should be built in the same way that the prelude
+		// functions are, so build a list containing the prototypes
+		// and allow MakeLibCfa to autogenerate the bodies.
 		std::list< Declaration * > assigns;
 		assigns.push_back( assignDecl );
@@ -595,5 +601,5 @@
 		LibCfa::makeLibCfa( assigns );
 
-		// need to remove the prototypes, since these can appear nested in a routine
+		// need to remove the prototypes, since this may be nested in a routine
 		for (int start = 0, end = assigns.size()/2; start < end; start++) {
 			delete assigns.front();
@@ -602,6 +608,4 @@
 
 		declsToAdd.insert( declsToAdd.begin(), assigns.begin(), assigns.end() );
-
-		// return assignDecl;
 	}
 
@@ -802,7 +806,9 @@
 
 	Type *EliminateTypedef::mutate( TypeInstType *typeInst ) {
-		std::map< std::string, TypedefDecl * >::const_iterator def = typedefNames.find( typeInst->get_name() );
+		// instances of typedef types will come here. If it is an instance 
+		// of a typdef type, link the instance to its actual type.
+		TypedefMap::const_iterator def = typedefNames.find( typeInst->get_name() );
 		if ( def != typedefNames.end() ) {
-			Type *ret = def->second->get_base()->clone();
+			Type *ret = def->second.first->get_base()->clone();
 			ret->get_qualifiers() += typeInst->get_qualifiers();
 			delete typeInst;
@@ -814,5 +820,17 @@
 	Declaration *EliminateTypedef::mutate( TypedefDecl *tyDecl ) {
 		Declaration *ret = Mutator::mutate( tyDecl );
-		typedefNames[ tyDecl->get_name() ] = tyDecl;
+		if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
+			// typedef to the same name from the same scope 
+			// must be from the same type
+
+			Type * t1 = tyDecl->get_base();
+			Type * t2 = typedefNames[ tyDecl->get_name() ].first->get_base();
+			if ( ! typeEquals( t1, t2, true ) ) {
+				throw SemanticError( "cannot redefine typedef: " + tyDecl->get_name() );
+			} 
+		} else {
+			typedefNames[ tyDecl->get_name() ] = std::make_pair( tyDecl, scopeLevel );
+		} // if
+
 		// When a typedef is a forward declaration:
 		//    typedef struct screen SCREEN;
@@ -833,5 +851,5 @@
 
 	TypeDecl *EliminateTypedef::mutate( TypeDecl *typeDecl ) {
-		std::map< std::string, TypedefDecl * >::iterator i = typedefNames.find( typeDecl->get_name() );
+		TypedefMap::iterator i = typedefNames.find( typeDecl->get_name() );
 		if ( i != typedefNames.end() ) {
 			typedefNames.erase( i ) ;
@@ -841,5 +859,5 @@
 
 	DeclarationWithType *EliminateTypedef::mutate( FunctionDecl *funcDecl ) {
-		std::map< std::string, TypedefDecl * > oldNames = typedefNames;
+		TypedefMap oldNames = typedefNames;
 		DeclarationWithType *ret = Mutator::mutate( funcDecl );
 		typedefNames = oldNames;
@@ -848,5 +866,5 @@
 
 	ObjectDecl *EliminateTypedef::mutate( ObjectDecl *objDecl ) {
-		std::map< std::string, TypedefDecl * > oldNames = typedefNames;
+		TypedefMap oldNames = typedefNames;
 		ObjectDecl *ret = Mutator::mutate( objDecl );
 		typedefNames = oldNames;
@@ -855,5 +873,5 @@
 
 	Expression *EliminateTypedef::mutate( CastExpr *castExpr ) {
-		std::map< std::string, TypedefDecl * > oldNames = typedefNames;
+		TypedefMap oldNames = typedefNames;
 		Expression *ret = Mutator::mutate( castExpr );
 		typedefNames = oldNames;
@@ -862,6 +880,8 @@
 
 	CompoundStmt *EliminateTypedef::mutate( CompoundStmt *compoundStmt ) {
-		std::map< std::string, TypedefDecl * > oldNames = typedefNames;
+		TypedefMap oldNames = typedefNames;
+		scopeLevel += 1;
 		CompoundStmt *ret = Mutator::mutate( compoundStmt );
+		scopeLevel -= 1;
 		std::list< Statement * >::iterator i = compoundStmt->get_kids().begin();
 		while ( i != compoundStmt->get_kids().end() ) {
Index: src/SymTab/module.mk
===================================================================
--- src/SymTab/module.mk	(revision 82dd287be3d478bfc671d7f0679e11c94f8b8500)
+++ src/SymTab/module.mk	(revision cff1143e2baa13d1597cb90a47cb8f47aa3cc8db)
@@ -10,7 +10,7 @@
 ## Author           : Richard C. Bilson
 ## Created On       : Mon Jun  1 17:49:17 2015
-## Last Modified By : Peter A. Buhr
-## Last Modified On : Mon Jun  1 17:53:50 2015
-## Update Count     : 1
+## Last Modified By : Rob Schluntz
+## Last Modified On : Tue Jul 07 16:22:23 2015
+## Update Count     : 2
 ###############################################################################
 
@@ -20,4 +20,4 @@
        SymTab/Validate.cc \
        SymTab/FixFunction.cc \
-       SymTab/ImplementationType.cc
-
+       SymTab/ImplementationType.cc \
+       SymTab/TypeEquality.cc
