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

Sean Silva chisophugis at gmail.com
Tue Oct 21 21:18:01 PDT 2014


On Tue, Oct 21, 2014 at 5:27 PM, Richard Smith <richard at metafoo.co.uk>
wrote:

> On Tue, Oct 21, 2014 at 2:34 PM, Sean Silva <chisophugis at gmail.com> wrote:
>
>> 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.
>>
>
> Did you try adding -D_USE_ to the command line in your reduced testcase?
>
> Richard, any ideas on what the "right" solution is here?
>>
>
> One possibility would be to split stdlib.h up into three:
>
> 1) A module providing most of the stdlib.h contents
> 2) A module providing xlocale/_stdlib.h (it seems this part is already
> done)
> 3) A file that imports (1) and (2)
>
> ... and to treat (3) as a textually-included header rather than a module.
> I think that's my preferred approach, since it allows retaining the
> existing horrible mess of _*_SOURCE configuration macros controlling which
> symbols come from which includes.
>
> Another would be for stdlib.h to always provide everything when built with
> modules enabled.
>
> Another would be to add -D_USE_EXTENDED_LOCALES_ to your clang command
> line.
>

I think in this case it's not meant to be something for the end-user to
configure. It seems like _USE_EXTENDED_LOCALES_ is just a cookie that
xlocale.h sets so that stdlib.h et al. remember to include their relevant
xlocale/_stdlib.h file (I was mostly thinking about config_macros as a hack
to work around it).

-- Sean Silva


>
> 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/338eaf72/attachment.html>


More information about the cfe-dev mailing list