Tested powerpc64le-linux. Pushed to trunk.

-- >8 --

When __LONG_DOUBLE_IEEE128__ is defined we need to declare a wrapper for
Glibc's 'snprintf' symbol, so we can call the original definition that
works with the IBM128 format of long double. Because we were declaring
the wrapper using __typeof__(__builtin_snprintf) it inherited the
__attribute__((format(printf, 3, 4))) decoration, and then we got a
warning for calling that wrapper with an __ibm128 argument for a %Lf
conversion specifier. The warning is bogus, because the function we're
calling really does want __ibm128 for %Lf, but there's no "printf but
with a different long double format" archetype for the attribute.

In r15-4039-g28911f626864e7 I added a diagnostic pragma to suppress the
warning, but it would be better to just declare the wrapper without the
attribute, and not have to suppress a warning for code that we know is
actually correct.

libstdc++-v3/ChangeLog:

        PR libstdc++/116969
        * include/bits/locale_facets_nonio.tcc (money_put::__do_put):
        Remove diagnostic pragmas.
        (__glibcxx_snprintfibm128): Declare type manually, instead of
        using __typeof__(__builtin_snprintf).
---
 libstdc++-v3/include/bits/locale_facets_nonio.tcc | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc 
b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
index 53553d113b2..863350a85f1 100644
--- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc
+++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
@@ -637,10 +637,14 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
 
 #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
       && defined __LONG_DOUBLE_IEEE128__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat" // '%Lf' expects 'long double'
-extern "C"
-__typeof__(__builtin_snprintf) __glibcxx_snprintfibm128 __asm__("snprintf");
+// The snprintf symbol in glibc that works with __ibm128 format is not visible
+// when compiling with -mabi=ieeelongdouble so we use this name for it instead.
+// N.B. we don't use __typeof__(__builtin_snprintf) for the type because that
+// would inherit __attribute__((format(printf, 3, 4))) and give a warning for
+// passing __ibm128 to %Lf instead of long double. The warning would be wrong
+// because long double in this TU is __ieee128 and snprintf expects __ibm128.
+extern "C" int
+__glibcxx_snprintfibm128(char*, size_t, const char*, ...) __asm__("snprintf");
 
   template<typename _CharT, typename _OutIter>
     _OutIter
@@ -673,7 +677,6 @@ __typeof__(__builtin_snprintf) __glibcxx_snprintfibm128 
__asm__("snprintf");
       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
                    : _M_insert<false>(__s, __io, __fill, __digits);
     }
-#pragma GCC diagnostic pop
 #endif
 
 _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
-- 
2.46.2

Reply via email to