From patchwork Thu Oct 14 01:20:28 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 67764 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id B20F3B70D1 for ; Thu, 14 Oct 2010 12:20:41 +1100 (EST) Received: (qmail 30300 invoked by alias); 14 Oct 2010 01:20:40 -0000 Received: (qmail 30292 invoked by uid 22791); 14 Oct 2010 01:20:39 -0000 X-SWARE-Spam-Status: No, hits=-6.1 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 14 Oct 2010 01:20:32 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o9E1KUom001359 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 13 Oct 2010 21:20:30 -0400 Received: from [127.0.0.1] ([10.3.113.12]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id o9E1KTjX030157 for ; Wed, 13 Oct 2010 21:20:30 -0400 Message-ID: <4CB65ADC.2030105@redhat.com> Date: Wed, 13 Oct 2010 21:20:28 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.14) Gecko/20101002 Lightning/1.0b1 Shredder/3.0.9pre MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/45984 (canonical type ice with attributes) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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