From patchwork Wed Nov 24 15:25:25 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tobias Burnus X-Patchwork-Id: 72902 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 306D7B6F10 for ; Thu, 25 Nov 2010 02:28:49 +1100 (EST) Received: (qmail 17517 invoked by alias); 24 Nov 2010 15:25:48 -0000 Received: (qmail 17297 invoked by uid 22791); 24 Nov 2010 15:25:39 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE, TW_EB X-Spam-Check-By: sourceware.org Received: from mx01.qsc.de (HELO mx01.qsc.de) (213.148.129.14) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 24 Nov 2010 15:25:29 +0000 Received: from [192.168.178.22] (port-92-204-76-125.dynamic.qsc.de [92.204.76.125]) by mx01.qsc.de (Postfix) with ESMTP id 820223D786; Wed, 24 Nov 2010 16:25:26 +0100 (CET) Message-ID: <4CED2E65.4000804@net-b.de> Date: Wed, 24 Nov 2010 16:25:25 +0100 From: Tobias Burnus User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.12) Gecko/20101026 SUSE/3.1.6 Thunderbird/3.1.6 MIME-Version: 1.0 To: gfortran , gcc patches Subject: [Fortran, Patch] PR 46638 Wrong results with TRANSFER to derived types Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org The code for simplifying the TRANSFER to a derived type assumed that the elements are all offset by the amount DECL_FIELD_OFFSET (in bytes). However, that's only the case if each element has the size of DECL_OFFSET_ALIGN -- or larger. On my system, that's chunks of 16 byte. Thus, for all components whose size is smaller, the result will be wrong. The trick is to add to DECL_FIELD_OFFSET additionally the bits of DECL_FIELD_BIT_OFFSET -- that actually done for transferring the data from a derived type. [Instead of using the magical number "8" one could also use BITS_PER_UNIT (and add #include "default.h").] Build and regtested on x86-64-linux. OK for the trunk and 4.4/4.5? Tobias PS: See PR 46638 for other issues raised in the c.l.f thread -- related to C_SIZEOF and SIZEOF. Anyone can feel free to work on that item -- I do not plan to do so in the near future. 2010-11-24 Tobias Burnus PR fortran/46638 * target-memory.c (gfc_interpret_derived): Correctly handle component offset. 2010-11-24 Tobias Burnus PR fortran/46638 * gfortran.dg/transfer_simplify_10.f90: New. diff --git a/gcc/fortran/target-memory.c b/gcc/fortran/target-memory.c index 93e1c8c..01383c7 100644 --- a/gcc/fortran/target-memory.c +++ b/gcc/fortran/target-memory.c @@ -477,7 +477,16 @@ gfc_interpret_derived (unsigned char *buffer, size_t buffer_size, gfc_expr *resu /* The constructor points to the component. */ c->n.component = cmp; - ptr = TREE_INT_CST_LOW (DECL_FIELD_OFFSET (cmp->backend_decl)); + /* Calculate the offset, which consists of the the FIELD_OFFSET in + bytes, which appears in multiples of DECL_OFFSET_ALIGN-bit-sized, + and additional bits of FIELD_BIT_OFFSET. The code assumes that all + sizes of the components are multiples of BITS_PER_UNIT, + i.e. there are, e.g., no bit fields. */ + + ptr = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (cmp->backend_decl)); + gcc_assert (ptr % 8 == 0); + ptr = ptr/8 + TREE_INT_CST_LOW (DECL_FIELD_OFFSET (cmp->backend_decl)); + gfc_target_interpret_expr (&buffer[ptr], buffer_size - ptr, e); } diff --git a/gcc/testsuite/gfortran.dg/transfer_simplify_10.f90 b/gcc/testsuite/gfortran.dg/transfer_simplify_10.f90 new file mode 100644 index 0000000..d0c83b5 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/transfer_simplify_10.f90 @@ -0,0 +1,28 @@ +! { dg-do run } +! +! PR fortran/46638 +! +! Contributed by James Van Buskirk +! +program test5 + use ISO_C_BINDING + implicit none + type, bind(C) :: CPUID_type + integer(C_INT32_T) eax + integer(C_INT32_T) ebx + integer(C_INT32_T) edx + integer(C_INT32_T) ecx + integer(C_INT32_T) bbb + end type CPUID_type + type(CPUID_TYPE) result + result = transfer(achar(10)//achar(0)//achar(0)//achar(0)//'GenuineIntel'//'abcd',result) + + if ( int(z'0000000A') /= result%eax & + .or. int(z'756E6547') /= result%ebx & + .or. int(z'49656E69') /= result%edx & + .or. int(z'6C65746E') /= result%ecx & + .or. int(z'64636261') /= result%bbb) then + write(*,'(5(z8.8:1x))') result + call abort() + end if +end program test5