diff mbox

Fix compilation errors with libstdc++v3 for AVR target and allow --enable-libstdcxx

Message ID 20161206184508.GQ6326@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Dec. 6, 2016, 6:45 p.m. UTC
On 16/09/16 02:53 -0300, Felipe Magno de Almeida wrote:
>On Fri, Sep 16, 2016 at 2:42 AM, Marc Glisse <marc.glisse@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 mbox

Patch

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>::