Add -f[no-]header-guard-opt

Added so that one can determine the include graph from the -E output.
This commit is contained in:
Nathan Sidwell 2021-02-03 11:37:35 -08:00
parent 000bee388b
commit 65165eb3f8
13 changed files with 106 additions and 19 deletions

View 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;

View 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

View 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;

View 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.

View File

@ -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} } } */

View File

@ -0,0 +1,3 @@
#ifndef INNER
#define INNER
#endif

View File

@ -0,0 +1,4 @@
#ifndef OUTER
#define OUTER
#include "noheaderguard-a.h"
#endif

View File

@ -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} } } */

View File

@ -0,0 +1,5 @@
// { dg-additional-options -fmodule-header }
#ifndef OUTER
#define OUTER
#endif

View File

@ -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} } }

View File

@ -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} } }

View 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;
}

View 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
{