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


Reply via email to