Instantiation of a VLA capture in a template wasn't working properly;
this fixes it.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 9e88ab6e258122ce7d4a709919df56f7c1514c06
Author: Jason Merrill <ja...@redhat.com>
Date: Thu Jun 13 09:29:11 2013 -0400
PR c++/55149
* decl.c (compute_array_index_type): Don't reject VLAs in SFINAE
context if we're in C++14 mode.
* tree.c (array_of_runtime_bound_p): Return true for a dependent
bound that is not potentually constant.
* cp-tree.h (DECL_VLA_CAPTURE_P, REFERENCE_VLA_OK): New.
* pt.c (tsubst) [REFERENCE_TYPE]: Check REFERENCE_VLA_OK.
* semantics.c (build_lambda_object): Don't rvalue a VLA capture.
(build_capture_proxy): Set REFERENCE_VLA_OK.
(vla_capture_type): Make it a proper C++ class.
(add_capture): Set DECL_VLA_CAPTURE_P. Don't pre-digest the
initializer.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9fc4aeb..cf54acf 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -126,6 +126,7 @@ c-common.h, not after.
5: CLASS_TYPE_P (in RECORD_TYPE and UNION_TYPE)
ENUM_FIXED_UNDERLYING_TYPE_P (in ENUMERAL_TYPE)
AUTO_IS_DECLTYPE (in TEMPLATE_TYPE_PARM)
+ REFERENCE_VLA_OK (in REFERENCE_TYPE)
6: TYPE_DEPENDENT_P_VALID
Usage of DECL_LANG_FLAG_?:
@@ -139,6 +140,7 @@ c-common.h, not after.
DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL)
FUNCTION_PARAMETER_PACK_P (in PARM_DECL)
USING_DECL_TYPENAME_P (in USING_DECL)
+ DECL_VLA_CAPTURE_P (in FIELD_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
3: DECL_IN_AGGR_P.
@@ -2979,6 +2981,11 @@ extern void decl_shadowed_for_var_insert (tree, tree);
&& (TREE_CODE (TREE_TYPE (TREE_OPERAND ((NODE), 0))) \
== REFERENCE_TYPE))
+/* True if NODE is a REFERENCE_TYPE which is OK to instantiate to be a
+ reference to VLA type, because it's used for VLA capture. */
+#define REFERENCE_VLA_OK(NODE) \
+ (TYPE_LANG_FLAG_5 (REFERENCE_TYPE_CHECK (NODE)))
+
#define NEW_EXPR_USE_GLOBAL(NODE) \
TREE_LANG_FLAG_0 (NEW_EXPR_CHECK (NODE))
#define DELETE_EXPR_USE_GLOBAL(NODE) \
@@ -3616,6 +3623,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define DECL_THIS_STATIC(NODE) \
DECL_LANG_FLAG_6 (VAR_FUNCTION_OR_PARM_DECL_CHECK (NODE))
+/* Nonzero for FIELD_DECL node means that this field is a lambda capture
+ field for an array of runtime bound. */
+#define DECL_VLA_CAPTURE_P(NODE) \
+ DECL_LANG_FLAG_1 (FIELD_DECL_CHECK (NODE))
+
/* Nonzero for FIELD_DECL node means that this field is a base class
of the parent object, as opposed to a member field. */
#define DECL_FIELD_IS_BASE(NODE) \
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index dad1e10..225f131 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8296,7 +8296,8 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
else if (TREE_CONSTANT (size)
/* We don't allow VLAs at non-function scopes, or during
tentative template substitution. */
- || !at_function_scope_p () || !(complain & tf_error))
+ || !at_function_scope_p ()
+ || (cxx_dialect < cxx1y && !(complain & tf_error)))
{
if (!(complain & tf_error))
return error_mark_node;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 256f9ab..4a0f411 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11608,7 +11608,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
r = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t));
r = cp_build_qualified_type_real (r, cp_type_quals (t), complain);
- if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type))
+ if (cxx_dialect >= cxx1y
+ && !(TREE_CODE (t) == REFERENCE_TYPE && REFERENCE_VLA_OK (t))
+ && array_of_runtime_bound_p (type))
{
if (complain & tf_warning_or_error)
pedwarn
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0a700b7..135ef74 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -9033,6 +9033,7 @@ build_lambda_object (tree lambda_expr)
if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE)
val = build_array_copy (val);
else if (DECL_NORMAL_CAPTURE_P (field)
+ && !DECL_VLA_CAPTURE_P (field)
&& TREE_CODE (TREE_TYPE (field)) != REFERENCE_TYPE)
{
/* "the entities that are captured by copy are used to
@@ -9404,8 +9405,7 @@ build_capture_proxy (tree member)
type = lambda_proxy_type (object);
- if (TREE_CODE (type) == RECORD_TYPE
- && TYPE_NAME (type) == NULL_TREE)
+ if (DECL_VLA_CAPTURE_P (member))
{
/* Rebuild the VLA type from the pointer and maxindex. */
tree field = next_initializable_field (TYPE_FIELDS (type));
@@ -9414,8 +9414,9 @@ build_capture_proxy (tree member)
tree max = build_simple_component_ref (object, field);
type = build_array_type (TREE_TYPE (TREE_TYPE (ptr)),
build_index_type (max));
- object = convert (build_reference_type (type), ptr);
- object = convert_from_reference (object);
+ type = build_reference_type (type);
+ REFERENCE_VLA_OK (type) = true;
+ object = convert (type, ptr);
}
var = build_decl (input_location, VAR_DECL, name, type);
@@ -9446,19 +9447,20 @@ static tree
vla_capture_type (tree array_type)
{
static tree ptr_id, max_id;
+ tree type = xref_tag (record_type, make_anon_name (), ts_current, false);
+ xref_basetypes (type, NULL_TREE);
+ type = begin_class_definition (type);
if (!ptr_id)
{
ptr_id = get_identifier ("ptr");
max_id = get_identifier ("max");
}
tree ptrtype = build_pointer_type (TREE_TYPE (array_type));
- tree field1 = build_decl (input_location, FIELD_DECL, ptr_id, ptrtype);
- tree field2 = build_decl (input_location, FIELD_DECL, max_id, sizetype);
- DECL_CHAIN (field2) = field1;
- tree type = make_node (RECORD_TYPE);
- finish_builtin_struct (type, "__cap", field2, NULL_TREE);
- TYPE_NAME (type) = NULL_TREE;
- return type;
+ tree field = build_decl (input_location, FIELD_DECL, ptr_id, ptrtype);
+ finish_member_declaration (field);
+ field = build_decl (input_location, FIELD_DECL, max_id, sizetype);
+ finish_member_declaration (field);
+ return finish_struct (type, NULL_TREE);
}
/* From an ID and INITIALIZER, create a capture (by reference if
@@ -9471,6 +9473,7 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
{
char *buf;
tree type, member, name;
+ bool vla = false;
if (TREE_CODE (initializer) == TREE_LIST)
initializer = build_x_compound_expr_from_list (initializer, ELK_INIT,
@@ -9478,6 +9481,7 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
type = lambda_capture_field_type (initializer, explicit_init_p);
if (array_of_runtime_bound_p (type))
{
+ vla = true;
if (!by_reference_p)
error ("array of runtime bound cannot be captured by copy, "
"only by reference");
@@ -9486,13 +9490,10 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
maximum index, and then reconstruct the VLA for the proxy. */
tree elt = cp_build_array_ref (input_location, initializer,
integer_zero_node, tf_warning_or_error);
- tree ctype = vla_capture_type (type);
- tree ptr_field = next_initializable_field (TYPE_FIELDS (ctype));
- tree nelts_field = next_initializable_field (DECL_CHAIN (ptr_field));
- initializer = build_constructor_va (ctype, 2,
- ptr_field, build_address (elt),
- nelts_field, array_type_nelts (type));
- type = ctype;
+ initializer = build_constructor_va (init_list_type_node, 2,
+ NULL_TREE, build_address (elt),
+ NULL_TREE, array_type_nelts (type));
+ type = vla_capture_type (type);
}
else if (variably_modified_type_p (type, NULL_TREE))
{
@@ -9544,6 +9545,7 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
/* Make member variable. */
member = build_lang_decl (FIELD_DECL, name, type);
+ DECL_VLA_CAPTURE_P (member) = vla;
if (!explicit_init_p)
/* Normal captures are invisible to name lookup but uses are replaced
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8524f6c..d54d46d 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -884,8 +884,8 @@ array_of_runtime_bound_p (tree t)
if (!dom)
return false;
tree max = TYPE_MAX_VALUE (dom);
- return (!value_dependent_expression_p (max)
- && !TREE_CONSTANT (max));
+ return (!potential_rvalue_constant_expression (max)
+ || (!value_dependent_expression_p (max) && !TREE_CONSTANT (max)));
}
/* Return a reference type node referring to TO_TYPE. If RVAL is
diff --git a/gcc/testsuite/g++.dg/cpp1y/vla8.C b/gcc/testsuite/g++.dg/cpp1y/vla8.C
new file mode 100644
index 0000000..6e2031a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/vla8.C
@@ -0,0 +1,31 @@
+// PR c++/55149
+// { dg-options -std=c++1y }
+
+template<unsigned int TA>
+ struct SA
+ {
+ SA (const int & PA);
+ int nt;
+ };
+
+template<typename TB>
+ inline void
+ test(TB aa)
+ {
+ ;
+ }
+
+template<unsigned int TA>
+ inline
+ SA<TA>::SA(const int & PA)
+ {
+ float e[nt];
+ test([&e](int i, int j){ return e[i] < e[j]; });
+ }
+
+int main()
+{
+ int d;
+ SA<2> iso(d);
+ return 0;
+}