On 1/9/25 12:05 PM, Patrick Palka wrote:
On Wed, 8 Jan 2025, Jason Merrill wrote:

On 12/21/24 11:35 AM, Simon Martin wrote:
When erroring out due to an incomplete type, we add a contextual note
about the type. However, when the error is suppressed by
-Wno-template-body, the note remains, making the compiler output quite
puzzling.

This patch makes sure the note is suppressed if we're processing a
template declaration body with -Wno-template-body.

Successfully tested on x86_64-pc-linux-gnu.

        PR c++/118163

gcc/cp/ChangeLog:

        * cp-tree.h (get_current_template): Declare.
        * error.cc (get_current_template): Make non static.
        * typeck2.cc (cxx_incomplete_type_inform): Suppress note when
        parsing a template declaration with -Wno-template-body.

I think rather than adding this sort of thing in lots of places where an error
is followed by an inform, we should change error to return bool like other
diagnostic functions, and check its return value before calling
cxx_incomplete_type_inform or plain inform.  This likely involves the same
number of changes, but they should be smaller.

Patrick, what do you think?

That makes sense to me, it's consistent with the 'warning' API and how
we handle issuing a warning followed by a note.  But since the
-Wtemplate-body mechanism is really only useful for compiling legacy
code where you don't really care about any diagnostics anyway, and
the intended way to use it is -fpermissive / -Wno-error=template-body
rather than -Wno-template-body, I'd prefer a less invasive solution that
doesn't change the API of 'error' if possible.

I wonder if we can work around this by taking advantage of the fact that
notes that follow an error are expected to be linked via an active
auto_diagnostic_group?  Roughly, if we issued a -Wtemplate-body
diagnostic from an active auto_diagnostic_group then all other
diagnostics from that auto_diagnostic_group should also be associated
with -Wtemplate-body, including notes.  That way -Wno-template-body will
effectively suppress subsequent notes followed by an eligible error, and
no 'error' callers need to be changed (unless to use
auto_diagnostic_group).

I like the idea that if the first diagnostic in an auto_diagnostic_group is suppressed, the others are as well.

Another simpler approach, maybe for templates that have already been
deemed erroneous, and -Wno-template-body is active, we could suppress
all subsequent diagnostics, including warnings/notes.

That would also make sense. Relatedly, see the handling of current_tinst_level->errors and setting CLASSTYPE_ERRONEOUS.

gcc/testsuite/ChangeLog:

        * g++.dg/diagnostic/incomplete-type-2.C: New test.
        * g++.dg/diagnostic/incomplete-type-2a.C: New test.

---
   gcc/cp/cp-tree.h                                    |  1 +
   gcc/cp/error.cc                                     |  2 +-
   gcc/cp/typeck2.cc                                   |  6 ++++++
   gcc/testsuite/g++.dg/diagnostic/incomplete-type-2.C |  7 +++++++
   .../g++.dg/diagnostic/incomplete-type-2a.C          | 13 +++++++++++++
   5 files changed, 28 insertions(+), 1 deletion(-)
   create mode 100644 gcc/testsuite/g++.dg/diagnostic/incomplete-type-2.C
   create mode 100644 gcc/testsuite/g++.dg/diagnostic/incomplete-type-2a.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 6de8f64b5ee..52f954b63d9 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7297,6 +7297,7 @@ struct decl_location_traits
   typedef hash_map<tree, location_t, decl_location_traits>
erroneous_templates_t;
   extern GTY((cache)) erroneous_templates_t *erroneous_templates;
   +extern tree get_current_template ();
   extern bool cp_seen_error ();
   #define seen_error() cp_seen_error ()
   diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 8c0644fba7e..7fd03dd6d12 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -197,7 +197,7 @@ class cxx_format_postprocessor : public
format_postprocessor
   /* Return the in-scope template that's currently being parsed, or
      NULL_TREE otherwise.  */
   -static tree
+tree
   get_current_template ()
   {
     if (scope_chain && in_template_context && !current_instantiation ())
diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index fce687e83b3..505c143dae7 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -273,6 +273,12 @@ cxx_incomplete_type_inform (const_tree type)
     if (!TYPE_MAIN_DECL (type))
       return;
   +  /* When processing a template declaration body, the error generated by
the
+     caller (if any) might have been suppressed by -Wno-template-body. If
that
+     is the case, suppress the inform as well.  */
+  if (!warn_template_body && get_current_template ())
+    return;
+
     location_t loc = DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type));
     tree ptype = strip_top_quals (CONST_CAST_TREE (type));
   diff --git a/gcc/testsuite/g++.dg/diagnostic/incomplete-type-2.C
b/gcc/testsuite/g++.dg/diagnostic/incomplete-type-2.C
new file mode 100644
index 00000000000..e2fb20a4ae8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/incomplete-type-2.C
@@ -0,0 +1,7 @@
+// PR c++/118163
+// { dg-do "compile" }
+
+template<class T>
+struct S {  // { dg-note "until the closing brace" }
+  S s;     // { dg-error "has incomplete type" }
+};
diff --git a/gcc/testsuite/g++.dg/diagnostic/incomplete-type-2a.C
b/gcc/testsuite/g++.dg/diagnostic/incomplete-type-2a.C
new file mode 100644
index 00000000000..d13021d0b68
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/incomplete-type-2a.C
@@ -0,0 +1,13 @@
+// PR c++/118163
+// { dg-do "compile" }
+// { dg-additional-options "-Wno-template-body" }
+
+template<class T>
+struct S {  // { dg-bogus "until the closing brace" }
+  S s;     // { dg-bogus "has incomplete type" }
+};
+
+// Check that we don't suppress errors outside of the body.
+struct forward_decl;       // { dg-note "forward declaration" }
+template<class T>
+void foo (forward_decl) {}  // { dg-error "has incomplete type" }




Reply via email to