On 05/29/2012 06:41 PM, Gabriel Dos Reis wrote:
On Tue, May 29, 2012 at 11:00 AM, Florian Weimer<fwei...@redhat.com>  wrote:
This patch flags operator new on variably modified types as an error.
If this is acceptable, this will simplify the implementation of the
C++11 requirement to throw std::bad_array_new_length instead of
allocating a memory region which is too short.

Okay for trunk?  Or should I guard this with -fpermissive?

I must say that ideally this should go in.  However, this having
been accepted in previous releases, I think people would like
one release of deprecation.  So my suggestion is:
    -- make it an error unless -fpermissive.
    -- if -fpermissive, make it unconditionally deprecated.
    -- schedule for entire removal in 4.9.

On the other hand, it is such an obscure feature that it is rather unlikely that it has any users. The usual C++ conformance fixes and libstdc++ header reorganizations cause much more pain, and no depreciation is required for them.

Perhaps we can get away here without depreciation, too?

I wrote a few tests for operator new[] (attached), and it does seem to work correctly as required. I secretly hoped it was broken, but no luck there.

--
Florian Weimer / Red Hat Product Security Team
// Testcase for invocation of constructors/destructors in operator new[].
// { dg-do run }

#include <stdlib.h>

struct E {
  virtual ~E() { }
};

struct S {
  S();
  ~S();
};

static int count;
static int max;
static int throwAfter = -1;
static S *pS;

S::S()
{
  if (throwAfter >= 0 && count >= throwAfter)
    throw E();
  if (pS)
    {
      ++pS;
      if (this != pS)
	abort();
    }
  else
    pS = this;
  ++count;
  max = count;
}

S::~S()
{
  if (count > 1)
    {
      if (this != pS)
	abort();
      --pS;
    }
  else
    pS = 0;
  --count;
}

void __attribute__((noinline)) doit(int n)
{
  {
    S *s = new S[n];
    if (count != n)
      abort();
    if (pS != s + n - 1)
      abort();
    delete [] s;
    if (count != 0)
      abort();
  }
  typedef S A[n];
  {
    S *s = new A;
    if (count != n)
      abort();
    if (pS != s + n - 1)
      abort();
    delete [] s;
    if (count != 0)
      abort();
  }
  throwAfter = 2;
  max = 0;
  try
    {
      new S[n];
      abort();
    }
  catch (E)
    {
      if (max != 2)
	abort();
    }
  max = 0;
  try
    {
      new A;
      abort();
    }
  catch (E)
    {
      if (max != 2)
	abort();
    }
  throwAfter = -1;
}

int main()
{
  {
    S s;
    if (count != 1)
      abort();
    if (pS != &s)
      abort();
  }
  if (count != 0)
    abort();
  {
    S *s = new S;
    if (count != 1)
      abort();
    if (pS != s)
      abort();
    delete s;
    if (count != 0)
      abort();
  }
  {
    S *s = new S[1];
    if (count != 1)
      abort();
    if (pS != s)
      abort();
    delete [] s;
    if (count != 0)
      abort();
  }
  {
    S *s = new S[5];
    if (count != 5)
      abort();
    if (pS != s + 4)
      abort();
    delete [] s;
    if (count != 0)
      abort();
  }
  typedef S A[5];
  {
    S *s = new A;
    if (count != 5)
      abort();
    if (pS != s + 4)
      abort();
    delete [] s;
    if (count != 0)
      abort();
  }
  throwAfter = 2;
  max = 0;
  try
    {
      new S[5];
      abort();
    }
  catch (E)
    {
      if (max != 2)
	abort();
    }
  max = 0;
  try
    {
      new A;
      abort();
    }
  catch (E)
    {
      if (max != 2)
	abort();
    }
  throwAfter = -1;
  doit(5);
}

Reply via email to