diff mbox

c++/71147 - [6 Regression] Flexible array member wrongly rejected in template

Message ID 57447E37.2010805@gmail.com
State New
Headers show

Commit Message

Martin Sebor May 24, 2016, 4:15 p.m. UTC
>> Thanks for the suggestions.  I implemented them in the attached
>> update to the the patch.  The macro I added evaluates its argument
>> multiple times.  That normally isn't a problem unless it's invoked
>> with a non-trivial argument like a call to complete_type() that's
>> passed to COMPLETE_TYPE_P() in grokdeclarator.  One way to avoid
>> possible problems due to evaluating the macro argument more than
>> once is to introduce a helper inline function.  I haven't seen
>> it done in tree.h so I didn't introduce one in this patch either,
>> but it might be worth considering for the new macro and any other
>> non-trivial macros like it.
>
> Yes, let's just make it an inline function (of which there are already
> quite a few in tree.h).

Attached is an updated patch with this change.

Martin

Comments

Jason Merrill May 24, 2016, 6:51 p.m. UTC | #1
On 05/24/2016 12:15 PM, Martin Sebor wrote:
> +  else if (TREE_CODE (type) == ARRAY_TYPE /* && TYPE_DOMAIN (type) */)

Why is this commented out rather than removed in this version of the 
patch?  Let's remove it, as before.  OK with that change.

Jason
Martin Sebor May 24, 2016, 8:43 p.m. UTC | #2
On 05/24/2016 12:51 PM, Jason Merrill wrote:
> On 05/24/2016 12:15 PM, Martin Sebor wrote:
>> +  else if (TREE_CODE (type) == ARRAY_TYPE /* && TYPE_DOMAIN (type) */)
>
> Why is this commented out rather than removed in this version of the
> patch?  Let's remove it, as before.  OK with that change.

It was commented out by accident.

Since c++/71147 is a regression, should I also backport the patch
to the 6.x branch?

Martin
Jason Merrill May 24, 2016, 9:06 p.m. UTC | #3
On 05/24/2016 04:43 PM, Martin Sebor wrote:
> On 05/24/2016 12:51 PM, Jason Merrill wrote:
>> On 05/24/2016 12:15 PM, Martin Sebor wrote:
>>> +  else if (TREE_CODE (type) == ARRAY_TYPE /* && TYPE_DOMAIN (type) */)
>>
>> Why is this commented out rather than removed in this version of the
>> patch?  Let's remove it, as before.  OK with that change.
>
> It was commented out by accident.
>
> Since c++/71147 is a regression, should I also backport the patch
> to the 6.x branch?

OK.

Jason
diff mbox

Patch

PR c++/71147 - [6 Regression] Flexible array member wrongly rejected in template

gcc/ChangeLog:
2016-05-24  Martin Sebor  <msebor@redhat.com>

	PR c++/71147
	* gcc/tree.h (complete_or_array_type_p): New inline function.

gcc/testsuite/ChangeLog:
2016-05-24  Martin Sebor  <msebor@redhat.com>

	PR c++/71147
	* g++.dg/ext/flexary16.C: New test.

gcc/cp/ChangeLog:
2016-05-24  Martin Sebor  <msebor@redhat.com>

	PR c++/71147
	* decl.c (layout_var_decl, grokdeclarator): Use complete_or_array_type_p.
	* pt.c (instantiate_class_template_1): Try to complete the element
	type of a flexible array member.
	(can_complete_type_without_circularity): Handle arrays of unknown bound.
	* typeck.c (complete_type): Also complete the type of the elements of
	arrays with an unspecified bound.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 7a69711..ef5fd66 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5305,10 +5305,7 @@  layout_var_decl (tree decl)
     complete_type (type);
   if (!DECL_SIZE (decl)
       && TREE_TYPE (decl) != error_mark_node
-      && (COMPLETE_TYPE_P (type)
-	  || (TREE_CODE (type) == ARRAY_TYPE
-	      && !TYPE_DOMAIN (type)
-	      && COMPLETE_TYPE_P (TREE_TYPE (type)))))
+      && complete_or_array_type_p (type))
     layout_decl (decl, 0);
 
   if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)
@@ -11165,8 +11162,7 @@  grokdeclarator (const cp_declarator *declarator,
 	  }
 	else if (!staticp && !dependent_type_p (type)
 		 && !COMPLETE_TYPE_P (complete_type (type))
-		 && (TREE_CODE (type) != ARRAY_TYPE
-		     || !COMPLETE_TYPE_P (TREE_TYPE (type))
+		 && (!complete_or_array_type_p (type)
 		     || initialized == 0))
 	  {
 	    if (TREE_CODE (type) != ARRAY_TYPE
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2bba571..03dee66 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9554,7 +9554,7 @@  can_complete_type_without_circularity (tree type)
     return 0;
   else if (COMPLETE_TYPE_P (type))
     return 1;
-  else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
+  else if (TREE_CODE (type) == ARRAY_TYPE /* && TYPE_DOMAIN (type) */)
     return can_complete_type_without_circularity (TREE_TYPE (type));
   else if (CLASS_TYPE_P (type)
 	   && TYPE_BEING_DEFINED (TYPE_MAIN_VARIANT (type)))
@@ -10119,17 +10119,12 @@  instantiate_class_template_1 (tree type)
 			  if (can_complete_type_without_circularity (rtype))
 			    complete_type (rtype);
 
-                          if (TREE_CODE (r) == FIELD_DECL
-                              && TREE_CODE (rtype) == ARRAY_TYPE
-                              && COMPLETE_TYPE_P (TREE_TYPE (rtype))
-                              && !COMPLETE_TYPE_P (rtype))
-                            {
-                              /* Flexible array mmembers of elements
-                                 of complete type have an incomplete type
-                                 and that's okay.  */
-                            }
-                          else if (!COMPLETE_TYPE_P (rtype))
+			  if (!complete_or_array_type_p (rtype))
 			    {
+			      /* If R's type couldn't be completed and
+				 it isn't a flexible array member (whose
+				 type is incomplete by definition) give
+				 an error.  */
 			      cxx_incomplete_type_error (r, rtype);
 			      TREE_TYPE (r) = error_mark_node;
 			    }
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index cd058fa..2688ab4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -112,7 +112,7 @@  complete_type (tree type)
 
   if (type == error_mark_node || COMPLETE_TYPE_P (type))
     ;
-  else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
+  else if (TREE_CODE (type) == ARRAY_TYPE)
     {
       tree t = complete_type (TREE_TYPE (type));
       unsigned int needs_constructing, has_nontrivial_dtor;
diff --git a/gcc/testsuite/g++.dg/ext/flexary16.C b/gcc/testsuite/g++.dg/ext/flexary16.C
new file mode 100644
index 0000000..a3e040d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/flexary16.C
@@ -0,0 +1,37 @@ 
+// PR c++/71147 - [6 Regression] Flexible array member wrongly rejected
+//   in template
+// { dg-do compile }
+
+template <typename>
+struct container
+{
+  struct elem {
+    unsigned u;
+  };
+
+  struct incomplete {
+    int x;
+    elem array[];
+  };
+};
+
+unsigned f (container<void>::incomplete* i)
+{
+  return i->array [0].u;
+}
+
+
+template <typename T>
+struct D: container<T>
+{
+  struct S {
+    int x;
+    typename container<T>::elem array[];
+  };
+};
+
+
+unsigned g (D<void>::S *s)
+{
+  return s->array [0].u;
+}
diff --git a/gcc/tree.h b/gcc/tree.h
index 2510d16..90413fc 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4753,6 +4753,17 @@  ptrofftype_p (tree type)
 	  && TYPE_UNSIGNED (type) == TYPE_UNSIGNED (sizetype));
 }
 
+/* Return true if the argument is a complete type or an array
+   of unknown bound (whose type is incomplete but) whose elements
+   have complete type.  */
+static inline bool
+complete_or_array_type_p (const_tree type)
+{
+  return COMPLETE_TYPE_P (type)
+         || (TREE_CODE (type) == ARRAY_TYPE
+	     && COMPLETE_TYPE_P (TREE_TYPE (type)));
+}
+
 extern tree strip_float_extensions (tree);
 extern int really_constant_p (const_tree);
 extern bool decl_address_invariant_p (const_tree);