This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/55149 (lambda VLA capture)


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]