mirror of git://gcc.gnu.org/git/gcc.git
PR c++/67376 - [5/6 regression] Comparison with pointer to past-the-end
PR c++/67376 - [5/6 regression] Comparison with pointer to past-the-end
of array fails inside constant expression
PR c++/70170 - [6 regression] bogus not a constant expression error comparing
pointer to array to null
PR c++/70172 - incorrect reinterpret_cast from integer to pointer error
on invalid constexpr initialization
PR c++/70228 - insufficient detail in diagnostics for a constexpr out of bounds
array subscript
gcc/testsuite/ChangeLog:
2016-04-02 Martin Sebor <msebor@redhat.com>
PR c++/67376
PR c++/70170
PR c++/70172
PR c++/70228
* g++.dg/cpp0x/constexpr-array-ptr10.C: New test.
* g++.dg/cpp0x/constexpr-array-ptr9.C: New test.
* g++.dg/cpp0x/constexpr-nullptr-1.C: New test.
* g++.dg/cpp0x/constexpr-array5.C: Adjust text of expected diagnostic.
* g++.dg/cpp0x/constexpr-string.C: Same.
* g++.dg/cpp0x/constexpr-wstring2.C: Same.
* g++.dg/cpp0x/pr65398.C: Same.
* g++.dg/ext/constexpr-vla1.C: Same.
* g++.dg/ext/constexpr-vla2.C: Same.
* g++.dg/ext/constexpr-vla3.C: Same.
* g++.dg/ubsan/pr63956.C: Same.
gcc/cp/ChangeLog:
2016-04-02 Martin Sebor <msebor@redhat.com>
PR c++/67376
PR c++/70170
PR c++/70172
PR c++/70228
* constexpr.c (diag_array_subscript): New function.
(cxx_eval_array_reference): Detect out of bounds array indices.
gcc/ChangeLog:
2016-04-02 Martin Sebor <msebor@redhat.com>
PR c++/67376
* fold-const.c (maybe_nonzero_address): New function.
(fold_comparison): Call it. Fold equality and relational
expressions involving null pointers.
(tree_single_nonzero_warnv_p): Call maybe_nonzero_address.
From-SVN: r234698
This commit is contained in:
parent
7d9979e629
commit
abdc16c867
|
|
@ -1,3 +1,11 @@
|
||||||
|
2016-04-02 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR c++/67376
|
||||||
|
* fold-const.c (maybe_nonzero_address): New function.
|
||||||
|
(fold_comparison): Call it. Fold equality and relational
|
||||||
|
expressions involving null pointers.
|
||||||
|
(tree_single_nonzero_warnv_p): Call maybe_nonzero_address.
|
||||||
|
|
||||||
2016-03-31 Evandro Menezes <e.menezes@samsung.com>
|
2016-03-31 Evandro Menezes <e.menezes@samsung.com>
|
||||||
|
|
||||||
Fix the predicate "aarch64_simd_reg_or_zero" to correctly validate
|
Fix the predicate "aarch64_simd_reg_or_zero" to correctly validate
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,12 @@
|
||||||
|
2016-04-02 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR c++/67376
|
||||||
|
PR c++/70170
|
||||||
|
PR c++/70172
|
||||||
|
PR c++/70228
|
||||||
|
* constexpr.c (diag_array_subscript): New function.
|
||||||
|
(cxx_eval_array_reference): Detect out of bounds array indices.
|
||||||
|
|
||||||
2016-04-01 Jason Merrill <jason@redhat.com>
|
2016-04-01 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
PR c++/70449
|
PR c++/70449
|
||||||
|
|
|
||||||
|
|
@ -1825,6 +1825,30 @@ find_array_ctor_elt (tree ary, tree dindex, bool insert = false)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Under the control of CTX, issue a detailed diagnostic for
|
||||||
|
an out-of-bounds subscript INDEX into the expression ARRAY. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
diag_array_subscript (const constexpr_ctx *ctx, tree array, tree index)
|
||||||
|
{
|
||||||
|
if (!ctx->quiet)
|
||||||
|
{
|
||||||
|
tree arraytype = TREE_TYPE (array);
|
||||||
|
|
||||||
|
/* Convert the unsigned array subscript to a signed integer to avoid
|
||||||
|
printing huge numbers for small negative values. */
|
||||||
|
tree sidx = fold_convert (ssizetype, index);
|
||||||
|
if (DECL_P (array))
|
||||||
|
{
|
||||||
|
error ("array subscript value %qE is outside the bounds "
|
||||||
|
"of array %qD of type %qT", sidx, array, arraytype);
|
||||||
|
inform (DECL_SOURCE_LOCATION (array), "declared here");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error ("array subscript value %qE is outside the bounds "
|
||||||
|
"of array type %qT", sidx, arraytype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Subroutine of cxx_eval_constant_expression.
|
/* Subroutine of cxx_eval_constant_expression.
|
||||||
Attempt to reduce a reference to an array slot. */
|
Attempt to reduce a reference to an array slot. */
|
||||||
|
|
@ -1873,8 +1897,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
|
||||||
if (!tree_fits_shwi_p (index)
|
if (!tree_fits_shwi_p (index)
|
||||||
|| (i = tree_to_shwi (index)) < 0)
|
|| (i = tree_to_shwi (index)) < 0)
|
||||||
{
|
{
|
||||||
if (!ctx->quiet)
|
diag_array_subscript (ctx, ary, index);
|
||||||
error ("negative array subscript");
|
|
||||||
*non_constant_p = true;
|
*non_constant_p = true;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
@ -1886,8 +1909,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
|
||||||
VERIFY_CONSTANT (nelts);
|
VERIFY_CONSTANT (nelts);
|
||||||
if (!tree_int_cst_lt (index, nelts))
|
if (!tree_int_cst_lt (index, nelts))
|
||||||
{
|
{
|
||||||
if (!ctx->quiet)
|
diag_array_subscript (ctx, ary, index);
|
||||||
error ("array subscript out of bound");
|
|
||||||
*non_constant_p = true;
|
*non_constant_p = true;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8338,6 +8338,20 @@ pointer_may_wrap_p (tree base, tree offset, HOST_WIDE_INT bitpos)
|
||||||
return total.to_uhwi () > (unsigned HOST_WIDE_INT) size;
|
return total.to_uhwi () > (unsigned HOST_WIDE_INT) size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return a positive integer when the symbol DECL is known to have
|
||||||
|
a nonzero address, zero when it's known not to (e.g., it's a weak
|
||||||
|
symbol), and a negative integer when the symbol is not yet in the
|
||||||
|
symbol table and so whether or not its address is zero is unknown. */
|
||||||
|
static int
|
||||||
|
maybe_nonzero_address (tree decl)
|
||||||
|
{
|
||||||
|
if (DECL_P (decl) && decl_in_symtab_p (decl))
|
||||||
|
if (struct symtab_node *symbol = symtab_node::get_create (decl))
|
||||||
|
return symbol->nonzero_address ();
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Subroutine of fold_binary. This routine performs all of the
|
/* Subroutine of fold_binary. This routine performs all of the
|
||||||
transformations that are common to the equality/inequality
|
transformations that are common to the equality/inequality
|
||||||
operators (EQ_EXPR and NE_EXPR) and the ordering operators
|
operators (EQ_EXPR and NE_EXPR) and the ordering operators
|
||||||
|
|
@ -8638,6 +8652,39 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
|
||||||
base1 = build_fold_addr_expr_loc (loc, base1);
|
base1 = build_fold_addr_expr_loc (loc, base1);
|
||||||
return fold_build2_loc (loc, code, type, base0, base1);
|
return fold_build2_loc (loc, code, type, base0, base1);
|
||||||
}
|
}
|
||||||
|
/* Comparison between an ordinary (non-weak) symbol and a null
|
||||||
|
pointer can be eliminated since such symbols must have a non
|
||||||
|
null address. In C, relational expressions between pointers
|
||||||
|
to objects and null pointers are undefined. The results
|
||||||
|
below follow the C++ rules with the additional property that
|
||||||
|
every object pointer compares greater than a null pointer.
|
||||||
|
*/
|
||||||
|
else if (DECL_P (base0)
|
||||||
|
&& maybe_nonzero_address (base0) > 0
|
||||||
|
/* Avoid folding references to struct members at offset 0 to
|
||||||
|
prevent tests like '&ptr->firstmember == 0' from getting
|
||||||
|
eliminated. When ptr is null, although the -> expression
|
||||||
|
is strictly speaking invalid, GCC retains it as a matter
|
||||||
|
of QoI. See PR c/44555. */
|
||||||
|
&& (offset0 == NULL_TREE && bitpos0 != 0)
|
||||||
|
/* The caller guarantees that when one of the arguments is
|
||||||
|
constant (i.e., null in this case) it is second. */
|
||||||
|
&& integer_zerop (arg1))
|
||||||
|
{
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case EQ_EXPR:
|
||||||
|
case LE_EXPR:
|
||||||
|
case LT_EXPR:
|
||||||
|
return boolean_false_node;
|
||||||
|
case GE_EXPR:
|
||||||
|
case GT_EXPR:
|
||||||
|
case NE_EXPR:
|
||||||
|
return boolean_true_node;
|
||||||
|
default:
|
||||||
|
gcc_unreachable ();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Transform comparisons of the form X +- C1 CMP Y +- C2 to
|
/* Transform comparisons of the form X +- C1 CMP Y +- C2 to
|
||||||
|
|
@ -13508,16 +13555,9 @@ tree_single_nonzero_warnv_p (tree t, bool *strict_overflow_p)
|
||||||
/* For objects in symbol table check if we know they are non-zero.
|
/* For objects in symbol table check if we know they are non-zero.
|
||||||
Don't do anything for variables and functions before symtab is built;
|
Don't do anything for variables and functions before symtab is built;
|
||||||
it is quite possible that they will be declared weak later. */
|
it is quite possible that they will be declared weak later. */
|
||||||
if (DECL_P (base) && decl_in_symtab_p (base))
|
int nonzero_addr = maybe_nonzero_address (base);
|
||||||
{
|
if (nonzero_addr >= 0)
|
||||||
struct symtab_node *symbol;
|
return nonzero_addr;
|
||||||
|
|
||||||
symbol = symtab_node::get_create (base);
|
|
||||||
if (symbol)
|
|
||||||
return symbol->nonzero_address ();
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Function local objects are never NULL. */
|
/* Function local objects are never NULL. */
|
||||||
if (DECL_P (base)
|
if (DECL_P (base)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,21 @@
|
||||||
|
2016-04-02 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
|
PR c++/67376
|
||||||
|
PR c++/70170
|
||||||
|
PR c++/70172
|
||||||
|
PR c++/70228
|
||||||
|
* g++.dg/cpp0x/constexpr-array-ptr10.C: New test.
|
||||||
|
* g++.dg/cpp0x/constexpr-array-ptr9.C: New test.
|
||||||
|
* g++.dg/cpp0x/constexpr-nullptr-1.C: New test.
|
||||||
|
* g++.dg/cpp0x/constexpr-array5.C: Adjust text of expected diagnostic.
|
||||||
|
* g++.dg/cpp0x/constexpr-string.C: Same.
|
||||||
|
* g++.dg/cpp0x/constexpr-wstring2.C: Same.
|
||||||
|
* g++.dg/cpp0x/pr65398.C: Same.
|
||||||
|
* g++.dg/ext/constexpr-vla1.C: Same.
|
||||||
|
* g++.dg/ext/constexpr-vla2.C: Same.
|
||||||
|
* g++.dg/ext/constexpr-vla3.C: Same.
|
||||||
|
* g++.dg/ubsan/pr63956.C: Same.
|
||||||
|
|
||||||
2016-04-01 Jakub Jelinek <jakub@redhat.com>
|
2016-04-01 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR rtl-optimization/70467
|
PR rtl-optimization/70467
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
// PR c++/67376 - [5/6 regression] Comparison with pointer to past-the-end
|
||||||
|
// of array fails inside constant expression
|
||||||
|
// This test verifies the aspect of the bug raised in comment #10,
|
||||||
|
// specifically comparing pointers to null. The basic regression test
|
||||||
|
// is in g++.dg/cpp0x/constexpr-67376.C.
|
||||||
|
// Note also that while the description of the bug talks about pointers
|
||||||
|
// pointing past the end of arrays but the prolem is more general than
|
||||||
|
// that and involves all constexpr object pointers.
|
||||||
|
|
||||||
|
// { dg-do compile { target c++11 } }
|
||||||
|
// { dg-additional-options "-Wall -Wextra" }
|
||||||
|
|
||||||
|
namespace A {
|
||||||
|
|
||||||
|
extern int i;
|
||||||
|
|
||||||
|
constexpr int *p0 = &i;
|
||||||
|
|
||||||
|
constexpr bool b0 = p0; // { dg-warning "address of .A::i." }
|
||||||
|
constexpr bool b1 = p0 == 0; // { dg-warning "address of .A::i." }
|
||||||
|
constexpr bool b2 = p0 != 0; // { dg-warning "address of .A::i." }
|
||||||
|
constexpr bool b3 = p0 < 0; // { dg-warning "ordered comparison" }
|
||||||
|
constexpr bool b4 = p0 <= 0; // { dg-warning "ordered comparison" }
|
||||||
|
constexpr bool b5 = p0 > 0; // { dg-warning "ordered comparison" }
|
||||||
|
constexpr bool b6 = p0 >= 0; // { dg-warning "ordered comparison" }
|
||||||
|
|
||||||
|
constexpr bool b7 = !p0; // { dg-warning "address of .A::i." }
|
||||||
|
constexpr bool b8 = 0 == p0; // { dg-warning "address of .A::i." }
|
||||||
|
constexpr bool b9 = 0 != p0; // { dg-warning "address of .A::i." }
|
||||||
|
constexpr bool b10 = 0 < p0; // { dg-warning "ordered comparison" }
|
||||||
|
constexpr bool b11 = 0 <= p0; // { dg-warning "ordered comparison" }
|
||||||
|
constexpr bool b12 = 0 > p0; // { dg-warning "ordered comparison" }
|
||||||
|
constexpr bool b13 = 0 >= p0; // { dg-warning "ordered comparison" }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace B {
|
||||||
|
|
||||||
|
// PR c++/70172 - incorrect reinterpret_cast from integer to pointer
|
||||||
|
// error on invalid constexpr initialization
|
||||||
|
|
||||||
|
struct S { int a, b[1]; } s;
|
||||||
|
|
||||||
|
constexpr S *p0 = &s;
|
||||||
|
|
||||||
|
constexpr int *q0 = p0->b; // { dg-bogus "reinterpret_cast from integer to pointer" }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace WeakRefTest1 {
|
||||||
|
|
||||||
|
extern __attribute__ ((weak)) int i;
|
||||||
|
|
||||||
|
constexpr int *p0 = &i;
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wextra"
|
||||||
|
// Suppress warning: ordered comparison of pointer with integer zero
|
||||||
|
|
||||||
|
constexpr bool b0 = p0; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b1 = p0 == 0; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b2 = p0 != 0; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b4 = p0 <= 0; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b5 = p0 > 0; // { dg-error "not a constant expression" }
|
||||||
|
|
||||||
|
constexpr bool b7 = !p0; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b8 = 0 == p0; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b9 = 0 != p0; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b10 = 0 < p0; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b13 = 0 >= p0; // { dg-error "not a constant expression" }
|
||||||
|
|
||||||
|
// The following are accepted as constant expressions due to bug c++/70196.
|
||||||
|
constexpr bool b3 = p0 < 0;
|
||||||
|
constexpr bool b6 = p0 >= 0;
|
||||||
|
constexpr bool b11 = 0 <= p0;
|
||||||
|
constexpr bool b12 = 0 > p0;
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace WeakRefTest2 {
|
||||||
|
|
||||||
|
extern __attribute__ ((weak)) int i;
|
||||||
|
|
||||||
|
constexpr int *p1 = &i + 1;
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wextra"
|
||||||
|
// Suppress warning: ordered comparison of pointer with integer zero
|
||||||
|
|
||||||
|
constexpr bool b0 = p1; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b1 = p1 == 0; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b2 = p1 != 0; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b4 = p1 <= 0; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b5 = p1 > 0; // { dg-error "not a constant expression" }
|
||||||
|
|
||||||
|
constexpr bool b7 = !p1; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b8 = 0 == p1; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b9 = 0 != p1; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b10 = 0 < p1; // { dg-error "not a constant expression" }
|
||||||
|
constexpr bool b13 = 0 >= p1; // { dg-error "not a constant expression" }
|
||||||
|
|
||||||
|
// The following are accepted as constant expressions due to bug c++/70196.
|
||||||
|
// constexpr bool b3 = p1 < 0;
|
||||||
|
// constexpr bool b6 = p1 >= 0;
|
||||||
|
// constexpr bool b11 = 0 <= p1;
|
||||||
|
// constexpr bool b12 = 0 > p1;
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
// PR c++/67376 - [5/6 regression] Comparison with pointer to past-the-end
|
||||||
|
// of array fails inside constant expression
|
||||||
|
// { dg-do compile { target c++11 } }
|
||||||
|
|
||||||
|
int a [2];
|
||||||
|
|
||||||
|
constexpr const int* pa[] = {
|
||||||
|
a,
|
||||||
|
a + 0,
|
||||||
|
a + 1,
|
||||||
|
a + 2,
|
||||||
|
&a [0],
|
||||||
|
&a [0] + 0,
|
||||||
|
&a [0] + 1,
|
||||||
|
&a [0] + 2,
|
||||||
|
&a [1],
|
||||||
|
&a [1] - 1,
|
||||||
|
&a [1] + 0,
|
||||||
|
&a [1] + 1,
|
||||||
|
&a [2] - 2,
|
||||||
|
&a [2] - 1,
|
||||||
|
&a [2] + 0
|
||||||
|
};
|
||||||
|
|
||||||
|
#define Assert(e) static_assert ((e), #e)
|
||||||
|
|
||||||
|
Assert (!(a == 0));
|
||||||
|
Assert (!(a == (int*)0));
|
||||||
|
Assert (!(a == nullptr));
|
||||||
|
|
||||||
|
Assert (a != 0);
|
||||||
|
Assert (a != (int*)0);
|
||||||
|
Assert (a != nullptr);
|
||||||
|
|
||||||
|
Assert (!(0 == a));
|
||||||
|
Assert (!((int*)0 == a));
|
||||||
|
Assert (!(nullptr == a));
|
||||||
|
|
||||||
|
Assert (0 != a);
|
||||||
|
Assert ((int*)0 != a);
|
||||||
|
Assert (nullptr != a);
|
||||||
|
|
||||||
|
bool constexpr test_eq (unsigned inx)
|
||||||
|
{
|
||||||
|
return inx ? pa [inx - 1] == 0 && 0 == pa [inx - 1]
|
||||||
|
&& test_eq (inx - 1) : pa [inx] == 0 && 0 == pa [inx];
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert (!test_eq (sizeof pa / sizeof *pa));
|
||||||
|
|
||||||
|
bool constexpr test_ne (unsigned inx)
|
||||||
|
{
|
||||||
|
return inx ? pa [inx - 1] != 0 && 0 != pa [inx - 1]
|
||||||
|
&& test_ne (inx - 1) : pa [inx] != 0 && 0 != pa [inx];
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert (test_ne (sizeof pa / sizeof *pa));
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
// Reliable ICE
|
// Reliable ICE
|
||||||
constexpr int n[3] = {};
|
constexpr int n[3] = {};
|
||||||
constexpr int k = n[-1]; // { dg-error "negative" }
|
constexpr int k = n[-1]; // { dg-error "array subscript" }
|
||||||
|
|
||||||
// Some random byte
|
// Some random byte
|
||||||
constexpr char c = "foo"[-1000]; // { dg-error "negative" }
|
constexpr char c = "foo"[-1000]; // { dg-error "array subscript" }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,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 "-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" } }
|
||||||
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
constexpr char c1 = "hi"[1];
|
constexpr char c1 = "hi"[1];
|
||||||
constexpr char c2 = "hi"[2];
|
constexpr char c2 = "hi"[2];
|
||||||
constexpr char c3 = "hi"[3]; // { dg-error "out of bound" }
|
constexpr char c3 = "hi"[3]; // { dg-error "array subscript" }
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// PR c++/48570
|
// PR c++/48570
|
||||||
// { dg-do compile { target c++11 } }
|
// { dg-do compile { target c++11 } }
|
||||||
|
|
||||||
constexpr wchar_t c1 = L"hi"[3]; // { dg-error "out of bound" }
|
constexpr wchar_t c1 = L"hi"[3]; // { dg-error "array subscript" }
|
||||||
constexpr char16_t c2 = u"hi"[3]; // { dg-error "out of bound" }
|
constexpr char16_t c2 = u"hi"[3]; // { dg-error "array subscript" }
|
||||||
constexpr char32_t c3 = U"hi"[3]; // { dg-error "out of bound" }
|
constexpr char32_t c3 = U"hi"[3]; // { dg-error "array subscript" }
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,12 @@ constexpr char c5 = *(&s[2] + 0);
|
||||||
constexpr char c6 = *(&s[0] + 2);
|
constexpr char c6 = *(&s[0] + 2);
|
||||||
constexpr char c7 = *(&s[2] + 1);
|
constexpr char c7 = *(&s[2] + 1);
|
||||||
|
|
||||||
constexpr char d1 = *(&s[4] - 0); // { dg-error "array subscript out of bound" }
|
constexpr char d1 = *(&s[4] - 0); // { dg-error "array subscript" }
|
||||||
constexpr char d2 = *(&s[4] - 1);
|
constexpr char d2 = *(&s[4] - 1);
|
||||||
constexpr char d3 = *(&s[4] - 2);
|
constexpr char d3 = *(&s[4] - 2);
|
||||||
constexpr char d4 = *(&s[4] - 3);
|
constexpr char d4 = *(&s[4] - 3);
|
||||||
constexpr char d5 = *(&s[4] - 4);
|
constexpr char d5 = *(&s[4] - 4);
|
||||||
constexpr char d6 = *(&s[4] - 5); // { dg-error "negative array subscript" }
|
constexpr char d6 = *(&s[4] - 5); // { dg-error "array subscript" }
|
||||||
|
|
||||||
/* Don't accept invalid stuff. */
|
/* Don't accept invalid stuff. */
|
||||||
constexpr char e1 = *(&s[5] - 1); // { dg-error "is not a constant expression" }
|
constexpr char e1 = *(&s[5] - 1); // { dg-error "is not a constant expression" }
|
||||||
|
|
@ -45,12 +45,12 @@ constexpr int i5 = *(&l[2] + 0);
|
||||||
constexpr int i6 = *(&l[0] + 2);
|
constexpr int i6 = *(&l[0] + 2);
|
||||||
constexpr int i7 = *(&l[2] + 1);
|
constexpr int i7 = *(&l[2] + 1);
|
||||||
|
|
||||||
constexpr char j1 = *(&l[4] - 0); // { dg-error "array subscript out of bound" }
|
constexpr char j1 = *(&l[4] - 0); // { dg-error "array subscript" }
|
||||||
constexpr char j2 = *(&l[4] - 1);
|
constexpr char j2 = *(&l[4] - 1);
|
||||||
constexpr char j3 = *(&l[4] - 2);
|
constexpr char j3 = *(&l[4] - 2);
|
||||||
constexpr char j4 = *(&l[4] - 3);
|
constexpr char j4 = *(&l[4] - 3);
|
||||||
constexpr char j5 = *(&l[4] - 4);
|
constexpr char j5 = *(&l[4] - 4);
|
||||||
constexpr char j6 = *(&l[4] - 5); // { dg-error "negative array subscript" }
|
constexpr char j6 = *(&l[4] - 5); // { dg-error "array subscript" }
|
||||||
|
|
||||||
/* Don't accept invalid stuff. */
|
/* Don't accept invalid stuff. */
|
||||||
constexpr char k1 = *(&l[5] - 1); // { dg-error "is not a constant expression" }
|
constexpr char k1 = *(&l[5] - 1); // { dg-error "is not a constant expression" }
|
||||||
|
|
|
||||||
|
|
@ -27,4 +27,4 @@ fn_not_ok (int n)
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int n1 = fn_ok (3);
|
constexpr int n1 = fn_ok (3);
|
||||||
constexpr int n2 = fn_not_ok (3); // { dg-error "array subscript out of bound" }
|
constexpr int n2 = fn_not_ok (3); // { dg-error "array subscript" }
|
||||||
|
|
|
||||||
|
|
@ -18,4 +18,4 @@ fn_ok (int n)
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int i1 = fn_ok (3);
|
constexpr int i1 = fn_ok (3);
|
||||||
constexpr int i2 = fn_bad (3); // { dg-error "array subscript out of bound" }
|
constexpr int i2 = fn_bad (3); // { dg-error "array subscript" }
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,4 @@ foo (int n)
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int n = foo (3); // { dg-error "array subscript out of bound" }
|
constexpr int n = foo (3); // { dg-error "array subscript" }
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ fn5 (const int *a, int b)
|
||||||
|
|
||||||
constexpr int m1[4] = { 1, 2, 3, 4 };
|
constexpr int m1[4] = { 1, 2, 3, 4 };
|
||||||
constexpr int m2 = fn5 (m1, 3);
|
constexpr int m2 = fn5 (m1, 3);
|
||||||
constexpr int m3 = fn5 (m1, 4); // { dg-error "array subscript out of bound" }
|
constexpr int m3 = fn5 (m1, 4); // { dg-error "array subscript" }
|
||||||
|
|
||||||
constexpr int
|
constexpr int
|
||||||
fn6 (const int &a, int b)
|
fn6 (const int &a, int b)
|
||||||
|
|
@ -116,7 +116,7 @@ fn8 (int i)
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int o1 = fn8 (9);
|
constexpr int o1 = fn8 (9);
|
||||||
constexpr int o2 = fn8 (10); // { dg-error "array subscript out of bound" }
|
constexpr int o2 = fn8 (10); // { dg-error "array subscript" }
|
||||||
|
|
||||||
constexpr int
|
constexpr int
|
||||||
fn9 (int a, int b)
|
fn9 (int a, int b)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue