re PR c++/47774 ([C++0x] constexpr specifier on ctor not ignored when template instan...
authorJason Merrill <jason@redhat.com>
Thu, 3 Mar 2011 02:49:19 +0000 (21:49 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 3 Mar 2011 02:49:19 +0000 (21:49 -0500)
PR c++/47774
* tree.c (build_vec_init_elt): Split out from...
(build_vec_init_expr): ...here.
(diagnose_non_constexpr_vec_init): New fn.
* semantics.c (potential_constant_expression_1): Use it.
* cp-tree.h: Declare it.

From-SVN: r170638

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C [new file with mode: 0644]

index a080431ff877a4c6988d38f15eea8a167653199c..b9ad026d3c2224f26d5726e01f3c25e84f82b9eb 100644 (file)
@@ -1,3 +1,12 @@
+2011-03-02  Jason Merrill  <jason@redhat.com>
+
+       PR c++/47774
+       * tree.c (build_vec_init_elt): Split out from...
+       (build_vec_init_expr): ...here.
+       (diagnose_non_constexpr_vec_init): New fn.
+       * semantics.c (potential_constant_expression_1): Use it.
+       * cp-tree.h: Declare it.
+
 2011-03-01  Jason Merrill  <jason@redhat.com>
 
        PR c++/46159
index d5a6d5c0763111cda4919961c00ee4ff1b04cf93..4b49046105f4f4323523b4f16a1e7703b77b7724 100644 (file)
@@ -5400,6 +5400,7 @@ extern tree build_cplus_array_type                (tree, tree);
 extern tree build_array_of_n_type              (tree, int);
 extern tree build_array_copy                   (tree);
 extern tree build_vec_init_expr                        (tree, tree);
+extern void diagnose_non_constexpr_vec_init    (tree);
 extern tree hash_tree_cons                     (tree, tree, tree);
 extern tree hash_tree_chain                    (tree, tree);
 extern tree build_qualified_name               (tree, tree, tree, bool);
index 6b3e9149a8015d2eb105659091a53dba387db21f..52a962dce09f6a0416ff41ee897b356318b020bc 100644 (file)
@@ -7722,7 +7722,10 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
       if (VEC_INIT_EXPR_IS_CONSTEXPR (t))
        return true;
       if (flags & tf_error)
-        error ("non-constant array initialization");
+       {
+         error ("non-constant array initialization");
+         diagnose_non_constexpr_vec_init (t);
+       }
       return false;
 
     default:
index ed4f67bbb0f08353fef56e807c4d607b35b3fb27..56639ffe836c700b1e42162f2cbd536fbd11f4b5 100644 (file)
@@ -456,6 +456,47 @@ build_cplus_new (tree type, tree init)
   return rval;
 }
 
+/* Subroutine of build_vec_init_expr: Build up a single element
+   intialization as a proxy for the full array initialization to get things
+   marked as used and any appropriate diagnostics.
+
+   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, void_type_node (indicating value-initialization), or
+   another array to copy.  */
+
+static tree
+build_vec_init_elt (tree type, tree init)
+{
+  tree inner_type = strip_array_types (type);
+  VEC(tree,gc) *argvec;
+
+  if (integer_zerop (array_type_nelts_total (type))
+      || !CLASS_TYPE_P (inner_type))
+    /* No interesting initialization to do.  */
+    return integer_zero_node;
+  else if (init == void_type_node)
+    return build_value_init (inner_type, tf_warning_or_error);
+
+  gcc_assert (init == NULL_TREE
+             || (same_type_ignoring_top_level_qualifiers_p
+                 (type, TREE_TYPE (init))));
+
+  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);
+    }
+  return build_special_member_call (NULL_TREE, complete_ctor_identifier,
+                                   &argvec, inner_type, LOOKUP_NORMAL,
+                                   tf_warning_or_error);
+}
+
 /* Return a TARGET_EXPR which expresses the initialization of an array to
    be named later, either default-initialization or copy-initialization
    from another array of the same type.  */
@@ -464,62 +505,22 @@ tree
 build_vec_init_expr (tree type, tree init)
 {
   tree slot;
-  tree inner_type = strip_array_types (type);
-  tree elt_init = integer_zero_node;
   bool value_init = false;
+  tree elt_init = build_vec_init_elt (type, init);
 
-  /* 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, void_type_node (indicating value-initialization), or
-     another array to copy.  */
-  if (integer_zerop (array_type_nelts_total (type)))
-    {
-      /* No actual initialization to do.  */;
-      init = NULL_TREE;
-    }
-  else if (init == void_type_node)
+  if (init == void_type_node)
     {
-      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))
-       {
-         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);
-       }
-    }
 
   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))
-    {
-      if (potential_constant_expression (elt_init))
-       VEC_INIT_EXPR_IS_CONSTEXPR (init) = true;
-      else if (!processing_template_decl)
-       require_potential_constant_expression (elt_init);
-    }
+  if (cxx_dialect >= cxx0x
+      && potential_constant_expression (elt_init))
+    VEC_INIT_EXPR_IS_CONSTEXPR (init) = true;
   VEC_INIT_EXPR_VALUE_INIT (init) = value_init;
 
   init = build_target_expr (slot, init);
@@ -528,6 +529,23 @@ build_vec_init_expr (tree type, tree init)
   return init;
 }
 
+/* Give a helpful diagnostic for a non-constexpr VEC_INIT_EXPR in a context
+   that requires a constant expression.  */
+
+void
+diagnose_non_constexpr_vec_init (tree expr)
+{
+  tree type = TREE_TYPE (VEC_INIT_EXPR_SLOT (expr));
+  tree init, elt_init;
+  if (VEC_INIT_EXPR_VALUE_INIT (expr))
+    init = void_zero_node;
+  else
+    init = VEC_INIT_EXPR_INIT (expr);
+
+  elt_init = build_vec_init_elt (type, init);
+  require_potential_constant_expression (elt_init);
+}
+
 tree
 build_array_copy (tree init)
 {
index c4f8ceeacfb430daefc9592983d739a9b513e5c5..328ed9e468eca148975a4c6b48acc09492e22bf3 100644 (file)
@@ -1,3 +1,7 @@
+2011-03-02  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/cpp0x/constexpr-ctor9.C: New.
+
 2011-03-01  Jason Merrill  <jason@redhat.com>
 
        * g++.dg/cpp0x/lambda/lambda-98.C: New.
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C
new file mode 100644 (file)
index 0000000..b7693f1
--- /dev/null
@@ -0,0 +1,19 @@
+// PR c++/47774
+// { dg-options -std=c++0x }
+
+struct A
+{
+  A() {}
+};
+
+template <typename T>
+struct array
+{
+  constexpr array() : mem() {}
+  T mem[7];
+};
+
+int main()
+{
+  array<A> ar;
+}