diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index 66c72c2d9f864aa9d618c2248a7de66c9747f56e..9a6d1eff5c2fc1fb1c144d33fbec63f78649231c 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -35,7 +35,7 @@
 #include <boost/shared_ptr.hpp>
 
 #include "llerror.h"
-#include "lltypeinfolookup.h"
+#include "llstl.h"
 
 namespace LLInitParam
 {
@@ -220,9 +220,9 @@ namespace LLInitParam
 		typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&);
 		typedef boost::function<void (name_stack_t&, S32, S32, const possible_values_t*)>	parser_inspect_func_t;
 
-		typedef LLTypeInfoLookup<parser_read_func_t>		parser_read_func_map_t;
-		typedef LLTypeInfoLookup<parser_write_func_t>		parser_write_func_map_t;
-		typedef LLTypeInfoLookup<parser_inspect_func_t>		parser_inspect_func_map_t;
+		typedef std::map<const std::type_info*, parser_read_func_t>		parser_read_func_map_t;
+		typedef std::map<const std::type_info*, parser_write_func_t>	parser_write_func_map_t;
+		typedef std::map<const std::type_info*, parser_inspect_func_t>	parser_inspect_func_map_t;
 
 		Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
 		:	mParseSilently(false),
@@ -234,20 +234,20 @@ namespace LLInitParam
 
 		template <typename T> bool readValue(T& param)
 	    {
-		    boost::optional<parser_read_func_t> found_it = mParserReadFuncs->find<T>();
-		    if (found_it)
+		    parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
+		    if (found_it != mParserReadFuncs->end())
 		    {
-			    return (*found_it)(*this, (void*)&param);
+			    return found_it->second(*this, (void*)&param);
 		    }
 		    return false;
 	    }
 
 		template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
 		{
-		    boost::optional<parser_write_func_t> found_it = mParserWriteFuncs->find<T>();
-		    if (found_it)
+		    parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T));
+		    if (found_it != mParserWriteFuncs->end())
 		    {
-			    return (*found_it)(*this, (const void*)&param, name_stack);
+			    return found_it->second(*this, (const void*)&param, name_stack);
 		    }
 		    return false;
 		}
@@ -255,10 +255,10 @@ namespace LLInitParam
 		// dispatch inspection to registered inspection functions, for each parameter in a param block
 		template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values)
 		{
-		    boost::optional<parser_inspect_func_t> found_it = mParserInspectFuncs->find<T>();
-		    if (found_it)
+		    parser_inspect_func_map_t::iterator found_it = mParserInspectFuncs->find(&typeid(T));
+		    if (found_it != mParserInspectFuncs->end())
 		    {
-			    (*found_it)(name_stack, min_count, max_count, possible_values);
+			    found_it->second(name_stack, min_count, max_count, possible_values);
 				return true;
 		    }
 			return false;
@@ -273,14 +273,14 @@ namespace LLInitParam
 		template <typename T>
 		void registerParserFuncs(parser_read_func_t read_func, parser_write_func_t write_func = NULL)
 		{
-			mParserReadFuncs->insert<T>(read_func);
-			mParserWriteFuncs->insert<T>(write_func);
+			mParserReadFuncs->insert(std::make_pair(&typeid(T), read_func));
+			mParserWriteFuncs->insert(std::make_pair(&typeid(T), write_func));
 		}
 
 		template <typename T>
 		void registerInspectFunc(parser_inspect_func_t inspect_func)
 		{
-			mParserInspectFuncs->insert<T>(inspect_func);
+			mParserInspectFuncs->insert(std::make_pair(&typeid(T), inspect_func));
 		}
 
 		bool				mParseSilently;
diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h
index babc1b87aacff355d1b4526eee3a27cf006255f8..853c427a13e87dfaeb5a209c2d755fa0d31aa3f4 100644
--- a/indra/llcommon/llregistry.h
+++ b/indra/llcommon/llregistry.h
@@ -30,38 +30,22 @@
 #include <list>
 
 #include <boost/type_traits.hpp>
-#include <boost/static_assert.hpp>
 #include "llsingleton.h"
+#include "llstl.h"
 
 template <typename T>
 struct LLRegistryDefaultComparator
 {
-	// It would be Bad if this comparison were used for const char*
-	BOOST_STATIC_ASSERT(! (boost::is_same<typename boost::remove_const<typename boost::remove_pointer<T>::type>::type, char>::value));
-	bool operator()(const T& lhs, const T& rhs) const { return lhs < rhs; }
-};
-
-// comparator for const char* registry keys
-template <>
-struct LLRegistryDefaultComparator<const char*>
-{
-	bool operator()(const char* lhs, const char* rhs) const
+	bool operator()(const T& lhs, const T& rhs) const
 	{
-		return strcmp(lhs, rhs) < 0;
+		using std::less;
+		return less<T>()(lhs, rhs);
 	}
 };
 
 template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
 class LLRegistry
 {
-	// Do not use LLRegistry with KEY = std::type_info* or KEY = const std::type_info*.
-	// This is known to fail on Linux.
-	// If you must use LLRegistry with dynamic type info, use KEY = const char*
-	// and pass std::type_info::name(); this works across load modules.
-	// Disallow both std::type_info* and const std::type_info*. First remove
-	// the pointer, then remove const, then compare is_same<std::type_info>.
-	BOOST_STATIC_ASSERT(! (boost::is_same<typename boost::remove_const<typename boost::remove_pointer<KEY>::type>::type, std::type_info>::value));
-
 public:
 	typedef LLRegistry<KEY, VALUE, COMPARATOR>											registry_t;
 	typedef typename boost::add_reference<typename boost::add_const<KEY>::type>::type	ref_const_key_t;
diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h
index 8ad12c9a03c29c8f08e4a7cc60589f5a11f69a41..d3941e1bc92c30502b0a05989ab4da896d776db5 100644
--- a/indra/llcommon/llstl.h
+++ b/indra/llcommon/llstl.h
@@ -33,6 +33,7 @@
 #include <vector>
 #include <set>
 #include <deque>
+#include <typeinfo>
 
 // Use to compare the first element only of a pair
 // e.g. typedef std::set<std::pair<int, Data*>, compare_pair<int, Data*> > some_pair_set_t; 
@@ -470,4 +471,54 @@ llbind2nd(const _Operation& __oper, const _Tp& __x)
   return llbinder2nd<_Operation>(__oper, _Arg2_type(__x));
 }
 
+/**
+ * Compare std::type_info* pointers a la std::less. We break this out as a
+ * separate function for use in two different std::less specializations.
+ */
+inline
+bool before(const std::type_info* lhs, const std::type_info* rhs)
+{
+#if LL_LINUX && defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 4))
+    // If we're building on Linux with gcc, and it's either gcc 3.x or
+    // 4.{0,1,2,3}, then we have to use a workaround. Note that we use gcc on
+    // Mac too, and some people build with gcc on Windows (cygwin or mingw).
+    // On Linux, different load modules may produce different type_info*
+    // pointers for the same type. Have to compare name strings to get good
+    // results.
+    return strcmp(lhs->name(), rhs->name()) < 0;
+#else  // not Linux, or gcc 4.4+
+    // Just use before(), as we normally would
+    return lhs->before(*rhs);
+#endif
+}
+
+/**
+ * Specialize std::less<std::type_info*> to use std::type_info::before().
+ * See MAINT-1175. It is NEVER a good idea to directly compare std::type_info*
+ * because, on Linux, you might get different std::type_info* pointers for the
+ * same type (from different load modules)!
+ */
+namespace std
+{
+	template <>
+	struct less<const std::type_info*>:
+		public std::binary_function<const std::type_info*, const std::type_info*, bool>
+	{
+		bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
+		{
+			return before(lhs, rhs);
+		}
+	};
+
+	template <>
+	struct less<std::type_info*>:
+		public std::binary_function<std::type_info*, std::type_info*, bool>
+	{
+		bool operator()(std::type_info* lhs, std::type_info* rhs) const
+		{
+			return before(lhs, rhs);
+		}
+	};
+} // std
+
 #endif // LL_LLSTL_H
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index f20cc2452f3bf544b62bcc3b3234874740804aad..8ca1e685a96922a823d5b182590f53ea90b7cc01 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -232,7 +232,7 @@ void LLFloater::initClass()
 }
 
 // defaults for floater param block pulled from widgets/floater.xml
-static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(typeid(LLFloater::Params).name(), "floater");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(&typeid(LLFloater::Params), "floater");
 
 LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
 :	LLPanel(),	// intentionally do not pass params here, see initFromParams
diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp
index 71bbcd8ade144284239d51e3bf43882f54d7d1a3..95a7d0938244cd6e43c640543c8acbe16b8c6369 100644
--- a/indra/llui/llradiogroup.cpp
+++ b/indra/llui/llradiogroup.cpp
@@ -66,7 +66,7 @@ class LLRadioCtrl : public LLCheckBoxCtrl
 
 	LLSD mPayload;	// stores data that this item represents in the radio group
 };
-static LLWidgetNameRegistry::StaticRegistrar register_radio_item(typeid(LLRadioGroup::ItemParams).name(), "radio_item");
+static LLWidgetNameRegistry::StaticRegistrar register_radio_item(&typeid(LLRadioGroup::ItemParams), "radio_item");
 
 LLRadioGroup::Params::Params()
 :	allow_deselect("allow_deselect"),
diff --git a/indra/llui/llrngwriter.cpp b/indra/llui/llrngwriter.cpp
index 90a1e77b1afde4de8e127c9b941825e89ff74b60..5e6840d7df83e96cf92b2e2841eec1c805d5eb98 100644
--- a/indra/llui/llrngwriter.cpp
+++ b/indra/llui/llrngwriter.cpp
@@ -92,7 +92,7 @@ void LLRNGWriter::addDefinition(const std::string& type_name, const LLInitParam:
 
 	// add includes for all possible children
 	const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name);
-	const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type->name());
+	const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type);
 	
 	// add include declarations for all valid children
 	for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems();
diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp
index d132d0cc7e41fd8fb3e866155fcdba8809428f13..07a6dfaa102c92a6cd9ad6f0ab73209bb498587d 100644
--- a/indra/llui/llscrolllistcolumn.cpp
+++ b/indra/llui/llscrolllistcolumn.cpp
@@ -39,7 +39,7 @@
 const S32 MIN_COLUMN_WIDTH = 20;
 
 // defaults for LLScrollColumnHeader param block pulled from widgets/scroll_column_header.xml
-static LLWidgetNameRegistry::StaticRegistrar sRegisterColumnHeaderParams(typeid(LLScrollColumnHeader::Params).name(), "scroll_column_header");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterColumnHeaderParams(&typeid(LLScrollColumnHeader::Params), "scroll_column_header");
 
 //---------------------------------------------------------------------------
 // LLScrollColumnHeader
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 8314386632d172e8e35d935fbc4b58f3b2808f17..7aeeae298f754407abcf026372b21c6d6935ba8b 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -131,7 +131,7 @@ struct LLTextBase::line_end_compare
 //
 
 // register LLTextBase::Params under name "textbase"
-static LLWidgetNameRegistry::StaticRegistrar sRegisterTextBaseParams(typeid(LLTextBase::Params).name(), "textbase");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterTextBaseParams(&typeid(LLTextBase::Params), "textbase");
 
 LLTextBase::LineSpacingParams::LineSpacingParams()
 :	multiple("multiple", 1.f),
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index 0723dbec704f97713b65ee31a3cd103e0dc57a04..f737d48abfaade2245b71b1c486a80663a7bae54 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -129,7 +129,7 @@ void LLToolTipView::drawStickyRect()
 }
 
 // defaults for floater param block pulled from widgets/floater.xml
-static LLWidgetNameRegistry::StaticRegistrar sRegisterInspectorParams(typeid(LLInspector::Params).name(), "inspector");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterInspectorParams(&typeid(LLInspector::Params), "inspector");
 
 //
 // LLToolTip
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index fe3b4707220fdbeee82edac9e0457f3cfc599a3e..25e7a31e9073de346c6a1bc43f2d37d1925d1b47 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -281,7 +281,7 @@ const LLInitParam::BaseBlock& get_empty_param_block()
 void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& tag)
 {
 	// associate parameter block type with template .xml file
-	std::string* existing_tag = LLWidgetNameRegistry::instance().getValue(param_block_type->name());
+	std::string* existing_tag = LLWidgetNameRegistry::instance().getValue(param_block_type);
 	if (existing_tag != NULL)
 	{
 		if(*existing_tag != tag)
@@ -297,7 +297,7 @@ void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const st
 			return;
 		}
 	}
-	LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type->name(), tag);
+	LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, tag);
 	//FIXME: comment this in when working on schema generation
 	//LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type);
 	//LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type, &get_empty_param_block<T>);
@@ -306,6 +306,6 @@ void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const st
 //static 
 const std::string* LLUICtrlFactory::getWidgetTag(const std::type_info* widget_type)
 {
-	return LLWidgetNameRegistry::instance().getValue(widget_type->name());
+	return LLWidgetNameRegistry::instance().getValue(widget_type);
 }
 
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index a5fd83e5559ed49160b59d58ccdb128c97d96d96..4e54354731e57fe76ef1afa9981cadc4e3ab4bc5 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -31,6 +31,7 @@
 #include "llinitparam.h"
 #include "llregistry.h"
 #include "llxuiparser.h"
+#include "llstl.h"
 
 class LLView;
 
@@ -60,16 +61,16 @@ class LLDefaultChildRegistry : public LLChildRegistry<LLDefaultChildRegistry>
 	friend class LLSingleton<LLDefaultChildRegistry>;
 };
 
-// lookup widget name by type (actually by std::type_info::name())
+// lookup widget name by type
 class LLWidgetNameRegistry 
-:	public LLRegistrySingleton<const char*, std::string, LLWidgetNameRegistry>
+:	public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry>
 {};
 
 // lookup function for generating empty param block by widget type
 // this is used for schema generation
 //typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)();
 //class LLDefaultParamBlockRegistry
-//:	public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry, LLCompareTypeID>
+//:	public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry>
 //{};
 
 extern LLFastTimer::DeclareTimer FTM_WIDGET_SETUP;
diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp
index c3a246b9a51bef81a5dbaa632727a7ef06f923bb..afc76024d1e0ef0f8688b8de638cbe52c29843e2 100644
--- a/indra/llui/llxuiparser.cpp
+++ b/indra/llui/llxuiparser.cpp
@@ -606,7 +606,7 @@ void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& p
 
 	// add includes for all possible children
 	const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name);
-	const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type->name());
+	const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type);
 
 	// add choices for valid children
 	if (widget_registryp)
diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h
index 3c092afdd6b238c6094e81288633b071156644fb..d7cd25696723dd11a104c4435dd9067a5d84bbab 100644
--- a/indra/llui/llxuiparser.h
+++ b/indra/llui/llxuiparser.h
@@ -55,9 +55,8 @@ typedef boost::function<LLView* (LLXMLNodePtr node, LLView *parent, LLXMLNodePtr
 
 typedef LLRegistry<std::string, LLWidgetCreatorFunc> widget_registry_t;
 
-// const char* key used for std::type_info::name() string
 class LLChildRegistryRegistry
-: public LLRegistrySingleton<const char*, widget_registry_t, LLChildRegistryRegistry>
+: public LLRegistrySingleton<const std::type_info*, widget_registry_t, LLChildRegistryRegistry>
 {};
 
 
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index c07fec8e5ec0329a09c11e8b6b9b0dbe65e1dbba..30eecfe3231ddb2a061696a30b94e4cafbc65a92 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -44,7 +44,7 @@ S32 LLAvatarListItem::sLeftPadding = 0;
 S32 LLAvatarListItem::sNameRightPadding = 0;
 S32 LLAvatarListItem::sChildrenWidths[LLAvatarListItem::ALIC_COUNT];
 
-static LLWidgetNameRegistry::StaticRegistrar sRegisterAvatarListItemParams(typeid(LLAvatarListItem::Params).name(), "avatar_list_item");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterAvatarListItemParams(&typeid(LLAvatarListItem::Params), "avatar_list_item");
 
 LLAvatarListItem::Params::Params()
 :	default_style("default_style"),
diff --git a/indra/newview/llinventorylistitem.cpp b/indra/newview/llinventorylistitem.cpp
index 5489671430e63bc6ce42b05a8934aeb9b71b5065..3e0849a79578d793e0890e45d8a4d74b77b46545 100644
--- a/indra/newview/llinventorylistitem.cpp
+++ b/indra/newview/llinventorylistitem.cpp
@@ -40,7 +40,7 @@
 #include "llinventorymodel.h"
 #include "llviewerinventory.h"
 
-static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelInventoryListItemBaseParams(typeid(LLPanelInventoryListItemBase::Params).name(), "inventory_list_item");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelInventoryListItemBaseParams(&typeid(LLPanelInventoryListItemBase::Params), "inventory_list_item");
 
 static const S32 WIDGET_SPACING = 3;
 
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index abb53301a6a02a4f849628db5344575079ce04bc..92697fb2eb8334b4023801342cb168dd25d6b103 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -135,7 +135,7 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name,
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
-static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelClothingListItem(typeid(LLPanelClothingListItem::Params).name(), "clothing_list_item");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelClothingListItem(&typeid(LLPanelClothingListItem::Params), "clothing_list_item");
 
 
 LLPanelClothingListItem::Params::Params()
@@ -222,7 +222,7 @@ BOOL LLPanelClothingListItem::postBuild()
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 
-static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelBodyPartsListItem(typeid(LLPanelBodyPartsListItem::Params).name(), "bodyparts_list_item");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelBodyPartsListItem(&typeid(LLPanelBodyPartsListItem::Params), "bodyparts_list_item");
 
 
 LLPanelBodyPartsListItem::Params::Params()
@@ -293,7 +293,7 @@ BOOL LLPanelBodyPartsListItem::postBuild()
 	return TRUE;
 }
 
-static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDeletableWearableListItem(typeid(LLPanelDeletableWearableListItem::Params).name(), "deletable_wearable_list_item");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDeletableWearableListItem(&typeid(LLPanelDeletableWearableListItem::Params), "deletable_wearable_list_item");
 
 LLPanelDeletableWearableListItem::Params::Params()
 :	delete_btn("delete_btn")
@@ -373,7 +373,7 @@ void LLPanelAttachmentListItem::updateItem(const std::string& name,
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
-static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDummyClothingListItem(typeid(LLPanelDummyClothingListItem::Params).name(), "dummy_clothing_list_item");
+static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelDummyClothingListItem(&typeid(LLPanelDummyClothingListItem::Params), "dummy_clothing_list_item");
 
 LLPanelDummyClothingListItem::Params::Params()
 :	add_panel("add_panel"),