<div dir="auto"><div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, 25 Jun 2020, 21:05 Louis Dionne via cfe-dev, <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
The C++ Standard Library has multiple headers of the form <cfoobar>, which are<br>
basically importing declarations from the corresponding <foobar.h> header into<br>
namespace std. For example, <cstdio> basically imports all the declarations from<br>
<stdio.h> into namespace std:<br>
<br>
    namespace std {<br>
        using ::FILE;<br>
        using ::fpos_t;<br>
        using ::size_t;<br>
        ...<br>
    }<br>
<br>
When porting libc++ to new platforms, especially more embedded-ish platforms, <br>
it is very common that some declarations are not provided by the underlying<br>
C Standard Library. This leads to having to detect what platform we're on,<br>
and then to conditionally exclude some declarations:<br>
<br>
    namespace std {<br>
    #if !defined(SOME_WEIRD_PLATFORM)<br>
        using ::FILE;<br>
        using ::fpos_t;<br>
    #endif<br>
        using ::size_t;<br>
    }<br>
<br>
Unfortunately, different platforms often offer slightly different subsets, so<br>
these #ifs quickly become difficult to maintain. Trying to find common themes<br>
for excluding declarations (e.g. #if !defined(_LIBCPP_HAS_NO_FILE)) is vain,<br>
because the subset provided by a platform is often arbitrary. For example, I've<br>
seen platforms where malloc() and free() were not provided, however operator new<br>
was -- so trying to carve out something like _LIBCPP_HAS_NO_ALLOCATION wouldn't<br>
really make sense.<br>
<br>
Given the difficulty of manually excluding such using declarations, I came to<br>
the conclusion that what we wanted was often something like (pseudocode):<br>
<br>
    namespace std {<br>
    #if __has_declaration(::FILE)<br>
        using ::FILE;<br>
    #endif<br>
<br>
    #if __has_declaration(::fpos_t)<br>
        using ::fpos_t;<br>
    #endif<br>
<br>
    #if __has_declaration(::size_t)<br>
        using ::size_t;<br>
    #endif<br>
<br>
        ...<br>
    }<br>
<br>
Basically, we want to import each declaration into namespace std only if the<br>
global namespace has such a declaration.<br>
<br>
Now, I understand this raises several questions. Of course, this couldn't be<br>
done at the preprocessor level because I don't think we can know whether a <br>
declaration exists at that time. However, I was curious to ask on this list<br>
whether someone could think of a reasonable way to solve this problem.<br>
<br>
Having some mechanism for doing this would be a huge life improvement for libc++.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">Do you always want to guard a namespace & scope using-declaration? We could probably support an attribute on such declarations that would result in them having no effect if no names are found -- or perhaps being invalid to reference if no names are found. (Otherwise, Clang already has some support for MSVC's __if_exists, but it's got some deep semantic problems, and I don't think we should recommend its use.)</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Cheers,<br>
Louis<br>
<br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" rel="noreferrer">cfe-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-</a><br>
</blockquote></div></div></div>