preprocessor: Add support for header unit translation

libcpp/
	* files.c (struct _cpp_file): Add header_unit field.
	(_cpp_stack_file): Add header unit support.
	(cpp_find_header_unit): New.
	* include/cpplib.h (cpp_find_header_unit): Declare.
This commit is contained in:
Nathan Sidwell 2020-11-18 08:27:16 -08:00
parent db87f19ae3
commit 7ceb899e93
2 changed files with 115 additions and 37 deletions

View File

@ -111,6 +111,9 @@ struct _cpp_file
/* If this file is implicitly preincluded. */ /* If this file is implicitly preincluded. */
bool implicit_preinclude : 1; bool implicit_preinclude : 1;
/* > 0: Known C++ Module header unit, <0: known not. ==0, unknown */
int header_unit : 2;
}; };
/* A singly-linked list for all searches for a given file name, with /* A singly-linked list for all searches for a given file name, with
@ -891,9 +894,9 @@ has_unique_contents (cpp_reader *pfile, _cpp_file *file, bool import,
} }
/* Place the file referenced by FILE into a new buffer on the buffer /* Place the file referenced by FILE into a new buffer on the buffer
stack if possible. IMPORT is true if this stacking attempt is stack if possible. Returns true if a buffer is stacked. Use LOC
because of a #import directive. Returns true if a buffer is for any diagnostics. */
stacked. Use LOC for any diagnostics. */
bool bool
_cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type, _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type,
location_t loc) location_t loc)
@ -901,39 +904,73 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type,
if (is_known_idempotent_file (pfile, file, type == IT_IMPORT)) if (is_known_idempotent_file (pfile, file, type == IT_IMPORT))
return false; return false;
if (!read_file (pfile, file, loc))
return false;
if (!has_unique_contents (pfile, file, type == IT_IMPORT, loc))
return false;
int sysp = 0; int sysp = 0;
if (pfile->buffer && file->dir) char *buf = nullptr;
sysp = MAX (pfile->buffer->sysp, file->dir->sysp);
/* Add the file to the dependencies on its first inclusion. */ /* Check C++ module include translation. */
if (CPP_OPTION (pfile, deps.style) > (sysp != 0) if (!file->header_unit && type < IT_HEADER_HWM
&& !file->stack_count /* Do not include translate include-next. */
&& file->path[0] && type != IT_INCLUDE_NEXT
&& !(file->main_file && CPP_OPTION (pfile, deps.ignore_main_file))) && pfile->cb.translate_include)
deps_add_dep (pfile->deps, file->path); buf = (pfile->cb.translate_include
(pfile, pfile->line_table, loc, file->path));
/* Clear buffer_valid since _cpp_clean_line messes it up. */ if (buf)
file->buffer_valid = false; {
file->stack_count++; /* We don't increment the line number at the end of a buffer,
because we don't usually need that location (we're popping an
include file). However in this case we do want to do the
increment. So push a writable buffer of two newlines to acheive
that. */
static uchar newlines[] = "\n\n";
cpp_push_buffer (pfile, newlines, 2, true);
/* Stack the buffer. */ cpp_buffer *buffer
cpp_buffer *buffer = cpp_push_buffer (pfile, reinterpret_cast<unsigned char *> (buf),
= cpp_push_buffer (pfile, file->buffer, file->st.st_size, strlen (buf), true);
CPP_OPTION (pfile, preprocessed) buffer->to_free = buffer->buf;
&& !CPP_OPTION (pfile, directives_only));
buffer->file = file;
buffer->sysp = sysp;
buffer->to_free = file->buffer_start;
/* Initialize controlling macro state. */ file->header_unit = +1;
pfile->mi_valid = true; _cpp_mark_file_once_only (pfile, file);
pfile->mi_cmacro = 0; }
else
{
/* Not a header unit, and we know it. */
file->header_unit = -1;
if (!read_file (pfile, file, loc))
return false;
if (!has_unique_contents (pfile, file, type == IT_IMPORT, loc))
return false;
if (pfile->buffer && file->dir)
sysp = MAX (pfile->buffer->sysp, file->dir->sysp);
/* Add the file to the dependencies on its first inclusion. */
if (CPP_OPTION (pfile, deps.style) > (sysp != 0)
&& !file->stack_count
&& file->path[0]
&& !(file->main_file && CPP_OPTION (pfile, deps.ignore_main_file)))
deps_add_dep (pfile->deps, file->path);
/* Clear buffer_valid since _cpp_clean_line messes it up. */
file->buffer_valid = false;
file->stack_count++;
/* Stack the buffer. */
cpp_buffer *buffer
= cpp_push_buffer (pfile, file->buffer, file->st.st_size,
CPP_OPTION (pfile, preprocessed)
&& !CPP_OPTION (pfile, directives_only));
buffer->file = file;
buffer->sysp = sysp;
buffer->to_free = file->buffer_start;
/* Initialize controlling macro state. */
pfile->mi_valid = true;
pfile->mi_cmacro = 0;
}
/* In the case of a normal #include, we're now at the start of the /* In the case of a normal #include, we're now at the start of the
line *following* the #include. A separate location_t for this line *following* the #include. A separate location_t for this
@ -941,19 +978,30 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type,
This does not apply if we found a PCH file, we're not a regular This does not apply if we found a PCH file, we're not a regular
include, or we ran out of locations. */ include, or we ran out of locations. */
if (file->pchname == NULL bool decrement = (file->pchname == NULL
&& type < IT_DIRECTIVE_HWM && type < IT_DIRECTIVE_HWM
&& pfile->line_table->highest_location != LINE_MAP_MAX_LOCATION - 1) && (pfile->line_table->highest_location
!= LINE_MAP_MAX_LOCATION - 1));
if (decrement)
pfile->line_table->highest_location--; pfile->line_table->highest_location--;
/* Add line map and do callbacks. */ if (file->header_unit <= 0)
_cpp_do_file_change (pfile, LC_ENTER, file->path, /* Add line map and do callbacks. */
_cpp_do_file_change (pfile, LC_ENTER, file->path,
/* With preamble injection, start on line zero, /* With preamble injection, start on line zero,
so the preamble doesn't appear to have been so the preamble doesn't appear to have been
included from line 1. Likewise when included from line 1. Likewise when
starting preprocessed, we expect an initial starting preprocessed, we expect an initial
locating line. */ locating line. */
type == IT_PRE_MAIN ? 0 : 1, sysp); type == IT_PRE_MAIN ? 0 : 1, sysp);
else if (decrement)
{
/* Adjust the line back one so we appear on the #include line itself. */
const line_map_ordinary *map
= LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table);
linenum_type line = SOURCE_LINE (map, pfile->line_table->highest_line);
linemap_line_start (pfile->line_table, line - 1, 0);
}
return true; return true;
} }
@ -1058,6 +1106,33 @@ _cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets,
return _cpp_stack_file (pfile, file, type, loc); return _cpp_stack_file (pfile, file, type, loc);
} }
/* NAME is a header file name, find the path we'll use to open it. */
const char *
cpp_find_header_unit (cpp_reader *pfile, const char *name, bool angle,
location_t loc)
{
cpp_dir *dir = search_path_head (pfile, name, angle, IT_INCLUDE);
if (!dir)
return NULL;
_cpp_file *file = _cpp_find_file (pfile, name, dir, angle,
_cpp_FFK_NORMAL, loc);
if (!file)
return NULL;
if (file->fd > 0)
{
/* Don't leave it open. */
close (file->fd);
file->fd = 0;
}
file->header_unit = +1;
_cpp_mark_file_once_only (pfile, file);
return file->path;
}
/* Could not open FILE. The complication is dependency output. */ /* Could not open FILE. The complication is dependency output. */
static void static void
open_file_failed (cpp_reader *pfile, _cpp_file *file, int angle_brackets, open_file_failed (cpp_reader *pfile, _cpp_file *file, int angle_brackets,

View File

@ -983,6 +983,9 @@ extern cpp_callbacks *cpp_get_callbacks (cpp_reader *) ATTRIBUTE_PURE;
extern void cpp_set_callbacks (cpp_reader *, cpp_callbacks *); extern void cpp_set_callbacks (cpp_reader *, cpp_callbacks *);
extern class mkdeps *cpp_get_deps (cpp_reader *) ATTRIBUTE_PURE; extern class mkdeps *cpp_get_deps (cpp_reader *) ATTRIBUTE_PURE;
extern const char *cpp_find_header_unit (cpp_reader *, const char *file,
bool angle_p, location_t);
/* This function reads the file, but does not start preprocessing. It /* This function reads the file, but does not start preprocessing. It
returns the name of the original file; this is the same as the returns the name of the original file; this is the same as the
input file, except for preprocessed input. This will generate at input file, except for preprocessed input. This will generate at