Skip to content

Commit 30dc7c7

Browse files
committed
[clang][bytecode] Fix visiting for-range loop variable
Make sure we're properly registering DecompositionDecls.
1 parent 113ea3d commit 30dc7c7

File tree

2 files changed

+281
-2
lines changed

2 files changed

+281
-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: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
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 long unsigned int 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 <class _E> class initializer_list {
144+
typedef size_t size_type;
145+
typedef const _E *iterator;
146+
typedef const _E *const_iterator;
147+
148+
private:
149+
iterator _M_array;
150+
size_type _M_len;
151+
152+
public:
153+
constexpr size_type size() const { return _M_len; }
154+
constexpr const_iterator begin() const { return _M_array; }
155+
constexpr const_iterator end() const { return begin() + size(); }
156+
};
157+
template <typename _Tp, typename _Alloc> struct _Vector_base {
158+
typedef
159+
typename __gnu_cxx::__alloc_traits<_Alloc>::template rebind<_Tp>::other
160+
_Tp_alloc_type;
161+
typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer pointer;
162+
struct _Vector_impl_data {
163+
pointer _M_start;
164+
pointer _M_finish;
165+
pointer _M_end_of_storage;
166+
};
167+
struct _Vector_impl : public _Tp_alloc_type, public _Vector_impl_data {};
168+
169+
public:
170+
typedef _Alloc allocator_type;
171+
constexpr _Tp_alloc_type &_M_get_Tp_allocator() { return this->_M_impl; }
172+
constexpr _Vector_base(const allocator_type &__a) : _M_impl(__a) {}
173+
constexpr ~_Vector_base() {
174+
_M_deallocate(_M_impl._M_start,
175+
_M_impl._M_end_of_storage - _M_impl._M_start);
176+
}
177+
178+
public:
179+
_Vector_impl _M_impl;
180+
constexpr pointer _M_allocate(size_t __n) {
181+
typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr;
182+
return __n != 0 ? _Tr::allocate(_M_impl, __n) : pointer();
183+
}
184+
constexpr void _M_deallocate(pointer __p, size_t __n) {
185+
typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr;
186+
if (__p)
187+
_Tr::deallocate(_M_impl, __p, __n);
188+
}
189+
190+
protected:
191+
};
192+
template <typename _Tp, typename _Alloc = std::allocator<_Tp>>
193+
class vector : protected _Vector_base<_Tp, _Alloc> {
194+
typedef _Vector_base<_Tp, _Alloc> _Base;
195+
196+
public:
197+
typedef _Tp value_type;
198+
typedef typename _Base::pointer pointer;
199+
typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;
200+
typedef size_t size_type;
201+
typedef _Alloc allocator_type;
202+
using _Base::_M_get_Tp_allocator;
203+
204+
public:
205+
private:
206+
public:
207+
constexpr vector(initializer_list<value_type> __l,
208+
const allocator_type &__a = allocator_type())
209+
: _Base(__a) {
210+
_M_range_initialize_n(__l.begin(), __l.end(), __l.size());
211+
}
212+
constexpr iterator begin() { return iterator(this->_M_impl._M_start); }
213+
constexpr iterator end() { return iterator(this->_M_impl._M_finish); }
214+
215+
protected:
216+
template <typename _Iterator>
217+
constexpr void _M_range_initialize_n(_Iterator __first, _Iterator __last,
218+
size_type __n) {
219+
pointer __start = this->_M_impl._M_start = this->_M_allocate(((__n)));
220+
this->_M_impl._M_end_of_storage = __start + __n;
221+
this->_M_impl._M_finish = std::__uninitialized_copy_a(
222+
__first, __last, __start, _M_get_Tp_allocator());
223+
}
224+
};
225+
template <typename _Tp> struct __is_empty_non_tuple : is_empty<_Tp> {};
226+
template <typename _Tp>
227+
using __empty_not_final =
228+
__conditional_t<__is_final(_Tp), false_type, __is_empty_non_tuple<_Tp>>;
229+
template <size_t _Idx, typename _Head, bool = __empty_not_final<_Head>::value>
230+
struct _Head_base;
231+
template <size_t _Idx, typename _Head> struct _Head_base<_Idx, _Head, false> {
232+
static constexpr const _Head &_M_head(const _Head_base &__b) {
233+
return __b._M_head_impl;
234+
}
235+
_Head _M_head_impl;
236+
};
237+
template <size_t _Idx, typename... _Elements> struct _Tuple_impl;
238+
template <size_t _Idx, typename _Head>
239+
struct _Tuple_impl<_Idx, _Head> : private _Head_base<_Idx, _Head> {
240+
typedef _Head_base<_Idx, _Head> _Base;
241+
static constexpr const _Head &_M_head(const _Tuple_impl &__t) {
242+
return _Base::_M_head(__t);
243+
}
244+
explicit constexpr _Tuple_impl(const _Head &__head) : _Base(__head) {}
245+
246+
protected:
247+
};
248+
template <typename... _Elements>
249+
class tuple : public _Tuple_impl<0, _Elements...> {
250+
using _Inherited = _Tuple_impl<0, _Elements...>;
251+
252+
public:
253+
template <typename = void>
254+
constexpr tuple(const _Elements &...__elements) : _Inherited(__elements...) {}
255+
};
256+
template <typename... _Elements>
257+
struct tuple_size<tuple<_Elements...>>
258+
: public integral_constant<size_t, sizeof...(_Elements)> {};
259+
template <size_t __i, typename... _Types>
260+
struct tuple_element<__i, tuple<_Types...>> {
261+
using type = typename _Nth_type<__i, _Types...>::type;
262+
};
263+
template <size_t __i, typename _Head, typename... _Tail>
264+
constexpr const _Head &
265+
__get_helper(const _Tuple_impl<__i, _Head, _Tail...> &__t) {
266+
return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t);
267+
};
268+
template <size_t __i, typename... _Elements>
269+
constexpr const int get(const tuple<_Elements...> &&__t) {
270+
return std::__get_helper<__i>(__t);
271+
};
272+
} // namespace std
273+
constexpr int foo() {
274+
std::vector<std::tuple<int>> data_tuples = {{1}};
275+
for (const auto [id] : data_tuples) {
276+
int a = id + 3;
277+
}
278+
return 1;
279+
}
280+
static_assert(foo() == 1);

0 commit comments

Comments
 (0)