[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