diff mbox

C++ PATCH for c++/46873, 46877 (ICE with constexpr constructor)

Message ID 4D068619.9070004@redhat.com
State New
Headers show

Commit Message

Jason Merrill Dec. 13, 2010, 8:46 p.m. UTC
We can also get a NOP_EXPR for the initialized member if the data member 
is const, so we need to handle that.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit e84b5c98c91b6d48e532ba5ade0e05b7d2b116f2
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Dec 13 13:52:09 2010 -0500

    	PR c++/46873
    	PR c++/46877
    	* semantics.c (build_data_member_initialization): Handle
    	cv-qualified data member.
diff mbox

Patch

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 1b3bfa3..27e2982 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5483,49 +5483,43 @@  build_data_member_initialization (tree t, VEC(constructor_elt,gc) **vec)
     {
       member = TREE_OPERAND (t, 0);
       init = unshare_expr (TREE_OPERAND (t, 1));
-      if (TREE_CODE (member) == INDIRECT_REF)
-	{
-	  tree op = TREE_OPERAND (member, 0);
-	  STRIP_NOPS (op);
-	  gcc_assert (TREE_CODE (op) == ADDR_EXPR);
-	  op = TREE_OPERAND (op, 0);
-	  if (TREE_CODE (op) == COMPONENT_REF)
-	    /* Initializing a cv-qualified member; we just looked through
-	       the const_cast.  */
-	    member = op;
-	  else
-	    {
-	      /* Initializing an empty base; just skip it.  */
-	      gcc_assert (is_empty_class (TREE_TYPE (member)));
-	      return true;
-	    }
-	}
     }
   else
     {
-      tree memtype;
       gcc_assert (TREE_CODE (t) == CALL_EXPR);
       member = CALL_EXPR_ARG (t, 0);
-      memtype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (member)));
-      if (TREE_CODE (member) == NOP_EXPR)
-	{
-	  /* We don't put out anything for an empty base.  */
-	  gcc_assert (is_empty_class (memtype));
-	  /* But if the constructor used isn't constexpr, leave in the call
-	     so we complain later.  */
-	  if (potential_constant_expression (t, tf_none))
-	    return true;
-	}
-      else
-	{
-	  gcc_assert (TREE_CODE (member) == ADDR_EXPR);
-	  member = TREE_OPERAND (member, 0);
-	}
       /* We don't use build_cplus_new here because it complains about
-	 abstract bases.  T has the wrong type, but
-	 cxx_eval_constant_expression doesn't care.  */
+	 abstract bases.  Leaving the call unwrapped means that it has the
+	 wrong type, but cxx_eval_constant_expression doesn't care.  */
       init = unshare_expr (t);
     }
+  if (TREE_CODE (member) == INDIRECT_REF)
+    member = TREE_OPERAND (member, 0);
+  if (TREE_CODE (member) == NOP_EXPR)
+    {
+      tree op = member;
+      STRIP_NOPS (op);
+      if (TREE_CODE (op) == ADDR_EXPR)
+	{
+	  gcc_assert (same_type_ignoring_top_level_qualifiers_p
+		      (TREE_TYPE (TREE_TYPE (op)),
+		       TREE_TYPE (TREE_TYPE (member))));
+	  /* Initializing a cv-qualified member; we need to look through
+	     the const_cast.  */
+	  member = op;
+	}
+      else
+	{
+	  /* We don't put out anything for an empty base.  */
+	  gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (member))));
+	  /* But if the initializer isn't constexpr, leave it in so we
+	     complain later.  */
+	  if (potential_constant_expression (init, tf_none))
+	    return true;
+	}
+    }
+  if (TREE_CODE (member) == ADDR_EXPR)
+    member = TREE_OPERAND (member, 0);
   if (TREE_CODE (member) == COMPONENT_REF)
     member = TREE_OPERAND (member, 1);
   CONSTRUCTOR_APPEND_ELT (*vec, member, init);
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor4.C
new file mode 100644
index 0000000..397b4b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor4.C
@@ -0,0 +1,15 @@ 
+// PR c++/46873
+// { dg-options -std=c++0x }
+
+struct S
+{
+  int i:1;
+};
+
+struct T
+{
+  const S s;
+  constexpr T (S a = S ()) : s (a) { }
+};
+
+T t;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor5.C
new file mode 100644
index 0000000..36b0178
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor5.C
@@ -0,0 +1,30 @@ 
+// PR c++/46877
+// { dg-options -std=c++0x }
+
+struct new_allocator
+{
+  constexpr new_allocator ();
+};
+
+struct string
+{
+  constexpr string ()
+  {
+  }
+  new_allocator a;
+};
+
+struct pair
+{
+  const string first;
+  constexpr pair ()
+  {
+  }
+};
+
+constexpr
+new_allocator::new_allocator ()
+{
+}
+
+pair p;