From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5689 invoked by alias); 7 Jun 2011 05:39:52 -0000 Received: (qmail 5533 invoked by uid 22791); 7 Jun 2011 05:39:50 -0000 X-SWARE-Spam-Status: No, hits=-6.4 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,T_RP_MATCHES_RCVD 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; Tue, 07 Jun 2011 05:39:29 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p575dSVu018997 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 7 Jun 2011 01:39:28 -0400 Received: from [127.0.0.1] (ovpn-113-53.phx2.redhat.com [10.3.113.53]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p575dRlR031356; Tue, 7 Jun 2011 01:39:28 -0400 Message-ID: <4DEDB98F.6010508@redhat.com> Date: Tue, 07 Jun 2011 05:39:00 -0000 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110428 Fedora/3.1.10-1.fc14 Lightning/1.0b2 Thunderbird/3.1.10 MIME-Version: 1.0 To: Richard Guenther CC: gcc-patches List Subject: RFA (fold): PATCH for c++/49290 (folding *(T*)(ar+10)) Content-Type: multipart/mixed; boundary="------------010203030804030501090005" 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 X-SW-Source: 2011-06/txt/msg00476.txt.bz2 This is a multi-part message in MIME format. --------------010203030804030501090005 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1097 In the testcase, fold_indirect_ref_1 won't fold *(T*)(s1+10) to an ARRAY_REF because T != unsigned. Even if it were just a typedef to unsigned, that isn't close enough, but in this case it's a typedef to const unsigned. I'm not sure what the type coherence rules are for ARRAY_REF. Is it really necessary that the type of the ARRAY_REF match exactly the element type of the array? In any case, constexpr expansion can be more flexible about type coherence because it is just trying to get a constant value; if that doesn't work out, we throw it away and fall back on the original expression. We already handle some cases in cxx_eval_indirect_ref that aren't appropriate for fold_indirect_ref_1, but this testcase demonstrates that we also want to adjust the cases that are handled by that function. So my options would seem to be either duplicating the whole of fold_indirect_ref_1, which tempts undesirable divergence, or adding a flag to that function to enable the more permissive type checking that the constexpr code wants. Does this seem like a reasonable thing to do? --------------010203030804030501090005 Content-Type: text/x-patch; name="49290.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="49290.patch" Content-length: 6429 commit 7881846ebf44868b0a27f727064d84c271127c65 Author: Jason Merrill Date: Tue Jun 7 00:00:36 2011 -0400 PR c++/49290 gcc/ * fold-const.c (fold_indirect_ref_maybe_permissive): Split out from... (fold_indirect_ref_1): ...here. * tree.h: Declare fold_indirect_ref_maybe_permissive. gcc/cp/ * semantics.c (cxx_eval_indirect_ref): Use fold_indirect_ref_maybe_permissive. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index f005f2f..d979c18 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -6765,6 +6765,7 @@ cxx_eval_indirect_ref (const constexpr_call *call, tree t, /*addr*/false, non_constant_p); tree type, sub, subtype, r; bool empty_base; + location_t loc = EXPR_LOCATION (t); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p) @@ -6843,8 +6844,8 @@ cxx_eval_indirect_ref (const constexpr_call *call, tree t, /* Let build_fold_indirect_ref handle the cases it does fine with. */ if (r == NULL_TREE) - r = build_fold_indirect_ref (op0); - if (TREE_CODE (r) != INDIRECT_REF) + r = fold_indirect_ref_maybe_permissive (loc, type, op0, true); + if (r) r = cxx_eval_constant_expression (call, r, allow_non_constant, addr, non_constant_p); else if (TREE_CODE (sub) == ADDR_EXPR @@ -6871,7 +6872,7 @@ cxx_eval_indirect_ref (const constexpr_call *call, tree t, TREE_CONSTANT (r) = true; } - if (TREE_CODE (r) == INDIRECT_REF && TREE_OPERAND (r, 0) == orig_op0) + if (r == NULL_TREE) return t; return r; } diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 9a3f8cb..ef880fc 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -15555,14 +15555,19 @@ fold_build_cleanup_point_expr (tree type, tree expr) /* Given a pointer value OP0 and a type TYPE, return a simplified version of an indirection through OP0, or NULL_TREE if no simplification is - possible. */ + possible. If PERMISSIVE is true, allow some variation in types. */ tree -fold_indirect_ref_1 (location_t loc, tree type, tree op0) +fold_indirect_ref_maybe_permissive (location_t loc, tree type, tree op0, + bool permissive) { tree sub = op0; tree subtype; +#define SAME_TYPE(X,Y) (permissive \ + ? TYPE_MAIN_VARIANT (X) == TYPE_MAIN_VARIANT (Y) \ + : (X) == (Y)) + STRIP_NOPS (sub); subtype = TREE_TYPE (sub); if (!POINTER_TYPE_P (subtype)) @@ -15586,7 +15591,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) } /* *(foo *)&fooarray => fooarray[0] */ else if (TREE_CODE (optype) == ARRAY_TYPE - && type == TREE_TYPE (optype) + && SAME_TYPE (type, TREE_TYPE (optype)) && (!in_gimple_form || TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)) { @@ -15602,11 +15607,11 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) } /* *(foo *)&complexfoo => __real__ complexfoo */ else if (TREE_CODE (optype) == COMPLEX_TYPE - && type == TREE_TYPE (optype)) + && SAME_TYPE (type, TREE_TYPE (optype))) return fold_build1_loc (loc, REALPART_EXPR, type, op); /* *(foo *)&vectorfoo => BIT_FIELD_REF */ else if (TREE_CODE (optype) == VECTOR_TYPE - && type == TREE_TYPE (optype)) + && SAME_TYPE (type, TREE_TYPE (optype))) { tree part_width = TYPE_SIZE (type); tree index = bitsize_int (0); @@ -15629,7 +15634,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF */ if (TREE_CODE (op00type) == VECTOR_TYPE - && type == TREE_TYPE (op00type)) + && SAME_TYPE (type, TREE_TYPE (op00type))) { HOST_WIDE_INT offset = tree_low_cst (op01, 0); tree part_width = TYPE_SIZE (type); @@ -15645,7 +15650,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) } /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */ else if (TREE_CODE (op00type) == COMPLEX_TYPE - && type == TREE_TYPE (op00type)) + && SAME_TYPE (type, TREE_TYPE (op00type))) { tree size = TYPE_SIZE_UNIT (type); if (tree_int_cst_equal (size, op01)) @@ -15653,7 +15658,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) } /* ((foo *)&fooarray)[1] => fooarray[1] */ else if (TREE_CODE (op00type) == ARRAY_TYPE - && type == TREE_TYPE (op00type)) + && SAME_TYPE (type, TREE_TYPE (op00type))) { tree type_domain = TYPE_DOMAIN (op00type); tree min_val = size_zero_node; @@ -15670,7 +15675,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) /* *(foo *)fooarrptr => (*fooarrptr)[0] */ if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE - && type == TREE_TYPE (TREE_TYPE (subtype)) + && SAME_TYPE (type, TREE_TYPE (TREE_TYPE (subtype))) && (!in_gimple_form || TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)) { @@ -15690,6 +15695,12 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) return NULL_TREE; } +tree +fold_indirect_ref_1 (location_t loc, tree type, tree op0) +{ + return fold_indirect_ref_maybe_permissive (loc, type, op0, false); +} + /* Builds an expression for an indirection through T, simplifying some cases. */ diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C new file mode 100644 index 0000000..75e6f43 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C @@ -0,0 +1,20 @@ +// PR c++/49290 +// { dg-options -std=c++0x } + +typedef const unsigned T; +struct S +{ + constexpr T foo (void); + unsigned s1[16]; +}; + +constexpr T +S::foo () +{ + return *(T *) (s1 + 10); +} + +constexpr S s = { 0,1,2,3,4,5,6,7,8,9,10 }; + +#define SA(X) static_assert ((X), #X) +SA(s.foo() == 10); diff --git a/gcc/tree.h b/gcc/tree.h index c7338ba..5b20a07 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -5172,6 +5172,7 @@ extern tree fold_single_bit_test (location_t, enum tree_code, tree, tree, tree); extern tree fold_ignored_result (tree); extern tree fold_abs_const (tree, tree); extern tree fold_indirect_ref_1 (location_t, tree, tree); +extern tree fold_indirect_ref_maybe_permissive (location_t, tree, tree, bool); extern void fold_defer_overflow_warnings (void); extern void fold_undefer_overflow_warnings (bool, const_gimple, int); extern void fold_undefer_and_ignore_overflow_warnings (void); --------------010203030804030501090005--