From c2d0cf1a7edc918d59267eaed5d65403f7ad4c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Mon, 3 Mar 2025 13:33:45 +0100 Subject: [PATCH] [clang][bytecode] Don't narrow() when dereferencing to array type It doesn't make sense to do this if the result is supposed to be an array. --- clang/lib/AST/ByteCode/Compiler.cpp | 6 +- .../AST/ByteCode/libcxx/deref-to-array.cpp | 391 ++++++++++++++++++ 2 files changed, 393 insertions(+), 4 deletions(-) create mode 100644 clang/test/AST/ByteCode/libcxx/deref-to-array.cpp diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 74f5d6ebd9ca6..aff931a1ec939 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -6028,14 +6028,12 @@ bool Compiler::VisitUnaryOperator(const UnaryOperator *E) { // We should already have a pointer when we get here. return this->delegate(SubExpr); case UO_Deref: // *x - if (DiscardResult) { - // assert(false); + if (DiscardResult) return this->discard(SubExpr); - } if (!this->visit(SubExpr)) return false; - if (classifyPrim(SubExpr) == PT_Ptr) + if (classifyPrim(SubExpr) == PT_Ptr && !E->getType()->isArrayType()) return this->emitNarrowPtr(E); return true; diff --git a/clang/test/AST/ByteCode/libcxx/deref-to-array.cpp b/clang/test/AST/ByteCode/libcxx/deref-to-array.cpp new file mode 100644 index 0000000000000..2a527ab336a0d --- /dev/null +++ b/clang/test/AST/ByteCode/libcxx/deref-to-array.cpp @@ -0,0 +1,391 @@ +// RUN: %clang_cc1 -std=c++2c -fexperimental-new-constant-interpreter -verify=expected,both %s +// RUN: %clang_cc1 -std=c++2c -verify=ref,both %s + +// both-no-diagnostics + +namespace std { +inline namespace { +template struct integral_constant { + static const _Tp value = __v; +}; +template using _BoolConstant = integral_constant; +template using __remove_cv_t = __remove_cv(_Tp); +template using remove_cv_t = __remove_cv_t<_Tp>; +template +constexpr bool is_convertible_v = __is_convertible(_From, _To); +template _Tp __declval(long); +template decltype(__declval<_Tp>(0)) declval(); +template +concept convertible_to = is_convertible_v<_From, _To> && + requires { static_cast<_To>(declval<_From>()); }; +template constexpr bool is_reference_v = __is_reference(_Tp); +template +constexpr bool is_lvalue_reference_v = __is_lvalue_reference(_Tp); +template +constexpr bool is_nothrow_destructible_v = + integral_constant::value; +template +concept destructible = is_nothrow_destructible_v<_Tp>; +template +using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>; +template +constexpr bool is_constructible_v = __is_constructible(_Args...); +template +concept constructible_from = destructible<_Tp> && is_constructible_v<_Tp>; +template +concept move_constructible = + constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>; +template +concept __same_as_impl = _IsSame<_Tp, _Up>::value; +template +concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>; +template struct _IfImpl; +template <> struct _IfImpl { + template using _Select = _ElseRes; +}; +template +using _If = _IfImpl<_Cond>::template _Select<_IfRes, _ElseRes>; +template struct conditional { + using type = _If; +}; +template +using conditional_t = conditional<_IfRes>::type; +template +using __libcpp_remove_reference_t = __remove_reference_t(_Tp); +template +using remove_reference_t = __libcpp_remove_reference_t<_Tp>; +template using __decay_t = __decay(_Tp); +template using __remove_cvref_t = __remove_cvref(_Tp); +template using remove_cvref_t = __remove_cvref_t<_Tp>; +struct __copy_cv { + template using __apply = _To; +}; +template using __copy_cv_t = __copy_cv::__apply<_To>; +template +using __cond_res = + decltype(false ? std::declval<_Xp (&)()>()() : std::declval<_Yp (&)()>()()); +template , + class = remove_reference_t<_Bp>> +struct __common_ref; +template +struct __common_ref : __common_ref<_Bp, _Ap> {}; +template +using __common_ref_t = __common_ref<_Xp, _Yp>::__type; +template +using __cv_cond_res = + __cond_res<__copy_cv_t<_Xp, _Yp> &, __copy_cv_t<_Yp, _Xp> &>; +template + requires requires { typename __cv_cond_res<_Xp, _Yp>; } && + is_reference_v<__cv_cond_res<_Xp, _Yp>> +struct __common_ref<_Ap, _Bp &, _Xp, _Yp> { + using __type = __cv_cond_res<_Xp, _Yp>; +}; +template +using __common_ref_D = __common_ref_t; +template + requires requires { typename __common_ref_D<_Xp, _Yp>; } && + is_convertible_v<_Ap, __common_ref_D<_Xp, _Yp>> +struct __common_ref<_Ap &&, _Bp &, _Xp, _Yp> { + using __type = __common_ref_D<_Xp, _Yp>; +}; +template struct common_reference; +template +using common_reference_t = common_reference<_Types...>::type; +template struct __common_reference_sub_bullet1; +template +struct common_reference<_Tp, _Up> : __common_reference_sub_bullet1<_Tp, _Up> {}; +template + requires is_reference_v<_Tp> && is_reference_v<_Up> && + requires { typename __common_ref_t<_Tp, _Up>; } +struct __common_reference_sub_bullet1<_Tp, _Up> { + using type = __common_ref_t<_Tp, _Up>; +}; +template +concept common_reference_with = + same_as, common_reference_t<_Up, _Tp>> && + convertible_to<_Tp, common_reference_t<_Tp, _Up>> && + convertible_to<_Up, common_reference_t<_Tp, _Up>>; +template +using __make_const_lvalue_ref = __libcpp_remove_reference_t<_Tp> &; +template +concept assignable_from = + is_lvalue_reference_v<_Lhs> && + common_reference_with<__make_const_lvalue_ref<_Lhs>, + __make_const_lvalue_ref<_Rhs>> && + requires(_Lhs __lhs, _Rhs __rhs) { + { __rhs } -> same_as<_Lhs>; + }; +template constexpr __libcpp_remove_reference_t<_Tp> &&move(_Tp &&); +typedef int type; +template using __enable_if_t = type; +namespace ranges { +inline namespace { +auto swap = int{}; +} +} // namespace ranges +template constexpr bool is_object_v = __is_object(_Tp); +template +concept movable = is_object_v<_Tp> && move_constructible<_Tp> && + assignable_from<_Tp &, _Tp>; +template struct tuple_element; +template class tuple; +template