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. 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