[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 <jwak...@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?

Reply via email to