From 7ceb899e9343493f646434f74a149395f3913d9a Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Wed, 18 Nov 2020 08:27:16 -0800 Subject: [PATCH] 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. --- libcpp/files.c | 155 +++++++++++++++++++++++++++++----------- libcpp/include/cpplib.h | 3 + 2 files changed, 118 insertions(+), 40 deletions(-) diff --git a/libcpp/files.c b/libcpp/files.c index d73177aa1ee..b5d9f30297e 100644 --- a/libcpp/files.c +++ b/libcpp/files.c @@ -111,6 +111,9 @@ struct _cpp_file /* 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 @@ -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 - 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) @@ -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)) 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 (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 @@ -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 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; } @@ -1058,6 +1106,33 @@ _cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets, 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, diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 75d4d0a9f2f..389af32bc5c 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -983,6 +983,9 @@ extern cpp_callbacks *cpp_get_callbacks (cpp_reader *) ATTRIBUTE_PURE; extern void cpp_set_callbacks (cpp_reader *, cpp_callbacks *); 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 returns the name of the original file; this is the same as the input file, except for preprocessed input. This will generate at -- 2.30.2