[cfe-dev] How do I try out C++ modules with clang?

Sean Silva chisophugis at gmail.com
Tue Oct 21 14:34:08 PDT 2014


After a bit of looking around on my Mac, I think I figured out what is
going on. The declaration for those functions is in <xlocale/_stdlib.h>.
That header is only included from two places:

1. From stdlib.h if _USE_EXTENDED_LOCALES_ is defined.
2. From xlocale.h if stdlib.h has been previously included (this is sort of
nasty, but documented
http://www.freebsd.org/cgi/man.cgi?query=xlocale&sektion=3 "These functions
are exposed by including <xlocale.h> after including the relevant headers
for the standard variant."; Apple doesn't document this because it looks
like they use a non-modular trick described below to work around this).

I'll assume you don't have _USE_EXTENDED_LOCALES_ defined on the command
line. Looking at libc++'s <locale> and the headers it includes, it looks
like xlocale.h gets included without stdlib.h having been included
(<locale> --> <__locale> --> <xlocale.h>). If this hypothesis is correct,
then these errors should go away if you change libc++'s <locale> by moving
`#include <__locale>` below `#include <cstdlib>`.

The trick that the Apple headers seem to use to work around the "must be
included after" issue is that xlocale.h defines _USE_EXTENDED_LOCALES_ so
that a subsequent include of stdlib.h will bring them in. However, stdlib.h
is brought in from the module, where it was built without
_USE_EXTENDED_LOCALES_ defined. Thus, <xlocale/_stdlib.h> is never seen by
the compiler, and those functions are missing.

This trick breaks one of the promises the module map file makes about
stdlib.h, which roughly boils down to "this header isn't meant to change
its behaviors depending on the set of macros defined when it is included";
thus it is not surprising that this should break. I made a reduced test
case (attached) which suggests that even clang's config_macros doesn't deal
with this.

Richard, any ideas on what the "right" solution is here?

Stephen, thanks for being a brave guinea pig here :)

-- Sean Silva




On Tue, Oct 21, 2014 at 4:57 AM, Stephen Kelly <steveire at gmail.com> wrote:

> Richard Smith <richard at ...> writes:
>
> > libc++ already ships with a module map.
>
> Today I built llvm, clang and libcxx on a Mac (OSX 10.9 I assume), and when
> I try to use -fmodules, it can't build the module.modulemap shipped with
> libcxx. Any idea what's going wrong?
>
> $ clang++ -E -fmodules test.cpp
> # 1 "test.cpp"
> # 1 "<built-in>" 1
> # 1 "<built-in>" 3
> # 325 "<built-in>" 3
> # 1 "<command line>" 1
> # 1 "<built-in>" 2
> # 1 "test.cpp" 2
> While building module 'std' imported from test.cpp:6:
> In file included from <module-includes>:4:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/ccomplex:21:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/complex:247:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/sstream:174:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/ostream:140:
> /Users/ske/dev/prefix/bin/../include/c++/v1/locale:873:26: error: use of
> undeclared identifier 'strtoll_l'; did you mean 'wcstoll_l'?
>         long long __ll = strtoll_l(__a, &__p2, __base,
> _LIBCPP_GET_C_LOCALE);
>                          ^
> /usr/include/xlocale/_wchar.h:98:2: note: 'wcstoll_l' declared here
>         wcstoll_l(const wchar_t * __restrict, wchar_t ** __restrict, int,
>         ^
> While building module 'std' imported from test.cpp:6:
> In file included from <module-includes>:4:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/ccomplex:21:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/complex:247:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/sstream:174:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/ostream:140:
> /Users/ske/dev/prefix/bin/../include/c++/v1/locale:873:36: error: cannot
> initialize a parameter of type 'const wchar_t *' with an lvalue of type
> 'const char *'
>         long long __ll = strtoll_l(__a, &__p2, __base,
> _LIBCPP_GET_C_LOCALE);
>                                    ^~~
> /usr/include/xlocale/_wchar.h:98:38: note: passing argument to parameter
> here
>         wcstoll_l(const wchar_t * __restrict, wchar_t ** __restrict, int,
>                                             ^
> While building module 'std' imported from test.cpp:6:
> In file included from <module-includes>:4:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/ccomplex:21:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/complex:247:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/sstream:174:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/ostream:140:
> /Users/ske/dev/prefix/bin/../include/c++/v1/locale:913:35: error: use of
> undeclared identifier 'strtoull_l'; did you mean 'wcstoull_l'?
>         unsigned long long __ll = strtoull_l(__a, &__p2, __base,
> _LIBCPP_GET_C_LOCALE);
>                                   ^
> /usr/include/xlocale/_wchar.h:101:2: note: 'wcstoull_l' declared here
>         wcstoull_l(const wchar_t * __restrict, wchar_t ** __restrict, int,
>         ^
> While building module 'std' imported from test.cpp:6:
> In file included from <module-includes>:4:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/ccomplex:21:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/complex:247:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/sstream:174:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/ostream:140:
> /Users/ske/dev/prefix/bin/../include/c++/v1/locale:913:46: error: cannot
> initialize a parameter of type 'const wchar_t *' with an lvalue of type
> 'const char *'
>         unsigned long long __ll = strtoull_l(__a, &__p2, __base,
> _LIBCPP_GET_C_LOCALE);
>                                              ^~~
> /usr/include/xlocale/_wchar.h:101:39: note: passing argument to parameter
> here
>         wcstoull_l(const wchar_t * __restrict, wchar_t ** __restrict, int,
>                                              ^
> While building module 'std' imported from test.cpp:6:
> In file included from <module-includes>:4:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/ccomplex:21:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/complex:247:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/sstream:174:
> In file included from
> /Users/ske/dev/prefix/bin/../include/c++/v1/ostream:140:
> /Users/ske/dev/prefix/bin/../include/c++/v1/locale:943:28: error: use of
> undeclared identifier 'strtold_l'
>         long double __ld = strtold_l(__a, &__p2, _LIBCPP_GET_C_LOCALE);
>                            ^
> test.cpp:6:10: fatal error: could not build module 'std'
> #include <utility>
>  ~~~~~~~~^
>
>
>
>
>
>
>
> int main(int argc, char** argv)
> {
>     return 0;
> }
> 6 errors generated.
>
> $ cat test.cpp
>
> //#include "foo.h"
>
> //#include <QtCore/qxmlstream.h>
>
> #include <utility>
>
> int main(int argc, char** argv)
> {
>     return 0;
> }
>
> $ clang++ --version
> clang version 3.6.0
> Target: x86_64-apple-darwin13.4.0
> Thread model: posix
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20141021/7ba023b2/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: testdoubleinclude.zip
Type: application/zip
Size: 1371 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20141021/7ba023b2/attachment.zip>


More information about the cfe-dev mailing list