aboutsummaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2025-12-10 23:11:26 +0800
committerJason Merrill <jason@redhat.com>2025-12-10 23:11:26 +0800
commit9783f6f2f67f9472fa428b984e4e045ee7b64f78 (patch)
treefdb1d37a23435694992b15208b07b93c7fb33992 /libcpp
parent23d71494fe0a6244b870db5a4f879b528903f52c (diff)
downloadgcc-9783f6f2f67f9472fa428b984e4e045ee7b64f78.zip
gcc-9783f6f2f67f9472fa428b984e4e045ee7b64f78.tar.gz
gcc-9783f6f2f67f9472fa428b984e4e045ee7b64f78.tar.bz2
c++/modules: #include <vector> -> import <bits/stdc++.h>
Since the standard library doesn't preclude an #include of a standard library header from bringing in declarations from other headers, we can translate an #include of any of the importable headers as an import of <bits/stdc++.h>. To reduce the amount of C++ standard knowledge encoded in libcpp, I extend the translate_include callback to allow it to suggest an alternate header to try translating. It's a bit awkward to bounce back and forth, but this seems like the right division of responsibilities. libcpp/ChangeLog: * include/cpplib.h (struct cpp_callbacks): Replace 'path' parameter with file, angle_brackets, and alternate name. (cpp_get_name): Declare. * files.cc (cpp_get_name): New. (_cpp_stack_include, _cpp_post_stack_file, _cpp_stack_file) (_cpp_stack_translated_file): Refactor, try alternate file. gcc/cp/ChangeLog: * module.cc (maybe_translate_include): Suggest <bits/stdc++.h> as an alternate for importable standard library headers. (importable_headers, is_importable_header): New. gcc/ChangeLog: * doc/invoke.texi (C++ Modules): Remove standard library header units from missing pieces, mention importable header redirection. gcc/testsuite/ChangeLog: * g++.dg/modules/compile-std1.C: Test <vector> translation.
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/files.cc179
-rw-r--r--libcpp/include/cpplib.h3
2 files changed, 108 insertions, 74 deletions
diff --git a/libcpp/files.cc b/libcpp/files.cc
index f8b3312..dd65848 100644
--- a/libcpp/files.cc
+++ b/libcpp/files.cc
@@ -211,6 +211,7 @@ static bool validate_pch (cpp_reader *, _cpp_file *file, const char *pchname);
static int pchf_save_compare (const void *e1, const void *e2);
static int pchf_compare (const void *d_p, const void *e_p);
static bool check_file_against_entries (cpp_reader *, _cpp_file *, bool);
+static void _cpp_post_stack_file (cpp_reader *, _cpp_file *, include_type, bool);
/* Given a filename in FILE->PATH, with the empty string interpreted
as <stdin>, open it.
@@ -954,88 +955,92 @@ 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))
+ int sysp = 0;
+
+ /* Not a header unit, and we know it. */
+ file->header_unit = -1;
+
+ 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));
+ 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]
+ && !(pfile->main_file == 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;
- 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. (We also need an extra newline, so this looks like a regular
- file, which we do that to to make sure we don't fall off the end in the
- middle of a line. */
- if (type != IT_CMDLINE)
- {
- static uchar newlines[] = "\n\n\n";
- cpp_push_buffer (pfile, newlines, 2, true);
- }
+ /* Initialize controlling macro state. */
+ pfile->mi_valid = true;
+ pfile->mi_cmacro = 0;
- size_t len = strlen (buf);
- buf[len] = '\n'; /* See above */
- cpp_buffer *buffer
- = cpp_push_buffer (pfile, reinterpret_cast<unsigned char *> (buf),
- len, true);
- buffer->to_free = buffer->buf;
- if (type == IT_CMDLINE)
- /* Tell _cpp_pop_buffer to change files. */
- buffer->file = file;
+ _cpp_post_stack_file (pfile, file, type, sysp);
+ return true;
+}
- file->header_unit = +1;
- _cpp_mark_file_once_only (pfile, file);
- }
- else
- {
- /* Not a header unit, and we know it. */
- file->header_unit = -1;
+/* Like _cpp_stack_file, but for a file that's been replaced by the contents of
+ BUF. Used for C++ modules include -> import translation. */
- if (!read_file (pfile, file, loc))
- return false;
+static bool
+_cpp_stack_translated_file (cpp_reader *pfile, _cpp_file *file,
+ char *buf, include_type type)
+{
+ /* 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. (We also need an extra newline, so this looks like a regular
+ file, which we do that to to make sure we don't fall off the end in the
+ middle of a line. */
+ if (type != IT_CMDLINE)
+ {
+ static uchar newlines[] = "\n\n\n";
+ cpp_push_buffer (pfile, newlines, 2, true);
+ }
- if (!has_unique_contents (pfile, file, type == IT_IMPORT, loc))
- return false;
+ size_t len = strlen (buf);
+ buf[len] = '\n'; /* See above */
+ cpp_buffer *buffer
+ = cpp_push_buffer (pfile, reinterpret_cast<unsigned char *> (buf),
+ len, true);
+ buffer->to_free = buffer->buf;
+ if (type == IT_CMDLINE)
+ /* Tell _cpp_pop_buffer to change files. */
+ buffer->file = file;
- if (pfile->buffer && file->dir)
- sysp = MAX (pfile->buffer->sysp, file->dir->sysp);
+ file->header_unit = +1;
+ _cpp_mark_file_once_only (pfile, file);
- /* Add the file to the dependencies on its first inclusion. */
- if (CPP_OPTION (pfile, deps.style) > (sysp != 0)
- && !file->stack_count
- && file->path[0]
- && !(pfile->main_file == file
- && CPP_OPTION (pfile, deps.ignore_main_file)))
- deps_add_dep (pfile->deps, file->path);
+ _cpp_post_stack_file (pfile, file, type, false);
+ return true;
+}
- /* 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;
- }
+/* The common epilogue of _cpp_stack_file and _cpp_stack_translated_file. */
+static void
+_cpp_post_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type,
+ bool sysp)
+{
/* 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
location makes no sense, until we do the LC_LEAVE.
@@ -1070,8 +1075,6 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, include_type type,
linenum_type line = SOURCE_LINE (map, pfile->line_table->highest_line);
linemap_line_start (pfile->line_table, line - 1, 0);
}
-
- return true;
}
/* Mark FILE to be included once only. */
@@ -1171,7 +1174,37 @@ _cpp_stack_include (cpp_reader *pfile, const char *fname, int angle_brackets,
if (type == IT_DEFAULT && file == NULL)
return false;
- return _cpp_stack_file (pfile, file, type, loc);
+ if (is_known_idempotent_file (pfile, file, type == IT_IMPORT))
+ return false;
+
+ /* Check C++ module include translation. */
+ char *buf = nullptr;
+ if (!file->header_unit && type < IT_DEFAULT
+ /* Do not include translate include-next. */
+ && type != IT_INCLUDE_NEXT
+ && pfile->cb.translate_include)
+ {
+ const char *aname = nullptr;
+ buf = (pfile->cb.translate_include
+ (pfile, pfile->line_table, loc, file,
+ angle_brackets, &aname));
+ if (!buf && aname)
+ {
+ _cpp_file *afile = _cpp_find_file (pfile, aname, dir, angle_brackets,
+ _cpp_FFK_NORMAL, loc);
+ if (afile && !afile->header_unit)
+ buf = (pfile->cb.translate_include
+ (pfile, pfile->line_table, loc,
+ afile, angle_brackets, nullptr));
+ if (buf)
+ file = afile;
+ }
+ }
+
+ if (buf)
+ return _cpp_stack_translated_file (pfile, file, buf, type);
+ else
+ return _cpp_stack_file (pfile, file, type, loc);
}
/* NAME is a header file name, find the _cpp_file, if any. */
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 16f030c..65e1bc6 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -860,7 +860,8 @@ struct cpp_callbacks
/* Maybe translate a #include into something else. Return a
cpp_buffer containing the translation if translating. */
char *(*translate_include) (cpp_reader *, line_maps *, location_t,
- const char *path);
+ _cpp_file *file, bool angle_brackets,
+ const char **alternate);
};
#ifdef VMS