https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127097
Bug ID: 127097
Summary: [modules] Alternate include of a header unit reads
stdin
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: alexey.klimkin at intel dot com
Target Milestone: ---
When a C++ header unit is imported and the same physical header is later
included textually through an alternate pathname, GCC reads from file
descriptor 0 instead of reopening the source header. This produces a misleading
"file is shorter than expected" warning followed by duplicate definition
errors.
The problem is in libcpp/files.cc::_cpp_find_header_unit. It closes the header
source descriptor and records file->fd = 0, but read_file uses -1 as the
closed-descriptor sentinel when deciding whether to reopen a file. A later
alternate-path include therefore skips reopening the source and passes
descriptor 0 to read, consuming stdin. The file->fd > 0 close condition also
fails when opening the header legitimately returns descriptor 0.
Reproducer
==========
Create an existing directory for the alternate path:
mkdir sys
header.H:
#pragma once
inline int f()
{
return 1;
}
use.C:
import "header.H";
#include "sys/../header.H"
int main()
{
return f() != 1;
}
Build:
g++ -std=c++20 -fmodule-header -c header.H
g++ -std=c++20 -fmodules -c use.C
Actual result
=============
use.C:2:10: warning: header.H is shorter than expected
header.H:3:12: error: redefinition of 'int f()'
Expected result
===============
The alternate spelling should be recognized as the already-imported, once-only
header. Compilation should succeed without reading stdin or processing the
header twice.
Proposed fix
============
Close every valid descriptor (file->fd != -1) and restore the established
closed sentinel:
close (file->fd);
file->fd = -1;
A regression test imports a header unit and then includes it through an
alternate sys/../ spelling. It fails on unpatched trunk and compiles, links,
and runs after the fix.