Skip to content

Commit 9c7320e

Browse files
authored
[clang][bytecode] Fix visiting for-range loop variable (#147188)
Make sure we're properly registering DecompositionDecls.
1 parent aa9e02c commit 9c7320e

File tree

2 files changed

+265
-2
lines changed

2 files changed

+265
-2
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5545,7 +5545,6 @@ bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
55455545
const Stmt *BeginStmt = S->getBeginStmt();
55465546
const Stmt *RangeStmt = S->getRangeStmt();
55475547
const Stmt *EndStmt = S->getEndStmt();
5548-
const VarDecl *LoopVar = S->getLoopVariable();
55495548

55505549
LabelTy EndLabel = this->getLabel();
55515550
LabelTy CondLabel = this->getLabel();
@@ -5570,7 +5569,7 @@ bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
55705569
if (!this->jumpFalse(EndLabel))
55715570
return false;
55725571

5573-
if (!this->visitVarDecl(LoopVar))
5572+
if (!this->visitDeclStmt(S->getLoopVarStmt(), /*EvaluateConditionDecl=*/true))
55745573
return false;
55755574

55765575
// Body.
Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
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+
// both-no-diagnostics
5+
6+
namespace std {
7+
typedef __SIZE_TYPE__ size_t;
8+
}
9+
extern "C++" {
10+
namespace std {
11+
template <typename> struct iterator_traits;
12+
}
13+
}
14+
namespace std {
15+
template <typename _Tp, _Tp __v> struct integral_constant {
16+
static constexpr _Tp value = __v;
17+
};
18+
template <bool __v> using __bool_constant = integral_constant<bool, __v>;
19+
using false_type = __bool_constant<false>;
20+
template <bool, typename _Tp = void> struct enable_if {
21+
using type = _Tp;
22+
};
23+
template <bool> struct __conditional {
24+
template <typename _Tp, typename> using type = _Tp;
25+
};
26+
template <bool _Cond, typename _If, typename _Else>
27+
using __conditional_t =
28+
typename __conditional<_Cond>::template type<_If, _Else>;
29+
template <typename _Tp>
30+
struct is_empty : public __bool_constant<__is_empty(_Tp)> {};
31+
template <typename _Tp, typename _Up>
32+
struct is_same : public __bool_constant<__is_same(_Tp, _Up)> {};
33+
template <typename _Tp> struct remove_cv {
34+
using type = __remove_cv(_Tp);
35+
};
36+
template <typename _Tp> struct tuple_size;
37+
template <typename _Tp, typename _Up = typename remove_cv<_Tp>::type,
38+
typename = typename enable_if<is_same<_Tp, _Up>::value>::type,
39+
size_t = tuple_size<_Tp>::value>
40+
using __enable_if_has_tuple_size = _Tp;
41+
template <typename _Tp>
42+
struct tuple_size<const __enable_if_has_tuple_size<_Tp>>
43+
: public tuple_size<_Tp> {};
44+
template <size_t __i, typename _Tp> struct tuple_element;
45+
template <size_t __i, typename _Tp>
46+
using __tuple_element_t = typename tuple_element<__i, _Tp>::type;
47+
template <size_t __i, typename _Tp> struct tuple_element<__i, const _Tp> {
48+
using type = const __tuple_element_t<__i, _Tp>;
49+
};
50+
template <size_t _Np, typename... _Types> struct _Nth_type {
51+
using type = __type_pack_element<_Np, _Types...>;
52+
};
53+
template <typename _Tp> struct iterator_traits<_Tp *> {
54+
using reference = _Tp &;
55+
};
56+
} // namespace std
57+
extern "C++" {
58+
void *operator new(std::size_t, void *__p);
59+
}
60+
namespace std {
61+
template <typename _Tp, typename... _Args>
62+
constexpr inline void _Construct(_Tp *__p, _Args &&...__args) {
63+
::new (__p) _Tp(__args...);
64+
};
65+
} // namespace std
66+
namespace __gnu_cxx {
67+
template <typename _Iterator, typename _Container> class __normal_iterator {
68+
protected:
69+
_Iterator _M_current;
70+
typedef std::iterator_traits<_Iterator> __traits_type;
71+
72+
public:
73+
typedef _Iterator iterator_type;
74+
typedef typename __traits_type::reference reference;
75+
explicit constexpr __normal_iterator(const _Iterator &__i)
76+
: _M_current(__i) {};
77+
constexpr reference operator*() const { return *_M_current; }
78+
constexpr __normal_iterator &operator++() {
79+
++_M_current;
80+
return *this;
81+
}
82+
constexpr const _Iterator &base() const { return _M_current; }
83+
};
84+
template <typename _Iterator, typename _Container>
85+
constexpr bool
86+
operator==(const __normal_iterator<_Iterator, _Container> &__lhs,
87+
const __normal_iterator<_Iterator, _Container> &__rhs) {
88+
return __lhs.base() == __rhs.base();
89+
}
90+
} // namespace __gnu_cxx
91+
namespace std {
92+
template <typename _Tp> class __new_allocator {};
93+
template <typename _Tp> using __allocator_base = __new_allocator<_Tp>;
94+
template <typename> struct allocator_traits;
95+
template <typename _Tp> class allocator : public __allocator_base<_Tp> {
96+
public:
97+
typedef _Tp value_type;
98+
constexpr _Tp *allocate(size_t __n) {
99+
__n *= sizeof(_Tp);
100+
return static_cast<_Tp *>(::operator new(__n));
101+
}
102+
constexpr void deallocate(_Tp *__p, size_t __n) { ::operator delete(__p); }
103+
};
104+
template <typename _Tp> struct allocator_traits<allocator<_Tp>> {
105+
using allocator_type = allocator<_Tp>;
106+
using pointer = _Tp *;
107+
using size_type = std::size_t;
108+
template <typename _Up> using rebind_alloc = allocator<_Up>;
109+
static constexpr pointer allocate(allocator_type &__a, size_type __n) {
110+
return __a.allocate(__n);
111+
}
112+
static constexpr void deallocate(allocator_type &__a, pointer __p,
113+
size_type __n) {
114+
__a.deallocate(__p, __n);
115+
}
116+
};
117+
} // namespace std
118+
namespace __gnu_cxx {
119+
template <typename _Alloc, typename = typename _Alloc::value_type>
120+
struct __alloc_traits : std::allocator_traits<_Alloc> {
121+
typedef std::allocator_traits<_Alloc> _Base_type;
122+
template <typename _Tp> struct rebind {
123+
typedef typename _Base_type::template rebind_alloc<_Tp> other;
124+
};
125+
};
126+
} // namespace __gnu_cxx
127+
namespace std {
128+
template <typename _InputIterator, typename _ForwardIterator>
129+
constexpr _ForwardIterator __do_uninit_copy(_InputIterator __first,
130+
_InputIterator __last,
131+
_ForwardIterator __result) {
132+
_ForwardIterator __cur = __result;
133+
for (; __first != __last; ++__first, ++__cur)
134+
std::_Construct(&*__cur, *__first);
135+
return __cur;
136+
};
137+
template <typename _InputIterator, typename _ForwardIterator, typename _Tp>
138+
constexpr inline _ForwardIterator
139+
__uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
140+
_ForwardIterator __result, allocator<_Tp> &) {
141+
return std::__do_uninit_copy(__first, __last, __result);
142+
}
143+
template <typename _Tp, typename _Alloc> struct _Vector_base {
144+
typedef
145+
typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<_Tp>::other
146+
_Tp_alloc_type;
147+
typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer pointer;
148+
struct _Vector_impl_data {
149+
pointer _M_start;
150+
pointer _M_finish;
151+
pointer _M_end_of_storage;
152+
};
153+
struct _Vector_impl : public _Tp_alloc_type, public _Vector_impl_data {};
154+
155+
public:
156+
typedef _Alloc allocator_type;
157+
constexpr _Tp_alloc_type &_M_get_Tp_allocator() { return this->_M_impl; }
158+
constexpr _Vector_base(const allocator_type &__a) : _M_impl(__a) {}
159+
constexpr ~_Vector_base() {
160+
_M_deallocate(_M_impl._M_start,
161+
_M_impl._M_end_of_storage - _M_impl._M_start);
162+
}
163+
164+
public:
165+
_Vector_impl _M_impl;
166+
constexpr pointer _M_allocate(size_t __n) {
167+
typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr;
168+
return __n != 0 ? _Tr::allocate(_M_impl, __n) : pointer();
169+
}
170+
constexpr void _M_deallocate(pointer __p, size_t __n) {
171+
typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr;
172+
if (__p)
173+
_Tr::deallocate(_M_impl, __p, __n);
174+
}
175+
176+
protected:
177+
};
178+
template <typename _Tp, typename _Alloc = std::allocator<_Tp>>
179+
class vector : protected _Vector_base<_Tp, _Alloc> {
180+
typedef _Vector_base<_Tp, _Alloc> _Base;
181+
182+
public:
183+
typedef _Tp value_type;
184+
typedef typename _Base::pointer pointer;
185+
typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;
186+
typedef size_t size_type;
187+
typedef _Alloc allocator_type;
188+
using _Base::_M_get_Tp_allocator;
189+
190+
public:
191+
private:
192+
public:
193+
constexpr vector(_Tp __l, const allocator_type &__a = allocator_type()) : _Base(__a) {
194+
195+
}
196+
constexpr iterator begin() { return iterator(this->_M_impl._M_start); }
197+
constexpr iterator end() { return iterator(this->_M_impl._M_finish); }
198+
199+
protected:
200+
template <typename _Iterator>
201+
constexpr void _M_range_initialize_n(_Iterator __first, _Iterator __last,
202+
size_type __n) {
203+
pointer __start = this->_M_impl._M_start = this->_M_allocate(((__n)));
204+
this->_M_impl._M_end_of_storage = __start + __n;
205+
this->_M_impl._M_finish = std::__uninitialized_copy_a(
206+
__first, __last, __start, _M_get_Tp_allocator());
207+
}
208+
};
209+
template <typename _Tp> struct __is_empty_non_tuple : is_empty<_Tp> {};
210+
template <typename _Tp>
211+
using __empty_not_final =
212+
__conditional_t<__is_final(_Tp), false_type, __is_empty_non_tuple<_Tp>>;
213+
template <size_t _Idx, typename _Head, bool = __empty_not_final<_Head>::value>
214+
struct _Head_base;
215+
template <size_t _Idx, typename _Head> struct _Head_base<_Idx, _Head, false> {
216+
static constexpr const _Head &_M_head(const _Head_base &__b) {
217+
return __b._M_head_impl;
218+
}
219+
_Head _M_head_impl;
220+
};
221+
template <size_t _Idx, typename... _Elements> struct _Tuple_impl;
222+
template <size_t _Idx, typename _Head>
223+
struct _Tuple_impl<_Idx, _Head> : private _Head_base<_Idx, _Head> {
224+
typedef _Head_base<_Idx, _Head> _Base;
225+
static constexpr const _Head &_M_head(const _Tuple_impl &__t) {
226+
return _Base::_M_head(__t);
227+
}
228+
explicit constexpr _Tuple_impl(const _Head &__head) : _Base(__head) {}
229+
230+
protected:
231+
};
232+
template <typename... _Elements>
233+
class tuple : public _Tuple_impl<0, _Elements...> {
234+
using _Inherited = _Tuple_impl<0, _Elements...>;
235+
236+
public:
237+
template <typename = void>
238+
constexpr tuple(const _Elements &...__elements) : _Inherited(__elements...) {}
239+
};
240+
template <typename... _Elements>
241+
struct tuple_size<tuple<_Elements...>>
242+
: public integral_constant<size_t, sizeof...(_Elements)> {};
243+
template <size_t __i, typename... _Types>
244+
struct tuple_element<__i, tuple<_Types...>> {
245+
using type = typename _Nth_type<__i, _Types...>::type;
246+
};
247+
template <size_t __i, typename _Head, typename... _Tail>
248+
constexpr const _Head &
249+
__get_helper(const _Tuple_impl<__i, _Head, _Tail...> &__t) {
250+
return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t);
251+
};
252+
template <size_t __i, typename... _Elements>
253+
constexpr const int get(const tuple<_Elements...> &&__t) {
254+
return std::__get_helper<__i>(__t);
255+
};
256+
} // namespace std
257+
constexpr int foo() {
258+
std::vector<std::tuple<int>> data_tuples = {{1}};
259+
for (const auto [id] : data_tuples) {
260+
int a = id + 3;
261+
}
262+
return 1;
263+
}
264+
static_assert(foo() == 1);

0 commit comments

Comments
 (0)