This is a regression present on the mainline: the compiler aborts on the access to a component of the value returned by a function call, if the return type is a volatile record type that isn't controlled or tagged.
Tested on i586-suse-linux, applied on the mainline. 2012-02-15 Eric Botcazou <ebotca...@adacore.com> * gcc-interface/trans.c (call_to_gnu): Create the temporary for the return value in the by-reference return type case if this isn't the expression of an object declaration. Tidy up. 2012-02-15 Eric Botcazou <ebotca...@adacore.com> * gnat.dg/volatile10.adb: New case. * gnat.dg/volatile10_pkg.ads: New helper. -- Eric Botcazou
Index: gcc-interface/trans.c =================================================================== --- gcc-interface/trans.c (revision 184256) +++ gcc-interface/trans.c (working copy) @@ -3642,24 +3642,34 @@ call_to_gnu (Node_Id gnat_node, tree *gn went_into_elab_proc = true; } - /* First, create the temporary for the return value if we need it: for a - variable-sized return type if there is no target and this is not an - object declaration, or else there is a target and it is a slice or an - array with fixed size, as the gimplifier doesn't handle these cases; - otherwise for a function with copy-in/copy-out parameters if there is - no target, because we need to preserve the return value before copying - back the parameters. This must be done before we push a binding level - around the call as we will pop it before copying the return value. */ + /* First, create the temporary for the return value when: + + 1. There is no target and the function has copy-in/copy-out parameters, + because we need to preserve the return value before copying back the + parameters. + + 2. There is no target and this is not an object declaration, and the + return type is by-reference or has variable size, because in these + cases the gimplifier cannot create the temporary. + + 3. There is a target and it is a slice or an array with fixed size, + and the return type has variable size, because the gimplifier + doesn't handle these cases. + + This must be done before we push a binding level around the call, since + we will pop it before copying the return value. */ if (function_call - && ((TREE_CODE (TYPE_SIZE (gnu_result_type)) != INTEGER_CST - && ((!gnu_target - && Nkind (Parent (gnat_node)) != N_Object_Declaration) - || (gnu_target - && (TREE_CODE (gnu_target) == ARRAY_RANGE_REF - || (TREE_CODE (TREE_TYPE (gnu_target)) == ARRAY_TYPE - && TREE_CODE (TYPE_SIZE (TREE_TYPE (gnu_target))) - == INTEGER_CST))))) - || (!gnu_target && TYPE_CI_CO_LIST (gnu_subprog_type)))) + && ((!gnu_target && TYPE_CI_CO_LIST (gnu_subprog_type)) + || (!gnu_target + && Nkind (Parent (gnat_node)) != N_Object_Declaration + && (TREE_ADDRESSABLE (gnu_result_type) + || TREE_CODE (TYPE_SIZE (gnu_result_type)) != INTEGER_CST)) + || (gnu_target + && (TREE_CODE (gnu_target) == ARRAY_RANGE_REF + || (TREE_CODE (TREE_TYPE (gnu_target)) == ARRAY_TYPE + && TREE_CODE (TYPE_SIZE (TREE_TYPE (gnu_target))) + == INTEGER_CST)) + && TREE_CODE (TYPE_SIZE (gnu_result_type)) != INTEGER_CST))) gnu_retval = create_temporary ("R", gnu_result_type); /* Create the list of the actual parameters as GCC expects it, namely a
-- { dg-do compile } with Volatile10_Pkg; use Volatile10_Pkg; procedure Volatile10 is N : Num; begin N := F.N1; N := F.N2; end;
package Volatile10_Pkg is type Num is mod 2**9; type Rec is record B1 : Boolean; N1 : Num; B2 : Boolean; N2 : Num; B3 : Boolean; B4 : Boolean; B5 : Boolean; B6 : Boolean; B7 : Boolean; B8 : Boolean; B9 : Boolean; B10 : Boolean; B11 : Boolean; B12 : Boolean; B13 : Boolean; B14 : Boolean; end record; pragma Pack (Rec); for Rec'Size use 32; pragma Volatile(Rec); function F return Rec; end Volatile10_Pkg;