Patchwork C++ PATCH to use VEC_INIT_EXPR for array mem-initializers

login
register
mail settings
Submitter Jason Merrill
Date Nov. 7, 2010, 12:46 a.m.
Message ID <4CD5F6EC.1030207@redhat.com>
Download mbox | patch
Permalink /patch/70339/
State New
Headers show

Comments

Jason Merrill - Nov. 7, 2010, 12:46 a.m.
On 10/26/2010 02:10 PM, Jason Merrill wrote:
> Our implementation of constexpr constructors involves walking the trees
> generated for the mem-initializers of a constructor and building up a
> simpler representation for use at expansion time. When we're dealing
> with an array member, this has meant trying to parse the output of
> build_vec_init, which is daunting. This patch changes
> perform_member_init to generate a VEC_INIT_EXPR instead, which is much
> easier to analyze.

That patch didn't deal with value-initialization; this patch extends it 
to do so.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit fbe525860f549b64222c7ecc45397c5cfb8e9e0f
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Nov 6 19:01:41 2010 -0400

    	* init.c (perform_member_init): Use build_vec_init_expr for
    	value-init of arrays, too.
    	* cp-gimplify.c (cp_gimplify_expr): Use VEC_INIT_EXPR_VALUE_INIT.
    	* cp-tree.h (VEC_INIT_EXPR_IS_CONSTEXPR): New macro.
    	(VEC_INIT_EXPR_VALUE_INIT): New macro.
    	* semantics.c (potential_constant_expression): No longer static.
    	Check VEC_INIT_EXPR_IS_CONSTEXPR.
    	* tree.c (build_vec_init_expr): Handle value-init.  Set
    	VEC_INIT_EXPR_IS_CONSTEXPR and VEC_INIT_EXPR_VALUE_INIT.

Patch

diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 705979d..557430d 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -535,7 +535,7 @@  cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 	gcc_assert (EXPR_HAS_LOCATION (*expr_p));
 	input_location = EXPR_LOCATION (*expr_p);
 	*expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE,
-				  init, /*explicit_value_init_p*/false,
+				  init, VEC_INIT_EXPR_VALUE_INIT (*expr_p),
 				  from_array,
 				  tf_warning_or_error);
 	ret = GS_OK;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8f52278..241805c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -72,6 +72,7 @@  c-common.h, not after.
       CONSTRUCTOR_IS_DIRECT_INIT (in CONSTRUCTOR)
       LAMBDA_EXPR_CAPTURES_THIS_P (in LAMBDA_EXPR)
       DECLTYPE_FOR_LAMBDA_CAPTURE (in DECLTYPE_TYPE)
+      VEC_INIT_EXPR_IS_CONSTEXPR (in VEC_INIT_EXPR)
    1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -2898,6 +2899,15 @@  more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #define VEC_INIT_EXPR_SLOT(NODE) TREE_OPERAND (NODE, 0)
 #define VEC_INIT_EXPR_INIT(NODE) TREE_OPERAND (NODE, 1)
 
+/* Indicates that a VEC_INIT_EXPR is a potential constant expression.
+   Only set when the current function is constexpr.  */
+#define VEC_INIT_EXPR_IS_CONSTEXPR(NODE) \
+  TREE_LANG_FLAG_0 (VEC_INIT_EXPR_CHECK (NODE))
+
+/* Indicates that a VEC_INIT_EXPR is expressing value-initialization.  */
+#define VEC_INIT_EXPR_VALUE_INIT(NODE) \
+  TREE_LANG_FLAG_1 (VEC_INIT_EXPR_CHECK (NODE))
+
 /* The TYPE_MAIN_DECL for a class template type is a TYPE_DECL, not a
    TEMPLATE_DECL.  This macro determines whether or not a given class
    type is really a template type, as opposed to an instantiation or
@@ -5240,6 +5250,7 @@  extern bool literal_type_p (tree);
 extern tree validate_constexpr_fundecl (tree);
 extern tree register_constexpr_fundef (tree, tree);
 extern tree ensure_literal_type_for_constexpr_object (tree);
+extern bool potential_constant_expression (tree, tsubst_flags_t);
 extern tree cxx_constant_value (tree);
 extern tree maybe_constant_value (tree);
 extern tree maybe_constant_init (tree);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index ab834bf..0ecd61d 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -453,10 +453,8 @@  perform_member_init (tree member, tree init)
       /* mem() means value-initialization.  */
       if (TREE_CODE (type) == ARRAY_TYPE)
 	{
-	  init = build_vec_init (decl, NULL_TREE, NULL_TREE,
-				 /*explicit_value_init_p=*/true,
-				 /* from_array=*/0,
-				 tf_warning_or_error);
+	  init = build_vec_init_expr (type, init);
+	  init = build2 (INIT_EXPR, type, decl, init);
 	  finish_expr_stmt (init);
 	}
       else
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 558be88..fd7da34 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5324,8 +5324,6 @@  typedef struct GTY(()) constexpr_fundef {
 
 static GTY ((param_is (constexpr_fundef))) htab_t constexpr_fundef_table;
 
-static bool potential_constant_expression (tree, tsubst_flags_t);
-
 /* Utility function used for managing the constexpr function table.
    Return true if the entries pointed to by P and Q are for the
    same constexpr function.  */
@@ -7066,7 +7064,7 @@  morally_constexpr_builtin_function_p (tree decl)
       logical OR (5.15), and conditional (5.16) operations that are
       not evaluated are not considered.   */
 
-static bool
+bool
 potential_constant_expression (tree t, tsubst_flags_t flags)
 {
   int i;
@@ -7451,11 +7449,7 @@  potential_constant_expression (tree t, tsubst_flags_t flags)
       return false;
 
     case VEC_INIT_EXPR:
-      /* We should only see this in a defaulted constructor for a class
-	 with a non-static data member of array type; if we get here we
-	 know this is a potential constant expression.  */
-      gcc_assert (DECL_DEFAULTED_FN (current_function_decl));
-      return true;
+      return VEC_INIT_EXPR_IS_CONSTEXPR (t);
 
     default:
       sorry ("unexpected ast of kind %s", tree_code_name[TREE_CODE (t)]);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index d1d306e..5440e10 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -462,34 +462,54 @@  build_vec_init_expr (tree type, tree init)
 {
   tree slot;
   tree inner_type = strip_array_types (type);
-
-  gcc_assert (init == NULL_TREE
-	      || (same_type_ignoring_top_level_qualifiers_p
-		  (type, TREE_TYPE (init))));
+  tree elt_init = integer_zero_node;
+  bool value_init = false;
 
   /* Since we're deferring building the actual constructor calls until
      gimplification time, we need to build one now and throw it away so
      that the relevant constructor gets mark_used before cgraph decides
      what functions are needed.  Here we assume that init is either
-     NULL_TREE or another array to copy.  */
-  if (CLASS_TYPE_P (inner_type))
+     NULL_TREE, void_type_node (indicating value-initialization), or
+     another array to copy.  */
+  if (init == void_type_node)
     {
-      VEC(tree,gc) *argvec = make_tree_vector ();
-      if (init)
+      elt_init = build_value_init (inner_type, tf_warning_or_error);
+      value_init = true;
+      init = NULL_TREE;
+    }
+  else
+    {
+      gcc_assert (init == NULL_TREE
+		  || (same_type_ignoring_top_level_qualifiers_p
+		      (type, TREE_TYPE (init))));
+
+      if (CLASS_TYPE_P (inner_type))
 	{
-	  tree dummy = build_dummy_object (inner_type);
-	  if (!real_lvalue_p (init))
-	    dummy = move (dummy);
-	  VEC_quick_push (tree, argvec, dummy);
+	  VEC(tree,gc) *argvec = make_tree_vector ();
+	  if (init)
+	    {
+	      tree dummy = build_dummy_object (inner_type);
+	      if (!real_lvalue_p (init))
+		dummy = move (dummy);
+	      VEC_quick_push (tree, argvec, dummy);
+	    }
+	  elt_init
+	    = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+					 &argvec, inner_type, LOOKUP_NORMAL,
+					 tf_warning_or_error);
 	}
-      build_special_member_call (NULL_TREE, complete_ctor_identifier,
-				 &argvec, inner_type, LOOKUP_NORMAL,
-				 tf_warning_or_error);
     }
 
   slot = build_local_temp (type);
   init = build2 (VEC_INIT_EXPR, type, slot, init);
   SET_EXPR_LOCATION (init, input_location);
+
+  if (current_function_decl
+      && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+      && potential_constant_expression (elt_init, tf_warning_or_error))
+    VEC_INIT_EXPR_IS_CONSTEXPR (init) = true;
+  VEC_INIT_EXPR_VALUE_INIT (init) = value_init;
+
   init = build_target_expr (slot, init);
   TARGET_EXPR_IMPLICIT_P (init) = 1;
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C
new file mode 100644
index 0000000..50d4d85
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C
@@ -0,0 +1,9 @@ 
+// { dg-options -std=c++0x }
+
+struct A
+{
+  int arr[1];
+
+  constexpr A()
+  : arr() { }
+};