Bug#221565: g++-3.3: more detail
Followup-For: Bug #221565
Sorry for the delay in providing this information. This information is
all from Graydon Hoare, and I'm just relaying it.
Date: Tue, 09 Mar 2004 12:29:44 -0500
From: graydon hoare <email@example.com>
To: "Zooko O'Whielacronx" <firstname.lastname@example.org>
Subject: Re: Debian's gcc still miscompiles Crypto++ when -O2 ?
Zooko O'Whielacronx wrote:
> Graydon, Wei:
> I reported it to Debian, but then I never got around to writing a nice little
> test case for them. If Crypto++ 5.1 exercises the bug in its self-test, then
> maybe Debian would accept that as a test case.
I have actually spent some time whittling it down. here is what I found
(with help from email@example.com): the problem file is integer.cpp, and
the problem with it is due to aliasing rules.
strict "type based alias analysis" (on by default with -O2) means that
accessing members of a union via a pointer to a member type, rather than
via the union itself, can confuse the compiler into thinking that two
accesses have different (non-aliasing) physical locations, because they
have a different type, when in fact you may be hitting the same region
through two different pointers. integer.cpp does a lot of this sort of
thing with the word/dword union.
the "normal" solution to this is to build the offending code with
-fno-strict-aliasing. I don't know precisely why RH's compiler doesn't
have this need, but I'd guess it's in one of the many patches applied
before shipping. apple's build of 3.3 actually ships with strict
aliasing turned off on -O2 altogether; too much trouble. I find a few RH
patches which diddle around with the alias analysis code, but nothing is
sticking out at me. I am not really good friends with the C++ frontend yet.
another solution involves a __may_alias__ attribute stuck on the
word/dword union in cryptopp itself, like so:
@@ -125,8 +125,8 @@
// dword should be twice as big as word
#if (defined(__GNUC__) && !defined(__alpha)) || defined(__MWERKS__)
- typedef unsigned long word;
- typedef unsigned long long dword;
+ typedef unsigned long __attribute__((__may_alias__)) word;
+ typedef unsigned long long __attribute__((__may_alias__)) dword;
#elif defined(_MSC_VER) || defined(__BCPLUSPLUS__)
typedef unsigned __int32 word;
typedef unsigned __int64 dword;
that seems to fix it, for me. of course, such a draconian fix might well
hurt performance, and it only works with gcc versions >= 3.3, I think,
so probably some more ifdef'ing is necessary in there, and maybe pushing
the attribute down to the union members themselves.
-- System Information:
Debian Release: testing/unstable
APT prefers testing
APT policy: (900, 'testing')
Architecture: i386 (i686)
Kernel: Linux 2.4.25
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8
Versions of packages g++-3.3 depends on:
ii gcc-3.3 1:3.3.3-6 The GNU C compiler
ii gcc-3.3-base 1:3.3.3-6 The GNU Compiler Collection (base
hi libc6 2.3.2.ds1-11 GNU C Library: Shared libraries an
ii libstdc++5-3.3-dev 1:3.3.3-6 The GNU Standard C++ Library v3 (d