diff mbox series

[libstdc++] GLIBCXX_HAVE_INT64_T

Message ID CAGWvnyk0q7RSgiwKr-e5R002JRrq+udBCNdaukWHRD-3L=DWgA@mail.gmail.com
State New
Headers show
Series [libstdc++] GLIBCXX_HAVE_INT64_T | expand

Commit Message

David Edelsohn Jan. 6, 2021, 6:38 p.m. UTC
Use __SIZEOF_LONG__ and __SIZEOF_LONG_LONG__ to determine the type of
streamoff at compile time instead of _GLIBCXX_HAVE_INT64_T_LONG and
_GLIBCXX_HAVE_INT64_T_LONG_LONG.

Currently the type of streamoff is determined at libstdc++ configure
time, chosen by the definitions of _GLIBCXX_HAVE_INT64_T_LONG and
_GLIBCXX_HAVE_INT64_T_LONG_LONG.  For a multilib configuration, the
difference is encoded in the different multilib header file paths.
For "FAT" library targets that package 32 bit and 64 bit libraries
together, G++ also expects a single header file directory hierarchy,
causing an incorrect value for streamoff in some situations.

This patch changes the only use of _GLIBCXX_HAVE_INT64_T_XXX to test
__SIZEOF_LONG__ and __SIZEOF__LONG_LONG__ at compile time.  Because
libstdc++ explicitly probes the type of __int64_t to choose the
declaration of streamoff, this patch only performs the dynamic
determination if either _GLIBCXX_HAVE_INT64_T_LONG or
_GLIBCXX_HAVE_INT64_T_LONG_LONG are defined.  In other words, it does
assume that if either one is defined, the other is defined, i.e., that
__int64_t is a typedef for one of those two types when one or the
other is present.  But it then dynamically chooses the type based on
the size of "long" and "long long" instead of using the configure time
value so that the header dynamically adapts to the 32/64 mode of GCC.
If neither __GLIBCXX_HAVE_INT64_T_XXX macro is defined, the original
logic proceeds, using either __int64_t or "long long".

Based on the configure time definitions, the size should be one or the
other when one of the macros is defined.  I can add an error case if
neither __SIZEOF_LONG__ nor __SIZEOF_LONG_LONG__ are 8 despite
__GLIBCXX_HAVE_INT64_T_XXX defined.

Is this an acceptable solution to determine the value at compile-time?

Thanks, David

Comments

Marc Glisse Jan. 6, 2021, 6:55 p.m. UTC | #1
On Wed, 6 Jan 2021, David Edelsohn via Gcc-patches wrote:

> Currently the type of streamoff is determined at libstdc++ configure
> time, chosen by the definitions of _GLIBCXX_HAVE_INT64_T_LONG and
> _GLIBCXX_HAVE_INT64_T_LONG_LONG.  For a multilib configuration, the
> difference is encoded in the different multilib header file paths.
> For "FAT" library targets that package 32 bit and 64 bit libraries
> together, G++ also expects a single header file directory hierarchy,
> causing an incorrect value for streamoff in some situations.

Shouldn't we change that? I don't see why using the same directory for 
linking should imply using the same directory for includes.
David Edelsohn Jan. 6, 2021, 7:11 p.m. UTC | #2
On Wed, Jan 6, 2021 at 1:55 PM Marc Glisse <marc.glisse@inria.fr> wrote:
>
> On Wed, 6 Jan 2021, David Edelsohn via Gcc-patches wrote:
>
> > Currently the type of streamoff is determined at libstdc++ configure
> > time, chosen by the definitions of _GLIBCXX_HAVE_INT64_T_LONG and
> > _GLIBCXX_HAVE_INT64_T_LONG_LONG.  For a multilib configuration, the
> > difference is encoded in the different multilib header file paths.
> > For "FAT" library targets that package 32 bit and 64 bit libraries
> > together, G++ also expects a single header file directory hierarchy,
> > causing an incorrect value for streamoff in some situations.
>
> Shouldn't we change that? I don't see why using the same directory for
> linking should imply using the same directory for includes.

First, the search path assumption is rather strongly embedded in the
GCC driver in somewhat delicate code.  There already is a lot of
fragile, complicated processing for multilibs and search paths and
exception.  It is more risky, both in the potential new search logic
and in possible breakage, to perform surgery on the multilib support
code.

Second, it's confusing and error-prone to have different search
behavior for different parts of the compiler until we can completely
remove multilib headers.

Third, there is no inherent reason that the header files should be
multilib-dependent.  I'm not trying to boil the ocean and remove all
multilib differences in headers.  I'm trying to solve specific issues
caused by the differences in header files that also happen to move GCC
in a direction of less multilib differences encoded in header files,
which I think is a GOOD THING[tm].

Thanks, David
Jakub Jelinek Jan. 6, 2021, 7:37 p.m. UTC | #3
On Wed, Jan 06, 2021 at 01:38:25PM -0500, David Edelsohn via Gcc-patches wrote:
> Is this an acceptable solution to determine the value at compile-time?

This looks wrong to me.  The fact that long is 64-bit doesn't imply that
int64_t as defined by stdint.h must be long, it could be long long too.
And while e.g. for C it doesn't really matter much whether streamoff
will be long or long long if those two have the same precision,
for C++ it matters a lot (affects mangling etc.).

> diff --git a/libstdc++-v3/include/bits/postypes.h
> b/libstdc++-v3/include/bits/postypes.h
> index cb44cfe1396..81b9c4c6ae5 100644
> --- a/libstdc++-v3/include/bits/postypes.h
> +++ b/libstdc++-v3/include/bits/postypes.h
> @@ -84,10 +84,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>     *  Note: In versions of GCC up to and including GCC 3.3, streamoff
>     *  was typedef long.
>    */
> -#ifdef _GLIBCXX_HAVE_INT64_T_LONG
> +#if defined(_GLIBCXX_HAVE_INT64_T_LONG) \
> +    || defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)
> +
> +#if __SIZEOF_LONG__ == 8
>    typedef long          streamoff;
> -#elif defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)
> +#elif __SIZEOF_LONG_LONG__ == 8
>    typedef long long     streamoff;
> +#endif
> +
>  #elif defined(_GLIBCXX_HAVE_INT64_T)
>    typedef int64_t       streamoff;
>  #else

	Jakub
David Edelsohn Jan. 6, 2021, 9:20 p.m. UTC | #4
On Wed, Jan 6, 2021 at 2:37 PM Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Wed, Jan 06, 2021 at 01:38:25PM -0500, David Edelsohn via Gcc-patches wrote:
> > Is this an acceptable solution to determine the value at compile-time?
>
> This looks wrong to me.  The fact that long is 64-bit doesn't imply that
> int64_t as defined by stdint.h must be long, it could be long long too.
> And while e.g. for C it doesn't really matter much whether streamoff
> will be long or long long if those two have the same precision,
> for C++ it matters a lot (affects mangling etc.).

Your response doesn't correspond to the patch nor to what I described.

Nowhere did I say that int64_t must correspond to "long".  The patch
specifically chooses "long" or "long long" based on the
__SIZEOF_LONG__ *and* __SIZEOF_LONG_LONG__.

Currently libstdc++ configure tests for the type at configuration
time.  My patch changes the behavior to retain the test for the type
at configure time but chooses "long" or "long long" at compile time.
I don't unilaterally choose "long" or "long long" as the type, but
rely on the configure test to ensure that __int64_t is a typedef for
either "long" or "long long".

The patch does assume that if __int64_t is a typedef for "long" or
"long long" and this is a 32/64 multilib, then the typedef for the
other 32/64 mode is an equivalent typedef, which is the case for
GLIBC, AIX, and other systems that I have checked.

Thanks, David


>
> > diff --git a/libstdc++-v3/include/bits/postypes.h
> > b/libstdc++-v3/include/bits/postypes.h
> > index cb44cfe1396..81b9c4c6ae5 100644
> > --- a/libstdc++-v3/include/bits/postypes.h
> > +++ b/libstdc++-v3/include/bits/postypes.h
> > @@ -84,10 +84,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >     *  Note: In versions of GCC up to and including GCC 3.3, streamoff
> >     *  was typedef long.
> >    */
> > -#ifdef _GLIBCXX_HAVE_INT64_T_LONG
> > +#if defined(_GLIBCXX_HAVE_INT64_T_LONG) \
> > +    || defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)
> > +
> > +#if __SIZEOF_LONG__ == 8
> >    typedef long          streamoff;
> > -#elif defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)
> > +#elif __SIZEOF_LONG_LONG__ == 8
> >    typedef long long     streamoff;
> > +#endif
> > +
> >  #elif defined(_GLIBCXX_HAVE_INT64_T)
> >    typedef int64_t       streamoff;
> >  #else
>
>         Jakub
>
Jakub Jelinek Jan. 6, 2021, 9:41 p.m. UTC | #5
On Wed, Jan 06, 2021 at 04:20:22PM -0500, David Edelsohn wrote:
> Your response doesn't correspond to the patch nor to what I described.
> 
> Nowhere did I say that int64_t must correspond to "long".  The patch
> specifically chooses "long" or "long long" based on the
> __SIZEOF_LONG__ *and* __SIZEOF_LONG_LONG__.
> 
> Currently libstdc++ configure tests for the type at configuration
> time.  My patch changes the behavior to retain the test for the type
> at configure time but chooses "long" or "long long" at compile time.
> I don't unilaterally choose "long" or "long long" as the type, but
> rely on the configure test to ensure that __int64_t is a typedef for
> either "long" or "long long".
> 
> The patch does assume that if __int64_t is a typedef for "long" or
> "long long" and this is a 32/64 multilib, then the typedef for the
> other 32/64 mode is an equivalent typedef, which is the case for
> GLIBC, AIX, and other systems that I have checked.

Yes, on glibc it is the case, but it doesn't have to be the case on other
OSes, which is why there is a configure check.  Other OSes can typedef
int64_t to whatever they want (or what somebody choose years ago and is now
an ABI issue).
So, if you wanted to do this, you'd need to check at configure time both
multilibs and determine what to do for both.

I don't really understand the problem you are trying to solve, because
normally the c++config.h header that defines _GLIBCXX_HAVE_INT64_T_LONG etc.
comes from a multilib specific header directory, e.g. on powerpc64-linux,
one has:
/usr/include/c++/11/powerpc64-unknown-linux-gnu/bits/c++config.h
and
/usr/include/c++/11/powerpc64-unknown-linux-gnu/32/bits/c++config.h
(or instead /64/, depending on which multilib is the default) and
g++ driver arranges for the search paths to first look at the multilib
specific subdirectory and only later at the generic one.

	Jakub
David Edelsohn Jan. 6, 2021, 11:01 p.m. UTC | #6
On Wed, Jan 6, 2021 at 4:42 PM Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Wed, Jan 06, 2021 at 04:20:22PM -0500, David Edelsohn wrote:
> > Your response doesn't correspond to the patch nor to what I described.
> >
> > Nowhere did I say that int64_t must correspond to "long".  The patch
> > specifically chooses "long" or "long long" based on the
> > __SIZEOF_LONG__ *and* __SIZEOF_LONG_LONG__.
> >
> > Currently libstdc++ configure tests for the type at configuration
> > time.  My patch changes the behavior to retain the test for the type
> > at configure time but chooses "long" or "long long" at compile time.
> > I don't unilaterally choose "long" or "long long" as the type, but
> > rely on the configure test to ensure that __int64_t is a typedef for
> > either "long" or "long long".
> >
> > The patch does assume that if __int64_t is a typedef for "long" or
> > "long long" and this is a 32/64 multilib, then the typedef for the
> > other 32/64 mode is an equivalent typedef, which is the case for
> > GLIBC, AIX, and other systems that I have checked.
>
> Yes, on glibc it is the case, but it doesn't have to be the case on other
> OSes, which is why there is a configure check.  Other OSes can typedef
> int64_t to whatever they want (or what somebody choose years ago and is now
> an ABI issue).
> So, if you wanted to do this, you'd need to check at configure time both
> multilibs and determine what to do for both.

You continue to not respond to the actual patch and to raise issues
that don't exist in the actual patch.

libstdc++ configure tests if __int64_t has any type, and separately
tests if __int64_t uses typedef "long" or "long long", setting
separate macros.

The patch uses __SIZEOF_LONG__ and __SIZEOF_LONG_LONG__ if
_GLIBCXX_HAVE_INT64_T_LONG or _GLIBCXX_HAVE_INT64_T_LONG_LONG is
defined -- exactly for the situation where configure already has
determined that __int64_t is either "long" or "long long" and not some
other definition or type.  If those are not defined, the patch falls
back to the current, existing behavior which uses __int64_t, if
__int64_t is defined, or "long long" if nothing is defined.  This is
exactly how the current code behaves if __int64_t is not "long" nor
"long long".  So, exactly as you state, __int64_t could be a different
typedef and the patch continues to use that typedef if the OS didn'f
use "long" or "long long".

What is not clear about that and how does that not address your concern?

>
> I don't really understand the problem you are trying to solve, because
> normally the c++config.h header that defines _GLIBCXX_HAVE_INT64_T_LONG etc.
> comes from a multilib specific header directory, e.g. on powerpc64-linux,
> one has:
> /usr/include/c++/11/powerpc64-unknown-linux-gnu/bits/c++config.h
> and
> /usr/include/c++/11/powerpc64-unknown-linux-gnu/32/bits/c++config.h
> (or instead /64/, depending on which multilib is the default) and
> g++ driver arranges for the search paths to first look at the multilib
> specific subdirectory and only later at the generic one.

AIX uses what Darwin calls "FAT" libraries.  A single archive, in the
case of AIX, contains both 32 bit and 64 bit objects and shared
objects.  Darwin places the two shared objects into another special
file, but it's the same effect.  On AIX there is (or should be) one
libstdc++.a, for both ppc32 and ppc64.  (pthreads suppose is a
separate multilib axis.)  The fact that GCC historically uses
multilibs is a problem.  Also, when AIX added 64 bit multilibs, 32 bit
was not defined as its own multilib separate from the "native"
library.  There historically has been a ppc64 multilib subdirectory
but not a ppc32 multilib subdirectory.

GCC on AIX now is being enhanced so that GCC itself can be built as a
32 bit or 64 bit application.  This means that the "native" library is
either 32 bit for GCC32 or 64 bit for GCC64.  Ideally GCC32 and GCC64
should be able to create 32 bit and 64 bit applications that
interoperate, but because of the multilib differences, they look in
different locations for libraries.  If GCC followed normal AIX
behavior and placed all 32 bit and 64 bit shared objects into the same
archive and same directory, the interoperability issue would not
exist.  Currently GCC32 apps look in the top-level directory and GCC32
-m64 look in the ppc64 multilib, but GCC64 apps look in the top-level
directory and GCC64 -m32 apps look in the ppc32 multilib.  Depending
on which toolchain is used to build a 32 bit or 64 bit application, it
will look for shared objects in different locations.  AIX does not
have a /lib64 or /lib32 directory, there only is /lib because both
object modes can co-exist.

The effort last year builds all of the multilibs but places the
objects and shared objects into the same archive.  And changes to
MULTILIB_MATCHES teaches GCC to look for both multilibs in the same
directory, matching AIX behavior.

The remaining issue is GCC also looks for headers in the same relative
multilib directories.  Instructing GCC to look in the "correct" place
for the libraries causes GCC to look in the "wrong" place for headers.
As I replied to Marc's message, changing the GCC driver to separate
library search behavior and header search behavior is fraught with
danger.

Most of the libstdc++ headers are architecture-neutral, OS neutral and
ABI neutral.  The differences are localized in bits/c++config.h.  And
most of c++config.h is identical for 32 bit AIX and 64 bit AIX.  The
only differences that matter are __int128 and __int64_t.

Because of the manner in which c++config.h is built, it currently does
not provide an easy mechanism to override the libstdc++ configure
definitions.  My approach has been to propose a few, localized changes
to the libstdc++ headers so that the __int128 and __int64_t decisions
are made at compile time based on the way in which GCC was invoked
instead of encoded in the multilib directory hierarchy.  With this
change, it doesn't matter which multilib version of the libstdc++
header files are chosen because they always behave correctly.  And
from a design standpoint, it seems more reasonable for libstdc++
headers to adapt to the information known to the compiler instead of
redundantly storing the information in a static manner.

I can create a set of patches so that c++config.h includes another
header after it's mangled version of configure config.h that overrides
the troublesome values, but that seems like it compounds a bad design
with a kludge.

I am proposing a few, small changes to the libstdc++ headers so that
the gratuitous differences between -m32 and -m64 are determined from
the compiler when the headers are used to compile an application or
library instead of hard coded into the multilib directory hierarchy.

Thanks, David
Jakub Jelinek Jan. 6, 2021, 11:39 p.m. UTC | #7
On Wed, Jan 06, 2021 at 06:01:23PM -0500, David Edelsohn wrote:
> You continue to not respond to the actual patch and to raise issues
> that don't exist in the actual patch.

We are talking past each other.

Consider an OS that has in stdint.h
typedef long long int64_t;
supports 32-bit and 64-bit multilibs and has the usual type sizes,
i.e. 32-bit int, 32/64-bit long and 64-bit long long.
On such a target, libstdc++ configury will define
_GLIBCXX_HAVE_INT64_T_LONG_LONG for both 32-bit and 64-bit multilib,
and without your patch will typedef long long streamoff;
for both the multilibs, so e.g.
void bar (streamoff) {} will mangle as _Z3barx on both.
Now, with your patch, _GLIBCXX_HAVE_INT64_T_LONG_LONG is defined,
but on the 64-bit multilib __SIZEOF_LONG__ is 8 and so you
instead typedef long streamoff; for the 64-bit multilib (and keep
typedef long long streamoff; for the 32-bit one).
The function that previously mangled _Z3barx now mangles _Z3barl,
so the ABI broke.

Anyway, I'll defer to Jonathan who is the libstdc++ maintainer.

	Jakub
Jakub Jelinek Jan. 6, 2021, 11:45 p.m. UTC | #8
On Thu, Jan 07, 2021 at 12:39:39AM +0100, Jakub Jelinek wrote:
> We are talking past each other.
> 
> Consider an OS that has in stdint.h
> typedef long long int64_t;

And, from grepping INT64_TYPE in config/* config/*/*
it isn't just theoretic, Darwin and OpenBSD behave that way.

	Jakub
David Edelsohn Jan. 7, 2021, 12:41 a.m. UTC | #9
Thanks for clarifying the issue.

As you implicitly point out, GCC knows the type of INT64 and defines
the macro __INT64_TYPE__ .  The revised code can use that directly,
such as:

#if defined(_GLIBCXX_HAVE_INT64_T_LONG) \
    || defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)
   typedef __INT64_TYPE__   streamoff;
 #elif defined(_GLIBCXX_HAVE_INT64_T)
   typedef int64_t                     streamoff;
 #else
   typedef long long                 streamoff;
 #endif

Are there any additional issues not addressed by that approach, other
than possible further simplification?

Thanks, David

On Wed, Jan 6, 2021 at 6:45 PM Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Thu, Jan 07, 2021 at 12:39:39AM +0100, Jakub Jelinek wrote:
> > We are talking past each other.
> >
> > Consider an OS that has in stdint.h
> > typedef long long int64_t;
>
> And, from grepping INT64_TYPE in config/* config/*/*
> it isn't just theoretic, Darwin and OpenBSD behave that way.
>
>         Jakub
>
Jonathan Wakely Jan. 8, 2021, 6:37 p.m. UTC | #10
On 06/01/21 19:41 -0500, David Edelsohn wrote:
>Thanks for clarifying the issue.
>
>As you implicitly point out, GCC knows the type of INT64 and defines
>the macro __INT64_TYPE__ .  The revised code can use that directly,
>such as:
>
>#if defined(_GLIBCXX_HAVE_INT64_T_LONG) \
>    || defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)
>   typedef __INT64_TYPE__   streamoff;
> #elif defined(_GLIBCXX_HAVE_INT64_T)
>   typedef int64_t                     streamoff;
> #else
>   typedef long long                 streamoff;
> #endif
>
>Are there any additional issues not addressed by that approach, other
>than possible further simplification?

That avoids the ABI break that Jakub pointed out. But I think we can
simplify it further, as in the attached patch.

This uses __INT64_TYPE__ if that's defined, and long long otherwise. I
think that should be equivalent in all practical cases (I can imagine
some strange target where __INT64_TYPE__ is defined by the compiler,
but int64_t isn't defined when the configure checks look for it, and
so the current code would use long long and with my patch would use
__INT64_TYPE__ which could be long ... but I think in practice that's
unlikely. It was probably more likely in older releases where the
configure test would have been done with -std=gnu++98 and so int64_t
might not have been declared by libc's <stdint.h>, but if that was the
case then any ABI break it caused happened years ago.
Jakub Jelinek Jan. 8, 2021, 6:52 p.m. UTC | #11
On Fri, Jan 08, 2021 at 06:37:03PM +0000, Jonathan Wakely wrote:
> This uses __INT64_TYPE__ if that's defined, and long long otherwise. I
> think that should be equivalent in all practical cases (I can imagine
> some strange target where __INT64_TYPE__ is defined by the compiler,
> but int64_t isn't defined when the configure checks look for it, and
> so the current code would use long long and with my patch would use
> __INT64_TYPE__ which could be long ... but I think in practice that's
> unlikely. It was probably more likely in older releases where the
> configure test would have been done with -std=gnu++98 and so int64_t
> might not have been declared by libc's <stdint.h>, but if that was the
> case then any ABI break it caused happened years ago.

Does clang and ICC define __INT64_TYPE__ (at least on most architectures)
and does it match what gcc defines it to?

	Jakub
David Edelsohn Jan. 8, 2021, 8:35 p.m. UTC | #12
On Fri, Jan 8, 2021 at 1:52 PM Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Fri, Jan 08, 2021 at 06:37:03PM +0000, Jonathan Wakely wrote:
> > This uses __INT64_TYPE__ if that's defined, and long long otherwise. I
> > think that should be equivalent in all practical cases (I can imagine
> > some strange target where __INT64_TYPE__ is defined by the compiler,
> > but int64_t isn't defined when the configure checks look for it, and
> > so the current code would use long long and with my patch would use
> > __INT64_TYPE__ which could be long ... but I think in practice that's
> > unlikely. It was probably more likely in older releases where the
> > configure test would have been done with -std=gnu++98 and so int64_t
> > might not have been declared by libc's <stdint.h>, but if that was the
> > case then any ABI break it caused happened years ago.
>
> Does clang and ICC define __INT64_TYPE__ (at least on most architectures)
> and does it match what gcc defines it to?

Clang (at least back to 3.0.0) and ICC (at least back to 16.0.0)
define __INT64_TYPE__.  If the value is not compatible with the target
__int64_t type (matching GCC), there presumably are deeper problems.

Thanks, David
David Edelsohn April 29, 2021, 8:06 p.m. UTC | #13
On Fri, Jan 8, 2021 at 1:37 PM Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On 06/01/21 19:41 -0500, David Edelsohn wrote:
> >Thanks for clarifying the issue.
> >
> >As you implicitly point out, GCC knows the type of INT64 and defines
> >the macro __INT64_TYPE__ .  The revised code can use that directly,
> >such as:
> >
> >#if defined(_GLIBCXX_HAVE_INT64_T_LONG) \
> >    || defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)
> >   typedef __INT64_TYPE__   streamoff;
> > #elif defined(_GLIBCXX_HAVE_INT64_T)
> >   typedef int64_t                     streamoff;
> > #else
> >   typedef long long                 streamoff;
> > #endif
> >
> >Are there any additional issues not addressed by that approach, other
> >than possible further simplification?
>
> That avoids the ABI break that Jakub pointed out. But I think we can
> simplify it further, as in the attached patch.
>
> This uses __INT64_TYPE__ if that's defined, and long long otherwise. I
> think that should be equivalent in all practical cases (I can imagine
> some strange target where __INT64_TYPE__ is defined by the compiler,
> but int64_t isn't defined when the configure checks look for it, and
> so the current code would use long long and with my patch would use
> __INT64_TYPE__ which could be long ... but I think in practice that's
> unlikely. It was probably more likely in older releases where the
> configure test would have been done with -std=gnu++98 and so int64_t
> might not have been declared by libc's <stdint.h>, but if that was the
> case then any ABI break it caused happened years ago.

Hi, Jonathan

Polite ping.

Now that GCC 11.1 has been released, can this patch be applied to
libstdc++?  As I replied at the time to Jakub's concerns, both Clang
(since 3.0.0) and ICC (since at least 16.0.0) have defined
__INT64_TYPE__ .

Thanks, David
Jonathan Wakely April 29, 2021, 8:23 p.m. UTC | #14
On 29/04/21 16:06 -0400, David Edelsohn wrote:
>On Fri, Jan 8, 2021 at 1:37 PM Jonathan Wakely <jwakely@redhat.com> wrote:
>>
>> On 06/01/21 19:41 -0500, David Edelsohn wrote:
>> >Thanks for clarifying the issue.
>> >
>> >As you implicitly point out, GCC knows the type of INT64 and defines
>> >the macro __INT64_TYPE__ .  The revised code can use that directly,
>> >such as:
>> >
>> >#if defined(_GLIBCXX_HAVE_INT64_T_LONG) \
>> >    || defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)
>> >   typedef __INT64_TYPE__   streamoff;
>> > #elif defined(_GLIBCXX_HAVE_INT64_T)
>> >   typedef int64_t                     streamoff;
>> > #else
>> >   typedef long long                 streamoff;
>> > #endif
>> >
>> >Are there any additional issues not addressed by that approach, other
>> >than possible further simplification?
>>
>> That avoids the ABI break that Jakub pointed out. But I think we can
>> simplify it further, as in the attached patch.
>>
>> This uses __INT64_TYPE__ if that's defined, and long long otherwise. I
>> think that should be equivalent in all practical cases (I can imagine
>> some strange target where __INT64_TYPE__ is defined by the compiler,
>> but int64_t isn't defined when the configure checks look for it, and
>> so the current code would use long long and with my patch would use
>> __INT64_TYPE__ which could be long ... but I think in practice that's
>> unlikely. It was probably more likely in older releases where the
>> configure test would have been done with -std=gnu++98 and so int64_t
>> might not have been declared by libc's <stdint.h>, but if that was the
>> case then any ABI break it caused happened years ago.
>
>Hi, Jonathan
>
>Polite ping.
>
>Now that GCC 11.1 has been released, can this patch be applied to
>libstdc++?  As I replied at the time to Jakub's concerns, both Clang
>(since 3.0.0) and ICC (since at least 16.0.0) have defined
>__INT64_TYPE__ .

Yes, I'll push that tomorrow.
Jonathan Wakely April 30, 2021, 7:31 p.m. UTC | #15
On 29/04/21 16:06 -0400, David Edelsohn wrote:
>On Fri, Jan 8, 2021 at 1:37 PM Jonathan Wakely <jwakely@redhat.com> wrote:
>>
>> On 06/01/21 19:41 -0500, David Edelsohn wrote:
>> >Thanks for clarifying the issue.
>> >
>> >As you implicitly point out, GCC knows the type of INT64 and defines
>> >the macro __INT64_TYPE__ .  The revised code can use that directly,
>> >such as:
>> >
>> >#if defined(_GLIBCXX_HAVE_INT64_T_LONG) \
>> >    || defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)
>> >   typedef __INT64_TYPE__   streamoff;
>> > #elif defined(_GLIBCXX_HAVE_INT64_T)
>> >   typedef int64_t                     streamoff;
>> > #else
>> >   typedef long long                 streamoff;
>> > #endif
>> >
>> >Are there any additional issues not addressed by that approach, other
>> >than possible further simplification?
>>
>> That avoids the ABI break that Jakub pointed out. But I think we can
>> simplify it further, as in the attached patch.
>>
>> This uses __INT64_TYPE__ if that's defined, and long long otherwise. I
>> think that should be equivalent in all practical cases (I can imagine
>> some strange target where __INT64_TYPE__ is defined by the compiler,
>> but int64_t isn't defined when the configure checks look for it, and
>> so the current code would use long long and with my patch would use
>> __INT64_TYPE__ which could be long ... but I think in practice that's
>> unlikely. It was probably more likely in older releases where the
>> configure test would have been done with -std=gnu++98 and so int64_t
>> might not have been declared by libc's <stdint.h>, but if that was the
>> case then any ABI break it caused happened years ago.
>
>Hi, Jonathan
>
>Polite ping.
>
>Now that GCC 11.1 has been released, can this patch be applied to
>libstdc++?  As I replied at the time to Jakub's concerns, both Clang
>(since 3.0.0) and ICC (since at least 16.0.0) have defined
>__INT64_TYPE__ .

Pushed to trunk after testing on x86_64-linux and powerpc-aix.
David Edelsohn April 30, 2021, 8:18 p.m. UTC | #16
On Fri, Apr 30, 2021 at 3:31 PM Jonathan Wakely <jwakely@redhat.com> wrote:
>
> On 29/04/21 16:06 -0400, David Edelsohn wrote:
> >On Fri, Jan 8, 2021 at 1:37 PM Jonathan Wakely <jwakely@redhat.com> wrote:
> >>
> >> On 06/01/21 19:41 -0500, David Edelsohn wrote:
> >> >Thanks for clarifying the issue.
> >> >
> >> >As you implicitly point out, GCC knows the type of INT64 and defines
> >> >the macro __INT64_TYPE__ .  The revised code can use that directly,
> >> >such as:
> >> >
> >> >#if defined(_GLIBCXX_HAVE_INT64_T_LONG) \
> >> >    || defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)
> >> >   typedef __INT64_TYPE__   streamoff;
> >> > #elif defined(_GLIBCXX_HAVE_INT64_T)
> >> >   typedef int64_t                     streamoff;
> >> > #else
> >> >   typedef long long                 streamoff;
> >> > #endif
> >> >
> >> >Are there any additional issues not addressed by that approach, other
> >> >than possible further simplification?
> >>
> >> That avoids the ABI break that Jakub pointed out. But I think we can
> >> simplify it further, as in the attached patch.
> >>
> >> This uses __INT64_TYPE__ if that's defined, and long long otherwise. I
> >> think that should be equivalent in all practical cases (I can imagine
> >> some strange target where __INT64_TYPE__ is defined by the compiler,
> >> but int64_t isn't defined when the configure checks look for it, and
> >> so the current code would use long long and with my patch would use
> >> __INT64_TYPE__ which could be long ... but I think in practice that's
> >> unlikely. It was probably more likely in older releases where the
> >> configure test would have been done with -std=gnu++98 and so int64_t
> >> might not have been declared by libc's <stdint.h>, but if that was the
> >> case then any ABI break it caused happened years ago.
> >
> >Hi, Jonathan
> >
> >Polite ping.
> >
> >Now that GCC 11.1 has been released, can this patch be applied to
> >libstdc++?  As I replied at the time to Jakub's concerns, both Clang
> >(since 3.0.0) and ICC (since at least 16.0.0) have defined
> >__INT64_TYPE__ .
>
> Pushed to trunk after testing on x86_64-linux and powerpc-aix.

Hi, Jonathan

Thanks very much!  It's very helpful to remove the multilib differences.

I'll follow up about the int128 change in a separate email.

Thanks, David
diff mbox series

Patch

diff --git a/libstdc++-v3/include/bits/postypes.h
b/libstdc++-v3/include/bits/postypes.h
index cb44cfe1396..81b9c4c6ae5 100644
--- a/libstdc++-v3/include/bits/postypes.h
+++ b/libstdc++-v3/include/bits/postypes.h
@@ -84,10 +84,15 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *  Note: In versions of GCC up to and including GCC 3.3, streamoff
    *  was typedef long.
   */
-#ifdef _GLIBCXX_HAVE_INT64_T_LONG
+#if defined(_GLIBCXX_HAVE_INT64_T_LONG) \
+    || defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)
+
+#if __SIZEOF_LONG__ == 8
   typedef long          streamoff;
-#elif defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)
+#elif __SIZEOF_LONG_LONG__ == 8
   typedef long long     streamoff;
+#endif
+
 #elif defined(_GLIBCXX_HAVE_INT64_T)
   typedef int64_t       streamoff;
 #else