On 16/09/16 02:53 -0300, Felipe Magno de Almeida wrote:
On Fri, Sep 16, 2016 at 2:42 AM, Marc Glisse <marc.gli...@inria.fr> wrote:
On Thu, 15 Sep 2016, Felipe Magno de Almeida wrote:

+               || sizeof(uint32_t) == sizeof(void*)
+                || sizeof(uint16_t) == sizeof(void*),

Indentation is off?

Call _M_extract_* functions family through temporary int objects


Would it make sense to use a template type instead of int for this
parameter? Or possibly have a typedef that defaults to int (what POSIX
requires). The hard case would be a libc that uses bitfields for the fields
of struct tm (that could save some space), but I don't think anyone does
that.

I've tried both approaches. Templates were causing problems of not
defined instantations because they were being used as ints too
in other _M_extract functions through a tmp integer. And typedef's
caused the same problem of having to use a tmp value of the right
type but for example _M_extract_wday_or_month could not have the
same type (in AVR they do) and I'd have to use a temporary anyway
then.

This was the least intrusive way.

Did you consider something like this?

This should have no overhead for the targets with standard conforming
struct tm, and only uses a temporary variable and additional
assignments for AVR.

It's ugly though.

diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
index 1a4f9a0..30cc57f 100644
--- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc
+++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
@@ -626,6 +626,29 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
     time_get<_CharT, _InIter>::do_date_order() const
     { return time_base::no_order; }
 
+  template<typename _Tp>
+    struct _Tm_member
+    {
+      explicit
+      _Tm_member(_Tp& __mem) : _M_mem(__mem) { _M_tmp = __mem; }
+      ~_Tm_member() { _M_mem = _M_tmp; }
+      operator int&() { return _M_mem; }
+      _Tp& _M_mem;
+      int _M_tmp;
+    };
+
+  template<>
+    struct _Tm_member<int>
+    {
+      explicit
+      _Tm_member(int& __mem) : _M_mem(__mem) { }
+      operator int&() { return _M_mem; }
+      int& _M_mem;
+    };
+
+#define _GLIBCXX_TM_MEM(_M) \
+  static_cast<int&>(_Tm_member<__decltype(__tm->tm_##_M)>(__tm->tm_##_M))
+
   // Expand a strftime format string and parse it.  E.g., do_get_date() may
   // pass %m/%d/%Y => extracted characters.
   template<typename _CharT, typename _InIter>
@@ -659,29 +682,29 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
 		  // Abbreviated weekday name [tm_wday]
 		  const char_type*  __days1[7];
 		  __tp._M_days_abbreviated(__days1);
-		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
-					  7, __io, __tmperr);
+		  __beg = _M_extract_name(__beg, __end, _GLIBCXX_TM_MEM(wday),
+					  __days1, 7, __io, __tmperr);
 		  break;
 		case 'A':
 		  // Weekday name [tm_wday].
 		  const char_type*  __days2[7];
 		  __tp._M_days(__days2);
-		  __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
-					  7, __io, __tmperr);
+		  __beg = _M_extract_name(__beg, __end, _GLIBCXX_TM_MEM(wday),
+					  __days2, 7, __io, __tmperr);
 		  break;
 		case 'h':
 		case 'b':
 		  // Abbreviated month name [tm_mon]
 		  const char_type*  __months1[12];
 		  __tp._M_months_abbreviated(__months1);
-		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
+		  __beg = _M_extract_name(__beg, __end, _GLIBCXX_TM_MEM(mon),
 					  __months1, 12, __io, __tmperr);
 		  break;
 		case 'B':
 		  // Month name [tm_mon].
 		  const char_type*  __months2[12];
 		  __tp._M_months(__months2);
-		  __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
+		  __beg = _M_extract_name(__beg, __end, _GLIBCXX_TM_MEM(mon),
 					  __months2, 12, __io, __tmperr);
 		  break;
 		case 'c':
@@ -693,18 +716,20 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
 		  break;
 		case 'd':
 		  // Day [01, 31]. [tm_mday]
-		  __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
-					 __io, __tmperr);
+		  __beg = _M_extract_num(__beg, __end, _GLIBCXX_TM_MEM(mday),
+					 1, 31, 2, __io, __tmperr);
 		  break;
 		case 'e':
 		  // Day [1, 31], with single digits preceded by
 		  // space. [tm_mday]
 		  if (__ctype.is(ctype_base::space, *__beg))
-		    __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
-					   1, __io, __tmperr);
+		    __beg = _M_extract_num(++__beg, __end,
+					   _GLIBCXX_TM_MEM(mday),
+					   1, 9, 1, __io, __tmperr);
 		  else
-		    __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
-					   2, __io, __tmperr);
+		    __beg = _M_extract_num(__beg, __end,
+					   _GLIBCXX_TM_MEM(mday),
+					   10, 31, 2, __io, __tmperr);
 		  break;
 		case 'D':
 		  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
@@ -715,13 +740,13 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
 		  break;
 		case 'H':
 		  // Hour [00, 23]. [tm_hour]
-		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
-					 __io, __tmperr);
+		  __beg = _M_extract_num(__beg, __end, _GLIBCXX_TM_MEM(hour),
+					 0, 23, 2, __io, __tmperr);
 		  break;
 		case 'I':
 		  // Hour [01, 12]. [tm_hour]
-		  __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
-					 __io, __tmperr);
+		  __beg = _M_extract_num(__beg, __end, _GLIBCXX_TM_MEM(hour),
+					 1, 12, 2, __io, __tmperr);
 		  break;
 		case 'm':
 		  // Month [01, 12]. [tm_mon]
@@ -732,8 +757,8 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
 		  break;
 		case 'M':
 		  // Minute [00, 59]. [tm_min]
-		  __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
-					 __io, __tmperr);
+		  __beg = _M_extract_num(__beg, __end, _GLIBCXX_TM_MEM(min),
+					 0, 59, 2, __io, __tmperr);
 		  break;
 		case 'n':
 		  if (__ctype.narrow(*__beg, 0) == '\n')
@@ -752,11 +777,12 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
 		  // Seconds. [tm_sec]
 		  // [00, 60] in C99 (one leap-second), [00, 61] in C89.
 #if _GLIBCXX_USE_C99
-		  __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
+		  static const int __max_secs = 60;
 #else
-		  __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
+		  static const int __max_secs = 61;
 #endif
-					 __io, __tmperr);
+		  __beg = _M_extract_num(__beg, __end, _GLIBCXX_TM_MEM(sec),
+					 0, __max_secs, 2, __io, __tmperr);
 		  break;
 		case 't':
 		  if (__ctype.narrow(*__beg, 0) == '\t')
@@ -842,6 +868,8 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
       return __beg;
     }
 
+#undef _GLIBCXX_TM_MEM
+
   template<typename _CharT, typename _InIter>
     _InIter
     time_get<_CharT, _InIter>::

Reply via email to