diff mbox series

[pushed] c++: modules don't require preprocessor output

Message ID 20241007155436.2096405-1-jason@redhat.com
State New
Headers show
Series [pushed] c++: modules don't require preprocessor output | expand

Commit Message

Jason Merrill Oct. 7, 2024, 3:53 p.m. UTC
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

init_modules has rejected -M -fmodules-ts on the premise that module
dependency analysis requires macro expansion, but this is no longer
accurate; P1857 prohibited module directives produced by macro expansion.
They can still be dependent on #if directives, but those are still handled
with -fdirectives-only.

What wasn't working was -M or -dM, because cpp_scan_nooutput never called
module_token_pre to implement the import.  The simplest fix is to use the
-fdirectives-only scan when modules are enabled and teach directives_only_cb
about flag_no_output.

gcc/cp/ChangeLog:

	* module.cc (init_modules): Don't warn about -M.

gcc/c-family/ChangeLog:

	* c-ppoutput.cc (preprocess_file): For modules,
	use directives-only scan even with flag_no_output.
	(directives_only_cb): Respect flag_no_output.

gcc/ChangeLog:

	* doc/invoke.texi (C++ Module Preprocessing): Allow -M,
	refer to -fdeps.

gcc/testsuite/ChangeLog:

	* g++.dg/modules/macro-8_a.H: New test.
	* g++.dg/modules/macro-8_b.C: New test.
	* g++.dg/modules/macro-8_c.C: New test.
	* g++.dg/modules/macro-8_d.C: New test.
---
 gcc/doc/invoke.texi                      | 13 ++++----
 gcc/c-family/c-ppoutput.cc               | 39 +++++++++++++++---------
 gcc/cp/module.cc                         | 17 -----------
 gcc/testsuite/g++.dg/modules/macro-8_b.C | 13 ++++++++
 gcc/testsuite/g++.dg/modules/macro-8_c.C | 13 ++++++++
 gcc/testsuite/g++.dg/modules/macro-8_d.C | 13 ++++++++
 gcc/testsuite/g++.dg/modules/macro-8_a.H |  4 +++
 7 files changed, 73 insertions(+), 39 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/macro-8_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/macro-8_c.C
 create mode 100644 gcc/testsuite/g++.dg/modules/macro-8_d.C
 create mode 100644 gcc/testsuite/g++.dg/modules/macro-8_a.H


base-commit: 5fb1ab539e3315175d2e843f4ce40bde6dd7c520
diff mbox series

Patch

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index d38c1feb86f..987b6360152 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -38206,13 +38206,12 @@  Whether a particular directive is translated is controlled by the
 module mapper.  Header unit names are canonicalized during
 preprocessing.
 
-Dependency information can be emitted for macro import, extending the
-functionality of @option{-MD} and @option{-MMD} options.  Detection of
-import declarations also requires phase 4 preprocessing, and thus
-requires full preprocessing (or compilation).
-
-The @option{-M}, @option{-MM} and @option{-E -fdirectives-only} options halt
-preprocessing before phase 4.
+Dependency information can be emitted for module import, extending the
+functionality of the various @option{-M} options.  Detection of import
+declarations requires phase 4 handling of preprocessor directives, but
+does not require macro expansion, so it is not necessary to use
+@option{-MD}.  See also @option{-fdeps-*} for an alternate format for
+module dependency information.
 
 The @option{-save-temps} option uses @option{-fdirectives-only} for
 preprocessing, and preserve the macro definitions in the preprocessed
diff --git a/gcc/c-family/c-ppoutput.cc b/gcc/c-family/c-ppoutput.cc
index e3f5ca3ec97..374252bb4f3 100644
--- a/gcc/c-family/c-ppoutput.cc
+++ b/gcc/c-family/c-ppoutput.cc
@@ -92,10 +92,16 @@  preprocess_file (cpp_reader *pfile)
      cpp_scan_nooutput or cpp_get_token next.  */
   if (flag_no_output && pfile->buffer)
     {
-      /* Scan -included buffers, then the main file.  */
-      while (pfile->buffer->prev)
-	cpp_scan_nooutput (pfile);
-      cpp_scan_nooutput (pfile);
+      if (flag_modules)
+	/* For macros from imported headers we need directives_only_cb.  */
+	scan_translation_unit_directives_only (pfile);
+      else
+	{
+	  /* Scan -included buffers, then the main file.  */
+	  while (pfile->buffer->prev)
+	    cpp_scan_nooutput (pfile);
+	  cpp_scan_nooutput (pfile);
+	}
     }
   else if (cpp_get_options (pfile)->traditional)
     scan_translation_unit_trad (pfile);
@@ -389,28 +395,31 @@  directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
       gcc_unreachable ();
 
     case CPP_DO_print:
-      {
-	print.src_line += va_arg (args, unsigned);
+      if (!flag_no_output)
+	{
+	  print.src_line += va_arg (args, unsigned);
 
-	const void *buf = va_arg (args, const void *);
-	size_t size = va_arg (args, size_t);
-	fwrite (buf, 1, size, print.outf);
-      }
+	  const void *buf = va_arg (args, const void *);
+	  size_t size = va_arg (args, size_t);
+	  fwrite (buf, 1, size, print.outf);
+	}
       break;
 
     case CPP_DO_location:
-      maybe_print_line (va_arg (args, location_t));
+      if (!flag_no_output)
+	maybe_print_line (va_arg (args, location_t));
       break;
 
     case CPP_DO_token:
       {
 	const cpp_token *token = va_arg (args, const cpp_token *);
-	location_t spelling_loc = va_arg (args, location_t);
-	streamer->stream (pfile, token, spelling_loc);
+	unsigned flags = 0;
 	if (streamer->filter)
+	  flags = lang_hooks.preprocess_token (pfile, token, streamer->filter);
+	if (!flag_no_output)
 	  {
-	    unsigned flags = lang_hooks.preprocess_token
-	      (pfile, token, streamer->filter);
+	    location_t spelling_loc = va_arg (args, location_t);
+	    streamer->stream (pfile, token, spelling_loc);
 	    if (flags & lang_hooks::PT_begin_pragma)
 	      streamer->begin_pragma ();
 	  }
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 65b37b4b554..2dc59ce8a12 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -20534,23 +20534,6 @@  init_modules (cpp_reader *reader)
     fatal_error (input_location,
 		 "C++ modules are incompatible with traditional preprocessing");
 
-  if (flag_preprocess_only)
-    {
-      cpp_options *cpp_opts = cpp_get_options (reader);
-      if (flag_no_output
-	  || (cpp_opts->deps.style != DEPS_NONE
-	      && !cpp_opts->deps.need_preprocessor_output))
-	{
-	  auto_diagnostic_group d;
-	  warning (0, flag_dump_macros == 'M'
-		   ? G_("macro debug output may be incomplete with modules")
-		   : G_("module dependencies require preprocessing"));
-	  if (cpp_opts->deps.style != DEPS_NONE)
-	    inform (input_location, "you should use the %<-%s%> option",
-		    cpp_opts->deps.style == DEPS_SYSTEM ? "MD" : "MMD");
-	}
-    }
-
   /* :: is always exported.  */
   DECL_MODULE_EXPORT_P (global_namespace) = true;
 
diff --git a/gcc/testsuite/g++.dg/modules/macro-8_b.C b/gcc/testsuite/g++.dg/modules/macro-8_b.C
new file mode 100644
index 00000000000..562d4ac0e65
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-8_b.C
@@ -0,0 +1,13 @@ 
+// Test that -dM works with a header unit.
+
+// { dg-do preprocess }
+// { dg-additional-options "-dM -fmodules-ts" }
+
+import "macro-8_a.H";
+
+#ifndef FOO
+#error FOOBAR
+#endif
+
+// { dg-final { scan-file macro-8_b.i {#define FOO foo} } }
+// { dg-final { scan-file-not macro-8_b.i {import *"} } }
diff --git a/gcc/testsuite/g++.dg/modules/macro-8_c.C b/gcc/testsuite/g++.dg/modules/macro-8_c.C
new file mode 100644
index 00000000000..875f8fa5ddb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-8_c.C
@@ -0,0 +1,13 @@ 
+// Test that -M works with a header unit.
+
+// { dg-do preprocess }
+// { dg-additional-options "-M -fmodules-ts" }
+
+import "macro-8_a.H";
+
+#ifndef FOO
+#error FOOBAR
+#endif
+
+// { dg-final { scan-file macro-8_c.i {macro-8_a.H.gcm} } }
+// { dg-final { scan-file-not macro-8_c.i {import *"} } }
diff --git a/gcc/testsuite/g++.dg/modules/macro-8_d.C b/gcc/testsuite/g++.dg/modules/macro-8_d.C
new file mode 100644
index 00000000000..c6322169a01
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-8_d.C
@@ -0,0 +1,13 @@ 
+// Test that -MM works with a header unit.
+
+// { dg-do preprocess }
+// { dg-additional-options "-MM -MF macro-8_d.d -fmodules-ts" }
+
+#include "macro-8_a.H"
+
+#ifndef FOO
+#error FOOBAR
+#endif
+
+// { dg-final { scan-file macro-8_d.d {macro-8_a.H.gcm} } }
+// { dg-final { scan-file-not macro-8_d.i {import *"} } }
diff --git a/gcc/testsuite/g++.dg/modules/macro-8_a.H b/gcc/testsuite/g++.dg/modules/macro-8_a.H
new file mode 100644
index 00000000000..281d5d79f88
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/macro-8_a.H
@@ -0,0 +1,4 @@ 
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#define FOO foo