Commit Graph

2751 Commits

Author SHA1 Message Date
Martin Storsjö e3add3e5a1 [libcxx] Fix building for windows after 54fa9ecd30
Move the implementation of __libcpp_thread_poll_with_backoff
and __libcpp_timed_backoff_policy::operator() out of the
_LIBCPP_HAS_THREAD_API_PTHREAD block. None of the code in these
methods is pthreads specific.

Also add "inline _LIBCPP_INLINE_VISIBILITY" to
__libcpp_timed_backoff_policy::operator(), to avoid errors due to
multiple definitions of the operator. Contrary to
__libcpp_thread_poll_with_backoff (which is a template function),
this is a normal non-templated method.

Differential Revision: https://reviews.llvm.org/D75102
2020-02-25 21:33:52 +02:00
Louis Dionne 7c2f4a8370 [libc++] Revert 03dd205c15 "Adjust max_align_t handling"
That commit was made without approval from a libc++ reviewer, and it
also broke the build in C++03 mode.
2020-02-25 11:42:08 -05:00
Louis Dionne ab41129b1e [libc++] Proper fix for libc++'s modulemap after D68480
Summary:
In libc++, we normally #ifdef out header content instead of #erroring
out when the Standard in use is insufficient for the requirements of
the header.

Reviewers: EricWF

Subscribers: jkorous, dexonsmith, libcxx-commits, teemperor

Tags: #libc

Differential Revision: https://reviews.llvm.org/D75074
2020-02-25 11:31:10 -05:00
Joerg Sonnenberger 03dd205c15 Adjust max_align_t handling
Depend on the compiler to provide a correct implementation of
max_align_t. If __STDCPP_NEW_ALIGNMENT__ is missing and C++03 mode has
been explicitly enabled, provide a minimal fallback in <new> as
alignment of the largest primitive types.
2020-02-25 01:36:43 +01:00
Raphael Isemann b61e83eb0e [libc++] Give headers that require C++14 a cplusplus14 requires in the modulemap
https://reviews.llvm.org/D68480 added those headers and made the std module
only usable with C++14 or later as the submodules were not marked as requiring
C++14 or later. This just adds the missing requires directives.
2020-02-24 20:20:55 +01:00
Louis Dionne b21405d1cd [libc++] Fix CI and Linux failures after landing D68480
- Avoid using C++11-and-later features in <atomic>:
  Historically, we've supported <atomic> in C++03, so we can't use C++11
  features in that header. This is something we really need to change,
  since our implementation of <atomic> is starting to accumulate technical
  debt because of that.
- Mark a test as unsupported on single threaded systems
- Add missing symbols to the Linux ABI list
2020-02-24 11:58:25 -05:00
Louis Dionne c008716417 [libc++] Mark the C++03 version of std::function as deprecated
Summary: We want to eventually remove it.

Reviewers: EricWF

Subscribers: christof, jkorous, dexonsmith, libcxx-commits

Tags: #libc

Differential Revision: https://reviews.llvm.org/D74719
2020-02-24 10:59:58 -05:00
Louis Dionne 80e73f2295 [libc++] Adapt a few things around the implementation of P1135R6
- Add the new symbols to the ABI list on Darwin
- Add XFAIL markup to the tests that require dylib support on older platforms
- Add availability markup for back-deployment
2020-02-24 10:59:35 -05:00
Olivier Giroux 54fa9ecd30 [libc++] Implementation of C++20's P1135R6 for libcxx
Differential Revision: https://reviews.llvm.org/D68480
2020-02-24 10:59:35 -05:00
Martijn Vels d8969a1cb9 Split _LIBCPP_STRING_EXTERN_TEMPLATE_LIST up into a V1 and UNSTABLE version.
This change splits the _LIBCPP_STRING_EXTERN_TEMPLATE_LIST up into a _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST containing the stable ABI, and a _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST containing the unstable ABI.

The purpose is to explicitly define and maintain the two lists, where the unstable ABI allows for ABI breaking changes for purposes such as optimization while offering a strong guarantee that any change inside the unstable ABI does not affect the stable ABI.

As per the comment in the __string header, we do still allow etries to be added to the stable ABI list as the c++ versions and corresponding c++ std API changes.
2020-02-20 23:21:14 -05:00
Mark de Wever 72ce0c8073 [libc++][regex] Validate backreferences in the constructor.
This patch enables throwing exceptions for invalid backreferences
in the constructor when using the basic, extended,  grep, or egrep grammar.

This fixes bug 34297.

Differential Revision: https://reviews.llvm.org/D62453
2020-02-20 18:16:21 -05:00
Logan Smith 092a57f508 [libc++] Fix unqualified call to 'ref' inside shared_ptr(unique_ptr<U, D>)
This prevents unintended ADL: https://gcc.godbolt.org/z/EHw3Gy
This issue was mentioned as an addendum in PR44398.

Differential Revision: https://reviews.llvm.org/D74289
2020-02-20 12:24:40 -05:00
Logan Smith e442f38395 [libc++] Fix unintended ADL inside ref(reference_wrapper<T>) and cref(reference_wrapper<T>)
This patch qualifies calls to ref and cref inside ref(reference_wrapper<T>)
and cref(reference_wrapper<T>), respectively. These previously unqualified
calls could break in the presence of user functions called ref/cref inside
associated namespaces: https://gcc.godbolt.org/z/8VfprT

Fixes PR44398.

Differential Revision: https://reviews.llvm.org/D74287
2020-02-20 12:22:21 -05:00
Louis Dionne c3478eff7a [libc++] reduce <complex> parsing time
Instead of including <ios> for ios_base::failbit, simply get failbit
member of the template argument. Print directly to a stream instead
of using intermediate ostringstream.

    Parsing time: 874ms -> 164ms (-81%)

Thanks to Nikita Kniazev for the patch!

Differential Revision: https://reviews.llvm.org/D71214
2020-02-19 16:09:41 -05:00
Louis Dionne 6ba2d7b166 [libc++] Fixes backreferences for extended grammar.
The regex backreferences were not properly parsed and used when using
the extended grammar. This change parses them. The issue was found while
working on PR34297.

Thanks to Mark de Wever for the patch!

Differential Revision: https://reviews.llvm.org/D62451
2020-02-19 15:57:16 -05:00
Eric Fiselier a829443cc7 [libc++] Fix ABI break in __bit_reference.
The libc++ __bit_iterator type has weird ABI calling conventions as a
quirk
of the implementation. The const bit iterator is trivial, but the
non-const
bit iterator is not because it declares a user-defined copy constructor.

Changing this now is an ABI break, so this test ensures that each type
is trivial/non-trivial as expected.

The definition of 'non-trivial for the purposes of calls':
  A type is considered non-trivial for the purposes of calls if:
      * it has a non-trivial copy constructor, move constructor, or
            destructor, or
	        * all of its copy and move constructors are deleted.
2020-02-19 12:02:06 -05:00
Raphael Isemann 23368bee15 Revert "[libc++] Move abs and div into stdlib.h to fix header cycle."
This reverts commit 82b47b2978.

This broke Clang and LLDB module builds without -fmodules-local-submodule-visbility.
I'll revert this for now until we have a fix and reland once Clang
can properly handle this code.

See also the discussion in https://reviews.llvm.org/rG82b47b2978405f802a33b00d046e6f18ef6a47be
2020-02-17 17:59:08 +01:00
Louis Dionne 8b60ba73af [libc++] Add availability markup for std::to_chars on Apple platforms
Summary:
Otherwise, one gets link errors when trying to back-deploy to older platforms.

rdar://problem/57854364

Reviewers: lichray, EricWF

Subscribers: christof, jkorous, dexonsmith, libcxx-commits

Tags: #libc

Differential Revision: https://reviews.llvm.org/D74626
2020-02-17 09:32:46 -05:00
Eric Fiselier 82b47b2978 [libc++] Move abs and div into stdlib.h to fix header cycle.
libc++ is careful to not fracture overload sets. When one overload
is visible to a user, all of them should be. Anything less causes
subtle bugs and ODR violations.

Previously, in order to support ::abs and ::div being supplied by
both <cmath> and <cstdlib> we had to do awful things that make
<math.h> and <stdlib.h> have header cycles and be non-modular.
This really breaks with modules.

Specifically the problem was that in C++ ::abs introduces overloads
for floating point numbers, these overloads forward to ::fabs,
which are defined in math.h. Therefore ::abs needed to be in math.h
too. But this required stdlib.h to include math.h and math.h to
include stdlib.h.

To avoid these problems the definitions have been moved to stddef.h
(which math includes), and the floating point overloads of ::abs
have been changed to call __builtin_fabs, which both Clang and GCC
support.
2020-02-15 18:55:07 -05:00
Eric Fiselier cccf1ef0c8 [libc++] Remove cycle between <type_traits> and <cstddef>
This was caused by byte depending on traits. This patch moves
the minimal amount of meta-programming into <cstddef> to break the cycle.
2020-02-14 17:36:27 +01:00
Eric Fiselier e337fb0790 add type_traits include as required for std::integral_constant 2020-02-14 16:38:28 +01:00
Louis Dionne 0a0e0afaa0 [libc++] span: Fix incorrect static asserts
The static asserts in span<T, N>::front() and span<T, N>::back() are
incorrect as they may be triggered from valid code due to evaluation
of a never taken branch:

    span<int, 0> foo;
    if (!foo.empty()) {
        auto x = foo.front();
    }

The problem is that the branch is always evaluated by the compiler,
creating invalid compile errors for span<T, 0>.

Thanks to Michael Schellenberger Costa for the patch.

Differential Revision: https://reviews.llvm.org/D71995
2020-02-14 14:32:41 +01:00
Louis Dionne b5abd50f06 [libc++] span: Guard against overflow in span::subspan
The calculation _Offset + _Count <= size() may overflow, so use
_Count <= size() - _Offset instead. Note that this is safe due to
the previous constraint that _Offset <= size().

Patch by Michael Schellenberger Costa.

Differential Revision: https://reviews.llvm.org/D71998
2020-02-12 16:21:46 +01:00
Louis Dionne 37f46650c3 [libc++] Make sure that vector copy-construction is disabled for non-copyable types
The Standard requires the value_type of the vector to be Cpp17CopyInsertable
in order for copy-construction to be enabled:

	http://eel.is/c++draft/container.requirements#tab:container.req

rdar://problem/56674564

Differential Revision: https://reviews.llvm.org/D74251
2020-02-11 17:12:16 +01:00
Louis Dionne 92a1f65f17 [libc++] span: Fix incorrect return type of span::subspan
The extent of the returned span was always std::dynamic_extent, which
is incorrect.

Thanks to Michael Schellenberger Costa for the patch.

Differential Revision: https://reviews.llvm.org/D71997
2020-02-11 11:58:45 +01:00
Louis Dionne b4a3e6b664 [libcxx] span: Remove unneeded comparison
size_t is always greater than 0, so remove the artifact from the old
index_type.

Patch by Michael Schellenberger Costa.

Differential Revision: https://reviews.llvm.org/D71996
2020-02-11 11:39:12 +01:00
Louis Dionne edbaa7fc04 [libc++] span: Cleanup includes
Thanks to Michael Schellenberger Costa for the patch.

Differential Revision: https://reviews.llvm.org/D72036
2020-02-11 11:17:30 +01:00
Louis Dionne 9fda213d62 [libcxx] Qualify make_move_iterator in vector::insert for input iterators
Unqualified calls to make_move_iterator in the vector::insert overload
for input iterators lead to ADL issues: https://gcc.godbolt.org/z/bmcNbh

Patch by Logan Smith.

Differential Revision: https://reviews.llvm.org/D74290
2020-02-11 11:00:45 +01:00
Louis Dionne 1ac44d9fd1 [libc++] Protect <span> against min/max macro
Patch by Corentin Jabot
Differential Revision: https://reviews.llvm.org/D73855
2020-02-10 13:41:34 +01:00
Marek Kurdej e93e58c6c4 Reland [libc++] [P0325] Implement to_array from LFTS with updates.
Fixed expected errors and notes.

Summary:
This patch implements https://wg21.link/P0325.

Reviewers: EricWF, mclow.lists, ldionne, lichray

Reviewed By: ldionne, lichray

Subscribers: lichray, dexonsmith, zoecarver, christof, ldionne, libcxx-commits

Tags: #libc

Differential Revision: https://reviews.llvm.org/D69882
2020-01-31 11:47:18 +01:00
Marek Kurdej 5e7017273f Revert "[libc++] [P0325] Implement to_array from LFTS with updates."
This reverts commit 86aae78268.

A test is failing on "Release" build without assertions enabled (Fedora 31 on x86_64).
2020-01-31 09:45:50 +01:00
Martijn Vels 282b803b62 White space only change: reflow a comment in basic_string
Summary: This change reflows a comment line. This change serves as a no-op test commit

Reviewers: mclow.lists, ldionne, EricWF

Subscribers: dexonsmith, christof, libcxx-commits

Tags: #libc

Differential Revision: https://reviews.llvm.org/D73552
2020-01-30 19:55:48 -05:00
Marek Kurdej 86aae78268 [libc++] [P0325] Implement to_array from LFTS with updates.
Summary:
This patch implements https://wg21.link/P0325.
Please mind that at it is my first contribution to libc++, so I may have forgotten to abide to some conventions.

Reviewers: EricWF, mclow.lists, ldionne, lichray

Reviewed By: ldionne, lichray

Subscribers: lichray, dexonsmith, zoecarver, christof, ldionne, libcxx-commits

Tags: #libc

Differential Revision: https://reviews.llvm.org/D69882
2020-01-30 13:38:37 +01:00
Dimitry Andric 5e416ba943 Define _LIBCPP_HAS_TIMESPEC_GET for FreeBSD when appropriate
Summary:
FreeBSD got `timespec_get` support somewhere in the 12.x timeframe, but
the C++ version check in its system headers was written incorrectly.
This has now been fixed for both FreeBSD 13 and 12.

Add checks for the corresponding `__FreeBSD_version` values, to define
`_LIBCPP_HAS_TIMESPEC_GET` when the function is supported.

Reviewers: emaste, EricWF, ldionne, mclow.lists

Reviewed By: ldionne

Subscribers: arichardson, krytarowski, christof, dexonsmith, libcxx-commits

Tags: #libc

Differential Revision: https://reviews.llvm.org/D71522
2020-01-30 08:00:56 +01:00
Martin Storsjö 7db4f2c694 [libcxx] [Windows] Store the lconv struct returned from localeconv in locale_t
This fixes using non-default locales, which currently can crash when
e.g. formatting numbers.

Within the localeconv_l function, the per-thread locale is temporarily
changed with __libcpp_locale_guard, then localeconv() is called,
returning an lconv * struct pointer.

When localeconv_l returns, the __libcpp_locale_guard dtor restores
the per-thread locale back to the original. This invalidates the
contents of the earlier returned lconv struct, and all C strings
that are pointed to within it are also invalidated.

Thus, to have an actually working localeconv_l function, the
function needs to allocate some sort of storage for the returned
contents, that stays valid for as long as the caller needs to use
the returned struct.

Extend the libcxx/win32 specific locale_t class with storage for
a deep copy of a lconv struct, and change localeconv_l to take
a reference to the locale_t, to allow it to store the returned
lconv struct there.

This works fine for libcxx itself, but wouldn't necessarily be right
for a caller that uses libcxx's localeconv_l function.

This fixes around 11 of libcxx's currently failing tests on windows.

Differential Revision: https://reviews.llvm.org/D69505
2020-01-29 22:37:11 +02:00
David Zarzycki 5dda92fcb0
Add test for spaceship operator to __config
Summary:
The libcxx test suite auto-detects spaceship operator, but __config does not. This means that the libcxx test suite has been broken for over a month when using top-of-tree clang. This also really ought to be fixed before 10.0.

See: bc633a42dd

Reviewers: chandlerc, mclow.lists, EricWF, ldionne, CaseyCarter

Reviewed By: EricWF

Subscribers: broadwaylamb, hans, dexonsmith, tstellar, llvm-commits, libcxx-commits

Tags: #libc, #llvm

Differential Revision: https://reviews.llvm.org/D72980
2020-01-24 13:27:22 -05:00
Louis Dionne 8ae404a2f6 [libc++] Make sure std::is_scalar returns true for block types
Summary:
The compiler already treats them as scalar types, so the library should
too. Furthermore, this allows blocks to be used in more places, for
example in std::optional, which requires an object type.

rdar://problem/57892832

Reviewers: dexonsmith, EricWF, mclow.lists
Differential Revision: https://reviews.llvm.org/D72708
2020-01-21 17:15:15 -08:00
Eric Fiselier fa40b41168 Revert "[libc++] Optimize / partially inline basic_string copy constructor"
This reverts commit a8a9c8e0a1.

There are multiple reported failures caused by this change.
Each failure is really weird, but it makes sense to revert
while investigating.
2020-01-20 21:41:58 -05:00
Eric Fiselier a8a9c8e0a1 [libc++] Optimize / partially inline basic_string copy constructor
Splits copy constructor up inlining short initialization, outlining long
initialization into __init_long() which is the externally instantiated slow
path initialization.

Subsequently changing the copy ctor to be inlined (not externally instantiated)
provides significant speed ups for short string initialization.

Generated code given:

void StringCopyCtor(void* mem, const std::string& s) {
    std::string*p = new(mem) std::string{s};
}

asm:
        cmp     byte ptr [rsi + 23], 0
        js      .LBB0_2
        mov     rax, qword ptr [rsi + 16]
        mov     qword ptr [rdi + 16], rax
        movups  xmm0, xmmword ptr [rsi]
        movups  xmmword ptr [rdi], xmm0
        ret
.LBB0_2:
        jmp     std::basic_string::__init_long # TAILCALL

Benchmark:
BM_StringCopy_Empty                                           5.19ns ± 6%             1.50ns ± 8%  -71.02%        (p=0.000 n=10+10)
BM_StringCopy_Small                                           5.14ns ± 8%             1.53ns ± 7%  -70.17%        (p=0.000 n=10+10)
BM_StringCopy_Large                                           18.9ns ± 0%             19.3ns ± 0%   +1.92%        (p=0.000 n=10+10)
BM_StringCopy_Huge                                             309ns ± 1%              316ns ± 5%     ~            (p=0.633 n=8+10)

Patch from Martijn Vels (mvels@google.com)
Reviewed as D72160.
2020-01-17 16:53:54 -05:00
Petr Hosek 9050d0fb59 [libcxx] Temporarily switch back to pthread backend for Fuchsia
We switched to C11 thread API on Fuchsia in ab9aefe, but further
testing showed that Fuchsia's C11 mutex implementation needs a few
improvements for this to be usable, so we temporarily switch back
to the pthread implementation until those issues are addressed.

Differential Revision: https://reviews.llvm.org/D72862
2020-01-16 14:53:08 -08:00
Eric Fiselier 59919c4d6b [libc++] Fix Windows DLL build for string.
We need to mark string::npos with _LIBCPP_FUNC_VIS on the first
in-class declaration, otherwise it might get ignored
2020-01-16 15:01:12 -05:00
Petr Hosek 3481e5d7ed [libcxx] Use mtx_plain | mtx_recursive following C11 API
The C11 API specifies that to initialize a recursive mutex,
mtx_plain | mtx_recursive should be used with mtx_init.

Differential Revision: https://reviews.llvm.org/D72809
2020-01-15 15:15:39 -08:00
Eric Fiselier 313d89724c [libc++] Fix parsing <string> in C++03.
Specifically, add a space between >> when closing templates.
2020-01-15 17:29:55 -05:00
Eric Fiselier 58c7fa5ade [libc++] Optimize basic_string::operator=(const basic_string&) for SSO assignments
This change optimizes the operator=() assignment for short strings by direcly
copying the raw data from the source into the current instance. This creates an
optimized / inlined mempcy up to over 2X faster for short string assignments.
With inlining enabled for operator=, performance is up to 6X faster.

Benchmarks 'as is':
name                                    old time/op   new time/op    delta
BM_StringAssignStr_Empty_Opaque         6.05ns ± 2%   3.59ns ± 0%  -40.67%
BM_StringAssignStr_Empty_Transparent    5.15ns ± 0%   3.08ns ± 0%  -40.12%
BM_StringAssignStr_Small_Opaque         7.71ns ± 0%   3.59ns ± 0%  -53.45%
BM_StringAssignStr_Small_Transparent    7.66ns ± 0%   3.09ns ± 0%  -59.66%
BM_StringAssignStr_Large_Opaque         24.1ns ± 0%   24.9ns ± 0%   +3.22%
BM_StringAssignStr_Large_Transparent    22.2ns ± 0%   22.8ns ± 0%   +2.77%
BM_StringAssignStr_Huge_Opaque           315ns ± 6%    320ns ± 5%     ~
BM_StringAssignStr_Huge_Transparent      318ns ± 5%    321ns ± 4%     ~

Benchmarks with partial inlining operator=():
name                                    old time/op   new time/op    delta
BM_StringAssignStr_Empty_Opaque         5.94ns ± 2%   1.95ns ± 0%  -67.21%
BM_StringAssignStr_Empty_Transparent    5.14ns ± 0%   1.04ns ± 1%  -79.73%
BM_StringAssignStr_Small_Opaque         7.69ns ± 0%   1.96ns ± 0%  -74.48%
BM_StringAssignStr_Small_Transparent    7.65ns ± 0%   1.04ns ± 0%  -86.40%
BM_StringAssignStr_Large_Opaque         24.1ns ± 0%   24.5ns ± 0%   +1.61%
BM_StringAssignStr_Large_Transparent    22.2ns ± 0%   21.1ns ± 0%   -4.70%
BM_StringAssignStr_Huge_Opaque           317ns ± 5%    323ns ± 4%     ~
BM_StringAssignStr_Huge_Transparent      318ns ± 5%    320ns ± 5%     ~

Patch by Martijn Vels (mvels@google.com)
Reviewed as https://reviews.llvm.org/D72704
2020-01-15 17:27:10 -05:00
Eric Fiselier 288a143639 [libc++] Explicitly enumerate std::string external instantiations - Attempt 2
The GCC build failures have been addressed, and the LLDB failures were
  fixed by LLDB.

   I have also verified that the apple-clang 9.0 segfault no longer
   occurs.

Original Message:

 The external instantiation of std::string is a problem for libc++.
    Additions and removals of inline functions in string can cause ABI
    breakages, including introducing new symbols.

    This patch aims to:
      (1) Make clear which functions are explicitly instatiated.
      (2) Prevent new functions from being accidentally instantiated.
      (3) Allow a migration path for adding or removing functions from the
      explicit instantiation over time.

    Although this new formulation is uglier, it is preferable from a
    maintainability and readability standpoint because it explicitly
    enumerates the functions we've chosen to expose in our ABI. Changing
    this list is non-trivial and requires thought and planning.

    (3) is achieved by making it possible to control the extern template declaration
    separately from it's definition. Meaning we could add a new definition to
    the dylib, wait for it to roll out, then add the extern template
    declaration to the header. Similarly, we could remove existing extern
    template declarations while still keeping the definition to prevent ABI
    breakages.
2020-01-15 17:12:49 -05:00
Eric Fiselier 2d8f23f571 [libc++] Explicitly mark basic_string<...>::npos with default
visibility.

This ensures that the version compiled into the library isn't
accidentally hidden.
2020-01-15 17:02:17 -05:00
Eric Fiselier 24d2a015ea [libc++] Make SFINAE'd member functions in string mutually exclusive.
This patch is needed in order to work around a GCC bug that fails to
explicitly instantiate a non-template function of a class template when
there is another overload that's a function template.
(See https://godbolt.org/z/4bUQ_b)

This patch SFINAE's away the function templates when the argument is
a basic_string.
2020-01-15 17:00:26 -05:00
Hans Wennborg 5852475e2c Bump the trunk major version to 11
and clear the release notes.
2020-01-15 13:38:01 +01:00
Petr Hosek ab9aefee9f [libcxx] Use C11 thread API on Fuchsia
On Fuchsia, pthread API is emulated on top of C11 thread API. Using C11
thread API directly is more efficient.

While this implementation is only used by Fuchsia at the moment, it's
not Fuchsia specific, and could be used by other platforms that use C11
threads rather than pthreads in the future.

Differential Revision: https://reviews.llvm.org/D64378
2020-01-14 16:48:20 -08:00
Martin Storsjö 337e435964 [libcxx] [Windows] Make a more proper implementation of strftime_l for mingw with msvcrt.dll
This also makes this function consistent with the rest of the
libc++ provided fallbacks.

The locale support in msvcrt.dll is very limited anyway; it can
only be configured processwide, not per thread, and it only seems
to support the locales "C" and "" (the user set locale), so it's
hard to make any meaningful automatic test for it. But manually tested,
this change does make time formatting locale code in libc++ output
times in the user requested format, when using locale "".

Differential Revision: https://reviews.llvm.org/D69554
2020-01-14 22:29:47 +02:00