Tested x86_64-pc-linux-gnu.  Any other ideas for how to communicate headerness
to the front-end?

-- 8< --

C++20 modules support has depended on the driver seeing the -fmodules-ts
flag in order to implicitly add other flags.  This won't work when we start
enabling modules support by default; it's better to leave it up to the
front-end to decide what behaviors are implied by modules.

But for header units to be generated properly, we still need some way for
the driver to communicate to the front-end that we're dealing with a header.
We could almost exploit the --output-pch flag for this, but that doesn't
help with preprocessed output, including during -save-temps.

So this patch adds an internal --header flag for communication between the
driver and the front-end.  Users are not expected to pass this flag
themselves.

The patch then removes all -fmodules-ts checks from C++ lang-spec.h
in favor of a few lines in c_common_post_options.  It also replaces
-fmodule-header= with -fsearch-include-path= and adds --header as
appropriate.

Instead of implying -fdirectives-only when preprocessing a header unit, this
patch implies only -dD, which seems like enough to transmit the macro
definitions to the eventual header unit CMI.

Before this change, legacy-3_b.H got neither -fdirectives-only nor -dD
because lang-specs was only checking for -fmodules-ts, not -fmodule-header.
After this change it has -dD active, so I needed to add some blank lines as
suggested by the comment, and adjust the expected line numbers accordingly.

gcc/ChangeLog:

        * doc/invoke.texi: Update module header preprocessing guidance.

gcc/c-family/ChangeLog:

        * c.opt: Add --header.
        * c-opts.cc (c_common_post_options): Use it to enable
        modules header unit mode.

gcc/cp/ChangeLog:

        * lang-specs.h: Use --header and -fsearch-include-path
        instead of -fmodule-header and checking -fmodules-ts.
        * module.cc (init_modules): Update PCH comment.
        (handle_module_option): -fmodule-header implies --header.

gcc/testsuite/ChangeLog:

        * g++.dg/modules/legacy-3_b.H: Adjust for -dD.
---
 gcc/doc/invoke.texi                       | 15 ++++----
 gcc/c-family/c.opt                        |  3 ++
 gcc/cp/lang-specs.h                       | 42 ++++++++---------------
 gcc/c-family/c-opts.cc                    | 12 +++++++
 gcc/cp/module.cc                          |  4 +--
 gcc/testsuite/g++.dg/modules/legacy-3_b.H |  6 +++-
 6 files changed, 46 insertions(+), 36 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c69d032323e..b27e85bc38a 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -38235,14 +38235,17 @@ 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
-output.  Usually you also want to use this option when explicitly
-preprocessing a header-unit, or consuming such preprocessed output:
+Preprocessing a header with modules enabled implicitly enables
+@option{-dD} so that if the preprocessed output is then compiled to
+produce a header unit, the macro definitions are included.  In that
+second compilation you also need to tell the compiler that it's a
+preprocessed header; the simplest way to do that is compiling the
+@samp{.ii} file (which implies @option{-x c++-cpp-output}) with
+@option{-fmodule-header}.
 
 @smallexample
-g++ -fmodules-ts -E -fdirectives-only my-header.hh -o my-header.ii
-g++ -x c++-header -fmodules-ts -fpreprocessed -fdirectives-only my-header.ii
+g++ -fmodules-ts -E my-header.hh -o my-header.ii
+g++ -c -fmodule-header my-header.ii
 @end smallexample
 
 @node C++ Compiled Module Interface
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 0aada1c3080..6056dbde4b4 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -76,6 +76,9 @@ C ObjC C++ ObjC++ Separate Alias(-embed-dir=) 
MissingArgError(missing path after
 -embed-directory=
 C ObjC C++ ObjC++ Joined Alias(-embed-dir=) MissingArgError(missing path after 
%qs)
 
+-header
+C ObjC C++ ObjC++ Undocumented Var(flag_header)
+
 -imacros
 C ObjC C++ ObjC++ Separate Alias(imacros) MissingArgError(missing filename 
after %qs)
 
diff --git a/gcc/cp/lang-specs.h b/gcc/cp/lang-specs.h
index e5651567a2d..b6ed85c399c 100644
--- a/gcc/cp/lang-specs.h
+++ b/gcc/cp/lang-specs.h
@@ -46,63 +46,51 @@ along with GCC; see the file COPYING3.  If not see
   {".c++m", "@c++", 0, 0, 0},
   {".ccm", "@c++", 0, 0, 0},
   {"@c++-header",
-      "%{E|M|MM:cc1plus -E %{fmodules-ts:-fdirectives-only -fmodule-header}"
+      "%{E|M|MM:cc1plus -E --header"
       "  %(cpp_options) %2 %(cpp_debug_options)}"
       "%{!E:%{!M:%{!MM:"
-      "  %{save-temps*|no-integrated-cpp:cc1plus -E"
-      "    %{fmodules-ts:-fdirectives-only -fmodule-header}"
+      "  %{save-temps*|no-integrated-cpp:cc1plus -E --header"
       "           %(cpp_options) %2 -o %{save-temps*:%b.ii} 
%{!save-temps*:%g.ii} \n}"
       "  cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed"
-      "            %{fmodules-ts:-fdirectives-only}"
       "           %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}"
       "  %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}"
-      "  %{fmodules-ts:-fmodule-header %{fpreprocessed:-fdirectives-only}}"
-      "  %(cc1_options) %2"
+      "  %(cc1_options) %2 --header"
       "  %{!fsyntax-only:"
       "    %{!S:-o %g.s}"
-      "    %{!fmodule-*:%{!fmodules-*:%{!fdump-ada-spec*:"
-      "                 %{!o*:--output-pch %w%i.gch}%W{o*:--output-pch 
%w%*}}}}%{!S:%V}}"
+      "    %{!fdump-ada-spec*:"
+      "                 %{!o*:--output-pch %w%i.gch}%W{o*:--output-pch 
%w%*}}%{!S:%V}}"
       "}}}",
      CPLUSPLUS_CPP_SPEC, 0, 0},
   {"@c++-system-header",
-      "%{E|M|MM:cc1plus -E"
-      "  %{fmodules-ts:-fdirectives-only -fmodule-header=system}"
+      "%{E|M|MM:cc1plus -E --header -fsearch-include-path=system"
       "  %(cpp_options) %2 %(cpp_debug_options)}"
       "%{!E:%{!M:%{!MM:"
-      "  %{save-temps*|no-integrated-cpp:cc1plus -E"
-      "    %{fmodules-ts:-fdirectives-only -fmodule-header=system}"
+      "  %{save-temps*|no-integrated-cpp:cc1plus -E --header"
       "           %(cpp_options) %2 -o %{save-temps*:%b.ii} 
%{!save-temps*:%g.ii} \n}"
       "  cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed"
-      "            %{fmodules-ts:-fdirectives-only}"
       "           %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}"
       "  %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}"
-      "  %{fmodules-ts:-fmodule-header=system"
-      "    %{fpreprocessed:-fdirectives-only}}"
-      "  %(cc1_options) %2"
+      "  %(cc1_options) %2 --header -fsearch-include-path=system"
       "  %{!fsyntax-only:"
       "    %{!S:-o %g.s}"
-      "    %{!fmodule-*:%{!fmodules-*:%{!fdump-ada-spec*:"
-      "                 %{!o*:--output-pch %w%i.gch}%W{o*:--output-pch 
%w%*}}}}%{!S:%V}}"
+      "    %{!fdump-ada-spec*:"
+      "                 %{!o*:--output-pch %w%i.gch}%W{o*:--output-pch 
%w%*}}%{!S:%V}}"
       "}}}",
      CPLUSPLUS_CPP_SPEC, 0, 0},
   {"@c++-user-header",
-      "%{E|M|MM:cc1plus -E"
-      "  %{fmodules-ts:-fdirectives-only -fmodule-header=user}"
+      "%{E|M|MM:cc1plus -E --header -fsearch-include-path=user"
       "  %(cpp_options) %2 %(cpp_debug_options)}"
       "%{!E:%{!M:%{!MM:"
-      "  %{save-temps*|no-integrated-cpp:cc1plus -E"
-      "    %{fmodules-ts:-fdirectives-only -fmodule-header=user}"
+      "  %{save-temps*|no-integrated-cpp:cc1plus -E --header"
       "           %(cpp_options) %2 -o %{save-temps*:%b.ii} 
%{!save-temps*:%g.ii} \n}"
       "  cc1plus %{save-temps*|no-integrated-cpp:-fpreprocessed"
-      "            %{fmodules-ts:-fdirectives-only}"
       "           %{save-temps*:%b.ii} %{!save-temps*:%g.ii}}"
       "  %{!save-temps*:%{!no-integrated-cpp:%(cpp_unique_options)}}"
-      "  %{fmodules-ts:-fmodule-header=user 
%{fpreprocessed:-fdirectives-only}}"
-      "  %(cc1_options) %2"
+      "  %(cc1_options) %2 --header -fsearch-include-path=user"
       "  %{!fsyntax-only:"
       "    %{!S:-o %g.s}"
-      "    %{!fmodule-*:%{!fmodules-*:%{!fdump-ada-spec*:"
-      "                 %{!o*:--output-pch %w%i.gch}%W{o*:--output-pch 
%w%*}}}}%{!S:%V}}"
+      "    %{!fdump-ada-spec*:"
+      "                 %{!o*:--output-pch %w%i.gch}%W{o*:--output-pch 
%w%*}}%{!S:%V}}"
       "}}}",
      CPLUSPLUS_CPP_SPEC, 0, 0},
   {"@c++",
diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index 2798b4d295f..c7115e63ce7 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -1209,6 +1209,18 @@ c_common_post_options (const char **pfilename)
     error ("too many filenames given; type %<%s %s%> for usage",
           progname, "--help");
 
+  if (flag_modules && flag_header)
+    {
+      flag_header_unit = true;
+      /* Ignore --output-pch.  */
+      pch_file = NULL;
+
+      /* Preserve macros so that they go in the header unit when we feed
+        the preprocessed output back to the compiler.  */
+      if (flag_preprocess_only)
+       flag_dump_macros = 'D';
+    }
+
   if (flag_preprocess_only)
     {
       /* Open the output now.  We must do so even if flag_no_output is
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index e58c057a96e..c43aa9dc324 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -20524,8 +20524,7 @@ maybe_add_global (tree val, unsigned &crc)
 void
 init_modules (cpp_reader *reader)
 {
-  /* PCH should not be reachable because of lang-specs, but the
-     user could have overriden that.  */
+  /* We should have cleared this in c_common_post_options.  */
   if (pch_file)
     fatal_error (input_location,
                 "C++ modules are incompatible with precompiled headers");
@@ -21030,6 +21029,7 @@ handle_module_option (unsigned code, const char *str, 
int)
 
     case OPT_fmodule_header:
       flag_header_unit = hdr;
+      flag_header = 1;
       flag_modules = 1;
       return true;
 
diff --git a/gcc/testsuite/g++.dg/modules/legacy-3_b.H 
b/gcc/testsuite/g++.dg/modules/legacy-3_b.H
index 3bf819db661..145bfbbddd1 100644
--- a/gcc/testsuite/g++.dg/modules/legacy-3_b.H
+++ b/gcc/testsuite/g++.dg/modules/legacy-3_b.H
@@ -5,6 +5,10 @@
 
 // Enough blank lines to force a line sync before the legacy import
 
+
+
+
+
 // this should be diverted, if it isn't the above #define will break us
 #include "legacy-3_a.H"
 int move (int X = __LINE__); // Capture __LINE__ in a non-definition
@@ -12,5 +16,5 @@ int move (int X = __LINE__); // Capture __LINE__ in a 
non-definition
 // this should not be diverted
 #include "legacy-3.h"
 
-// { dg-final { scan-file legacy-3_b.i {\n# 9 "[^\n]*legacy-3_b.H"\nimport  
"[^\n]*legacy-3_a.H" \[\[__translated\]\];\nint move \(int X = 10\);\n} } }
+// { dg-final { scan-file legacy-3_b.i {\n# 13 "[^\n]*legacy-3_b.H"\nimport  
"[^\n]*legacy-3_a.H" \[\[__translated\]\];\nint move \(int X = 14\);\n} } }
 
-- 
2.46.2

Reply via email to