Skip to content

Commit 1828381

Browse files
authored
[clang][bytecode] Fix APValue generation for RValueReferenceType (#147207)
We need to ignore the lvalue path, just like we do for lvalue reference types.
1 parent e26f8ba commit 1828381

File tree

2 files changed

+123
-1
lines changed

2 files changed

+123
-1
lines changed

clang/lib/AST/ByteCode/Pointer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
207207

208208
bool UsePath = true;
209209
if (const ValueDecl *VD = getDeclDesc()->asValueDecl();
210-
VD && VD->getType()->isLValueReferenceType())
210+
VD && VD->getType()->isReferenceType())
211211
UsePath = false;
212212

213213
// Build the path into the object.
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// RUN: %clang_cc1 -std=c++2c -verify=expected,both %s -fexperimental-new-constant-interpreter
2+
// RUN: %clang_cc1 -std=c++2c -verify=ref,both %s
3+
4+
template <int __v> struct integral_constant {
5+
static const int value = __v;
6+
};
7+
template <bool _Val> using _BoolConstant = integral_constant<_Val>;
8+
template <class _From, class _To>
9+
constexpr bool is_convertible_v = __is_convertible(_From, _To);
10+
template <class _Tp> _Tp __declval(int);
11+
template <class _Tp> decltype(__declval<_Tp>(0)) declval();
12+
template <class _Tp, class _Up>
13+
using _IsSame = _BoolConstant<__is_same(_Tp, _Up)>;
14+
template <class _If> struct conditional {
15+
using type = _If;
16+
};
17+
template <bool, class _IfRes, class>
18+
using conditional_t = conditional<_IfRes>::type;
19+
template <class _Tp, class>
20+
concept __weakly_equality_comparable_with = requires(_Tp __t) { __t; };
21+
template <bool, class _Tp = void> using __enable_if_t = _Tp;
22+
template <template <class> class, class>
23+
integral_constant<true> __sfinae_test_impl(int);
24+
template <template <class> class _Templ, class... _Args>
25+
using _IsValidExpansion = decltype(__sfinae_test_impl<_Templ, _Args...>(0));
26+
template <class _Tp>
27+
using __test_for_primary_template =
28+
__enable_if_t<_IsSame<_Tp, typename _Tp::__primary_template>::value>;
29+
template <class _Tp>
30+
using __is_primary_template =
31+
_IsValidExpansion<__test_for_primary_template, _Tp>;
32+
template <class _Ip>
33+
using iter_difference_t =
34+
conditional_t<__is_primary_template<_Ip>::value, _Ip, _Ip>::difference_type;
35+
template <int> struct _OrImpl {
36+
template <class, class _First>
37+
using _Result = _OrImpl<!_First::value>::template _Result<_First>;
38+
};
39+
template <> struct _OrImpl<false> {
40+
template <class _Res> using _Result = _Res;
41+
};
42+
template <class... _Args>
43+
using _Or = _OrImpl<sizeof...(_Args)>::template _Result<_Args...>;
44+
struct input_iterator_tag {};
45+
template <class _Dp, class _Bp>
46+
concept derived_from = is_convertible_v<_Dp, _Bp>;
47+
template <class _Ip>
48+
concept input_or_output_iterator = requires(_Ip __i) { __i; };
49+
template <class _Sp, class _Ip>
50+
concept sentinel_for = __weakly_equality_comparable_with<_Sp, _Ip>;
51+
struct __iter_concept_category_test {
52+
template <class> using _Apply = input_iterator_tag;
53+
};
54+
struct __test_iter_concept
55+
: _IsValidExpansion<__iter_concept_category_test::_Apply, int>,
56+
__iter_concept_category_test {};
57+
struct __iter_concept_cache {
58+
using type = _Or<int, __test_iter_concept>;
59+
};
60+
template <class _Iter>
61+
using _ITER_CONCEPT = __iter_concept_cache::type::_Apply<_Iter>;
62+
template <class _Ip>
63+
concept input_iterator = derived_from<_ITER_CONCEPT<_Ip>, input_iterator_tag>;
64+
template <class _T1, class _T2> struct pair {
65+
_T1 first;
66+
_T2 second;
67+
};
68+
struct {
69+
template <class _Tp> auto operator()(_Tp __t) { return __t.begin(); }
70+
} begin;
71+
template <class _Tp> using iterator_t = decltype(begin(declval<_Tp>()));
72+
template <class _Tp>
73+
concept __member_size = requires(_Tp __t) { __t; };
74+
struct {
75+
template <__member_size _Tp> constexpr void operator()(_Tp &&__t) {
76+
__t.size(); // both-note 2{{in instantiation}}
77+
}
78+
} size;
79+
template <class _Tp>
80+
concept range = requires(_Tp __t) { __t; };
81+
template <class _Tp>
82+
concept input_range = input_iterator<_Tp>;
83+
template <range _Rp>
84+
using range_difference_t = iter_difference_t<iterator_t<_Rp>>;
85+
struct {
86+
template <range _Rp> constexpr range_difference_t<_Rp> operator()(_Rp &&__r) {
87+
size(__r); // both-note 2{{in instantiation}}
88+
} // both-warning {{does not return a value}}
89+
} distance;
90+
template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>
91+
struct subrange {
92+
_Iter __begin_;
93+
_Sent __end_;
94+
_Iter begin();
95+
constexpr _Iter size() { __end_ - __begin_; } // both-warning {{does not return a value}} \
96+
// both-note {{in instantiation}}
97+
};
98+
struct {
99+
template <input_range _Range1, input_range _Range2>
100+
void operator()(_Range1 &&__range1, _Range2) {
101+
(void)(distance(__range1) != 0); // both-note 3{{in instantiation}}
102+
}
103+
} equal;
104+
template <class _Owner> struct __key_value_iterator {
105+
using difference_type = _Owner::difference_type;
106+
constexpr friend difference_type operator-(__key_value_iterator,
107+
__key_value_iterator &) {} // both-warning {{does not return a value}}
108+
};
109+
struct flat_multimap {
110+
template <bool> using __iterator = __key_value_iterator<flat_multimap>;
111+
using difference_type =
112+
decltype(static_cast<int *>(nullptr) - static_cast<int *>(nullptr));
113+
pair<__iterator<true>, __iterator<true>> equal_range(const char *);
114+
} test_expected_range;
115+
void test() {
116+
flat_multimap m;
117+
auto test_found = [](auto map, auto expected_key, int) {
118+
auto [first, last] = map.equal_range(expected_key);
119+
equal(subrange(first, last), test_expected_range); // both-note 3{{in instantiation}}
120+
};
121+
test_found(m, "", {});
122+
}

0 commit comments

Comments
 (0)