[cfe-dev] C++ modules imported in extern "C"

Richard Smith richard at metafoo.co.uk
Wed Oct 1 22:12:00 PDT 2014


On Wed, Oct 1, 2014 at 7:54 PM, Seth Cantrell <seth.cantrell at gmail.com>
wrote:

> 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.
>
> Here's the issue I ran into with one header:
>
>
> glcorearb.h:616:1: error: import of C++ module 'Darwin.C.stddef' appears
> within extern "C" language linkage specification
> #include <stddef.h>
> ^
> glcorearb.h:5:1: note: extern "C" language linkage specification begins
> here
> extern "C" {
> ^
> glcorearb.h:1517:1: error: import of C++ module 'Darwin.C.inttypes'
> appears within extern "C" language linkage specification
> #include <inttypes.h>
> ^
> glcorearb.h:5:1: note: extern "C" language linkage specification begins
> here
> extern "C" {
> ^
>
>
> 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


C++ absolutely does disallow it for its own headers (which include
<stddef.h> and <inttypes.h>):

[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."

and I have certainly seen circumstances where people recommended extern "C"
> { #include <system header> } for various reasons.
>
> 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.
>
> Anyway, I checked
> http://clang.llvm.org/docs/Modules.html#modularizing-a-platform 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.)


See http://clang.llvm.org/docs/Modules.html#module-declaration 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:
1) The module is built surrounded by an implicit extern "C" context, and
2) The module can be imported within a top-level extern "C" linkage
specification.

This attribute should typically be applied to modules whose headers contain
the

#ifdef __cplusplus
extern "C" {
#endif
// ...
#ifdef __cplusplus
}
#endif

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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20141001/eb5e29e0/attachment.html>


More information about the cfe-dev mailing list