[C++ PATCH] Don't crash on vector_size attribute in templates (PR c++/34913)
Jakub Jelinek
jakub@redhat.com
Tue Jan 22 17:30:00 GMT 2008
Hi!
When processing_template_decl, reconstruct_complex_type hack which is
called from handle_vector_size_attribute is dangerous, as e.g. when array
size is dependent, C++ private tree codes leak into middle-end where they
cause problems.
Attached are 2 alternative patches (depending on which patch is acked if any
for PR c++/34914), which work around this by going through the ARRAY_TYPEs
etc. in cplus_decl_attributes before calling middle-end decl_attributes,
call middle-end decl_attributes on the inner type which is supposed to
become a vector and then reconstruct the complex type using an alternative
reconstruct_complex_type.
The second patch has been bootstrapped/regtested on x86_64-linux.
Ok for trunk?
Jakub
-------------- next part --------------
2008-01-22 Jakub Jelinek <jakub@redhat.com>
PR c++/34913
* decl2.c (cp_reconstruct_complex_type): New function.
(cplus_decl_attributes): Make sure reconstruct_complex_type
isn't called by handle_vector_size_attribute when
processing_template_decl.
* g++.dg/ext/vector11.C: New test.
--- gcc/cp/decl2.c.jj 2007-12-11 00:26:21.000000000 +0100
+++ gcc/cp/decl2.c 2008-01-22 13:01:51.000000000 +0100
@@ -1080,6 +1080,60 @@ save_template_attributes (tree *attr_p,
*q = late_attrs;
}
+/* HACK. GROSS. This is absolutely disgusting. I wish there was a
+ better way.
+
+ If we requested a pointer to a vector, build up the pointers that
+ we stripped off while looking for the inner type. Similarly for
+ return values from functions.
+
+ The argument TYPE is the top of the chain, and BOTTOM is the
+ new type which we will point to. */
+
+static tree
+cp_reconstruct_complex_type (tree type, tree bottom)
+{
+ tree inner, outer;
+
+ if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ outer = build_pointer_type_for_mode (inner, TYPE_MODE (type),
+ TYPE_REF_CAN_ALIAS_ALL (type));
+ }
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ outer = build_reference_type_for_mode (inner, TYPE_MODE (type),
+ TYPE_REF_CAN_ALIAS_ALL (type));
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ outer = build_cplus_array_type (inner, TYPE_DOMAIN (type));
+ }
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ outer = build_function_type (inner, TYPE_ARG_TYPES (type));
+ }
+ else if (TREE_CODE (type) == METHOD_TYPE)
+ {
+ inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ /* The build_method_type_directly() routine prepends 'this' to argument list,
+ so we must compensate by getting rid of it. */
+ outer
+ = build_method_type_directly
+ (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))),
+ inner,
+ TREE_CHAIN (TYPE_ARG_TYPES (type)));
+ }
+ else
+ return bottom;
+
+ return cp_build_qualified_type (outer, TYPE_QUALS (type));
+}
+
/* Like decl_attributes, but handle C++ complexity. */
void
@@ -1100,6 +1154,62 @@ cplus_decl_attributes (tree *decl, tree
if (TREE_CODE (*decl) == TEMPLATE_DECL)
decl = &DECL_TEMPLATE_RESULT (*decl);
+ if (processing_template_decl)
+ {
+ tree *a;
+
+ for (a = &attributes; *a; )
+ {
+ tree name = TREE_PURPOSE (*a);
+
+ /* When processing_template_decl, avoid handle_vector_size_attribute
+ calling reconstruct_complex_type, because type might be
+ dependent. */
+ if (is_attribute_p ("vector_size", name))
+ {
+ tree type = *decl, innertype, origtype;
+
+ if (DECL_P (*decl))
+ type = TREE_TYPE (*decl);
+
+ innertype = type;
+ while (POINTER_TYPE_P (innertype)
+ || TREE_CODE (innertype) == FUNCTION_TYPE
+ || TREE_CODE (innertype) == METHOD_TYPE
+ || TREE_CODE (innertype) == ARRAY_TYPE)
+ innertype = TREE_TYPE (innertype);
+
+ if (innertype == type)
+ a = &TREE_CHAIN (*a);
+ else
+ {
+ tree attr = *a;
+ *a = TREE_CHAIN (*a);
+ TREE_CHAIN (attr) = NULL;
+ origtype = innertype;
+ decl_attributes (&innertype, attr,
+ flags & ~ATTR_FLAG_TYPE_IN_PLACE);
+ if (innertype != origtype)
+ {
+ type = cp_reconstruct_complex_type (type, innertype);
+ if (DECL_P (*decl))
+ {
+ TREE_TYPE (*decl) = type;
+ if (TREE_CODE (*decl) == VAR_DECL
+ && TREE_CODE (*decl) == PARM_DECL
+ && TREE_CODE (*decl) == RESULT_DECL)
+ relayout_decl (*decl);
+ }
+ else
+ *decl = type;
+ }
+ }
+ }
+ else
+ a = &TREE_CHAIN (*a);
+ }
+ }
+
decl_attributes (decl, attributes, flags);
if (TREE_CODE (*decl) == TYPE_DECL)
--- gcc/testsuite/g++.dg/ext/vector11.C.jj 2008-01-22 13:10:03.000000000 +0100
+++ gcc/testsuite/g++.dg/ext/vector11.C 2008-01-22 13:45:42.000000000 +0100
@@ -0,0 +1,15 @@
+// PR c++/34913
+// { dg-do compile }
+// { dg-options "" }
+
+template <typename T> struct A
+{
+ int x[sizeof (T)] __attribute ((vector_size (8)));
+};
+
+A<int> a;
+
+void foo ()
+{
+ a.x[0] = (int __attribute ((vector_size (8)))) { 4 };
+}
-------------- next part --------------
2008-01-22 Jakub Jelinek <jakub@redhat.com>
PR c++/34913
* decl2.c (cp_reconstruct_complex_type): New function.
(cplus_decl_attributes): Make sure reconstruct_complex_type
isn't called by handle_vector_size_attribute when
processing_template_decl.
* g++.dg/ext/vector11.C: New test.
--- gcc/cp/decl2.c.jj 2007-12-11 00:26:21.000000000 +0100
+++ gcc/cp/decl2.c 2008-01-22 14:32:50.000000000 +0100
@@ -1080,6 +1080,65 @@ save_template_attributes (tree *attr_p,
*q = late_attrs;
}
+/* HACK. GROSS. This is absolutely disgusting. I wish there was a
+ better way.
+
+ If we requested a pointer to a vector, build up the pointers that
+ we stripped off while looking for the inner type. Similarly for
+ return values from functions.
+
+ The argument TYPE is the top of the chain, and BOTTOM is the
+ new type which we will point to. */
+
+static tree
+cp_reconstruct_complex_type (tree type, tree bottom)
+{
+ tree inner, outer;
+
+ if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ outer = build_pointer_type_for_mode (inner, TYPE_MODE (type),
+ TYPE_REF_CAN_ALIAS_ALL (type));
+ }
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ outer = build_reference_type_for_mode (inner, TYPE_MODE (type),
+ TYPE_REF_CAN_ALIAS_ALL (type));
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ outer = build_cplus_array_type (inner, TYPE_DOMAIN (type));
+ }
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ outer = build_function_type (inner, TYPE_ARG_TYPES (type));
+ }
+ else if (TREE_CODE (type) == METHOD_TYPE)
+ {
+ inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ /* The build_method_type_directly() routine prepends 'this' to argument list,
+ so we must compensate by getting rid of it. */
+ outer
+ = build_method_type_directly
+ (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))),
+ inner,
+ TREE_CHAIN (TYPE_ARG_TYPES (type)));
+ }
+ else if (TREE_CODE (type) == OFFSET_TYPE)
+ {
+ inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ outer = build_offset_type (TYPE_OFFSET_BASETYPE (type), inner);
+ }
+ else
+ return bottom;
+
+ return cp_build_qualified_type (outer, TYPE_QUALS (type));
+}
+
/* Like decl_attributes, but handle C++ complexity. */
void
@@ -1100,6 +1159,63 @@ cplus_decl_attributes (tree *decl, tree
if (TREE_CODE (*decl) == TEMPLATE_DECL)
decl = &DECL_TEMPLATE_RESULT (*decl);
+ if (processing_template_decl)
+ {
+ tree *a;
+
+ for (a = &attributes; *a; )
+ {
+ tree name = TREE_PURPOSE (*a);
+
+ /* When processing_template_decl, avoid handle_vector_size_attribute
+ calling reconstruct_complex_type, because type might be
+ dependent. */
+ if (is_attribute_p ("vector_size", name))
+ {
+ tree type = *decl, innertype, origtype;
+
+ if (DECL_P (*decl))
+ type = TREE_TYPE (*decl);
+
+ innertype = type;
+ while (POINTER_TYPE_P (innertype)
+ || TREE_CODE (innertype) == FUNCTION_TYPE
+ || TREE_CODE (innertype) == METHOD_TYPE
+ || TREE_CODE (innertype) == ARRAY_TYPE
+ || TREE_CODE (innertype) == OFFSET_TYPE)
+ innertype = TREE_TYPE (innertype);
+
+ if (innertype == type)
+ a = &TREE_CHAIN (*a);
+ else
+ {
+ tree attr = *a;
+ *a = TREE_CHAIN (*a);
+ TREE_CHAIN (attr) = NULL;
+ origtype = innertype;
+ decl_attributes (&innertype, attr,
+ flags & ~ATTR_FLAG_TYPE_IN_PLACE);
+ if (innertype != origtype)
+ {
+ type = cp_reconstruct_complex_type (type, innertype);
+ if (DECL_P (*decl))
+ {
+ TREE_TYPE (*decl) = type;
+ if (TREE_CODE (*decl) == VAR_DECL
+ && TREE_CODE (*decl) == PARM_DECL
+ && TREE_CODE (*decl) == RESULT_DECL)
+ relayout_decl (*decl);
+ }
+ else
+ *decl = type;
+ }
+ }
+ }
+ else
+ a = &TREE_CHAIN (*a);
+ }
+ }
+
decl_attributes (decl, attributes, flags);
if (TREE_CODE (*decl) == TYPE_DECL)
--- gcc/testsuite/g++.dg/ext/vector11.C.jj 2008-01-22 13:10:03.000000000 +0100
+++ gcc/testsuite/g++.dg/ext/vector11.C 2008-01-22 13:45:42.000000000 +0100
@@ -0,0 +1,15 @@
+// PR c++/34913
+// { dg-do compile }
+// { dg-options "" }
+
+template <typename T> struct A
+{
+ int x[sizeof (T)] __attribute ((vector_size (8)));
+};
+
+A<int> a;
+
+void foo ()
+{
+ a.x[0] = (int __attribute ((vector_size (8)))) { 4 };
+}
More information about the Gcc-patches
mailing list