Date: Thu, 12 May 2022 14:06:16 -0600
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
#define BAR <bar.h>
#include BAR
import BAR;
#include <foo.h>
#ifndef FOO
import <foo.h>;
#endif
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.
- Michael Spencer
On Wed, May 11, 2022 at 9:44 PM Boris Kolpackov <boris_at_[hidden]>
wrote:
> [Switched to the new SG15 mailing list.]
>
> Michael Spencer <bigcheesegs_at_[hidden]> 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
>
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
#define BAR <bar.h>
#include BAR
import BAR;
#include <foo.h>
#ifndef FOO
import <foo.h>;
#endif
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.
- Michael Spencer
On Wed, May 11, 2022 at 9:44 PM Boris Kolpackov <boris_at_[hidden]>
wrote:
> [Switched to the new SG15 mailing list.]
>
> Michael Spencer <bigcheesegs_at_[hidden]> 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
>
Received on 2022-05-12 20:06:30