[Bug c++/125230] [modules] #include transformed into import
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125230 Nathaniel Shead changed: What|Removed |Added See Also||https://gcc.gnu.org/bugzill ||a/show_bug.cgi?id=101126 CC||nshead at gcc dot gnu.org --- Comment #11 from Nathaniel Shead --- (In reply to Rainer Deyke from comment #8) > Consensus at [email protected] seems to be that the set of > "importable headers" is meant to be a finite closed set of > implementation-provided headers that does not include user-provided headers. > a.hpp in my example is not supposed to be an "importable header". Importing > it should not turn it into an importable header. Precompiling it should not > turn it into turn it into an "importable header". An #include of this > header be turned into an import. The actual issue here is PR101126; we don't support precompiled headers with modules currently. When you compile a header with modules support enabled, you are promising the compiler that this is an importable header and are building a CMI for it. The default module mapper (for simple command-line usage, not really intended for proper build systems) then assumes that any header it can see that's been built is a valid importable header. If you choose to instead use a custom module mapper you can indicate which headers are intended to be importable (and thus should undergo include translation) and which are not. See also https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Module-Preprocessing.html: > Include translation converts #include, #include_next and #import directives > to internal import declarations. Whether a particular directive is translated > is controlled by the module mapper. The mapper protocol itself is described in https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Module-Mapper.html and https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1184r2.pdf; see section 4.9 of the latter to determine whether given headers are meant to be part of the importable header list or not.
[Bug c++/125230] [modules] #include transformed into import
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125230 --- Comment #10 from Jonathan Wakely --- I don't think we want the compiler to notice whether a header depends on any macros, and then mark it for not being translated to import (either unconditionally or if those macros are defined). 99.999% of headers depend on macros (of nothing else, the include guard at the very top of the header!) and many depend on macros which are routinely defined, such as: #ifdef __linux__ #ifdef __cpp_concepts We don't want to make a header non-importable just because it uses #ifdef anywhere in the header. Recording _which_ macros a header depends on and testing that all of them have the same definition before doing include translation would work but I'm not sure how well it would scale.
[Bug c++/125230] [modules] #include transformed into import
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125230 --- Comment #9 from Jonathan Wakely --- I think GCC's rationale is that you explicitly compiled the header into a header unit. That part wasn't done silently, you did it. If you tell GCC that a.hpp can be imported as a header unit, it will assume it can be imported as a header unit. Maybe what we need is an option that turns off include translation, either for the whole file or for specific headers, so you could still compile a.hpp as a header unit, but compile b.cpp with -fno-include-translation or -fno-include-translation=a.hpp
[Bug c++/125230] [modules] #include transformed into import
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125230 Rainer Deyke changed: What|Removed |Added Resolution|INVALID |--- Status|RESOLVED|UNCONFIRMED --- Comment #8 from Rainer Deyke --- Consensus at [email protected] seems to be that the set of "importable headers" is meant to be a finite closed set of implementation-provided headers that does not include user-provided headers. a.hpp in my example is not supposed to be an "importable header". Importing it should not turn it into an importable header. Precompiling it should not turn it into turn it into an "importable header". An #include of this header be turned into an import. I concede that the language of the standard is ambiguous, but this is not "exactly how c++20 modules are supposed to work".
[Bug c++/125230] [modules] #include transformed into import
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125230 --- Comment #7 from Rainer Deyke --- (In reply to Jonathan Wakely from comment #6) > (In reply to Rainer Deyke from comment #5) > > This is problematic because "importable header" is never defined. It can > > reasonably mean "any header" in a compiler that compiles header units on > > demand, in which case my header-only library cannot work at all. I believe > > this is a defect in the standard. > > It's defined in 10.3 [module.import] paragraph 5: > > "An importable header is a member of an implementation-defined set of > headers that includes all importable C++ library headers (16.4.2.3)." > > And 16.4.2.3 [headers] p2 says: > > "The headers listed in Table 24, or, for a freestanding implementation, the > subset of such headers that are provided by the implementation, are > collectively known as the importable C ++ library headers." That just confirms my point: the set of importable headers is implementation-defined (i.e. not defined by the standard). It is permitted for an implementation to treat all headers as importable headers. Therefore an implementation is allowed to turn all #includes into imports. Therefore any idiom that uses macros to pass information from a C++ source file to a header is no longer standard-conforming, even if #include is used exclusively.
[Bug c++/125230] [modules] #include transformed into import
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125230 --- Comment #6 from Jonathan Wakely --- (In reply to Rainer Deyke from comment #5) > This is problematic because "importable header" is never defined. It can > reasonably mean "any header" in a compiler that compiles header units on > demand, in which case my header-only library cannot work at all. I believe > this is a defect in the standard. It's defined in 10.3 [module.import] paragraph 5: "An importable header is a member of an implementation-defined set of headers that includes all importable C++ library headers (16.4.2.3)." And 16.4.2.3 [headers] p2 says: "The headers listed in Table 24, or, for a freestanding implementation, the subset of such headers that are provided by the implementation, are collectively known as the importable C ++ library headers."
[Bug c++/125230] [modules] #include transformed into import
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125230 --- Comment #5 from Rainer Deyke --- (In reply to Drea Pinski from comment #3) > https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Modules.html I don't see any text in the link that suggests that #includes in general are translated into imports. The closest I see is this statement: But for the standard library in particular this is unnecessary: if a header unit has been built for the libstdc++ ‘bits/stdc++.h’ header, the compiler will translate an ‘#include’ of any importable standard library header into an import of that header unit, speeding up compilation without needing to specify ‘-include’. Note that the ‘bits/stdc++.h’ header unit is also built by the --compile-std-module option. But that statement is specifically about the standard library, and does not suggest that the same translation happens to other #includes. > But this is exactly how c++20 modules are supposed to work. Checking on https://cppreference.com/cpp/preprocessor/include, I see that this behavior is in fact standard-compliant, but not mandated. The exact text is this: If the header identified by the header-name (i.e., < h-char-sequence > or " q-char-sequence ") denotes an importable header, it is implementation-defined whether the #include preprocessing directive is instead replaced by an import directive of the form import header-name ; new-line This is problematic because "importable header" is never defined. It can reasonably mean "any header" in a compiler that compiles header units on demand, in which case my header-only library cannot work at all. I believe this is a defect in the standard. Anyway, given that this is standard-conformant behaviors, it's also not difficult to work around. a-indirect.hpp: #include "a.hpp" b.cpp: #define A_IMPL #include "a.hpp" c.cpp: import "a-indirect.hpp" c.cpp:
[Bug c++/125230] [modules] #include transformed into import
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125230 --- Comment #4 from Drea Pinski --- Also read https://isocpp.org/files/papers/D2654R0.html
[Bug c++/125230] [modules] #include transformed into import
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125230 --- Comment #3 from Drea Pinski --- https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Modules.html Has part of this documented for gcc. But this is exactly how c++20 modules are supposed to work.
[Bug c++/125230] [modules] #include transformed into import
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125230 Drea Pinski changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #2 from Drea Pinski --- > This may be a clever optimization in some cases, but I believe it is not > standard-conforming and it breaks real code. No it is how c++20 modules work.
[Bug c++/125230] [modules] #include transformed into import
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125230 --- Comment #1 from Rainer Deyke --- (In reply to Rainer Deyke from comment #0) > b.ii: > # 0 "b.cpp" > # 0 "" > # 0 "" > # 1 "/usr/include/stdc-predef.h" 1 3 > # 0 "" 2 > # 1 "b.cpp" It seems the relevant line was cut off: import "./a.hpp" [[__translated]];
