From patchwork Mon Dec 19 05:56:15 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 132156 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 0FF3BB703B for ; Mon, 19 Dec 2011 16:56:44 +1100 (EST) Received: (qmail 15617 invoked by alias); 19 Dec 2011 05:56:40 -0000 Received: (qmail 15608 invoked by uid 22791); 19 Dec 2011 05:56:38 -0000 X-SWARE-Spam-Status: No, hits=-5.4 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 19 Dec 2011 05:56:18 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id pBJ5uH4A011146 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 19 Dec 2011 00:56:17 -0500 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id pBJ5uHWR014806 for ; Mon, 19 Dec 2011 00:56:17 -0500 Received: from [0.0.0.0] (ovpn-113-21.phx2.redhat.com [10.3.113.21]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id pBJ5uFcr006935 for ; Mon, 19 Dec 2011 00:56:16 -0500 Message-ID: <4EEED1FF.5000101@redhat.com> Date: Mon, 19 Dec 2011 00:56:15 -0500 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux i686; rv:8.0) Gecko/20111112 Thunderbird/8.0 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/51489 (pointer subtraction in constant expression) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org DR 1313 removes the blanket prohibition on pointer subtraction in constant expressions and replaces it with a prohibition on operations with undefined behavior, so this testcase ought to work. It wasn't working because our internal representation of pointer subtraction involves converting the pointers to ptrdiff_t before subtracting, and such a conversion is prohibited (previously specifically, now as a reinterpret_cast). There's currently no good way to distinguish between a user-written cast and the compiler-generated one, so I've moved the check to cxx_eval_outermost_constant_expr for now. Tested x86_64-pc-linux-gnu, applying to trunk. commit 502ce5b614044439f19eaec7c7241e414015a314 Author: Jason Merrill Date: Sun Dec 18 06:15:09 2011 -0500 PR c++/51489 * semantics.c (cxx_eval_outermost_constant_expr): Check for conversion from pointer to integer here. (cxx_eval_constant_expression) [NOP_EXPR]: Not here. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index ab9227f..a6462fc 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -7703,17 +7703,6 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, tree oldop = TREE_OPERAND (t, 0); tree op = oldop; tree to = TREE_TYPE (t); - tree source = TREE_TYPE (op); - if (TYPE_PTR_P (source) && ARITHMETIC_TYPE_P (to) - && !(TREE_CODE (op) == COMPONENT_REF - && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (op, 0))))) - { - if (!allow_non_constant) - error ("conversion of expression %qE of pointer type " - "cannot yield a constant expression", op); - *non_constant_p = true; - return t; - } op = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0), allow_non_constant, addr, non_constant_p); @@ -7802,6 +7791,20 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant) non_constant_p = true; } + /* Technically we should check this for all subexpressions, but that + runs into problems with our internal representation of pointer + subtraction and the 5.19 rules are still in flux. */ + if (CONVERT_EXPR_CODE_P (TREE_CODE (r)) + && ARITHMETIC_TYPE_P (TREE_TYPE (r)) + && TREE_CODE (TREE_OPERAND (r, 0)) == ADDR_EXPR) + { + if (!allow_non_constant) + error ("conversion from pointer type %qT " + "to arithmetic type %qT in a constant-expression", + TREE_TYPE (TREE_OPERAND (r, 0)), TREE_TYPE (r)); + non_constant_p = true; + } + if (non_constant_p && !allow_non_constant) return error_mark_node; else if (non_constant_p && TREE_CONSTANT (t)) @@ -8109,25 +8112,10 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case NOP_EXPR: case CONVERT_EXPR: case VIEW_CONVERT_EXPR: - /* -- an array-to-pointer conversion that is applied to an lvalue - that designates an object with thread or automatic storage - duration; FIXME not implemented as it breaks constexpr arrays; - need to fix the standard - -- a type conversion from a pointer or pointer-to-member type - to a literal type. */ + /* -- a reinterpret_cast. FIXME not implemented, and this rule + may change to something more specific to type-punning (DR 1312). */ { tree from = TREE_OPERAND (t, 0); - tree source = TREE_TYPE (from); - tree target = TREE_TYPE (t); - if (TYPE_PTR_P (source) && ARITHMETIC_TYPE_P (target) - && !(TREE_CODE (from) == COMPONENT_REF - && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (from, 0))))) - { - if (flags & tf_error) - error ("conversion of expression %qE of pointer type " - "cannot yield a constant expression", from); - return false; - } return (potential_constant_expression_1 (from, TREE_CODE (t) != VIEW_CONVERT_EXPR, flags)); } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub.C new file mode 100644 index 0000000..bccec73 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub.C @@ -0,0 +1,14 @@ +// PR c++/51489 +// DR 1313 +// { dg-options "-std=c++0x" } + +struct array +{ + constexpr array() :x(0) {} + constexpr int const* begin() { return &x; } + int x; +}; +constexpr array aa; +constexpr auto b = aa.begin(); +static_assert(b-b == 0, "compiles just fine"); +static_assert(aa.begin()-aa.begin() == 0, "compiler thinks it's not a constant expression");