| // PR c++/89833 |
| // Test to verify that arrays of null pointer to members used as |
| // non-type template arguments are interprested as null regardless |
| // of the form of their initialization. |
| // { dg-do compile { target c++20 } } |
| // { dg-options "-O2 -Wall -fdump-tree-optimized" } |
| |
| struct A { int i; }; |
| |
| typedef int A::*pam_t; |
| |
| struct B { pam_t a[2]; }; |
| template <B x> struct C { static constexpr B b = x; }; |
| |
| B f__ () { return B{ }; } |
| B f0_ () { return B{ 0 }; } |
| B f00 () { return B{ 0, 0 }; } |
| |
| typedef C<B{ }> X__; |
| typedef C<B{ 0 }> X0_; |
| typedef C<B{ 0, 0 }> X00; |
| |
| B g__ () { return X__::b; } |
| B g0_ () { return X0_::b; } |
| B g00 () { return X00::b; } |
| |
| const B b__{ }; |
| const B b0_{ 0 }; |
| const B b00{ 0, 0 }; |
| |
| const pam_t apam__[2] = { }; |
| const pam_t apam0_[2] = { 0 }; |
| const pam_t apam00[2] = { 0, 0 }; |
| |
| #define assert(expr) \ |
| (expr) ? (void)0 : __builtin_abort () |
| |
| void test () |
| { |
| assert (f__ ().a[0] == nullptr && f__ ().a[1] == nullptr); |
| assert (f0_ ().a[0] == nullptr && f0_ ().a[1] == nullptr); |
| assert (f00 ().a[0] == nullptr && f00 ().a[1] == nullptr); |
| |
| assert (g__ ().a[0] == nullptr && g__ ().a[1] == nullptr); |
| assert (g0_ ().a[0] == nullptr && g0_ ().a[1] == nullptr); |
| assert (g00 ().a[0] == nullptr && g00 ().a[1] == nullptr); |
| |
| assert (b__.a[0] == nullptr && b__.a[1] == nullptr); |
| assert (b0_.a[0] == nullptr && b0_.a[1] == nullptr); |
| assert (b00.a[0] == nullptr && b00.a[1] == nullptr); |
| |
| assert (apam__[0] == nullptr && apam__[1] == nullptr); |
| assert (apam0_[0] == nullptr && apam0_[1] == nullptr); |
| assert (apam00[0] == nullptr && apam00[1] == nullptr); |
| } |
| |
| // { dg-final { scan-tree-dump-not "abort" "optimized" } } |