[PATCH] D152003: [clang] Fix `static_cast` to array of unknown bound

Mariya Podchishchaeva via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 26 05:04:18 PDT 2023


Fznamznon added a comment.

> What do you mean with libstdc++ is fine?

What I mean is when I do (current patch is applied to clang):

  source/llvm-project/build/bin/clang++ -std=c++20 t.cpp -c // compilation succeeds

But when I do (libc++ is built together with clang)

  source/llvm-project/build/bin/clang++ -std=c++20 t.cpp -stdlib=libc++ -c
  t.cpp:4:15: error: static assertion failed due to requirement '!std::is_invocable_v<const std::ranges::__crend::__fn, int (&)[]>'
      4 | static_assert(!std::is_invocable_v<RangeCREndT, int (&)[]>);
        |               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1 error generated.



> Based on the bug and this patch I am correct that "transformation" of an array of unknown bounds to anarray of known bounds only happens with an explicit cast and not implicitly?

Yes, type is changed only for explicit casts.

> I have a strong suspicion that this patch changes the test to

Well technically it only changes explicit casts, so no.  With this patch this static assertion still fails

  static_assert(std::is_same<int (&)[1], int(&)[]>::value);

What I'm seeing is that in libc++ there is a bunch of explicit static casts in `ranges::__crend::__fn` that endup transformed:

  namespace ranges {
  namespace __crend {                                                                    
  struct __fn {
    template <class _Tp>
      requires is_lvalue_reference_v<_Tp&&>                                              
    [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
    constexpr auto operator()(_Tp&& __t) const
      noexcept(noexcept(ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t))))
      -> decltype(      ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t)))  
      { return          ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t)); }
                                                                                         
    template <class _Tp>                                                                 
      requires is_rvalue_reference_v<_Tp&&>                                              
    [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
    constexpr auto operator()(_Tp&& __t) const
      noexcept(noexcept(ranges::rend(static_cast<const _Tp&&>(__t))))                    
      -> decltype(      ranges::rend(static_cast<const _Tp&&>(__t)))
      { return          ranges::rend(static_cast<const _Tp&&>(__t)); }
  };
  } // namespace __crend

Is that expected?

Please note that other implementations would do the same transformation and that is the point of this bugfix:
https://godbolt.org/z/ff8f3YEbz


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152003/new/

https://reviews.llvm.org/D152003



More information about the cfe-commits mailing list