On Wed, Mar 19, 2025 at 12:00:00PM -0400, Jason Merrill wrote: > On 3/17/25 6:55 PM, Marek Polacek wrote: > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > > > -- >8 -- > > We crash while we call warning_at ("inline function used but never defined") > > since it invokes dump_template_bindings -> tsubst -> ... -> convert_like -> > > ... -> c_common_truthvalue_conversion -> warning_at ("enum constant in > > boolean > > context") > > > > cp_truthvalue_conversion correctly gets complain=0 but it calls > > c_common_truthvalue_conversion from c-family which doesn't have > > a similar parameter. > > It seems that we try to prevent this in cp_convert_and_check with > > warning_sentinel c (warn_int_in_bool_context); > > which is why we don't get a warning when we first instantiate the template. > > But that doesn't help when we rebuild the expression for > dump_template_bindings because the recursion check in report_diagnostic > comes before the check whether the diagnostic is actually enabled. > > I think rather than adding another mechanism for suppressing warnings, I'd > like to make the existing ones work better by moving the recursion check > after the checks for disabled diagnostics.
Fair enough. That happens to fix c++/116960 et al too. Note that my adding a complain parameter into c-family isn't entirely novel: c_sizeof_or_alignof_type also has one. Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- We crash while we call warning_at ("inline function used but never defined") since it invokes dump_template_bindings -> tsubst -> ... -> convert_like -> ... -> c_common_truthvalue_conversion -> warning_at ("enum constant in boolean context") cp_truthvalue_conversion correctly gets complain=0 but it calls c_common_truthvalue_conversion from c-family which doesn't have a similar parameter. We can fix this by tweaking diagnostic_context::report_diagnostic to check for recursion after checking if the diagnostic was enabled. PR c++/116960 PR c++/119303 gcc/ChangeLog: * diagnostic.cc (diagnostic_context::report_diagnostic): Check for non-zero m_lock only after diagnostic_enabled. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/lambda-uneval26.C: New test. * g++.dg/warn/undefined2.C: New test. --- gcc/diagnostic.cc | 24 ++++++++++---------- gcc/testsuite/g++.dg/cpp2a/lambda-uneval26.C | 10 ++++++++ gcc/testsuite/g++.dg/warn/undefined2.C | 14 ++++++++++++ 3 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-uneval26.C create mode 100644 gcc/testsuite/g++.dg/warn/undefined2.C diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc index 82d7f946818..425477ea5b2 100644 --- a/gcc/diagnostic.cc +++ b/gcc/diagnostic.cc @@ -1398,18 +1398,6 @@ diagnostic_context::report_diagnostic (diagnostic_info *diagnostic) if (diagnostic->kind == DK_NOTE && m_inhibit_notes_p) return false; - if (m_lock > 0) - { - /* If we're reporting an ICE in the middle of some other error, - try to flush out the previous error, then let this one - through. Don't do this more than once. */ - if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT) - && m_lock == 1) - pp_newline_and_flush (m_reference_printer); - else - error_recursion (); - } - /* If the user requested that warnings be treated as errors, so be it. Note that we do this before the next block so that individual warnings can be overridden back to warnings with @@ -1426,6 +1414,18 @@ diagnostic_context::report_diagnostic (diagnostic_info *diagnostic) if (!diagnostic_enabled (diagnostic)) return false; + if (m_lock > 0) + { + /* If we're reporting an ICE in the middle of some other error, + try to flush out the previous error, then let this one + through. Don't do this more than once. */ + if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT) + && m_lock == 1) + pp_newline_and_flush (m_reference_printer); + else + error_recursion (); + } + if ((was_warning || diagnostic->kind == DK_WARNING) && ((!m_warn_system_headers && diagnostic->m_iinfo.m_allsyslocs) diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval26.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval26.C new file mode 100644 index 00000000000..3e3097bedcb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval26.C @@ -0,0 +1,10 @@ +// PR c++/116960 +// { dg-do compile { target c++20 } } + +template<auto> +using Foo = decltype([](auto) { return 0; }(0)); + +template<typename...> +Foo<[] {}> foo() {} // { dg-warning "no return statement" } + +auto t = foo(); diff --git a/gcc/testsuite/g++.dg/warn/undefined2.C b/gcc/testsuite/g++.dg/warn/undefined2.C new file mode 100644 index 00000000000..1b2ec353adb --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/undefined2.C @@ -0,0 +1,14 @@ +// PR c++/119303 + +template <class> struct c { + enum { d = 4 }; +}; +template <bool> struct e { + typedef void g; +}; +template <class _Tp> +inline typename e<!c<_Tp>::d>::g bar(_Tp); // { dg-warning "used but never defined" } + +int x; + +void foo() { bar(x); } base-commit: 2af32814cf2ba3c632fd5a3f69f275613383723d -- 2.49.0