Patchwork C++ PATCH for c++/53989 (ICE with array of typedef)

login
register
mail settings
Submitter Jason Merrill
Date July 17, 2012, 9:33 p.m.
Message ID <5005DA3A.5050303@redhat.com>
Download mbox | patch
Permalink /patch/171564/
State New
Headers show

Comments

Jason Merrill - July 17, 2012, 9:33 p.m.
As it turns out, the problem in this case was that we were building up a 
canonical array as part of building up an array of the typedef, but we 
didn't add it to the list of array variants, so 
complete_vars/finalize_type_size couldn't find it to fix it up.  Fixed 
by adding it to the variant list appropriately.

Tested x86_64-pc-linux-gnu, applying to trunk and 4.7.

Patch

commit 465cefa1e575ccedfa6655018a31241ba2a669c6
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jul 17 16:56:04 2012 -0400

    	PR c++/53989
    	* tree.c (build_cplus_array_type): Also add TYPE_CANONICAL
    	to the list of variants.

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 01bc483..3c7bbb132 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -803,12 +803,23 @@  build_cplus_array_type (tree elt_type, tree index_type)
     {
       tree m = build_cplus_array_type (TYPE_MAIN_VARIANT (elt_type),
 				       index_type);
+      tree c = TYPE_CANONICAL (t);
+
       if (TYPE_MAIN_VARIANT (t) != m)
 	{
 	  TYPE_MAIN_VARIANT (t) = m;
 	  TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
 	  TYPE_NEXT_VARIANT (m) = t;
 	}
+
+      /* If we built a new array type for TYPE_CANONICAL, add
+	 that to the list of variants as well.  */
+      if (c && c != t && TYPE_MAIN_VARIANT (c) != m)
+	{
+	  TYPE_MAIN_VARIANT (c) = m;
+	  TYPE_NEXT_VARIANT (c) = t;
+	  TYPE_NEXT_VARIANT (m) = c;
+	}
     }
 
   /* Push these needs up so that initialization takes place
diff --git a/gcc/testsuite/g++.dg/template/array23.C b/gcc/testsuite/g++.dg/template/array23.C
new file mode 100644
index 0000000..6ede8b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/array23.C
@@ -0,0 +1,12 @@ 
+// PR c++/53989
+
+struct Foo {
+  int value;
+  typedef Foo Foo2;
+  static Foo2 const foos[2];
+};
+
+template <class T> void g (T);
+void bar() {
+  g(&Foo::foos);
+}