Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision ff29f0885c5ef43cc494cdb91326ef1813825a32)
+++ src/SymTab/Indexer.cc	(revision 80a7d48799fc4a072133fdd163de97b6228345d6)
@@ -26,4 +26,5 @@
 #include "Common/SemanticError.h"  // for SemanticError
 #include "Common/utility.h"        // for cloneAll
+#include "GenPoly/GenPoly.h"
 #include "InitTweak/InitTweak.h"   // for isConstructor, isCopyFunction, isC...
 #include "Mangler.h"               // for Mangler
@@ -377,8 +378,27 @@
 	}
 
+	bool isFunction( DeclarationWithType * decl ) {
+		return GenPoly::getFunctionType( decl->get_type() );
+	}
+
+	bool isObject( DeclarationWithType * decl ) {
+		return ! isFunction( decl );
+	}
+
+	bool isDefinition( DeclarationWithType * decl ) {
+		if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) {
+			// a function is a definition if it has a body
+			return func->statements;
+		} else {
+			// an object is a definition if it is not marked extern.
+			// both objects must be marked extern
+			return ! decl->get_storageClasses().is_extern;
+		}
+	}
+
 	bool addedIdConflicts( Indexer::IdData & existing, DeclarationWithType *added, BaseSyntaxNode * deleteStmt, Indexer::ConflictFunction handleConflicts ) {
 		// if we're giving the same name mangling to things of different types then there is something wrong
-		assert( (dynamic_cast<ObjectDecl*>( added ) && dynamic_cast<ObjectDecl*>( existing.id ) )
-			|| (dynamic_cast<FunctionDecl*>( added ) && dynamic_cast<FunctionDecl*>( existing.id ) ) );
+		assert( (isObject( added ) && isObject( existing.id ) )
+			|| ( isFunction( added ) && isFunction( existing.id ) ) );
 
 		if ( LinkageSpec::isOverridable( existing.id->get_linkage() ) ) {
@@ -394,20 +414,8 @@
 			}
 
-			// typesCompatible doesn't really do the right thing here. When checking compatibility of function types,
-			// we should ignore outermost pointer qualifiers, except _Atomic?
-			FunctionDecl * newentry = dynamic_cast< FunctionDecl * >( added );
-			FunctionDecl * oldentry = dynamic_cast< FunctionDecl * >( existing.id );
-			if ( newentry && oldentry ) {
-				if ( newentry->get_statements() && oldentry->get_statements() ) {
+			if ( isDefinition( added ) && isDefinition( existing.id ) ) {
+				if ( isFunction( added ) ) {
 					return handleConflicts( existing, "duplicate function definition for " );
-				} // if
-			} else {
-				// two objects with the same mangled name defined in the same scope.
-				// both objects must be marked extern or both must be intrinsic for this to be okay
-				// xxx - perhaps it's actually if either is intrinsic then this is okay?
-				//       might also need to be same storage class?
-				ObjectDecl * newobj = dynamic_cast< ObjectDecl * >( added );
-				ObjectDecl * oldobj = dynamic_cast< ObjectDecl * >( existing.id );
-				if ( ! newobj->get_storageClasses().is_extern && ! oldobj->get_storageClasses().is_extern ) {
+				} else {
 					return handleConflicts( existing, "duplicate object definition for " );
 				} // if
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision ff29f0885c5ef43cc494cdb91326ef1813825a32)
+++ src/SymTab/Mangler.cc	(revision 80a7d48799fc4a072133fdd163de97b6228345d6)
@@ -35,5 +35,5 @@
 		namespace {
 			/// Mangles names to a unique C identifier
-			struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler> {
+			struct Mangler : public WithShortCircuiting, public WithVisitorRef<Mangler>, public WithGuards {
 				Mangler( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
 				Mangler( const Mangler & ) = delete;
@@ -55,4 +55,5 @@
 				void postvisit( EnumInstType * aggregateUseType );
 				void postvisit( TypeInstType * aggregateUseType );
+				void postvisit( TraitInstType * inst );
 				void postvisit( TupleType * tupleType );
 				void postvisit( VarArgsType * varArgsType );
@@ -70,4 +71,5 @@
 				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.
 
 				void mangleDecl( DeclarationWithType *declaration );
@@ -177,5 +179,6 @@
 			void Mangler::postvisit( PointerType * pointerType ) {
 				printQualifiers( pointerType );
-				mangleName << "P";
+				// mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
+				if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName << "P";
 				maybeAccept( pointerType->base, *visitor );
 			}
@@ -189,6 +192,10 @@
 
 			void Mangler::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.),
+				// by pretending every reference type is a function parameter.
+				GuardValue( inFunctionType );
+				inFunctionType = true;
 				printQualifiers( refType );
-				mangleName << "R";
 				maybeAccept( refType->base, *visitor );
 			}
@@ -206,4 +213,9 @@
 				printQualifiers( functionType );
 				mangleName << "F";
+				// 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::list< Type* > returnTypes = getTypes( functionType->get_returnVals() );
 				acceptAll( returnTypes, *visitor );
@@ -270,4 +282,9 @@
 			}
 
+			void Mangler::postvisit( TraitInstType * inst ) {
+				printQualifiers( inst );
+				mangleName << "_Y" << inst->name << "_";
+			}
+
 			void Mangler::postvisit( TupleType * tupleType ) {
 				printQualifiers( tupleType );
@@ -304,5 +321,4 @@
 				// skip if not including qualifiers
 				if ( typeMode ) return;
-
 				if ( ! type->get_forall().empty() ) {
 					std::list< std::string > assertionNames;
@@ -337,24 +353,33 @@
 					mangleName << "_";
 				} // if
-				if ( type->get_const() ) {
-					mangleName << "C";
-				} // if
-				if ( type->get_volatile() ) {
-					mangleName << "V";
-				} // if
+				if ( ! inFunctionType ) {
+					// these qualifiers do not distinguish the outermost type of a function parameter
+					if ( type->get_const() ) {
+						mangleName << "C";
+					} // if
+					if ( type->get_volatile() ) {
+						mangleName << "V";
+					} // if
+					// Removed due to restrict not affecting function compatibility in GCC
+					// if ( type->get_isRestrict() ) {
+					// 	mangleName << "E";
+					// } // if
+					if ( type->get_atomic() ) {
+						mangleName << "A";
+					} // if
+				}
 				if ( type->get_mutex() ) {
 					mangleName << "M";
 				} // if
-				// Removed due to restrict not affecting function compatibility in GCC
-		//		if ( type->get_isRestrict() ) {
-		//			mangleName << "E";
-		//		} // if
 				if ( type->get_lvalue() ) {
 					// mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues
 					mangleName << "L";
 				}
-				if ( type->get_atomic() ) {
-					mangleName << "A";
-				} // if
+
+				if ( inFunctionType ) {
+					// turn off inFunctionType so that types can be differentiated for nested qualifiers
+					GuardValue( inFunctionType );
+					inFunctionType = false;
+				}
 			}
 		}	// namespace
