aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-03-02 21:49:19 -0500
committerJason Merrill <jason@gcc.gnu.org>2011-03-02 21:49:19 -0500
commit262a7d6bc0820d7aed46a05b2b8b6ef7824bb08f (patch)
treeec4922a31a757f11986c001b1ffa43d50264d890
parent20532210cd1a8e0b3b2d6ec1bcaa8c0e928af5ca (diff)
downloadgcc-262a7d6bc0820d7aed46a05b2b8b6ef7824bb08f.zip
gcc-262a7d6bc0820d7aed46a05b2b8b6ef7824bb08f.tar.gz
gcc-262a7d6bc0820d7aed46a05b2b8b6ef7824bb08f.tar.bz2
re PR c++/47774 ([C++0x] constexpr specifier on ctor not ignored when template instantiation causes ctor to not satify constexpr requirements)
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
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/semantics.c5
-rw-r--r--gcc/cp/tree.c108
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C19
6 files changed, 100 insertions, 46 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a080431..b9ad026 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d5a6d5c..4b49046 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 6b3e914..52a962d 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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:
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index ed4f67b..56639ff 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c4f8cee..328ed9e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..b7693f1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C
@@ -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;
+}