From patchwork Thu Jan 28 12:54:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 1432785 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=Ce4GeWeB; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DRL5c1xC7z9sSC for ; Thu, 28 Jan 2021 23:54:26 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C8583398E49A; Thu, 28 Jan 2021 12:54:23 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qk1-x72f.google.com (mail-qk1-x72f.google.com [IPv6:2607:f8b0:4864:20::72f]) by sourceware.org (Postfix) with ESMTPS id 377783865C2D for ; Thu, 28 Jan 2021 12:54:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 377783865C2D Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nathanmsidwell@gmail.com Received: by mail-qk1-x72f.google.com with SMTP id r77so5033579qka.12 for ; Thu, 28 Jan 2021 04:54:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=ey5Y1u6YXlgYt32TQsDh5nfr4izw2fQmyVKjXfsMYkM=; b=Ce4GeWeBxqzL5oHgH2gbkZeat5/jCaV5rEdmfv4AJ6DRz+Gf3w4bQofE+rl7/lBbQ2 eCeyRlO4dg14yPDIQc7hCMyB1GXzzttEdF3Vgn/p8W9x7AM0MsfchabU59/KCC+O2SSz mDYqLkKxI4a3k2ZE97OA90EE54lEFRqNzn2GGfwCMfzPSI+zvyPM8q6xnumgtJOq1JMW 19TqITjNXPXz4cF1sBIvgzR6jw4WdzIOMoU+eRAEUheo4O7WiCDBUWEqfhtcmnVMhWdM 7nlm2xWr4UhTRrOv7cNyBqowyAEXSYmMJalW6Glca8OdI5D6lxm4qSY4GP3W0okq4KnE c1Cw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:from:subject:message-id:date :user-agent:mime-version:content-language; bh=ey5Y1u6YXlgYt32TQsDh5nfr4izw2fQmyVKjXfsMYkM=; b=No+R7aNaLe/+Se0mFqS1KgShkee0TxBMw9v3Pgt7hb79+SX1RPHUdDGvKnkq1vTbEt 6GLPfJ1IM70iOtZ5TioqgKT522lFHfU4r1MTMtc+IhGpxobX2T02qlfZRTqxZmCyvXVY 09mF8YZg8ngbUt6/q3196L8wi9A4+/6w46Lg70VBediuiOUs4jQhiICidehOszzu1kD1 g9Eq50Xf6Qmreqbt4+Rh7Ah3F4YPAQPTsPVxmi5qGt5p4xSOiAUgwm+a5sEDTwtVuwxu xQ1vCPTXzDkw1hVqwbky0McwlDZ0gsPLKGShWBOuIKr6hgeS3OmpMg45zc+kv5faoqKC bQYQ== X-Gm-Message-State: AOAM531FbP4yLrClMAcftP+XSN4fFuCQlY9iH4Ed54iYhhYpRe84aFqL fk89UV0Lz+nJykjrJvmrvKo= X-Google-Smtp-Source: ABdhPJyQPNF9BLUCBFpHvY6E1iNU+dmORTPoYnK0i5ImYYTFBszhTdNE8Xz+gVD6cznwlOh1QssGYw== X-Received: by 2002:a05:620a:9cf:: with SMTP id y15mr15434469qky.44.1611838460799; Thu, 28 Jan 2021 04:54:20 -0800 (PST) Received: from ?IPv6:2620:10d:c0a8:1102:b861:737e:f651:762b? ([2620:10d:c091:480::1:55c2]) by smtp.googlemail.com with ESMTPSA id i129sm3277413qkd.114.2021.01.28.04.54.18 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 28 Jan 2021 04:54:18 -0800 (PST) To: GCC Patches From: Nathan Sidwell Subject: c++: header unit template alias merging [PR 98770] Message-ID: <7e0e26b4-aac6-9928-ef02-0802c743a53b@acm.org> Date: Thu, 28 Jan 2021 07:54:17 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-11.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" Typedefs are streamed by streaming the underlying type, and then recreating the typedef. But this breaks checking a duplicate is the same as the original when it is a template alias -- we end up checking a template alias (eg __void_t) against the underlying type (void). And those are not the same template alias. This stops pretendig that the underlying type is the typedef for that checking and tells is_matching_decl 'you have a typedef', so it knows what to do. (We do not want to recreate the typedef of the duplicate, because that whole set of nodes is going to go away.) PR c++/98770 gcc/cp/ gcc/testsuite/ * g++.dg/modules/pr98770_a.C: New. * g++.dg/modules/pr98770_b.C: New. diff --git c/gcc/cp/module.cc w/gcc/cp/module.cc index 18f5de8724b..daf75b16007 100644 --- c/gcc/cp/module.cc +++ w/gcc/cp/module.cc @@ -3029,7 +3029,7 @@ public: bool read_definition (tree decl); private: - bool is_matching_decl (tree existing, tree decl); + bool is_matching_decl (tree existing, tree decl, bool is_typedef); static bool install_implicit_member (tree decl); bool read_function_def (tree decl, tree maybe_template); bool read_var_def (tree decl, tree maybe_template); @@ -7864,8 +7864,8 @@ trees_out::decl_value (tree decl, depset *dep) || !dep == (VAR_OR_FUNCTION_DECL_P (inner) && DECL_LOCAL_DECL_P (inner))); else if ((TREE_CODE (inner) == TYPE_DECL - && TYPE_NAME (TREE_TYPE (inner)) == inner - && !is_typedef) + && !is_typedef + && TYPE_NAME (TREE_TYPE (inner)) == inner) || TREE_CODE (inner) == FUNCTION_DECL) { bool write_defn = !dep && has_definition (decl); @@ -8088,12 +8088,6 @@ trees_in::decl_value () && TREE_CODE (inner) == TYPE_DECL && DECL_ORIGINAL_TYPE (inner) && !TREE_TYPE (inner)); - if (is_typedef) - { - /* Frob it to be ready for cloning. */ - TREE_TYPE (inner) = DECL_ORIGINAL_TYPE (inner); - DECL_ORIGINAL_TYPE (inner) = NULL_TREE; - } existing = back_refs[~tag]; bool installed = install_entity (existing); @@ -8156,7 +8150,12 @@ trees_in::decl_value () } if (is_typedef) - set_underlying_type (inner); + { + /* Frob it to be ready for cloning. */ + TREE_TYPE (inner) = DECL_ORIGINAL_TYPE (inner); + DECL_ORIGINAL_TYPE (inner) = NULL_TREE; + set_underlying_type (inner); + } if (inner_tag) /* Set the TEMPLATE_DECL's type. */ @@ -8218,7 +8217,7 @@ trees_in::decl_value () /* Set the TEMPLATE_DECL's type. */ TREE_TYPE (decl) = TREE_TYPE (inner); - if (!is_matching_decl (existing, decl)) + if (!is_matching_decl (existing, decl, is_typedef)) unmatched_duplicate (existing); /* And our result is the existing node. */ @@ -8257,8 +8256,8 @@ trees_in::decl_value () if (inner && !NAMESPACE_SCOPE_P (inner) && ((TREE_CODE (inner) == TYPE_DECL - && TYPE_NAME (TREE_TYPE (inner)) == inner - && !is_typedef) + && !is_typedef + && TYPE_NAME (TREE_TYPE (inner)) == inner) || TREE_CODE (inner) == FUNCTION_DECL) && u ()) read_definition (decl); @@ -11088,7 +11087,7 @@ trees_in::binfo_mergeable (tree *type) decls_match because it can cause instantiations of constraints. */ bool -trees_in::is_matching_decl (tree existing, tree decl) +trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef) { // FIXME: We should probably do some duplicate decl-like stuff here // (beware, default parms should be the same?) Can we just call @@ -11099,35 +11098,36 @@ trees_in::is_matching_decl (tree existing, tree decl) // can elide some of the checking gcc_checking_assert (TREE_CODE (existing) == TREE_CODE (decl)); - tree inner = decl; + tree d_inner = decl; + tree e_inner = existing; if (TREE_CODE (decl) == TEMPLATE_DECL) { - inner = DECL_TEMPLATE_RESULT (decl); - gcc_checking_assert (TREE_CODE (DECL_TEMPLATE_RESULT (existing)) - == TREE_CODE (inner)); + d_inner = DECL_TEMPLATE_RESULT (d_inner); + e_inner = DECL_TEMPLATE_RESULT (e_inner); + gcc_checking_assert (TREE_CODE (e_inner) == TREE_CODE (d_inner)); } gcc_checking_assert (!map_context_from); /* This mapping requres the new decl on the lhs and the existing entity on the rhs of the comparitors below. */ - map_context_from = inner; - map_context_to = STRIP_TEMPLATE (existing); + map_context_from = d_inner; + map_context_to = e_inner; - if (TREE_CODE (inner) == FUNCTION_DECL) + if (TREE_CODE (d_inner) == FUNCTION_DECL) { tree e_ret = fndecl_declared_return_type (existing); tree d_ret = fndecl_declared_return_type (decl); - if (decl != inner && DECL_NAME (inner) == fun_identifier - && LAMBDA_TYPE_P (DECL_CONTEXT (inner))) + if (decl != d_inner && DECL_NAME (d_inner) == fun_identifier + && LAMBDA_TYPE_P (DECL_CONTEXT (d_inner))) /* This has a recursive type that will compare different. */; else if (!same_type_p (d_ret, e_ret)) goto mismatch; - tree e_type = TREE_TYPE (existing); - tree d_type = TREE_TYPE (decl); + tree e_type = TREE_TYPE (e_inner); + tree d_type = TREE_TYPE (d_inner); - if (DECL_EXTERN_C_P (decl) != DECL_EXTERN_C_P (existing)) + if (DECL_EXTERN_C_P (d_inner) != DECL_EXTERN_C_P (e_inner)) goto mismatch; for (tree e_args = TYPE_ARG_TYPES (e_type), @@ -11176,6 +11176,13 @@ trees_in::is_matching_decl (tree existing, tree decl) && !comp_except_specs (d_spec, e_spec, ce_type)) goto mismatch; } + else if (is_typedef) + { + if (!DECL_ORIGINAL_TYPE (e_inner) + || !same_type_p (DECL_ORIGINAL_TYPE (d_inner), + DECL_ORIGINAL_TYPE (e_inner))) + goto mismatch; + } /* Using cp_tree_equal because we can meet TYPE_ARGUMENT_PACKs here. I suspect the entities that directly do that are things that shouldn't go to duplicate_decls (FIELD_DECLs etc). */ @@ -11255,12 +11262,10 @@ trees_in::is_matching_decl (tree existing, tree decl) /* Don't instantiate again! */ DECL_TEMPLATE_INSTANTIATED (existing) = true; - tree e_inner = inner == decl ? existing : DECL_TEMPLATE_RESULT (existing); - - if (TREE_CODE (inner) == FUNCTION_DECL - && DECL_DECLARED_INLINE_P (inner)) + if (TREE_CODE (d_inner) == FUNCTION_DECL + && DECL_DECLARED_INLINE_P (d_inner)) DECL_DECLARED_INLINE_P (e_inner) = true; - if (!DECL_EXTERNAL (inner)) + if (!DECL_EXTERNAL (d_inner)) DECL_EXTERNAL (e_inner) = false; // FIXME: Check default tmpl and fn parms here diff --git c/gcc/testsuite/g++.dg/modules/pr98770_a.C w/gcc/testsuite/g++.dg/modules/pr98770_a.C new file mode 100644 index 00000000000..668ff2891ca --- /dev/null +++ w/gcc/testsuite/g++.dg/modules/pr98770_a.C @@ -0,0 +1,10 @@ +// PR 98770 confused about duplicate template type aliases +// { dg-additional-options "-fmodules-ts -Wno-pedantic" } + +module ; +# 6 __FILE__ 1 +template using __void_t = void; +# 8 "" 2 +export module Foo; + +export using B = __void_t; diff --git c/gcc/testsuite/g++.dg/modules/pr98770_b.C w/gcc/testsuite/g++.dg/modules/pr98770_b.C new file mode 100644 index 00000000000..a4ab2376815 --- /dev/null +++ w/gcc/testsuite/g++.dg/modules/pr98770_b.C @@ -0,0 +1,12 @@ +// PR 98770 confused about duplicate template type aliases +// { dg-additional-options "-fmodules-ts -Wno-pedantic" } + +module ; +# 6 __FILE__ 1 +template using __void_t = void; +# 8 "" 2 +export module Bar; + +import Foo; + +export B *b;