1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
// Verify the correctness of folding relational expressions involving
// pointers to array elements and struct data members and null pointers.
// Although the C semantics of relational expressions are only defined
// for pointers to objects, C++ makes them well-defined when
// (nullptr < p) yields true. See the discussion of the patch for
// c++/67376 on gcc-patches for additional background.
// { dg-do compile { target c++11 } }
// { dg-options "-O1 -fdelete-null-pointer-checks -fdump-tree-optimized" }
// Runtime assert. Used for potentially invalid expressions.
#define RA(e) ((e) ? (void)0 : __builtin_abort ())
// Static assert. Used for valid core constant expressions.
#define SA(e) static_assert ((e), #e)
void test_first_array_element ()
{
static constexpr int a[] = { 0 };
constexpr const int *null = 0;
constexpr const int *pi = a;
// The following are valid constant expressions since in &*pi
// the '&*' "cancel each other out."
SA (!(null == &*pi));
SA ( (null != &*pi));
// The validity of the relational expressions involving null
// pointers in a constexpr context is questionable. Use a run
// time assertion to verify these.
RA ( (null < &*pi));
RA ( (null <= &*pi));
RA (!(null > &*pi));
RA (!(null >= &*pi));
SA (!(&*pi == null));
SA ( (&*pi != null));
RA (!(&*pi < null));
RA (!(&*pi <= null));
RA ( (&*pi > null));
RA ( (&*pi >= null));
// The following are valid constant expressions since &pi [0] is
// equivalent to &*pi.
SA (!(null == &pi [0]));
SA ( (null != &pi [0]));
RA ( (null < &pi [0]));
RA ( (null <= &pi [0]));
RA (!(null > &pi [0]));
RA (!(null >= &pi [0]));
SA (!(&pi [0] == null));
SA ( (&pi [0] != null));
RA (!(&pi [0] < null));
RA (!(&pi [0] <= null));
RA ( (&pi [0] > null));
RA ( (&pi [0] >= null));
}
void test_first_null_array_element ()
{
constexpr const int *pi = 0;
constexpr const int *qi = 0;
// The following are valid constant expressions since in &*qi
// the '&*' "cancel each other out."
SA ( (pi == &*qi));
SA (!(pi != &*qi));
// The validity of the relational expressions involving null
// pointers in a constexpr context is questionable.
RA (!(pi < &*qi));
RA ( (pi <= &*qi));
RA (!(pi > &*qi));
RA ( (pi >= &*qi));
SA ( (&*qi == pi));
SA (!(&*qi != pi));
RA (!(&*qi < pi));
RA ( (&*qi <= pi));
RA (!(&*qi > pi));
RA ( (&*qi >= pi));
// The following are valid constant expressions since &qi [0] is
// equivalent to &*qi.
SA ( (pi == &qi [0]));
SA (!(pi != &qi [0]));
RA (!(pi < &qi [0]));
RA ( (pi <= &qi [0]));
RA (!(pi > &qi [0]));
RA ( (pi >= &qi [0]));
SA ( (&qi [0] == pi));
SA (!(&qi [0] != pi));
RA (!(&qi [0] < pi));
RA ( (&qi [0] <= pi));
RA (!(&qi [0] > pi));
RA ( (&qi [0] >= pi));
}
void test_first_struct_member ()
{
static struct S { int a, b; } s = { 0, 0 };
constexpr const int *p = 0;
constexpr const S *q = &s;
SA (!(p == &q->b));
SA ( (p != &q->b));
RA ( (p < &q->b));
RA ( (p <= &q->b));
RA (!(p > &q->b));
RA (!(p >= &q->b));
SA (!(&q->b == p));
SA ( (&q->b != p));
RA (!(&q->b < p));
RA (!(&q->b <= p));
RA ( (&q->b > p));
RA ( (&q->b >= p));
}
// Expect all runtime asserts to have been eliminated as a result
// of the tested expressions constant folded into true.
// { dg-final { scan-assembler-not "abort" } }
|