/* If this file is implicitly preincluded. */
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
}
/* Place the file referenced by FILE into a new buffer on the buffer
- stack if possible. IMPORT is true if this stacking attempt is
- because of a #import directive. Returns true if a buffer is
- stacked. Use LOC for any diagnostics. */
+ stack if possible. Returns true if a buffer is stacked. Use LOC
+ for any diagnostics. */
+
bool
_cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type,
location_t loc)
if (is_known_idempotent_file (pfile, file, type == IT_IMPORT))
return false;
- if (!read_file (pfile, file, loc))
- return false;
+ int sysp = 0;
+ char *buf = nullptr;
- if (!has_unique_contents (pfile, file, type == IT_IMPORT, loc))
- return false;
+ /* Check C++ module include translation. */
+ if (!file->header_unit && type < IT_HEADER_HWM
+ /* Do not include translate include-next. */
+ && type != IT_INCLUDE_NEXT
+ && pfile->cb.translate_include)
+ buf = (pfile->cb.translate_include
+ (pfile, pfile->line_table, loc, file->path));
- 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 (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;
+ if (buf)
+ {
+ /* 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);
+
+ cpp_buffer *buffer
+ = cpp_push_buffer (pfile, reinterpret_cast<unsigned char *> (buf),
+ strlen (buf), true);
+ buffer->to_free = buffer->buf;
+
+ file->header_unit = +1;
+ _cpp_mark_file_once_only (pfile, file);
+ }
+ 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
line *following* the #include. A separate location_t for this
This does not apply if we found a PCH file, we're not a regular
include, or we ran out of locations. */
- if (file->pchname == NULL
- && type < IT_DIRECTIVE_HWM
- && pfile->line_table->highest_location != LINE_MAP_MAX_LOCATION - 1)
+ bool decrement = (file->pchname == NULL
+ && type < IT_DIRECTIVE_HWM
+ && (pfile->line_table->highest_location
+ != LINE_MAP_MAX_LOCATION - 1));
+ if (decrement)
pfile->line_table->highest_location--;
- /* Add line map and do callbacks. */
- _cpp_do_file_change (pfile, LC_ENTER, file->path,
+ if (file->header_unit <= 0)
+ /* Add line map and do callbacks. */
+ _cpp_do_file_change (pfile, LC_ENTER, file->path,
/* With preamble injection, start on line zero,
so the preamble doesn't appear to have been
included from line 1. Likewise when
starting preprocessed, we expect an initial
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 _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. */
static void
open_file_failed (cpp_reader *pfile, _cpp_file *file, int angle_brackets,