[gcc r11-7283] c++: header-unit build capability [PR 99023]
Nathan Sidwell
nathan@gcc.gnu.org
Thu Feb 18 21:22:55 GMT 2021
https://gcc.gnu.org/g:1f9db6929d926222aee0628b93f77cd20cf3adc4
commit r11-7283-g1f9db6929d926222aee0628b93f77cd20cf3adc4
Author: Nathan Sidwell <nathan@acm.org>
Date: Thu Feb 18 12:46:25 2021 -0800
c++: header-unit build capability [PR 99023]
This defect really required building header-units and include translation
of pieces of the standard library. This adds smarts to the modules
test harness to do that -- accept .X files as the source file, but
provide '-x c++-system-header $HDR' in the options. The .X file will
be considered by the driver to be a linker script and ignored (with a
warning).
Using this we can add 2 tests that end up building list_initializer
and iostream, along with a test that iostream's build
include-translates list_initializer's #include. That discovered a set
of issues with the -flang-info-include-translate=HDR handling, also
fixed and documented here.
PR c++/99023
gcc/cp/
* module.cc (canonicalize_header_name): Use
cpp_probe_header_unit.
(maybe_translate_include): Fix note_includes comparison.
(init_modules): Fix note_includes string termination.
libcpp/
* include/cpplib.h (cpp_find_header_unit): Rename to ...
(cpp_probe_header_unit): ... this.
* internal.h (_cp_find_header_unit): Declare.
* files.c (cpp_find_header_unit): Break apart to ..
(test_header_unit): ... this, and ...
(_cpp_find_header_unit): ... and, or and ...
(cpp_probe_header_unit): ... this.
* macro.c (cpp_get_token_1): Call _cpp_find_header_unit.
gcc/
* doc/invoke.texi (flang-info-include-translate): Document header
lookup behaviour.
gcc/testsuite/
* g++.dg/modules/modules.exp: Bail on cross-testing. Add support
for .X files.
* g++.dg/modules/pr99023_a.X: New.
* g++.dg/modules/pr99023_b.X: New.
Diff:
---
gcc/cp/module.cc | 22 ++++--------
gcc/doc/invoke.texi | 7 +++-
gcc/testsuite/g++.dg/modules/modules.exp | 40 ++++++++++++++++------
gcc/testsuite/g++.dg/modules/pr99023_a.X | 6 ++++
gcc/testsuite/g++.dg/modules/pr99023_b.X | 7 ++++
libcpp/files.c | 59 ++++++++++++++++++++++----------
libcpp/include/cpplib.h | 4 +--
libcpp/internal.h | 2 ++
libcpp/macro.c | 2 +-
9 files changed, 101 insertions(+), 48 deletions(-)
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 064e57a29c4..e801c52069e 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -19091,7 +19091,7 @@ canonicalize_header_name (cpp_reader *reader, location_t loc, bool unquoted,
buf[len] = 0;
if (const char *hdr
- = cpp_find_header_unit (reader, buf, str[-1] == '<', loc))
+ = cpp_probe_header_unit (reader, buf, str[-1] == '<', loc))
{
len = strlen (hdr);
str = hdr;
@@ -19185,19 +19185,11 @@ maybe_translate_include (cpp_reader *reader, line_maps *lmaps, location_t loc,
else if (note_include_translate_no && xlate == 0)
note = true;
else if (note_includes)
- {
- /* We do not expect the note_includes vector to be large, so O(N)
- iteration. */
- for (unsigned ix = note_includes->length (); !note && ix--;)
- {
- const char *hdr = (*note_includes)[ix];
- size_t hdr_len = strlen (hdr);
- if ((hdr_len == len
- || (hdr_len < len && IS_DIR_SEPARATOR (path[len - hdr_len - 1])))
- && !memcmp (hdr, path + len - hdr_len, hdr_len))
- note = true;
- }
- }
+ /* We do not expect the note_includes vector to be large, so O(N)
+ iteration. */
+ for (unsigned ix = note_includes->length (); !note && ix--;)
+ if (!strcmp ((*note_includes)[ix], path))
+ note = true;
if (note)
inform (loc, xlate
@@ -19570,7 +19562,7 @@ init_modules (cpp_reader *reader)
0, !delimed, hdr, len);
char *path = XNEWVEC (char, len + 1);
memcpy (path, hdr, len);
- path[len+1] = 0;
+ path[len] = 0;
(*note_includes)[ix] = path;
}
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e8baa545eee..c00514a6306 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -3382,7 +3382,12 @@ is used when building the C++ library.)
@itemx -flang-info-include-translate=@var{header}
@opindex flang-info-include-translate
@opindex flang-info-include-translate-not
-Diagnose include translation events.
+Diagnose include translation events. The first will note accepted
+include translations, the second will note declined include
+translations. The @var{header} form will inform of include
+translations relating to that specific header. If @var{header} is of
+the form @code{"user"} or @code{<system>} it will be resolved to a
+specific user or system header using the include path.
@item -stdlib=@var{libstdc++,libc++}
@opindex stdlib
diff --git a/gcc/testsuite/g++.dg/modules/modules.exp b/gcc/testsuite/g++.dg/modules/modules.exp
index c17120f2c00..38654caf7b9 100644
--- a/gcc/testsuite/g++.dg/modules/modules.exp
+++ b/gcc/testsuite/g++.dg/modules/modules.exp
@@ -39,6 +39,11 @@ set MOD_STD_LIST { 17 2a }
dg-init
+if {[is_remote host]} {
+ # remote testing not functional here :(
+ return
+}
+
global module_do
global module_cmis
@@ -274,6 +279,9 @@ proc module-init { src } {
return $option_list
}
+# cleanup any detritus from previous run
+cleanup_module_files [find $DEFAULT_REPO *.gcm]
+
# not grouped tests, sadly tcl doesn't have negated glob
foreach test [prune [lsort [find $srcdir/$subdir {*.[CH]}]] \
"$srcdir/$subdir/*_?.\[CH\]"] {
@@ -282,6 +290,7 @@ foreach test [prune [lsort [find $srcdir/$subdir {*.[CH]}]] \
set std_list [module-init $test]
foreach std $std_list {
+ global module_cmis
set module_cmis {}
verbose "Testing $nshort $std" 1
dg-test $test "$std" $DEFAULT_MODFLAGS
@@ -292,11 +301,11 @@ foreach test [prune [lsort [find $srcdir/$subdir {*.[CH]}]] \
}
# grouped tests
-foreach src [lsort [find $srcdir/$subdir {*_a.[CH}]] {
+foreach src [lsort [find $srcdir/$subdir {*_a.[CHX}]] {
# use the FOO_a.C name as the parallelization key
if [runtest_file_p $runtests $src] {
set tests [lsort [find [file dirname $src] \
- [regsub {_a.[CH]$} [file tail $src] {_[a-z].[CH]}]]]
+ [regsub {_a.[CHX]$} [file tail $src] {_[a-z].[CHX]}]]]
set std_list [module-init $src]
foreach std $std_list {
@@ -304,30 +313,39 @@ foreach src [lsort [find $srcdir/$subdir {*_a.[CH}]] {
global module_do
set module_do {"compile" "P"}
set asm_list {}
+ set any_hdrs 0
+ global DEFAULT_REPO
+ file_on_host delete $DEFAULT_REPO
foreach test $tests {
if { [lindex $module_do 1] != "N" } {
+ global module_cmis
set module_cmis {}
set nshort [file tail [file dirname $test]]/[file tail $test]
verbose "Testing $nshort $std" 1
- if { [file extension $test] == ".C" } {
- lappend asm_list [file rootname [file tail $test]].s
+ switch [file extension $test] {
+ ".C" {
+ lappend asm_list [file rootname [file tail $test]].s
+ }
+ ".X" {
+ set any_hdrs 1
+ }
}
dg-test -keep-output $test "$std" $DEFAULT_MODFLAGS
set testcase [string range $test [string length "$srcdir/"] end]
lappend mod_files [module_cmi_p $testcase $module_cmis]
}
}
- set ok 1
set testcase [regsub {_a.[CH]} $src {}]
set testcase \
[string range $testcase [string length "$srcdir/"] end]
- set ok [module_do_it $module_do $testcase $std $asm_list]
- if { $ok } {
- foreach asm $asm_list {
- file_on_host delete $asm
- }
- cleanup_module_files $mod_files
+ module_do_it $module_do $testcase $std $asm_list
+ foreach asm $asm_list {
+ file_on_host delete $asm
+ }
+ if { $any_hdrs } {
+ set mod_files [find $DEFAULT_REPO *.gcm]
}
+ cleanup_module_files $mod_files
}
}
}
diff --git a/gcc/testsuite/g++.dg/modules/pr99023_a.X b/gcc/testsuite/g++.dg/modules/pr99023_a.X
new file mode 100644
index 00000000000..c872d15f792
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99023_a.X
@@ -0,0 +1,6 @@
+// PR c++/99023, ICE
+// { dg-additional-options {-x c++-system-header initializer_list -fmodules-ts --param ggc-min-expand=0} }
+
+// { dg-prune-output {linker input file unused} }
+
+NO DO NOT COMPILE
diff --git a/gcc/testsuite/g++.dg/modules/pr99023_b.X b/gcc/testsuite/g++.dg/modules/pr99023_b.X
new file mode 100644
index 00000000000..3d82f34868b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99023_b.X
@@ -0,0 +1,7 @@
+// PR c++/99023, ICE
+// { dg-additional-options {-x c++-system-header iostream -fmodules-ts -flang-info-include-translate=<initializer_list> --param ggc-min-expand=0} }
+
+// { dg-prune-output {linker input file unused} }
+
+// { dg-regexp {[^\n]*: note: include '[^\n]*/initializer_list' translated to import\n} }
+NO DO NOT COMPILE
diff --git a/libcpp/files.c b/libcpp/files.c
index 3a35f7c9743..6e20fc5887f 100644
--- a/libcpp/files.c
+++ b/libcpp/files.c
@@ -1108,31 +1108,54 @@ _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. */
+/* NAME is a header file name, find the _cpp_file, if any. */
-const char *
-cpp_find_header_unit (cpp_reader *pfile, const char *name, bool angle,
- location_t loc)
+static _cpp_file *
+test_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;
+ if (cpp_dir *dir = search_path_head (pfile, name, angle, IT_INCLUDE))
+ return _cpp_find_file (pfile, name, dir, angle, _cpp_FFK_NORMAL, loc);
+
+ return nullptr;
+}
- _cpp_file *file = _cpp_find_file (pfile, name, dir, angle,
- _cpp_FFK_NORMAL, loc);
- if (!file)
- return NULL;
+/* NAME is a header file name, find the path we'll use to open it and infer that
+ it is a header-unit. */
- if (file->fd > 0)
+const char *
+_cpp_find_header_unit (cpp_reader *pfile, const char *name, bool angle,
+ location_t loc)
+{
+ if (_cpp_file *file = test_header_unit (pfile, name, angle, loc))
{
- /* Don't leave it open. */
- close (file->fd);
- file->fd = 0;
+ 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;
}
- file->header_unit = +1;
- _cpp_mark_file_once_only (pfile, file);
- return file->path;
+ return nullptr;
+}
+
+/* NAME is a header file name, find the path we'll use to open it. But do not
+ infer it is a header unit. */
+
+const char *
+cpp_probe_header_unit (cpp_reader *pfile, const char *name, bool angle,
+ location_t loc)
+{
+ if (_cpp_file *file = test_header_unit (pfile, name, angle, loc))
+ return file->path;
+
+ return nullptr;
}
/* Retrofit the just-entered main file asif it was an include. This
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 17feb648ebe..41d75d9e731 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -1012,8 +1012,8 @@ 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);
+extern const char *cpp_probe_header_unit (cpp_reader *, const char *file,
+ bool angle_p, location_t);
/* Call these to get name data about the various compile-time
charsets. */
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 32f9f508562..fd44de6b8f0 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -703,6 +703,8 @@ extern _cpp_file *_cpp_find_file (cpp_reader *, const char *, cpp_dir *,
int angle, _cpp_find_file_kind, location_t);
extern bool _cpp_find_failed (_cpp_file *);
extern void _cpp_mark_file_once_only (cpp_reader *, struct _cpp_file *);
+extern const char *_cpp_find_header_unit (cpp_reader *, const char *file,
+ bool angle_p, location_t);
extern void _cpp_fake_include (cpp_reader *, const char *);
extern bool _cpp_stack_file (cpp_reader *, _cpp_file*, include_type, location_t);
extern bool _cpp_stack_include (cpp_reader *, const char *, int,
diff --git a/libcpp/macro.c b/libcpp/macro.c
index fa6acfff771..dff7c98a4df 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -3010,7 +3010,7 @@ cpp_get_token_1 (cpp_reader *pfile, location_t *location)
if (need_search)
{
- found = cpp_find_header_unit (pfile, fname, angle, tmp->src_loc);
+ found = _cpp_find_header_unit (pfile, fname, angle, tmp->src_loc);
if (!found)
found = "";
len = strlen (found);
More information about the Gcc-cvs
mailing list