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
PR c++/71147 - [6 Regression] Flexible array member wrongly rejected in template
gcc/ChangeLog:
2016-05-24 Martin Sebor <mse...@redhat.com>
PR c++/71147
* gcc/tree.h (complete_or_array_type_p): New inline function.
gcc/testsuite/ChangeLog:
2016-05-24 Martin Sebor <mse...@redhat.com>
PR c++/71147
* g++.dg/ext/flexary16.C: New test.
gcc/cp/ChangeLog:
2016-05-24 Martin Sebor <mse...@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);