On 5/29/25 2:57 PM, David Malcolm wrote:
On Thu, 2025-05-29 at 09:11 -0400, Jason Merrill wrote:
On 5/27/25 5:12 PM, Jason Merrill wrote:
On 5/27/25 4:47 PM, Jason Merrill wrote:
On 5/27/25 1:33 PM, David Malcolm wrote:
On Fri, 2025-05-23 at 16:58 -0400, Jason Merrill wrote:
On 4/14/25 9:57 AM, Jason Merrill wrote:
On 1/9/25 10:00 PM, Jason Merrill wrote:
Tested x86_64-pc-linux-gnu. Is the diagnostic.h change
OK for
trunk?
To respect the #pragma diagnostic lines in libstdc++
headers when
compiling
with module std, we need to represent them in the module.
I think it's reasonable to make module_state a friend of
diagnostic_option_classifier to allow direct access to
the data.
This
is a
different approach from how Jakub made PCH streaming
members of
diagnostic_option_classifier, but it seems to me that
modules
handling
belongs in module.cc.
Putting it in module.cc looks good to me, though perhaps it
should be
just a friend of diagnostic_option_classifier but not of
diagnostic_context? Could the functions take a
diagnostic_option_classifier rather than a diagnostic_context?
diagnostic_context is something of a "big blob" of a class.
The friend in diagnostic_context is to be able to name
m_option_classifier. We could instead make that member public?
Thoughts? The functions could take the _classifier, or even just the
m_classification_history, but that just moves the access problem into
their callers, who would still need some way to get there from the
diagnostic_context. Do you have another idea for that?
I'm trying to eventually make all of the member data of
diagnostic_context private, so how about keeping it private, but adding
a public accessor, something like:
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index cdd6f26ba2a..cda090d55ff 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -830,6 +830,12 @@ public:
m_abort_on_error = val;
}
+ diagnostic_option_classifier &
+ get_option_classifier ()
+ {
+ return m_option_classifier;
+ }
+
private:
void error_recursion () ATTRIBUTE_NORETURN;
OK, how about this?
From f57505c7c6fa05a14e285c14a81021655a43ccbc Mon Sep 17 00:00:00 2001
From: Jason Merrill <ja...@redhat.com>
Date: Wed, 20 Nov 2024 16:20:52 +0100
Subject: [PATCH] c++: modules and #pragma diagnostic
To: gcc-patches@gcc.gnu.org
To respect the #pragma diagnostic lines in libstdc++ headers when compiling
with module std, we need to represent them in the module.
I think it's reasonable to give serializers direct access to the underlying
data, as here with get_classification_history. This is a different approach
from how Jakub made PCH streaming members of diagnostic_option_classifier,
but it seems to me that modules handling belongs in module.cc.
gcc/ChangeLog:
* diagnostic.h (diagnostic_option_classifier): Friend
diagnostic_context.
(diagnostic_context::get_classification_history): New.
gcc/cp/ChangeLog:
* module.cc (module_state::write_diagnostic_classification): New.
(module_state::write_begin): Call it.
(module_state::read_diagnostic_classification): New.
(module_state::read_initial): Call it.
gcc/testsuite/ChangeLog:
* g++.dg/modules/warn-spec-3_a.C: New test.
* g++.dg/modules/warn-spec-3_b.C: New test.
---
gcc/diagnostic.h | 10 +++
gcc/cp/module.cc | 86 +++++++++++++++++++-
gcc/testsuite/g++.dg/modules/warn-spec-3_a.C | 20 +++++
gcc/testsuite/g++.dg/modules/warn-spec-3_b.C | 8 ++
4 files changed, 123 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/modules/warn-spec-3_a.C
create mode 100644 gcc/testsuite/g++.dg/modules/warn-spec-3_b.C
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index cdd6f26ba2a..b6cab0d52ed 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -307,6 +307,9 @@ private:
diagnostic. */
vec<diagnostic_classification_change_t> m_classification_history;
+ /* For diagnostic_context::get_classification_history, declared later. */
+ friend class diagnostic_context;
+
/* For pragma push/pop. */
vec<int> m_push_list;
};
@@ -830,6 +833,13 @@ public:
m_abort_on_error = val;
}
+ /* Accessor for use in serialization, e.g. by C++ modules. */
+ auto &
+ get_classification_history ()
+ {
+ return m_option_classifier.m_classification_history;
+ }
+
private:
void error_recursion () ATTRIBUTE_NORETURN;
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 2fa92b514d6..3f88baa7544 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -3879,6 +3879,9 @@ class GTY((chain_next ("%h.parent"), for_user)) module_state {
void write_macro_maps (elf_out *to, range_t &, unsigned *crc_ptr);
bool read_macro_maps (line_map_uint_t);
+ void write_diagnostic_classification (elf_out *, diagnostic_context *, unsigned *);
+ bool read_diagnostic_classification (diagnostic_context *);
+
private:
void write_define (bytes_out &, const cpp_macro *);
cpp_macro *read_define (bytes_in &, cpp_reader *) const;
@@ -18181,6 +18184,78 @@ module_state::write_ordinary_maps (elf_out *to, range_t &info,
dump.outdent ();
}
+/* Write out any #pragma GCC diagnostic info to the .dgc section. */
+
+void
+module_state::write_diagnostic_classification (elf_out *to,
+ diagnostic_context *dc,
+ unsigned *crc_p)
+{
+ auto &changes = dc->get_classification_history ();
+
+ dump () && dump ("Writing diagnostic change locations");
+ dump.indent ();
+
+ bytes_out sec (to);
+ if (sec.streaming_p ())
+ sec.begin ();
+
+ unsigned len = changes.length ();
+ dump () && dump ("Diagnostic changes: %u", len);
+ if (sec.streaming_p ())
+ sec.u (len);
+
+ for (const auto &c: changes)
+ {
+ write_location (sec, c.location);
+ if (sec.streaming_p ())
+ {
+ sec.u (c.option);
+ sec.u (c.kind);
+ }
+ }
+
+ if (sec.streaming_p ())
+ sec.end (to, to->name (MOD_SNAME_PFX ".dgc"), crc_p);
+ dump.outdent ();
+}
+
+/* Read any #pragma GCC diagnostic info from the .dgc section. */
+
+bool
+module_state::read_diagnostic_classification (diagnostic_context *dc)
+{
+ bytes_in sec;
+
+ if (!sec.begin (loc, from (), MOD_SNAME_PFX ".dgc"))
+ return false;
+
+ dump () && dump ("Reading diagnostic change locations");
+ dump.indent ();
+
+ unsigned len = sec.u ();
+ dump () && dump ("Diagnostic changes: %u", len);
+
+ auto &changes = dc->get_classification_history ();
+ unsigned offset = changes.length ();
+ changes.reserve (len);
+ for (unsigned i = 0; i < len; ++i)
+ {
+ location_t loc = read_location (sec);
+ int opt = sec.u ();
+ diagnostic_t kind = (diagnostic_t) sec.u ();
+ if (kind == DK_POP)
+ opt += offset;
+ changes.quick_push ({ loc, opt, kind });
+ }
+
+ dump.outdent ();
+ if (!sec.end (from ()))
+ return false;
+
+ return true;
+}
+
void
module_state::write_macro_maps (elf_out *to, range_t &info, unsigned *crc_p)
{
@@ -19871,6 +19946,8 @@ module_state::write_begin (elf_out *to, cpp_reader *reader,
if (is_header ())
macros = prepare_macros (reader);
+ write_diagnostic_classification (nullptr, global_dc, nullptr);
+
config.num_imports = mod_hwm;
config.num_partitions = modules->length () - mod_hwm;
auto map_info = write_prepare_maps (&config, bool (config.num_partitions));
@@ -20012,7 +20089,10 @@ module_state::write_begin (elf_out *to, cpp_reader *reader,
/* Write the line maps. */
if (config.ordinary_locs)
- write_ordinary_maps (to, map_info, bool (config.num_partitions), &crc);
+ {
+ write_ordinary_maps (to, map_info, bool (config.num_partitions), &crc);
+ write_diagnostic_classification (to, global_dc, &crc);
+ }
if (config.macro_locs)
write_macro_maps (to, map_info, &crc);
@@ -20145,6 +20225,10 @@ module_state::read_initial (cpp_reader *reader)
else if (!read_macro_maps (config.macro_locs))
ok = false;
+ if (ok && have_locs && config.ordinary_locs
+ && !read_diagnostic_classification (global_dc))
+ ok = false;
+
/* Note whether there's an active initializer. */
active_init_p = !is_header () && bool (config.active_init);
diff --git a/gcc/testsuite/g++.dg/modules/warn-spec-3_a.C b/gcc/testsuite/g++.dg/modules/warn-spec-3_a.C
new file mode 100644
index 00000000000..2e50303c41e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/warn-spec-3_a.C
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++20 } }
+// { dg-additional-options -fmodules }
+// { dg-module-cmi M }
+
+module;
+
+#include <initializer_list>
+
+export module M;
+
+#pragma GCC diagnostic ignored "-Winit-list-lifetime"
+
+template <class T>
+struct myspan {
+ const T* p; unsigned s;
+ myspan (std::initializer_list<T> il)
+ : p (il.begin()), s (il.size()) { }
+};
+
+export void f(myspan<int>);
diff --git a/gcc/testsuite/g++.dg/modules/warn-spec-3_b.C b/gcc/testsuite/g++.dg/modules/warn-spec-3_b.C
new file mode 100644
index 00000000000..2a8e60af206
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/warn-spec-3_b.C
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodules }
+
+import M;
+
+int main()
+{
+ f({24,42});
+}
--
2.49.0