diff mbox

LWG 2019 - std::isblank<C>(C, const std::locale&)

Message ID 20141017094122.GR4197@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Oct. 17, 2014, 9:41 a.m. UTC
http://cplusplus.github.io/LWG/lwg-defects.html#2019 

I've checked the relevant _ISblank/_ISBLANK/_CTYPE_B constant on all
targets except VxWorks where I chose something that looks reasonable.
Not all targets reserve a bit for isblank, but this way
ctype_base::blank is always defined, but on some platforms with the
same value as ctype_base::space. That means that on those targets
isblank(c, loc) is equivalent to isspace(c, loc) which is not correct,
but isn't completely crazy either.

Some systems (bionic, newlib, netbsd, openbsd) do define a _B (or
_CTYPE_B) constant, but as it says on netbsd:

/*
 * isblank() is implemented as C function, due to insufficient bitwidth in
 * _ctype_.  Note that _B does not mean isblank - it means isprint && !isgraph.
 */

On those targets there is no bitmask corresponding to the isblank set.
I don't know how to solve that without changing ctype_base::mask to a
wider type, which I'm not planning on doing.

N.B. on other BSDs (freebsd, darwin, dragonfly) _CTYPE_B *does*
correspond to isblank. Portability is fun.

Some implementations of ctype<char>::is(mask, char) and/or
ctype<wchar_t>::do_is defined inline in config/os/*/ctype_inline.h
need the ctype_base::blank mask, but those files get included by C++98
code, so for some targets ctype_base::blank is always defined even in
C++98 mode. Solving that is too difficult.

Tested x86_64-linux, with --enable-clocale={gnu,generic}
and also by hacking configure.host to use config/os/generic, and also
tested on x86_64-netbsd5.1 and x86_64-dragonfly3.6. Something will
probably break on a target I didn't test, but should be easy to fix.

I plan to commit this later today.

Comments

Jonathan Wakely Oct. 20, 2014, 12:34 p.m. UTC | #1
On 17/10/14 10:41 +0100, Jonathan Wakely wrote:
>http://cplusplus.github.io/LWG/lwg-defects.html#2019
>
>I've checked the relevant _ISblank/_ISBLANK/_CTYPE_B constant on all
>targets except VxWorks where I chose something that looks reasonable.
>Not all targets reserve a bit for isblank, but this way
>ctype_base::blank is always defined, but on some platforms with the
>same value as ctype_base::space. That means that on those targets
>isblank(c, loc) is equivalent to isspace(c, loc) which is not correct,
>but isn't completely crazy either.
>
>Some systems (bionic, newlib, netbsd, openbsd) do define a _B (or
>_CTYPE_B) constant, but as it says on netbsd:
>
>/*
>* isblank() is implemented as C function, due to insufficient bitwidth in
>* _ctype_.  Note that _B does not mean isblank - it means isprint && !isgraph.
>*/
>
>On those targets there is no bitmask corresponding to the isblank set.
>I don't know how to solve that without changing ctype_base::mask to a
>wider type, which I'm not planning on doing.
>
>N.B. on other BSDs (freebsd, darwin, dragonfly) _CTYPE_B *does*
>correspond to isblank. Portability is fun.
>
>Some implementations of ctype<char>::is(mask, char) and/or
>ctype<wchar_t>::do_is defined inline in config/os/*/ctype_inline.h
>need the ctype_base::blank mask, but those files get included by C++98
>code, so for some targets ctype_base::blank is always defined even in
>C++98 mode. Solving that is too difficult.
>
>Tested x86_64-linux, with --enable-clocale={gnu,generic}
>and also by hacking configure.host to use config/os/generic, and also
>tested on x86_64-netbsd5.1 and x86_64-dragonfly3.6. Something will
>probably break on a target I didn't test, but should be easy to fix.
>
>I plan to commit this later today.

Committed to trunk.
diff mbox

Patch

commit 1c95ff5159b6a41e4f5f4d4919b8e394905bb9c4
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Oct 16 15:21:02 2014 +0100

    	* src/c++98/Makefile.am: Move ctype.cc, ctype_configure_char.cc and
    	ctype_members.cc to ...
    	* src/c++11/Makefile.am: Here.
    	* src/c++98/Makefile.in: Regenerate.
    	* src/c++11/Makefile.in: Regenerate.
    	* src/c++98/ctype.cc: Move file to ...
    	* src/c++11/ctype.cc: Here, define ctype_base::blank.
    	* config/abi/pre/gnu.ver: Export ctype_base::blank.
    	* config/locale/generic/ctype_members.cc
    	(ctype<wchar_t>::_M_convert_to_wmask): Handle blank. Update comments.
    	* config/locale/gnu/ctype_members.cc
    	(ctype<wchar_t>::_M_convert_to_wmask): Likewise.
    	* config/os/aix/ctype_base.h (ctype_base::blank): Declare.
    	* config/os/bionic/ctype_base.h (ctype_base::blank): Likewise.
    	* config/os/bsd/darwin/ctype_base.h (ctype_base::blank): Declare.
    	* config/os/bsd/darwin/ctype_inline.h (ctype<char>::is): Use blank.
    	(ctype<wchar_t::do_is): Likewise.
    	* config/os/bsd/dragonfly/ctype_base.h (ctype_base::blank): Declare.
    	* config/os/bsd/dragonfly/ctype_inline.h (ctype<char>::is): Use blank.
    	(ctype<wchar_t::do_is): Likewise.
    	* config/os/bsd/freebsd/ctype_base.h (ctype_base::blank): Declare.
    	* config/os/bsd/freebsd/ctype_inline.h (ctype<char>::is): Use blank.
    	(ctype<wchar_t::do_is): Likewise.
    	* config/os/bsd/netbsd/ctype_base.h (ctype_base::blank): Declare.
    	* config/os/bsd/openbsd/ctype_base.h (ctype_base::blank): Likewise.
    	* config/os/djgpp/ctype_base.h (ctype_base::blank): Likewise.
    	* config/os/generic/ctype_base.h (ctype_base::blank): Declare.
    	* config/os/generic/ctype_inline.h (ctype<char>::is): Use blank.
    	* config/os/gnu-linux/ctype_base.h (ctype_base::blank): Declare.
    	* config/os/hpux/ctype_base.h (ctype_base::blank): Likewise.
    	* config/os/mingw32-w64/ctype_base.h (ctype_base::blank): Declare.
    	* config/os/mingw32-w64/ctype_configure_char.cc
    	(ctype<char>::classic_table()): Set blank bit for space and tab.
    	* config/os/mingw32/ctype_base.h (ctype_base::blank): Declare.
    	* config/os/mingw32/ctype_configure_char.cc
    	(ctype<char>::classic_table()): Set blank bit for space and tab.
    	* config/os/newlib/ctype_base.h (ctype_base::blank): Declare.
    	* config/os/qnx/qnx6.1/ctype_base.h (ctype_base::blank): Likewise.
    	* config/os/solaris/solaris2.10/ctype_base.h (ctype_base::blank):
    	Likewise.
    	* config/os/tpf/ctype_base.h (ctype_base::blank): Likewise.
    	* config/os/uclibc/ctype_base.h (ctype_base::blank): Likewise.
    	* config/os/vxworks/ctype_base.h (ctype_base::blank): Likewise.
    	* include/bits/locale_facets.h (isblank): Define.
    	* include/bits/localefwd.h (isblank): Declare.
    	* testsuite/22_locale/classification/isblank.cc: New.
    	* testsuite/22_locale/ctype_base/blank.cc: New.

diff --git a/libstdc++-v3/src/c++11/Makefile.am b/libstdc++-v3/src/c++11/Makefile.am
index 39425d4..c8507ce 100644
--- a/libstdc++-v3/src/c++11/Makefile.am
+++ b/libstdc++-v3/src/c++11/Makefile.am
@@ -27,9 +27,22 @@  noinst_LTLIBRARIES = libc++11convenience.la
 
 headers =
 
+# Source files linked in via configuration/make substitution for a
+# particular host.
+host_sources = \
+	ctype_configure_char.cc \
+	ctype_members.cc
+
+ctype_configure_char.cc: ${glibcxx_srcdir}/$(OS_INC_SRCDIR)/ctype_configure_char.cc
+	$(LN_S) ${glibcxx_srcdir}/$(OS_INC_SRCDIR)/ctype_configure_char.cc . || true
+
+ctype_members.cc: ${glibcxx_srcdir}/$(CCTYPE_CC)
+	$(LN_S) ${glibcxx_srcdir}/$(CCTYPE_CC) . || true
+
 sources = \
 	chrono.cc \
 	condition_variable.cc \
+	ctype.cc \
 	debug.cc \
 	functexcept.cc \
 	functional.cc \
@@ -45,7 +58,8 @@  sources = \
 	shared_ptr.cc \
 	snprintf_lite.cc \
 	system_error.cc \
-	thread.cc
+	thread.cc \
+	${host_sources}
 
 if ENABLE_EXTERN_TEMPLATE
 # XTEMPLATE_FLAGS = -fno-implicit-templates
diff --git a/libstdc++-v3/src/c++11/ctype.cc b/libstdc++-v3/src/c++11/ctype.cc
new file mode 100644
index 0000000..b76962a
--- /dev/null
+++ b/libstdc++-v3/src/c++11/ctype.cc
@@ -0,0 +1,133 @@ 
+// Copyright (C) 1997-2014 Free Software Foundation, Inc.
+//
+// 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+#include <locale>
+#include <cstdlib>
+#include <cstring>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  // Definitions for static const data members of ctype_base.
+  const ctype_base::mask ctype_base::space;
+  const ctype_base::mask ctype_base::print;
+  const ctype_base::mask ctype_base::cntrl;
+  const ctype_base::mask ctype_base::upper;
+  const ctype_base::mask ctype_base::lower;
+  const ctype_base::mask ctype_base::alpha;
+  const ctype_base::mask ctype_base::digit;
+  const ctype_base::mask ctype_base::punct;
+  const ctype_base::mask ctype_base::xdigit;
+  const ctype_base::mask ctype_base::alnum;
+  const ctype_base::mask ctype_base::graph;
+  const ctype_base::mask ctype_base::blank;
+
+  // Definitions for locale::id of standard facets that are specialized.
+  locale::id ctype<char>::id;
+
+#ifdef _GLIBCXX_USE_WCHAR_T  
+  locale::id ctype<wchar_t>::id;
+#endif
+
+  const size_t ctype<char>::table_size;
+
+  ctype<char>::~ctype()
+  { 
+    _S_destroy_c_locale(_M_c_locale_ctype);
+    if (_M_del) 
+      delete[] this->table(); 
+  }
+
+  // Fill in the narrowing cache and flag whether all values are
+  // valid or not.  _M_narrow_ok is set to 2 if memcpy can't
+  // be used.
+  void
+  ctype<char>::
+  _M_narrow_init() const
+  {
+    char __tmp[sizeof(_M_narrow)];
+    for (size_t __i = 0; __i < sizeof(_M_narrow); ++__i)
+      __tmp[__i] = __i;
+    do_narrow(__tmp, __tmp + sizeof(__tmp), 0, _M_narrow);
+    
+    _M_narrow_ok = 1;
+    if (__builtin_memcmp(__tmp, _M_narrow, sizeof(_M_narrow)))
+      _M_narrow_ok = 2;
+    else
+      {
+	// Deal with the special case of zero: renarrow with a
+	// different default and compare.
+	char __c;
+	do_narrow(__tmp, __tmp + 1, 1, &__c);
+	if (__c == 1)
+	  _M_narrow_ok = 2;
+      }
+  }
+
+  void
+  ctype<char>::
+  _M_widen_init() const
+  {
+    char __tmp[sizeof(_M_widen)];
+    for (size_t __i = 0; __i < sizeof(_M_widen); ++__i)
+      __tmp[__i] = __i;
+    do_widen(__tmp, __tmp + sizeof(__tmp), _M_widen);
+    
+    _M_widen_ok = 1;
+    // Set _M_widen_ok to 2 if memcpy can't be used.
+    if (__builtin_memcmp(__tmp, _M_widen, sizeof(_M_widen)))
+      _M_widen_ok = 2;
+  }
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  ctype<wchar_t>::ctype(size_t __refs) 
+  : __ctype_abstract_base<wchar_t>(__refs), 
+  _M_c_locale_ctype(_S_get_c_locale()), _M_narrow_ok(false)
+  { _M_initialize_ctype(); }
+
+  ctype<wchar_t>::ctype(__c_locale __cloc, size_t __refs) 
+  : __ctype_abstract_base<wchar_t>(__refs),
+  _M_c_locale_ctype(_S_clone_c_locale(__cloc)), _M_narrow_ok(false)
+  { _M_initialize_ctype(); }
+
+  ctype<wchar_t>::~ctype() 
+  { _S_destroy_c_locale(_M_c_locale_ctype); }
+
+  ctype_byname<wchar_t>::ctype_byname(const char* __s, size_t __refs)
+  : ctype<wchar_t>(__refs) 
+  { 		
+    if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
+      {
+	this->_S_destroy_c_locale(this->_M_c_locale_ctype);
+	this->_S_create_c_locale(this->_M_c_locale_ctype, __s);
+	this->_M_initialize_ctype();
+      }
+  }
+
+  ctype_byname<wchar_t>::~ctype_byname() 
+  { }
+
+#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/src/c++98/Makefile.am b/libstdc++-v3/src/c++98/Makefile.am
index 6da69f8..9afe904 100644
--- a/libstdc++-v3/src/c++98/Makefile.am
+++ b/libstdc++-v3/src/c++98/Makefile.am
@@ -33,8 +33,6 @@  host_sources = \
 	atomicity.cc \
 	codecvt_members.cc \
 	collate_members.cc \
-	ctype_configure_char.cc \
-	ctype_members.cc \
 	messages_members.cc \
 	monetary_members.cc \
 	numeric_members.cc \
@@ -46,12 +44,6 @@  codecvt_members.cc: ${glibcxx_srcdir}/$(CCODECVT_CC)
 collate_members.cc: ${glibcxx_srcdir}/$(CCOLLATE_CC)
 	$(LN_S) ${glibcxx_srcdir}/$(CCOLLATE_CC) . || true
 
-ctype_configure_char.cc: ${glibcxx_srcdir}/$(OS_INC_SRCDIR)/ctype_configure_char.cc
-	$(LN_S) ${glibcxx_srcdir}/$(OS_INC_SRCDIR)/ctype_configure_char.cc . || true
-
-ctype_members.cc: ${glibcxx_srcdir}/$(CCTYPE_CC)
-	$(LN_S) ${glibcxx_srcdir}/$(CCTYPE_CC) . || true
-
 messages_members.cc: ${glibcxx_srcdir}/$(CMESSAGES_CC)
 	$(LN_S) ${glibcxx_srcdir}/$(CMESSAGES_CC) . || true
 
@@ -104,7 +96,6 @@  sources = \
 	mt_allocator.cc \
 	codecvt.cc \
 	complex_io.cc \
-	ctype.cc \
 	globals_io.cc \
 	hash_tr1.cc \
 	hashtable_tr1.cc \
diff --git a/libstdc++-v3/src/c++98/ctype.cc b/libstdc++-v3/src/c++98/ctype.cc
deleted file mode 100644
index ffeeafc..0000000
--- a/libstdc++-v3/src/c++98/ctype.cc
+++ /dev/null
@@ -1,132 +0,0 @@ 
-// Copyright (C) 1997-2014 Free Software Foundation, Inc.
-//
-// 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.
-
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
-// <http://www.gnu.org/licenses/>.
-
-#include <locale>
-#include <cstdlib>
-#include <cstring>
-
-namespace std _GLIBCXX_VISIBILITY(default)
-{
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
-
-  // Definitions for static const data members of ctype_base.
-  const ctype_base::mask ctype_base::space;
-  const ctype_base::mask ctype_base::print;
-  const ctype_base::mask ctype_base::cntrl;
-  const ctype_base::mask ctype_base::upper;
-  const ctype_base::mask ctype_base::lower;
-  const ctype_base::mask ctype_base::alpha;
-  const ctype_base::mask ctype_base::digit;
-  const ctype_base::mask ctype_base::punct;
-  const ctype_base::mask ctype_base::xdigit;
-  const ctype_base::mask ctype_base::alnum;
-  const ctype_base::mask ctype_base::graph;
-
-  // Definitions for locale::id of standard facets that are specialized.
-  locale::id ctype<char>::id;
-
-#ifdef _GLIBCXX_USE_WCHAR_T  
-  locale::id ctype<wchar_t>::id;
-#endif
-
-  const size_t ctype<char>::table_size;
-
-  ctype<char>::~ctype()
-  { 
-    _S_destroy_c_locale(_M_c_locale_ctype);
-    if (_M_del) 
-      delete[] this->table(); 
-  }
-
-  // Fill in the narrowing cache and flag whether all values are
-  // valid or not.  _M_narrow_ok is set to 2 if memcpy can't
-  // be used.
-  void
-  ctype<char>::
-  _M_narrow_init() const
-  {
-    char __tmp[sizeof(_M_narrow)];
-    for (size_t __i = 0; __i < sizeof(_M_narrow); ++__i)
-      __tmp[__i] = __i;
-    do_narrow(__tmp, __tmp + sizeof(__tmp), 0, _M_narrow);
-    
-    _M_narrow_ok = 1;
-    if (__builtin_memcmp(__tmp, _M_narrow, sizeof(_M_narrow)))
-      _M_narrow_ok = 2;
-    else
-      {
-	// Deal with the special case of zero: renarrow with a
-	// different default and compare.
-	char __c;
-	do_narrow(__tmp, __tmp + 1, 1, &__c);
-	if (__c == 1)
-	  _M_narrow_ok = 2;
-      }
-  }
-
-  void
-  ctype<char>::
-  _M_widen_init() const
-  {
-    char __tmp[sizeof(_M_widen)];
-    for (size_t __i = 0; __i < sizeof(_M_widen); ++__i)
-      __tmp[__i] = __i;
-    do_widen(__tmp, __tmp + sizeof(__tmp), _M_widen);
-    
-    _M_widen_ok = 1;
-    // Set _M_widen_ok to 2 if memcpy can't be used.
-    if (__builtin_memcmp(__tmp, _M_widen, sizeof(_M_widen)))
-      _M_widen_ok = 2;
-  }
-
-#ifdef _GLIBCXX_USE_WCHAR_T
-  ctype<wchar_t>::ctype(size_t __refs) 
-  : __ctype_abstract_base<wchar_t>(__refs), 
-  _M_c_locale_ctype(_S_get_c_locale()), _M_narrow_ok(false)
-  { _M_initialize_ctype(); }
-
-  ctype<wchar_t>::ctype(__c_locale __cloc, size_t __refs) 
-  : __ctype_abstract_base<wchar_t>(__refs),
-  _M_c_locale_ctype(_S_clone_c_locale(__cloc)), _M_narrow_ok(false)
-  { _M_initialize_ctype(); }
-
-  ctype<wchar_t>::~ctype() 
-  { _S_destroy_c_locale(_M_c_locale_ctype); }
-
-  ctype_byname<wchar_t>::ctype_byname(const char* __s, size_t __refs)
-  : ctype<wchar_t>(__refs) 
-  { 		
-    if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
-      {
-	this->_S_destroy_c_locale(this->_M_c_locale_ctype);
-	this->_S_create_c_locale(this->_M_c_locale_ctype, __s);
-	this->_M_initialize_ctype();
-      }
-  }
-
-  ctype_byname<wchar_t>::~ctype_byname() 
-  { }
-
-#endif
-
-_GLIBCXX_END_NAMESPACE_VERSION
-} // namespace
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 0559444..4c6d994 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -513,7 +513,7 @@  GLIBCXX_3.4 {
     _ZNSt5ctypeI[cw]*;
 
     # std::ctype_base
-    _ZNSt10ctype_base*;
+    _ZNSt10ctype_base[56][ac-z]*;
 
     # std::ctype_byname
     _ZNSt12ctype_bynameI[cw]*;
@@ -1473,6 +1473,9 @@  GLIBCXX_3.4.21 {
     # std::basic_ios::operator bool() const
     _ZNKSt9basic_iosI[cw]St11char_traitsI[cw]EEcvbEv;
 
+    # std::ctype_base::blank
+    _ZNSt10ctype_base5blankE;
+
 } GLIBCXX_3.4.20;
 
 
diff --git a/libstdc++-v3/config/locale/generic/ctype_members.cc b/libstdc++-v3/config/locale/generic/ctype_members.cc
index 126c0f3..367a893 100644
--- a/libstdc++-v3/config/locale/generic/ctype_members.cc
+++ b/libstdc++-v3/config/locale/generic/ctype_members.cc
@@ -93,7 +93,12 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	__ret = wctype("graph");
 	break;
       default:
-	__ret = __wmask_type();
+	// For some targets ctype_base::blank == ctype_base::space so check
+	// here to avoid a duplicate case error.
+	if (__m == blank)
+	  __ret = wctype("blank");
+	else
+	  __ret = __wmask_type();
       }
     return __ret;
   };
@@ -133,7 +138,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   do_is(mask __m, char_type __c) const
   { 
     bool __ret = false;
-    // Generically, 15 (instead of 10) since we don't know the numerical
+    // Generically, 15 (instead of 11) since we don't know the numerical
     // encoding of the various categories in /usr/include/ctype.h.
     const size_t __bitmasksize = 15; 
     for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
@@ -152,7 +157,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
     for (;__lo < __hi; ++__vec, ++__lo)
       {
-	// Generically, 15 (instead of 10) since we don't know the numerical
+	// Generically, 15 (instead of 11) since we don't know the numerical
 	// encoding of the various categories in /usr/include/ctype.h.
 	const size_t __bitmasksize = 15; 
 	mask __m = 0;
diff --git a/libstdc++-v3/config/locale/gnu/ctype_members.cc b/libstdc++-v3/config/locale/gnu/ctype_members.cc
index 043a53a..cd9604c 100644
--- a/libstdc++-v3/config/locale/gnu/ctype_members.cc
+++ b/libstdc++-v3/config/locale/gnu/ctype_members.cc
@@ -94,6 +94,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       case graph:
 	__ret = __wctype_l("graph", _M_c_locale_ctype);
 	break;
+      case blank:
+	__ret = __wctype_l("blank", _M_c_locale_ctype);
+	break;
       default:
 	__ret = __wmask_type();
       }
@@ -144,8 +147,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __ret = __iswctype_l(__c, _M_wmask[5], _M_c_locale_ctype);
     else
       {
-	// Highest bitmask in ctype_base == 10, but extra in "C"
-	// library for blank.
+	// Highest bitmask in ctype_base == 11
 	const size_t __bitmasksize = 11;
 	for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
 	  if (__m & _M_bit[__bitcur])
@@ -168,8 +170,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
     for (; __lo < __hi; ++__vec, ++__lo)
       {
-	// Highest bitmask in ctype_base == 10, but extra in "C"
-	// library for blank.
+	// Highest bitmask in ctype_base == 11
 	const size_t __bitmasksize = 11; 
 	mask __m = 0;
 	for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
diff --git a/libstdc++-v3/config/os/aix/ctype_base.h b/libstdc++-v3/config/os/aix/ctype_base.h
index 012375f..de78205 100644
--- a/libstdc++-v3/config/os/aix/ctype_base.h
+++ b/libstdc++-v3/config/os/aix/ctype_base.h
@@ -52,6 +52,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _ISCNTRL;
     static const mask punct 	= _ISPUNCT;
     static const mask alnum 	= _ISALPHA | _ISDIGIT;
+#if __cplusplus >= 201103L
+    static const mask blank	= _ISBLANK;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/bionic/ctype_base.h b/libstdc++-v3/config/os/bionic/ctype_base.h
index 597509b..1b441a6 100644
--- a/libstdc++-v3/config/os/bionic/ctype_base.h
+++ b/libstdc++-v3/config/os/bionic/ctype_base.h
@@ -26,9 +26,7 @@ 
 // ISO C++ 14882: 22.1  Locales
 //
 
-// Information as gleaned from /usr/include/ctype.h, for solaris2.5.1
-
-// Support for Solaris 2.5.1
+// Information as gleaned from /usr/include/ctype.h
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -54,6 +52,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _C;
     static const mask punct 	= _P;
     static const mask alnum 	= _U | _L | _N;
+#if __cplusplus >= 201103L
+    static const mask blank 	= space;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/bsd/darwin/ctype_base.h b/libstdc++-v3/config/os/bsd/darwin/ctype_base.h
index edf23e1..b77ac70 100644
--- a/libstdc++-v3/config/os/bsd/darwin/ctype_base.h
+++ b/libstdc++-v3/config/os/bsd/darwin/ctype_base.h
@@ -54,6 +54,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _CTYPE_C;
     static const mask punct 	= _CTYPE_P;
     static const mask alnum 	= _CTYPE_A | _CTYPE_D;
+    static const mask blank	= _CTYPE_B;
 #else
     // Older versions, including Free BSD 3.4, use this style of define.
     static const mask upper    	= _U;
@@ -67,6 +68,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _C;
     static const mask punct 	= _P;
     static const mask alnum 	= _A | _D;
+    static const mask blank	= _B;
 #endif
   };
 
diff --git a/libstdc++-v3/config/os/bsd/darwin/ctype_inline.h b/libstdc++-v3/config/os/bsd/darwin/ctype_inline.h
index 1170e4e..5ae5789 100644
--- a/libstdc++-v3/config/os/bsd/darwin/ctype_inline.h
+++ b/libstdc++-v3/config/os/bsd/darwin/ctype_inline.h
@@ -60,7 +60,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	{
 #if defined (_CTYPE_S) || defined (__istype)
 	  *__vec = __maskrune (*__low, upper | lower | alpha | digit | xdigit
-			       | space | print | graph | cntrl | punct | alnum);
+			       | space | print | graph | cntrl | punct | alnum
+			       | blank);
 #else
 	  mask __m = 0;
 	  if (this->is(upper, *__low)) __m |= upper;
@@ -75,6 +76,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  if (this->is(punct, *__low)) __m |= punct;
 	  // Do not include explicit line for alnum mask since it is a
 	  // pure composite of masks on FreeBSD.
+	  if (this->is(blank, *__low)) __m |= blank;
 	  *__vec = __m;
 #endif
 	}
@@ -123,7 +125,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
     for (; __lo < __hi; ++__vec, ++__lo)
       *__vec = __maskrune (*__lo, upper | lower | alpha | digit | xdigit
-			   | space | print | graph | cntrl | punct | alnum);
+			   | space | print | graph | cntrl | punct | alnum
+			   | blank);
     return __hi;
   }
   
diff --git a/libstdc++-v3/config/os/bsd/dragonfly/ctype_base.h b/libstdc++-v3/config/os/bsd/dragonfly/ctype_base.h
index a95b248..856da8e 100644
--- a/libstdc++-v3/config/os/bsd/dragonfly/ctype_base.h
+++ b/libstdc++-v3/config/os/bsd/dragonfly/ctype_base.h
@@ -52,6 +52,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _CTYPE_C;
     static const mask punct 	= _CTYPE_P;
     static const mask alnum 	= _CTYPE_A | _CTYPE_D;
+    static const mask blank	= _CTYPE_B;
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/bsd/dragonfly/ctype_inline.h b/libstdc++-v3/config/os/bsd/dragonfly/ctype_inline.h
index 984665e..8e0f078 100644
--- a/libstdc++-v3/config/os/bsd/dragonfly/ctype_inline.h
+++ b/libstdc++-v3/config/os/bsd/dragonfly/ctype_inline.h
@@ -59,7 +59,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       for (;__low < __high; ++__vec, ++__low)
 	{
 	  *__vec = __maskrune (*__low, upper | lower | alpha | digit | xdigit
-			       | space | print | graph | cntrl | punct | alnum);
+			       | space | print | graph | cntrl | punct | alnum
+			       | blank);
 	}
     return __high;
   }
@@ -106,7 +107,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
     for (; __lo < __hi; ++__vec, ++__lo)
       *__vec = __maskrune (*__lo, upper | lower | alpha | digit | xdigit
-			   | space | print | graph | cntrl | punct | alnum);
+			   | space | print | graph | cntrl | punct | alnum
+			   | blank);
     return __hi;
   }
 
diff --git a/libstdc++-v3/config/os/bsd/freebsd/ctype_base.h b/libstdc++-v3/config/os/bsd/freebsd/ctype_base.h
index 9bd2a18..ba6433a 100644
--- a/libstdc++-v3/config/os/bsd/freebsd/ctype_base.h
+++ b/libstdc++-v3/config/os/bsd/freebsd/ctype_base.h
@@ -56,6 +56,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _CTYPE_C;
     static const mask punct 	= _CTYPE_P;
     static const mask alnum 	= _CTYPE_A | _CTYPE_D;
+    static const mask blank	= _CTYPE_B;
 #else
     // Older versions, including Free BSD 3.4, use this style of define.
     static const mask upper    	= _U;
@@ -69,6 +70,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _C;
     static const mask punct 	= _P;
     static const mask alnum 	= _A | _D;
+    static const mask blank	= _B;
 #endif
   };
 
diff --git a/libstdc++-v3/config/os/bsd/freebsd/ctype_inline.h b/libstdc++-v3/config/os/bsd/freebsd/ctype_inline.h
index 939304a..0153099 100644
--- a/libstdc++-v3/config/os/bsd/freebsd/ctype_inline.h
+++ b/libstdc++-v3/config/os/bsd/freebsd/ctype_inline.h
@@ -60,7 +60,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	{
 #if defined (_CTYPE_S) || defined (__istype)
 	  *__vec = __maskrune (*__low, upper | lower | alpha | digit | xdigit
-			       | space | print | graph | cntrl | punct | alnum);
+			       | space | print | graph | cntrl | punct | alnum
+			       | blank);
 #else
 	  mask __m = 0;
 	  if (this->is(upper, *__low)) __m |= upper;
@@ -75,6 +76,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  if (this->is(punct, *__low)) __m |= punct;
 	  // Do not include explicit line for alnum mask since it is a
 	  // pure composite of masks on FreeBSD.
+	  if (this->is(blank, *__low)) __m |= blank;
 	  *__vec = __m;
 #endif
 	}
@@ -123,7 +125,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
     for (; __lo < __hi; ++__vec, ++__lo)
       *__vec = __maskrune (*__lo, upper | lower | alpha | digit | xdigit
-			   | space | print | graph | cntrl | punct | alnum);
+			   | space | print | graph | cntrl | punct | alnum
+			   | blank);
     return __hi;
   }
 
diff --git a/libstdc++-v3/config/os/bsd/netbsd/ctype_base.h b/libstdc++-v3/config/os/bsd/netbsd/ctype_base.h
index f441d74..6cd339f 100644
--- a/libstdc++-v3/config/os/bsd/netbsd/ctype_base.h
+++ b/libstdc++-v3/config/os/bsd/netbsd/ctype_base.h
@@ -70,6 +70,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask punct 	= _CTYPE_P;
     static const mask alnum 	= _CTYPE_U | _CTYPE_L | _CTYPE_N;
 #endif
+#if __cplusplus >= 201103L
+    static const mask blank 	= space;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/bsd/openbsd/ctype_base.h b/libstdc++-v3/config/os/bsd/openbsd/ctype_base.h
index 3599c95..ad9799a 100644
--- a/libstdc++-v3/config/os/bsd/openbsd/ctype_base.h
+++ b/libstdc++-v3/config/os/bsd/openbsd/ctype_base.h
@@ -53,6 +53,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl	= _C;
     static const mask punct	= _P;
     static const mask alnum	= _U | _L | _N;
+#if __cplusplus >= 201103L
+    static const mask blank	= space;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/djgpp/ctype_base.h b/libstdc++-v3/config/os/djgpp/ctype_base.h
index b4befe1..1be9767 100644
--- a/libstdc++-v3/config/os/djgpp/ctype_base.h
+++ b/libstdc++-v3/config/os/djgpp/ctype_base.h
@@ -51,6 +51,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask xdigit = __dj_ISXDIGIT;   // Hexadecimal numeric
     static const mask alnum = __dj_ISALPHA | __dj_ISDIGIT;  // Alphanumeric
     static const mask graph = __dj_ISALPHA | __dj_ISDIGIT | __dj_ISPUNCT;  // Graphical
+#if __cplusplus >= 201103L
+    static const mask blank	= __dj_ISBLANK;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/generic/ctype_base.h b/libstdc++-v3/config/os/generic/ctype_base.h
index 8a8606b..c70c03f 100644
--- a/libstdc++-v3/config/os/generic/ctype_base.h
+++ b/libstdc++-v3/config/os/generic/ctype_base.h
@@ -52,6 +52,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= 1 << 8;
     static const mask punct 	= 1 << 9;
     static const mask alnum 	= (1 << 2) | (1 << 3);  // alpha|digit
+    static const mask blank	= 1 << 10;
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/generic/ctype_inline.h b/libstdc++-v3/config/os/generic/ctype_inline.h
index d150f31..31c8c57 100644
--- a/libstdc++-v3/config/os/generic/ctype_inline.h
+++ b/libstdc++-v3/config/os/generic/ctype_inline.h
@@ -97,6 +97,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		  case graph:
 		    __testis = isgraph(__c);
 		    break;
+#ifdef _GLIBCXX_USE_C99_CTYPE_TR1
+		  case blank:
+		    __testis = isblank(__c);
+		    break;
+#endif
 		  default:
 		    __testis = false;
 		    break;
@@ -117,7 +122,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	*__vec++ = _M_table[static_cast<unsigned char>(*__low++)];
     else
       {
-	// Highest bitmask in ctype_base == 10.
+	// Highest bitmask in ctype_base == 11.
 	const size_t __bitmasksize = 15; 
 	for (;__low < __high; ++__vec, ++__low)
 	  {
diff --git a/libstdc++-v3/config/os/gnu-linux/ctype_base.h b/libstdc++-v3/config/os/gnu-linux/ctype_base.h
index 8cd1d46..e28ed94 100644
--- a/libstdc++-v3/config/os/gnu-linux/ctype_base.h
+++ b/libstdc++-v3/config/os/gnu-linux/ctype_base.h
@@ -57,6 +57,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _IScntrl;
     static const mask punct 	= _ISpunct;
     static const mask alnum 	= _ISalpha | _ISdigit;
+#if __cplusplus >= 201103L
+    static const mask blank	= _ISblank;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/hpux/ctype_base.h b/libstdc++-v3/config/os/hpux/ctype_base.h
index f8b0f7c..b093ffb 100644
--- a/libstdc++-v3/config/os/hpux/ctype_base.h
+++ b/libstdc++-v3/config/os/hpux/ctype_base.h
@@ -52,6 +52,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl     = _ISCNTRL;
     static const mask punct     = _ISPUNCT;
     static const mask alnum     = _ISALPHA | _ISDIGIT;
+#if __cplusplus >= 201103L
+    static const mask blank	= _ISBLANK;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/mingw32-w64/ctype_base.h b/libstdc++-v3/config/os/mingw32-w64/ctype_base.h
index 7803422..0780091 100644
--- a/libstdc++-v3/config/os/mingw32-w64/ctype_base.h
+++ b/libstdc++-v3/config/os/mingw32-w64/ctype_base.h
@@ -58,6 +58,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl	= 1 << 8;
     static const mask punct 	= 1 << 9;
     static const mask alnum	= (1 << 2) | (1 << 3);  // alpha|digit
+#if __cplusplus >= 201103L
+    static const mask blank	= 1 << 10;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/mingw32-w64/ctype_configure_char.cc b/libstdc++-v3/config/os/mingw32-w64/ctype_configure_char.cc
index 19456e0..b1b4fa0 100644
--- a/libstdc++-v3/config/os/mingw32-w64/ctype_configure_char.cc
+++ b/libstdc++-v3/config/os/mingw32-w64/ctype_configure_char.cc
@@ -54,7 +54,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       cntrl /* ^F */,
       cntrl /* ^G */,
       cntrl /* ^H */,
-      ctype_base::mask(space | cntrl) /* tab */,
+      ctype_base::mask(space | cntrl | blank) /* tab */,
       ctype_base::mask(space | cntrl) /* LF */,
       ctype_base::mask(space | cntrl) /* ^K */,
       ctype_base::mask(space | cntrl) /* FF */,
@@ -77,7 +77,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       cntrl /* ^] */,
       cntrl /* ^^ */,
       cntrl /* ^_ */,
-      ctype_base::mask(space | print) /*   */,
+      ctype_base::mask(space | print | blank) /*   */,
       ctype_base::mask(punct | print) /* ! */,
       ctype_base::mask(punct | print) /* " */,
       ctype_base::mask(punct | print) /* # */,
diff --git a/libstdc++-v3/config/os/mingw32/ctype_base.h b/libstdc++-v3/config/os/mingw32/ctype_base.h
index 7803422..0780091 100644
--- a/libstdc++-v3/config/os/mingw32/ctype_base.h
+++ b/libstdc++-v3/config/os/mingw32/ctype_base.h
@@ -58,6 +58,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl	= 1 << 8;
     static const mask punct 	= 1 << 9;
     static const mask alnum	= (1 << 2) | (1 << 3);  // alpha|digit
+#if __cplusplus >= 201103L
+    static const mask blank	= 1 << 10;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/mingw32/ctype_configure_char.cc b/libstdc++-v3/config/os/mingw32/ctype_configure_char.cc
index 19456e0..b1b4fa0 100644
--- a/libstdc++-v3/config/os/mingw32/ctype_configure_char.cc
+++ b/libstdc++-v3/config/os/mingw32/ctype_configure_char.cc
@@ -54,7 +54,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       cntrl /* ^F */,
       cntrl /* ^G */,
       cntrl /* ^H */,
-      ctype_base::mask(space | cntrl) /* tab */,
+      ctype_base::mask(space | cntrl | blank) /* tab */,
       ctype_base::mask(space | cntrl) /* LF */,
       ctype_base::mask(space | cntrl) /* ^K */,
       ctype_base::mask(space | cntrl) /* FF */,
@@ -77,7 +77,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       cntrl /* ^] */,
       cntrl /* ^^ */,
       cntrl /* ^_ */,
-      ctype_base::mask(space | print) /*   */,
+      ctype_base::mask(space | print | blank) /*   */,
       ctype_base::mask(punct | print) /* ! */,
       ctype_base::mask(punct | print) /* " */,
       ctype_base::mask(punct | print) /* # */,
diff --git a/libstdc++-v3/config/os/newlib/ctype_base.h b/libstdc++-v3/config/os/newlib/ctype_base.h
index 29f527d..1bf5beb 100644
--- a/libstdc++-v3/config/os/newlib/ctype_base.h
+++ b/libstdc++-v3/config/os/newlib/ctype_base.h
@@ -26,10 +26,8 @@ 
 // ISO C++ 14882: 22.1  Locales
 //
   
-// Information as gleaned from /usr/include/ctype.h, for solaris2.5.1
+// Information as gleaned from /usr/include/ctype.h
 
-// Support for Solaris 2.5.1
-  
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -54,6 +52,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _C;
     static const mask punct 	= _P;
     static const mask alnum 	= _U | _L | _N;
+#if __cplusplus >= 201103L
+    static const mask blank 	= space;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/qnx/qnx6.1/ctype_base.h b/libstdc++-v3/config/os/qnx/qnx6.1/ctype_base.h
index bf7c756..c5e1182 100644
--- a/libstdc++-v3/config/os/qnx/qnx6.1/ctype_base.h
+++ b/libstdc++-v3/config/os/qnx/qnx6.1/ctype_base.h
@@ -57,6 +57,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _BB;
     static const mask punct 	= _PU;
     static const mask alnum 	= _DI | _LO | _UP | _XA;
+#if __cplusplus >= 201103L
+    static const mask blank	= _SP | _XB;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/solaris/solaris2.10/ctype_base.h b/libstdc++-v3/config/os/solaris/solaris2.10/ctype_base.h
index c584fee..893b732 100644
--- a/libstdc++-v3/config/os/solaris/solaris2.10/ctype_base.h
+++ b/libstdc++-v3/config/os/solaris/solaris2.10/ctype_base.h
@@ -54,6 +54,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _ISCNTRL;
     static const mask punct 	= _ISPUNCT;
     static const mask alnum 	= _ISALPHA | _ISDIGIT;
+#if __cplusplus >= 201103L
+    static const mask blank	= _ISBLANK;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/tpf/ctype_base.h b/libstdc++-v3/config/os/tpf/ctype_base.h
index d3b2a25..2089358 100644
--- a/libstdc++-v3/config/os/tpf/ctype_base.h
+++ b/libstdc++-v3/config/os/tpf/ctype_base.h
@@ -52,6 +52,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _IScntrl;
     static const mask punct 	= _ISpunct;
     static const mask alnum 	= _ISalpha | _ISdigit;
+#if __cplusplus >= 201103L
+    static const mask blank	= _ISblank;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/uclibc/ctype_base.h b/libstdc++-v3/config/os/uclibc/ctype_base.h
index 39453afe..86a6007 100644
--- a/libstdc++-v3/config/os/uclibc/ctype_base.h
+++ b/libstdc++-v3/config/os/uclibc/ctype_base.h
@@ -59,6 +59,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _IScntrl;
     static const mask punct 	= _ISpunct;
     static const mask alnum 	= _ISalpha | _ISdigit;
+#if __cplusplus >= 201103L
+    static const mask blank	= _ISblank;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/config/os/vxworks/ctype_base.h b/libstdc++-v3/config/os/vxworks/ctype_base.h
index bc105a2..4f92412 100644
--- a/libstdc++-v3/config/os/vxworks/ctype_base.h
+++ b/libstdc++-v3/config/os/vxworks/ctype_base.h
@@ -53,6 +53,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask cntrl 	= _C_CONTROL;
     static const mask punct 	= _C_PUNCT;
     static const mask alnum 	= _C_UPPER | _C_LOWER | _C_NUMBER;
+#if __cplusplus >= 201103L
+    static const mask blank	= _C_WHITE_SPACE;
+#endif
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h
index 453bbed..234693b 100644
--- a/libstdc++-v3/include/bits/locale_facets.h
+++ b/libstdc++-v3/include/bits/locale_facets.h
@@ -2590,6 +2590,14 @@  _GLIBCXX_END_NAMESPACE_LDBL
     isgraph(_CharT __c, const locale& __loc)
     { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::graph, __c); }
 
+#if __cplusplus >= 201103L
+  /// Convenience interface to ctype.is(ctype_base::blank, __c).
+  template<typename _CharT>
+    inline bool
+    isblank(_CharT __c, const locale& __loc)
+    { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::blank, __c); }
+#endif
+
   /// Convenience interface to ctype.toupper(__c).
   template<typename _CharT>
     inline _CharT
diff --git a/libstdc++-v3/include/bits/localefwd.h b/libstdc++-v3/include/bits/localefwd.h
index f9983c9..3025c22 100644
--- a/libstdc++-v3/include/bits/localefwd.h
+++ b/libstdc++-v3/include/bits/localefwd.h
@@ -107,6 +107,12 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     bool
     isgraph(_CharT, const locale&);
 
+#if __cplusplus >= 201103L
+  template<typename _CharT>
+    bool
+    isblank(_CharT, const locale&);
+#endif
+
   template<typename _CharT>
     _CharT
     toupper(_CharT, const locale&);
diff --git a/libstdc++-v3/testsuite/22_locale/classification/isblank.cc b/libstdc++-v3/testsuite/22_locale/classification/isblank.cc
new file mode 100644
index 0000000..0c7adc2
--- /dev/null
+++ b/libstdc++-v3/testsuite/22_locale/classification/isblank.cc
@@ -0,0 +1,49 @@ 
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// 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/>.
+
+// { dg-options " -std=gnu++11 " }
+
+// 22.3.3.1 Character classification [classification]
+
+#include <locale>
+#include <testsuite_hooks.h>
+
+typedef char char_type;
+
+void
+test01()
+{
+  bool test __attribute__((unused)) = true;
+  VERIFY( std::isblank(' ', std::locale::classic()) );
+  VERIFY( std::isblank('\t', std::locale::classic()) );
+}
+
+void
+test02()
+{
+#ifdef _GLIBCXX_USE_WCHAR_T
+  bool test __attribute__((unused)) = true;
+  VERIFY( std::isblank(L' ', std::locale::classic()) );
+  VERIFY( std::isblank(L'\t', std::locale::classic()) );
+#endif
+}
+
+int main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/22_locale/ctype_base/blank.cc b/libstdc++-v3/testsuite/22_locale/ctype_base/blank.cc
new file mode 100644
index 0000000..cfd02a4
--- /dev/null
+++ b/libstdc++-v3/testsuite/22_locale/ctype_base/blank.cc
@@ -0,0 +1,28 @@ 
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// 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/>.
+
+// { dg-options "-std=gnu++11" }
+// { dg-do compile }
+
+#include <locale>
+
+void
+test01()
+{
+  const std::ctype_base::mask* blank __attribute__((unused));
+  blank = &std::ctype_base::blank;
+}