[preprocessor] Include stacking

https://gcc.gnu.org/ml/gcc-patches/2019-08/msg01971.html
	* internal.h (enum include_type): Add IT_MAIN, IT_DIRECTIVE_HWM,
	IT_HEADER_HWM.
	(_cpp_stack_file): Take include_type, not a bool.
	* files.c (_cpp_find_file): Refactor to not hide an if inside a
	for conditional.
	(should_stack_file): Break apart to ...
	(is_known_idempotent_file, has_unique_contents): ... these.
	(_cpp_stack_file): Replace IMPORT boolean with include_type enum.
	Refactor to use new predicates.  Do linemap compensation here ...
	(_cpp_stack_include): ... not here.
	* init.c (cpp_read_main_file): Pass IT_MAIN to _cpp_stack_file.

From-SVN: r275034
This commit is contained in:
Nathan Sidwell 2019-08-29 14:06:32 +00:00 committed by Nathan Sidwell
parent d02a041242
commit b0d11f1ed6
4 changed files with 163 additions and 153 deletions

View File

@ -1,3 +1,17 @@
2019-08-29 Nathan Sidwell <nathan@acm.org>
* internal.h (enum include_type): Add IT_MAIN, IT_DIRECTIVE_HWM,
IT_HEADER_HWM.
(_cpp_stack_file): Take include_type, not a bool.
* files.c (_cpp_find_file): Refactor to not hide an if inside a
for conditional.
(should_stack_file): Break apart to ...
(is_known_idempotent_file, has_unique_contents): ... these.
(_cpp_stack_file): Replace IMPORT boolean with include_type enum.
Refactor to use new predicates. Do linemap compensation here ...
(_cpp_stack_include): ... not here.
* init.c (cpp_read_main_file): Pass IT_MAIN to _cpp_stack_file.
2019-08-28 Nathan Sidwell <nathan@acm.org> 2019-08-28 Nathan Sidwell <nathan@acm.org>
* directives-only.c (_cpp_preprocess_dir_only): Use false, not * directives-only.c (_cpp_preprocess_dir_only): Use false, not

View File

@ -176,8 +176,6 @@ static bool read_file_guts (cpp_reader *pfile, _cpp_file *file,
location_t loc); location_t loc);
static bool read_file (cpp_reader *pfile, _cpp_file *file, static bool read_file (cpp_reader *pfile, _cpp_file *file,
location_t loc); location_t loc);
static bool should_stack_file (cpp_reader *, _cpp_file *file, bool import,
location_t loc);
static struct cpp_dir *search_path_head (cpp_reader *, const char *fname, static struct cpp_dir *search_path_head (cpp_reader *, const char *fname,
int angle_brackets, enum include_type); int angle_brackets, enum include_type);
static const char *dir_name_of_file (_cpp_file *file); static const char *dir_name_of_file (_cpp_file *file);
@ -536,79 +534,86 @@ _cpp_find_file (cpp_reader *pfile, const char *fname, cpp_dir *start_dir,
|| (pfile->buffer || (pfile->buffer
&& pfile->buffer->file->implicit_preinclude)); && pfile->buffer->file->implicit_preinclude));
/* Try each path in the include chain. */ if (!fake)
for (; !fake ;) /* Try each path in the include chain. */
{ for (;;)
if (find_file_in_dir (pfile, file, &invalid_pch, loc)) {
break; if (find_file_in_dir (pfile, file, &invalid_pch, loc))
break;
file->dir = file->dir->next; file->dir = file->dir->next;
if (file->dir == NULL) if (file->dir == NULL)
{ {
if (search_path_exhausted (pfile, fname, file)) if (search_path_exhausted (pfile, fname, file))
{ {
/* Although this file must not go in the cache, because /* Although this file must not go in the cache,
the file found might depend on things (like the current file) because the file found might depend on things (like
that aren't represented in the cache, it still has to go in the current file) that aren't represented in the
the list of all files so that #import works. */ cache, it still has to go in the list of all files
file->next_file = pfile->all_files; so that #import works. */
pfile->all_files = file; file->next_file = pfile->all_files;
if (*hash_slot == NULL) pfile->all_files = file;
{ if (*hash_slot == NULL)
/* If *hash_slot is NULL, the above htab_find_slot_with_hash {
call just created the slot, but we aren't going to store /* If *hash_slot is NULL, the above
there anything, so need to remove the newly created entry. htab_find_slot_with_hash call just created the
htab_clear_slot requires that it is non-NULL, so store slot, but we aren't going to store there
there some non-NULL pointer, htab_clear_slot will anything, so need to remove the newly created
overwrite it immediately. */ entry. htab_clear_slot requires that it is
*hash_slot = file; non-NULL, so store there some non-NULL pointer,
htab_clear_slot (pfile->file_hash, hash_slot); htab_clear_slot will overwrite it
} immediately. */
return file; *hash_slot = file;
} htab_clear_slot (pfile->file_hash, hash_slot);
}
return file;
}
if (invalid_pch) if (invalid_pch)
{ {
cpp_error (pfile, CPP_DL_ERROR,
"one or more PCH files were found, but they were invalid");
if (!cpp_get_options (pfile)->warn_invalid_pch)
cpp_error (pfile, CPP_DL_ERROR, cpp_error (pfile, CPP_DL_ERROR,
"use -Winvalid-pch for more information"); "one or more PCH files were found,"
} " but they were invalid");
if (implicit_preinclude) if (!cpp_get_options (pfile)->warn_invalid_pch)
{ cpp_error (pfile, CPP_DL_ERROR,
free ((char *) file->name); "use -Winvalid-pch for more information");
free (file); }
if (*hash_slot == NULL)
{ if (implicit_preinclude)
/* See comment on the above htab_clear_slot call. */ {
*hash_slot = file; free ((char *) file->name);
htab_clear_slot (pfile->file_hash, hash_slot); free (file);
} if (*hash_slot == NULL)
return NULL; {
} /* See comment on the above htab_clear_slot call. */
else *hash_slot = file;
htab_clear_slot (pfile->file_hash, hash_slot);
}
return NULL;
}
open_file_failed (pfile, file, angle_brackets, loc); open_file_failed (pfile, file, angle_brackets, loc);
break; break;
} }
/* Only check the cache for the starting location (done above) /* Only check the cache for the starting location (done above)
and the quote and bracket chain heads because there are no and the quote and bracket chain heads because there are no
other possible starting points for searches. */ other possible starting points for searches. */
if (file->dir == pfile->bracket_include) if (file->dir == pfile->bracket_include)
saw_bracket_include = true; saw_bracket_include = true;
else if (file->dir == pfile->quote_include) else if (file->dir == pfile->quote_include)
saw_quote_include = true; saw_quote_include = true;
else else
continue; continue;
entry = search_cache ((struct cpp_file_hash_entry *) *hash_slot, file->dir); entry
if (entry) = search_cache ((struct cpp_file_hash_entry *) *hash_slot, file->dir);
{ if (entry)
found_in_cache = file->dir; {
break; found_in_cache = file->dir;
} break;
} }
}
if (entry) if (entry)
{ {
@ -778,18 +783,14 @@ read_file (cpp_reader *pfile, _cpp_file *file, location_t loc)
return !file->dont_read; return !file->dont_read;
} }
/* Returns TRUE if FILE's contents have been successfully placed in /* Returns TRUE if FILE is already known to be idempotent, and should
FILE->buffer and the file should be stacked, otherwise false. therefore not be read again. */
Use LOC for any diagnostics. */
static bool static bool
should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import, is_known_idempotent_file (cpp_reader *pfile, _cpp_file *file, bool import)
location_t loc)
{ {
_cpp_file *f;
/* Skip once-only files. */ /* Skip once-only files. */
if (file->once_only) if (file->once_only)
return false; return true;
/* We must mark the file once-only if #import now, before header /* We must mark the file once-only if #import now, before header
guard checks. Otherwise, undefining the header guard might guard checks. Otherwise, undefining the header guard might
@ -800,13 +801,13 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
/* Don't stack files that have been stacked before. */ /* Don't stack files that have been stacked before. */
if (file->stack_count) if (file->stack_count)
return false; return true;
} }
/* Skip if the file had a header guard and the macro is defined. /* Skip if the file had a header guard and the macro is defined.
PCH relies on this appearing before the PCH handler below. */ 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))
return false; return true;
/* Handle PCH files immediately; don't stack them. */ /* Handle PCH files immediately; don't stack them. */
if (file->pchname) if (file->pchname)
@ -815,12 +816,19 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
file->fd = -1; file->fd = -1;
free ((void *) file->pchname); free ((void *) file->pchname);
file->pchname = NULL; file->pchname = NULL;
return false; return true;
} }
if (!read_file (pfile, file, loc)) return false;
return false; }
/* Return TRUE if file has unique contents, so we should read process
it. The file's contents must already have been read. */
static bool
has_unique_contents (cpp_reader *pfile, _cpp_file *file, bool import,
location_t loc)
{
/* Check the file against the PCH file. This is done before /* Check the file against the PCH file. This is done before
checking against files we've already seen, since it may save on checking against files we've already seen, since it may save on
I/O. */ I/O. */
@ -841,10 +849,10 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
/* We may have read the file under a different name. Look /* We may have read the file under a different name. Look
for likely candidates and compare file contents to be sure. */ for likely candidates and compare file contents to be sure. */
for (f = pfile->all_files; f; f = f->next_file) for (_cpp_file *f = pfile->all_files; f; f = f->next_file)
{ {
if (f == file) if (f == file)
continue; continue; /* It'sa me! */
if ((import || f->once_only) if ((import || f->once_only)
&& f->err_no == 0 && f->err_no == 0
@ -852,7 +860,6 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
&& f->st.st_size == file->st.st_size) && f->st.st_size == file->st.st_size)
{ {
_cpp_file *ref_file; _cpp_file *ref_file;
bool same_file_p = false;
if (f->buffer && !f->buffer_valid) if (f->buffer && !f->buffer_valid)
{ {
@ -865,12 +872,11 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
/* The file is not stacked anymore. We can reuse it. */ /* The file is not stacked anymore. We can reuse it. */
ref_file = f; ref_file = f;
same_file_p = read_file (pfile, ref_file, loc) bool same_file_p = (read_file (pfile, ref_file, loc)
/* Size might have changed in read_file(). */ /* Size might have changed in read_file(). */
&& ref_file->st.st_size == file->st.st_size && ref_file->st.st_size == file->st.st_size
&& !memcmp (ref_file->buffer, && !memcmp (ref_file->buffer, file->buffer,
file->buffer, file->st.st_size));
file->st.st_size);
if (f->buffer && !f->buffer_valid) if (f->buffer && !f->buffer_valid)
{ {
@ -879,11 +885,12 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
} }
if (same_file_p) if (same_file_p)
break; /* Already seen under a different name. */
return false;
} }
} }
return f == NULL; return true;
} }
/* 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
@ -891,25 +898,27 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
because of a #import directive. Returns true if a buffer is because of a #import directive. Returns true if a buffer is
stacked. Use LOC for any diagnostics. */ stacked. Use LOC for any diagnostics. */
bool bool
_cpp_stack_file (cpp_reader *pfile, _cpp_file *file, bool import, _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type,
location_t loc) location_t loc)
{ {
cpp_buffer *buffer; if (is_known_idempotent_file (pfile, file, type == IT_IMPORT))
int sysp;
if (!should_stack_file (pfile, file, import, loc))
return false; return false;
if (pfile->buffer == NULL || file->dir == NULL) if (!read_file (pfile, file, loc))
sysp = 0; return false;
else
sysp = MAX (pfile->buffer->sysp, file->dir->sysp); if (!has_unique_contents (pfile, file, type == IT_IMPORT, loc))
return false;
int sysp = 0;
if (pfile->buffer && file->dir)
sysp = MAX (pfile->buffer->sysp, file->dir->sysp);
/* Add the file to the dependencies on its first inclusion. */ /* Add the file to the dependencies on its first inclusion. */
if (!file->stack_count if (CPP_OPTION (pfile, deps.style) > (sysp != 0)
&& CPP_OPTION (pfile, deps.style) > !!sysp && !file->stack_count
&& file->path[0] && file->path[0]
&& (!file->main_file || !CPP_OPTION (pfile, deps.ignore_main_file))) && !(file->main_file && CPP_OPTION (pfile, deps.ignore_main_file)))
deps_add_dep (pfile->deps, file->path); deps_add_dep (pfile->deps, file->path);
/* Clear buffer_valid since _cpp_clean_line messes it up. */ /* Clear buffer_valid since _cpp_clean_line messes it up. */
@ -917,9 +926,10 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
file->stack_count++; file->stack_count++;
/* Stack the buffer. */ /* Stack the buffer. */
buffer = cpp_push_buffer (pfile, file->buffer, file->st.st_size, cpp_buffer *buffer
CPP_OPTION (pfile, preprocessed) = cpp_push_buffer (pfile, file->buffer, file->st.st_size,
&& !CPP_OPTION (pfile, directives_only)); CPP_OPTION (pfile, preprocessed)
&& !CPP_OPTION (pfile, directives_only));
buffer->file = file; buffer->file = file;
buffer->sysp = sysp; buffer->sysp = sysp;
buffer->to_free = file->buffer_start; buffer->to_free = file->buffer_start;
@ -928,7 +938,27 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
pfile->mi_valid = true; pfile->mi_valid = true;
pfile->mi_cmacro = 0; pfile->mi_cmacro = 0;
/* Generate the call back. */ /* Compensate for the increment in linemap_add that occurs when in
do_file_change. In the case of a normal #include, we're
currently at the start of the line *following* the #include. A
separate location_t for this location makes no sense (until we do
the LC_LEAVE), and complicates LAST_SOURCE_LINE_LOCATION. This
does not apply if we found a PCH file (in which case linemap_add
is not called) or we were included from the command-line. In the
case that the #include is the last line in the file,
highest_location still points to the current line, not the start
of the next line, so we do not decrement in this case. See
plugin/location-overflow-test-pr83173.h for an example. */
bool decremented = false;
if (file->pchname == NULL && file->err_no == 0 && type < IT_DIRECTIVE_HWM)
{
decremented = (pfile->line_table->highest_line
== pfile->line_table->highest_location);
if (decremented)
pfile->line_table->highest_location--;
}
/* Add line map and do callbacks. */
_cpp_do_file_change (pfile, LC_ENTER, file->path, 1, sysp); _cpp_do_file_change (pfile, LC_ENTER, file->path, 1, sysp);
return true; return true;
@ -1009,11 +1039,6 @@ bool
_cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets, _cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets,
enum include_type type, location_t loc) enum include_type type, location_t loc)
{ {
struct cpp_dir *dir;
_cpp_file *file;
bool stacked;
bool decremented = false;
/* For -include command-line flags we have type == IT_CMDLINE. /* For -include command-line flags we have type == IT_CMDLINE.
When the first -include file is processed we have the case, where When the first -include file is processed we have the case, where
pfile->cur_token == pfile->cur_run->base, we are directly called up pfile->cur_token == pfile->cur_run->base, we are directly called up
@ -1026,48 +1051,16 @@ _cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets,
if (type == IT_CMDLINE && pfile->cur_token != pfile->cur_run->base) if (type == IT_CMDLINE && pfile->cur_token != pfile->cur_run->base)
pfile->cur_token[-1].src_loc = 0; pfile->cur_token[-1].src_loc = 0;
dir = search_path_head (pfile, fname, angle_brackets, type); cpp_dir *dir = search_path_head (pfile, fname, angle_brackets, type);
if (!dir) if (!dir)
return false; return false;
file = _cpp_find_file (pfile, fname, dir, false, angle_brackets, _cpp_file *file = _cpp_find_file (pfile, fname, dir, false, angle_brackets,
type == IT_DEFAULT, loc); type == IT_DEFAULT, loc);
if (type == IT_DEFAULT && file == NULL) if (type == IT_DEFAULT && file == NULL)
return false; return false;
/* Compensate for the increment in linemap_add that occurs if return _cpp_stack_file (pfile, file, type, loc);
_cpp_stack_file actually stacks the file. In the case of a normal
#include, we're currently at the start of the line *following* the
#include. A separate location_t for this location makes no
sense (until we do the LC_LEAVE), and complicates
LAST_SOURCE_LINE_LOCATION. This does not apply if we found a PCH
file (in which case linemap_add is not called) or we were included
from the command-line. In the case that the #include is the last
line in the file, highest_location still points to the current
line, not the start of the next line, so we do not decrement in
this case. See plugin/location-overflow-test-pr83173.h for an
example. */
if (file->pchname == NULL && file->err_no == 0
&& type != IT_CMDLINE && type != IT_DEFAULT)
{
int highest_line = linemap_get_expansion_line (pfile->line_table,
pfile->line_table->highest_location);
int source_line = linemap_get_expansion_line (pfile->line_table, loc);
if (highest_line > source_line)
{
pfile->line_table->highest_location--;
decremented = true;
}
}
stacked = _cpp_stack_file (pfile, file, type == IT_IMPORT, loc);
if (decremented && !stacked)
/* _cpp_stack_file didn't stack the file, so let's rollback the
compensation dance we performed above. */
pfile->line_table->highest_location++;
return stacked;
} }
/* Could not open FILE. The complication is dependency output. */ /* Could not open FILE. The complication is dependency output. */

View File

@ -651,7 +651,7 @@ cpp_read_main_file (cpp_reader *pfile, const char *fname)
if (_cpp_find_failed (pfile->main_file)) if (_cpp_find_failed (pfile->main_file))
return NULL; return NULL;
_cpp_stack_file (pfile, pfile->main_file, false, loc); _cpp_stack_file (pfile, pfile->main_file, IT_MAIN, 0);
/* For foo.i, read the original filename foo.c now, for the benefit /* For foo.i, read the original filename foo.c now, for the benefit
of the front ends. */ of the front ends. */

View File

@ -123,6 +123,10 @@ enum include_type
/* Non-directive including mechanisms. */ /* Non-directive including mechanisms. */
IT_CMDLINE, /* -include */ IT_CMDLINE, /* -include */
IT_DEFAULT, /* forced header */ IT_DEFAULT, /* forced header */
IT_MAIN, /* main */
IT_DIRECTIVE_HWM = IT_IMPORT + 1, /* Directives below this. */
IT_HEADER_HWM = IT_DEFAULT + 1, /* Header files below this. */
}; };
union utoken union utoken
@ -671,8 +675,7 @@ extern _cpp_file *_cpp_find_file (cpp_reader *, const char *, cpp_dir *,
extern bool _cpp_find_failed (_cpp_file *); extern bool _cpp_find_failed (_cpp_file *);
extern void _cpp_mark_file_once_only (cpp_reader *, struct _cpp_file *); extern void _cpp_mark_file_once_only (cpp_reader *, struct _cpp_file *);
extern void _cpp_fake_include (cpp_reader *, const char *); extern void _cpp_fake_include (cpp_reader *, const char *);
extern bool _cpp_stack_file (cpp_reader *, _cpp_file*, bool, extern bool _cpp_stack_file (cpp_reader *, _cpp_file*, include_type, location_t);
location_t);
extern bool _cpp_stack_include (cpp_reader *, const char *, int, extern bool _cpp_stack_include (cpp_reader *, const char *, int,
enum include_type, location_t); enum include_type, location_t);
extern int _cpp_compare_file_date (cpp_reader *, const char *, int); extern int _cpp_compare_file_date (cpp_reader *, const char *, int);