From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 106422 invoked by alias); 31 Mar 2016 17:53:15 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 106407 invoked by uid 89); 31 Mar 2016 17:53:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 spammy=msebor@redhat.com, mseborredhatcom, Reliable X-HELO: mail-qg0-f52.google.com Received: from mail-qg0-f52.google.com (HELO mail-qg0-f52.google.com) (209.85.192.52) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Thu, 31 Mar 2016 17:53:11 +0000 Received: by mail-qg0-f52.google.com with SMTP id n34so63774956qge.1 for ; Thu, 31 Mar 2016 10:53:10 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:to:references:cc:from:message-id:date :user-agent:mime-version:in-reply-to; bh=XVSZ1wCaMI+HbiHeITO4N/d/6niZZtVgj5XUkCyhtV4=; b=EEw/pvJbnBGa9ELiXX//niRO/cGYnMPPn9ud/bnihKrwaug6XHNMoA5mRDn7WhT0am PpOETlIMxzH6K7ZUGivPUQKTI+JBN+cp27frttGsLR5jo1+eQpCsXut9758PQiFNJ+fE Yf4NUCHaDeJO6wk204WlzzIEbNN5OZWB7eptorZc43vI1GwBiM8X3QXCnEO3en2bKxdh mwXip/0P62Ksqd2CSeiYj2/ncrpnAdrQeGIff1AaIaWjY0vlwJUq6c/ePpcKOsPEsn9Y pLsMecFsmoC3HUet6aV8j+iXpVw599eKlLBNB+wkM+eI6tH9reeFpzj8D1m9b8NDcCuE 7Y3A== X-Gm-Message-State: AD7BkJIBWYDvnv7CHQna97TYiHBN3MO+TyBzyjUi0Llpi/QhujW+1p9mDbn+ZkiK3T4oPA== X-Received: by 10.140.217.202 with SMTP id n193mr19470881qhb.101.1459446788917; Thu, 31 Mar 2016 10:53:08 -0700 (PDT) Received: from [192.168.0.26] (97-124-173-67.hlrn.qwest.net. [97.124.173.67]) by smtp.gmail.com with ESMTPSA id h5sm4365311qge.48.2016.03.31.10.53.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 31 Mar 2016 10:53:08 -0700 (PDT) Subject: Re: [PATCH] c++/67376 Comparison with pointer to past-the-end, of array fails inside constant expression To: Jason Merrill , Jeff Law , Gcc Patch List References: <56E72C33.8000301@gmail.com> <56E9B9C3.5000908@redhat.com> <56EB1ECA.90800@gmail.com> <56EC3500.4030701@redhat.com> <56F03567.8040306@redhat.com> <56F07137.1050400@redhat.com> <56F19456.3030900@redhat.com> <56F1A494.1060407@gmail.com> <56F2EC3C.5000606@redhat.com> <56F9AA63.4090201@gmail.com> <56FACF51.5000407@redhat.com> <56FB4EBE.9000500@gmail.com> <56FBF112.6080806@redhat.com> <56FBFFB2.2060301@gmail.com> <56FC2847.8000705@redhat.com> <56FC5840.6000503@gmail.com> <56FCA61A.4060106@redhat.com> Cc: Marek Polacek , Jakub Jelinek From: Martin Sebor Message-ID: <56FD6401.5090705@gmail.com> Date: Thu, 31 Mar 2016 19:30:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.1.0 MIME-Version: 1.0 In-Reply-To: <56FCA61A.4060106@redhat.com> Content-Type: multipart/mixed; boundary="------------070804020300090808090703" X-IsSubscribed: yes X-SW-Source: 2016-03/txt/msg01713.txt.bz2 This is a multi-part message in MIME format. --------------070804020300090808090703 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1471 >>>> + /* 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. */ >>>> + && (TREE_CODE (op0) != ADDR_EXPR >>>> + || TREE_CODE (TREE_OPERAND (op0, 0)) != COMPONENT_REF >>>> + || compare_tree_int (DECL_FIELD_OFFSET ((TREE_OPERAND >>>> + (TREE_OPERAND (op0, 0), 1))), 0)) >>> >>> Can we look at offset/bitpos here rather than examine the tree structure >>> of op0? get_inner_reference already examined it for us. >> >> Good suggestion, thanks! > > But you're still examining the tree structure: > >> + && (TREE_CODE (op0) != ADDR_EXPR >> + || TREE_CODE (TREE_OPERAND (op0, 0)) != COMPONENT_REF >> + || bitpos0 != 0) > > Here instead of looking at op0 we can check (offset0 == NULL_TREE && > bitpos0 != 0), which indicates a constant non-zero offset. > >> + && TREE_CODE (arg1) == INTEGER_CST >> + && integer_zerop (arg1)) > > And here you don't need the check for INTEGER_CST. I've updated the patch to simplify the tests. I have to confess I don't yet find it straightforward to tell exactly which tests are essential to avoid an ICE and which ones can safely be simplified. Martin --------------070804020300090808090703 Content-Type: text/x-patch; name="gcc-67376.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="gcc-67376.patch" Content-length: 21886 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-03-31 Martin Sebor 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-03-31 Martin Sebor 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-03-31 Martin Sebor 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. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 8ea7111..5d1b8b3 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1837,6 +1837,30 @@ find_array_ctor_elt (tree ary, tree dindex, bool insert = false) 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. Attempt to reduce a reference to an array slot. */ @@ -1885,8 +1909,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, if (!tree_fits_shwi_p (index) || (i = tree_to_shwi (index)) < 0) { - if (!ctx->quiet) - error ("negative array subscript"); + diag_array_subscript (ctx, ary, index); *non_constant_p = true; return t; } @@ -1898,8 +1921,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, VERIFY_CONSTANT (nelts); if (!tree_int_cst_lt (index, nelts)) { - if (!ctx->quiet) - error ("array subscript out of bound"); + diag_array_subscript (ctx, ary, index); *non_constant_p = true; return t; } diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 44fe2a2..eb66143 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8336,6 +8336,20 @@ pointer_may_wrap_p (tree base, tree offset, HOST_WIDE_INT bitpos) 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 transformations that are common to the equality/inequality operators (EQ_EXPR and NE_EXPR) and the ordering operators @@ -8636,6 +8650,39 @@ fold_comparison (location_t loc, enum tree_code code, tree type, base1 = build_fold_addr_expr_loc (loc, 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 @@ -13506,16 +13553,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. Don't do anything for variables and functions before symtab is built; it is quite possible that they will be declared weak later. */ - if (DECL_P (base) && decl_in_symtab_p (base)) - { - struct symtab_node *symbol; - - symbol = symtab_node::get_create (base); - if (symbol) - return symbol->nonzero_address (); - else - return false; - } + int nonzero_addr = maybe_nonzero_address (base); + if (nonzero_addr >= 0) + return nonzero_addr; /* Function local objects are never NULL. */ if (DECL_P (base) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C new file mode 100644 index 0000000..f75b3c3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr10.C @@ -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 + +} diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr9.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr9.C new file mode 100644 index 0000000..f0250cb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr9.C @@ -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)); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array5.C index 4605b4b..00dfd6d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array5.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array5.C @@ -3,7 +3,7 @@ // Reliable ICE constexpr int n[3] = {}; -constexpr int k = n[-1]; // { dg-error "negative" } +constexpr int k = n[-1]; // { dg-error "array subscript" } // Some random byte -constexpr char c = "foo"[-1000]; // { dg-error "negative" } +constexpr char c = "foo"[-1000]; // { dg-error "array subscript" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-1.C new file mode 100644 index 0000000..420a04b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-1.C @@ -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" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C index 0f561a4..41fa466 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C @@ -2,4 +2,4 @@ constexpr char c1 = "hi"[1]; constexpr char c2 = "hi"[2]; -constexpr char c3 = "hi"[3]; // { dg-error "out of bound" } +constexpr char c3 = "hi"[3]; // { dg-error "array subscript" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C index db79a9c..4055e0e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C @@ -1,6 +1,6 @@ // PR c++/48570 // { dg-do compile { target c++11 } } -constexpr wchar_t c1 = L"hi"[3]; // { dg-error "out of bound" } -constexpr char16_t c2 = u"hi"[3]; // { dg-error "out of bound" } -constexpr char32_t c3 = U"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 "array subscript" } +constexpr char32_t c3 = U"hi"[3]; // { dg-error "array subscript" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr65398.C b/gcc/testsuite/g++.dg/cpp0x/pr65398.C index a4aeba5..6bd34a4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr65398.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr65398.C @@ -12,12 +12,12 @@ constexpr char c5 = *(&s[2] + 0); constexpr char c6 = *(&s[0] + 2); 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 d3 = *(&s[4] - 2); constexpr char d4 = *(&s[4] - 3); 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. */ 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 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 j3 = *(&l[4] - 2); constexpr char j4 = *(&l[4] - 3); 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. */ constexpr char k1 = *(&l[5] - 1); // { dg-error "is not a constant expression" } diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla1.C b/gcc/testsuite/g++.dg/ext/constexpr-vla1.C index a5615bb..21eb93d 100644 --- a/gcc/testsuite/g++.dg/ext/constexpr-vla1.C +++ b/gcc/testsuite/g++.dg/ext/constexpr-vla1.C @@ -27,4 +27,4 @@ fn_not_ok (int n) } 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" } diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla2.C b/gcc/testsuite/g++.dg/ext/constexpr-vla2.C index 6cb1f70..6aab184 100644 --- a/gcc/testsuite/g++.dg/ext/constexpr-vla2.C +++ b/gcc/testsuite/g++.dg/ext/constexpr-vla2.C @@ -18,4 +18,4 @@ fn_ok (int n) } 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" } diff --git a/gcc/testsuite/g++.dg/ext/constexpr-vla3.C b/gcc/testsuite/g++.dg/ext/constexpr-vla3.C index ba4eb50..33fc968 100644 --- a/gcc/testsuite/g++.dg/ext/constexpr-vla3.C +++ b/gcc/testsuite/g++.dg/ext/constexpr-vla3.C @@ -11,4 +11,4 @@ foo (int n) return z; } -constexpr int n = foo (3); // { dg-error "array subscript out of bound" } +constexpr int n = foo (3); // { dg-error "array subscript" } diff --git a/gcc/testsuite/g++.dg/ubsan/pr63956.C b/gcc/testsuite/g++.dg/ubsan/pr63956.C index b265631..90360be 100644 --- a/gcc/testsuite/g++.dg/ubsan/pr63956.C +++ b/gcc/testsuite/g++.dg/ubsan/pr63956.C @@ -86,7 +86,7 @@ fn5 (const int *a, int b) constexpr int m1[4] = { 1, 2, 3, 4 }; 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 fn6 (const int &a, int b) @@ -116,7 +116,7 @@ fn8 (int i) } 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 fn9 (int a, int b) --------------070804020300090808090703--