In this testcase, cxx_fold_indirect_ref was failing to fold away the *& implied in (IdHdr) because the result type and the type of the variable were different: the result type was an array of unknown bound, because the expression was built before the length of the initializer was known, but we're trying to fold the expression after we've figured out the length. It seems appropriate to recognize and handle this situation.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 77291d4ac23a6b0cf8fa8adaba8458af03c558c7
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Jan 8 17:31:33 2016 -0500

    	PR c++/69158
    	* constexpr.c (cxx_fold_indirect_ref): Handle array type differing
    	in completion.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index c6c3467..7b5594e 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -2382,7 +2382,15 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
       if (TREE_CODE (op) == CONST_DECL)
 	return DECL_INITIAL (op);
       /* *&p => p;  make sure to handle *&"str"[cst] here.  */
-      if (same_type_ignoring_top_level_qualifiers_p (optype, type))
+      if (same_type_ignoring_top_level_qualifiers_p (optype, type)
+	  /* Also handle the case where the desired type is an array of unknown
+	     bounds because the variable has had its bounds deduced since the
+	     ADDR_EXPR was created.  */
+	  || (TREE_CODE (type) == ARRAY_TYPE
+	      && TREE_CODE (optype) == ARRAY_TYPE
+	      && TYPE_DOMAIN (type) == NULL_TREE
+	      && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (optype),
+							    TREE_TYPE (type))))
 	{
 	  tree fop = fold_read_from_constant_string (op);
 	  if (fop)
diff --git a/gcc/testsuite/g++.dg/init/array40.C b/gcc/testsuite/g++.dg/init/array40.C
new file mode 100644
index 0000000..5c976e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array40.C
@@ -0,0 +1,2 @@
+// PR c++/69158
+char IdHdr[] = { (IdHdr)[0] };

Reply via email to