Yes, we perfectly model the preprocessor state as it pertains to dependencies. Currently this is done by actually building a header unit that is empty except for the exported macros and then importing that, but it's possible to do this directly.
The only issue is if you want to automatically detect `importable header`s by seeing `import <header>;`. This is simply not possible with the module mapper. With scanning it's possible, but has some issues. It would either need to be done at the start of phase 4 (ignoring preprocessor directives and expansion), or be done in multiple passes with some way of resolving cycles (technically it's possible for an `import <foo.h>` to depend on the content of a previous `#include <foo.h>` and whether or not include translation is done).
My preference here is to do this optimistically at the start of phase 4 on a per TU (treating importable units independently) basis. This means that in the following main.cpp would do include translation on <foo.h>, but not on <bar.h>:
/// bar.h
# // Doesn't matter
/// foo.h
#ifdef BAR
#define FOO
#endif
/// main.cpp
It also means a separate translation unit may not treat <foo.h> as importable, but that's ok and allowed by the standard.
In general I think we'll still need explicit lists of importable headers, but implicitly assuming `import <header.h>` makes the header importable and doing include translation will work in practice as the above code should be incredibly rare.
[Switched to the new SG15 mailing list.]
Michael Spencer <bigcheesegs@gmail.com> writes:
> On Fri, Apr 15, 2022 at 5:42 AM Boris Kolpackov via Ext <
>
> > Sure, module mapper approach is not without its complications (I
> > even wrote a paper on this). But so far the only proposed alternative
> > is to pre-scan the world, which doesn't feel scalable (and, as you
> > know, I have doubts it can be implemented correctly for header units).
> >
>
> We have already deployed this for Clang modules. I don't see anything about
> header units that would make our approach invalid.
Do you provide the macro isolation semantics for header units during
the scan (not sure if it applies to Clang modules)? Here is a C++20
modules example that illustrates the problem:
// file: header-unit.hpp
//
#ifdef BAR
#define FOO
#endif
// file: importer.cpp
//
#define BAR
import "header-unit.hpp"; // Should not "see" BAR.
//#include "header-unit.hpp" // Should "see" BAR.
#ifdef FOO
import "header-unit2.hpp";
#endif