aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2025-03-27 15:03:18 -0400
committerMarek Polacek <polacek@redhat.com>2025-03-31 10:35:12 -0400
commitc7eec82942496520d6b0604aa945a89f279e2562 (patch)
treec271be3897aa104883d5e2ee077bc901a1964ca7 /gcc
parent432f0dd62c3b29efbc0b8a1650c05c370477c0b6 (diff)
downloadgcc-c7eec82942496520d6b0604aa945a89f279e2562.zip
gcc-c7eec82942496520d6b0604aa945a89f279e2562.tar.gz
gcc-c7eec82942496520d6b0604aa945a89f279e2562.tar.bz2
c++: fix reporting routines re-entered [PR119303]
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 later, after checking diagnostic_enabled. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/lambda-uneval26.C: New test. * g++.dg/warn/undefined2.C: New test. Reviewed-by: Jason Merrill <jason@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/diagnostic.cc24
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/lambda-uneval26.C10
-rw-r--r--gcc/testsuite/g++.dg/warn/undefined2.C14
3 files changed, 36 insertions, 12 deletions
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 82d7f94..07c76b6 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
@@ -1437,6 +1425,18 @@ diagnostic_context::report_diagnostic (diagnostic_info *diagnostic)
if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
check_max_errors (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 ();
+ }
+
m_lock++;
if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
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 0000000..3e3097b
--- /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 0000000..1b2ec35
--- /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); }