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.
This commit is contained in:
parent
d82f829905
commit
1f9db6929d
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
6
gcc/testsuite/g++.dg/modules/pr99023_a.X
Normal file
6
gcc/testsuite/g++.dg/modules/pr99023_a.X
Normal file
@ -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
|
7
gcc/testsuite/g++.dg/modules/pr99023_b.X
Normal file
7
gcc/testsuite/g++.dg/modules/pr99023_b.X
Normal file
@ -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
|
@ -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. */
|
||||
|
||||
static _cpp_file *
|
||||
test_header_unit (cpp_reader *pfile, const char *name, bool angle,
|
||||
location_t loc)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* NAME is a header file name, find the path we'll use to open it and infer that
|
||||
it is a header-unit. */
|
||||
|
||||
const char *
|
||||
cpp_find_header_unit (cpp_reader *pfile, const char *name, bool angle,
|
||||
location_t loc)
|
||||
_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)
|
||||
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
|
||||
|
@ -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. */
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user