This aligns the processing of constants used by reference in Identifier_to_gnu with that of regular constants; in particular we stop returning the underlying constant if this is the address of a constant and an lvalue is required.
Tested on i586-suse-linux, applied on the mainline. 2012-06-11 Eric Botcazou <ebotca...@adacore.com> * gcc-interface/trans.c (Identifier_to_gnu): Test Is_Elementary_Type instead of Is_Scalar_Type for a constant with an address clause. Do not return the underlying constant for a constant used by reference if it holds the address of a constant and an lvalue is required. -- Eric Botcazou
Index: gcc-interface/trans.c =================================================================== --- gcc-interface/trans.c (revision 188377) +++ gcc-interface/trans.c (working copy) @@ -1019,7 +1019,7 @@ Identifier_to_gnu (Node_Id gnat_node, tr order-of-elaboration issue here. */ gnu_result_type = get_unpadded_type (gnat_temp_type); - /* If this is a non-imported scalar constant with an address clause, + /* If this is a non-imported elementary constant with an address clause, retrieve the value instead of a pointer to be dereferenced unless an lvalue is required. This is generally more efficient and actually required if this is a static expression because it might be used @@ -1028,7 +1028,7 @@ Identifier_to_gnu (Node_Id gnat_node, tr volatile-ness short-circuit here since Volatile constants must be imported per C.6. */ if (Ekind (gnat_temp) == E_Constant - && Is_Scalar_Type (gnat_temp_type) + && Is_Elementary_Type (gnat_temp_type) && !Is_Imported (gnat_temp) && Present (Address_Clause (gnat_temp))) { @@ -1080,7 +1080,10 @@ Identifier_to_gnu (Node_Id gnat_node, tr = convert (build_pointer_type (gnu_result_type), gnu_result); /* If it's a CONST_DECL, return the underlying constant like below. */ - else if (TREE_CODE (gnu_result) == CONST_DECL) + else if (TREE_CODE (gnu_result) == CONST_DECL + && !(DECL_CONST_ADDRESS_P (gnu_result) + && lvalue_required_p (gnat_node, gnu_result_type, true, + true, false))) gnu_result = DECL_INITIAL (gnu_result); /* If it's a renaming pointer and we are at the right binding level,