On Wed, 8 Jan 2025, Jason Merrill wrote: > On 12/21/24 11:35 AM, Simon Martin wrote: > > When erroring out due to an incomplete type, we add a contextual note > > about the type. However, when the error is suppressed by > > -Wno-template-body, the note remains, making the compiler output quite > > puzzling. > > > > This patch makes sure the note is suppressed if we're processing a > > template declaration body with -Wno-template-body. > > > > Successfully tested on x86_64-pc-linux-gnu. > > > > PR c++/118163 > > > > gcc/cp/ChangeLog: > > > > * cp-tree.h (get_current_template): Declare. > > * error.cc (get_current_template): Make non static. > > * typeck2.cc (cxx_incomplete_type_inform): Suppress note when > > parsing a template declaration with -Wno-template-body. > > I think rather than adding this sort of thing in lots of places where an error > is followed by an inform, we should change error to return bool like other > diagnostic functions, and check its return value before calling > cxx_incomplete_type_inform or plain inform. This likely involves the same > number of changes, but they should be smaller. > > Patrick, what do you think?
That makes sense to me, it's consistent with the 'warning' API and how we handle issuing a warning followed by a note. But since the -Wtemplate-body mechanism is really only useful for compiling legacy code where you don't really care about any diagnostics anyway, and the intended way to use it is -fpermissive / -Wno-error=template-body rather than -Wno-template-body, I'd prefer a less invasive solution that doesn't change the API of 'error' if possible. I wonder if we can work around this by taking advantage of the fact that notes that follow an error are expected to be linked via an active auto_diagnostic_group? Roughly, if we issued a -Wtemplate-body diagnostic from an active auto_diagnostic_group then all other diagnostics from that auto_diagnostic_group should also be associated with -Wtemplate-body, including notes. That way -Wno-template-body will effectively suppress subsequent notes followed by an eligible error, and no 'error' callers need to be changed (unless to use auto_diagnostic_group). Another simpler approach, maybe for templates that have already been deemed erroneous, and -Wno-template-body is active, we could suppress all subsequent diagnostics, including warnings/notes. > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/diagnostic/incomplete-type-2.C: New test. > > * g++.dg/diagnostic/incomplete-type-2a.C: New test. > > > > --- > > gcc/cp/cp-tree.h | 1 + > > gcc/cp/error.cc | 2 +- > > gcc/cp/typeck2.cc | 6 ++++++ > > gcc/testsuite/g++.dg/diagnostic/incomplete-type-2.C | 7 +++++++ > > .../g++.dg/diagnostic/incomplete-type-2a.C | 13 +++++++++++++ > > 5 files changed, 28 insertions(+), 1 deletion(-) > > create mode 100644 gcc/testsuite/g++.dg/diagnostic/incomplete-type-2.C > > create mode 100644 gcc/testsuite/g++.dg/diagnostic/incomplete-type-2a.C > > > > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h > > index 6de8f64b5ee..52f954b63d9 100644 > > --- a/gcc/cp/cp-tree.h > > +++ b/gcc/cp/cp-tree.h > > @@ -7297,6 +7297,7 @@ struct decl_location_traits > > typedef hash_map<tree, location_t, decl_location_traits> > > erroneous_templates_t; > > extern GTY((cache)) erroneous_templates_t *erroneous_templates; > > +extern tree get_current_template (); > > extern bool cp_seen_error (); > > #define seen_error() cp_seen_error () > > diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc > > index 8c0644fba7e..7fd03dd6d12 100644 > > --- a/gcc/cp/error.cc > > +++ b/gcc/cp/error.cc > > @@ -197,7 +197,7 @@ class cxx_format_postprocessor : public > > format_postprocessor > > /* Return the in-scope template that's currently being parsed, or > > NULL_TREE otherwise. */ > > -static tree > > +tree > > get_current_template () > > { > > if (scope_chain && in_template_context && !current_instantiation ()) > > diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc > > index fce687e83b3..505c143dae7 100644 > > --- a/gcc/cp/typeck2.cc > > +++ b/gcc/cp/typeck2.cc > > @@ -273,6 +273,12 @@ cxx_incomplete_type_inform (const_tree type) > > if (!TYPE_MAIN_DECL (type)) > > return; > > + /* When processing a template declaration body, the error generated by > > the > > + caller (if any) might have been suppressed by -Wno-template-body. If > > that > > + is the case, suppress the inform as well. */ > > + if (!warn_template_body && get_current_template ()) > > + return; > > + > > location_t loc = DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)); > > tree ptype = strip_top_quals (CONST_CAST_TREE (type)); > > diff --git a/gcc/testsuite/g++.dg/diagnostic/incomplete-type-2.C > > b/gcc/testsuite/g++.dg/diagnostic/incomplete-type-2.C > > new file mode 100644 > > index 00000000000..e2fb20a4ae8 > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/diagnostic/incomplete-type-2.C > > @@ -0,0 +1,7 @@ > > +// PR c++/118163 > > +// { dg-do "compile" } > > + > > +template<class T> > > +struct S { // { dg-note "until the closing brace" } > > + S s; // { dg-error "has incomplete type" } > > +}; > > diff --git a/gcc/testsuite/g++.dg/diagnostic/incomplete-type-2a.C > > b/gcc/testsuite/g++.dg/diagnostic/incomplete-type-2a.C > > new file mode 100644 > > index 00000000000..d13021d0b68 > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/diagnostic/incomplete-type-2a.C > > @@ -0,0 +1,13 @@ > > +// PR c++/118163 > > +// { dg-do "compile" } > > +// { dg-additional-options "-Wno-template-body" } > > + > > +template<class T> > > +struct S { // { dg-bogus "until the closing brace" } > > + S s; // { dg-bogus "has incomplete type" } > > +}; > > + > > +// Check that we don't suppress errors outside of the body. > > +struct forward_decl; // { dg-note "forward declaration" } > > +template<class T> > > +void foo (forward_decl) {} // { dg-error "has incomplete type" } > >