Loading of named modules during preprocessing in c++2a

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Loading of named modules during preprocessing in c++2a

Kristof Beyls via cfe-dev
In build2 we scan a preprocessed TU in order to discover named modules
that are needed to compile said TU. Clang, however, tries to load named
modules during preprocessing, because, I believe, Clang's module map-
based modules can also be named and such modules can export macros. This
poses a problem for build systems that are only attempting to support
C++20 modules.

Prior to Clang 9 we hacked around this by simply not enabling (i.e., not
passing -fmodules-ts) modules during preprocessing. However, starting
with Clang 9, modules are enabled by default in the c++2a mode[1] and
there doesn't seem to be a way to disable them. Plus, disabling them is
really a hack rather than a solution: for example, it will fall apart
once we try to support header units (e.g., via the module mapper).

I would therefore like to propose a "strict" C++20 modules mode either
as a default or as an opt-in. Another approach (suggested by Richard
in private communication) is to try to load such a module but to not
fail if it doesn't exist. I see two issues with this approach:

1. It would be hard to distinguish intentional and unintentional
   "absence" of a BMI.

2. More importantly, the BMI might exist but be out of date.

On the other hand, the strict mode sounds like a fairly simple solution
(but I am happy to explore Richard's suggestion if this is preferred).

I've done a quick survey of the modules-related options and modes in
Clang. Options:

  -f[no-]modules      # Enable/Disable Clang modules.
  -f[no-]cxx-modules  # Enable/Disable Clang modules in C++ TUs.
  -fmodules-ts        # Enable Modules TS.
  -std=c++2a          # Enables C++20 modules.

LangOpts:

  CPlusPlusModules
  ModulesTS
  Modules

The current mapping of the options to LangOpts is best captured by this
fragment from lib/Frontend/CompilerInvocation.cpp[2]:

  Opts.CPlusPlusModules = Opts.CPlusPlus2a;
  Opts.ModulesTS = Args.hasArg(OPT_fmodules_ts);
  Opts.Modules =
    Args.hasArg(OPT_fmodules) || Opts.ModulesTS || Opts.CPlusPlusModules;

To support strict C++20 modules at the LangOpts level, it seems natural
to introduce ClangModules (there is already a precedent in
lib/Driver/ToolChains/Clang.cpp:RenderModuleOptions()[3]) with the
following basic semantics:

  Opts.ClangModules = Args.hasArg(OPT_fmodules);
  Opts.Modules = Opts.ClangModules || Opts.ModulesTS || Opts.CPlusPlusModules;

At the options level, the approach depends on whether we want the default
to be strict or if we want to make it opt-in. If it's strict by default,
then using -fmodules in addition to -std=c++2a seems like a natural way to
additionally request the Clang modules semantics. If we want it as opt-in,
then -fno-modules again in combination with -std=c++2a seems natural (in
fact, I was surprised that neither -fno-modules nor -fno-cxx-modules had
any effect when -std=c++2a was specified).

To me personally, strict by default seems cleaner (the Clang modules
semantics would have been more appropriate for something like
-std=clang++2a). But I am also ok with opt-in.

What do you thinks? If this sounds sensible, I can come up with a patch.

[1] https://github.com/llvm-mirror/clang/commit/cab7f1f7bc141ac88d15030088b311bd450b2c94
[2] https://github.com/llvm-mirror/clang/blob/master/lib/Frontend/CompilerInvocation.cpp#L2754
[3] https://github.com/llvm-mirror/clang/blob/master/lib/Driver/ToolChains/Clang.cpp#L2698
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Loading of named modules during preprocessing in c++2a

Kristof Beyls via cfe-dev
On Thu, 17 Oct 2019 at 03:16, Boris Kolpackov via cfe-dev <[hidden email]> wrote:
In build2 we scan a preprocessed TU in order to discover named modules
that are needed to compile said TU. Clang, however, tries to load named
modules during preprocessing, because, I believe, Clang's module map-
based modules can also be named and such modules can export macros. This
poses a problem for build systems that are only attempting to support
C++20 modules.

Prior to Clang 9 we hacked around this by simply not enabling (i.e., not
passing -fmodules-ts) modules during preprocessing. However, starting
with Clang 9, modules are enabled by default in the c++2a mode[1] and
there doesn't seem to be a way to disable them. Plus, disabling them is
really a hack rather than a solution: for example, it will fall apart
once we try to support header units (e.g., via the module mapper).

I would therefore like to propose a "strict" C++20 modules mode either
as a default or as an opt-in. Another approach (suggested by Richard
in private communication) is to try to load such a module but to not
fail if it doesn't exist.

Well, approximately. What I intended to suggest was: perform normal module name lookup, and then only try to load (or implicitly build) the module if the lookup succeeds and we find the module name was declared in a module map file (or slightly more broadly, that it names a header module rather than a module interface unit).

I see two issues with this approach:

1. It would be hard to distinguish intentional and unintentional
   "absence" of a BMI.

2. More importantly, the BMI might exist but be out of date.

For the alternative suggestion of checking whether there's a module map file describing the module (rather than whether there's a BMI), I think these aren't the right concerns. There is nonetheless a possibility that (in a misconfigured preprocessing step) the module name lookup could fail when preprocessing but succeed when compiling. But I don't think that's a major problem, and we can't avoid the possibility that the preprocessing step is misconfigured.

On the other hand, the strict mode sounds like a fairly simple solution
(but I am happy to explore Richard's suggestion if this is preferred).

It's simple, but it provides less functionality and comes at the cost of an extra configuration switch. I would prefer to not take that option if we can avoid it.
 
I've done a quick survey of the modules-related options and modes in
Clang. Options:

  -f[no-]modules      # Enable/Disable Clang modules.
  -f[no-]cxx-modules  # Enable/Disable Clang modules in C++ TUs.
  -fmodules-ts        # Enable Modules TS.
  -std=c++2a          # Enables C++20 modules.

LangOpts:

  CPlusPlusModules
  ModulesTS
  Modules

The current mapping of the options to LangOpts is best captured by this
fragment from lib/Frontend/CompilerInvocation.cpp[2]:

  Opts.CPlusPlusModules = Opts.CPlusPlus2a;
  Opts.ModulesTS = Args.hasArg(OPT_fmodules_ts);
  Opts.Modules =
    Args.hasArg(OPT_fmodules) || Opts.ModulesTS || Opts.CPlusPlusModules;

To support strict C++20 modules at the LangOpts level, it seems natural
to introduce ClangModules (there is already a precedent in
lib/Driver/ToolChains/Clang.cpp:RenderModuleOptions()[3]) with the
following basic semantics:

  Opts.ClangModules = Args.hasArg(OPT_fmodules);
  Opts.Modules = Opts.ClangModules || Opts.ModulesTS || Opts.CPlusPlusModules;

At the options level, the approach depends on whether we want the default
to be strict or if we want to make it opt-in. If it's strict by default,
then using -fmodules in addition to -std=c++2a seems like a natural way to
additionally request the Clang modules semantics. If we want it as opt-in,
then -fno-modules again in combination with -std=c++2a seems natural (in
fact, I was surprised that neither -fno-modules nor -fno-cxx-modules had
any effect when -std=c++2a was specified).

To me personally, strict by default seems cleaner (the Clang modules
semantics would have been more appropriate for something like
-std=clang++2a). But I am also ok with opt-in.

What do you thinks? If this sounds sensible, I can come up with a patch.

[1] https://github.com/llvm-mirror/clang/commit/cab7f1f7bc141ac88d15030088b311bd450b2c94
[2] https://github.com/llvm-mirror/clang/blob/master/lib/Frontend/CompilerInvocation.cpp#L2754
[3] https://github.com/llvm-mirror/clang/blob/master/lib/Driver/ToolChains/Clang.cpp#L2698
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev