This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Fortran,Patch] PR 46638 Wrong results with TRANSFER to derived types

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?


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
+   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 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]