* [PATCH] c++: ICE on loopy var tmpl auto deduction [PR109300] @ 2023-03-28 17:37 Patrick Palka 2023-03-29 18:17 ` Jason Merrill 0 siblings, 1 reply; 4+ messages in thread From: Patrick Palka @ 2023-03-28 17:37 UTC (permalink / raw) To: gcc-patches; +Cc: jason, Patrick Palka 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>; */ + 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 "" } -- 2.40.0.130.g27d43aaaf5 ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] c++: ICE on loopy var tmpl auto deduction [PR109300] 2023-03-28 17:37 [PATCH] c++: ICE on loopy var tmpl auto deduction [PR109300] Patrick Palka @ 2023-03-29 18:17 ` Jason Merrill 2023-04-03 16:28 ` Patrick Palka 0 siblings, 1 reply; 4+ messages in thread From: Jason Merrill @ 2023-03-29 18:17 UTC (permalink / raw) To: Patrick Palka, gcc-patches 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 "" } ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] c++: ICE on loopy var tmpl auto deduction [PR109300] 2023-03-29 18:17 ` Jason Merrill @ 2023-04-03 16:28 ` Patrick Palka 2023-04-03 20:19 ` Jason Merrill 0 siblings, 1 reply; 4+ messages in thread From: Patrick Palka @ 2023-04-03 16:28 UTC (permalink / raw) To: Jason Merrill; +Cc: Patrick Palka, gcc-patches 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 "" } > > ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] c++: ICE on loopy var tmpl auto deduction [PR109300] 2023-04-03 16:28 ` Patrick Palka @ 2023-04-03 20:19 ` Jason Merrill 0 siblings, 0 replies; 4+ messages in thread From: Jason Merrill @ 2023-04-03 20:19 UTC (permalink / raw) To: Patrick Palka; +Cc: gcc-patches 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 "" } >> >> > ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-04-03 20:19 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2023-03-28 17:37 [PATCH] c++: ICE on loopy var tmpl auto deduction [PR109300] Patrick Palka 2023-03-29 18:17 ` Jason Merrill 2023-04-03 16:28 ` Patrick Palka 2023-04-03 20:19 ` Jason Merrill
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).