<div dir="ltr"><div dir="ltr">On Thu, 17 Oct 2019 at 03:16, Boris Kolpackov via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">In build2 we scan a preprocessed TU in order to discover named modules<br>
that are needed to compile said TU. Clang, however, tries to load named<br>
modules during preprocessing, because, I believe, Clang's module map-<br>
based modules can also be named and such modules can export macros. This<br>
poses a problem for build systems that are only attempting to support<br>
C++20 modules.<br>
<br>
Prior to Clang 9 we hacked around this by simply not enabling (i.e., not<br>
passing -fmodules-ts) modules during preprocessing. However, starting<br>
with Clang 9, modules are enabled by default in the c++2a mode[1] and<br>
there doesn't seem to be a way to disable them. Plus, disabling them is<br>
really a hack rather than a solution: for example, it will fall apart<br>
once we try to support header units (e.g., via the module mapper).<br>
<br>
I would therefore like to propose a "strict" C++20 modules mode either<br>
as a default or as an opt-in. Another approach (suggested by Richard<br>
in private communication) is to try to load such a module but to not<br>
fail if it doesn't exist.</blockquote><div><br></div><div>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).</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I see two issues with this approach:<br>
<br>
1. It would be hard to distinguish intentional and unintentional<br>
"absence" of a BMI.<br>
<br>
2. More importantly, the BMI might exist but be out of date.<br></blockquote><div><br></div><div>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.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
On the other hand, the strict mode sounds like a fairly simple solution<br>
(but I am happy to explore Richard's suggestion if this is preferred).<br></blockquote><div><br></div><div>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.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
I've done a quick survey of the modules-related options and modes in<br>
Clang. Options:<br>
<br>
-f[no-]modules # Enable/Disable Clang modules.<br>
-f[no-]cxx-modules # Enable/Disable Clang modules in C++ TUs.<br>
-fmodules-ts # Enable Modules TS.<br>
-std=c++2a # Enables C++20 modules.<br>
<br>
LangOpts:<br>
<br>
CPlusPlusModules<br>
ModulesTS<br>
Modules<br>
<br>
The current mapping of the options to LangOpts is best captured by this<br>
fragment from lib/Frontend/CompilerInvocation.cpp[2]:<br>
<br>
Opts.CPlusPlusModules = Opts.CPlusPlus2a;<br>
Opts.ModulesTS = Args.hasArg(OPT_fmodules_ts);<br>
Opts.Modules =<br>
Args.hasArg(OPT_fmodules) || Opts.ModulesTS || Opts.CPlusPlusModules;<br>
<br>
To support strict C++20 modules at the LangOpts level, it seems natural<br>
to introduce ClangModules (there is already a precedent in<br>
lib/Driver/ToolChains/Clang.cpp:RenderModuleOptions()[3]) with the<br>
following basic semantics:<br>
<br>
Opts.ClangModules = Args.hasArg(OPT_fmodules);<br>
Opts.Modules = Opts.ClangModules || Opts.ModulesTS || Opts.CPlusPlusModules;<br>
<br>
At the options level, the approach depends on whether we want the default<br>
to be strict or if we want to make it opt-in. If it's strict by default,<br>
then using -fmodules in addition to -std=c++2a seems like a natural way to<br>
additionally request the Clang modules semantics. If we want it as opt-in,<br>
then -fno-modules again in combination with -std=c++2a seems natural (in<br>
fact, I was surprised that neither -fno-modules nor -fno-cxx-modules had<br>
any effect when -std=c++2a was specified).<br>
<br>
To me personally, strict by default seems cleaner (the Clang modules<br>
semantics would have been more appropriate for something like<br>
-std=clang++2a). But I am also ok with opt-in.<br>
<br>
What do you thinks? If this sounds sensible, I can come up with a patch.<br>
<br>
[1] <a href="https://github.com/llvm-mirror/clang/commit/cab7f1f7bc141ac88d15030088b311bd450b2c94" rel="noreferrer" target="_blank">https://github.com/llvm-mirror/clang/commit/cab7f1f7bc141ac88d15030088b311bd450b2c94</a><br>
[2] <a href="https://github.com/llvm-mirror/clang/blob/master/lib/Frontend/CompilerInvocation.cpp#L2754" rel="noreferrer" target="_blank">https://github.com/llvm-mirror/clang/blob/master/lib/Frontend/CompilerInvocation.cpp#L2754</a><br>
[3] <a href="https://github.com/llvm-mirror/clang/blob/master/lib/Driver/ToolChains/Clang.cpp#L2698" rel="noreferrer" target="_blank">https://github.com/llvm-mirror/clang/blob/master/lib/Driver/ToolChains/Clang.cpp#L2698</a><br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div></div>