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);
}