On 07/20/2012 09:26 AM, Jakub Jelinek wrote:
As detailed in the PR, I believe we should only add c into m's variant chain if m's element type is the main variant of c's element type.
We want c to get onto the appropriate variant chain even if it isn't m's, so I'm applying this patch instead.
Tested x86_64-pc-linux-gnu, applying to trunk and 4.7.
commit 3e16b98aa7e47f321974b5623cd68d2671a87f1e Author: Jason Merrill <ja...@redhat.com> Date: Fri Jul 20 11:19:07 2012 -0400 PR c++/54038 * tree.c (build_cplus_array_type): Use build_cplus_array_type to build canonical array type rather than mess with its TYPE_*_VARIANT. diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 1e98f85..de9e0f6 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -786,7 +786,18 @@ build_cplus_array_type (tree elt_type, tree index_type) } } else - t = build_array_type (elt_type, index_type); + { + if (!TYPE_STRUCTURAL_EQUALITY_P (elt_type) + && !(index_type && TYPE_STRUCTURAL_EQUALITY_P (index_type)) + && (TYPE_CANONICAL (elt_type) != elt_type + || (index_type && TYPE_CANONICAL (index_type) != index_type))) + /* Make sure that the canonical type is on the appropriate + variants list. */ + build_cplus_array_type + (TYPE_CANONICAL (elt_type), + index_type ? TYPE_CANONICAL (index_type) : index_type); + t = build_array_type (elt_type, index_type); + } /* We want TYPE_MAIN_VARIANT of an array to strip cv-quals from the element type as well, so fix it up if needed. */ @@ -794,7 +805,6 @@ 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) { @@ -802,15 +812,6 @@ build_cplus_array_type (tree elt_type, tree index_type) 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/other/array7.C b/gcc/testsuite/g++.dg/other/array7.C new file mode 100644 index 0000000..72322f0 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/array7.C @@ -0,0 +1,9 @@ +// PR c++/54038 + +extern const char *const v[]; +typedef char T; +void foo (const T *const[]); +struct A +{ + static const char *const a[]; +};