Message ID | f15851e2-5c46-e9da-e510-c3e0714b0c68@codesourcery.com |
---|---|
State | New |
Headers | show |
Series | [testsuite] Add -fdelete-null-pointer-checks to some C++ testcases | expand |
On Tue, 2020-01-21 at 15:00 -0700, Sandra Loosemore wrote: > In doing some nios2-elf testing, I ran into a bunch of failures in > constexpr-related tests in the C++ testsuite. This target defaults to > -fno-delete-null-pointer-checks at the request of Altera/Intel, in order > to support some of their BSPs where 0 is a legitimate memory address. > Some other bare-metal targets also default to > -fno-delete-null-pointer-checks. > > This patch makes the dependence of these tests on > -fdelete-null-pointer-checks explicit. I've previously fixed some other > tests that failed on nios2-elf in the same way so this is borderline > obvious, but it's a little troubling to me that the correct semantics of > some of these testcases seems to depend on what we document in the > manual as an optimization option. :-S Maybe there is some other bug here? > > Anyway, if nobody has any objections or better ideas, I will go ahead > and commit this in a few days. It'd be nice to know why that flag matters for constexpr. But I've got no problem with the change itself. jeff
On 1/23/20 1:17 PM, Jeff Law wrote: > On Tue, 2020-01-21 at 15:00 -0700, Sandra Loosemore wrote: >> In doing some nios2-elf testing, I ran into a bunch of failures in >> constexpr-related tests in the C++ testsuite. This target defaults to >> -fno-delete-null-pointer-checks at the request of Altera/Intel, in order >> to support some of their BSPs where 0 is a legitimate memory address. >> Some other bare-metal targets also default to >> -fno-delete-null-pointer-checks. >> >> This patch makes the dependence of these tests on >> -fdelete-null-pointer-checks explicit. I've previously fixed some other >> tests that failed on nios2-elf in the same way so this is borderline >> obvious, but it's a little troubling to me that the correct semantics of >> some of these testcases seems to depend on what we document in the >> manual as an optimization option. :-S Maybe there is some other bug here? >> >> Anyway, if nobody has any objections or better ideas, I will go ahead >> and commit this in a few days. > It'd be nice to know why that flag matters for constexpr. But I've got > no problem with the change itself. I haven't looked at all of the failing tests in detail, but the ones I did peek at all seemed to be related to constant-folding pointer comparisons against null. The thing that nags at me is that e.g. in g++.dg/cpp0x/constexpr-odr1.C we have: template<int> struct A { static const bool x; static_assert(&x, ""); // odr-uses A<...>::x }; int g; template<int I> const bool A<I>::x = (g = 42, false); void f(A<0>) {} // A<0> must be complete, so is instantiated int main() { if (g != 42) __builtin_abort (); } Whether or not this is valid code depends on whether "&x != 0" can be constant-folded. Without -fdelete-null-pointer-checks, g++ says: /path/to/g++.dg/cpp0x/constexpr-odr1.C: In instantiation of 'struct A<0>': /path/to/g++.dg/cpp0x/constexpr-odr1.C:14:12: required from here /path/to/g++.dg/cpp0x/constexpr-odr1.C:6:17: error: non-constant condition for static assertion /path/to/g++.dg/cpp0x/constexpr-odr1.C:12:12: error: '((& A<0>::x) != 0)' is not a constant expression So is -fdelete-null-pointer-checks really an optimization option, or a language semantics option? BTW, here's Altera's original description of the over-eager optimization problems they were trying to work around: https://gcc.gnu.org/ml/gcc/2015-02/msg00163.html -Sandra
On Thu, 2020-01-23 at 14:59 -0700, Sandra Loosemore wrote: > On 1/23/20 1:17 PM, Jeff Law wrote: > > On Tue, 2020-01-21 at 15:00 -0700, Sandra Loosemore wrote: > > > In doing some nios2-elf testing, I ran into a bunch of failures in > > > constexpr-related tests in the C++ testsuite. This target defaults to > > > -fno-delete-null-pointer-checks at the request of Altera/Intel, in order > > > to support some of their BSPs where 0 is a legitimate memory address. > > > Some other bare-metal targets also default to > > > -fno-delete-null-pointer-checks. > > > > > > This patch makes the dependence of these tests on > > > -fdelete-null-pointer-checks explicit. I've previously fixed some other > > > tests that failed on nios2-elf in the same way so this is borderline > > > obvious, but it's a little troubling to me that the correct semantics of > > > some of these testcases seems to depend on what we document in the > > > manual as an optimization option. :-S Maybe there is some other bug here? > > > > > > Anyway, if nobody has any objections or better ideas, I will go ahead > > > and commit this in a few days. > > It'd be nice to know why that flag matters for constexpr. But I've got > > no problem with the change itself. > > I haven't looked at all of the failing tests in detail, but the ones I > did peek at all seemed to be related to constant-folding pointer > comparisons against null. > > The thing that nags at me is that e.g. in g++.dg/cpp0x/constexpr-odr1.C > we have: > > template<int> struct A { > static const bool x; > static_assert(&x, ""); // odr-uses A<...>::x > }; > > int g; > > template<int I> > const bool A<I>::x = (g = 42, false); > > void f(A<0>) {} // A<0> must be complete, so is instantiated > int main() > { > if (g != 42) > __builtin_abort (); > } > > Whether or not this is valid code depends on whether "&x != 0" can be > constant-folded. Without -fdelete-null-pointer-checks, g++ says: > > /path/to/g++.dg/cpp0x/constexpr-odr1.C: > In instantiation of 'struct A<0>': > /path/to/g++.dg/cpp0x/constexpr-odr1.C:14:12: > required from here > /path/to/g++.dg/cpp0x/constexpr-odr1.C:6:17: > error: non-constant condition for static assertion > /path/to/g++.dg/cpp0x/constexpr-odr1.C:12:12: > error: '((& A<0>::x) != 0)' is not a constant expression > > So is -fdelete-null-pointer-checks really an optimization option, or a > language semantics option? It's an optimization option, pure and simple. But determining if an expression is a constant sometimes requires folding (as in this case). Normally folding will assume that the address of an object can't be zero. -fno-delete-pointer-checks turns off that assumption (as it should). > > BTW, here's Altera's original description of the over-eager optimization > problems they were trying to work around: Yea. Using -fno-delete-pointer-checks is the right thing for them to do in their case. > https://gcc.gnu.org/ml/gcc/2015-02/msg00163.html >
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-odr1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-odr1.C index cf3f95f..d00baae 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-odr1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-odr1.C @@ -1,5 +1,6 @@ // PR c++/92062 - ODR-use ignored for static member of class template. // { dg-do run { target c++11 } } +// { dg-additional-options "-fdelete-null-pointer-checks" } template<int> struct A { static const bool x; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-odr2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-odr2.C index 0927488..dd569a9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-odr2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-odr2.C @@ -1,5 +1,6 @@ // PR c++/92062 - ODR-use ignored for static member of class template. // { dg-do run { target c++11 } } +// { dg-additional-options "-fdelete-null-pointer-checks" } template<int> struct A { static const bool x; diff --git a/gcc/testsuite/g++.dg/cpp0x/nontype4.C b/gcc/testsuite/g++.dg/cpp0x/nontype4.C index 2c552d0..b6a1ae7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nontype4.C +++ b/gcc/testsuite/g++.dg/cpp0x/nontype4.C @@ -1,5 +1,6 @@ // PR c++/56428 // { dg-do compile { target c++11 } } +// { dg-additional-options "-fdelete-null-pointer-checks" } struct A { }; diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C index 6316ff2..d0ca0b7 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C @@ -1,4 +1,5 @@ // { dg-do compile { target c++14 } } +// { dg-additional-options "-fdelete-null-pointer-checks" } constexpr int *f4(bool b) { if (b) { diff --git a/gcc/testsuite/g++.dg/cpp1y/new1.C b/gcc/testsuite/g++.dg/cpp1y/new1.C index b9ad64d..7016951 100644 --- a/gcc/testsuite/g++.dg/cpp1y/new1.C +++ b/gcc/testsuite/g++.dg/cpp1y/new1.C @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-cddce-details" } */ +// { dg-additional-options "-fdelete-null-pointer-checks" } #include <stdlib.h> diff --git a/gcc/testsuite/g++.dg/cpp1y/new2.C b/gcc/testsuite/g++.dg/cpp1y/new2.C index 926e796..97f4001 100644 --- a/gcc/testsuite/g++.dg/cpp1y/new2.C +++ b/gcc/testsuite/g++.dg/cpp1y/new2.C @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -std=c++17 -fdump-tree-cddce-details" } */ +/* { dg-additional-options "-fdelete-null-pointer-checks" } */ #include <cstdio> #include <cstdlib> diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic11.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic11.C index 6069fbf..8dfa03a 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic11.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic11.C @@ -1,5 +1,6 @@ // PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr. // { dg-do compile { target c++2a } } +// { dg-additional-options "-fdelete-null-pointer-checks" } // dynamic_cast in a constructor. // [class.cdtor]#6: "If the operand of the dynamic_cast refers to the object diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C index 6b443d2..c574e75 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic17.C @@ -1,5 +1,6 @@ // PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr. // { dg-do compile { target c++2a } } +// { dg-additional-options "-fdelete-null-pointer-checks" } // dynamic_cast in a constructor. // [class.cdtor]#6: "If the operand of the dynamic_cast refers to the object diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic4.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic4.C index 3adc524..6f42d20 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic4.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dynamic4.C @@ -1,5 +1,6 @@ // PR c++/88337 - Implement P1327R1: Allow dynamic_cast/typeid in constexpr. // { dg-do compile { target c++2a } } +// { dg-additional-options "-fdelete-null-pointer-checks" } // From clang's constant-expression-cxx2a.cpp. diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new1.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new1.C index 873edd4..5d1b7ef 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new1.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new1.C @@ -1,5 +1,6 @@ // P0784R7 // { dg-do compile { target c++2a } } +// { dg-additional-options "-fdelete-null-pointer-checks" } struct S { constexpr S () : s (5) {} constexpr S (int x) : s (x) {} int s; }; diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new10.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new10.C index 500a324..bc5e6e5 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new10.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new10.C @@ -1,5 +1,6 @@ // PR c++/91369 // { dg-do compile { target c++2a } } +// { dg-additional-options "-fdelete-null-pointer-checks" } struct S { constexpr S (int* i) : s{i} {} diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new2.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new2.C index be54962..d3733e8 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new2.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new2.C @@ -1,5 +1,6 @@ // P0784R7 // { dg-do compile { target c++2a } } +// { dg-additional-options "-fdelete-null-pointer-checks" } template <int N> constexpr bool diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C index 3380df7..6e7880a 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new3.C @@ -1,5 +1,6 @@ // P0784R7 // { dg-do compile { target c++2a } } +// { dg-additional-options "-fdelete-null-pointer-checks" } constexpr int * f1 () diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new4.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new4.C index 6cac983..b9bd5ea 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new4.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new4.C @@ -1,5 +1,6 @@ // P0784R7 // { dg-do compile { target c++2a } } +// { dg-additional-options "-fdelete-null-pointer-checks" } struct S { diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new8.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new8.C index c9c852d..f13da10 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new8.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new8.C @@ -1,5 +1,6 @@ // PR c++/91369 // { dg-do compile { target c++2a } } +// { dg-additional-options "-fdelete-null-pointer-checks" } struct A { constexpr A () : p{new int} {} diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new9.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new9.C index 552d3c1..f99f080 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new9.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new9.C @@ -1,5 +1,6 @@ // PR c++/91369 // { dg-do compile { target c++2a } } +// { dg-additional-options "-fdelete-null-pointer-checks" } struct S { constexpr S (int *i) : i{i} {} diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class1.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class1.C index 0c0b94d..a3334fc 100644 --- a/gcc/testsuite/g++.dg/cpp2a/nontype-class1.C +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class1.C @@ -1,4 +1,5 @@ // { dg-do compile { target c++2a } } +// { dg-additional-options "-fdelete-null-pointer-checks" } struct A {