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:
parent
8fc95c057c
commit
593bcbb8e4
7 changed files with 83 additions and 22 deletions
|
@ -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
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
31
gcc/testsuite/g++.dg/cpp1y/vla8.C
Normal file
31
gcc/testsuite/g++.dg/cpp1y/vla8.C
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue