]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Add -f[no-]header-guard-opt devel/c++-modules
authorNathan Sidwell <nathan@acm.org>
Wed, 3 Feb 2021 19:37:35 +0000 (11:37 -0800)
committerNathan Sidwell <nathan@acm.org>
Wed, 3 Feb 2021 19:37:35 +0000 (11:37 -0800)
Added so that one can determine the include graph from the -E output.

13 files changed:
gcc/c-family/c-opts.c
gcc/c-family/c.opt
gcc/cp/module.cc
gcc/doc/cppopts.texi
gcc/testsuite/c-c++-common/cpp/headerguard.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/cpp/noheaderguard-a.h [new file with mode: 0644]
gcc/testsuite/c-c++-common/cpp/noheaderguard-b.h [new file with mode: 0644]
gcc/testsuite/c-c++-common/cpp/noheaderguard.c [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/noheaderguard-1_a.H [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/noheaderguard-1_b.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/noheaderguard-1_c.C [new file with mode: 0644]
libcpp/files.c
libcpp/include/cpplib.h

index bd15b9cd902d7b5f3d9d24e174b8fdb6d03b1e1c..240d3b8839e78e72e67ab56191a6683b235f6c4d 100644 (file)
@@ -477,6 +477,10 @@ c_common_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
       cpp_opts->extended_identifiers = value;
       break;
 
+    case OPT_fheader_guard_opt:
+      cpp_opts->no_header_guard_opt = !value;
+      break;
+
     case OPT_fmax_include_depth_:
        cpp_opts->max_include_depth = value;
       break;
index b209d46d32b37d625a398bef09879240db9927ba..7c155b01cc68ac7b80609d6c3a77ee7894d7ab7d 100644 (file)
@@ -1660,6 +1660,10 @@ C++ ObjC++ WarnRemoved
 fhandle-exceptions
 C++ ObjC++ Optimization Alias(fexceptions) Warn({%<-fhandle-exceptions%> has been renamed %<-fexceptions%> (and is now on by default)})
 
+fheader-guard-opt
+C ObjC C++ ObjC++
+Enable header file include guard optimization.
+
 fhonor-std
 C++ ObjC++ WarnRemoved
 
index 41ce20115255aae298acc7da0af51de8845cd9e4..213d9f699b87ab0e813c24ffb1f14b1dfd4afbfd 100644 (file)
@@ -19144,22 +19144,28 @@ maybe_translate_include (cpp_reader *reader, line_maps *lmaps, location_t loc,
 
   size_t len = strlen (path);
   path = canonicalize_header_name (NULL, loc, true, path, len);
-  auto packet = mapper->IncludeTranslate (path, Cody::Flags::None, len);
   int xlate = false;
-  if (packet.GetCode () == Cody::Client::PC_BOOL)
-    xlate = -int (packet.GetInteger ());
-  else if (packet.GetCode () == Cody::Client::PC_PATHNAME)
-    {
-      /* Record the CMI name for when we do the import.  */
-      module_state *import = get_module (build_string (len, path));
-      import->set_filename (packet);
-      xlate = +1;
-    }
+  auto name_str = build_string (len, path);
+  if (get_module_slot (name_str, nullptr, false, false))
+    /* We've already met this header.  */
+    xlate = +1;
   else
     {
-      gcc_checking_assert (packet.GetCode () == Cody::Client::PC_ERROR);
-      error_at (loc, "cannot determine %<#include%> translation of %s: %s",
-               path, packet.GetString ().c_str ());
+      auto packet = mapper->IncludeTranslate (path, Cody::Flags::None, len);
+      if (packet.GetCode () == Cody::Client::PC_BOOL)
+       xlate = -int (packet.GetInteger ());
+      else if (packet.GetCode () == Cody::Client::PC_PATHNAME)
+       {
+         /* Record the CMI name for when we do the import.  */
+         get_module (name_str)->set_filename (packet);
+         xlate = +1;
+       }
+      else
+       {
+         gcc_checking_assert (packet.GetCode () == Cody::Client::PC_ERROR);
+         error_at (loc, "cannot determine %<#include%> translation of %s: %s",
+                   path, packet.GetString ().c_str ());
+       }
     }
 
   bool note = false;
index b941de6df1b114241e50a1ecdb8073c38d3bd91c..a3bad58f6abab090672fb5e8d58ede1ff2485f89 100644 (file)
@@ -266,6 +266,20 @@ standard versions) and C++.
 @opindex fno-canonical-system-headers
 When preprocessing, do not shorten system header paths with canonicalization.
 
+@item -fno-header-guard-opt
+@opindex fno-header-guard-opt
+This disables the preprocessor's optimization of header files that
+have a macro header-guard.  Usually such files are do not appear at
+all in the preprocessed output on their second and subsequent
+inclusion.  This disables that optimization such that they will appear
+in the @code{#} line directive output, but of course their contents
+will be elided by the controlling @code{#if} directive.  This also
+covers C++ 20 include-translated header-unit imports, those will be
+subject to multiple include translations.  This option is useful to
+discover the complete #include graph of a translation unit.  It does
+not apply to idempotent headerfiles marked with @code{#pragma once},
+nor to headers read with @code{#import}.
+
 @item -fmax-include-depth=@var{depth}
 @opindex fmax-include-depth
 Set the maximum depth of the nested #include. The default is 200. 
diff --git a/gcc/testsuite/c-c++-common/cpp/headerguard.c b/gcc/testsuite/c-c++-common/cpp/headerguard.c
new file mode 100644 (file)
index 0000000..be63849
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do preprocess }  */
+/* Check header guards are optimized.  */
+
+#include "noheaderguard-b.h"
+#include "noheaderguard-b.h"
+#include "noheaderguard-a.h"
+
+/* { dg-final { scan-file headerguard.i {# [0-9]* "[^\n]*headerguard.c"\n\n*# [0-9]* "[^\n]*headerguard-b.h" 1\n\n*# [0-9]* "[^\n]*headerguard-a.h" 1\n\n*# [0-9]* "[^\n]*headerguard-b.h" 2\n\n*# [0-9]* "[^\n]*headerguard.c" 2\n} } } */
diff --git a/gcc/testsuite/c-c++-common/cpp/noheaderguard-a.h b/gcc/testsuite/c-c++-common/cpp/noheaderguard-a.h
new file mode 100644 (file)
index 0000000..6a6c2b4
--- /dev/null
@@ -0,0 +1,3 @@
+#ifndef INNER
+#define INNER
+#endif
diff --git a/gcc/testsuite/c-c++-common/cpp/noheaderguard-b.h b/gcc/testsuite/c-c++-common/cpp/noheaderguard-b.h
new file mode 100644 (file)
index 0000000..8b72a9f
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef OUTER
+#define OUTER
+#include "noheaderguard-a.h"
+#endif
diff --git a/gcc/testsuite/c-c++-common/cpp/noheaderguard.c b/gcc/testsuite/c-c++-common/cpp/noheaderguard.c
new file mode 100644 (file)
index 0000000..3e6fd87
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do preprocess }  */
+/* { dg-additional-options -fno-header-guard-opt }  */
+/* Check header guard optimization is disabled.  */
+
+#include "noheaderguard-b.h"
+#include "noheaderguard-b.h"
+#include "noheaderguard-a.h"
+
+/* { dg-final { scan-file noheaderguard.i {# [0-9]* "[^\n]*noheaderguard.c"\n\n*# [0-9]* "[^\n]*noheaderguard-b.h" 1\n\n*# [0-9]* "[^\n]*noheaderguard-a.h" 1\n\n*# [0-9]* "[^\n]*noheaderguard-b.h" 2\n\n*# [0-9]* "[^\n]*noheaderguard.c" 2\n\n*# [0-9]* "[^\n]*noheaderguard-b.h" 1\n\n*# [0-9]* "[^\n]*noheaderguard.c" 2\n\n*# [0-9]* "[^\n]*noheaderguard-a.h" 1\n\n*# [0-9]* "[^\n]*noheaderguard.c" 2\n} } } */
diff --git a/gcc/testsuite/g++.dg/modules/noheaderguard-1_a.H b/gcc/testsuite/g++.dg/modules/noheaderguard-1_a.H
new file mode 100644 (file)
index 0000000..6d552bf
--- /dev/null
@@ -0,0 +1,5 @@
+// { dg-additional-options -fmodule-header }
+
+#ifndef OUTER
+#define OUTER
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/noheaderguard-1_b.C b/gcc/testsuite/g++.dg/modules/noheaderguard-1_b.C
new file mode 100644 (file)
index 0000000..d5de8b2
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-additional-options {-fmodules-ts -fno-header-guard-opt} }
+
+#include "noheaderguard-1_a.H"
+#include "noheaderguard-1_a.H"
+
+// { dg-final { scan-file noheaderguard-1_b.i {# [0-9]* "[^\n]*noheaderguard-1_b.C"\n\n*import  "[^\n]*noheaderguard-1_a.H" \[\[__translated\]\];\nimport  "[^\n]*noheaderguard-1_a.H" \[\[__translated\]\];\n} } }
diff --git a/gcc/testsuite/g++.dg/modules/noheaderguard-1_c.C b/gcc/testsuite/g++.dg/modules/noheaderguard-1_c.C
new file mode 100644 (file)
index 0000000..b4f0442
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-additional-options {-fmodules-ts -fno-header-guard-opt} }
+
+import "noheaderguard-1_a.H";
+#include "noheaderguard-1_a.H"
+
+// { dg-final { scan-file noheaderguard-1_c.i {# [0-9]* "[^\n]*noheaderguard-1_c.C"\n\n*import  "[^\n]*noheaderguard-1_a.H";\nimport  "[^\n]*noheaderguard-1_a.H" \[\[__translated\]\];\n} } }
index 5ea3f8e1bf30f9f0cb8b64fc1e8a6009ff5c8b23..44c51fad729ce298fd48cfd7d8a4ab3fae1e96c9 100644 (file)
@@ -803,7 +803,9 @@ is_known_idempotent_file (cpp_reader *pfile, _cpp_file *file, bool import)
 
   /* Skip if the file had a header guard and the macro is defined.
      PCH relies on this appearing before the PCH handler below.  */
-  if (file->cmacro && cpp_macro_p (file->cmacro))
+  if (file->cmacro && cpp_macro_p (file->cmacro)
+      /* Ignore if the idempotency optimization is disabled.  */
+      && (file->pchname || !CPP_OPTION (pfile, no_header_guard_opt)))
     return true;
 
   /* Handle PCH files immediately; don't stack them.  */
@@ -819,6 +821,18 @@ is_known_idempotent_file (cpp_reader *pfile, _cpp_file *file, bool import)
   return false;
 }
 
+/* Mark FILE as a header_unit, if we're spotting idempotency.  */
+
+static void
+maybe_mark_header_unit (cpp_reader *pfile, _cpp_file *file)
+{
+  if (!CPP_OPTION (pfile, no_header_guard_opt))
+    {
+      file->header_unit = +1;
+      _cpp_mark_file_once_only (pfile, file);
+    }
+}
+      
 /* Return TRUE if file has unique contents, so we should read process
    it.  The file's contents must already have been read.  */
 
@@ -927,8 +941,7 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type,
                           strlen (buf), true);
       buffer->to_free = buffer->buf;
 
-      file->header_unit = +1;
-      _cpp_mark_file_once_only (pfile, file);
+      maybe_mark_header_unit (pfile, file);
     }
   else
     {
@@ -983,7 +996,7 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type,
   if (decrement)
     pfile->line_table->highest_location--;
 
-  if (file->header_unit <= 0)
+  if (!buf)
     /* Add line map and do callbacks.  */
     _cpp_do_file_change (pfile, LC_ENTER, file->path,
                       /* With preamble injection, start on line zero,
@@ -1126,8 +1139,8 @@ cpp_find_header_unit (cpp_reader *pfile, const char *name, bool angle,
       file->fd = 0;
     }
 
-  file->header_unit = +1;
-  _cpp_mark_file_once_only (pfile, file);
+  maybe_mark_header_unit (pfile, file);
+
   return file->path;
 }
 
index 4467c73284d9dddb5aa8a8563e9f4b5c628981a5..2b089a18c261c43e8881829663b9486ccf2eac26 100644 (file)
@@ -528,6 +528,9 @@ struct cpp_options
   /* True if warn about differences between C++98 and C++11.  */
   bool cpp_warn_cxx11_compat;
 
+  /* True if header file idempotency should not be optimized.  */
+  bool no_header_guard_opt;
+
   /* Dependency generation.  */
   struct
   {