RFA: Add libstdc++-v3 support for avr 4/7: fix locale_facets_nonio overloading on struct tm using template

Jonathan Wakely jwakely@redhat.com
Wed Oct 22 15:09:00 GMT 2014


[CCing the libstdc++ list, all libstdc++ patches should go there as
well as gcc-patches]

On 21/10/14 17:47 +0100, Joern Rennecke wrote:
>On 21 October 2014 17:29, Jonathan Wakely <jwakely@redhat.com> wrote:
> >> +typedef typeof (((tm*)0)->tm_sec) __tm_small_int;
>>
>>
>> I think this should probably use __typeof__ to work with
>> -Wpedantic-errors
>
>Ok, makes sense, and it's a straightforward change.
>
>>
>>> +#else /* For 100% mangling compatibility, use int directly.  */
>>> +#define __tm_small_int int
>>> +#endif
>>
>>
>> I'd prefer to always use a typedef, which can be a private member of
>> std::time_get, instead of defining a macro (even a macro using a
>> reserved name).
>
>Is the typedef mangling compatible with the original "int" type?

Mangled names use the real type, not typedefs. These are three
declarations of the same function, with _Z1fi as the mangled name:

  typedef int Int;
  typedef int iiiiiiii;
  void f(int);
  void f(Int);
  void f(iiiiiiii);

So you can replace the __tm_small_int macro/typedef with a private
typedef inside time_get:

  private:
#ifdef __AVR__
    // [same comment as you had before ...]
    typedef typeof (((tm*)0)->tm_sec) __tm_small_int;
#else
    typedef int __tm_small_int;
#endif

>>>   /**
>>>    *  @brief  Time format ordering data.
>>>    *  @ingroup locales
>>> @@ -654,14 +663,16 @@ namespace std _GLIBCXX_VISIBILITY(defaul
>>>                   ios_base::iostate& __err, tm* __tm) const;
>>>
>>>       // Extract numeric component of length __len.
>>> +      template <typename _Member_t>
>>>       iter_type
>>> -      _M_extract_num(iter_type __beg, iter_type __end, int& __member,
>>> +      _M_extract_num(iter_type __beg, iter_type __end, _Member_t&
>>> __member,
>>>                      int __min, int __max, size_t __len,
>>>                      ios_base& __io, ios_base::iostate& __err) const;
>>
>>
>> I think this function is exported from the library, so turning it into
>> a template would be an ABI change.
>
>The avr needs both an int and and int8_t __member variant of M_extract_num.
>So do template instantiations mangle differently from directly defined
>functions?

Yes, template<class T> void f(T) instantiated for int has the mangled
name _Z1fIiEvT_ so it is an ABI change to change f(int) to f<int>(int).

>In that case, what is the preferred solution?  Duplicate the code (with all the
>maintenance ugliness that entails)?

Would you have to duplicate it all?

Could you add an overload for int8_t that forwards to the int version?

#ifdef __AVR__
      inline iter_type
      _M_extract_num(iter_type __beg, iter_type __end, int8_t& __member,
                     int __min, int __max, size_t __len,
                     ios_base& __io, ios_base::iostate& __err) const
      {
        int __tmp;
        iter_type __ret = _M_extract_num(__beg, __end, __tmp, __min,
                                         __max, __len, __io, __err);
        if (__err == ios_base::goodbit)
          __member = __tmp;
        return __ret;
      }
#endif

I think you wouldn't need to do any range checking on the value,
because _M_extract_num checks the max value anyway, so there's no risk
that __member will overflow when converted to int8_t.

>Or convert the function definition into an uber-ugly macro that is invoked twice
>to get what the template implementation denies us - metaprogramming with
>mangling compatibility?

That would be uber-ugly :-)

>Define a templated function with a different name, and then define two
>_M_extract_num
>overloads as a wrapper?
>Does that even work in the case  __tm_small_int is a typedef for int?

No, that would be ambiguous (but you could guard the second overload
with #ifdef __AVR__ so it's only defined when it has a different
parameter type).

I think my preference would be the small forwarding function shown
above, would that work?



More information about the Libstdc++ mailing list