diff options
author | fw <fw@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-06-25 17:03:10 +0000 |
---|---|---|
committer | fw <fw@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-06-25 17:03:10 +0000 |
commit | 653d8b92299e8d19a665c9fafa60493bbde37eba (patch) | |
tree | 6bc99a9a98432fdbf6966014f5b49826eca80801 /gcc/testsuite/g++.dg/init | |
parent | 425588b539280e2ad6c934ee6d255655bdc311bd (diff) | |
download | gcc-653d8b92299e8d19a665c9fafa60493bbde37eba.tar.gz |
C++: Reject variably modified types in operator new
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@188948 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/testsuite/g++.dg/init')
-rw-r--r-- | gcc/testsuite/g++.dg/init/new35.C | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/new36.C | 153 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/new37.C | 63 |
3 files changed, 229 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/init/new35.C b/gcc/testsuite/g++.dg/init/new35.C new file mode 100644 index 00000000000..c5f79aa2f80 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/new35.C @@ -0,0 +1,13 @@ +// { dg-do compile } +// { dg-options "" } + +int +main (int argc, char **argv) +{ + typedef char A[argc]; + new A; // { dg-warning "variable-length array types|not a constant" } + new A[0]; // { dg-error "must be constant|not a constant" } + new A[5]; // { dg-error "must be constant|not a constant" } + new (A[0]); // { dg-error "must be constant|not a constant" } + new (A[5]); // { dg-error "must be constant|not a constant" } +} diff --git a/gcc/testsuite/g++.dg/init/new36.C b/gcc/testsuite/g++.dg/init/new36.C new file mode 100644 index 00000000000..c9b7af2d871 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/new36.C @@ -0,0 +1,153 @@ +// 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(); + } + throwAfter = 2; + max = 0; + try + { + new S[n]; + 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); +} diff --git a/gcc/testsuite/g++.dg/init/new37.C b/gcc/testsuite/g++.dg/init/new37.C new file mode 100644 index 00000000000..82ca18b7aeb --- /dev/null +++ b/gcc/testsuite/g++.dg/init/new37.C @@ -0,0 +1,63 @@ +// { dg-do compile } + +void +nonconst(int n) +{ + new (long[n][n]); // { dg-error "variable length|array size|not a constant" } + new long[n][n]; // { dg-error "variable length|array size|not a constant" } +} + +template <typename T> +void * +callnew(int n) +{ + return new long[n][T::n]; +} + +template <typename T> +void * +callnew_fail_1(int n) +{ + return new long[n][T::n]; // { dg-error "variable length|array size|usable in a constant" } +} + +template <typename T> +void * +callnew_fail_2() +{ + return new long[T::n]; // { dg-error "size in array new" } +} + +template <typename T> +void * +callnew_fail_3() +{ + return new T[2][T::n]; // { dg-error "size of array has non-integral type" } +} + +struct T1 { + static int n; +}; + +struct T2 { + static const double n = 2; // { dg-error "non-integral type" } +}; + +struct T3 { + static const int n = 2; +}; + +struct T4 { + enum { n = 3 }; +}; + +void +test_callnew(int n) +{ + new long[0.2]; // { dg-error "integral or enumeration type" } + callnew_fail_1<T1>(n); + callnew_fail_2<T2>(); + callnew_fail_3<T2>(); + callnew<T3>(n); + callnew<T4>(n); +} |