On 3/27/25 5:00 PM, Marek Polacek wrote:
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 ();
+ }
Let's move this a little farther down, past...
if ((was_warning || diagnostic->kind == DK_WARNING)
&& ((!m_warn_system_headers
&& diagnostic->m_iinfo.m_allsyslocs)
...this early exit, as well.
The m_lock check used to be right before the increment, until DJ's
r109907 that added #pragma GCC diagnostic; it would make sense to me for
them to be together again. I don't suppose it matters whether the
check_max_errors is before or after the m_lock handling.
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