https://gcc.gnu.org/g:c877a27f04f648e53c27daa252ca46d47e49b3a1
commit r15-4119-gc877a27f04f648e53c27daa252ca46d47e49b3a1 Author: Jason Merrill <ja...@redhat.com> Date: Fri Oct 4 10:33:16 2024 -0400 c++: modules don't require preprocessor output 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. Diff: --- 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(-) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index d38c1feb86f7..987b63601520 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 e3f5ca3ec97c..374252bb4f37 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 65b37b4b5544..2dc59ce8a120 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 000000000000..562d4ac0e655 --- /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 000000000000..875f8fa5ddb3 --- /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 000000000000..c6322169a013 --- /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 000000000000..281d5d79f88d --- /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