This is the mail archive of the gcc-patches@gcc.gnu.org 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]

[PATCH] Fix 16681


This patch fixes 16681, a memory use regression in zero initializing
a huge array.  We already permit a RANGE_EXPR in constructor elt, this
patch builds such an elt.  The test cases check that exceptions are correctly
dealt with for those arrays with non-pod elements.

I guess we could use the same form for 'new T[n] ()' statements, (rather
than a loop) but that's a different non-regression.

booted & tested on i686-pc-linux-gnu.

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2004-12-09  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/16681
	* init.c (build_zero_init): Build a RANGE_EXPR for an array
	initializer.

Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.403
diff -c -3 -p -r1.403 init.c
*** cp/init.c	8 Dec 2004 08:35:41 -0000	1.403
--- cp/init.c	9 Dec 2004 09:21:02 -0000
*************** build_zero_init (tree type, tree nelts, 
*** 214,220 ****
      }
    else if (TREE_CODE (type) == ARRAY_TYPE)
      {
-       tree index;
        tree max_index;
        tree inits;
  
--- 214,219 ----
*************** build_zero_init (tree type, tree nelts, 
*** 228,241 ****
        /* A zero-sized array, which is accepted as an extension, will
  	 have an upper bound of -1.  */
        if (!tree_int_cst_equal (max_index, integer_minus_one_node))
! 	for (index = size_zero_node;
! 	     !tree_int_cst_lt (max_index, index);
! 	     index = size_binop (PLUS_EXPR, index, size_one_node))
! 	  inits = tree_cons (index,
! 			     build_zero_init (TREE_TYPE (type),
! 					      /*nelts=*/NULL_TREE,
! 					      static_storage_p),
! 			     inits);
        CONSTRUCTOR_ELTS (init) = nreverse (inits);
      }
    else
--- 227,242 ----
        /* A zero-sized array, which is accepted as an extension, will
  	 have an upper bound of -1.  */
        if (!tree_int_cst_equal (max_index, integer_minus_one_node))
! 	{
! 	  tree elt_init = build_zero_init (TREE_TYPE (type),
! 					   /*nelts=*/NULL_TREE,
! 					   static_storage_p);
! 	  tree range = build2 (RANGE_EXPR,
! 			       sizetype, size_zero_node, max_index);
! 	  
! 	  inits = tree_cons (range, elt_init, inits);
! 	}
!       
        CONSTRUCTOR_ELTS (init) = nreverse (inits);
      }
    else
// { dg-do run }

// Copyright (C) 2004 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 8 Dec 2004 <nathan@codesourcery.com>

// PR 16681 too much memory used
// Origin:  Matt LaFary <lafary@activmedia.com>

struct foo {
  unsigned char buffer[4111222];
  foo() ;
  bool check () const;
};

foo::foo ()
  : buffer()
{}

bool foo::check () const
{
  for (unsigned ix = sizeof (buffer); ix--;)
    if (buffer[ix])
      return false;
  return true;
}

void *operator new (__SIZE_TYPE__ size, void *p)
{
  return p;
}

char heap[5000000];

int main ()
{
  for (unsigned ix = sizeof (heap); ix--;)
    heap[ix] = ix;
  
  foo *f = new (heap) foo ();

  if (!f->check ())
    return 1;
  return 0;
}

  
// { dg-do run }

// Copyright (C) 2004 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 8 Dec 2004 <nathan@codesourcery.com>

// PR 16681 too much memory used
// Origin:  Matt LaFary <lafary@activmedia.com>


struct elt 
{
  static int count;
  static elt*ptr;
  static int abort;
  char c;
  
  elt ();
  ~elt ();
  
};

int elt::count;
elt *elt::ptr;
int elt::abort;

elt::elt ()
  :c ()
{
  if (count >= 0)
    {
      if (!ptr)
	ptr = this;
      if (count == 100)
	throw 2;
      if (this != ptr)
	abort = 1;
      count++;
      ptr++;
    }
}

elt::~elt ()
{
  if (count >= 0)
    {
      ptr--;
      count--;
      if (ptr != this)
	abort = 2;
    }
}

struct foo {
  elt buffer[4111222];
  foo() ;
  bool check () const;
};

foo::foo ()
  : buffer()
{}

bool foo::check () const
{
  for (unsigned ix = sizeof (buffer)/ sizeof (buffer[0]); ix--;)
    if (buffer[ix].c)
      return false;
  return true;
}

void *operator new (__SIZE_TYPE__ size, void *p)
{
  return p;
}

char heap[5000000];

int main ()
{
  for (unsigned ix = sizeof (heap); ix--;)
    heap[ix] = ix;

  try
    {
      foo *f = new (heap) foo ();
      return 1;
    }
  catch (...)
    {
      if (elt::count)
	return 2;
      if (elt::abort)
	return elt::abort + 3;
    }

  for (unsigned ix = sizeof (heap); ix--;)
    heap[ix] = ix;

  elt::count = -1;
  foo *f = new (heap) foo ();
  if (!f->check ())
    return 3;
  return 0;
}

  

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