<div dir="ltr">This is related to how clang's modules are implemented. Every top level module is basically turned into a PCH containing all headers within it (including submodules; except those excluded by `requires`). The "submodules" are just name hiding trickery on top of the PCH. So inherently all the files within a top-level module come in at the same time.<div><br></div><div>Clang internally generates a text file containing a #include of all the files listed in the top level module, then effectively compiles that into a PCH (and some extra modules-specific information so that it can do the name hiding trickery and other stuff). See `addHeaderInclude` and its callsites in lib/Frontend/FrontendActions.cpp</div><div><br></div><div>When a submodule is imported, clang basically imports the entire PCH, then hides names that are not supposed to be visible based on the submodule structure.</div><div><br></div><div>Inside clang, have an ever-expanding set of workarounds to this fundamental reality, so it seems in line with that to add another workaround to remedy this undesirable behavior. Richard, what do you think? It sounds like IRGen just needs to gain some awareness of where the globals are coming from; something like "only emit a global if it is in the transitive closure of headers reachable from the submodules that were imported by the TU" (probably needs some finessing surrounding when a submodule doesn't `export *`).<div><div><br></div><div>-- Sean Silva<br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Dec 11, 2015 at 4:55 PM, Srivastava, Sunil via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">





<div lang="EN-US" link="#0563C1" vlink="#954F72">
<div>
<p class="MsoNormal">Hi All,<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">I am seeing something unexpected with –fmodules. Is this intentional ?<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">If I include a file of one submodule, I see code for static initialization for global
<u></u><u></u></p>
<p class="MsoNormal">variables of files of other submodules of the same parent module.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">To take a standalone example, make a directory “HDR” with three files “A.h”, “B.h” and
<u></u><u></u></p>
<p class="MsoNormal">“module.modulemap” with the following contents: <u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">A.h: <u></u><u></u></p>
<p class="MsoNormal">    struct AA { AA();};<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">B.h:<u></u><u></u></p>
<p class="MsoNormal">    struct counter {<u></u><u></u></p>
<p class="MsoNormal">      int v;<u></u><u></u></p>
<p class="MsoNormal">      counter() { v = 0; }<u></u><u></u></p>
<p class="MsoNormal">    };<u></u><u></u></p>
<p class="MsoNormal">    const counter junk;<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">module.modulemap:<u></u><u></u></p>
<p class="MsoNormal">   module TOP {<u></u><u></u></p>
<p class="MsoNormal">      module A {<u></u><u></u></p>
<p class="MsoNormal">        header "A.h"<u></u><u></u></p>
<p class="MsoNormal">        export *<u></u><u></u></p>
<p class="MsoNormal">      }<u></u><u></u></p>
<p class="MsoNormal">      module B {<u></u><u></u></p>
<p class="MsoNormal">        header "B.h"<u></u><u></u></p>
<p class="MsoNormal">        export *<u></u><u></u></p>
<p class="MsoNormal">      }<u></u><u></u></p>
<p class="MsoNormal">    }<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Now take a main file, test.cpp, with just one line<u></u><u></u></p>
<p class="MsoNormal">    #include <A.h><u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">and compile it with ‘clang –S –fmodules –IHDR test.cpp’<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Since there are no object definitions in A.h, one would expect an empty file. But
<u></u><u></u></p>
<p class="MsoNormal">we see code for static initialization of ‘junk’. <u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">So the question: Why is ‘junk’ being initialized in test.s ?<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">If modules A and B are not nested in another module "TOP", then this initialization
<u></u><u></u></p>
<p class="MsoNormal">does not occur. However, even with this nesting, why should module TOP.B be initialized<u></u><u></u></p>
<p class="MsoNormal">when only A.h is being included?<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Without –fmodules, we get an effectively empty file, as expected.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">I realize that putting a definition (of junk) in an include file is not a good idea,
<u></u><u></u></p>
<p class="MsoNormal">still, I am not using that include file. Why should I be penalized for files that I am<u></u><u></u></p>
<p class="MsoNormal">not using.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Note that with the test case above, even if I include <A.h> (or even <B.h>) in multiple files,
<u></u><u></u></p>
<p class="MsoNormal">no multiple definition error occurs because the variable definition is a const. The only cost
<u></u><u></u></p>
<p class="MsoNormal">of -fmodules is some extra initialization code, though with multiple instances of this<u></u><u></u></p>
<p class="MsoNormal">phenomenon it can become significant.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Now, if the variable definition is made non-const, -fmodules prevents me from including <A.h>
<u></u><u></u></p>
<p class="MsoNormal">in multiple translation units. The poor-programming-practice in <B.h> prevents inclusion
<u></u><u></u></p>
<p class="MsoNormal">of <A.h> in multiple TUs. That is much more serious than just some extra code.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">I have tested this with current TOT on Linux x86. The module cache was empty before doing
<u></u><u></u></p>
<p class="MsoNormal">the compilation in these tests.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Thanks<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Sunil Srivastava<u></u><u></u></p>
<p class="MsoNormal">Sony Computer Entertainment<u></u><u></u></p>
</div>
</div>

<br>_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
<br></blockquote></div><br></div></div></div></div></div>