From patchwork Thu Oct 14 01:20:28 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: C++ PATCH for c++/45984 (canonical type ice with attributes) Date: Wed, 13 Oct 2010 15:20:28 -0000 From: Jason Merrill X-Patchwork-Id: 67764 Message-Id: <4CB65ADC.2030105@redhat.com> To: gcc-patches List The problem in this testcase was that when we see an elaborated-type-specifier for a class, and use it to form variants, then define the class with attributes, and use one of the same variants within the definition of the class, check_qualified_type didn't reuse the variant we had previously created because the attributes (and alignment) didn't match. Fixed by propagating those two fields immediately after applying attributes. Tested x86_64-pc-linux-gnu, applied to trunk. commit e587ccbae647308fa483818592889c47e0924c03 Author: Jason Merrill Date: Wed Oct 13 10:37:47 2010 -0400 PR c++/45984 * class.c (fixup_attribute_variants): New fn. * cp-tree.h: Declare it. * pt.c (instantiate_class_template): Call it. * semantics.c (begin_class_definition): Call it. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index b093ce0..f76c2be 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1515,12 +1515,31 @@ fixup_type_variants (tree t) TYPE_VFIELD (variants) = TYPE_VFIELD (t); TYPE_METHODS (variants) = TYPE_METHODS (t); TYPE_FIELDS (variants) = TYPE_FIELDS (t); + } +} - /* All variants of a class have the same attributes. */ +/* Early variant fixups: we apply attributes at the beginning of the class + definition, and we need to fix up any variants that have already been + made via elaborated-type-specifier so that check_qualified_type works. */ + +void +fixup_attribute_variants (tree t) +{ + tree variants; + + if (!t) + return; + + for (variants = TYPE_NEXT_VARIANT (t); + variants; + variants = TYPE_NEXT_VARIANT (variants)) + { + /* These are the two fields that check_qualified_type looks at and + are affected by attributes. */ TYPE_ATTRIBUTES (variants) = TYPE_ATTRIBUTES (t); + TYPE_ALIGN (variants) = TYPE_ALIGN (t); } } - /* Set memoizing fields and bits of T (and its variants) for later use. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index bfc6fd3..29a4bdb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4711,6 +4711,7 @@ extern bool type_has_move_assign (tree); extern void defaulted_late_check (tree); extern bool defaultable_fn_check (tree); extern void fixup_type_variants (tree); +extern void fixup_attribute_variants (tree); extern tree* decl_cloned_function_p (const_tree, bool); extern void clone_function_decl (tree, int); extern void adjust_clone_args (tree); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 84901d3..9ddb4fd 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7943,6 +7943,7 @@ instantiate_class_template (tree type) apply_late_template_attributes (&type, TYPE_ATTRIBUTES (pattern), (int) ATTR_FLAG_TYPE_IN_PLACE, args, tf_error, NULL_TREE); + fixup_attribute_variants (type); /* Now that our base classes are set up, enter the scope of the class, so that name lookups into base classes, etc. will work diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index b73dffb..787c72c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2391,6 +2391,7 @@ begin_class_definition (tree t, tree attributes) TYPE_BEING_DEFINED (t) = 1; cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); + fixup_attribute_variants (t); if (flag_pack_struct) { diff --git a/gcc/testsuite/g++.dg/template/canon-type-8.C b/gcc/testsuite/g++.dg/template/canon-type-8.C new file mode 100644 index 0000000..fd1fe3c --- /dev/null +++ b/gcc/testsuite/g++.dg/template/canon-type-8.C @@ -0,0 +1,38 @@ +// PR c++/45984 +// We were getting different canonical types for matching types because +// TYPE_ALIGN wasn't propagated to all the variants fast enough. +// { dg-options "" } + +typedef __SIZE_TYPE__ size_t; +enum { chunk_size = 16 }; +typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__)); +typedef float __v4sf __attribute__ ((__vector_size__ (16))); +struct __attribute__((aligned((16)))) float4_t { + typedef float scalar_t; + typedef __m128 type_t; + typedef float4_t return_type_t; + type_t m; + inline __attribute__((artificial, gnu_inline, always_inline)) explicit + float4_t(scalar_t a) : m(((__m128) (__v4sf) { (a), (a), (a), (a) })) { } + inline __attribute__((artificial, gnu_inline, always_inline, pure)) friend + return_type_t operator+(float4_t lhs, float4_t rhs) { } +}; +template class __attribute__((aligned((16)))) chunk_array_t { +public: + typedef float4_t value_type_t; + typedef value_type_t value_array_t[chunk_size/4]; + enum { num_scalars = chunk_size, num_values = num_scalars/4 }; + const value_array_t &chan(size_t c) const { } + value_type_t operator[](size_t i) const { } +}; +typedef chunk_array_t<1> chunk_array_mono_t; +typedef chunk_array_t<2> chunk_array_stereo_t; +class freeverb_stereo_t { + void process(const chunk_array_stereo_t & __restrict__ src, + chunk_array_stereo_t & __restrict__ dst) { + enum { chunk_size = chunk_array_t<1>::num_values }; + chunk_array_mono_t mix; + for (size_t i=0; i