Patchwork C++ PATCH for c++/49988 (constexpr causing wrong code)

login
register
mail settings
Submitter Jason Merrill
Date Aug. 6, 2011, 4:28 a.m.
Message ID <4E3CC2E8.2070004@redhat.com>
Download mbox | patch
Permalink /patch/108756/
State New
Headers show

Comments

Jason Merrill - Aug. 6, 2011, 4:28 a.m.
The constexpr on the A constructor led us to try to expand the call in 
the B constructor to a constant.  But in that call we're passing the B 
parameter s, which is not constant, so it should just fail quietly.  But 
instead we were trying to treat it as a STRING_CST, which causes an ICE 
with checking enabled, or wrong code with checking off.

Tested x86_64-pc-linux-gnu, applying to trunk and 4.6.  On the 4.6 
branch I replaced the gcc_unreachable with just returning t to be extra 
conservative.

Patch

commit 15dfe0b93a072a167d7a818799487119f516231d
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Aug 5 16:12:24 2011 -0400

    	PR c++/49988
    	* semantics.c (cxx_eval_array_reference): Handle failure to
    	reduce the array operand to something we can work with.

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index ac24b77..2f02e69 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6428,12 +6428,19 @@  cxx_eval_array_reference (const constexpr_call *call, tree t,
   elem_type = TREE_TYPE (TREE_TYPE (ary));
   if (TREE_CODE (ary) == CONSTRUCTOR)
     len = CONSTRUCTOR_NELTS (ary);
-  else
+  else if (TREE_CODE (ary) == STRING_CST)
     {
       elem_nchars = (TYPE_PRECISION (elem_type)
 		     / TYPE_PRECISION (char_type_node));
       len = (unsigned) TREE_STRING_LENGTH (ary) / elem_nchars;
     }
+  else
+    {
+      /* We can't do anything with other tree codes, so use
+	 VERIFY_CONSTANT to complain and fail.  */
+      VERIFY_CONSTANT (ary);
+      gcc_unreachable ();
+    }
   if (compare_tree_int (index, len) >= 0)
     {
       if (tree_int_cst_lt (index, array_type_nelts_top (TREE_TYPE (ary))))
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg3.C
new file mode 100644
index 0000000..581be6d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg3.C
@@ -0,0 +1,23 @@ 
+// PR c++/49988
+// { dg-options -std=c++0x }
+// { dg-do run }
+
+template<int ... I> struct X { };
+
+struct A {
+  char data[3];
+  template<int ... I>
+    constexpr
+    A(const char (&s)[3], X<I...> x) : data{ s[I]...} { }
+};
+struct B {
+  A a;
+  B(const char (&s)[3]) : a{s,X<0,1,2>{}} { }
+};
+
+int main()
+{
+  B b{"12"};
+  if (b.a.data[0] != '1')
+    return 1;
+}