<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Oct 2, 2014 at 7:21 AM, Seth Cantrell <span dir="ltr"><<a href="mailto:seth.cantrell@gmail.com" target="_blank">seth.cantrell@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><span class=""><div>On Oct 2, 2014, at 1:12 AM, Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>> wrote:</div><br></span><blockquote type="cite"><div style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class="">On Wed, Oct 1, 2014 at 7:54 PM, Seth Cantrell<span> </span><span dir="ltr"><<a href="mailto:seth.cantrell@gmail.com" target="_blank">seth.cantrell@gmail.com</a>></span><span> </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">With C++ modules being far enough along to be included in -fmodules now I tried enabling -fmodules on a small C++ program I have laying around. I was impressed that it almost all worked right away.<br><br>Here's the issue I ran into with one header:<br><br><br>glcorearb.h:616:1: error: import of C++ module 'Darwin.C.stddef' appears within extern "C" language linkage specification<br>#include <stddef.h><br>^<br>glcorearb.h:5:1: note: extern "C" language linkage specification begins here<br>extern "C" {<br>^<br>glcorearb.h:1517:1: error: import of C++ module 'Darwin.C.inttypes' appears within extern "C" language linkage specification<br>#include <inttypes.h><br>^<br>glcorearb.h:5:1: note: extern "C" language linkage specification begins here<br>extern "C" {<br>^<br><br><br>Even without modules it seems like people should be taking care not #include a header in a context that may not be compatible with the content of those headers. Here we are building C++ and stddef.h and inttypes.h are therefore C++ headers that might not work in an extern "C" context. Platforms owners, who are in control of both the including file and the included file can legitimately do this, but I don't think this is good practice when included someone else's header. However the standards don't clearly disallow this</blockquote><div><br></div><div>C++ absolutely does disallow it for its own headers (which include <stddef.h> and <inttypes.h>):</div><div><br></div></span><div>[using.headers]p3: "A translation unit shall include a header only outside of any external declaration or definition, and shall include the header lexically before the first reference in that translation unit to any of the entities declared in that header. No diagnostic is required.”</div></div></div></div></div></blockquote><div><br></div>Oh, excellent. That means I can report it to the header’s devs as a bug with a nice standards quote. Thanks.</div><span class=""><div><br></div><div><br><blockquote type="cite"><div style="font-family:Menlo-Regular;font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><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">and I have certainly seen circumstances where people recommended extern "C" { #include <system header> } for various reasons.<br><br>In this specific case it's not even deliberate as far as I can tell, but it's worked and so no one's bothered to fix it here. A quick hack to remove these #includes from extern "C" solved the issue for me.<br><br>Anyway, I checked<span> </span><a href="http://clang.llvm.org/docs/Modules.html#modularizing-a-platform" target="_blank">http://clang.llvm.org/docs/Modules.html#modularizing-a-platform</a><span> </span>but didn't notice any recommendations that apply here. So what should be recommended? Is this an 'anti-pattern' for modules? An anti-pattern for 'well organized' non-module headers? Should modules be able to coexist with these kinds of shenanigans when the code worked fine pre-modules? Should I contact the developers of this header and recommend a change? (It's an automatically generated header from gl3w.)</blockquote><div><br></div><div>See<span> </span><a href="http://clang.llvm.org/docs/Modules.html#module-declaration" target="_blank">http://clang.llvm.org/docs/Modules.html#module-declaration</a><span> </span>and in particular the description of the [extern_c] attribute. By default, a module that can be used in C++ can only be used at global scope (outside of all namespaces and language linkage specifications). This attribute says that the module provides a C interface to C++ code, and thus:</div><div>1) The module is built surrounded by an implicit extern "C" context, and</div><div>2) The module can be imported within a top-level extern "C" linkage specification.</div><div><br></div><div>This attribute should typically be applied to modules whose headers contain the</div><div><br></div><div>#ifdef __cplusplus</div><div>extern "C" {</div><div>#endif</div><div>// ...</div><div>#ifdef __cplusplus</div><div>}</div><div>#endif</div><div><br></div><div>pattern. Depending on your platform, it may or may not make sense to use the [extern_c] on your libc module; Darwin's doesn't (probably because its module map predates this attribute) but my glibc module map does.</div></div></div></div></div></blockquote></div><br></span><div>Would it make sense for the compiler, in the interest of backwards compatibility, to just go ahead and import a module ignoring the fact that it’s imported in an extern “C” context?</div></div></blockquote><div><br></div><div>That breaks things. Suppose you have a C header that does *not* include the above conditional 'extern "C" {' shenanigans. From C++ code, you'd use that library like this:</div><div><br></div><div>extern "C" {</div><div>  #include "that_library.h"</div><div>}</div><div><br></div><div>If you supply a module map for that library and you add neither 'requires !cplusplus' nor '[extern_c]', *and* we follow your suggestion, then we'd build that_library.h has a non-extern-C C++ header file, which will lead to weird link errors.</div><div><br></div><div>And we can't link the implicit "extern "C" { ... }" to the 'requires' line because there are also libraries that provide a richer interface when included from C++ (they don't just wrap everything in extern "C" themselves). The best option here seems to be to require module maps to explicitly specify this property.</div></div></div></div>