Use std::type_info::name() for type lookups outside stdlibc++

Using `std::type_info::operator==` fails under libc++ because the .so
is loaded with RTLD_LOCAL.  libc++ considers types under such .sos
distinct, and so comparing typeid() values directly isn't going to work.

This adds a custom hasher and equality class for the type lookup maps
when not under stdlibc++, and adds a `detail::same_type` function to
perform the equality test.  It also converts a few pointer arguments to
const lvalue references, particularly since doing the pointer
comparison wasn't technically valid to being with (though in practice,
appeared to work everywhere).

This fixes #912.
diff --git a/include/pybind11/attr.h b/include/pybind11/attr.h
index da81c0d..15d6208 100644
--- a/include/pybind11/attr.h
+++ b/include/pybind11/attr.h
@@ -243,17 +243,17 @@
     /// Is the default (unique_ptr) holder type used?
     bool default_holder : 1;
 
-    PYBIND11_NOINLINE void add_base(const std::type_info *base, void *(*caster)(void *)) {
-        auto base_info = detail::get_type_info(*base, false);
+    PYBIND11_NOINLINE void add_base(const std::type_info &base, void *(*caster)(void *)) {
+        auto base_info = detail::get_type_info(base, false);
         if (!base_info) {
-            std::string tname(base->name());
+            std::string tname(base.name());
             detail::clean_type_id(tname);
             pybind11_fail("generic_type: type \"" + std::string(name) +
                           "\" referenced unknown base type \"" + tname + "\"");
         }
 
         if (default_holder != base_info->default_holder) {
-            std::string tname(base->name());
+            std::string tname(base.name());
             detail::clean_type_id(tname);
             pybind11_fail("generic_type: type \"" + std::string(name) + "\" " +
                     (default_holder ? "does not have" : "has") +
@@ -384,7 +384,7 @@
 /// Process a parent class attribute (deprecated, does not support multiple inheritance)
 template <typename T>
 struct process_attribute<base<T>> : process_attribute_default<base<T>> {
-    static void init(const base<T> &, type_record *r) { r->add_base(&typeid(T), nullptr); }
+    static void init(const base<T> &, type_record *r) { r->add_base(typeid(T), nullptr); }
 };
 
 /// Process a multiple inheritance attribute
diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h
index fbca3c6..d34afbc 100644
--- a/include/pybind11/cast.h
+++ b/include/pybind11/cast.h
@@ -16,7 +16,6 @@
 #include <array>
 #include <limits>
 #include <tuple>
-#include <cstring>
 
 #if defined(PYBIND11_CPP17)
 #  if defined(__has_include)
@@ -659,14 +658,14 @@
     // isn't needed or can't be used.  If the type is unknown, sets the error and returns a pair
     // with .second = nullptr.  (p.first = nullptr is not an error: it becomes None).
     PYBIND11_NOINLINE static std::pair<const void *, const type_info *> src_and_type(
-            const void *src, const std::type_info *cast_type, const std::type_info *rtti_type = nullptr) {
+            const void *src, const std::type_info &cast_type, const std::type_info *rtti_type = nullptr) {
         auto &internals = get_internals();
-        auto it = internals.registered_types_cpp.find(std::type_index(*cast_type));
+        auto it = internals.registered_types_cpp.find(std::type_index(cast_type));
         if (it != internals.registered_types_cpp.end())
             return {src, (const type_info *) it->second};
 
         // Not found, set error:
-        std::string tname = (rtti_type ? rtti_type : cast_type)->name();
+        std::string tname = rtti_type ? rtti_type->name() : cast_type.name();
         detail::clean_type_id(tname);
         std::string msg = "Unregistered type : " + tname;
         PyErr_SetString(PyExc_TypeError, msg.c_str());
@@ -743,11 +742,11 @@
     static std::pair<const void *, const type_info *> src_and_type(const itype *src) {
         const void *vsrc = src;
         auto &internals = get_internals();
-        auto cast_type = &typeid(itype);
+        auto &cast_type = typeid(itype);
         const std::type_info *instance_type = nullptr;
         if (vsrc) {
             instance_type = &typeid(*src);
-            if (instance_type != cast_type) {
+            if (!same_type(cast_type, *instance_type)) {
                 // This is a base pointer to a derived type; if it is a pybind11-registered type, we
                 // can get the correct derived pointer (which may be != base pointer) by a
                 // dynamic_cast to most derived type:
@@ -764,7 +763,7 @@
     // Non-polymorphic type, so no dynamic casting; just call the generic version directly
     template <typename T = itype, enable_if_t<!std::is_polymorphic<T>::value, int> = 0>
     static std::pair<const void *, const type_info *> src_and_type(const itype *src) {
-        return type_caster_generic::src_and_type(src, &typeid(itype));
+        return type_caster_generic::src_and_type(src, typeid(itype));
     }
 
     static handle cast(const itype *src, return_value_policy policy, handle parent) {
@@ -1739,7 +1738,7 @@
 
 NAMESPACE_BEGIN(detail)
 
-// forward declaration
+// forward declaration (definition in attr.h)
 struct function_record;
 
 /// Internal data associated with a single function call
diff --git a/include/pybind11/common.h b/include/pybind11/common.h
index b0d1bc2..9282051 100644
--- a/include/pybind11/common.h
+++ b/include/pybind11/common.h
@@ -124,6 +124,7 @@
 #endif
 
 #include <cstddef>
+#include <cstring>
 #include <forward_list>
 #include <vector>
 #include <string>
@@ -426,13 +427,48 @@
     }
 };
 
+// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly
+// other stls, this means `typeid(A)` from one module won't equal `typeid(A)` from another module
+// even when `A` is the same, non-hidden-visibility type (e.g. from a common include).  Under
+// stdlibc++, this doesn't happen: equality and the type_index hash are based on the type name,
+// which works.  If not under a known-good stl, provide our own name-based hasher and equality
+// functions that use the type name.
+#if defined(__GLIBCXX__)
+inline bool same_type(const std::type_info &lhs, const std::type_info &rhs) { return lhs == rhs; }
+using type_hash = std::hash<std::type_index>;
+using type_equal_to = std::equal_to<std::type_index>;
+#else
+inline bool same_type(const std::type_info &lhs, const std::type_info &rhs) {
+    return lhs.name() == rhs.name() ||
+        std::strcmp(lhs.name(), rhs.name()) == 0;
+}
+struct type_hash {
+    size_t operator()(const std::type_index &t) const {
+        size_t hash = 5381;
+        const char *ptr = t.name();
+        while (auto c = static_cast<unsigned char>(*ptr++))
+            hash = (hash * 33) ^ c;
+        return hash;
+    }
+};
+struct type_equal_to {
+    bool operator()(const std::type_index &lhs, const std::type_index &rhs) const {
+        return lhs.name() == rhs.name() ||
+            std::strcmp(lhs.name(), rhs.name()) == 0;
+    }
+};
+#endif
+
+template <typename value_type>
+using type_map = std::unordered_map<std::type_index, value_type, type_hash, type_equal_to>;
+
 /// Internal data structure used to track registered instances and types
 struct internals {
-    std::unordered_map<std::type_index, void*> registered_types_cpp; // std::type_index -> type_info
+    type_map<void *> registered_types_cpp; // std::type_index -> type_info
     std::unordered_map<PyTypeObject *, std::vector<type_info *>> registered_types_py; // PyTypeObject* -> base type_info(s)
     std::unordered_multimap<const void *, instance*> registered_instances; // void * -> instance*
     std::unordered_set<std::pair<const PyObject *, const char *>, overload_hash> inactive_overload_cache;
-    std::unordered_map<std::type_index, std::vector<bool (*)(PyObject *, void *&)>> direct_conversions;
+    type_map<std::vector<bool (*)(PyObject *, void *&)>> direct_conversions;
     std::forward_list<void (*) (std::exception_ptr)> registered_exception_translators;
     std::unordered_map<std::string, void *> shared_data; // Custom data to be shared across extensions
     PyTypeObject *static_property_type;
diff --git a/include/pybind11/functional.h b/include/pybind11/functional.h
index ae168c4..fdb6b33 100644
--- a/include/pybind11/functional.h
+++ b/include/pybind11/functional.h
@@ -46,7 +46,8 @@
             auto c = reinterpret_borrow<capsule>(PyCFunction_GET_SELF(cfunc.ptr()));
             auto rec = (function_record *) c;
 
-            if (rec && rec->is_stateless && rec->data[1] == &typeid(function_type)) {
+            if (rec && rec->is_stateless &&
+                    same_type(typeid(function_type), *reinterpret_cast<const std::type_info *>(rec->data[1]))) {
                 struct capture { function_type f; };
                 value = ((capture *) &rec->data)->f;
                 return true;
diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h
index 08268b8..40b32a8 100644
--- a/include/pybind11/pybind11.h
+++ b/include/pybind11/pybind11.h
@@ -968,7 +968,7 @@
 
     template <typename Base, detail::enable_if_t<is_base<Base>::value, int> = 0>
     static void add_base(detail::type_record &rec) {
-        rec.add_base(&typeid(Base), [](void *src) -> void * {
+        rec.add_base(typeid(Base), [](void *src) -> void * {
             return static_cast<Base *>(reinterpret_cast<type *>(src));
         });
     }