Message ID | 20230328173732.1722425-1-ppalka@redhat.com |
---|---|
State | New |
Headers |
Return-Path: <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> 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 5A3F4385842E for <patchwork@sourceware.org>; Tue, 28 Mar 2023 17:38:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5A3F4385842E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1680025086; bh=4d5nxm2clb8m3T1st9WnrWRHm0325f2ZqWh3d2zr/4A=; h=To:Cc:Subject:Date:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=CMs3DcUFcU6roBXzX2UH8Qfig77qAJNaznpRs/qjeq8kuFaOTVvGtu1iPpzMiiS4e eTL1VJLZEoy02Nn2AXsChJg5KwdLBseYs/TjlvPObLn72E4vdBF/49ovykOANpjMjk 3VbYDFclEL/cHKHEQm+KY2EKZK4AiEUWFRWr1Gww= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 373073858D39 for <gcc-patches@gcc.gnu.org>; Tue, 28 Mar 2023 17:37:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 373073858D39 Received: from mail-qv1-f72.google.com (mail-qv1-f72.google.com [209.85.219.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-600-I2QHP1JYPqOiOGeiRSE-Kw-1; Tue, 28 Mar 2023 13:37:35 -0400 X-MC-Unique: I2QHP1JYPqOiOGeiRSE-Kw-1 Received: by mail-qv1-f72.google.com with SMTP id v8-20020a0ccd88000000b005c1927d1609so5385084qvm.12 for <gcc-patches@gcc.gnu.org>; Tue, 28 Mar 2023 10:37:35 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680025055; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=4d5nxm2clb8m3T1st9WnrWRHm0325f2ZqWh3d2zr/4A=; b=6+7hBPdRK3zQkWtzyJVo9KnquapBYm4wAKQQMQQYTY1N9JH6RSrmUzO2OGBY9VrfTg gf/ZGLAPna7HDpGzUplb8c1hLeIVtjuf6hZApCBU6Unun5Uf+TRzTpD6Al6Ap4R3yZjc /9+R65QkjYSWMOCTudDx/VeKHoMbw3+YBdvzKk5neHYq9iMbdhQOdf0+/DD8Z2ijOMz/ DigjgCCn3fwiXIN3ve8qWRKXVXqz7jqE4fffAJR1hlf+1aWDjDaSaOste3lcJmGK4Xp+ ZIjjiz28amfhnyTzNowiro690Jm8Hqn87uto1kGrfNzCSmpQDg7U9iwkYflkoWKSwwlP jFWQ== X-Gm-Message-State: AAQBX9ckkNnrwwWwC+k2wEN+ML/Kjfr8VoOscY07jn1Qz86puoQEogIT +o6wz0fxx5LpiG3vPnjx0hXGucUUiJlOqXNyKww7E3IlkuxGB2frZUBYbv3jpcFcPflBmYyJ5cd bP+VAcJunu1RDcSfBiVY6nrDYG12JpntUomsjQZbj5+KhNvRP642/vj2BED92xnJtdNPY+VEFQ/ w= X-Received: by 2002:ac8:5c14:0:b0:3e4:d887:3e83 with SMTP id i20-20020ac85c14000000b003e4d8873e83mr25357368qti.12.1680025054872; Tue, 28 Mar 2023 10:37:34 -0700 (PDT) X-Google-Smtp-Source: AKy350aycjsg0B0DkBN1E0Y9D3LOYzyPDevbLp6FEvCvGj2Jzd+O2OAFpB+bamRlVv0yVun9RGasQQ== X-Received: by 2002:ac8:5c14:0:b0:3e4:d887:3e83 with SMTP id i20-20020ac85c14000000b003e4d8873e83mr25357339qti.12.1680025054594; Tue, 28 Mar 2023 10:37:34 -0700 (PDT) Received: from localhost.localdomain (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id v6-20020ac87486000000b003bffe7fdc38sm11903667qtq.9.2023.03.28.10.37.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Mar 2023 10:37:34 -0700 (PDT) To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com, Patrick Palka <ppalka@redhat.com> Subject: [PATCH] c++: ICE on loopy var tmpl auto deduction [PR109300] Date: Tue, 28 Mar 2023 13:37:32 -0400 Message-Id: <20230328173732.1722425-1-ppalka@redhat.com> X-Mailer: git-send-email 2.40.0.130.g27d43aaaf5 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-13.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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 <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> From: Patrick Palka via Gcc-patches <gcc-patches@gcc.gnu.org> Reply-To: Patrick Palka <ppalka@redhat.com> Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> |
Series |
c++: ICE on loopy var tmpl auto deduction [PR109300]
|
|
Commit Message
Patrick Palka
March 28, 2023, 5:37 p.m. UTC
Now that we resolve non-dependent variable template-ids ahead of time, cp_finish_decl needs to handle a new invalid situation: we can end up trying to instantiate a variable template with deduced return type before we fully parsed (and attached) its initializer. Bootstrapped and regtested on x86_64-pc-linux-gnu, does this OK for trunK? PR c++/109300 gcc/cp/ChangeLog: * decl.cc (cp_finish_decl): Diagnose ordinary auto deduction with no initializer instead of asserting. gcc/testsuite/ChangeLog: * g++.dg/cpp1y/var-templ79.C: New test. --- gcc/cp/decl.cc | 15 ++++++++++++++- gcc/testsuite/g++.dg/cpp1y/var-templ79.C | 5 +++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ79.C
Comments
On 3/28/23 13:37, Patrick Palka wrote: > Now that we resolve non-dependent variable template-ids ahead of time, > cp_finish_decl needs to handle a new invalid situation: we can end up > trying to instantiate a variable template with deduced return type > before we fully parsed (and attached) its initializer. > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this OK for > trunK? > > PR c++/109300 > > gcc/cp/ChangeLog: > > * decl.cc (cp_finish_decl): Diagnose ordinary auto deduction > with no initializer instead of asserting. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp1y/var-templ79.C: New test. > --- > gcc/cp/decl.cc | 15 ++++++++++++++- > gcc/testsuite/g++.dg/cpp1y/var-templ79.C | 5 +++++ > 2 files changed, 19 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ79.C > > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc > index 20b980f68c8..2c91693b99d 100644 > --- a/gcc/cp/decl.cc > +++ b/gcc/cp/decl.cc > @@ -8276,7 +8276,20 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, > return; > } > > - gcc_assert (CLASS_PLACEHOLDER_TEMPLATE (auto_node)); > + if (CLASS_PLACEHOLDER_TEMPLATE (auto_node)) > + /* Class deduction with no initializer is OK. */; > + else > + { > + /* Ordinary auto deduction without an initializer, a situation > + which grokdeclarator already catches and rejects for the most > + part. But we can still get here if we're instantiating a > + variable template before we've fully parsed (and attached) its > + initializer, e.g. template<class> auto x = x<int>; */ In the case of recursively dependent instantiation I'd hope to have an error_mark_node initializer, rather than none? > + error_at (DECL_SOURCE_LOCATION (decl), > + "declaration of %q#D has no initializer", decl); > + TREE_TYPE (decl) = error_mark_node; > + return; > + } > } > d_init = init; > if (d_init) > diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ79.C b/gcc/testsuite/g++.dg/cpp1y/var-templ79.C > new file mode 100644 > index 00000000000..3c0d276153a > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ79.C > @@ -0,0 +1,5 @@ > +// PR c++/109300 > +// { dg-do compile { target c++14 } } > + > +template<class> > +auto x = x<int>; // { dg-error "" }
On Wed, 29 Mar 2023, Jason Merrill wrote: > On 3/28/23 13:37, Patrick Palka wrote: > > Now that we resolve non-dependent variable template-ids ahead of time, > > cp_finish_decl needs to handle a new invalid situation: we can end up > > trying to instantiate a variable template with deduced return type > > before we fully parsed (and attached) its initializer. > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this OK for > > trunK? > > > > PR c++/109300 > > > > gcc/cp/ChangeLog: > > > > * decl.cc (cp_finish_decl): Diagnose ordinary auto deduction > > with no initializer instead of asserting. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/cpp1y/var-templ79.C: New test. > > --- > > gcc/cp/decl.cc | 15 ++++++++++++++- > > gcc/testsuite/g++.dg/cpp1y/var-templ79.C | 5 +++++ > > 2 files changed, 19 insertions(+), 1 deletion(-) > > create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ79.C > > > > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc > > index 20b980f68c8..2c91693b99d 100644 > > --- a/gcc/cp/decl.cc > > +++ b/gcc/cp/decl.cc > > @@ -8276,7 +8276,20 @@ cp_finish_decl (tree decl, tree init, bool > > init_const_expr_p, > > return; > > } > > - gcc_assert (CLASS_PLACEHOLDER_TEMPLATE (auto_node)); > > + if (CLASS_PLACEHOLDER_TEMPLATE (auto_node)) > > + /* Class deduction with no initializer is OK. */; > > + else > > + { > > + /* Ordinary auto deduction without an initializer, a situation > > + which grokdeclarator already catches and rejects for the most > > + part. But we can still get here if we're instantiating a > > + variable template before we've fully parsed (and attached) > > its > > + initializer, e.g. template<class> auto x = x<int>; */ > > In the case of recursively dependent instantiation I'd hope to have an > error_mark_node initializer, rather than none? Do you mean setting the initializer to error_mark_node after the fact, e.g. @@ -8288,7 +8297,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, error_at (DECL_SOURCE_LOCATION (decl), "declaration of %q#D has no initializer", decl); TREE_TYPE (decl) = error_mark_node; - return; + init = error_mark_node; } } d_init = init; or before the fact, i.e. setting DECL_INITIAL to error_mark_node as a sentinel value for detecting recursion before we begin parsing a variable initializer? The former should work I suppose, but the latter is problematic because we also call cp_finish_decl with init=error_mark_node when the initializer is generally invalid, so by overloading the meaning of error_mark_node here and checking for it from cp_finish_decl we would end up emitting a bogus extra diagnostic in a bunch of cases e.g. g++.dg/pr53055.C: int i = p ->* p ; // invalid initializer I guess we would need to use a different sentinel value for detecting recursion, or expose and inspect the 'lambda_scope' stack which already keeps track of whether we're in the middle of a variable initializer... Dunno if it's worth it just for sake of a better diagnostic for this corner case, I notice e.g. Clang doesn't give a great diagnostic either: src/gcc/testsuite/g++.dg/cpp1y/var-templ79.C:5:6: error: declaration of variable 'x' with deduced type 'auto' requires an initializer auto x = x<int>; // { dg-error "" } ^ > > > + error_at (DECL_SOURCE_LOCATION (decl), > > + "declaration of %q#D has no initializer", decl); > > + TREE_TYPE (decl) = error_mark_node; > > + return; > > + } > > } > > d_init = init; > > if (d_init) > > diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ79.C > > b/gcc/testsuite/g++.dg/cpp1y/var-templ79.C > > new file mode 100644 > > index 00000000000..3c0d276153a > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ79.C > > @@ -0,0 +1,5 @@ > > +// PR c++/109300 > > +// { dg-do compile { target c++14 } } > > + > > +template<class> > > +auto x = x<int>; // { dg-error "" } > >
On 4/3/23 12:28, Patrick Palka wrote: > On Wed, 29 Mar 2023, Jason Merrill wrote: > >> On 3/28/23 13:37, Patrick Palka wrote: >>> Now that we resolve non-dependent variable template-ids ahead of time, >>> cp_finish_decl needs to handle a new invalid situation: we can end up >>> trying to instantiate a variable template with deduced return type >>> before we fully parsed (and attached) its initializer. >>> >>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this OK for >>> trunK? >>> >>> PR c++/109300 >>> >>> gcc/cp/ChangeLog: >>> >>> * decl.cc (cp_finish_decl): Diagnose ordinary auto deduction >>> with no initializer instead of asserting. >>> >>> gcc/testsuite/ChangeLog: >>> >>> * g++.dg/cpp1y/var-templ79.C: New test. >>> --- >>> gcc/cp/decl.cc | 15 ++++++++++++++- >>> gcc/testsuite/g++.dg/cpp1y/var-templ79.C | 5 +++++ >>> 2 files changed, 19 insertions(+), 1 deletion(-) >>> create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ79.C >>> >>> diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc >>> index 20b980f68c8..2c91693b99d 100644 >>> --- a/gcc/cp/decl.cc >>> +++ b/gcc/cp/decl.cc >>> @@ -8276,7 +8276,20 @@ cp_finish_decl (tree decl, tree init, bool >>> init_const_expr_p, >>> return; >>> } >>> - gcc_assert (CLASS_PLACEHOLDER_TEMPLATE (auto_node)); >>> + if (CLASS_PLACEHOLDER_TEMPLATE (auto_node)) >>> + /* Class deduction with no initializer is OK. */; >>> + else >>> + { >>> + /* Ordinary auto deduction without an initializer, a situation >>> + which grokdeclarator already catches and rejects for the most >>> + part. But we can still get here if we're instantiating a >>> + variable template before we've fully parsed (and attached) >>> its >>> + initializer, e.g. template<class> auto x = x<int>; */ >> >> In the case of recursively dependent instantiation I'd hope to have an >> error_mark_node initializer, rather than none? > > Do you mean setting the initializer to error_mark_node after the fact, e.g. > > @@ -8288,7 +8297,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, > error_at (DECL_SOURCE_LOCATION (decl), > "declaration of %q#D has no initializer", decl); > TREE_TYPE (decl) = error_mark_node; > - return; > + init = error_mark_node; > } > } > d_init = init; > > or before the fact, i.e. setting DECL_INITIAL to error_mark_node as a > sentinel value for detecting recursion before we begin parsing a variable > initializer? The former should work I suppose, but the latter is > problematic because we also call cp_finish_decl with init=error_mark_node > when the initializer is generally invalid, so by overloading the meaning > of error_mark_node here and checking for it from cp_finish_decl we would > end up emitting a bogus extra diagnostic in a bunch of cases e.g. > g++.dg/pr53055.C: > > int i = p ->* p ; // invalid initializer > > I guess we would need to use a different sentinel value for detecting > recursion, or expose and inspect the 'lambda_scope' stack which already > keeps track of whether we're in the middle of a variable initializer... > Dunno if it's worth it just for sake of a better diagnostic for this > corner case, I notice e.g. Clang doesn't give a great diagnostic either: > > src/gcc/testsuite/g++.dg/cpp1y/var-templ79.C:5:6: error: declaration of variable 'x' with deduced type 'auto' requires an initializer > auto x = x<int>; // { dg-error "" } > ^ Yeah, let's just go with your patch, thanks. >> >>> + error_at (DECL_SOURCE_LOCATION (decl), >>> + "declaration of %q#D has no initializer", decl); >>> + TREE_TYPE (decl) = error_mark_node; >>> + return; >>> + } >>> } >>> d_init = init; >>> if (d_init) >>> diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ79.C >>> b/gcc/testsuite/g++.dg/cpp1y/var-templ79.C >>> new file mode 100644 >>> index 00000000000..3c0d276153a >>> --- /dev/null >>> +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ79.C >>> @@ -0,0 +1,5 @@ >>> +// PR c++/109300 >>> +// { dg-do compile { target c++14 } } >>> + >>> +template<class> >>> +auto x = x<int>; // { dg-error "" } >> >> >
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 20b980f68c8..2c91693b99d 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -8276,7 +8276,20 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, return; } - gcc_assert (CLASS_PLACEHOLDER_TEMPLATE (auto_node)); + if (CLASS_PLACEHOLDER_TEMPLATE (auto_node)) + /* Class deduction with no initializer is OK. */; + else + { + /* Ordinary auto deduction without an initializer, a situation + which grokdeclarator already catches and rejects for the most + part. But we can still get here if we're instantiating a + variable template before we've fully parsed (and attached) its + initializer, e.g. template<class> auto x = x<int>; */ + error_at (DECL_SOURCE_LOCATION (decl), + "declaration of %q#D has no initializer", decl); + TREE_TYPE (decl) = error_mark_node; + return; + } } d_init = init; if (d_init) diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ79.C b/gcc/testsuite/g++.dg/cpp1y/var-templ79.C new file mode 100644 index 00000000000..3c0d276153a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ79.C @@ -0,0 +1,5 @@ +// PR c++/109300 +// { dg-do compile { target c++14 } } + +template<class> +auto x = x<int>; // { dg-error "" }