Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision 98a82908d5b46fe37f82d8e30dd8d3f93d1ca285)
+++ src/SymTab/Mangler.cc	(revision 1867c96d7df869c1fc1c021525251dcd1ccf2386)
@@ -32,11 +32,13 @@
 #include "SynTree/Type.h"                // for Type, ReferenceToType, Type::Fora...
 
+#include "AST/Pass.hpp"
+
 namespace SymTab {
 	namespace Mangler {
 		namespace {
 			/// Mangles names to a unique C identifier
-			struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler>, public WithGuards {
-				Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
-				Mangler( const Mangler & ) = delete;
+			struct Mangler_old : public WithShortCircuiting, public WithVisitorRef<Mangler_old>, public WithGuards {
+				Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
+				Mangler_old( const Mangler_old & ) = delete;
 
 				void previsit( BaseSyntaxNode * ) { visit_children = false; }
@@ -77,5 +79,5 @@
 
 			  public:
-				Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 
+				Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 
 					int nextVarNum, const VarMapType& varNums );
 
@@ -85,9 +87,9 @@
 
 				void printQualifiers( Type *type );
-			}; // Mangler
+			}; // Mangler_old
 		} // namespace
 
 		std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
-			PassVisitor<Mangler> mangler( mangleOverridable, typeMode, mangleGenericParams );
+			PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams );
 			maybeAccept( decl, mangler );
 			return mangler.pass.get_mangleName();
@@ -95,5 +97,5 @@
 
 		std::string mangleType( Type * ty ) {
-			PassVisitor<Mangler> mangler( false, true, true );
+			PassVisitor<Mangler_old> mangler( false, true, true );
 			maybeAccept( ty, mangler );
 			return mangler.pass.get_mangleName();
@@ -101,5 +103,5 @@
 
 		std::string mangleConcrete( Type * ty ) {
-			PassVisitor<Mangler> mangler( false, false, false );
+			PassVisitor<Mangler_old> mangler( false, false, false );
 			maybeAccept( ty, mangler );
 			return mangler.pass.get_mangleName();
@@ -107,10 +109,10 @@
 
 		namespace {
-			Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
+			Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
 				: nextVarNum( 0 ), isTopLevel( true ), 
 				mangleOverridable( mangleOverridable ), typeMode( typeMode ), 
 				mangleGenericParams( mangleGenericParams ) {}
 			
-			Mangler::Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 
+			Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 
 				int nextVarNum, const VarMapType& varNums )
 				: varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), 
@@ -118,5 +120,5 @@
 				mangleGenericParams( mangleGenericParams ) {}
 
-			void Mangler::mangleDecl( DeclarationWithType * declaration ) {
+			void Mangler_old::mangleDecl( DeclarationWithType * declaration ) {
 				bool wasTopLevel = isTopLevel;
 				if ( isTopLevel ) {
@@ -148,18 +150,18 @@
 			}
 
-			void Mangler::postvisit( ObjectDecl * declaration ) {
+			void Mangler_old::postvisit( ObjectDecl * declaration ) {
 				mangleDecl( declaration );
 			}
 
-			void Mangler::postvisit( FunctionDecl * declaration ) {
+			void Mangler_old::postvisit( FunctionDecl * declaration ) {
 				mangleDecl( declaration );
 			}
 
-			void Mangler::postvisit( VoidType * voidType ) {
+			void Mangler_old::postvisit( VoidType * voidType ) {
 				printQualifiers( voidType );
 				mangleName << Encoding::void_t;
 			}
 
-			void Mangler::postvisit( BasicType * basicType ) {
+			void Mangler_old::postvisit( BasicType * basicType ) {
 				printQualifiers( basicType );
 				assertf( basicType->get_kind() < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->get_kind() );
@@ -167,5 +169,5 @@
 			}
 
-			void Mangler::postvisit( PointerType * pointerType ) {
+			void Mangler_old::postvisit( PointerType * pointerType ) {
 				printQualifiers( pointerType );
 				// mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
@@ -174,5 +176,5 @@
 			}
 
-			void Mangler::postvisit( ArrayType * arrayType ) {
+			void Mangler_old::postvisit( ArrayType * arrayType ) {
 				// TODO: encode dimension
 				printQualifiers( arrayType );
@@ -181,5 +183,5 @@
 			}
 
-			void Mangler::postvisit( ReferenceType * refType ) {
+			void Mangler_old::postvisit( ReferenceType * refType ) {
 				// don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
 				// Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
@@ -200,5 +202,5 @@
 			}
 
-			void Mangler::postvisit( FunctionType * functionType ) {
+			void Mangler_old::postvisit( FunctionType * functionType ) {
 				printQualifiers( functionType );
 				mangleName << Encoding::function;
@@ -217,5 +219,5 @@
 			}
 
-			void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) {
+			void Mangler_old::mangleRef( ReferenceToType * refType, std::string prefix ) {
 				printQualifiers( refType );
 
@@ -236,17 +238,17 @@
 			}
 
-			void Mangler::postvisit( StructInstType * aggregateUseType ) {
+			void Mangler_old::postvisit( StructInstType * aggregateUseType ) {
 				mangleRef( aggregateUseType, Encoding::struct_t );
 			}
 
-			void Mangler::postvisit( UnionInstType * aggregateUseType ) {
+			void Mangler_old::postvisit( UnionInstType * aggregateUseType ) {
 				mangleRef( aggregateUseType, Encoding::union_t );
 			}
 
-			void Mangler::postvisit( EnumInstType * aggregateUseType ) {
+			void Mangler_old::postvisit( EnumInstType * aggregateUseType ) {
 				mangleRef( aggregateUseType, Encoding::enum_t );
 			}
 
-			void Mangler::postvisit( TypeInstType * typeInst ) {
+			void Mangler_old::postvisit( TypeInstType * typeInst ) {
 				VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
 				if ( varNum == varNums.end() ) {
@@ -264,10 +266,10 @@
 			}
 
-			void Mangler::postvisit( TraitInstType * inst ) {
+			void Mangler_old::postvisit( TraitInstType * inst ) {
 				printQualifiers( inst );
 				mangleName << inst->name.size() << inst->name;
 			}
 
-			void Mangler::postvisit( TupleType * tupleType ) {
+			void Mangler_old::postvisit( TupleType * tupleType ) {
 				printQualifiers( tupleType );
 				mangleName << Encoding::tuple << tupleType->types.size();
@@ -275,5 +277,5 @@
 			}
 
-			void Mangler::postvisit( VarArgsType * varArgsType ) {
+			void Mangler_old::postvisit( VarArgsType * varArgsType ) {
 				printQualifiers( varArgsType );
 				static const std::string vargs = "__builtin_va_list";
@@ -281,13 +283,13 @@
 			}
 
-			void Mangler::postvisit( ZeroType * ) {
+			void Mangler_old::postvisit( ZeroType * ) {
 				mangleName << Encoding::zero;
 			}
 
-			void Mangler::postvisit( OneType * ) {
+			void Mangler_old::postvisit( OneType * ) {
 				mangleName << Encoding::one;
 			}
 
-			void Mangler::postvisit( QualifiedType * qualType ) {
+			void Mangler_old::postvisit( QualifiedType * qualType ) {
 				bool inqual = inQualifiedType;
 				if (! inqual ) {
@@ -305,5 +307,5 @@
 			}
 
-			void Mangler::postvisit( TypeDecl * decl ) {
+			void Mangler_old::postvisit( TypeDecl * decl ) {
 				// TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
 				// fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
@@ -311,5 +313,5 @@
 				// and the case has not yet come up in practice. Alternatively, if not then this code can be removed
 				// aside from the assert false.
-				assertf(false, "Mangler should not visit typedecl: %s", toCString(decl));
+				assertf(false, "Mangler_old should not visit typedecl: %s", toCString(decl));
 				assertf( decl->get_kind() < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->get_kind() );
 				mangleName << Encoding::typeVariables[ decl->get_kind() ] << ( decl->name.length() ) << decl->name;
@@ -322,5 +324,5 @@
 			}
 
-			void Mangler::printQualifiers( Type * type ) {
+			void Mangler_old::printQualifiers( Type * type ) {
 				// skip if not including qualifiers
 				if ( typeMode ) return;
@@ -345,5 +347,5 @@
 						varNums[ (*i)->name ] = std::make_pair( nextVarNum, (int)(*i)->get_kind() );
 						for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) {
-							PassVisitor<Mangler> sub_mangler( 
+							PassVisitor<Mangler_old> sub_mangler( 
 								mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
 							(*assert)->accept( sub_mangler );
@@ -391,9 +393,350 @@
 
 namespace Mangle {
+	namespace {
+		/// Mangles names to a unique C identifier
+		struct Mangler_new : public ast::WithShortCircuiting, public ast::WithVisitorRef<Mangler_new>, public ast::WithGuards {
+			Mangler_new( Mangle::Mode mode );
+			Mangler_new( const Mangler_new & ) = delete;
+
+			void previsit( ast::Node * ) { visit_children = false; }
+
+			void postvisit( ast::ObjectDecl * declaration );
+			void postvisit( ast::FunctionDecl * declaration );
+			void postvisit( ast::TypeDecl * declaration );
+
+			void postvisit( ast::VoidType * voidType );
+			void postvisit( ast::BasicType * basicType );
+			void postvisit( ast::PointerType * pointerType );
+			void postvisit( ast::ArrayType * arrayType );
+			void postvisit( ast::ReferenceType * refType );
+			void postvisit( ast::FunctionType * functionType );
+			void postvisit( ast::StructInstType * aggregateUseType );
+			void postvisit( ast::UnionInstType * aggregateUseType );
+			void postvisit( ast::EnumInstType * aggregateUseType );
+			void postvisit( ast::TypeInstType * aggregateUseType );
+			void postvisit( ast::TraitInstType * inst );
+			void postvisit( ast::TupleType * tupleType );
+			void postvisit( ast::VarArgsType * varArgsType );
+			void postvisit( ast::ZeroType * zeroType );
+			void postvisit( ast::OneType * oneType );
+			void postvisit( ast::QualifiedType * qualType );
+
+			std::string get_mangleName() { return mangleName.str(); }
+		  private:
+			std::ostringstream mangleName;  ///< Mangled name being constructed
+			typedef std::map< std::string, std::pair< int, int > > VarMapType;
+			VarMapType varNums;             ///< Map of type variables to indices
+			int nextVarNum;                 ///< Next type variable index
+			bool isTopLevel;                ///< Is the Mangler at the top level
+			bool mangleOverridable;         ///< Specially mangle overridable built-in methods
+			bool typeMode;                  ///< Produce a unique mangled name for a type
+			bool mangleGenericParams;       ///< Include generic parameters in name mangling if true
+			bool inFunctionType = false;    ///< Include type qualifiers if false.
+			bool inQualifiedType = false;   ///< Add start/end delimiters around qualified type
+
+		  private:
+			Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,  
+				int nextVarNum, const VarMapType& varNums );
+			friend class ast::Pass<Mangler_new>;
+
+		  private:
+			void mangleDecl( ast::DeclWithType *declaration );
+			void mangleRef( ast::ReferenceToType *refType, std::string prefix );
+
+			void printQualifiers( ast::Type *type );
+		}; // Mangler_new
+	} // namespace
+
+
 	std::string mangle( const ast::Node * decl, Mangle::Mode mode ) {
-		#warning unimplemented
-		assert( decl && mode.val && false );
-		return "";
+		ast::Pass<Mangler_new> mangler( mode );
+		maybeAccept( decl, mangler );
+		return mangler.pass.get_mangleName();
 	}
+
+	namespace {
+		Mangler_new::Mangler_new( Mangle::Mode mode )
+			: nextVarNum( 0 ), isTopLevel( true ), 
+			mangleOverridable  ( ! mode.no_overrideable   ),
+			typeMode           (   mode.type              ), 
+			mangleGenericParams( ! mode.no_generic_params ) {}
+		
+		Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 
+			int nextVarNum, const VarMapType& varNums )
+			: varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), 
+			mangleOverridable( mangleOverridable ), typeMode( typeMode ), 
+			mangleGenericParams( mangleGenericParams ) {}
+
+		void Mangler_new::mangleDecl( ast::DeclWithType * decl ) {
+			bool wasTopLevel = isTopLevel;
+			if ( isTopLevel ) {
+				varNums.clear();
+				nextVarNum = 0;
+				isTopLevel = false;
+			} // if
+			mangleName << Encoding::manglePrefix;
+			CodeGen::OperatorInfo opInfo;
+			if ( operatorLookup( decl->name, opInfo ) ) {
+				mangleName << opInfo.outputName.size() << opInfo.outputName;
+			} else {
+				mangleName << decl->name.size() << decl->name;
+			} // if
+			maybeAccept( decl->get_type(), *visitor );
+			if ( mangleOverridable && decl->linkage.is_overrideable ) {
+				// want to be able to override autogenerated and intrinsic routines,
+				// so they need a different name mangling
+				if ( decl->linkage == ast::Linkage::AutoGen ) {
+					mangleName << Encoding::autogen;
+				} else if ( decl->linkage == ast::Linkage::Intrinsic ) {
+					mangleName << Encoding::intrinsic;
+				} else {
+					// if we add another kind of overridable function, this has to change
+					assert( false && "unknown overrideable linkage" );
+				} // if
+			}
+			isTopLevel = wasTopLevel;
+		}
+
+		void Mangler_new::postvisit( ast::ObjectDecl * decl ) {
+			mangleDecl( decl );
+		}
+
+		void Mangler_new::postvisit( ast::FunctionDecl * decl ) {
+			mangleDecl( decl );
+		}
+
+		void Mangler_new::postvisit( ast::VoidType * voidType ) {
+			printQualifiers( voidType );
+			mangleName << Encoding::void_t;
+		}
+
+		void Mangler_new::postvisit( ast::BasicType * basicType ) {
+			printQualifiers( basicType );
+			assertf( basicType->kind < ast::BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
+			mangleName << Encoding::basicTypes[ basicType->kind ];
+		}
+
+		void Mangler_new::postvisit( ast::PointerType * pointerType ) {
+			printQualifiers( pointerType );
+			// mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
+			if ( ! pointerType->base.as<ast::FunctionType>() ) mangleName << Encoding::pointer;
+			maybe_accept( pointerType->base.get(), *visitor );
+		}
+
+		void Mangler_new::postvisit( ast::ArrayType * arrayType ) {
+			// TODO: encode dimension
+			printQualifiers( arrayType );
+			mangleName << Encoding::array << "0";
+			maybeAccept( arrayType->base.get(), *visitor );
+		}
+
+		void Mangler_new::postvisit( ast::ReferenceType * refType ) {
+			// don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
+			// Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
+			// by pretending every reference type is a function parameter.
+			GuardValue( inFunctionType );
+			inFunctionType = true;
+			printQualifiers( refType );
+			maybeAccept( refType->base.get(), *visitor );
+		}
+
+		namespace {
+			inline std::vector< ast::ptr< ast::Type > > getTypes( const std::vector< ast::ptr< ast::DeclWithType > > & decls ) {
+				std::vector< ast::ptr< ast::Type > > ret;
+				std::transform( decls.begin(), decls.end(), std::back_inserter( ret ),
+								std::mem_fun( &ast::DeclWithType::get_type ) );
+				return ret;
+			}
+		}
+
+		void Mangler_new::postvisit( ast::FunctionType * functionType ) {
+			printQualifiers( functionType );
+			mangleName << Encoding::function;
+			// turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
+			// since qualifiers on outermost parameter type do not differentiate function types, e.g.,
+			// void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different
+			GuardValue( inFunctionType );
+			inFunctionType = true;
+			std::vector< ast::ptr< ast::Type > > returnTypes = getTypes( functionType->returns );
+			if (returnTypes.empty()) mangleName << Encoding::void_t;
+			else acceptAll( returnTypes, *visitor );
+			mangleName << "_";
+			std::vector< ast::ptr< ast::Type > > paramTypes = getTypes( functionType->params );
+			acceptAll( paramTypes, *visitor );
+			mangleName << "_";
+		}
+
+		void Mangler_new::mangleRef( ast::ReferenceToType * refType, std::string prefix ) {
+			printQualifiers( refType );
+
+			mangleName << prefix << refType->name.length() << refType->name;
+
+			if ( mangleGenericParams ) {
+				std::vector< ast::ptr< ast::Expr > >& params = refType->params;
+				if ( ! params.empty() ) {
+					mangleName << "_";
+					for ( std::vector< ast::ptr< ast::Expr > >::const_iterator param = params.begin(); param != params.end(); ++param ) {
+						const ast::TypeExpr *paramType = param->as< ast::TypeExpr >();
+						assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(*param));
+						maybeAccept( paramType->type.get(), *visitor );
+					}
+					mangleName << "_";
+				}
+			}
+		}
+
+		void Mangler_new::postvisit( ast::StructInstType * aggregateUseType ) {
+			mangleRef( aggregateUseType, Encoding::struct_t );
+		}
+
+		void Mangler_new::postvisit( ast::UnionInstType * aggregateUseType ) {
+			mangleRef( aggregateUseType, Encoding::union_t );
+		}
+
+		void Mangler_new::postvisit( ast::EnumInstType * aggregateUseType ) {
+			mangleRef( aggregateUseType, Encoding::enum_t );
+		}
+
+		void Mangler_new::postvisit( ast::TypeInstType * typeInst ) {
+			VarMapType::iterator varNum = varNums.find( typeInst->name );
+			if ( varNum == varNums.end() ) {
+				mangleRef( typeInst, Encoding::type );
+			} else {
+				printQualifiers( typeInst );
+				// Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g.
+				//   forall(dtype T) void f(T);
+				//   forall(dtype S) void f(S);
+				// are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they
+				// are first found and prefixing with the appropriate encoding for the type class.
+				assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
+				mangleName << Encoding::typeVariables[varNum->second.second] << varNum->second.first;
+			} // if
+		}
+
+		void Mangler_new::postvisit( ast::TraitInstType * inst ) {
+			printQualifiers( inst );
+			mangleName << inst->name.size() << inst->name;
+		}
+
+		void Mangler_new::postvisit( ast::TupleType * tupleType ) {
+			printQualifiers( tupleType );
+			mangleName << Encoding::tuple << tupleType->types.size();
+			acceptAll( tupleType->types, *visitor );
+		}
+
+		void Mangler_new::postvisit( ast::VarArgsType * varArgsType ) {
+			printQualifiers( varArgsType );
+			static const std::string vargs = "__builtin_va_list";
+			mangleName << Encoding::type << vargs.size() << vargs;
+		}
+
+		void Mangler_new::postvisit( ast::ZeroType * ) {
+			mangleName << Encoding::zero;
+		}
+
+		void Mangler_new::postvisit( ast::OneType * ) {
+			mangleName << Encoding::one;
+		}
+
+		void Mangler_new::postvisit( ast::QualifiedType * qualType ) {
+			bool inqual = inQualifiedType;
+			if (! inqual ) {
+				// N marks the start of a qualified type
+				inQualifiedType = true;
+				mangleName << Encoding::qualifiedTypeStart;
+			}
+			maybeAccept( qualType->parent.get(), *visitor );
+			maybeAccept( qualType->child.get(), *visitor );
+			if ( ! inqual ) {
+				// E marks the end of a qualified type
+				inQualifiedType = false;
+				mangleName << Encoding::qualifiedTypeEnd;
+			}
+		}
+
+		void Mangler_new::postvisit( ast::TypeDecl * decl ) {
+			// TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
+			// fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
+			// Note: The current scheme may already work correctly for this case, I have not thought about this deeply
+			// and the case has not yet come up in practice. Alternatively, if not then this code can be removed
+			// aside from the assert false.
+			assertf(false, "Mangler_new should not visit typedecl: %s", toCString(decl));
+			assertf( decl->kind < ast::TypeVar::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
+			mangleName << Encoding::typeVariables[ decl->kind ] << ( decl->name.length() ) << decl->name;
+		}
+
+		__attribute__((unused)) 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_new::printQualifiers( ast::Type * type ) {
+			// skip if not including qualifiers
+			if ( typeMode ) return;
+			if ( ast::ParameterizedType * ptype = dynamic_cast< ast::ParameterizedType * >(type) ) {
+				if ( ! ptype->forall.empty() ) {
+					std::list< std::string > assertionNames;
+					int dcount = 0, fcount = 0, vcount = 0, acount = 0;
+					mangleName << Encoding::forall;
+					for ( ast::ParameterizedType::ForallList::iterator i = ptype->forall.begin(); i != ptype->forall.end(); ++i ) {
+						switch ( (*i)->kind ) {
+							case ast::TypeVar::Kind::Dtype:
+							dcount++;
+							break;
+							case ast::TypeVar::Kind::Ftype:
+							fcount++;
+							break;
+							case ast::TypeVar::Kind::Ttype:
+							vcount++;
+							break;
+							default:
+							assert( false );
+						} // switch
+						varNums[ (*i)->name ] = std::make_pair( nextVarNum, (int)(*i)->kind );
+						for ( std::vector< ast::ptr< ast::DeclWithType > >::const_iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) {
+							ast::Pass<Mangler_new> sub_mangler( 
+								mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
+							(*assert)->accept( sub_mangler );
+							assertionNames.push_back( sub_mangler.pass.get_mangleName() );
+							acount++;
+						} // for
+					} // for
+					mangleName << dcount << "_" << fcount << "_" << vcount << "_" << acount << "_";
+					std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
+					mangleName << "_";
+				} // if
+			} // if
+			if ( ! inFunctionType ) {
+				// these qualifiers do not distinguish the outermost type of a function parameter
+				if ( type->is_const() ) {
+					mangleName << Encoding::qualifiers.at(Type::Const);
+				} // if
+				if ( type->is_volatile() ) {
+					mangleName << Encoding::qualifiers.at(Type::Volatile);
+				} // if
+				// Removed due to restrict not affecting function compatibility in GCC
+				// if ( type->get_isRestrict() ) {
+				// 	mangleName << "E";
+				// } // if
+				if ( type->is_atomic() ) {
+					mangleName << Encoding::qualifiers.at(Type::Atomic);
+				} // if
+			}
+			if ( type->is_mutex() ) {
+				mangleName << Encoding::qualifiers.at(Type::Mutex);
+			} // if
+			if ( type->is_lvalue() ) {
+				// mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues
+				mangleName << Encoding::qualifiers.at(Type::Lvalue);
+			}
+
+			if ( inFunctionType ) {
+				// turn off inFunctionType so that types can be differentiated for nested qualifiers
+				GuardValue( inFunctionType );
+				inFunctionType = false;
+			}
+		}
+	}	// namespace
 } // namespace Mangle
 
