Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
+++ src/SymTab/Indexer.cc	(revision 5447e096f5c70e8f732f6456b20b5978dfe20cad)
@@ -19,4 +19,5 @@
 #include <typeinfo>
 #include <unordered_map>
+#include <unordered_set>
 #include <utility>
 
@@ -435,16 +436,23 @@
 
 	void Indexer::lookupId( const std::string &id, std::list< DeclarationWithType* > &out ) const {
-		if ( ! tables ) return;
-
-		IdTable::const_iterator decls = tables->idTable.find( id );
-		if ( decls != tables->idTable.end() ) {
-			const MangleTable &mangleTable = decls->second;
-			for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
-				out.push_back( decl->second );
-			}
-		}
+		std::unordered_set< std::string > foundMangleNames;
 		
-		// get declarations from base indexers
-		tables->base.lookupId( id, out );
+		Indexer::Impl *searchTables = tables;
+		while ( searchTables ) {
+
+			IdTable::const_iterator decls = searchTables->idTable.find( id );
+			if ( decls != searchTables->idTable.end() ) {
+				const MangleTable &mangleTable = decls->second;
+				for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
+					// mark the mangled name as found, skipping this insertion if a declaration for that name has already been found
+					if ( foundMangleNames.insert( decl->first ).second == false ) continue;
+					
+					out.push_back( decl->second );
+				}
+			}
+			
+			// get declarations from base indexers
+			searchTables = searchTables->base.tables;
+		}
 	}
 
@@ -498,5 +506,5 @@
 	}
 
-	bool Indexer::hasCDeclWithName( const std::string &id ) const {
+	bool Indexer::hasIncompatibleCDecl( const std::string &id, const std::string &mangleName ) const {
 		if ( ! tables ) return false;
 
@@ -505,9 +513,11 @@
 			const MangleTable &mangleTable = decls->second;
 			for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
-				if ( decl->second->get_linkage() == LinkageSpec::C ) return true;
-			}
-		}
-
-		return tables->base.hasCDeclWithName( id );
+				// check for C decls with the same name, skipping 
+				// those with a compatible type (by mangleName)
+				if ( decl->second->get_linkage() == LinkageSpec::C && decl->first != mangleName ) return true;
+			}
+		}
+
+		return tables->base.hasIncompatibleCDecl( id, mangleName );
 	}
 	
@@ -592,4 +602,8 @@
 		const std::string &name = decl->get_name();
 		std::string mangleName;
+		// TODO the first branch of this if is a bug-for-bug replication of Richard's code;
+		// it can allow C decls to hide CFA decls when they shouldn't, but the current prelude 
+		// depends on this bug to build ... <stdlib>'s random() should be fixed to *not* hide 
+		// <stdlib.h>'s random() before this first branch is taken out again
 		if ( decl->get_linkage() == LinkageSpec::C ) {
 			mangleName = name;
@@ -605,7 +619,11 @@
 		if ( ! existing || ! addedIdConflicts( existing, decl ) ) {
 			// this ensures that no two declarations with the same unmangled name both have C linkage
-			if ( decl->get_linkage() == LinkageSpec::C && hasCDeclWithName( name ) ) {
+			if ( decl->get_linkage() == LinkageSpec::C && hasIncompatibleCDecl( name, mangleName ) ) {
 				throw SemanticError( "invalid overload of C function ", decl );
-			}
+			} // NOTE this is broken in Richard's original code in such a way that it never triggers (it 
+			  // doesn't check decls that have the same manglename, and all C-linkage decls are defined to 
+			  // have their name as their manglename, hence the error can never trigger).
+			  // The elided code here is closer to correct, but name mangling would have to be completely 
+			  // isomorphic to C type-compatibility, which it may not be.
 			
 			tables->idTable[ name ][ mangleName ] = decl;
Index: src/SymTab/Indexer.h
===================================================================
--- src/SymTab/Indexer.h	(revision ae357ec6fbde71fbc5bee4ea0bb712010be78deb)
+++ src/SymTab/Indexer.h	(revision 5447e096f5c70e8f732f6456b20b5978dfe20cad)
@@ -97,6 +97,6 @@
 		/// looks up a specific mangled ID at the given scope
 		DeclarationWithType *lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
-		/// returns true if there exists a declaration with C linkage and the given name
-		bool hasCDeclWithName( const std::string &id ) const;
+		/// returns true if there exists a declaration with C linkage and the given name with a different mangled name
+		bool hasIncompatibleCDecl( const std::string &id, const std::string &mangleName ) const;
 		// equivalents to lookup functions that only look at tables at scope `scope` (which should be >= tables->scope)
 		NamedTypeDecl *lookupTypeAtScope( const std::string &id, unsigned long scope ) const;
