From patchwork Fri Sep 24 11:14:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: nick huang X-Patchwork-Id: 45412 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6E39D385801A for ; Fri, 24 Sep 2021 11:14:40 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 6E39D385801A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1632482080; bh=VpeQ3KWNDQqq7o7Roz1lPhxalt69HFO6l1MfOX3VCHA=; h=To:Subject:Date:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=rul81aGrp1ya/zjyeSF3zl5lZuo9r3smDuOL6ngt9miDnjsM3Tg2rq4V8O8MRwF33 lKqbvYO2tvQIK2e6Alyp/nZ0H5yHE9mTNhwVOgzYPo97lM0C/xN1v0pIQ7YSBoTmIW 1TVUOGuSUA1OdTH58D+4IN6DTwOKFsD9uXTX0Hfk= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from NAM02-SN1-obe.outbound.protection.outlook.com (mail-sn1anam02olkn2052.outbound.protection.outlook.com [40.92.44.52]) by sourceware.org (Postfix) with ESMTPS id CA9473858402 for ; Fri, 24 Sep 2021 11:14:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org CA9473858402 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Kje2kuUeVQlyvJwa+gKgZ2OpEsdW1JzEqBz5A7y6i226AAen4Bdrvu1TgxVA7xgPcWbcxu/wVFUHY7k8ujVOO9wm9yqN+xVjYOswSDS4xntz1tEKVdsuJbeZSo7jIP0DuOZr1ZB+Jhrr7jZVcrAiKnJEEiMARXu0BnQz9x2X9vFdXeTKp1H7I0K5950OdUdrR7+/uiqw92/KNIqNEoRLTb/j3P5MDZvzYKV7yrF4434ngbeENQIaPUppBrprxB2alcKhy+RSOnAwG+9PgyZTz78Vn9sv+4TgxIybxiZOFWblxBSFFoVc4Y3FNLcCvjKejFPaceC5q6YXgo8yUAbO7Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=VpeQ3KWNDQqq7o7Roz1lPhxalt69HFO6l1MfOX3VCHA=; b=CKx1tIkFs+BBYtjTCZ45a1bb7BASrBHnWm8S0WYSJ5VRXK9UKECza8v0NX/YKBSKvuCPxGonK7wH7nurx3v1FGQo1CH7dQ88Bdz1mYsstp2JZ1m0K3qNvsTZ+VlTA45V3gyy5EEAWs/pFjH8brSr1MFocRcP6SRIqdOHC342RWSxHSfiaY8r7+X8I/M6cZYl2keeoiUDvTuKtpXA2TAxsDzearDGubjMSIcMbUN70YAFKROKnIu2+4JvpQVnE1eVe/h1v5ovAGOsGur+sinQh/pTRirBHLyET1r+CMgZoSFMy+97wRshSyBHgI8WMBjv0+V2HMqRYDy1owZdnsUc6g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none Received: from DM5PR0501MB3733.namprd05.prod.outlook.com (2603:10b6:4:80::23) by DM5PR05MB2971.namprd05.prod.outlook.com (2603:10b6:3:55::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4566.9; Fri, 24 Sep 2021 11:14:08 +0000 Received: from DM5PR0501MB3733.namprd05.prod.outlook.com ([fe80::80fb:3d56:dd10:755d]) by DM5PR0501MB3733.namprd05.prod.outlook.com ([fe80::80fb:3d56:dd10:755d%7]) with mapi id 15.20.4544.018; Fri, 24 Sep 2021 11:14:07 +0000 To: "gcc-patches@gcc.gnu.org" Subject: *PING* [PATCH] c++: fix cases of core1001/1322 by not dropping cv-qualifier of function parameter of type of typename or decltype[PR101402,PR102033,PR102034,PR102039,PR102044] Thread-Topic: *PING* [PATCH] c++: fix cases of core1001/1322 by not dropping cv-qualifier of function parameter of type of typename or decltype[PR101402,PR102033,PR102034,PR102039,PR102044] Thread-Index: AQHXnm3npvcE3z86VU61Xh5HS2CgaKuzLUUn Date: Fri, 24 Sep 2021 11:14:07 +0000 Message-ID: References: In-Reply-To: Accept-Language: en-CA, en-US Content-Language: en-CA X-MS-Has-Attach: X-MS-TNEF-Correlator: suggested_attachment_session_id: c06fe9ef-b936-e250-10b9-31631045d5a1 x-ms-exchange-messagesentrepresentingtype: 1 x-tmn: [nqgaCkt9tbywE6GkRALolZ9Z2Gd9K6v+] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 02ff69d1-2fd1-4ba3-5e9f-08d97f4c6d63 x-ms-traffictypediagnostic: DM5PR05MB2971: x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: KKrF8yrMDD3bwmIzyi455LqC4CW1t9KKkAVcNHgXalgL7o9XOKhkyif4H1GYt5xh+e+G6FQ23A0iJE1/h1maGO/n1FmxPQ2XkZfDIp3F2x8XDXC7e8KQYsB/UN4YHNPpmyK7rED1hJj/UcXs/ViceFMnWAUTHyp3VetVmyXTSFsAoTf5I2u0tjMTGXRHpJygAIcLvUYTdbr7Hd9qUzijHV6rFc2tvV5lmjov9OzePKUry7PkbT7fiRhPdnH4yY3zXhkV9yJPQmLS/Ilr8ejsoIZcH6Yrl5XeA9bdZYiy7IMgVevvh2904o8r3Rx5M4n9SlDqWGS6Pc5VY8pSYEdag8q6u+/PZQrItodCMk93Kj3Bsd12+l2VqsKZY9+jrgociHa6uzZEun/kLmERMyU3/ut4WpTcUo1+co5itgiC2GCcXoWlI77wiU96G09PI0Z9lWyw1Q7AZ0i3Tww+ubC6uZRem9lMSQngA5AnQnd1kmI= x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: Ff4Kt06DQLBTaeswGX5X6v+9rOcoNN/qJYUUR7qt3G4W73JMLZ9fp9zS/BCJlLGoGuSNAzX/L4yMiEg6HODpe8qzLpNGu1i1RAU7hQUf5FKfHpywW5OwaOIajPZdIWXyuHkN5Cv/nPOzlz0MkJ6NFQ== x-ms-exchange-transport-forked: True MIME-Version: 1.0 X-OriginatorOrg: sct-15-20-3174-8-msonline-outlook-e6bda.templateTenant X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: DM5PR0501MB3733.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-CrossTenant-Network-Message-Id: 02ff69d1-2fd1-4ba3-5e9f-08d97f4c6d63 X-MS-Exchange-CrossTenant-originalarrivaltime: 24 Sep 2021 11:14:07.8706 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-rms-persistedconsumerorg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR05MB2971 X-Spam-Status: No, score=-9.0 required=5.0 tests=BAYES_00, BODY_8BITS, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: nick huang via Gcc-patches From: nick huang Reply-To: nick huang Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" These bugs are considered duplicate cases of PR51851 which has been suspended since 2012, an issue known as "core1001/1322". Considering this background, it deserves a long comment to explain. Many people believed the root cause of this family of bugs is related with the nature of how and when the array type is converted to pointer type during function signature is calculated. This is true, but we may need to go into details to understand the exact reason. There is a pattern for these bugs(PR101402,PR102033,PR102034,PR102039). In the template function declaration, the function parameter is consisted of a "const" followed by a typename-type which is actually an array type. According to standard, function signature is calculated by dropping so-called "top-level-cv-qualifier". As a result, the templater specialization complains no matching to declaration can be found because specialization has const and template function declaration doesn't have const which is dropped as mentioned. Obviously the template function declaration should NOT drop the const. But why? Let's review the procedure of standard first. (https://timsong-cpp.github.io/cppwp/dcl.fct#5.sentence-3) "After determining the type of each parameter, any parameter of type “array of T” or of function type T is adjusted to be “pointer to T”. After producing the list of parameter types, any top-level cv-qualifiers modifying a parameter type are deleted when forming the function type." Please note the action of deleting top-level cv-qualifiers happens at last stage after array type is converted to pointer type. More importantly, there are two conditions: a) Each type must be able to be determined. b) The cv-qualifier must be top-level. Let's analysis if these two conditions can be met one by one. 1) Keyword "typename" indicates inside template it involves dependent name  (https://timsong-cpp.github.io/cppwp/n4659/temp.res#2) for which the name lookup can be postponed until template instantiation. Clearly the type of dependent name cannot be determined without name lookup. Then we can NOT proceed to next step until concrete template argument type is determined during specialization. 2) After “array of T” is converted to “pointer to T”, the cv-qualifiers are no longer top-level! Unfortunately in standard there is no definition of "top-level". Mr. Dan Saks's articals (https://www.dansaks.com/articles.shtml) are tremendous help! Especially this wonderful paper (https://www.dansaks.com/articles/2000-02%20Top-Level%20cv-Qualifiers%20in%20Function%20Parameters.pdf)  discusses this topic in details. In one short sentence, the "const" before array type is NOT top-level-cv-qualifier and should NOT be dropped. So, understanding the root cause makes the fix very clear: Let's NOT drop cv-qualifier for typename-type inside template. Leave this task for template substitution later when template specialization locks template argument types. Similarly inside template, "decltype" may also include dependent name and the best strategy for parser is to preserve all original declaration and postpone the task till template substitution. Here is an interesting observation to share. Originally my fix is trying to use function "resolve_typename_type" to see if the "typename-type" is indeed an array type so as to decide whether the const should be dropped. It works for cases of PR101402,PR102033(with a small fix of function), but cannot succeed on cases of PR102034,PR102039. Especially PR102039 is impossible because it depends on template argument. This helps me realize that parser should not do any work if it cannot be 100% successful. All can wait. At last I want to acknowledge other efforts to tackle this core 1001/1322 from PR92010 which is an irreplaceable different approach from this fix by doing rebuilding template function signature during template substitution stage. After all, this fix can only deal with dependent type started with "typename" or "decltype" which is not the case of pr92010.   gcc/cp/ChangeLog: 2021-08-30  qingzhe huang          * decl.c (grokparms): gcc/testsuite/ChangeLog: 2021-08-30  qingzhe huang          * g++.dg/parse/pr101402.C: New test.         * g++.dg/parse/pr102033.C: New test.         * g++.dg/parse/pr102034.C: New test.         * g++.dg/parse/pr102039.C: New test.         * g++.dg/parse/pr102044.C: New test. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e0c603aaab6..940c43ce707 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -14384,7 +14384,16 @@ grokparms (tree parmlist, tree *parms)              /* Top-level qualifiers on the parameters are               ignored for function types.  */ -         type = cp_build_qualified_type (type, 0); + +         int type_quals = 0; +         /* Inside template declaration, typename and decltype indicating +            dependent name and cv-qualifier are preserved until +            template instantiation. +            PR101402/PR102033/PR102034/PR102039/PR102044 */ +         if (processing_template_decl +               && (TREE_CODE (type) == TYPENAME_TYPE || TREE_CODE (type) == DECLTYPE_TYPE)) +                 type_quals = CP_TYPE_CONST_P(type); +         type = cp_build_qualified_type (type, type_quals);            if (TREE_CODE (type) == METHOD_TYPE)              {                error ("parameter %qD invalidly declared method type", decl); diff --git a/gcc/testsuite/g++.dg/parse/pr101402.C b/gcc/testsuite/g++.dg/parse/pr101402.C new file mode 100644 index 00000000000..58d9c4f8542 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr101402.C @@ -0,0 +1,5 @@ +template struct A { +     typedef T arr[3]; +}; +template void f(const typename A::arr) { } // #1 +template void f(const A::arr); diff --git a/gcc/testsuite/g++.dg/parse/pr102033.C b/gcc/testsuite/g++.dg/parse/pr102033.C new file mode 100644 index 00000000000..0d5cc17620f --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr102033.C @@ -0,0 +1,34 @@ +/* {dg-do compile } */ +/* {dg-options "-std=c++11" } */ + +namespace test1 +{ +template +struct A{ +        template +        using Type=TB[3]; +}; +template +void f(const typename A::template Type){} +template <> +void f(const typename A::template Type){} +} +namespace test2 +{ +template +struct A{ +        template +        struct B{ +                using TB_Alias=TB; +                template +                struct C{ +                        typedef TC Arr3[3]; +                }; +        }; +}; +template +void f(const typename A::template B::template C<>::Arr3){} +template <> +void f(const typename A::template B::template C<>::Arr3){} +} + diff --git a/gcc/testsuite/g++.dg/parse/pr102034.C b/gcc/testsuite/g++.dg/parse/pr102034.C new file mode 100644 index 00000000000..37fdce52912 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr102034.C @@ -0,0 +1,13 @@ +/*{dg-do compile} */ +template +struct A{ +        template +        struct B{ +        typedef TB Arr3[3]; +        }; +}; +template +void f(const typename A::template B::Arr3){} +template <> +void f(const typename A::B::Arr3){} + diff --git a/gcc/testsuite/g++.dg/parse/pr102039.C b/gcc/testsuite/g++.dg/parse/pr102039.C new file mode 100644 index 00000000000..25d3e77fd74 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr102039.C @@ -0,0 +1,24 @@ +namespace test1 +{ +struct A{ +        typedef int Arr3[3]; +}; + +template +void f(const typename T::Arr3){} + +template<> +void f(const int[3]){} +} + +namespace test2 +{ +struct A{ +        typedef int Arr3[3]; +}; +template +void f(const typename T::Arr3){} +template<> +void f(const int*){} +} + diff --git a/gcc/testsuite/g++.dg/parse/pr102044.C b/gcc/testsuite/g++.dg/parse/pr102044.C new file mode 100644 index 00000000000..bef6a920b47 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr102044.C @@ -0,0 +1,32 @@ +/* {dg-do compile } */ +/* {dg-options "-std=c++11" } */ +namespace test1 +{ +template +void f(const T[N]){} + +template +using fPtr=decltype(f)*; + +template +fPtr af[N]={&f}; + +template +void g(const decltype(af)){} + +template<> +void g<1,int>(const fPtr<1,int>[1]){} +} + +namespace test2 +{ +template +struct A{ +T arr3[3]; +}; +template +void f(const decltype(A::arr3)){} +template <> +void f(const int[3]){} +} +