Hi, On Fri May 9, 2025 at 5:37 PM CEST, Simon Martin wrote: > Several gcc_assert through the C++ front-end involve seen_error (), that > does not take into account errors that were turned into warnings due to > -fpermissive or -Wtemplate-body. > > Running the full C++ testsuite when forcing the use of -fpermissive > leads to ICEs for 6 tests (see list in ticket); one could consider those > as reject-valid cases. > > This patch keeps track of whether we tried to emit an error (whether it > was eventually output as such or not) and uses this in seen_error. > > Successfully tested on x86_64-pc-linux-gnu. Friendly ping.
Thanks! Simon > PR c++/118388 > > gcc/cp/ChangeLog: > > * error.cc (seen_error_raw): New counter to keep track of errors > including those downgraded to warnings. > (cp_seen_error): Take downgraded errors into account. > * typeck2.cc (merge_exception_specifiers): Use seen_error > instead of errorcount. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp0x/lambda/lambda-ice5-fpermissive.C: New test. > * g++.dg/cpp0x/noexcept128-fpermissive.C: New test. > > --- > gcc/cp/error.cc | 54 +++++++++---------- > gcc/cp/typeck2.cc | 2 +- > .../cpp0x/lambda/lambda-ice5-fpermissive.C | 14 +++++ > .../g++.dg/cpp0x/noexcept128-fpermissive.C | 21 ++++++++ > 4 files changed, 63 insertions(+), 28 deletions(-) > create mode 100644 > gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice5-fpermissive.C > create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept128-fpermissive.C > > diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc > index 75bf7dcef62..78ecafb0e02 100644 > --- a/gcc/cp/error.cc > +++ b/gcc/cp/error.cc > @@ -215,6 +215,11 @@ get_current_template () > > erroneous_templates_t *erroneous_templates; > > +/* SEEN_ERROR_RAW will be true if we tried to emit an error message, > regardless > + of whether it was actually output or downgraded to a warning. */ > + > +bool seen_error_raw = false; > + > /* Callback function diagnostic_context::m_adjust_diagnostic_info. > > Errors issued when parsing a template are automatically treated like > @@ -227,40 +232,35 @@ cp_adjust_diagnostic_info (diagnostic_context *context, > diagnostic_info *diagnostic) > { > if (diagnostic->kind == DK_ERROR) > - if (tree tmpl = get_current_template ()) > - { > - diagnostic->option_id = OPT_Wtemplate_body; > - > - if (context->m_permissive) > - diagnostic->kind = DK_WARNING; > - > - bool existed; > - location_t &error_loc > - = hash_map_safe_get_or_insert<true> (erroneous_templates, > - tmpl, &existed); > - if (!existed) > - /* Remember that this template had a parse-time error so > - that we'll ensure a hard error has been issued upon > - its instantiation. */ > - error_loc = diagnostic->richloc->get_loc (); > - } > + { > + seen_error_raw = true; > + if (tree tmpl = get_current_template ()) > + { > + diagnostic->option_id = OPT_Wtemplate_body; > + > + if (context->m_permissive) > + diagnostic->kind = DK_WARNING; > + > + bool existed; > + location_t &error_loc > + = hash_map_safe_get_or_insert<true> (erroneous_templates, > + tmpl, &existed); > + if (!existed) > + /* Remember that this template had a parse-time error so > + that we'll ensure a hard error has been issued upon > + its instantiation. */ > + error_loc = diagnostic->richloc->get_loc (); > + } > + } > } > > /* A generalization of seen_error which also returns true if we've > - permissively downgraded an error to a warning inside a template. */ > + permissively downgraded an error to a warning. */ > > bool > cp_seen_error () > { > - if ((seen_error) ()) > - return true; > - > - if (erroneous_templates) > - if (tree tmpl = get_current_template ()) > - if (erroneous_templates->get (tmpl)) > - return true; > - > - return false; > + return (seen_error) () || seen_error_raw; > } > > /* CONTEXT->printer is a basic pretty printer that was constructed > diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc > index 45edd180173..a2d230461c4 100644 > --- a/gcc/cp/typeck2.cc > +++ b/gcc/cp/typeck2.cc > @@ -2726,7 +2726,7 @@ merge_exception_specifiers (tree list, tree add) > return add; > noex = TREE_PURPOSE (list); > gcc_checking_assert (!TREE_PURPOSE (add) > - || errorcount || !flag_exceptions > + || seen_error () || !flag_exceptions > || cp_tree_equal (noex, TREE_PURPOSE (add))); > > /* Combine the dynamic-exception-specifiers, if any. */ > diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice5-fpermissive.C > b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice5-fpermissive.C > new file mode 100644 > index 00000000000..11300ad23e0 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice5-fpermissive.C > @@ -0,0 +1,14 @@ > +// PR c++/118388 > +// { dg-do compile { target c++11 } } > +// { dg-additional-options "-fpermissive" } > + > +template<int> int foo() > +{ > + [] (void i) { return 0; } (0); // { dg-warning "incomplete|invalid|no > match" } > + return 0; > +} > + > +void bar() > +{ > + foo<0>(); > +} > diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept128-fpermissive.C > b/gcc/testsuite/g++.dg/cpp0x/noexcept128-fpermissive.C > new file mode 100644 > index 00000000000..dfc9629cb06 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept128-fpermissive.C > @@ -0,0 +1,21 @@ > +// PR c++/118388 > +// { dg-do compile { target c++11 } } > +// { dg-additional-options "-fpermissive" } > + > +template<typename T> > +struct traits > +{ > + static constexpr bool foo() { return sizeof(T) > 1; } > + static constexpr bool bar() { return sizeof(T) > 1; } > +}; > + > +template<typename T> > +struct X > +{ > + X& operator=(X&&) noexcept(traits<T>::foo()); > +}; > + > +template<typename T> > + X<T>& > + X<T>::operator=(X&&) noexcept(traits<T>::foo() && traits<T>::bar()) // { > dg-warning "different exception" } > + { return *this; } > -- > 2.44.0