From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12996 invoked by alias); 29 Sep 2005 23:52:59 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 12755 invoked by uid 48); 29 Sep 2005 23:52:32 -0000 Date: Thu, 29 Sep 2005 23:52:00 -0000 Message-ID: <20050929235232.12754.qmail@sourceware.org> From: "uweigand at gcc dot gnu dot org" To: gcc-bugs@gcc.gnu.org In-Reply-To: <20050111211052.19382.laurent@guerby.net> References: <20050111211052.19382.laurent@guerby.net> Reply-To: gcc-bugzilla@gcc.gnu.org Subject: [Bug ada/19382] ACATS cxb4005 cxb5002 simple To_COBOL/To_Fortran test fails at runtime on s390-linux X-Bugzilla-Reason: CC X-SW-Source: 2005-09/txt/msg03697.txt.bz2 List-Id: ------- Additional Comments From uweigand at gcc dot gnu dot org 2005-09-29 23:52 ------- I've found some time to look a bit more into this. First of all, here's a much reduced test case: procedure CXB4005 is type Alphanumeric is array (Positive range <>) of Character; TC_Alphanumeric : Alphanumeric(1..1); begin TC_Alphanumeric := "A"; pragma Assert (TC_Alphanumeric = "A"); end CXB4005; The assertion fails when built with -O2 -gnata. The comparsion TC_Alphanumeric = "A" gets translated by the front end into this tree (02.original): if (VIEW_CONVERT_EXPR(tc_alphanumeric) != "A") which get gimplified into (03.generic): tc_alphanumeric.0 = (character[1:1] *) &tc_alphanumeric; tc_alphanumeric.1 = (const *) tc_alphanumeric.0; D.388 = *tc_alphanumeric.1; D.389 = (integer) D.388; D.390 = (const *) "A"; D.391 = *D.390; D.392 = (integer) D.391; D.393 = D.389 - D.392; if (D.393 != 0) This transformation happens because an NE_EXPR of array types is handled by gimplify_variable_sized_compare, which converts it into an implicit call to memcmp. This call (with length 1) is then transformed by fold_builtin_memcmp into the computation of the difference of the two bytes. This is done in fold_builtin_memcpy by casting the addresses to an 'const unsigned char *' and dereferencing that expression, where that type is constructed as a variant of the predefined unsigned_char_type_node. (This type shows up in the above listings as 'const *'.) Now, when the so-casted expression is dereferenced, we obviously get into aliasing issues. This works fine in C-based languages, because there 'unsigned char' is explicitly allowed to alias any other type -- the fold_builtin_memcpy code is correct really only when making that assumption. However, in Ada there is no such special case, and the Ada hook for get_alias_set does not handle unsigned_char_type_node at all. Thus the type gets assigned a fresh alias set (that aliases nothing at all since the type didn't otherwise occur). I guess this is really a bug in fold_builtin_memcpy, but I'm not sure what exactly the proper fix would be. As a workaround, I've added the "C-style" treatment of 'char' to the Ada get_alias_set, and this fixes the symptom as well. The patch for this is: Index: gcc/ada/misc.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/ada/misc.c,v retrieving revision 1.106 diff -c -p -r1.106 misc.c *** gcc/ada/misc.c 4 Jul 2005 13:27:09 -0000 1.106 --- gcc/ada/misc.c 29 Sep 2005 23:34:18 -0000 *************** gnat_get_alias_set (tree type) *** 713,718 **** --- 713,725 ---- return get_alias_set (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (type))))); + /* ??? The middle end occasionally generates 'char' types by itself + and implicitly assumes they are allowed to alias everything. One + example is fold_builtin_memcmp, causing PR 19382. */ + if (type == char_type_node + || type == signed_char_type_node + || type == unsigned_char_type_node) + return 0; return -1; } -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19382