From patchwork Thu Apr 4 00:16:07 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 233600 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]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id D1DC12C00F1 for ; Thu, 4 Apr 2013 11:16:23 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=f+li6vlkq3M15GG42tVdvDCXnVlNPHQKA6wrJqGGGTuPFO 7NBOO6gmcNgjVLeqjIIG7Y3dMpYzuB/qFWUx7o9zeT7W5hngWjMmd5gN2r1Vmxv1 foDQv44OhYEsZS5gh9Bex89EWaMu+iyGDBb0ECcJmOdOKGoX2CGsiGBtFaisY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=dHJVYKfLZ3NXM9KIAsMFRamSN60=; b=PiT78MzQGb1xJjNFhqtC G8a4zIvgkNghkiDrbqi49hIUJFoUFJhsKLfawLVaVRvDNWChmLNdSl7CeXMDCfRe o44er6OsY71py+LfGCN8rHwES/WKEc4EOfIf2keLA0ldTpw5JKOinGIwzXLR3NdJ VOyMB2hvf7nxOejFfhjAS0k= Received: (qmail 2086 invoked by alias); 4 Apr 2013 00:16:13 -0000 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 Received: (qmail 2070 invoked by uid 89); 4 Apr 2013 00:16:12 -0000 X-Spam-SWARE-Status: No, score=-7.6 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.1 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Thu, 04 Apr 2013 00:16:09 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r340G8UF016684 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 3 Apr 2013 20:16:08 -0400 Received: from [10.3.113.56] (ovpn-113-56.phx2.redhat.com [10.3.113.56]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id r340G73H024419 for ; Wed, 3 Apr 2013 20:16:07 -0400 Message-ID: <515CC647.1090106@redhat.com> Date: Wed, 03 Apr 2013 20:16:07 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux i686; rv:22.0) Gecko/20100101 Thunderbird/22.0a2 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH to correct mangling/demangling of cv-qualified function types X-Virus-Found: No While I was working on the ref-qualifier mangling, I noticed that we were handling function-cv-quals wrong; those quals should be considered an indivisible part of the function type rather than a separate qualifier. Tested x86_64-pc-linux-gnu, applying to trunk. commit 6af1b337883b2c88e6411f24d8cb7bf2a76ea94e Author: Jason Merrill Date: Wed Apr 3 12:37:41 2013 -0400 libiberty/ * cp-demangle.c (cplus_demangle_type): Fix function quals. (d_pointer_to_member_type): Simplify. gcc/cp/ * mangle.c (write_type): When writing a function type with function-cv-quals, don't add the unqualified type as a substitution candidate. diff --git a/gcc/common.opt b/gcc/common.opt index bdbd3b6..e02e7ed 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -792,6 +792,11 @@ Driver Undocumented ; 7: The version of the ABI that treats nullptr_t as a builtin type and ; corrects the mangling of lambdas in default argument scope. ; First selectable in G++ 4.8. +; +; 8: The version of the ABI that corrects the substitution behavior of +; function types with function-cv-qualifiers. +; First selectable in G++ 4.9. +; ; Additional positive integers will be assigned as new versions of ; the ABI become the default version of the ABI. fabi-version= diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 4e68c51..83c3e62 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1897,8 +1897,16 @@ write_type (tree type) tree t = TYPE_MAIN_VARIANT (type); if (TREE_CODE (t) == FUNCTION_TYPE || TREE_CODE (t) == METHOD_TYPE) - t = build_ref_qualified_type (t, type_memfn_rqual (type)); - write_type (t); + { + t = build_ref_qualified_type (t, type_memfn_rqual (type)); + if (abi_version_at_least (8)) + /* Avoid adding the unqualified function type as a substitution. */ + write_function_type (t); + else + write_type (t); + } + else + write_type (t); } else if (TREE_CODE (type) == ARRAY_TYPE) /* It is important not to use the TYPE_MAIN_VARIANT of TYPE here diff --git a/gcc/testsuite/g++.dg/abi/mangle62.C b/gcc/testsuite/g++.dg/abi/mangle62.C new file mode 100644 index 0000000..6dbfd78 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/mangle62.C @@ -0,0 +1,11 @@ +// Before v8, we mistakenly treated an unqualified function type +// as a substitution candidate for a function type with function-cv-quals. +// Test for the conformant behavior. + +// { dg-options -fabi-version=0 } + +template struct A { }; +// { dg-final { scan-assembler "_Z1fP1AIKFvvEFvvEE" } } +void f (A *){} +// { dg-final { scan-assembler "_Z1gP1AIFvvEKFvvEE" } } +void g (A *){} diff --git a/gcc/testsuite/g++.dg/abi/mangle62a.C b/gcc/testsuite/g++.dg/abi/mangle62a.C new file mode 100644 index 0000000..fca1cb6 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/mangle62a.C @@ -0,0 +1,11 @@ +// Before v8, we mistakenly treated an unqualified function type +// as a substitution candidate for a function type with function-cv-quals. +// Test for that for backward compatibility. + +// { dg-options -fabi-version=7 } + +template struct A { }; +// { dg-final { scan-assembler "_Z1fP1AIKFvvES0_E" } } +void f (A *){} +// { dg-final { scan-assembler "_Z1gP1AIFvvEKS0_E" } } +void g (A *){} diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 271d3d3..70f5438 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -2198,8 +2198,16 @@ cplus_demangle_type (struct d_info *di) pret = d_cv_qualifiers (di, &ret, 0); if (pret == NULL) return NULL; - *pret = cplus_demangle_type (di); - if (! *pret) + if (d_peek_char (di) == 'F') + { + /* cv-qualifiers before a function type apply to 'this', + so avoid adding the unqualified function type to + the substitution list. */ + *pret = d_function_type (di); + } + else + *pret = cplus_demangle_type (di); + if (!*pret) return NULL; if ((*pret)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS || (*pret)->type == DEMANGLE_COMPONENT_REFERENCE_THIS) @@ -2739,53 +2747,32 @@ d_pointer_to_member_type (struct d_info *di) { struct demangle_component *cl; struct demangle_component *mem; - struct demangle_component **pmem; if (! d_check_char (di, 'M')) return NULL; cl = cplus_demangle_type (di); - - /* The ABI specifies that any type can be a substitution source, and - that M is followed by two types, and that when a CV-qualified - type is seen both the base type and the CV-qualified types are - substitution sources. The ABI also specifies that for a pointer - to a CV-qualified member function, the qualifiers are attached to - the second type. Given the grammar, a plain reading of the ABI - suggests that both the CV-qualified member function and the - non-qualified member function are substitution sources. However, - g++ does not work that way. g++ treats only the CV-qualified - member function as a substitution source. FIXME. So to work - with g++, we need to pull off the CV-qualifiers here, in order to - avoid calling add_substitution() in cplus_demangle_type(). But - for a CV-qualified member which is not a function, g++ does - follow the ABI, so we need to handle that case here by calling - d_add_substitution ourselves. */ - - pmem = d_cv_qualifiers (di, &mem, 1); - if (pmem == NULL) - return NULL; - *pmem = cplus_demangle_type (di); - if (*pmem == NULL) + if (cl == NULL) return NULL; - if (pmem != &mem - && ((*pmem)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS - || (*pmem)->type == DEMANGLE_COMPONENT_REFERENCE_THIS)) - { - /* Move the ref-qualifier outside the cv-qualifiers so that - they are printed in the right order. */ - struct demangle_component *fn = d_left (*pmem); - d_left (*pmem) = mem; - mem = *pmem; - *pmem = fn; - } + /* The ABI says, "The type of a non-static member function is considered + to be different, for the purposes of substitution, from the type of a + namespace-scope or static member function whose type appears + similar. The types of two non-static member functions are considered + to be different, for the purposes of substitution, if the functions + are members of different classes. In other words, for the purposes of + substitution, the class of which the function is a member is + considered part of the type of function." - if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE) - { - if (! d_add_substitution (di, mem)) - return NULL; - } + For a pointer to member function, this call to cplus_demangle_type + will end up adding a (possibly qualified) non-member function type to + the substitution table, which is not correct; however, the member + function type will never be used in a substitution, so putting the + wrong type in the substitution table is harmless. */ + + mem = cplus_demangle_type (di); + if (mem == NULL) + return NULL; return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem); } diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index ed73245..1259e4a 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -4273,8 +4273,8 @@ foo # --format=gnu-v3 --no-params _Z1fIKFvvES0_Evv -void f() -f +void f() +f # --format=gnu-v3 _ZN4modc6parser8sequenceINS_9astParser13LocatedParserINS0_9ParserRefINS2_UlRNS2_16TokenParserInputEE_EEEEEINS0_14OptionalParserINS2_18ListParserTemplateILNS_6tokens5Token4TypeE4EXadL_ZNSD_Ut_13parenthesizedEEEE6ParserINS4_INS0_6ParserIS5_NS_3ast10ExpressionEEEEEEEEENSA_INS4_INS2_22OneOfKeywordsToTParserINSJ_5StyleEEEEEEENS0_14SequenceParserIS5_INS0_18ExactElementParserIS5_EENSA_ISM_EEEEENS0_14RepeatedParserINS4_INS0_15TransformParserINSU_IS5_INS4_INSP_INSJ_10Annotation12RelationshipEEEEESX_EEENS2_UlNS2_3LocES12_ONS_5MaybeISK_EEE19_EEEEELb0EEEEEENSU_INS0_17ExtractParserTypeIT_E9InputTypeEINS0_8MaybeRefIS1F_E4TypeEDpNS1I_IT0_E4TypeEEEEOS1F_DpOS1L_