Patchwork Implement N3642 - User-defined Literals for Standard Library Types

login
register
mail settings
Submitter Ed Smith-Rowland
Date May 31, 2013, 2:15 p.m.
Message ID <51A8B078.9000308@verizon.net>
Download mbox | patch
Permalink /patch/247964/
State New
Headers show

Comments

Ed Smith-Rowland - May 31, 2013, 2:15 p.m.
Greetings,

This patch implements N3642 - User-defined literals for 
std::chrono::duration and std::basic_string
and N3660 - User-defined literals for std::complex.

User-defined literals were separated into two papers because of some 
controversy about noexcept for complex literals.
If desired, I could split the patch into two bits for the two 
proposals.  OTOH, I'm pretty sure complex literals will make it in.

The patch includes a utility for compile-time parsing of integers which 
is a modified version of that suggested in N3642.
Support for binary literals of the form 0b01010 and support for a digit 
separator are added relative to that paper.
The digit parsing is used in the chrono literals.

One bit: I would like someone to look over my treatment of namespace 
versioning and tell me if that's OK
and/or whether I need to mess with gnu-versioned-namespace.ver.

Otherwise, this builds and tests clean on x86_64-linux.

Thanks,
Ed
2013-05-30  Ed Smith-Rowland  <3dw4rd@verizon.net>

	Implement N3642 - User-defined Literals for Standard Library Types
	Implement N3660 - User-defined Literals for std::complex,
	part 2 of UDL for Standard Library Types
	* include/bits/parse_numbers.h: New.
	* include/std/chrono: Add duration literal operators.
	* include/bits/basic_string.h: Add string literal operators.
	* include/std/complex: Add complex literal operators.
	* include/Makefile.in: Add parse_numbers.h.
	* include/Makefile.am: Ditto.
	* testsuite/20_util/duration/literals/values.cc: New.
	* testsuite/20_util/duration/literals/types.cc: New.
	* testsuite/20_util/duration/requirements/typedefs_neg1.cc: Adjust.
	* testsuite/20_util/duration/requirements/typedefs_neg2.cc: Adjust.
	* testsuite/20_util/duration/requirements/typedefs_neg3.cc: Adjust.
	* testsuite/21_strings/basic_string/literals/values.cc: New.
	* testsuite/21_strings/basic_string/literals/types.cc: New.
	* testsuite/26_numerics/complex/literals/types.cc: New.
	* testsuite/26_numerics/complex/literals/values.cc: New.
	* config/abi/pre/gnu.ver: Add literal operator symbols.
Daniel Kr├╝gler - May 31, 2013, 2:41 p.m.
2013/5/31 Ed Smith-Rowland <3dw4rd@verizon.net>:
> Greetings,
>
> This patch implements N3642 - User-defined literals for
> std::chrono::duration and std::basic_string
> and N3660 - User-defined literals for std::complex.

 N3660 was rejected during the Bristol meeting, the main reason being
the ugliness of the complex-float literal and giving it some time to
find a possible sore language solution. Is there still the idea to add
this now?

- Daniel
Jonathan Wakely - May 31, 2013, 5:12 p.m.
On 31 May 2013 15:15, Ed Smith-Rowland wrote:
> Greetings,
>
> This patch implements N3642 - User-defined literals for
> std::chrono::duration and std::basic_string
> and N3660 - User-defined literals for std::complex.

Great, thanks!

> User-defined literals were separated into two papers because of some
> controversy about noexcept for complex literals.
> If desired, I could split the patch into two bits for the two proposals.
> OTOH, I'm pretty sure complex literals will make it in.

I'm not so sure, and if they do they might use "if" as the suffix
rather than "i_f", so please split this patch so the non-complex parts
can go in.

I don't think you need to touch config/abi/pre/gnu.ver, al lthe new
functions are inline and not exported from the library, so you don't
need to version symbols that aren't in the library (in fact, you
*can't* version symbols that aren't in the library!)

It looks like the changes to existing headers could be simplified by
not closing and reopening the namespace, i.e. instead of:

 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
[...]
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace

+#if __cplusplus > 201103L
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+inline namespace literals {
+inline namespace string_literals {
[...]

Just put the new stuff inside the already open namespace, i.e.

 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 [...]
+#if __cplusplus > 201103L
+
+inline namespace literals {
+inline namespace string_literals {
[...]
+} }
+#endif
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace

Patch

Index: include/bits/parse_numbers.h
===================================================================
--- include/bits/parse_numbers.h	(revision 0)
+++ include/bits/parse_numbers.h	(working copy)
@@ -0,0 +1,417 @@ 
+// Components for compile-time parsing of numbers -*- C++ -*-
+
+// Copyright (C) 2013 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/>.
+
+/** @file bits/parse_numbers.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{chrono}
+ */
+
+#ifndef _PARSE_NUMBERS_H
+#define _PARSE_NUMBERS_H 1
+
+#pragma GCC system_header
+
+// From n3642.pdf except I added binary literals and digit separator '`'.
+
+#if __cplusplus > 201103L
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+namespace __parse_int {
+
+  template<unsigned _Base, char _Dig>
+    struct _Digit;
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '0'>
+    {
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '1'>
+    {
+      static constexpr bool valid{true};
+      static constexpr unsigned value{1};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '2'>
+    {
+      static_assert(_Base > 2, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{2};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '3'>
+    {
+      static_assert(_Base > 3, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{3};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '4'>
+    {
+      static_assert(_Base > 4, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{4};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '5'>
+    {
+      static_assert(_Base > 5, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{5};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '6'>
+    {
+      static_assert(_Base > 6, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{6};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '7'>
+    {
+      static_assert(_Base > 7, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{7};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '8'>
+    {
+      static_assert(_Base > 8, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{8};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, '9'>
+    {
+      static_assert(_Base > 9, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{9};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'a'>
+    {
+      static_assert(_Base > 0xa, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xa};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'A'>
+    {
+      static_assert(_Base > 0xa, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xa};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'b'>
+    {
+      static_assert(_Base > 0xb, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xb};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'B'>
+    {
+      static_assert(_Base > 0xb, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xb};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'c'>
+    {
+      static_assert(_Base > 0xc, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xc};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'C'>
+    {
+      static_assert(_Base > 0xc, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xc};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'd'>
+    {
+      static_assert(_Base > 0xd, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xd};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'D'>
+    {
+      static_assert(_Base > 0xd, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xd};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'e'>
+    {
+      static_assert(_Base > 0xe, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xe};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'E'>
+    {
+      static_assert(_Base > 0xe, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xe};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'f'>
+    {
+      static_assert(_Base > 0xf, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xf};
+    };
+
+  template<unsigned _Base>
+    struct _Digit<_Base, 'F'>
+    {
+      static_assert(_Base > 0xf, "invalid digit");
+      static constexpr bool valid{true};
+      static constexpr unsigned value{0xf};
+    };
+
+  //  Digit separator
+  template<unsigned _Base>
+    struct _Digit<_Base, '`'>
+    {
+      static constexpr bool valid{false};
+      static constexpr unsigned value{0};
+    };
+
+
+//------------------------------------------------------------------------------
+
+  template<unsigned _Base, char _Dig, char... _Digs>
+    struct _Digits_help
+    {
+      static constexpr unsigned
+	value{_Digit<_Base, _Dig>::valid ?
+	      1U + _Digits_help<_Base, _Digs...>::value :
+	      _Digits_help<_Base, _Digs...>::value};
+    };
+
+  template<unsigned _Base, char _Dig>
+    struct _Digits_help<_Base, _Dig>
+    {
+      static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U};
+    };
+
+  template<unsigned _Base, char... _Digs>
+    struct _Digits
+    {
+      static constexpr unsigned value{_Digits_help<_Base, _Digs...>::value};
+    };
+
+  template<unsigned _Base>
+    struct _Digits<_Base>
+    {
+      static constexpr unsigned value{0U};
+    };
+
+//------------------------------------------------------------------------------
+
+  template<unsigned _Base, char _Dig, char... _Digs>
+    struct _Power_help
+    {
+      static constexpr unsigned
+	value{_Digit<_Base, _Dig>::valid ?
+	      _Base * _Power_help<_Base, _Digs...>::value :
+	      _Power_help<_Base, _Digs...>::value};
+    };
+
+  template<unsigned _Base, char _Dig>
+    struct _Power_help<_Base, _Dig>
+    {
+      static constexpr unsigned value{_Digit<_Base, _Dig>::valid ? 1U : 0U};
+    };
+
+  template<unsigned _Base, char... _Digs>
+    struct _Power
+    {
+      static constexpr unsigned value{_Power_help<_Base, _Digs...>::value};
+    };
+
+  template<unsigned _Base>
+    struct _Power<_Base>
+    {
+      static constexpr unsigned value{0U};
+    };
+
+//------------------------------------------------------------------------------
+
+  template<unsigned _Base, unsigned _Pow, char _Dig, char... _Digs>
+    struct _Number_help
+    {
+      static constexpr unsigned
+	value{_Digit<_Base, _Dig>::valid ?
+	      _Pow * _Digit<_Base, _Dig>::value
+	      + _Number_help<_Base, _Pow / _Base, _Digs...>::value :
+	      _Number_help<_Base, _Pow, _Digs...>::value};
+    };
+
+  template<unsigned _Base, unsigned _Pow, char _Dig>
+    struct _Number_help<_Base, _Pow, _Dig>
+    {
+      //static_assert(_Pow == 1U, "power should be one");
+      static constexpr unsigned
+	value{_Digit<_Base, _Dig>::valid ? _Digit<_Base, _Dig>::value : 0U};
+    };
+
+  template<unsigned _Base, char... _Digs>
+    struct _Number
+    {
+      static constexpr unsigned
+	value{_Number_help<_Base, _Power<_Base, _Digs...>::value,
+			   _Digs...>::value};
+    };
+
+  template<unsigned _Base>
+    struct _Number<_Base>
+    {
+      static constexpr unsigned value{0U};
+    };
+
+//------------------------------------------------------------------------------
+//  This _Parse_int is the same 'level' as the old _Base_dispatch.
+
+  template<char... _Digs>
+    struct _Parse_int;
+
+  template<char... _Digs>
+    struct _Parse_int<'0', 'b', _Digs...>
+    {
+      static constexpr unsigned long long
+	value{_Number<2U, _Digs...>::value};
+    };
+
+  template<char... _Digs>
+    struct _Parse_int<'0', 'B', _Digs...>
+    {
+      static constexpr unsigned long long
+	value{_Number<2U, _Digs...>::value};
+    };
+
+  template<char... _Digs>
+    struct _Parse_int<'0', 'x', _Digs...>
+    {
+      static constexpr unsigned long long
+	value{_Number<16U, _Digs...>::value};
+    };
+
+  template<char... _Digs>
+    struct _Parse_int<'0', 'X', _Digs...>
+    {
+      static constexpr unsigned long long
+	value{_Number<16U, _Digs...>::value};
+    };
+
+  template<char... _Digs>
+    struct _Parse_int<'0', _Digs...>
+    {
+      static constexpr unsigned long long
+	value{_Number<8U, _Digs...>::value};
+    };
+
+  template<char... _Digs>
+    struct _Parse_int
+    {
+      static constexpr unsigned long long
+	value{_Number<10U, _Digs...>::value};
+    };
+
+} // namespace __parse_int
+
+
+namespace __select_int {
+
+  template<unsigned long long _Val, typename... _Ints>
+    struct _Select_int_base;
+
+  template<unsigned long long _Val, typename _IntType, typename... _Ints>
+    struct _Select_int_base<_Val, _IntType, _Ints...>
+    : integral_constant
+      <
+	typename conditional
+	<
+	  _Val <= static_cast<unsigned long long>
+		    (std::numeric_limits<_IntType>::max()),
+	  _IntType,
+	  typename _Select_int_base<_Val, _Ints...>::value_type
+	>::type,
+	_Val
+      >
+    { };
+
+  template<unsigned long long _Val>
+    struct _Select_int_base<_Val> : integral_constant<unsigned long long, _Val>
+    { };
+
+  template<char... _Digs>
+    struct _Select_int
+    : _Select_int_base<
+	__parse_int::_Parse_int<_Digs...>::value,
+	unsigned char,
+	unsigned short,
+	unsigned int,
+	unsigned long,
+	unsigned long long
+      >
+    { };
+
+} // namespace __select_int
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // __cplusplus > 201103L
+
+#endif // _PARSE_NUMBERS_H
Index: include/std/chrono
===================================================================
--- include/std/chrono	(revision 199471)
+++ include/std/chrono	(working copy)
@@ -39,6 +39,7 @@ 
 #include <type_traits>
 #include <limits>
 #include <ctime>
+#include <bits/parse_numbers.h> // for literals support.
 
 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
 
@@ -786,4 +787,136 @@ 
 
 #endif // C++11
 
+#if __cplusplus > 201103L
+
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+inline namespace literals {
+inline namespace chrono_literals {
+
+  namespace __detail {
+
+    using namespace __parse_int;
+
+    template<unsigned long long _Val, typename _Dur>
+      struct _Select_type
+      : conditional<
+	  _Val <= static_cast<unsigned long long>
+		    (numeric_limits<typename _Dur::rep>::max()),
+	  _Dur, void>
+      {
+	static constexpr typename _Select_type::type
+	  value{static_cast<typename _Select_type::type>(_Val)};
+      };
+
+    template<unsigned long long _Val, typename _Dur>
+      constexpr typename _Select_type<_Val, _Dur>::type
+      _Select_type<_Val, _Dur>::value;
+
+  } // __detail
+
+  inline constexpr chrono::duration<long double, ratio<3600,1>>
+  operator"" h(long double __hours)
+  { return chrono::duration<long double, ratio<3600,1>>{__hours}; }
+
+  template <char... _Digits>
+    inline constexpr typename
+    __detail::_Select_type<__select_int::_Select_int<_Digits...>::value,
+			   chrono::hours>::type
+    operator"" h()
+    {
+      return __detail::_Select_type<
+			__select_int::_Select_int<_Digits...>::value,
+			chrono::hours>::value;
+    }
+
+  inline constexpr chrono::duration<long double, ratio<60,1>>
+  operator"" min(long double __mins)
+  { return chrono::duration<long double, ratio<60,1>>{__mins}; }
+
+  template <char... _Digits>
+    inline constexpr typename
+    __detail::_Select_type<__select_int::_Select_int<_Digits...>::value,
+			   chrono::minutes>::type
+    operator"" min()
+    {
+      return __detail::_Select_type<
+			__select_int::_Select_int<_Digits...>::value,
+			chrono::minutes>::value;
+    }
+
+  inline constexpr chrono::duration<long double>
+  operator"" s(long double __secs)
+  { return chrono::duration<long double>{__secs}; }
+
+  template <char... _Digits>
+    inline constexpr typename
+    __detail::_Select_type<__select_int::_Select_int<_Digits...>::value,
+			   chrono::seconds>::type
+    operator"" s()
+    {
+      return __detail::_Select_type<
+			__select_int::_Select_int<_Digits...>::value,
+			chrono::seconds>::value;
+    }
+
+  inline constexpr chrono::duration<long double, milli>
+  operator"" ms(long double __msecs)
+  { return chrono::duration<long double, milli>{__msecs}; }
+
+  template <char... _Digits>
+    inline constexpr typename
+    __detail::_Select_type<__select_int::_Select_int<_Digits...>::value,
+			   chrono::milliseconds>::type
+    operator"" ms()
+    {
+      return __detail::_Select_type<
+			__select_int::_Select_int<_Digits...>::value,
+			chrono::milliseconds>::value;
+    }
+
+  inline constexpr chrono::duration<long double, micro>
+  operator"" us(long double __usecs)
+  { return chrono::duration<long double, micro>{__usecs}; }
+
+  template <char... _Digits>
+    inline constexpr typename
+    __detail::_Select_type<__select_int::_Select_int<_Digits...>::value,
+			   chrono::microseconds>::type
+    operator"" us()
+    {
+      return __detail::_Select_type<
+			__select_int::_Select_int<_Digits...>::value,
+			chrono::microseconds>::value;
+    }
+
+  inline constexpr chrono::duration<long double, nano>
+  operator"" ns(long double __nsecs)
+  { return chrono::duration<long double, nano>{__nsecs}; }
+
+  template <char... _Digits>
+    inline constexpr typename
+    __detail::_Select_type<__select_int::_Select_int<_Digits...>::value,
+			   chrono::nanoseconds>::type
+    operator"" ns()
+    {
+      return __detail::_Select_type<
+			__select_int::_Select_int<_Digits...>::value,
+			chrono::nanoseconds>::value;
+    }
+
+} // inline namespace chrono_literals
+} // inline namespace literals
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif //_GLIBCXX_USE_C99_STDINT_TR1
+
+#endif // __cplusplus > 201103L
+
 #endif //_GLIBCXX_CHRONO
Index: include/bits/basic_string.h
===================================================================
--- include/bits/basic_string.h	(revision 199471)
+++ include/bits/basic_string.h	(working copy)
@@ -3106,6 +3106,43 @@ 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
+#if __cplusplus > 201103L
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+inline namespace literals {
+inline namespace string_literals {
+
+  inline basic_string<char>
+  operator"" s(const char* __str, size_t __len)
+  { return basic_string<char>{__str, __len}; }
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+  inline basic_string<wchar_t>
+  operator"" s(const wchar_t* __str, size_t __len)
+  { return basic_string<wchar_t>{__str, __len}; }
+#endif
+
+#ifdef _GLIBCXX_USE_C99_STDINT_TR1
+  inline basic_string<char16_t>
+  operator"" s(const char16_t* __str, size_t __len)
+  { return basic_string<char16_t>{__str, __len}; }
+
+  inline basic_string<char32_t>
+  operator"" s(const char32_t* __str, size_t __len)
+  { return basic_string<char32_t>{__str, __len}; }
+#endif
+
+} // inline namespace string_literals
+} // inline namespace literals
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // __cplusplus > 201103L
+
 #endif // C++11
 
 #endif /* _BASIC_STRING_H */
Index: include/std/complex
===================================================================
--- include/std/complex	(revision 199471)
+++ include/std/complex	(working copy)
@@ -1930,4 +1930,45 @@ 
 
 #endif  // C++11
 
+#if __cplusplus > 201103L
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+inline namespace literals {
+inline namespace complex_literals {
+
+  inline constexpr std::complex<float>
+  operator"" i_f(long double __num)
+  { return std::complex<float>{0.0F, static_cast<float>(__num)}; }
+
+  inline constexpr std::complex<float>
+  operator"" i_f(unsigned long long __num)
+  { return std::complex<float>{0.0F, static_cast<float>(__num)}; }
+
+  inline constexpr std::complex<double>
+  operator"" i(long double __num)
+  { return std::complex<double>{0.0, static_cast<double>(__num)}; }
+
+  inline constexpr std::complex<double>
+  operator"" i(unsigned long long __num)
+  { return std::complex<double>{0.0, static_cast<double>(__num)}; }
+
+  inline constexpr std::complex<long double>
+  operator"" il(long double __num)
+  { return std::complex<long double>{0.0L, __num}; }
+
+  inline constexpr std::complex<long double>
+  operator"" il(unsigned long long __num)
+  { return std::complex<long double>{0.0L, static_cast<long double>(__num)}; }
+
+} // inline namespace complex_literals
+} // inline namespace literals
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // __cplusplus > 201103L
+
 #endif  /* _GLIBCXX_COMPLEX */
Index: include/Makefile.in
===================================================================
--- include/Makefile.in	(revision 199471)
+++ include/Makefile.in	(working copy)
@@ -379,6 +379,7 @@ 
 	${bits_srcdir}/move.h \
 	${bits_srcdir}/ostream.tcc \
 	${bits_srcdir}/ostream_insert.h \
+	${bits_srcdir}/parse_numbers.h \
 	${bits_srcdir}/postypes.h \
 	${bits_srcdir}/ptr_traits.h \
 	${bits_srcdir}/random.h \
Index: include/Makefile.am
===================================================================
--- include/Makefile.am	(revision 199471)
+++ include/Makefile.am	(working copy)
@@ -117,6 +117,7 @@ 
 	${bits_srcdir}/move.h \
 	${bits_srcdir}/ostream.tcc \
 	${bits_srcdir}/ostream_insert.h \
+	${bits_srcdir}/parse_numbers.h \
 	${bits_srcdir}/postypes.h \
 	${bits_srcdir}/ptr_traits.h \
 	${bits_srcdir}/random.h \
Index: testsuite/20_util/duration/literals/values.cc
===================================================================
--- testsuite/20_util/duration/literals/values.cc	(revision 0)
+++ testsuite/20_util/duration/literals/values.cc	(working copy)
@@ -0,0 +1,69 @@ 
+// { dg-do run }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 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/>.
+
+// NOTE: This makes use of the fact that we know how moveable
+// is implemented on string (via swap). If the implementation changed
+// this test may begin to fail.
+
+#include <chrono>
+#include <testsuite_hooks.h>
+
+void
+test03()
+{
+  using namespace std::literals::chrono_literals;
+
+  auto jiffy = 23ns;
+  VERIFY( jiffy == std::chrono::nanoseconds(23) );
+  auto fjiffy = 23.0ns;
+  VERIFY( (fjiffy == std::chrono::duration<long double, std::nano>(23.0L)) );
+  auto blip = 14us;
+  VERIFY( blip == std::chrono::microseconds(14) );
+  auto fblip = 14.0us;
+  VERIFY( (fblip == std::chrono::duration<long double, std::micro>(14.0L)) );
+  auto bit = 77ms;
+  VERIFY( bit == std::chrono::milliseconds(77) );
+  auto fbit = 77.0ms;
+  VERIFY( (fbit == std::chrono::duration<long double, std::milli>(77.0L)) );
+  auto warmup = 33s;
+  VERIFY( warmup == std::chrono::seconds(33) );
+  auto fwarmup = 33.0s;
+  VERIFY( (fwarmup == std::chrono::duration<long double, std::ratio<1,1>>(33.0L)) );
+  auto classtime = 50min;
+  VERIFY( classtime == std::chrono::minutes(50) );
+  auto fclasstime = 50.0min;
+  VERIFY( (fclasstime == std::chrono::duration<long double, std::ratio<60,1>>(50.0L)) );
+  auto longtime = 1h + 30min;
+  VERIFY( longtime == std::chrono::minutes(90) );
+  auto flongtime = 1.0h + 30.0min;
+  VERIFY( (flongtime == std::chrono::duration<long double, std::ratio<3600,1>>(1.0L)
+		      + std::chrono::duration<long double, std::ratio<60,1>>(30.0L)) );
+  VERIFY( (flongtime == std::chrono::duration<long double, std::ratio<60,1>>(90.0L)) );
+  auto workday = 8h;
+  VERIFY( workday == std::chrono::hours(8) );
+  auto fworkday = 8.0h;
+  VERIFY( (fworkday == std::chrono::duration<long double, std::ratio<3600,1>>(8.0L)) );
+}
+
+int
+main()
+{
+  test03();
+}
Index: testsuite/20_util/duration/literals/types.cc
===================================================================
--- testsuite/20_util/duration/literals/types.cc	(revision 0)
+++ testsuite/20_util/duration/literals/types.cc	(working copy)
@@ -0,0 +1,74 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 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/>.
+
+// NOTE: This makes use of the fact that we know how moveable
+// is implemented on string (via swap). If the implementation changed
+// this test may begin to fail.
+
+#include <chrono>
+#include <type_traits>
+
+void
+test03()
+{
+  using namespace std::literals::chrono_literals;
+
+  static_assert(std::is_same<decltype(1h), std::chrono::hours>::value,
+		"1h is std::chrono::hours");
+
+  static_assert(std::is_same<decltype(1.0h),
+	std::chrono::duration<long double, std::ratio<3600L, 1L>>>::value,
+	"1.0h is std::chrono::duration<long double, std::ratio<3600L, 1L>>");
+
+  static_assert(std::is_same<decltype(1min), std::chrono::minutes>::value,
+		"1min is std::chrono::minutes");
+
+  static_assert(std::is_same<decltype(1.0min),
+	std::chrono::duration<long double, std::ratio<60L, 1L>>>::value,
+	"1.0min is std::chrono::duration<long double, std::ratio<60L, 1L>>");
+
+  static_assert(std::is_same<decltype(1s), std::chrono::seconds>::value,
+		"1s is std::chrono::seconds");
+
+  static_assert(std::is_same<decltype(1.0s),
+	std::chrono::duration<long double, std::ratio<1L, 1L>>>::value,
+	"1.0s is std::chrono::duration<long double, std::ratio<1L, 1L>>");
+
+  static_assert(std::is_same<decltype(1ms), std::chrono::milliseconds>::value,
+		"1ms is std::chrono::milliseconds");
+
+  static_assert(std::is_same<decltype(1.0ms),
+	std::chrono::duration<long double, std::ratio<1L, 1000L>>>::value,
+	"1.0ms is std::chrono::duration<long double, std::ratio<1L, 1000L>>");
+
+  static_assert(std::is_same<decltype(1us), std::chrono::microseconds>::value,
+		"1us is std::chrono::microseconds");
+
+  static_assert(std::is_same<decltype(1.0us),
+	std::chrono::duration<long double, std::ratio<1L, 1000000L>>>::value,
+	"1.0us is std::chrono::duration<long double, std::ratio<1L, 1000000L>>");
+
+  static_assert(std::is_same<decltype(1ns), std::chrono::nanoseconds>::value,
+		"1ns is std::chrono::nanoseconds");
+
+  static_assert(std::is_same<decltype(1.0ns),
+	std::chrono::duration<long double, std::ratio<1L, 1000000000L>>>::value,
+	"1.0ns is std::chrono::duration<long double, std::ratio<1L, 1000000000L>>");
+}
Index: testsuite/20_util/duration/requirements/typedefs_neg1.cc
===================================================================
--- testsuite/20_util/duration/requirements/typedefs_neg1.cc	(revision 199471)
+++ testsuite/20_util/duration/requirements/typedefs_neg1.cc	(working copy)
@@ -31,5 +31,5 @@ 
   test_type d;
 }
 
-// { dg-error "rep cannot be a duration" "" { target *-*-* } 245 }
+// { dg-error "rep cannot be a duration" "" { target *-*-* } 246 }
 // { dg-error "required from here" "" { target *-*-* } 31 }
Index: testsuite/20_util/duration/requirements/typedefs_neg2.cc
===================================================================
--- testsuite/20_util/duration/requirements/typedefs_neg2.cc	(revision 199471)
+++ testsuite/20_util/duration/requirements/typedefs_neg2.cc	(working copy)
@@ -32,5 +32,5 @@ 
   test_type d;			// { dg-error "required from here" }
 }
 
-// { dg-error "must be a specialization of ratio" "" { target *-*-* } 246 }
+// { dg-error "must be a specialization of ratio" "" { target *-*-* } 247 }
 // { dg-prune-output "not a member" }
Index: testsuite/20_util/duration/requirements/typedefs_neg3.cc
===================================================================
--- testsuite/20_util/duration/requirements/typedefs_neg3.cc	(revision 199471)
+++ testsuite/20_util/duration/requirements/typedefs_neg3.cc	(working copy)
@@ -33,5 +33,5 @@ 
   test_type d;
 }
 
-// { dg-error "period must be positive" "" { target *-*-* } 248 }
+// { dg-error "period must be positive" "" { target *-*-* } 249 }
 // { dg-error "required from here" "" { target *-*-* } 33 }
Index: testsuite/21_strings/basic_string/literals/values.cc
===================================================================
--- testsuite/21_strings/basic_string/literals/values.cc	(revision 0)
+++ testsuite/21_strings/basic_string/literals/values.cc	(working copy)
@@ -0,0 +1,50 @@ 
+// { dg-do run }
+// { dg-options "-std=gnu++1y" }
+
+// Copyright (C) 2013 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/>.
+
+// NOTE: This makes use of the fact that we know how moveable
+// is implemented on string (via swap). If the implementation changed
+// this test may begin to fail.
+
+#include <string>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  using namespace std::literals::string_literals;
+
+  std::string planet = "Mercury"s;
+  std::wstring wplanet = L"Venus"s;
+  std::string u8planet = u8"Mars"s;
+  std::u16string u16planet = u"Juiter"s;
+  std::u32string u32planet = U"Saturn"s;
+
+  VERIFY( planet == std::string("Mercury") );
+  VERIFY( wplanet == std::wstring(L"Venus") );
+  VERIFY( u8planet == std::string(u8"Mars") );
+  VERIFY( u16planet == std::u16string(u"Juiter") );
+  VERIFY( u32planet == std::u32string(U"Saturn") );
+}
+
+int
+main()
+{
+  test01();
+}
Index: testsuite/21_strings/basic_string/literals/types.cc
===================================================================
--- testsuite/21_strings/basic_string/literals/types.cc	(revision 0)
+++ testsuite/21_strings/basic_string/literals/types.cc	(working copy)
@@ -0,0 +1,47 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 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/>.
+
+// NOTE: This makes use of the fact that we know how moveable
+// is implemented on string (via swap). If the implementation changed
+// this test may begin to fail.
+
+#include <string>
+#include <type_traits>
+
+void
+test01()
+{
+  using namespace std::literals::string_literals;
+
+  static_assert(std::is_same<decltype("Hello"s), std::string>::value,
+		"\"Hello\"s is std::string");
+
+  static_assert(std::is_same<decltype(u8"Hello"s), std::string>::value,
+		"u8\"Hello\"s is std::string");
+
+  static_assert(std::is_same<decltype(L"Hello"s), std::wstring>::value,
+		"L\"Hello\"s is std::wstring");
+
+  static_assert(std::is_same<decltype(u"Hello"s), std::u16string>::value,
+		"u\"Hello\"s is std::u16string");
+
+  static_assert(std::is_same<decltype(U"Hello"s), std::u32string>::value,
+		"U\"Hello\"s is std::u32string");
+}
Index: testsuite/26_numerics/complex/literals/types.cc
===================================================================
--- testsuite/26_numerics/complex/literals/types.cc	(revision 0)
+++ testsuite/26_numerics/complex/literals/types.cc	(working copy)
@@ -0,0 +1,46 @@ 
+// { dg-options "-std=c++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 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/>.
+
+#include <complex>
+#include <type_traits>
+
+void
+test02()
+{
+  using namespace std::literals::complex_literals;
+
+  static_assert(std::is_same<decltype(1.0i_f), std::complex<float>>::value,
+		"1.0i_f is std::complex<float>");
+
+  static_assert(std::is_same<decltype(1i_f), std::complex<float>>::value,
+		"1i_f is std::complex<float>");
+
+  static_assert(std::is_same<decltype(1.0i), std::complex<double>>::value,
+		"1.0i is std::complex<double>");
+
+  static_assert(std::is_same<decltype(1i), std::complex<double>>::value,
+		"1i is std::complex<double>");
+
+  static_assert(std::is_same<decltype(1.0il), std::complex<long double>>::value,
+		"1.0il is std::complex<long double>");
+
+  static_assert(std::is_same<decltype(1il), std::complex<long double>>::value,
+		"1il is std::complex<long double>");
+}
Index: testsuite/26_numerics/complex/literals/values.cc
===================================================================
--- testsuite/26_numerics/complex/literals/values.cc	(revision 0)
+++ testsuite/26_numerics/complex/literals/values.cc	(working copy)
@@ -0,0 +1,48 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 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/>.
+
+#include <complex>
+#include <testsuite_hooks.h>
+
+void
+test02()
+{
+  using namespace std::literals::complex_literals;
+
+  std::complex<float> j1 = 1.0i_f;
+  std::complex<float> k1 = 1i_f;
+  std::complex<double> j2 = 2.0i;
+  std::complex<double> k2 = 2i;
+  std::complex<long double> j4 = 4.0il;
+  std::complex<long double> k4 = 4il;
+
+  VERIFY( j1 == std::complex<float>(0.0F, 1.0F) );
+  VERIFY( k1 == std::complex<float>(0.0F, 1.0F) );
+  VERIFY( j2 == std::complex<double>(0.0, 2.0) );
+  VERIFY( k2 == std::complex<double>(0.0, 2.0) );
+  VERIFY( j4 == std::complex<long double>(0.0L, 4.0L) );
+  VERIFY( k4 == std::complex<long double>(0.0L, 4.0L) );
+}
+
+int
+main()
+{
+  test02();
+}
Index: config/abi/pre/gnu.ver
===================================================================
--- config/abi/pre/gnu.ver	(revision 199471)
+++ config/abi/pre/gnu.ver	(working copy)
@@ -1365,6 +1365,28 @@ 
     # std::get_unexpected()
     _ZSt14get_unexpectedv;
 
+    # std::literals::chrono_literals::operator""()
+    _ZNSt8literals15chrono_literalsli2ns*;
+    _ZNSt8literals15chrono_literalsli2us*;
+    _ZNSt8literals15chrono_literalsli2ms*;
+    _ZNSt8literals15chrono_literalsli1s*;
+    _ZNSt8literals15chrono_literalsli3min*;
+    _ZNSt8literals15chrono_literalsli1h*;
+
+    # std::literals::string_literals::operator""()
+    _ZNSt8literals15string_literalsli1sEPKcm;
+    _ZNSt8literals15string_literalsli1sEPKDim;
+    _ZNSt8literals15string_literalsli1sEPKDsm;
+    _ZNSt8literals15string_literalsli1sEPKwm;
+
+    # std::literals::complex_literals::operator""()
+    _ZNSt8literals16complex_literalsli3i_fEe;
+    _ZNSt8literals16complex_literalsli3i_fEy;
+    _ZNSt8literals16complex_literalsli1iEe;
+    _ZNSt8literals16complex_literalsli1iEy;
+    _ZNSt8literals16complex_literalsli2ilEe;
+    _ZNSt8literals16complex_literalsli2ilEy;
+
 } GLIBCXX_3.4.19;
 
 # Symbols in the support library (libsupc++) have their own tag.