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);
|| (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;
-
- 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)
- 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
- open_file_failed (pfile, file, angle_brackets, loc);
+ if (!fake)
+ /* Try each path in the include chain. */
+ for (;;)
+ {
+ if (find_file_in_dir (pfile, file, &invalid_pch, loc))
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;
+ 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)
+ 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;
+ }
- entry = search_cache ((struct cpp_file_hash_entry *) *hash_slot, file->dir);
- if (entry)
- {
- found_in_cache = file->dir;
- break;
- }
- }
+ open_file_failed (pfile, file, angle_brackets, loc);
+ 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;
+
+ entry
+ = search_cache ((struct cpp_file_hash_entry *) *hash_slot, file->dir);
+ if (entry)
+ {
+ found_in_cache = file->dir;
+ break;
+ }
+ }
if (entry)
{
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
/* 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)
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. */
/* 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
&& f->st.st_size == file->st.st_size)
{
_cpp_file *ref_file;
- bool same_file_p = false;
if (f->buffer && !f->buffer_valid)
{
/* 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)
{
}
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
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 (is_known_idempotent_file (pfile, file, type == IT_IMPORT))
+ return false;
- if (!should_stack_file (pfile, file, import, loc))
+ if (!read_file (pfile, file, loc))
return false;
- if (pfile->buffer == NULL || file->dir == NULL)
- sysp = 0;
- 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. */
- 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. */
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;
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;
_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
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. */