diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index ab3c32df63cc7a6073ed2e9f5361df5ca0d2fabc..03a1397f624c22877adf392c8c3b5f9925150ebb 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,14 @@
+2009-05-19  Paolo Carlini  <paolo.carlini@oracle.com>
+
+	PR libstdc++/40184
+	* include/bits/locale_classes.h (locale::facet::_S_lc_ctype_c_locale):
+	Declare...
+	* config/locale/gnu/c_locale.cc: ... and define.
+	* config/locale/generic/c_locale.cc: Define.
+	* src/localename.cc (locale::_Impl::_Impl(const char*, size_t)):
+	Use it.
+	* testsuite/22_locale/locale/cons/40184.cc: New.
+
 2009-05-18  Paolo Carlini  <paolo.carlini@oracle.com>
 
 	PR libstdc++/40192
diff --git a/libstdc++-v3/config/locale/generic/c_locale.cc b/libstdc++-v3/config/locale/generic/c_locale.cc
index 3b9f1bd42a51670c73ef0a4cbe17a566b42de51f..a79a970f23134af13c12e4f0d749ba2e515c1483 100644
--- a/libstdc++-v3/config/locale/generic/c_locale.cc
+++ b/libstdc++-v3/config/locale/generic/c_locale.cc
@@ -226,6 +226,10 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
   locale::facet::_S_clone_c_locale(__c_locale&)
   { return __c_locale(); }
 
+  __c_locale
+  locale::facet::_S_lc_ctype_c_locale(__c_locale, const char*)
+  { return __c_locale(); }
+
 _GLIBCXX_END_NAMESPACE
 
 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
diff --git a/libstdc++-v3/config/locale/gnu/c_locale.cc b/libstdc++-v3/config/locale/gnu/c_locale.cc
index cd32dc03130e0719fecb26fddd2c4cbfaeddff29..4864d25cd342abbb6e74f88e4cc44786c0de74ba 100644
--- a/libstdc++-v3/config/locale/gnu/c_locale.cc
+++ b/libstdc++-v3/config/locale/gnu/c_locale.cc
@@ -133,10 +133,10 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
       {
 	// This named locale is not supported by the underlying OS.
 	__throw_runtime_error(__N("locale::facet::_S_create_c_locale "
-			      "name not valid"));
+				  "name not valid"));
       }
   }
-  
+
   void
   locale::facet::_S_destroy_c_locale(__c_locale& __cloc)
   {
@@ -148,6 +148,23 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
   locale::facet::_S_clone_c_locale(__c_locale& __cloc)
   { return __duplocale(__cloc); }
 
+  __c_locale
+  locale::facet::_S_lc_ctype_c_locale(__c_locale __cloc, const char* __s)
+  {
+    __c_locale __dup = __duplocale(__cloc);
+    if (__dup == __c_locale(0))
+      __throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale "
+				"duplocale error"));
+    __c_locale __changed = __newlocale(LC_CTYPE_MASK, __s, __dup);
+    if (__changed == __c_locale(0))
+      {
+	__freelocale(__dup);
+	__throw_runtime_error(__N("locale::facet::_S_lc_ctype_c_locale "
+				  "newlocale error"));
+      }
+    return __changed;
+  }
+
 _GLIBCXX_END_NAMESPACE
 
 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
diff --git a/libstdc++-v3/include/bits/locale_classes.h b/libstdc++-v3/include/bits/locale_classes.h
index 1a7f2c20912c2a9536e98f3c850698dfd5665698..7ae9c53bc6acbb38007820a4360963a0271b3fc6 100644
--- a/libstdc++-v3/include/bits/locale_classes.h
+++ b/libstdc++-v3/include/bits/locale_classes.h
@@ -381,6 +381,9 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
     static void
     _S_destroy_c_locale(__c_locale& __cloc);
 
+    static __c_locale
+    _S_lc_ctype_c_locale(__c_locale __cloc, const char* __s);
+
     // Returns data from the underlying "C" library data for the
     // classic locale.
     static __c_locale
diff --git a/libstdc++-v3/src/localename.cc b/libstdc++-v3/src/localename.cc
index ae932a3a7e0b82fee25aec0dcbd7b8b7b721137a..98f6020533c272a32632a1e19fd84a042c22aa47 100644
--- a/libstdc++-v3/src/localename.cc
+++ b/libstdc++-v3/src/localename.cc
@@ -180,6 +180,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
     // see if the given name is valid.
     __c_locale __cloc;
     locale::facet::_S_create_c_locale(__cloc, __s);
+    __c_locale __clocm = __cloc;
 
     __try
       {
@@ -194,15 +195,19 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
 	  _M_names[__k] = 0;
 
 	// Name the categories.
+	const char* __smon = __s;
 	const size_t __len = std::strlen(__s);
 	if (!std::memchr(__s, ';', __len))
 	  {
 	    _M_names[0] = new char[__len + 1];
-	    std::memcpy(_M_names[0], __s, __len + 1);	    
+	    std::memcpy(_M_names[0], __s, __len + 1);
 	  }
 	else
 	  {
 	    const char* __end = __s;
+	    bool __found_ctype = false;
+	    bool __found_monetary = false;
+	    size_t __ci = 0, __mi = 0;
 	    for (size_t __i = 0; __i < _S_categories_size; ++__i)
 	      {
 		const char* __beg = std::strchr(__end + 1, '=') + 1;
@@ -212,6 +217,24 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
 		_M_names[__i] = new char[__end - __beg + 1];
 		std::memcpy(_M_names[__i], __beg, __end - __beg);
 		_M_names[__i][__end - __beg] = '\0';
+		if (!__found_ctype
+		    && *(__beg - 2) == 'E' && *(__beg - 3) == 'P')
+		  {
+		    __found_ctype = true;
+		    __ci = __i;
+		  }
+		else if (!__found_monetary && *(__beg - 2) == 'Y')
+		  {
+		    __found_monetary = true;
+		    __mi = __i;
+		  }
+	      }
+
+	    if (std::strcmp(_M_names[__ci], _M_names[__mi]))
+	      {
+		__smon = _M_names[__mi];
+		__clocm = locale::facet::_S_lc_ctype_c_locale(__cloc,
+							      __smon);
 	      }
 	  }
  
@@ -222,8 +245,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
 	_M_init_facet(new num_get<char>);
 	_M_init_facet(new num_put<char>);
 	_M_init_facet(new std::collate<char>(__cloc));
-	_M_init_facet(new moneypunct<char, false>(__cloc, __s));
-	_M_init_facet(new moneypunct<char, true>(__cloc, __s));
+	_M_init_facet(new moneypunct<char, false>(__cloc, 0));
+	_M_init_facet(new moneypunct<char, true>(__cloc, 0));
 	_M_init_facet(new money_get<char>);
 	_M_init_facet(new money_put<char>);
 	_M_init_facet(new __timepunct<char>(__cloc, __s));
@@ -238,8 +261,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
 	_M_init_facet(new num_get<wchar_t>);
 	_M_init_facet(new num_put<wchar_t>);
 	_M_init_facet(new std::collate<wchar_t>(__cloc));
-	_M_init_facet(new moneypunct<wchar_t, false>(__cloc, __s));
-	_M_init_facet(new moneypunct<wchar_t, true>(__cloc, __s));
+	_M_init_facet(new moneypunct<wchar_t, false>(__clocm, __smon));
+	_M_init_facet(new moneypunct<wchar_t, true>(__clocm, __smon));
 	_M_init_facet(new money_get<wchar_t>);
 	_M_init_facet(new money_put<wchar_t>);
 	_M_init_facet(new __timepunct<wchar_t>(__cloc, __s));
@@ -248,10 +271,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
 	_M_init_facet(new std::messages<wchar_t>(__cloc, __s));
 #endif	  
 	locale::facet::_S_destroy_c_locale(__cloc);
+	if (__clocm != __cloc)
+	  locale::facet::_S_destroy_c_locale(__clocm);
       }
     __catch(...)
       {
 	locale::facet::_S_destroy_c_locale(__cloc);
+	if (__clocm != __cloc)
+	  locale::facet::_S_destroy_c_locale(__clocm);
 	this->~_Impl();
 	__throw_exception_again;
       }	
diff --git a/libstdc++-v3/testsuite/22_locale/locale/cons/40184.cc b/libstdc++-v3/testsuite/22_locale/locale/cons/40184.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d7e30eba1c3c0d824a705b64221adbed65864ad7
--- /dev/null
+++ b/libstdc++-v3/testsuite/22_locale/locale/cons/40184.cc
@@ -0,0 +1,60 @@
+// { dg-require-namedlocale "" }
+
+// Copyright (C) 2009 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 22.1.1.2 locale constructors and destructors [lib.locale.cons]
+
+#include <locale>
+#include <testsuite_hooks.h>
+
+// libstdc++/40184
+void test01()
+{
+#ifdef _GLIBCXX_USE_WCHAR_T
+  using namespace std;
+  bool test __attribute__((unused)) = true;
+
+  locale locf(locale("C"), "ja_JP.eucjp", locale::monetary);
+
+  const moneypunct<wchar_t, false>& mpf = 
+    use_facet<moneypunct<wchar_t, false> >(locf);
+
+  locale locf_copy(locf.name().c_str());
+  const moneypunct<wchar_t, false>& mpf_copy = 
+    use_facet<moneypunct<wchar_t, false> >(locf_copy);
+
+  VERIFY( mpf.curr_symbol() == mpf_copy.curr_symbol() );
+
+  locale loct(locale("C"), "ja_JP.eucjp", locale::monetary);
+
+  const moneypunct<wchar_t, true>& mpt = 
+    use_facet<moneypunct<wchar_t, true> >(loct);
+
+  locale loct_copy(loct.name().c_str());
+  const moneypunct<wchar_t, true>& mpt_copy = 
+    use_facet<moneypunct<wchar_t, true> >(loct_copy);
+
+  VERIFY( mpt.curr_symbol() == mpt_copy.curr_symbol() );
+#endif
+}
+
+int main()
+{
+  test01();
+  return 0;
+}