<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Jun 26, 2020, at 12:22, Richard Smith <<a href="mailto:richard@metafoo.co.uk" class="">richard@metafoo.co.uk</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="auto" style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><div class=""><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" class="">cfe-dev@lists.llvm.org</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;">Hi,<br class=""><br class="">The C++ Standard Library has multiple headers of the form <cfoobar>, which are<br class="">basically importing declarations from the corresponding <foobar.h> header into<br class="">namespace std. For example, <cstdio> basically imports all the declarations from<br class=""><stdio.h> into namespace std:<br class=""><br class="">   <span class="Apple-converted-space"> </span>namespace std {<br class="">       <span class="Apple-converted-space"> </span>using ::FILE;<br class="">       <span class="Apple-converted-space"> </span>using ::fpos_t;<br class="">       <span class="Apple-converted-space"> </span>using ::size_t;<br class="">       <span class="Apple-converted-space"> </span>...<br class="">   <span class="Apple-converted-space"> </span>}<br class=""><br class="">When porting libc++ to new platforms, especially more embedded-ish platforms,<span class="Apple-converted-space"> </span><br class="">it is very common that some declarations are not provided by the underlying<br class="">C Standard Library. This leads to having to detect what platform we're on,<br class="">and then to conditionally exclude some declarations:<br class=""><br class="">   <span class="Apple-converted-space"> </span>namespace std {<br class="">   <span class="Apple-converted-space"> </span>#if !defined(SOME_WEIRD_PLATFORM)<br class="">       <span class="Apple-converted-space"> </span>using ::FILE;<br class="">       <span class="Apple-converted-space"> </span>using ::fpos_t;<br class="">   <span class="Apple-converted-space"> </span>#endif<br class="">       <span class="Apple-converted-space"> </span>using ::size_t;<br class="">   <span class="Apple-converted-space"> </span>}<br class=""><br class="">Unfortunately, different platforms often offer slightly different subsets, so<br class="">these #ifs quickly become difficult to maintain. Trying to find common themes<br class="">for excluding declarations (e.g. #if !defined(_LIBCPP_HAS_NO_FILE)) is vain,<br class="">because the subset provided by a platform is often arbitrary. For example, I've<br class="">seen platforms where malloc() and free() were not provided, however operator new<br class="">was -- so trying to carve out something like _LIBCPP_HAS_NO_ALLOCATION wouldn't<br class="">really make sense.<br class=""><br class="">Given the difficulty of manually excluding such using declarations, I came to<br class="">the conclusion that what we wanted was often something like (pseudocode):<br class=""><br class="">   <span class="Apple-converted-space"> </span>namespace std {<br class="">   <span class="Apple-converted-space"> </span>#if __has_declaration(::FILE)<br class="">       <span class="Apple-converted-space"> </span>using ::FILE;<br class="">   <span class="Apple-converted-space"> </span>#endif<br class=""><br class="">   <span class="Apple-converted-space"> </span>#if __has_declaration(::fpos_t)<br class="">       <span class="Apple-converted-space"> </span>using ::fpos_t;<br class="">   <span class="Apple-converted-space"> </span>#endif<br class=""><br class="">   <span class="Apple-converted-space"> </span>#if __has_declaration(::size_t)<br class="">       <span class="Apple-converted-space"> </span>using ::size_t;<br class="">   <span class="Apple-converted-space"> </span>#endif<br class=""><br class="">       <span class="Apple-converted-space"> </span>...<br class="">   <span class="Apple-converted-space"> </span>}<br class=""><br class="">Basically, we want to import each declaration into namespace std only if the<br class="">global namespace has such a declaration.<br class=""><br class="">Now, I understand this raises several questions. Of course, this couldn't be<br class="">done at the preprocessor level because I don't think we can know whether a<span class="Apple-converted-space"> </span><br class="">declaration exists at that time. However, I was curious to ask on this list<br class="">whether someone could think of a reasonable way to solve this problem.<br class=""><br class="">Having some mechanism for doing this would be a huge life improvement for libc++.<br class=""></blockquote></div></div><div dir="auto" class=""><br class=""></div><div dir="auto" class="">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></div></blockquote><div><br class=""></div><div>Yes, as far as I can tell, I only want to apply this to using declarations inside namespace std. It's a pretty constrained use case.</div><div><br class=""></div><div>I think the better semantics would be to have no effect if no names are found, since that's what's closest in effect to having an #ifdef in front that removes it. The resulting error is also quite straightforward, i.e. the compiler just says "oops, no such member in namespace std". We could potentially augment the diagnostic to say "there's no such member in namespace std BECAUSE we tried importing it and it wasn't in the global namespace".</div><div><br class=""></div><div>Louis</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><div dir="auto" class=""><br class=""></div><div dir="auto" class=""><div class="gmail_quote"><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;">Cheers,<br class="">Louis<br class=""><br class="">_______________________________________________<br class="">cfe-dev mailing list<br class=""><a href="mailto:cfe-dev@lists.llvm.org" target="_blank" rel="noreferrer" class="">cfe-dev@lists.llvm.org</a><br class=""><a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer noreferrer" target="_blank" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-</a></blockquote></div></div></div></div></blockquote></div><br class=""></body></html>