public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* RFA (fold): PATCH for c++/49290 (folding *(T*)(ar+10))
@ 2011-06-07  5:39 Jason Merrill
  2011-06-07 10:20 ` Richard Guenther
  0 siblings, 1 reply; 35+ messages in thread
From: Jason Merrill @ 2011-06-07  5:39 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 1097 bytes --]

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?


[-- Attachment #2: 49290.patch --]
[-- Type: text/x-patch, Size: 6429 bytes --]

commit 7881846ebf44868b0a27f727064d84c271127c65
Author: Jason Merrill <jason@redhat.com>
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<vectorfoo,...> */
       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<vectorfoo,...> */
 	  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);

^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2011-06-20  9:22 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-07  5:39 RFA (fold): PATCH for c++/49290 (folding *(T*)(ar+10)) Jason Merrill
2011-06-07 10:20 ` Richard Guenther
2011-06-07 10:27   ` Jakub Jelinek
2011-06-07 12:03     ` Richard Guenther
2011-06-07 12:22       ` Richard Guenther
2011-06-07 13:46         ` Michael Matz
2011-06-07 13:49           ` Richard Guenther
2011-06-07 13:55   ` Jason Merrill
2011-06-07 14:05     ` Richard Guenther
2011-06-07 14:24       ` Jason Merrill
2011-06-09 19:47         ` Jason Merrill
2011-06-10  8:53           ` Richard Guenther
2011-06-10 14:03             ` Jason Merrill
2011-06-10 14:20               ` Richard Guenther
2011-06-10 14:32                 ` Jason Merrill
2011-06-10 14:34                   ` Richard Guenther
2011-06-10 14:45                     ` Jason Merrill
2011-06-11 18:24                     ` Mike Stump
2011-06-12 11:03                       ` Richard Guenther
2011-06-13  7:29                         ` Mike Stump
2011-06-13 12:46                           ` Richard Guenther
2011-06-14 20:31                             ` Mike Stump
2011-06-15  9:54                               ` Richard Guenther
2011-06-15 18:57                                 ` Mike Stump
2011-06-16  7:39                                   ` Richard Guenther
2011-06-17 14:17                                     ` Michael Matz
2011-06-20 10:24                                       ` Richard Guenther
2011-06-12  7:58                     ` Is VIEW_CONVERT_EXPR an lvalue? (was Re: RFA (fold): PATCH for c++/49290 (folding *(T*)(ar+10))) Jason Merrill
2011-06-12 13:18                       ` Richard Guenther
2011-06-12 13:22                         ` Richard Guenther
2011-06-13  6:12                           ` Mike Stump
2011-06-12 22:42                         ` Jason Merrill
2011-06-13 12:44                           ` Richard Guenther
2011-06-13 17:59                             ` RFA (fold): PATCH for c++/49290 (folding *(T*)(ar+10)) Jason Merrill
2011-06-14  9:10                               ` Richard Guenther

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).