prevent creation of improper static vars in gimplify_init_constructor

Olivier Hainque hainque@adacore.com
Thu May 11 12:32:00 GMT 2006


Hello,

The patch below is a suggestion to fix an issue with
gimplify_init_constructor, which currently might create static
versions of the constructor that varasm:output_constructor doesn't
handle.

The problem is visible out of the Ada testcase below, featuring
the initialization with a constructor of a bitfield aggregate:

   procedure P is

       type Mod_64 is mod 2 ** 64;
       for Mod_64'Size use 64;

       type Uint_16 is range 0 .. 2 ** 16 - 1;
       for Uint_16'Size use 16;

       type Values_Type is record
	  M64 : Mod_64;
	  U16 : Uint_16;
       end record;

       for Values_Type use record
	  M64 at 0 range 0 .. 63;
	  U16 at 8 range 0 .. 15;
       end record;

       type Wrapper_Type is record
	  Values : Values_Type;
       end record;

       for Wrapper_Type use record
	  Values at 0 range 0 .. 79;  -- bitfield aggregate
       end record;

       W : Wrapper_Type := (Values => (2, 4));

   begin
      null;
   end;

This code is expected to compile silently, while on e.g. x86-linux we
get an spurious "invalid initial value for member 'values'" error from
output_constructor (a regression from GCC 3.4, btw)

gimplify_init_constructor currently guards the creation of static
versions with "num_nonconstant_elements == 0", num_nonconstant_elements
being set as

   * how many scalar fields are set to non-constant values,

from categorize_ctor_elements. This is not restrictive enough to
prevent the error above because this looks through intermediate
aggregates among which there might be bitfields.

The suggested fix consists in replacing the "num_nonconstant_elements"
based guards by the outcome of "initializer_constant_valid_p" for the
constructor at hand.

Bootstrapped and regression tested on i686-pc-linux-gnu with
enable-languages=all,ada.

Olivier

2006-05-11  Olivier Hainque  <hainque@adacore.com>

	* gimplify.c (gimplify_init_constructor): Prevent the creation of
	static versions of the constructor if it is not a valid constant
	initializer.

*** gcc/gimplify.c.orig	2006-05-03 14:20:25.000000000 +0200
--- gcc/gimplify.c	2006-05-10 09:40:54.000000000 +0200
*************** gimplify_init_constructor (tree *expr_p,
*** 2885,2891 ****
  	struct gimplify_init_ctor_preeval_data preeval_data;
  	HOST_WIDE_INT num_type_elements, num_ctor_elements;
  	HOST_WIDE_INT num_nonzero_elements, num_nonconstant_elements;
! 	bool cleared;
  
  	/* Aggregate types must lower constructors to initialization of
  	   individual elements.  The exception is that a CONSTRUCTOR node
--- 2885,2891 ----
  	struct gimplify_init_ctor_preeval_data preeval_data;
  	HOST_WIDE_INT num_type_elements, num_ctor_elements;
  	HOST_WIDE_INT num_nonzero_elements, num_nonconstant_elements;
! 	bool cleared, ctor_is_valid_const_initializer;
  
  	/* Aggregate types must lower constructors to initialization of
  	   individual elements.  The exception is that a CONSTRUCTOR node
*************** gimplify_init_constructor (tree *expr_p,
*** 2897,2905 ****
  				  &num_nonconstant_elements,
  				  &num_ctor_elements, &cleared);
  
  	/* If a const aggregate variable is being initialized, then it
! 	   should never be a lose to promote the variable to be static.  */
! 	if (num_nonconstant_elements == 0
  	    && num_nonzero_elements > 1
  	    && TREE_READONLY (object)
  	    && TREE_CODE (object) == VAR_DECL)
--- 2897,2916 ----
  				  &num_nonconstant_elements,
  				  &num_ctor_elements, &cleared);
  
+ 	/* In some cases, making a static version of the constructor at hand
+ 	   would be a win, and we must ensure that varasm will be able to
+ 	   output it before doing so.  num_nonconstant_elements == 0 is not
+ 	   exactly what we need here, as it conveys information about embedded
+ 	   scalar components, looking through intermediate constructors among
+ 	   which there might be bitfield aggregates which output_constructor
+ 	   doesn't handle.  */
+ 	ctor_is_valid_const_initializer =
+ 	   initializer_constant_valid_p (ctor, TREE_TYPE (ctor)) != NULL_TREE;
+ 
  	/* If a const aggregate variable is being initialized, then it
! 	   should never be a lose to promote the variable to be static,
! 	   as soon as we're able to output the associated value.  */
! 	if (ctor_is_valid_const_initializer
  	    && num_nonzero_elements > 1
  	    && TREE_READONLY (object)
  	    && TREE_CODE (object) == VAR_DECL)
*************** gimplify_init_constructor (tree *expr_p,
*** 2956,2962 ****
  	   for sparse arrays, though, as it's more efficient to follow
  	   the standard CONSTRUCTOR behavior of memset followed by
  	   individual element initialization.  */
! 	if (num_nonconstant_elements == 0 && !cleared)
  	  {
  	    HOST_WIDE_INT size = int_size_in_bytes (type);
  	    unsigned int align;
--- 2967,2973 ----
  	   for sparse arrays, though, as it's more efficient to follow
  	   the standard CONSTRUCTOR behavior of memset followed by
  	   individual element initialization.  */
! 	if (ctor_is_valid_const_initializer && !cleared)
  	  {
  	    HOST_WIDE_INT size = int_size_in_bytes (type);
  	    unsigned int align;











More information about the Gcc-patches mailing list