public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* RFC (attributes): PATCH for c++/50800 to set affects_type_identity for may_alias
@ 2016-06-23 19:39 Jason Merrill
  2016-06-27 11:41 ` Florian Weimer
  2016-06-27 14:09 ` Richard Biener
  0 siblings, 2 replies; 4+ messages in thread
From: Jason Merrill @ 2016-06-23 19:39 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 956 bytes --]

My earlier patch for 50800 fixed the ICE by consistently stripping 
non-mangled attributes from template arguments, and mangling those that 
affect type identity.  At the C++ meeting this week someone pointed out 
to me that this is a real problem for x86 vector code, which relies on 
may_alias semantics: if may_alias is stripped from __m128, users can't 
use templates with vectors.

So, it seems that the solution is to mangle may_alias by saying that it 
affects type identity.  But since we still want to be able to convert 
back and forth, I thought that it would make sense to treat the 
may_alias version of a type as a variant, rather than a new distinct 
type.  So the first patch creates a new category of attributes that are 
treated as type variants.

An alternative patch just sets affects_type_identity and adjusts the C++ 
front end to allow conversion between pointers to add or discard may_alias.

Thoughts?

Tested x86_64-pc-linux-gnu.

[-- Attachment #2: may_alias-be.diff --]
[-- Type: text/x-patch, Size: 14127 bytes --]

commit b9722b2721f8e3901a7343b9c373d37a9e4ecefd
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jun 21 22:26:38 2016 +0300

    	PR c++/50800 - may_alias and templates
    
    gcc/c/
    	* tree-core.h (ATTRIBUTE_TYPE_VARIANT): New enumerator.
    	* tree.c (comp_type_attributes): Check variant_attribute_p.
    	(build_type_attribute_qual_variant): Handle variant attributes.
    	(check_attribute_qualified_type, get_attribute_qualified_type): New.
    	* tree.h: Declare get_attribute_qualified_type.
    	* attribs.c (variant_attribute_p, remove_variant_attributes): New.
    	* attribs.h: Declare them.
    gcc/c-family/
    	* c-common.c (c_common_attribute_table): may_alias affects type
    	identity.
    gcc/cp/
    	* tree.c (apply_identity_attributes): No longer static.
    	* mangle.c (canonicalize_for_substitution): Call it.
    	* cp-tree.h: Declare it.
    	* typeck.c (underlying_type_name): New.
    	(structural_comptypes): Do structurally compare arithmetic types.

diff --git a/gcc/attribs.c b/gcc/attribs.c
index 9a88621..c36f4b4 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -690,3 +690,43 @@ make_attribute (const char *name, const char *arg_name, tree chain)
   attr = tree_cons (attr_name, attr_args, chain);
   return attr;
 }
+
+/* True iff ATTR is a type attribute that should be treated as creating a
+   variant of a base type, rather than a completely distinct type.  */
+
+bool
+variant_attribute_p (const_tree attr)
+{
+  const attribute_spec *s = lookup_attribute_spec (TREE_PURPOSE (attr));
+  return s && s->affects_type_identity == ATTRIBUTE_TYPE_VARIANT;
+}
+
+/* Return either ATTRS or a list of attributes without any attributes for which
+   variant_attribute_p is true.  Does not modify ATTRs.  */
+
+tree
+remove_variant_attributes (tree attrs)
+{
+  tree last = NULL_TREE;
+  for (tree a = attrs; a; a = TREE_CHAIN (a))
+    if (variant_attribute_p (a))
+      last = a;
+  if (!last)
+    return attrs;
+  tree l = NULL_TREE;
+  tree *p = &l;
+  for (tree a = attrs; a; a = TREE_CHAIN (a))
+    {
+      if (a == last)
+	{
+	  *p = TREE_CHAIN (a);
+	  break;
+	}
+      if (!variant_attribute_p (a))
+	{
+	  *p = build_tree_list (TREE_PURPOSE (a), TREE_VALUE (a));
+	  p = &TREE_CHAIN (*p);
+	}
+    }
+  return l;
+}
diff --git a/gcc/attribs.h b/gcc/attribs.h
index 23d3043..9a4d4e0 100644
--- a/gcc/attribs.h
+++ b/gcc/attribs.h
@@ -41,4 +41,7 @@ extern tree make_attribute (const char *, const char *, tree);
 extern struct scoped_attributes* register_scoped_attributes (const struct attribute_spec *,
 							     const char *);
 
+extern bool variant_attribute_p (const_tree);
+extern tree remove_variant_attributes (tree);
+
 #endif // GCC_ATTRIBS_H
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 8f21fd1..96e97c4 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -757,7 +757,8 @@ const struct attribute_spec c_common_attribute_table[] =
 			      handle_nonnull_attribute, false },
   { "nothrow",                0, 0, true,  false, false,
 			      handle_nothrow_attribute, false },
-  { "may_alias",	      0, 0, false, true, false, NULL, false },
+  { "may_alias",	      0, 0, false, true, false, NULL,
+			      ATTRIBUTE_TYPE_VARIANT },
   { "cleanup",		      1, 1, true, false, false,
 			      handle_cleanup_attribute, false },
   { "warn_unused_result",     0, 0, false, true, true,
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 5b87bb3..418b650 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6508,6 +6508,7 @@ extern bool class_tmpl_impl_spec_p		(const_tree);
 extern int zero_init_p				(const_tree);
 extern bool check_abi_tag_redeclaration		(const_tree, const_tree, const_tree);
 extern bool check_abi_tag_args			(tree, tree);
+extern tree apply_identity_attributes		(tree, tree, bool * = NULL);
 extern tree strip_typedefs			(tree, bool * = NULL);
 extern tree strip_typedefs_expr			(tree, bool * = NULL);
 extern tree copy_binfo				(tree, tree, tree,
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 0e44409..19208a2 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -368,6 +368,8 @@ canonicalize_for_substitution (tree node)
       else
 	node = cp_build_qualified_type (TYPE_MAIN_VARIANT (node),
 					cp_type_quals (node));
+      if (abi_version_at_least (10))
+	node = apply_identity_attributes (node, TYPE_ATTRIBUTES (orig));
       if (TREE_CODE (node) == FUNCTION_TYPE
 	  || TREE_CODE (node) == METHOD_TYPE)
 	node = build_ref_qualified_type (node, type_memfn_rqual (orig));
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 6010f63..9193b2d 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1225,7 +1225,7 @@ cv_unqualified (tree type)
    from ATTRIBS that affect type identity, and no others.  If any are not
    applied, set *remove_attributes to true.  */
 
-static tree
+tree
 apply_identity_attributes (tree result, tree attribs, bool *remove_attributes)
 {
   tree first_ident = NULL_TREE;
@@ -1268,7 +1268,7 @@ apply_identity_attributes (tree result, tree attribs, bool *remove_attributes)
 
   if (first_ident == attribs)
     /* All attributes affected type identity.  */;
-  else
+  else if (remove_attributes)
     *remove_attributes = true;
 
   return cp_build_type_attribute_variant (result, new_attribs);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 3704b88..9dd5ed6 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1181,6 +1181,17 @@ comp_template_parms_position (tree t1, tree t2)
   return true;
 }
 
+/* Look through typedefs to find the name of the underlying type of T.  */
+
+static tree
+underlying_type_name (tree t)
+{
+  tree d = TYPE_NAME (t);
+  while (d && is_typedef_decl (d))
+    d = TYPE_NAME (DECL_ORIGINAL_TYPE (d));
+  return d;
+}
+
 /* Subroutine in comptypes.  */
 
 static bool
@@ -1235,7 +1246,7 @@ structural_comptypes (tree t1, tree t2, int strict)
 
   if (TREE_CODE (t1) != ARRAY_TYPE
       && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-    return true;
+    return comp_type_attributes (t1, t2);
 
 
   /* Compare the types.  Break out if they could be the same.  */
@@ -1249,7 +1260,7 @@ structural_comptypes (tree t1, tree t2, int strict)
     case INTEGER_TYPE:
     case FIXED_POINT_TYPE:
     case REAL_TYPE:
-      /* With these nodes, we can't determine type equivalence by
+      /* With these nodes, it isn't simple to determine type equivalence by
 	 looking at what is stored in the nodes themselves, because
 	 two nodes might have different TYPE_MAIN_VARIANTs but still
 	 represent the same type.  For example, wchar_t and int could
@@ -1261,9 +1272,21 @@ structural_comptypes (tree t1, tree t2, int strict)
            typedef int INT __attribute((may_alias));
 
 	 have identical properties, different TYPE_MAIN_VARIANTs, but
-	 represent the same type.  The canonical type system keeps
-	 track of equivalence in this case, so we fall back on it.  */
-      return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
+	 represent the same type.  */
+      /* If the properties are different, they are different types.  */
+      if (TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)
+	  || TYPE_PRECISION (t1) != TYPE_PRECISION (t2))
+	return false;
+      {
+	/* If one of the types is based on a named built-in type and the other
+	   one is not based on the same type, they are different types.  */
+	tree n1 = underlying_type_name (t1);
+	tree n2 = underlying_type_name (t2);
+	if ((n1 || n2) && n1 != n2)
+	  return false;
+      }
+      /* Otherwise, compare attributes.  */
+      break;
 
     case TEMPLATE_TEMPLATE_PARM:
     case BOUND_TEMPLATE_TEMPLATE_PARM:
diff --git a/gcc/testsuite/c-c++-common/attr-may-alias-1.c b/gcc/testsuite/c-c++-common/attr-may-alias-1.c
index 978b9a5..5b2986f 100644
--- a/gcc/testsuite/c-c++-common/attr-may-alias-1.c
+++ b/gcc/testsuite/c-c++-common/attr-may-alias-1.c
@@ -1,13 +1,13 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -Wall" } */
+/* { dg-options "-O2 -Wall" { target c } } */
 
 typedef int T __attribute__((may_alias));
 
 extern T *p;
-extern int *p;
+extern int *p;			/* { dg-error "conflicting" "" { target c++ } } */
 
 extern int *p2;
-extern T *p2;
+extern T *p2;			/* { dg-error "conflicting" "" { target c++ } } */
 
 void fn1 (T);
 void fn1 (int);
diff --git a/gcc/testsuite/g++.dg/ext/alias-mangle.C b/gcc/testsuite/g++.dg/ext/alias-mangle.C
index d804c1a..062b365 100644
--- a/gcc/testsuite/g++.dg/ext/alias-mangle.C
+++ b/gcc/testsuite/g++.dg/ext/alias-mangle.C
@@ -1,6 +1,6 @@
 // PR c++/34936
 // { dg-do compile }
-/* { dg-final { scan-assembler "_ZN1AIdEC1Ev" } } */
+/* { dg-final { scan-assembler "_ZN1AIU9may_aliasdEC1Ev" } } */
 typedef double X __attribute((may_alias)) ;
 
 template<typename> struct A
@@ -8,4 +8,4 @@ template<typename> struct A
   A();
 };
 
-A<X> a;	       // { dg-warning "ignoring attributes on template argument" }
+A<X> a;
diff --git a/gcc/testsuite/g++.dg/ext/attrib50.C b/gcc/testsuite/g++.dg/ext/attrib50.C
index 9ff9918..a46c9f7 100644
--- a/gcc/testsuite/g++.dg/ext/attrib50.C
+++ b/gcc/testsuite/g++.dg/ext/attrib50.C
@@ -8,4 +8,4 @@ struct A {
   typedef int TA __attribute__((__may_alias__));
 };
 void d() { B<int &> b; }
-int main() { B<A::TA &> b; }	// { dg-warning "attributes" }
+int main() { B<A::TA &> b; }
diff --git a/gcc/testsuite/g++.dg/warn/Wignored-attributes-1.C b/gcc/testsuite/g++.dg/warn/Wignored-attributes-1.C
index 46ccc4a..fb95f7e 100644
--- a/gcc/testsuite/g++.dg/warn/Wignored-attributes-1.C
+++ b/gcc/testsuite/g++.dg/warn/Wignored-attributes-1.C
@@ -3,4 +3,4 @@
 
 typedef float __m128 __attribute__((__vector_size__(16), __may_alias__));
 template <typename> struct A;
-template <> struct A<__m128>; // { dg-warning "ignoring attributes on template argument" }
+template <> struct A<__m128>;
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index db5b470..6c098f6 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1860,10 +1860,13 @@ struct attribute_spec {
      by the rest of this structure.  */
   tree (*handler) (tree *node, tree name, tree args,
 		   int flags, bool *no_add_attrs);
-  /* Specifies if attribute affects type's identity.  */
-  bool affects_type_identity;
+  /* Specifies if attribute affects type's identity.  0 means no, 1 means it
+     creates a new distinct type, and 2 means it creates a variant.  */
+  int affects_type_identity;
 };
 
+enum { ATTRIBUTE_TYPE_VARIANT = 2 };
+
 /* These functions allow a front-end to perform a manual layout of a
    RECORD_TYPE.  (For instance, if the placement of subsequent fields
    depends on the placement of fields so far.)  Begin by calling
diff --git a/gcc/tree.c b/gcc/tree.c
index bc60190..8ce23e4 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4836,6 +4836,23 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
 	}
 
       ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED);
+
+      tree a;
+      if (a = remove_variant_attributes (attribute),
+	  a != attribute)
+	{
+	  /* Some of the attributes create a variant type.  First apply any
+	     other attributes, then create the variant.  */
+	  t = build_type_attribute_variant (ttype, a);
+	  ntype = get_attribute_qualified_type (t, attribute);
+	  if (!ntype)
+	    {
+	      ntype = build_variant_type_copy (t);
+	      TYPE_ATTRIBUTES (ntype) = attribute;
+	    }
+	}
+      else
+	{
 	  ntype = build_distinct_type_copy (ttype);
 
 	  TYPE_ATTRIBUTES (ntype) = attribute;
@@ -4871,6 +4888,7 @@ build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
 	    }
 
 	  ntype = type_hash_canon (hstate.end(), ntype);
+	}
 
       /* If the target-dependent attributes make NTYPE different from
 	 its canonical type, we will need to use structural equality
@@ -5082,6 +5100,9 @@ comp_type_attributes (const_tree type1, const_tree type2)
     }
   if (lookup_attribute ("transaction_safe", CONST_CAST_TREE (a)))
     return 0;
+  /* An attribute that creates a type variant changes the type.  */
+  if (variant_attribute_p (a))
+    return 0;
   /* As some type combinations - like default calling-convention - might
      be compatible, we have to call the target hook to get the final result.  */
   return targetm.comp_type_attributes (type1, type2);
@@ -6550,6 +6571,20 @@ check_aligned_type (const_tree cand, const_tree base, unsigned int align)
 				   TYPE_ATTRIBUTES (base)));
 }
 
+/* True iff type CAND is equivalent to BASE with ATTRIBUTE.  */
+
+static bool
+check_attribute_qualified_type (const_tree cand, const_tree base,
+				tree attribute)
+{
+  return (TYPE_QUALS (cand) == TYPE_QUALS (base)
+	  && TYPE_NAME (cand) == TYPE_NAME (base)
+	  && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
+	  && TYPE_ALIGN (cand) == TYPE_ALIGN (base)
+	  && attribute_list_equal (TYPE_ATTRIBUTES (cand),
+				   attribute));
+}
+
 /* This function checks to see if TYPE matches the size one of the built-in 
    atomic types, and returns that core atomic type.  */
 
@@ -6614,6 +6649,22 @@ get_qualified_type (tree type, int type_quals)
   return NULL_TREE;
 }
 
+/* Return a version of TYPE with ATTRIBUTES, if one exists.  If no suitable
+   type exists yet, return NULL_TREE.  */
+
+tree
+get_attribute_qualified_type (tree type, tree attribute)
+{
+  if (attribute_list_equal (TYPE_ATTRIBUTES (type), attribute))
+    return type;
+
+  for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+    if (check_attribute_qualified_type (t, type, attribute))
+      return t;
+
+  return NULL_TREE;
+}
+
 /* Like get_qualified_type, but creates the type if it does not
    exist.  This function never returns NULL_TREE.  */
 
diff --git a/gcc/tree.h b/gcc/tree.h
index 012fa54..92b53f6 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4196,6 +4196,11 @@ extern bool check_qualified_type (const_tree, const_tree, int);
 
 extern tree get_qualified_type (tree, int);
 
+/* Return a version of TYPE with ATTRIBUTES, if one exists.  If no suitable
+   type exists yet, return NULL_TREE.  */
+
+extern tree get_attribute_qualified_type (tree, tree);
+
 /* Like get_qualified_type, but creates the type if it does not
    exist.  This function never returns NULL_TREE.  */
 

[-- Attachment #3: may_alias-fe.diff --]
[-- Type: text/x-patch, Size: 6001 bytes --]

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 8f21fd1..6a8c114 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -757,7 +757,7 @@ const struct attribute_spec c_common_attribute_table[] =
 			      handle_nonnull_attribute, false },
   { "nothrow",                0, 0, true,  false, false,
 			      handle_nothrow_attribute, false },
-  { "may_alias",	      0, 0, false, true, false, NULL, false },
+  { "may_alias",	      0, 0, false, true, false, NULL, true },
   { "cleanup",		      1, 1, true, false, false,
 			      handle_cleanup_attribute, false },
   { "warn_unused_result",     0, 0, false, true, true,
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 0e44409..ca01286 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -2296,6 +2296,8 @@ write_builtin_type (tree type)
 {
   if (TYPE_CANONICAL (type))
     type = TYPE_CANONICAL (type);
+  else
+    type = TREE_TYPE (TYPE_NAME (TYPE_MAIN_VARIANT (type)));
 
   switch (TREE_CODE (type))
     {
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 3704b88..9e44c07 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1181,6 +1181,17 @@ comp_template_parms_position (tree t1, tree t2)
   return true;
 }
 
+/* Look through typedefs to find the name of the underlying type of T.  */
+
+static tree
+underlying_type_name (tree t)
+{
+  tree d = TYPE_NAME (t);
+  while (d && is_typedef_decl (d))
+    d = TYPE_NAME (DECL_ORIGINAL_TYPE (d));
+  return d;
+}
+
 /* Subroutine in comptypes.  */
 
 static bool
@@ -1249,7 +1260,7 @@ structural_comptypes (tree t1, tree t2, int strict)
     case INTEGER_TYPE:
     case FIXED_POINT_TYPE:
     case REAL_TYPE:
-      /* With these nodes, we can't determine type equivalence by
+      /* With these nodes, it isn't simple to determine type equivalence by
 	 looking at what is stored in the nodes themselves, because
 	 two nodes might have different TYPE_MAIN_VARIANTs but still
 	 represent the same type.  For example, wchar_t and int could
@@ -1261,9 +1272,21 @@ structural_comptypes (tree t1, tree t2, int strict)
            typedef int INT __attribute((may_alias));
 
 	 have identical properties, different TYPE_MAIN_VARIANTs, but
-	 represent the same type.  The canonical type system keeps
-	 track of equivalence in this case, so we fall back on it.  */
-      return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
+	 represent the same type.  */
+      /* If the properties are different, they are different types.  */
+      if (TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)
+	  || TYPE_PRECISION (t1) != TYPE_PRECISION (t2))
+	return false;
+      {
+	/* If one of the types is based on a named built-in type and the other
+	   one is not based on the same type, they are different types.  */
+	tree n1 = underlying_type_name (t1);
+	tree n2 = underlying_type_name (t2);
+	if ((n1 || n2) && n1 != n2)
+	  return false;
+      }
+      /* Otherwise, compare attributes.  */
+      break;
 
     case TEMPLATE_TEMPLATE_PARM:
     case BOUND_TEMPLATE_TEMPLATE_PARM:
@@ -9010,6 +9033,24 @@ comp_ptr_ttypes_real (tree to, tree from, int constp)
       if (VECTOR_TYPE_P (to))
 	is_opaque_pointer = vector_targets_convertible_p (to, from);
 
+      /* Allow conversion to add or remove may_alias.  */
+      if (!OVERLOAD_TYPE_P (to) && !OVERLOAD_TYPE_P (from))
+	{
+	  tree talias = lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to));
+	  tree falias = lookup_attribute ("may_alias", TYPE_ATTRIBUTES (from));
+	  if (!talias != !falias)
+	    {
+	      tree *lacks, a;
+	      if (talias)
+		lacks = &from, a = talias;
+	      else
+		lacks = &to, a = falias;
+	      tree lacka = tree_cons (TREE_PURPOSE (a), TREE_VALUE (a),
+				      TYPE_ATTRIBUTES (*lacks));
+	      *lacks = cp_build_type_attribute_variant (*lacks, lacka);
+	    }
+	}
+
       if (!TYPE_PTR_P (to) && !TYPE_PTRDATAMEM_P (to))
 	return ((constp >= 0 || to_more_cv_qualified)
 		&& (is_opaque_pointer
diff --git a/gcc/testsuite/g++.dg/ext/alias-mangle.C b/gcc/testsuite/g++.dg/ext/alias-mangle.C
index d804c1a..062b365 100644
--- a/gcc/testsuite/g++.dg/ext/alias-mangle.C
+++ b/gcc/testsuite/g++.dg/ext/alias-mangle.C
@@ -1,6 +1,6 @@
 // PR c++/34936
 // { dg-do compile }
-/* { dg-final { scan-assembler "_ZN1AIdEC1Ev" } } */
+/* { dg-final { scan-assembler "_ZN1AIU9may_aliasdEC1Ev" } } */
 typedef double X __attribute((may_alias)) ;
 
 template<typename> struct A
@@ -8,4 +8,4 @@ template<typename> struct A
   A();
 };
 
-A<X> a;	       // { dg-warning "ignoring attributes on template argument" }
+A<X> a;
diff --git a/gcc/testsuite/g++.dg/ext/attrib50.C b/gcc/testsuite/g++.dg/ext/attrib50.C
index 9ff9918..a46c9f7 100644
--- a/gcc/testsuite/g++.dg/ext/attrib50.C
+++ b/gcc/testsuite/g++.dg/ext/attrib50.C
@@ -8,4 +8,4 @@ struct A {
   typedef int TA __attribute__((__may_alias__));
 };
 void d() { B<int &> b; }
-int main() { B<A::TA &> b; }	// { dg-warning "attributes" }
+int main() { B<A::TA &> b; }
diff --git a/gcc/testsuite/g++.dg/warn/Wignored-attributes-1.C b/gcc/testsuite/g++.dg/warn/Wignored-attributes-1.C
index 46ccc4a..fb95f7e 100644
--- a/gcc/testsuite/g++.dg/warn/Wignored-attributes-1.C
+++ b/gcc/testsuite/g++.dg/warn/Wignored-attributes-1.C
@@ -3,4 +3,4 @@
 
 typedef float __m128 __attribute__((__vector_size__(16), __may_alias__));
 template <typename> struct A;
-template <> struct A<__m128>; // { dg-warning "ignoring attributes on template argument" }
+template <> struct A<__m128>;
diff --git a/gcc/tree.c b/gcc/tree.c
index bc60190..45e56bf 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -5082,6 +5082,8 @@ comp_type_attributes (const_tree type1, const_tree type2)
     }
   if (lookup_attribute ("transaction_safe", CONST_CAST_TREE (a)))
     return 0;
+  if (lookup_attribute ("may_alias", CONST_CAST_TREE (a)))
+    return 0;
   /* As some type combinations - like default calling-convention - might
      be compatible, we have to call the target hook to get the final result.  */
   return targetm.comp_type_attributes (type1, type2);

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: RFC (attributes): PATCH for c++/50800 to set affects_type_identity for may_alias
  2016-06-23 19:39 RFC (attributes): PATCH for c++/50800 to set affects_type_identity for may_alias Jason Merrill
@ 2016-06-27 11:41 ` Florian Weimer
  2016-06-27 14:09 ` Richard Biener
  1 sibling, 0 replies; 4+ messages in thread
From: Florian Weimer @ 2016-06-27 11:41 UTC (permalink / raw)
  To: Jason Merrill, gcc-patches List

On 06/23/2016 09:39 PM, Jason Merrill wrote:
> -/* { dg-final { scan-assembler "_ZN1AIdEC1Ev" } } */
> +/* { dg-final { scan-assembler "_ZN1AIU9may_aliasdEC1Ev" } } */

I find this rather worrying.

In glibc, we want to use the may_alias attribute on struct 
sockaddr_storage for POSIX conformance.  We can only do this if it does 
not affect name mangling in application code.

If we define a struct like this:

extern "C" {

struct sockaddr_storage
{
   int ss_family;
   char pad[100];
};

};

would your patch change the assembler name of a C++ function with the 
following declaration

   void get_address(struct sockaddr_storage *);

?

Thanks,
Florian

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: RFC (attributes): PATCH for c++/50800 to set affects_type_identity for may_alias
  2016-06-23 19:39 RFC (attributes): PATCH for c++/50800 to set affects_type_identity for may_alias Jason Merrill
  2016-06-27 11:41 ` Florian Weimer
@ 2016-06-27 14:09 ` Richard Biener
  2016-07-08 21:45   ` Jason Merrill
  1 sibling, 1 reply; 4+ messages in thread
From: Richard Biener @ 2016-06-27 14:09 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List

On Thu, Jun 23, 2016 at 9:39 PM, Jason Merrill <jason@redhat.com> wrote:
> My earlier patch for 50800 fixed the ICE by consistently stripping
> non-mangled attributes from template arguments, and mangling those that
> affect type identity.  At the C++ meeting this week someone pointed out to
> me that this is a real problem for x86 vector code, which relies on
> may_alias semantics: if may_alias is stripped from __m128, users can't use
> templates with vectors.
>
> So, it seems that the solution is to mangle may_alias by saying that it
> affects type identity.  But since we still want to be able to convert back
> and forth, I thought that it would make sense to treat the may_alias version
> of a type as a variant, rather than a new distinct type.  So the first patch
> creates a new category of attributes that are treated as type variants.
>
> An alternative patch just sets affects_type_identity and adjusts the C++
> front end to allow conversion between pointers to add or discard may_alias.
>
> Thoughts?

As may_alias purely affects semantics in the implementation of an API
but not the ABI it shouldn't effect mangling.  In the middle-end we use
TYPE_REF_CAN_ALIAS_ALL and that and the unqualified pointer
share the same canonical type (but it's not a variant type, pointer types
are chained via TYPE_POINTER_TO).

Not sure if you can make use of the canonicalness in the C++ FE
and maybe drop the attribute early there.

Richard.

> Tested x86_64-pc-linux-gnu.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: RFC (attributes): PATCH for c++/50800 to set affects_type_identity for may_alias
  2016-06-27 14:09 ` Richard Biener
@ 2016-07-08 21:45   ` Jason Merrill
  0 siblings, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2016-07-08 21:45 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches List

On Jun 27, 2016 12:53 PM, "Richard Biener" <richard.guenther@gmail.com> wrote:
>
> On Thu, Jun 23, 2016 at 9:39 PM, Jason Merrill <jason@redhat.com> wrote:
> > My earlier patch for 50800 fixed the ICE by consistently stripping
> > non-mangled attributes from template arguments, and mangling those that
> > affect type identity.  At the C++ meeting this week someone pointed out to
> > me that this is a real problem for x86 vector code, which relies on
> > may_alias semantics: if may_alias is stripped from __m128, users can't use
> > templates with vectors.
> >
> > So, it seems that the solution is to mangle may_alias by saying that it
> > affects type identity.  But since we still want to be able to convert back
> > and forth, I thought that it would make sense to treat the may_alias version
> > of a type as a variant, rather than a new distinct type.  So the first patch
> > creates a new category of attributes that are treated as type variants.
> >
> > An alternative patch just sets affects_type_identity and adjusts the C++
> > front end to allow conversion between pointers to add or discard may_alias.
> >
> > Thoughts?
>
> As may_alias purely affects semantics in the implementation of an API
> but not the ABI it shouldn't effect mangling.  In the middle-end we use
> TYPE_REF_CAN_ALIAS_ALL and that and the unqualified pointer
> share the same canonical type (but it's not a variant type, pointer types
> are chained via TYPE_POINTER_TO).
>
> Not sure if you can make use of the canonicalness in the C++ FE
> and maybe drop the attribute early there.

We already drop the attribute; the problem is that users want it to
affect template instantiations. For that to work it needs to affect
mangling of template arguments, at least, so that A<__m128d> and
A<__v2df> can be different types, as they need to be; if they are the
same, one or the other has the wrong semantics.

But to answer Florian's question, mangling of structs would not be
affected, only attribute-qualified built-in types.

Or perhaps we could make __m128* somehow mangle using those names
rather than the underlying vectors, maybe by wrapping them in a
struct.

Jason

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-07-08 21:45 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-23 19:39 RFC (attributes): PATCH for c++/50800 to set affects_type_identity for may_alias Jason Merrill
2016-06-27 11:41 ` Florian Weimer
2016-06-27 14:09 ` Richard Biener
2016-07-08 21:45   ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).