re PR c++/55149 (capturing VLA in lambda)

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.

From-SVN: r200279
This commit is contained in:
Jason Merrill 2013-06-20 20:28:30 -04:00 committed by Jason Merrill
parent 8fc95c057c
commit 593bcbb8e4
7 changed files with 83 additions and 22 deletions

View file

@ -1,5 +1,18 @@
2013-06-20 Jason Merrill <jason@redhat.com>
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.
* decl.c (compute_array_index_type): Use size_one_node.
* pt.c (process_partial_specialization): Build a TEMPLATE_DECL for

View file

@ -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) \

View file

@ -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;

View file

@ -11575,7 +11575,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

View file

@ -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

View file

@ -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

View file

@ -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;
}