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