[cfe-dev] [libc++] RFC: Add Windows kernel support and partial MSVC 2015 support

Eric Fiselier via cfe-dev cfe-dev at lists.llvm.org
Wed Mar 29 14:08:15 PDT 2017


>
> Even if I did use Clang though, that would only address one of the four
> sub-features you identified, the port to MSVC.
>

Right, it would only address the MSVC port but that's at least one less
work-item to reach the goal.


>
> > However I have large concerns regarding the changes required for [Kernel
> C library] and [Kernel subset] as I suspect they won't satisfy the above
> requirement.
>
> Understood.  This was feedback I was expecting.  Subsets and niche
> platforms are a maintenance burden.
>

Libc++ has support for other niche C libraries, but that support has been
mostly limited to #ifdef'ing out parts of the <cfoo> headers because the
underlying C library
doesn't provide it. If supporting the Kernel C library requires only
similar changes then I think those would be reasonable to accept.

The complexity for C library ports usually comes from locales and
input/output functions. If those are no concern then I'm hopeful it will be
easy to support
the Kernel C library.


> >
>
> > First Libc++ cannot reasonably limit itself to the proposed language and
> library feature set since
>
> > it must be free to use "restricted" features within the implementation
> of non-restricted ones whenever
>
> > it is beneficial to the implementation. The burden of maintaining a
> working restricted feature set could
>
> > not fall on upstream maintainers.
>
> I'm not going to make any promises... but would a public build bot address
> your concerns?  What if the restricted feature set got standardized as the
> C++2x definition of a freestanding implementation?
>

A public buildbot would be a requirement, and I would be happy to host it.

I would be much more comfortable maintaining a standardized definition of a
"freestanding implementation", and I would support your push to fix the
C++17 definition of freestanding.


>
>
> I can definitely see maintaining a restricted include set to be
> burdensome  I will have to think on how to address that in a reasonable
> way.  Your clang-tidy suggestion may be useful here.
>
>
>
> I don't think maintaining a restricted use of features will be
> particularly hard though.  For <array>, <tuple>, <utility>, and
> <algorithm>, do you foresee changes where an existing function doesn't
> throw, but starts to throw?  Or doesn't currently allocate, but starts to
> allocate?  If we were talking about the containers, or iostreams, or regex,
> I would definitely agree that the implementation flexibility is needed.
> I'm not sure I agree when it's a smaller list of low level headers though.
>

I agree with your examples. Existing functions are unlikely to suddenly
require exceptions or allocations. However it is conceivable that <tuple>
or <utility> could require some internals, which themselves don't allocate
or throw, that were previously only used by restricted features, or that
live in restricted headers. For example libc++ often uses unique_ptr as a
scope guard, but the class is primarily used to deal with dynamically
memory and likely wouldn't be a part of freestanding mode. Forbidding its
use in freestanding features could quickly become problematic. (Note:
<algorithm> already widely depends on unique_ptr for this purpose).

I posit that the implementation requires the general freedom to use classes
not supported in freestanding mode. We'll likely be able to strike a
balance between what the implementation needs and what freestanding users
expect, but there needs to be leeway; Leeway that restricting entire
headers in freestanding mode does not provide.



> > I think it would be much better to get as much of libc++ compiling as
> possible, even if it depends on restricted
>
> > features, and then finding another mechanism to restrict the features
> end-users are allowed to use (Such as clang-tidy).
>
> > This would eliminate the need to restructure headers or spam out
> internal #ifdef guards.
>


> One thing I want to avoid is turning straightforward mistakes into errors
> that are even more cryptic than what C++ users have grown accustomed to.  I
> don't really want the failure condition of inplace_merge to be a linker
> error complaining about a missing operator new.  clang-tidy might help with
> that.  #ifdefs are a straightforward way to address that concern, though it
> requires a substantial amount of effort.  Would you be opposed to
> widespread static_asserts?
>

What kind of static asserts? Can you provide an example?


> >> * I'll also need to figure out how to not drag along unwanted header
> dependencies.
>
>
>
> > I don't see how libc++ could upstream changes since it requires every
> header
>
> > it currently includes (modulo bugs).
>
> The straightforward (and labor intensive) way is with #ifdef
> _LIBCPP_HAS_NO_ALLOC
>
>
>

_LIBCPP_HAS_NO_ALLOC is exactly the invasive change I wanted to avoid.
First <new> is currently a freestanding header,
and I think it should stay that way. Second I want to avoid the maintenance
cost of such a restrictive
configuration. This macro would have to guard the the vast majority of the
library, unlike
_LIBCPP_HAS_EXCEPTIONS and _LIBCPP_NO_RTTI which have a much smaller and
more manageable scope.

If the end goal is simply to diagnose when end users use features that
dynamically allocate I suspect there
are less invasive ways to do it. First there are two important things to
note:

(1) Libc++ has very few naked new/delete calls. Almost all dynamic
allocations go through std::allocator.
(2) std::allocator is typically used in dependent contexts (templates).

Instead of #ifdef'ing out std::allocator and everything that uses it, we
could make instantiating std::allocator::allocate
produce a diagnostic. This would make the changes needed within libc++
significantly smaller while still
producing reasonable diagnostics when users attempt to use those types.



> Using hard-coded kernel paths is not a change I see being upstream-able.
> However
>
> > we might be able to convince MSVC to implement #include_next if we can
> provide
>
> > strong enough rational for why we need it.
>
> These wouldn't be hard coded paths.  The code would look something like...
>
> #if __LIBCPP_HAS_INCLUDE_NEXT
>
> #include_next <limits.h>
>
> #else
>
> #include __LIBCPP_HACK_INCLUDE_NEXT(limits.h)
>
> #endif
>
> __config would have the definition of __LIBCPP_HACK_INCLUDE_NEXT, and
>
> config_site.in would have the relative path needed to glue everything
> together ("../../km/crt" in my case).
>

That sounds like a fairly reasonable solution. Although aren't macro
expansions inside #include directives UB?


>
>
> > I'm violently against working around MSVC template bugs. Every time I've
> seen
>
> > it done it makes the implementation worse.
>
> That's fair.  I will say that not _all_ of the workarounds make worse code,
>
> but quite a few do.  This may end up being what forces me to MSVC 2017.
>
>
>
> One example of a workaround that I don't think made things worse...
>
> struct _LIBCPP_TYPE_VIS __check_tuple_constructor_fail {
>
>      template <class ...>
>
> -    static constexpr bool __enable_default() { return false; }
>
> +    static constexpr bool __enable_default = false;
>

Your example uses C++14 variable templates, which I don't think you
intended because MSVC 2015 doesn't support
them either.

Ironically that's a perfect example of a change that would make things
drasticly worse.
First the suggested fix cannot be applied because variable templates are
C++14 features.
Second we couldn't use a non-template in this case because it's important
that the result is
type dependent in the non-fail cases to prevent eager SFINAE evaluation.

The <tuple> SFINAE is very complicated and it's full of subtle but
important details.
It can barely manage it with a fully conforming C++11 compiler.



> > Another point is that libc++ doesn't have an <atomic> implementation for
> MSVC
>
> > so adding MSVC support would required adding one.
>
> Yep, I've got one implemented (and untested).  This is the biggest reason
> why
>
> I excluded ARM support explicitly.
>

Nice!


>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170329/950e1a9a/attachment.html>


More information about the cfe-dev mailing list