[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:
parent
d02a041242
commit
b0d11f1ed6
@ -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>
|
||||
|
||||
* directives-only.c (_cpp_preprocess_dir_only): Use false, not
|
||||
|
293
libcpp/files.c
293
libcpp/files.c
@ -176,8 +176,6 @@ static bool read_file_guts (cpp_reader *pfile, _cpp_file *file,
|
||||
location_t loc);
|
||||
static bool read_file (cpp_reader *pfile, _cpp_file *file,
|
||||
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,
|
||||
int angle_brackets, enum include_type);
|
||||
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->file->implicit_preinclude));
|
||||
|
||||
/* Try each path in the include chain. */
|
||||
for (; !fake ;)
|
||||
{
|
||||
if (find_file_in_dir (pfile, file, &invalid_pch, loc))
|
||||
break;
|
||||
if (!fake)
|
||||
/* Try each path in the include chain. */
|
||||
for (;;)
|
||||
{
|
||||
if (find_file_in_dir (pfile, file, &invalid_pch, loc))
|
||||
break;
|
||||
|
||||
file->dir = file->dir->next;
|
||||
if (file->dir == NULL)
|
||||
{
|
||||
if (search_path_exhausted (pfile, fname, file))
|
||||
{
|
||||
/* Although this file must not go in the cache, because
|
||||
the file found might depend on things (like the current file)
|
||||
that aren't represented in the cache, it still has to go in
|
||||
the list of all files so that #import works. */
|
||||
file->next_file = pfile->all_files;
|
||||
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
|
||||
there anything, so need to remove the newly created entry.
|
||||
htab_clear_slot requires that it is non-NULL, so store
|
||||
there some non-NULL pointer, htab_clear_slot will
|
||||
overwrite it immediately. */
|
||||
*hash_slot = file;
|
||||
htab_clear_slot (pfile->file_hash, hash_slot);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
file->dir = file->dir->next;
|
||||
if (file->dir == NULL)
|
||||
{
|
||||
if (search_path_exhausted (pfile, fname, file))
|
||||
{
|
||||
/* Although this file must not go in the cache,
|
||||
because the file found might depend on things (like
|
||||
the current file) that aren't represented in the
|
||||
cache, it still has to go in the list of all files
|
||||
so that #import works. */
|
||||
file->next_file = pfile->all_files;
|
||||
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 there
|
||||
anything, so need to remove the newly created
|
||||
entry. htab_clear_slot requires that it is
|
||||
non-NULL, so store there some non-NULL pointer,
|
||||
htab_clear_slot will overwrite it
|
||||
immediately. */
|
||||
*hash_slot = file;
|
||||
htab_clear_slot (pfile->file_hash, hash_slot);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
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)
|
||||
if (invalid_pch)
|
||||
{
|
||||
cpp_error (pfile, CPP_DL_ERROR,
|
||||
"use -Winvalid-pch for more information");
|
||||
}
|
||||
if (implicit_preinclude)
|
||||
{
|
||||
free ((char *) file->name);
|
||||
free (file);
|
||||
if (*hash_slot == NULL)
|
||||
{
|
||||
/* See comment on the above htab_clear_slot call. */
|
||||
*hash_slot = file;
|
||||
htab_clear_slot (pfile->file_hash, hash_slot);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
"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,
|
||||
"use -Winvalid-pch for more information");
|
||||
}
|
||||
|
||||
if (implicit_preinclude)
|
||||
{
|
||||
free ((char *) file->name);
|
||||
free (file);
|
||||
if (*hash_slot == NULL)
|
||||
{
|
||||
/* See comment on the above htab_clear_slot call. */
|
||||
*hash_slot = file;
|
||||
htab_clear_slot (pfile->file_hash, hash_slot);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
open_file_failed (pfile, file, angle_brackets, loc);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Only check the cache for the starting location (done above)
|
||||
and the quote and bracket chain heads because there are no
|
||||
other possible starting points for searches. */
|
||||
if (file->dir == pfile->bracket_include)
|
||||
saw_bracket_include = true;
|
||||
else if (file->dir == pfile->quote_include)
|
||||
saw_quote_include = true;
|
||||
else
|
||||
continue;
|
||||
/* Only check the cache for the starting location (done above)
|
||||
and the quote and bracket chain heads because there are no
|
||||
other possible starting points for searches. */
|
||||
if (file->dir == pfile->bracket_include)
|
||||
saw_bracket_include = true;
|
||||
else if (file->dir == pfile->quote_include)
|
||||
saw_quote_include = true;
|
||||
else
|
||||
continue;
|
||||
|
||||
entry = search_cache ((struct cpp_file_hash_entry *) *hash_slot, file->dir);
|
||||
if (entry)
|
||||
{
|
||||
found_in_cache = file->dir;
|
||||
break;
|
||||
}
|
||||
}
|
||||
entry
|
||||
= search_cache ((struct cpp_file_hash_entry *) *hash_slot, file->dir);
|
||||
if (entry)
|
||||
{
|
||||
found_in_cache = file->dir;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry)
|
||||
{
|
||||
@ -778,18 +783,14 @@ read_file (cpp_reader *pfile, _cpp_file *file, location_t loc)
|
||||
return !file->dont_read;
|
||||
}
|
||||
|
||||
/* Returns TRUE if FILE's contents have been successfully placed in
|
||||
FILE->buffer and the file should be stacked, otherwise false.
|
||||
Use LOC for any diagnostics. */
|
||||
/* Returns TRUE if FILE is already known to be idempotent, and should
|
||||
therefore not be read again. */
|
||||
static bool
|
||||
should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
|
||||
location_t loc)
|
||||
is_known_idempotent_file (cpp_reader *pfile, _cpp_file *file, bool import)
|
||||
{
|
||||
_cpp_file *f;
|
||||
|
||||
/* Skip once-only files. */
|
||||
if (file->once_only)
|
||||
return false;
|
||||
return true;
|
||||
|
||||
/* We must mark the file once-only if #import now, before header
|
||||
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. */
|
||||
if (file->stack_count)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* 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))
|
||||
return false;
|
||||
return true;
|
||||
|
||||
/* Handle PCH files immediately; don't stack them. */
|
||||
if (file->pchname)
|
||||
@ -815,12 +816,19 @@ should_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
|
||||
file->fd = -1;
|
||||
free ((void *) file->pchname);
|
||||
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
|
||||
checking against files we've already seen, since it may save on
|
||||
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
|
||||
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)
|
||||
continue;
|
||||
continue; /* It'sa me! */
|
||||
|
||||
if ((import || f->once_only)
|
||||
&& 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)
|
||||
{
|
||||
_cpp_file *ref_file;
|
||||
bool same_file_p = false;
|
||||
|
||||
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. */
|
||||
ref_file = f;
|
||||
|
||||
same_file_p = read_file (pfile, ref_file, loc)
|
||||
/* Size might have changed in read_file(). */
|
||||
&& ref_file->st.st_size == file->st.st_size
|
||||
&& !memcmp (ref_file->buffer,
|
||||
file->buffer,
|
||||
file->st.st_size);
|
||||
bool same_file_p = (read_file (pfile, ref_file, loc)
|
||||
/* Size might have changed in read_file(). */
|
||||
&& ref_file->st.st_size == file->st.st_size
|
||||
&& !memcmp (ref_file->buffer, file->buffer,
|
||||
file->st.st_size));
|
||||
|
||||
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)
|
||||
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
|
||||
@ -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
|
||||
stacked. Use LOC for any diagnostics. */
|
||||
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)
|
||||
{
|
||||
cpp_buffer *buffer;
|
||||
int sysp;
|
||||
|
||||
if (!should_stack_file (pfile, file, import, loc))
|
||||
if (is_known_idempotent_file (pfile, file, type == IT_IMPORT))
|
||||
return false;
|
||||
|
||||
if (pfile->buffer == NULL || file->dir == NULL)
|
||||
sysp = 0;
|
||||
else
|
||||
sysp = MAX (pfile->buffer->sysp, file->dir->sysp);
|
||||
if (!read_file (pfile, file, loc))
|
||||
return false;
|
||||
|
||||
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. */
|
||||
if (!file->stack_count
|
||||
&& CPP_OPTION (pfile, deps.style) > !!sysp
|
||||
if (CPP_OPTION (pfile, deps.style) > (sysp != 0)
|
||||
&& !file->stack_count
|
||||
&& 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);
|
||||
|
||||
/* 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++;
|
||||
|
||||
/* Stack the buffer. */
|
||||
buffer = cpp_push_buffer (pfile, file->buffer, file->st.st_size,
|
||||
CPP_OPTION (pfile, preprocessed)
|
||||
&& !CPP_OPTION (pfile, directives_only));
|
||||
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;
|
||||
@ -928,7 +938,27 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, bool import,
|
||||
pfile->mi_valid = true;
|
||||
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);
|
||||
|
||||
return true;
|
||||
@ -1009,11 +1039,6 @@ bool
|
||||
_cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets,
|
||||
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.
|
||||
When the first -include file is processed we have the case, where
|
||||
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)
|
||||
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)
|
||||
return false;
|
||||
|
||||
file = _cpp_find_file (pfile, fname, dir, false, angle_brackets,
|
||||
type == IT_DEFAULT, loc);
|
||||
_cpp_file *file = _cpp_find_file (pfile, fname, dir, false, angle_brackets,
|
||||
type == IT_DEFAULT, loc);
|
||||
if (type == IT_DEFAULT && file == NULL)
|
||||
return false;
|
||||
|
||||
/* Compensate for the increment in linemap_add that occurs if
|
||||
_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;
|
||||
return _cpp_stack_file (pfile, file, type, loc);
|
||||
}
|
||||
|
||||
/* Could not open FILE. The complication is dependency output. */
|
||||
|
@ -651,7 +651,7 @@ cpp_read_main_file (cpp_reader *pfile, const char *fname)
|
||||
if (_cpp_find_failed (pfile->main_file))
|
||||
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
|
||||
of the front ends. */
|
||||
|
@ -123,6 +123,10 @@ enum include_type
|
||||
/* Non-directive including mechanisms. */
|
||||
IT_CMDLINE, /* -include */
|
||||
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
|
||||
@ -671,8 +675,7 @@ extern _cpp_file *_cpp_find_file (cpp_reader *, const char *, cpp_dir *,
|
||||
extern bool _cpp_find_failed (_cpp_file *);
|
||||
extern void _cpp_mark_file_once_only (cpp_reader *, struct _cpp_file *);
|
||||
extern void _cpp_fake_include (cpp_reader *, const char *);
|
||||
extern bool _cpp_stack_file (cpp_reader *, _cpp_file*, bool,
|
||||
location_t);
|
||||
extern bool _cpp_stack_file (cpp_reader *, _cpp_file*, include_type, location_t);
|
||||
extern bool _cpp_stack_include (cpp_reader *, const char *, int,
|
||||
enum include_type, location_t);
|
||||
extern int _cpp_compare_file_date (cpp_reader *, const char *, int);
|
||||
|
Loading…
Reference in New Issue
Block a user