diff mbox

C++ PATCH for c++/68049 (ICE with may_alias)

Message ID 56CF0AA6.9000406@redhat.com
State New
Headers show

Commit Message

Jason Merrill Feb. 25, 2016, 2:07 p.m. UTC
strip_typedefs was failing to strip the typedef in this case, because 
TYPE_MAIN_VARIANT doesn't strip attributes, which were applied after 
applying the typedef name.  Fixed by explicitly using DECL_ORIGINAL_TYPE.

Tested x86_64-pc-linux-gnu, applying to trunk and 5.
diff mbox

Patch

commit bd94683bb095be2533c7cdae930e9fb987a22dbf
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Feb 24 16:46:09 2016 -0500

    	PR c++/68049
    	* tree.c (strip_typedefs): Use DECL_ORIGINAL_TYPE.

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 0f7287a..ac38ce3 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1447,7 +1447,15 @@  strip_typedefs (tree t, bool *remove_attributes)
     }
 
   if (!result)
-      result = TYPE_MAIN_VARIANT (t);
+    {
+      if (typedef_variant_p (t))
+	/* Explicitly get the underlying type, as TYPE_MAIN_VARIANT doesn't
+	   strip typedefs with attributes.  */
+	result = TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (TYPE_NAME (t)));
+      else
+	result = TYPE_MAIN_VARIANT (t);
+    }
+  gcc_assert (!typedef_variant_p (result));
   if (TYPE_USER_ALIGN (t) != TYPE_USER_ALIGN (result)
       || TYPE_ALIGN (t) != TYPE_ALIGN (result))
     {
diff --git a/gcc/testsuite/g++.dg/ext/attribute-may-alias-3.C b/gcc/testsuite/g++.dg/ext/attribute-may-alias-3.C
new file mode 100644
index 0000000..ba6091b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attribute-may-alias-3.C
@@ -0,0 +1,22 @@ 
+// PR c++/68049
+// { dg-do compile { target c++11 } }
+
+template <typename T> struct Bar
+{
+    using type = T;
+};
+template <typename T> struct Foo
+{
+    typedef typename Bar<T>::type alias_type [[gnu::may_alias]];
+
+    alias_type operator()() { return {}; }
+};
+
+template <typename T> void print(T) {}
+
+int main()
+{
+    print(Foo<int>()());
+    print(0);
+    return 0;
+}